Subversion Repository Public Repository

Divide-Framework

This repository has no backups
This repository's network speed is throttled to 100KB/sec

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include "Headers/Task.h"

#include "Core/Headers/TaskPool.h"
#include "Core/Headers/Console.h"
#include "Core/Headers/Application.h"
#include "Core/Time/Headers/ApplicationTimer.h"
#include "Utility/Headers/Localization.h"

namespace Divide {

namespace {
    const bool g_DebugTaskStartStop = false;
};

Task::Task()
  : GUIDWrapper(),
    _taskFlags(0),
    _tp(nullptr),
    _poolIndex(0),
    _jobIdentifier(-1),
    _priority(TaskPriority::DONT_CARE)
{
    _parentTask = nullptr;
    _childTaskCount = 0;
    _done = true;
    _stopRequested = false;

    if (g_DebugTaskStartStop) {
        SetBit(_taskFlags, to_const_uint(TaskFlags::PRINT_DEBUG_INFO));
    }
}

Task::~Task()
{
    stopTask();
    wait();
}

void Task::reset() {
    if (!_done) {
        stopTask();
        wait();
    }

    _stopRequested = false;
    //_callback = DELEGATE_CBK_PARAM<bool>();
    _jobIdentifier = -1;
    _priority = TaskPriority::DONT_CARE;
    _parentTask = nullptr;
    _childTasks.resize(0);
    _childTaskCount = 0;
}

void Task::startTask(TaskPriority priority, U32 taskFlags) {
    SetBit(_taskFlags, taskFlags);

    assert(!isRunning());

    if (Config::USE_SINGLE_THREADED_TASK_POOLS) {
        if (priority != TaskPriority::REALTIME &&
            priority != TaskPriority::REALTIME_WITH_CALLBACK) {
            priority = TaskPriority::REALTIME_WITH_CALLBACK;
        }
    }
    if (!Config::USE_GPU_THREADED_LOADING) {
        if (BitCompare(_taskFlags, to_const_uint(TaskFlags::SYNC_WITH_GPU))) {
            priority = TaskPriority::REALTIME_WITH_CALLBACK;
        }
    }
    _done = false;
    _priority = priority;
    if (priority != TaskPriority::REALTIME && 
        priority != TaskPriority::REALTIME_WITH_CALLBACK &&
        _tp != nullptr && _tp->workerThreadCount() > 0)
    {
        while (!_tp->threadPool().schedule(PoolTask(to_uint(priority), DELEGATE_BIND(&Task::run, this)))) {
            Console::errorfn(Locale::get(_ID("TASK_SCHEDULE_FAIL")));
        }
    } else {
        run();
    }
}

void Task::stopTask() {
#if defined(_DEBUG)
    if (isRunning()) {
        Console::errorfn(Locale::get(_ID("TASK_DELETE_ACTIVE")));
    }
#endif

    for (Task* child : _childTasks){
        child->stopTask();
    }

    _stopRequested = true;
}

void Task::wait() {
    std::unique_lock<std::mutex> lk(_taskDoneMutex);
    while (!_done) {
        _taskDoneCV.wait(lk);
    }
}

//ToDo: Add better wait for children system. Just manually balance calls for now -Ionut
void Task::waitForChildren(bool yeld, I64 timeout) {
    U64 startTime = 0UL;
    if (timeout > 0L) {
        startTime = Time::ElapsedMicroseconds(true);
    }

    while(_childTaskCount > 0) {
        if (timeout > 0L) {
            U64 endTime = Time::ElapsedMicroseconds(true);
            if (endTime - startTime >= static_cast<U64>(timeout)) {
                return;
            }
        } else if (timeout == 0L) {
            return;
        }

        if (yeld) {
            std::this_thread::yield();
        }
    }
}

void Task::run() {
    waitForChildren(true, -1L);

    if (BitCompare(_taskFlags, to_const_uint(TaskFlags::PRINT_DEBUG_INFO))) {
        Console::d_printfn(Locale::get(_ID("TASK_RUN_IN_THREAD")), getGUID(), std::this_thread::get_id());
    }

    if (BitCompare(_taskFlags, to_const_uint(TaskFlags::SYNC_WITH_GPU))) {
        beginSyncGPU();
    }

    if (!Application::instance().ShutdownRequested()) {

        if (_callback) {
            _callback(_stopRequested);
        }
    }

    if (_parentTask != nullptr) {
        _parentTask->_childTaskCount -= 1;
    }

    _done = true;

    std::unique_lock<std::mutex> lk(_taskDoneMutex);
    _taskDoneCV.notify_one();

    if (BitCompare(_taskFlags, to_const_uint(TaskFlags::PRINT_DEBUG_INFO))) {
        Console::d_printfn(Locale::get(_ID("TASK_COMPLETE_IN_THREAD")), getGUID(), std::this_thread::get_id());
    }

    if (BitCompare(_taskFlags, to_const_uint(TaskFlags::SYNC_WITH_GPU))) {
        endSyncGPU();
    }

    // task finished. Everything else is bookkeeping
    _tp->taskCompleted(poolIndex(), _priority);
}

void Task::beginSyncGPU() {
    Attorney::ApplicationTask::syncThreadToGPU(std::this_thread::get_id(), true);
}

void Task::endSyncGPU() {
    Attorney::ApplicationTask::syncThreadToGPU(std::this_thread::get_id(), false);
}

};

Commits for Divide-Framework/trunk/Source Code/Platform/Threading/Task.cpp

Diff revisions: vs.
Revision Author Commited Message
757 Diff Diff IonutCava picture IonutCava Mon 01 Aug, 2016 16:13:27 +0000

[IonutCava]
- Add glObjectLabel calls for easier debugging
- Add config option to disable all multithreaded rendering API calls

756 Diff Diff IonutCava picture IonutCava Fri 29 Jul, 2016 16:09:29 +0000

[IonutCava]
- Cleaned up material shader:
— Add explicit functions for material colour properties
— Separate Phong from PBR
— Remove texture count variable and use TEX_OPERATION_NONE for single texture
- Added a Shader compute queue that all materials share. This allows better frame time allocation for shader compilation
- Attempt to fix Task and TaskPool race conditions

743 Diff Diff IonutCava picture IonutCava Tue 28 Jun, 2016 15:55:50 +0000

[IonutCava]
- More performance tuning:
— Move billboarding related camera variable calculation to shaders instead of CPU
— Replace some DIVIDE_ASSERT calls with regular assert calls in really low level code.
— Some cleanup of the GenericDrawCommand class
— glRegularBuffer does an invalidation call before updating
— Misc changes

730 Diff Diff IonutCava picture IonutCava Thu 16 Jun, 2016 15:35:07 +0000

[IonutCava]
- More shadow mapping fixes
- Small performance improvements
- Proper per scene XML data loading (e.g. fog)

716 Diff Diff IonutCava picture IonutCava Tue 31 May, 2016 16:08:29 +0000

[IonutCava]
- Multithreaded scene load/unload fixes:
— Added postLoadMainThread call for scenes for thread sensitive loading steps
— GUI element adding is a thread sensitive loading step (a fast one) because CEGUI doesn’t handle threading
- Added REALTIME_WITH_CALLBACK task priority for tasks that need an immediate callback when they complete instead of using the flushCallbackQueue system.
- Some work on shadow mapping for getting it to work again
- ShaderPrograms that fail to load can cause a LockManager infinite wait. Delete the lockManager if the shader didn’t load to avoid waiting on commands that never get called.

714 Diff Diff IonutCava picture IonutCava Thu 26 May, 2016 16:26:23 +0000

[IonutCava]
- Initial code for multithreaded scene load:
— Tasks can have a “sync with gpu” flag that will cause them to use a shared context (so they can call GL functions)
- Added per scene GUI lists that get passed to the main GUI class (still need a base class to hold the map and accessors to avoid code duplication)
- Re-enabled threading unit tests

693 Diff Diff IonutCava picture IonutCava Thu 28 Apr, 2016 16:19:35 +0000

[IonutCava]
- Cleanup Time and Profiling code

679 Diff Diff IonutCava picture IonutCava Wed 13 Apr, 2016 21:21:51 +0000

[IonutCava]
- Add unit tests for task system
- Adapt task system for better modularity
- Split Divide-Game into Game lib and Game executable projects
- Cleanup unit test projects

674 Diff Diff IonutCava picture IonutCava Mon 11 Apr, 2016 16:17:10 +0000

[IonutCava]
- Some profile guided optimizations:
— Remove the task state hashmap and replace with flat array
— Allow PhysX to load collision meshes from a RAM cache first -> then file -> then recompute
- Improve memory logger output

670 IonutCava picture IonutCava Wed 06 Apr, 2016 16:21:35 +0000

[IonutCava]
- getInstance() renamed to instance() for simplicity (should really go away altogether, but that’s a different issue)
- some particle emitter threading updates