00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef _LUXRAYS_PIXELDEVICE_H
00023 #define _LUXRAYS_PIXELDEVICE_H
00024
00025 #include <boost/thread/mutex.hpp>
00026
00027 #include "luxrays/luxrays.h"
00028 #include "luxrays/core/device.h"
00029 #include "luxrays/core/pixel/framebuffer.h"
00030 #include "luxrays/core/pixel/filter.h"
00031
00032 namespace luxrays {
00033
00034
00035
00036
00037
00038 typedef enum {
00039 TONEMAP_LINEAR, TONEMAP_REINHARD02
00040 } ToneMapType;
00041
00042 class ToneMapParams {
00043 public:
00044 virtual ToneMapType GetType() const = 0;
00045 virtual ToneMapParams *Copy() const = 0;
00046 };
00047
00048 class LinearToneMapParams : public ToneMapParams {
00049 public:
00050 LinearToneMapParams(const float s = 1.f) {
00051 scale = s;
00052 }
00053
00054 ToneMapType GetType() const { return TONEMAP_LINEAR; }
00055
00056 ToneMapParams *Copy() const {
00057 return new LinearToneMapParams(scale);
00058 }
00059
00060 float scale;
00061 };
00062
00063 class Reinhard02ToneMapParams : public ToneMapParams {
00064 public:
00065 Reinhard02ToneMapParams(const float preS = 1.f, const float postS = 1.2f,
00066 const float b = 3.75f) {
00067 preScale = preS;
00068 postScale = postS;
00069 burn = b;
00070 }
00071
00072 ToneMapType GetType() const { return TONEMAP_REINHARD02; }
00073
00074 ToneMapParams *Copy() const {
00075 return new Reinhard02ToneMapParams(preScale, postScale, burn);
00076 }
00077
00078 float preScale, postScale, burn;
00079 };
00080
00081
00082
00083
00084
00085 typedef enum {
00086 FILTER_NONE, FILTER_PREVIEW, FILTER_GAUSSIAN
00087 } FilterType;
00088
00089
00090
00091
00092
00093 class PixelDevice : public Device {
00094 public:
00095 virtual void Init(const unsigned int w, const unsigned int h);
00096 virtual void ClearFrameBuffer() = 0;
00097 virtual void ClearSampleFrameBuffer() = 0;
00098 virtual void SetGamma(const float gamma = 2.2f) = 0;
00099
00100 virtual SampleBuffer *GetFreeSampleBuffer() = 0;
00101 virtual void FreeSampleBuffer(SampleBuffer *sampleBuffer) = 0;
00102 virtual void AddSampleBuffer(const FilterType type, SampleBuffer *sampleBuffer) = 0;
00103
00104 virtual void Merge(const SampleFrameBuffer *sfb) = 0;
00105 virtual const SampleFrameBuffer *GetSampleFrameBuffer() const = 0;
00106
00107 virtual void UpdateFrameBuffer(const ToneMapParams ¶ms) = 0;
00108 virtual const FrameBuffer *GetFrameBuffer() const = 0;
00109
00110 double GetPerformance() const {
00111 return (statsTotalSampleTime == 0.0) ? 1.0 : (statsTotalSamplesCount / statsTotalSampleTime);
00112 }
00113
00114 friend class Context;
00115
00116 protected:
00117 PixelDevice(const Context *context, const DeviceType type, const unsigned int index);
00118 virtual ~PixelDevice();
00119
00120 virtual void Start();
00121
00122 unsigned int width, height;
00123 double statsTotalSampleTime, statsTotalSamplesCount;
00124 };
00125
00126
00127
00128
00129
00130 class NativePixelDevice : public PixelDevice {
00131 public:
00132 NativePixelDevice(const Context *context, const unsigned int threadIndex,
00133 const unsigned int devIndex);
00134 ~NativePixelDevice();
00135
00136 void Init(const unsigned int w, const unsigned int h);
00137 void ClearFrameBuffer();
00138 void ClearSampleFrameBuffer();
00139 void SetGamma(const float gamma = 2.2f);
00140
00141 void Start();
00142 void Interrupt();
00143 void Stop();
00144
00145 SampleBuffer *GetFreeSampleBuffer();
00146 void FreeSampleBuffer(SampleBuffer *sampleBuffer);
00147 void AddSampleBuffer(const FilterType type, SampleBuffer *sampleBuffer);
00148
00149 void Merge(const SampleFrameBuffer *sfb);
00150 const SampleFrameBuffer *GetSampleFrameBuffer() const;
00151
00152 void UpdateFrameBuffer(const ToneMapParams ¶ms);
00153 const FrameBuffer *GetFrameBuffer() const { return frameBuffer; }
00154
00155 unsigned int GetFreeDevBufferCount() {
00156 boost::mutex::scoped_lock lock(splatMutex);
00157
00158 return freeSampleBuffers.size();
00159 }
00160 unsigned int GetTotalDevBufferCount() {
00161 boost::mutex::scoped_lock lock(splatMutex);
00162
00163 return sampleBuffers.size();
00164 }
00165
00166 static size_t SampleBufferSize;
00167
00168 friend class Context;
00169
00170 private:
00171 static const unsigned int GammaTableSize = 1024;
00172
00173 void SplatPreview(const SampleBufferElem *sampleElem);
00174 void SplatFiltered(const SampleBufferElem *sampleElem);
00175
00176 void SplatRadiance(const Spectrum radiance, const unsigned int x, const unsigned int y, const float weight = 1.f) {
00177 const unsigned int offset = x + y * width;
00178 SamplePixel *sp = &(sampleFrameBuffer->GetPixels()[offset]);
00179
00180 sp->radiance += weight * radiance;
00181 sp->weight += weight;
00182 }
00183
00184 float Radiance2PixelFloat(const float x) const {
00185
00186
00187
00188 const float indexf = GammaTableSize * Clamp(x, 0.f, 1.f);
00189 if (indexf < 0.f)
00190 return 0.f;
00191
00192 const unsigned int index = Min<unsigned int>((unsigned int) indexf, GammaTableSize - 1);
00193
00194 return gammaTable[index];
00195 }
00196
00197 boost::mutex splatMutex;
00198 SampleFrameBuffer *sampleFrameBuffer;
00199 FrameBuffer *frameBuffer;
00200
00201 std::vector<SampleBuffer *> sampleBuffers;
00202 std::deque<SampleBuffer *> freeSampleBuffers;
00203
00204 float gammaTable[GammaTableSize];
00205
00206 Filter *filter;
00207 FilterLUTs *filterLUTs;
00208 };
00209
00210
00211
00212
00213
00214 #if !defined(LUXRAYS_DISABLE_OPENCL)
00215
00216 class OpenCLPixelDevice;
00217
00218 class OpenCLSampleBuffer : public SampleBuffer {
00219 public:
00220 OpenCLSampleBuffer(OpenCLPixelDevice *dev, const size_t bufferSize);
00221 ~OpenCLSampleBuffer();
00222
00223 void Write() const;
00224 void Wait() const;
00225 void CollectStats() const;
00226
00227 cl::Buffer *GetOCLBuffer() { return oclBuffer; }
00228 cl::Event *GetOCLEvent() { return &oclEvent; }
00229
00230 private:
00231 OpenCLPixelDevice *device;
00232 cl::Buffer *oclBuffer;
00233 cl::Event oclEvent;
00234 };
00235
00236 class OpenCLPixelDevice : public PixelDevice {
00237 public:
00238 OpenCLPixelDevice(const Context *context, OpenCLDeviceDescription *desc,
00239 const unsigned int index);
00240 ~OpenCLPixelDevice();
00241
00242 void Init(const unsigned int w, const unsigned int h);
00243 void ClearFrameBuffer();
00244 void ClearSampleFrameBuffer();
00245 void SetGamma(const float gamma = 2.2f);
00246
00247 void Start();
00248 void Interrupt();
00249 void Stop();
00250
00251 SampleBuffer *GetFreeSampleBuffer();
00252 void FreeSampleBuffer(SampleBuffer *sampleBuffer);
00253 void AddSampleBuffer(const FilterType type, SampleBuffer *sampleBuffer);
00254
00255 void Merge(const SampleFrameBuffer *sfb);
00256 const SampleFrameBuffer *GetSampleFrameBuffer() const;
00257
00258 void UpdateFrameBuffer(const ToneMapParams ¶ms);
00259 const FrameBuffer *GetFrameBuffer() const { return frameBuffer; }
00260
00261 const OpenCLDeviceDescription *GetDeviceDesc() const { return deviceDesc; }
00262
00263 unsigned int GetFreeDevBufferCount() {
00264 boost::mutex::scoped_lock lock(splatMutex);
00265
00266 return freeSampleBuffers.size();
00267 }
00268 unsigned int GetTotalDevBufferCount() {
00269 boost::mutex::scoped_lock lock(splatMutex);
00270
00271 return sampleBuffers.size();
00272 }
00273
00274 static size_t SampleBufferSize;
00275
00276 friend class Context;
00277 friend class OpenCLSampleBuffer;
00278
00279 private:
00280 static const unsigned int GammaTableSize = 1024;
00281 static const unsigned int FilterTableSize = 16;
00282
00283 void CompileKernel(cl::Context &ctx, cl::Device &device, const std::string &src,
00284 const char *kernelName, cl::Kernel **kernel);
00285
00286 OpenCLDeviceDescription *deviceDesc;
00287 SampleFrameBuffer *sampleFrameBuffer;
00288 FrameBuffer *frameBuffer;
00289
00290 boost::mutex splatMutex;
00291
00292
00293 cl::CommandQueue *oclQueue;
00294
00295
00296 cl::Kernel *clearFBKernel;
00297 size_t clearFBWorkGroupSize;
00298
00299 cl::Kernel *clearSampleFBKernel;
00300 cl::Kernel *addSampleBufferKernel;
00301 cl::Kernel *addSampleBufferPreviewKernel;
00302 cl::Kernel *addSampleBufferGaussian2x2Kernel;
00303 cl::Kernel *updateFrameBufferKernel;
00304
00305
00306 cl::Buffer *sampleFrameBuff;
00307 cl::Buffer *frameBuff;
00308
00309 std::vector<OpenCLSampleBuffer *> sampleBuffers;
00310 std::deque<OpenCLSampleBuffer *> freeSampleBuffers;
00311
00312 cl::Buffer *gammaTableBuff;
00313 cl::Buffer *filterTableBuff;
00314
00315 float gammaTable[GammaTableSize];
00316 float Gaussian2x2_filterTable[FilterTableSize * FilterTableSize];
00317 };
00318
00319 #endif
00320
00321 }
00322
00323 #endif