00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef _LUXRAYS_RAYBUFFER_H
00024 #define _LUXRAYS_RAYBUFFER_H
00025
00026 #include <deque>
00027 #include <vector>
00028 #include <cmath>
00029 #include <limits>
00030 #include <algorithm>
00031
00032 #include "luxrays/core/geometry/ray.h"
00033
00034 #include <boost/thread/mutex.hpp>
00035 #include <boost/thread/condition_variable.hpp>
00036
00037 namespace luxrays {
00038
00039
00040 class RayBuffer {
00041 public:
00042 RayBuffer(const size_t bufferSize) : size(bufferSize), currentFreeRayIndex(0) {
00043 rays = new Ray[size];
00044 rayHits = new RayHit[size];
00045 }
00046
00047 ~RayBuffer() {
00048 delete[] rays;
00049 delete[] rayHits;
00050 }
00051
00052 void PushUserData(size_t data) {
00053 userData.push_back(data);
00054 }
00055
00056 size_t GetUserData() {
00057 return userData.back();
00058 }
00059
00060 size_t GetUserData(const size_t index) {
00061 assert (index < userData.size());
00062
00063 return userData[userData.size() - index - 1];
00064 }
00065
00066 size_t PopUserData() {
00067 size_t data = userData.back();
00068 userData.pop_back();
00069
00070 return data;
00071 }
00072
00073 size_t GetUserDataCount() {
00074 return userData.size();
00075 }
00076
00077 void ResetUserData() {
00078 userData.clear();
00079 }
00080
00081 void Reset() {
00082 currentFreeRayIndex = 0;
00083 }
00084
00085 size_t ReserveRay() {
00086 assert (currentFreeRayIndex < size);
00087 return currentFreeRayIndex++;
00088 }
00089
00090 size_t AddRay(const Ray &ray) {
00091 assert (currentFreeRayIndex < size);
00092 rays[currentFreeRayIndex] = ray;
00093
00094 return currentFreeRayIndex++;
00095 }
00096
00097 const RayHit *GetRayHit(const size_t index) const {
00098 return &rayHits[index];
00099 }
00100
00101 size_t GetSize() const {
00102 return size;
00103 }
00104
00105 size_t GetRayCount() const {
00106 return currentFreeRayIndex;
00107 }
00108
00109 bool IsFull() const {
00110 return (currentFreeRayIndex >= size);
00111 }
00112
00113 size_t LeftSpace() const {
00114 return size - currentFreeRayIndex;
00115 }
00116
00117 Ray *GetRayBuffer() const {
00118 return rays;
00119 }
00120
00121 RayHit *GetHitBuffer() {
00122 return rayHits;
00123 }
00124
00125 private:
00126 size_t size;
00127 size_t currentFreeRayIndex;
00128 std::vector<size_t> userData;
00129
00130 Ray *rays;
00131 RayHit *rayHits;
00132 };
00133
00134
00135 class RayBufferQueue {
00136 public:
00137 virtual ~RayBufferQueue() { }
00138
00139 virtual void Clear() = 0;
00140 virtual size_t GetSizeToDo() = 0;
00141 virtual size_t GetSizeDone() = 0;
00142
00143 virtual void PushToDo(RayBuffer *rayBuffer, const unsigned int index) = 0;
00144 virtual RayBuffer *PopToDo() = 0;
00145
00146 virtual void Pop3xToDo(RayBuffer **rayBuffer0, RayBuffer **rayBuffer1, RayBuffer **rayBuffer2) = 0;
00147
00148 virtual void PushDone(RayBuffer *rayBuffer) = 0;
00149 virtual RayBuffer *PopDone(const unsigned int index = 0) = 0;
00150 };
00151
00152 class RayBufferSingleQueue {
00153 public:
00154 RayBufferSingleQueue() {
00155 }
00156
00157 ~RayBufferSingleQueue() {
00158 }
00159
00160 void Clear() {
00161 boost::unique_lock<boost::mutex> lock(queueMutex);
00162
00163 queue.clear();
00164 }
00165
00166 size_t GetSize() {
00167 boost::unique_lock<boost::mutex> lock(queueMutex);
00168
00169 return queue.size();
00170 }
00171
00172
00173
00174 void Push(RayBuffer *rayBuffer) {
00175 {
00176 boost::unique_lock<boost::mutex> lock(queueMutex);
00177 queue.push_back(rayBuffer);
00178 }
00179
00180 condition.notify_all();
00181 }
00182
00183 RayBuffer *Pop() {
00184 boost::unique_lock<boost::mutex> lock(queueMutex);
00185
00186 while (queue.size() < 1) {
00187
00188 condition.wait(lock);
00189 }
00190
00191 RayBuffer *rayBuffer = queue.front();
00192 queue.pop_front();
00193 return rayBuffer;
00194 }
00195
00196 void Pop3x(RayBuffer **rayBuffer0, RayBuffer **rayBuffer1, RayBuffer **rayBuffer2) {
00197 boost::unique_lock<boost::mutex> lock(queueMutex);
00198
00199 while (queue.size() < 1) {
00200
00201 condition.wait(lock);
00202 }
00203
00204 switch (queue.size()) {
00205 default:
00206 case 3:
00207 *rayBuffer0 = queue[0];
00208 *rayBuffer1 = queue[1];
00209 *rayBuffer2 = queue[2];
00210 queue.erase(queue.begin(), queue.begin() + 3);
00211 break;
00212 case 2:
00213 *rayBuffer0 = queue[0];
00214 *rayBuffer1 = queue[1];
00215 *rayBuffer2 = NULL;
00216 queue.erase(queue.begin(), queue.begin() + 2);
00217 break;
00218 case 1:
00219 *rayBuffer0 = queue[0];
00220 *rayBuffer1 = NULL;
00221 *rayBuffer2 = NULL;
00222 queue.pop_front();
00223 break;
00224 }
00225 }
00226
00227
00228
00229 void Push(RayBuffer *rayBuffer, const unsigned int queueIndex) {
00230 {
00231 boost::unique_lock<boost::mutex> lock(queueMutex);
00232 rayBuffer->PushUserData(queueIndex);
00233 queue.push_back(rayBuffer);
00234 }
00235
00236 condition.notify_all();
00237 }
00238
00239 RayBuffer *Pop(const unsigned int queueIndex) {
00240 boost::unique_lock<boost::mutex> lock(queueMutex);
00241
00242 for (;;) {
00243 for (size_t i = 0; i < queue.size(); ++i) {
00244
00245 if (queue[i]->GetUserData() == queueIndex) {
00246 RayBuffer *rayBuffer = queue[i];
00247 queue.erase(queue.begin() + i);
00248 rayBuffer->PopUserData();
00249
00250 return rayBuffer;
00251 }
00252 }
00253
00254
00255 condition.wait(lock);
00256 }
00257 }
00258
00259
00260
00261 void Push(RayBuffer *rayBuffer, const unsigned int queueIndex, const unsigned int queueProgressive) {
00262 {
00263 boost::unique_lock<boost::mutex> lock(queueMutex);
00264
00265 rayBuffer->PushUserData(queueProgressive);
00266 rayBuffer->PushUserData(queueIndex);
00267 queue.push_back(rayBuffer);
00268 }
00269
00270 condition.notify_all();
00271 }
00272
00273 RayBuffer *Pop(const unsigned int queueIndex, const unsigned int queueProgressive) {
00274 boost::unique_lock<boost::mutex> lock(queueMutex);
00275
00276 for (;;) {
00277 for (size_t i = 0; i < queue.size(); ++i) {
00278
00279 if ((queue[i]->GetUserData(0) == queueIndex) &&
00280 (queue[i]->GetUserData(1) == queueProgressive)) {
00281 RayBuffer *rayBuffer = queue[i];
00282 queue.erase(queue.begin() + i);
00283 rayBuffer->PopUserData();
00284 rayBuffer->PopUserData();
00285
00286 return rayBuffer;
00287 }
00288 }
00289
00290
00291 condition.wait(lock);
00292 }
00293 }
00294
00295 private:
00296 boost::mutex queueMutex;
00297 boost::condition_variable condition;
00298
00299 std::deque<RayBuffer *> queue;
00300 };
00301
00302
00303 class RayBufferQueueO2O : public RayBufferQueue {
00304 public:
00305 RayBufferQueueO2O() { }
00306 ~RayBufferQueueO2O() { }
00307
00308 void Clear() {
00309 todoQueue.Clear();
00310 doneQueue.Clear();
00311 }
00312
00313 size_t GetSizeToDo() { return todoQueue.GetSize(); }
00314 size_t GetSizeDone() { return doneQueue.GetSize(); }
00315
00316 void PushToDo(RayBuffer *rayBuffer, const unsigned int queueIndex) { todoQueue.Push(rayBuffer); }
00317 RayBuffer *PopToDo() { return todoQueue.Pop(); }
00318 void Pop3xToDo(RayBuffer **rayBuffer0, RayBuffer **rayBuffer1, RayBuffer **rayBuffer2) {
00319 todoQueue.Pop3x(rayBuffer0, rayBuffer1, rayBuffer2);
00320 }
00321
00322 void PushDone(RayBuffer *rayBuffer) { doneQueue.Push(rayBuffer); }
00323 RayBuffer *PopDone(const unsigned int queueIndex) { return doneQueue.Pop(); }
00324
00325 private:
00326 RayBufferSingleQueue todoQueue;
00327 RayBufferSingleQueue doneQueue;
00328 };
00329
00330
00331 class RayBufferQueueM2O : public RayBufferQueue {
00332 public:
00333 RayBufferQueueM2O() { }
00334 ~RayBufferQueueM2O() { }
00335
00336 void Clear() {
00337 todoQueue.Clear();
00338 doneQueue.Clear();
00339 }
00340
00341 size_t GetSizeToDo() { return todoQueue.GetSize(); }
00342 size_t GetSizeDone() { return doneQueue.GetSize(); }
00343
00344 void PushToDo(RayBuffer *rayBuffer, const unsigned int queueIndex) { todoQueue.Push(rayBuffer, queueIndex); }
00345 RayBuffer *PopToDo() { return todoQueue.Pop(); }
00346 void Pop3xToDo(RayBuffer **rayBuffer0, RayBuffer **rayBuffer1, RayBuffer **rayBuffer2) {
00347 todoQueue.Pop3x(rayBuffer0, rayBuffer1, rayBuffer2);
00348 }
00349
00350 void PushDone(RayBuffer *rayBuffer) { doneQueue.Push(rayBuffer); }
00351 RayBuffer *PopDone(const unsigned int queueIndex) { return doneQueue.Pop(queueIndex); }
00352
00353 private:
00354 RayBufferSingleQueue todoQueue;
00355 RayBufferSingleQueue doneQueue;
00356 };
00357
00358
00359 class RayBufferQueueM2M : public RayBufferQueue {
00360 public:
00361 RayBufferQueueM2M(const unsigned int consumersCount) {
00362 queueToDoCounters.resize(consumersCount);
00363 std::fill(queueToDoCounters.begin(), queueToDoCounters.end(), 0);
00364 queueDoneCounters.resize(consumersCount, 0);
00365 std::fill(queueDoneCounters.begin(), queueDoneCounters.end(), 0);
00366 }
00367 ~RayBufferQueueM2M() { }
00368
00369 void Clear() {
00370 todoQueue.Clear();
00371 doneQueue.Clear();
00372 }
00373
00374 size_t GetSizeToDo() { return todoQueue.GetSize(); }
00375 size_t GetSizeDone() { return doneQueue.GetSize(); }
00376
00377 void PushToDo(RayBuffer *rayBuffer, const unsigned int queueIndex) {
00378 todoQueue.Push(rayBuffer, queueIndex, queueToDoCounters[queueIndex]);
00379 queueToDoCounters[queueIndex]++;
00380 }
00381 RayBuffer *PopToDo() { return todoQueue.Pop(); }
00382 void Pop3xToDo(RayBuffer **rayBuffer0, RayBuffer **rayBuffer1, RayBuffer **rayBuffer2) {
00383 todoQueue.Pop3x(rayBuffer0, rayBuffer1, rayBuffer2);
00384 }
00385
00386 void PushDone(RayBuffer *rayBuffer) { doneQueue.Push(rayBuffer); }
00387 RayBuffer *PopDone(const unsigned int queueIndex) {
00388 RayBuffer *rb = doneQueue.Pop(queueIndex, queueDoneCounters[queueIndex]);
00389 queueDoneCounters[queueIndex]++;
00390
00391 return rb;
00392 }
00393
00394 private:
00395 std::vector<unsigned int> queueToDoCounters;
00396 std::vector<unsigned int> queueDoneCounters;
00397 RayBufferSingleQueue todoQueue;
00398 RayBufferSingleQueue doneQueue;
00399 };
00400
00401 }
00402
00403 #endif