HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CE_VDBCreate.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: CE_VDBCreate.h ( CE Library, C++)
7  *
8  * COMMENTS: GPU NanoVDB Creation.
9  */
10 
11 #ifndef __CE_VDBCreate__
12 #define __CE_VDBCreate__
13 
14 #include "CE_API.h"
15 
16 #include <bitset>
17 
18 #include <UT/UT_Error.h>
19 #include <UT/UT_String.h>
20 #include <UT/UT_Debug.h>
21 
22 #include <CE/CE_Context.h>
23 
24 #include <nanovdb/NanoVDB.h>
27 
28 namespace nanovdb
29 {
30 
31 //
32 // Pointer check utils
33 //
34 
35 static inline void ptrAssert(const void* ptr, const char* msg, const char* file, int line)
36 {
37  if (ptr == nullptr)
38  {
39  UTdebugFormatCd(red, "NULL pointer error: {} {} {}\n", msg, file, line);
40  UT_ASSERT(false);
41  }
42  else if (uint64_t(ptr) % NANOVDB_DATA_ALIGNMENT)
43  {
44  UTdebugFormatCd(red, "Pointer misalignment error: {} {} {}\n", msg, file, line);
45  UT_ASSERT(false);
46  }
47 }
48 
49 #define checkPtr(ptr, msg) \
50  { \
51  ptrAssert((ptr), (msg), __FILE__, __LINE__); \
52  }
53 
54 //
55 // OclDeviceBuffer
56 // TODO: should be moved to it's own header
57 //
58 
60 {
61  uint64_t mSize; // total number of bytes managed by this buffer (assumed to be identical for host and device)
62  uint8_t *mCpuData; // raw pointers to the host buffer
63  cl::Buffer mGpuData; // device buffer
64 
65 public:
66  /// @brief Static factory method that return an instance of this buffer
67  /// @param size byte size of buffer to be initialized
68  /// @param host If true buffer is initialized only on the host/CPU, else on the device/GPU
69  /// @return An instance of this class using move semantics
70  static OclDeviceBuffer create(uint64_t size, bool host = true);
71 
72  /// @brief Constructor
73  /// @param size byte size of buffer to be initialized
74  /// @param host If true buffer is initialized only on the host/CPU, else on the device/GPU
75  OclDeviceBuffer(uint64_t size = 0, bool host = true)
76  : mSize(0)
77  , mCpuData(nullptr)
78  , mGpuData(cl::Buffer())
79  {
80  if (size > 0) this->init(size, host);
81  }
82 
83  /// @brief Disallow copy-construction
84  OclDeviceBuffer(const OclDeviceBuffer&) = delete;
85 
86  /// @brief Move copy-constructor
87  OclDeviceBuffer(OclDeviceBuffer&& other) noexcept
88  : mSize(other.mSize)
89  , mCpuData(other.mCpuData)
90  , mGpuData(other.mGpuData)
91  {
92  other.mSize = 0;
93  other.mCpuData = nullptr;
94  other.mGpuData = cl::Buffer();
95  }
96 
97  /// @brief Disallow copy assignment operation
98  OclDeviceBuffer& operator=(const OclDeviceBuffer&) = delete;
99 
100  /// @brief Move copy assignment operation
102  {
103  this->clear();
104  mSize = other.mSize;
105  mCpuData = other.mCpuData;
106  mGpuData = other.mGpuData;
107  other.mSize = 0;
108  other.mCpuData = nullptr;
109  other.mGpuData = cl::Buffer();
110  return *this;
111  }
112 
113  /// @brief Destructor frees memory on both the host and device
114  ~OclDeviceBuffer() { this->clear(); };
115 
116  /// @brief Initialize buffer
117  /// @param size byte size of buffer to be initialized
118  /// @param host If true buffer is initialized only on the host/CPU, else on the device/GPU
119  /// @note All existing buffers are first cleared
120  /// @warning size is expected to be non-zero. Use clear() clear buffer!
121  void init(uint64_t size, bool host = true);
122 
123  /// @brief Retuns a raw pointer to the host/CPU buffer managed by this allocator.
124  /// @warning Note that the pointer can be NULL!
125  uint8_t* data() const { return mCpuData; }
126 
127  /// @brief Retuns a cl::Buffer ref to the device/GPU buffer managed by this allocator.
128  /// @warning Note that the pointer can be NULL!
129  const cl::Buffer& deviceData() const { return mGpuData; }
130 
131  /// @brief Upload this buffer from the host to the device, i.e. CPU -> GPU.
132  /// @param stream optional stream (defaults to stream 0) (never used)
133  /// @param sync if false the memory copy is asynchronous (never used)
134  /// @note If the device/GPU buffer does not exist it is first allocated
135  /// @warning Assumes that the host/CPU buffer already exists
136  void deviceUpload(void* stream = nullptr, bool sync = true);
137 
138  /// @brief Upload this buffer from the device to the host, i.e. GPU -> CPU.
139  /// @param stream optional stream (defaults to stream 0) (never used)
140  /// @param sync if false the memory copy is asynchronous (never used)
141  /// @note If the host/CPU buffer does not exist it is first allocated
142  /// @warning Assumes that the device/GPU buffer already exists
143  void deviceDownload(void* stream = nullptr, bool sync = true);
144 
145  /// @brief Returns the size in bytes of the raw memory buffer managed by this allocator.
146  uint64_t size() const { return mSize; }
147 
148  //@{
149  /// @brief Returns true if this allocator is empty, i.e. has no allocated memory
150  bool empty() const { return mSize == 0; }
151  bool isEmpty() const { return mSize == 0; }
152  //@}
153 
154  /// @brief De-allocate all memory managed by this allocator and set all pointers to NULL
155  void clear();
156 
157 };
158 
159 template<>
161 {
162  static constexpr bool hasDeviceDual = true;
163 };
164 
165 // --------------------------> Implementations below <--------------------------
166 
167 inline OclDeviceBuffer OclDeviceBuffer::create(uint64_t size, bool host)
168 {
169  return OclDeviceBuffer(size, host);
170 }
171 
172 inline void OclDeviceBuffer::init(uint64_t size, bool host)
173 {
174  if (mSize > 0)
175  this->clear();
176  UT_ASSERT(size > 0);
177  if (host)
178  {
179  mCpuData = new uint8_t[size];
180  checkPtr(mCpuData, "OclDeviceBuffer::init: failed to allocate host buffer");
181  }
182  else
183  {
184  CE_Context* context = CE_Context::getContext();
185  mGpuData = context->allocBuffer(size); // un-managed memory on the device, always 32B aligned!
186  checkPtr(mGpuData(), "OclDeviceBuffer::init: failed to allocate device buffer");
187  }
188  mSize = size;
189 }
190 
191 inline void OclDeviceBuffer::deviceUpload(void* stream, bool sync)
192 {
193  CE_Context *context = CE_Context::getContext();
194 
195  checkPtr(mCpuData, "uninitialized cpu data");
196  if (mGpuData() == nullptr) {
197  mGpuData = context->allocBuffer(mSize); // un-managed memory on the device, always 32B aligned!
198  }
199  checkPtr(mGpuData(), "uninitialized gpu data");
200 
201  context->writeBuffer(mGpuData, mSize, mCpuData);
202 }
203 
204 inline void OclDeviceBuffer::deviceDownload(void* stream, bool sync)
205 {
206  CE_Context *context = CE_Context::getContext();
207 
208  checkPtr(mGpuData(), "uninitialized gpu data");
209  if (mCpuData == nullptr) {
210  mCpuData = new uint8_t[mSize];
211  }
212  checkPtr(mCpuData, "uninitialized cpu data");
213 
214  context->readBuffer(mGpuData, mSize, mCpuData);
215 }
216 
218 {
219  CE_Context *context = CE_Context::getContext();
220  if (mGpuData() != nullptr) context->releaseBuffer(std::move(mGpuData));
221  if (mCpuData != nullptr) delete[] mCpuData;
222  mCpuData = nullptr;
223  mGpuData = cl::Buffer();
224  mSize = 0;
225 }
226 
227 } // nanovdb namespace
228 
230 {
231 public:
233 
234  static uint32_t
235  runLengthEncoding(
236  uint32_t in_count,
237  const cl::Buffer& input,
239  cl::Buffer& counts,
240  uint32_t bit_shift_right = 0);
241 
242  static void
243  radixSortPairs(
244  uint32_t in_count,
245  cl::Buffer& in_key,
246  cl::Buffer& in_val,
247  uint32_t lsb = -1,
248  uint32_t msb = -1,
249  uint32_t offset = 0, // offset in elems of the in_* arrays
250  uint32_t buffer_nelem = -1);
251 
252  template <
253  typename BuildT,
254  typename PtrT,
255  typename BufferT = nanovdb::OclDeviceBuffer>
256  static nanovdb::GridHandle<BufferT> oclPointsToGrid(
257  const PtrT d_ijk,
258  uint32_t voxelcount,
259  double voxelsize,
260  const uint32_t leafdilation,
261  const UT_String& gridname,
262  const nanovdb::GridClass gridclass,
263  const BuildT& bgvalue,
264  cl::Buffer& tilestart,
265  exint& tilestartcount,
266  void** datacacheptr);
267 
268  template <typename BuildT>
269  static void deleteDataCache(void* datacacheptr);
270 };
271 
272 #endif
GLuint GLuint stream
Definition: glcorearb.h:1832
#define CE_API
Definition: CE_API.h:11
void releaseBuffer(cl::Buffer &&buf)
Release the specified buffer, possibly to the CE_MemoryPool.
const cl::Buffer & deviceData() const
Retuns a cl::Buffer ref to the device/GPU buffer managed by this allocator.
Definition: CE_VDBCreate.h:129
GridClass
Classes (superset of OpenVDB) that are currently supported by NanoVDB.
Definition: NanoVDB.h:339
#define checkPtr(ptr, msg)
Definition: CE_VDBCreate.h:49
int64 exint
Definition: SYS_Types.h:125
#define UTdebugFormatCd(...)
Definition: UT_Debug.h:145
OclDeviceBuffer(uint64_t size=0, bool host=true)
Constructor.
Definition: CE_VDBCreate.h:75
uint8_t * data() const
Retuns a raw pointer to the host/CPU buffer managed by this allocator.
Definition: CE_VDBCreate.h:125
OclDeviceBuffer & operator=(OclDeviceBuffer &&other) noexcept
Move copy assignment operation.
Definition: CE_VDBCreate.h:101
void init(uint64_t size, bool host=true)
Initialize buffer.
Definition: CE_VDBCreate.h:172
void writeBuffer(const cl::Buffer &buf, size_t size, const void *p, bool blocking=true, size_t offset=0)
Write the specified number of bytes to the buffer.
Defines GridHandle, which manages a host, and possibly a device, memory buffer containing one or more...
uint64_t size() const
Returns the size in bytes of the raw memory buffer managed by this allocator.
Definition: CE_VDBCreate.h:146
This class serves to manage a buffer containing one or more NanoVDB Grids.
Definition: GridHandle.h:37
#define NANOVDB_DATA_ALIGNMENT
Definition: NanoVDB.h:154
GLintptr offset
Definition: glcorearb.h:665
static CE_Context * getContext(bool gl_shared=true, bool shared_fallback=true)
~OclDeviceBuffer()
Destructor frees memory on both the host and device.
Definition: CE_VDBCreate.h:114
Implements a light-weight self-contained VDB data-structure in a single file! In other words...
void readBuffer(const cl::Buffer &buf, size_t size, void *p, bool blocking=true, size_t offset=0)
Read the specified number of bytes from the buffer.
static OclDeviceBuffer create(uint64_t size, bool host=true)
Static factory method that return an instance of this buffer.
Definition: CE_VDBCreate.h:167
HostBuffer - a buffer that contains a shared or private bump pool to either externally or internally ...
OclDeviceBuffer & operator=(const OclDeviceBuffer &)=delete
Disallow copy assignment operation.
static constexpr bool hasDeviceDual
Definition: HostBuffer.h:101
bool isEmpty() const
Returns true if this allocator is empty, i.e. has no allocated memory.
Definition: CE_VDBCreate.h:151
void clear()
De-allocate all memory managed by this allocator and set all pointers to NULL.
Definition: CE_VDBCreate.h:217
GLsizeiptr size
Definition: glcorearb.h:664
void deviceUpload(void *stream=nullptr, bool sync=true)
Upload this buffer from the host to the device, i.e. CPU -> GPU.
Definition: CE_VDBCreate.h:191
GLenum GLsizei GLsizei GLint * values
Definition: glcorearb.h:1602
void deviceDownload(void *stream=nullptr, bool sync=true)
Upload this buffer from the device to the host, i.e. GPU -> CPU.
Definition: CE_VDBCreate.h:204
auto ptr(T p) -> const void *
Definition: format.h:2448
Memory buffer interface.
Definition: cl.hpp:1867
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
OclDeviceBuffer(OclDeviceBuffer &&other) noexcept
Move copy-constructor.
Definition: CE_VDBCreate.h:87
bool empty() const
Returns true if this allocator is empty, i.e. has no allocated memory.
Definition: CE_VDBCreate.h:150
png_structrp int png_fixed_point red
Definition: png.h:1083
cl::Buffer allocBuffer(int64 size, bool usePool=true, bool read=true, bool write=true, uint32 ogl_bind=SYS_UINT32_MAX)