00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef NVBLASTEXTPXTASKIMPL_H
00030 #define NVBLASTEXTPXTASKIMPL_H
00031
00032 #include "NvBlastExtPxTask.h"
00033 #include "PxTask.h"
00034 #include "NvBlastTkGroup.h"
00035
00036 #include <atomic>
00037 #include <mutex>
00038 #include <condition_variable>
00039
00040 namespace Nv
00041 {
00042 namespace Blast
00043 {
00044
00048 class ExtTaskSync
00049 {
00050 public:
00054 ExtTaskSync(uint32_t count) : m_count(count) {}
00055
00059 void wait()
00060 {
00061 std::unique_lock<std::mutex> lk(m_mutex);
00062 m_cv.wait(lk, [&] { return m_count == 0; });
00063 }
00064
00068 void notify()
00069 {
00070
00071 std::unique_lock<std::mutex> lk(m_mutex);
00072 if (m_count > 0)
00073 {
00074 m_count--;
00075 }
00076 if (m_count == 0)
00077 {
00078 lk.unlock();
00079 m_cv.notify_one();
00080 }
00081 }
00082
00086 bool isDone()
00087 {
00088 std::unique_lock<std::mutex> lk(m_mutex);
00089 return m_count == 0;
00090 }
00091
00095 void setCount(uint32_t count)
00096 {
00097 m_count = count;
00098 }
00099
00100 private:
00101 std::mutex m_mutex;
00102 std::condition_variable m_cv;
00103 uint32_t m_count;
00104 };
00105
00106
00110 class ExtAtomicCounter
00111 {
00112 public:
00113 ExtAtomicCounter() : m_current(0), m_maxCount(0) {}
00114
00115 bool isValid(uint32_t val)
00116 {
00117 return val < m_maxCount;
00118 }
00119
00120 uint32_t next()
00121 {
00122 return m_current.fetch_add(1);
00123 }
00124
00125 void reset(uint32_t maxCount)
00126 {
00127 m_maxCount = maxCount;
00128 m_current = 0;
00129 }
00130 private:
00131 std::atomic<uint32_t> m_current;
00132 uint32_t m_maxCount;
00133 };
00134
00135
00139 class ExtGroupWorkerTask : public physx::PxLightCpuTask
00140 {
00141 public:
00142 ExtGroupWorkerTask() : PxLightCpuTask(), m_group(nullptr), m_counter(nullptr), m_sync(nullptr)
00143 {
00144 }
00145
00146 void setup(TkGroup* group, ExtAtomicCounter* counter, ExtTaskSync* sync)
00147 {
00148 m_group = group;
00149 m_counter = counter;
00150 m_sync = sync;
00151 }
00152
00153 virtual void run() override
00154 {
00155 Nv::Blast::TkGroupWorker* worker = m_group->acquireWorker();
00156 uint32_t jobID = m_counter->next();
00157 while (m_counter->isValid(jobID))
00158 {
00159 worker->process(jobID);
00160 jobID = m_counter->next();
00161 }
00162 m_group->returnWorker(worker);
00163 }
00164
00165 virtual void release() override
00166 {
00167 PxLightCpuTask::release();
00168
00169
00170 m_sync->notify();
00171 }
00172
00173 virtual const char* getName() const override { return "BlastGroupWorkerTask"; }
00174
00175 private:
00176 TkGroup* m_group;
00177 ExtAtomicCounter* m_counter;
00178 ExtTaskSync* m_sync;
00179 };
00180
00181
00185 class ExtGroupTaskManagerImpl : public ExtGroupTaskManager
00186 {
00187 public:
00188 ExtGroupTaskManagerImpl(physx::PxTaskManager& taskManager, TkGroup* group)
00189 : m_taskManager(taskManager), m_sync(0), m_group(group) {}
00190
00191
00192 virtual void setGroup(TkGroup*) override;
00193 virtual uint32_t process(uint32_t) override;
00194 virtual void release() override;
00195 virtual bool wait(bool block) override;
00196
00197 private:
00198 static const uint32_t TASKS_MAX_COUNT = 16;
00199 physx::PxTaskManager& m_taskManager;
00200 ExtAtomicCounter m_counter;
00201 ExtGroupWorkerTask m_tasks[TASKS_MAX_COUNT];
00202 ExtTaskSync m_sync;
00203 TkGroup* m_group;
00204 };
00205
00206 }
00207 }
00208
00209 #endif // NVBLASTEXTPXTASKIMPL_H