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 <UT/UT_Debug.h>
17 #include <UT/UT_Error.h>
18 #include <UT/UT_NonCopyable.h>
19 #include <UT/UT_StringHolder.h>
20 #include <UT/UT_UniquePtr.h>
21 
22 #include <CE/CE_Context.h>
23 
24 #include <nanovdb/NanoVDB.h>
27 
28 #include <bitset>
29 #include <utility>
30 
31 namespace nanovdb
32 {
33 
34 //
35 // Pointer check utils
36 //
37 
38 static inline void
39 ptrAssert(const void* ptr, const char* msg, const char* file, int line)
40 {
41  if (ptr == nullptr)
42  {
43  UTdebugFormatCd(red, "NULL pointer error: {} {} {}\n", msg, file, line);
44  UT_ASSERT(false);
45  }
46  else if (uint64_t(ptr) % NANOVDB_DATA_ALIGNMENT)
47  {
48  UTdebugFormatCd(red, "Pointer misalignment error: {} {} {}\n", msg, file, line);
49  UT_ASSERT(false);
50  }
51 }
52 
53 static inline void
54 bufferAssert(const void* buf, const char* msg, const char* file, int line)
55 {
56  if (buf == nullptr)
57  {
58  UTdebugFormatCd(red, "NULL buffer error: {} {} {}\n", msg, file, line);
59  UT_ASSERT(false);
60  }
61 }
62 
63 #define CEcheckPtr(ptr, msg) \
64  { \
65  ptrAssert((ptr).get(), (msg), __FILE__, __LINE__); \
66  }
67 
68 #define CEcheckBuffer(buf, msg) \
69  { \
70  bufferAssert((buf), (msg), __FILE__, __LINE__); \
71  }
72 
73 //
74 // OclDeviceBuffer
75 // TODO: should be moved to it's own header
76 //
77 
79 {
80  uint64_t mySize; // total number of bytes managed by this buffer (assumed to be identical for host and device)
81  UT_UniquePtr<uint8_t[]> myCpuData; // raw pointers to the host buffer
82  cl::Buffer myGpuData; // device buffer
83 
84 public:
85  /// @brief Static factory method that return an instance of this buffer
86  /// @param size byte size of buffer to be initialized
87  /// @param host If true buffer is initialized only on the host/CPU, else on the device/GPU
88  /// @return An instance of this class using move semantics
89  static OclDeviceBuffer create(uint64_t size, bool host = true);
90 
91  /// @brief Constructor
92  /// @param size byte size of buffer to be initialized
93  /// @param host If true buffer is initialized only on the host/CPU, else on the device/GPU
94  OclDeviceBuffer(uint64_t size = 0, bool host = true)
95  : mySize(0)
96  , myCpuData(nullptr)
97  , myGpuData(cl::Buffer())
98  {
99  if (size > 0) this->init(size, host);
100  }
101 
102  /// @brief Disallow copy-construction
103  OclDeviceBuffer(const OclDeviceBuffer&) = delete;
104 
105  /// @brief Move copy-constructor
107  : mySize(std::exchange(other.mySize, 0))
108  , myCpuData(std::move(other.myCpuData))
109  , myGpuData(std::exchange(other.myGpuData, cl::Buffer()))
110  {
111  }
112 
113  /// @brief Disallow copy assignment operation
114  OclDeviceBuffer& operator=(const OclDeviceBuffer&) = delete;
115 
116  /// @brief Move copy assignment operation
118  {
119  this->clear();
120  mySize = std::exchange(other.mySize, 0);
121  myCpuData = std::move(other.myCpuData);
122  myGpuData = std::exchange(other.myGpuData, cl::Buffer());
123  return *this;
124  }
125 
126  /// @brief Destructor frees memory on both the host and device
127  ~OclDeviceBuffer() { this->clear(); };
128 
129  /// @brief Initialize buffer
130  /// @param size byte size of buffer to be initialized
131  /// @param host If true buffer is initialized only on the host/CPU, else on the device/GPU
132  /// @note All existing buffers are first cleared
133  /// @warning size is expected to be non-zero. Use clear() clear buffer!
134  void init(uint64_t size, bool host = true);
135 
136  /// @brief Retuns a raw pointer to the host/CPU buffer managed by this allocator.
137  /// @warning Note that the pointer can be NULL!
138  uint8_t* data() const { return myCpuData.get(); }
139 
140  /// @brief Retuns a cl::Buffer ref to the device/GPU buffer managed by this allocator.
141  /// @warning Note that the pointer can be NULL!
142  const cl::Buffer& deviceData() const { return myGpuData; }
143 
144  /// @brief Upload this buffer from the host to the device, i.e. CPU -> GPU.
145  /// @param stream optional stream (defaults to stream 0) (never used)
146  /// @param sync if false the memory copy is asynchronous (never used)
147  /// @note If the device/GPU buffer does not exist it is first allocated
148  /// @warning Assumes that the host/CPU buffer already exists
149  void deviceUpload(void* stream = nullptr, bool sync = true);
150 
151  /// @brief Upload this buffer from the device to the host, i.e. GPU -> CPU.
152  /// @param stream optional stream (defaults to stream 0) (never used)
153  /// @param sync if false the memory copy is asynchronous (never used)
154  /// @note If the host/CPU buffer does not exist it is first allocated
155  /// @warning Assumes that the device/GPU buffer already exists
156  void deviceDownload(void* stream = nullptr, bool sync = true);
157 
158  /// @brief Returns the size in bytes of the raw memory buffer managed by this allocator.
159  uint64_t size() const { return mySize; }
160 
161  //@{
162  /// @brief Returns true if this allocator is empty, i.e. has no allocated memory
163  bool empty() const { return mySize == 0; }
164  bool isEmpty() const { return mySize == 0; }
165  //@}
166 
167  /// @brief De-allocate all memory managed by this allocator and set all pointers to NULL
168  void clear();
169 
170 };
171 
172 template<>
174 {
175  static constexpr bool hasDeviceDual = true;
176 };
177 
178 // --------------------------> Implementations below <--------------------------
179 
180 inline OclDeviceBuffer
181 OclDeviceBuffer::create(uint64_t size, bool host)
182 {
183  return OclDeviceBuffer(size, host);
184 }
185 
186 inline void
187 OclDeviceBuffer::init(uint64_t size, bool host)
188 {
189  if (mySize > 0)
190  this->clear();
191  UT_ASSERT(size > 0);
192  if (host)
193  {
194  myCpuData = UTmakeUniqueForOverwrite<uint8_t[]>(size);
195  CEcheckPtr(myCpuData, "OclDeviceBuffer::init: failed to allocate host buffer");
196  }
197  else
198  {
199  CE_Context* context = CE_Context::getContext();
200  myGpuData = context->allocBuffer(size); // un-managed memory on the device, always 32B aligned!
201  CEcheckBuffer(myGpuData(), "OclDeviceBuffer::init: failed to allocate device buffer");
202  }
203  mySize = size;
204 }
205 
206 inline void
208 {
209  CE_Context *context = CE_Context::getContext();
210 
211  CEcheckPtr(myCpuData, "uninitialized cpu data");
212  if (myGpuData() == nullptr)
213  myGpuData = context->allocBuffer(mySize); // un-managed memory on the device, always 32B aligned!
214  CEcheckBuffer(myGpuData(), "uninitialized gpu data");
215 
216  context->writeBuffer(myGpuData, mySize, myCpuData.get());
217 }
218 
219 inline void
221 {
222  CE_Context *context = CE_Context::getContext();
223 
224  CEcheckBuffer(myGpuData(), "uninitialized gpu data");
225  if (myCpuData == nullptr)
226  myCpuData = UTmakeUniqueForOverwrite<uint8_t[]>(mySize);
227  CEcheckPtr(myCpuData, "uninitialized cpu data");
228 
229  context->readBuffer(myGpuData, mySize, myCpuData.get());
230 }
231 
232 inline void
234 {
235  CE_Context *context = CE_Context::getContext();
236  if (myGpuData() != nullptr)
237  context->releaseBuffer(std::move(myGpuData));
238  myCpuData.reset();
239  myGpuData = cl::Buffer();
240  mySize = 0;
241 }
242 
243 struct OclPointsData; // opaque
244 
245 } // nanovdb namespace
246 
248 {
249 public:
251 
252  static uint32_t
253  runLengthEncoding(
254  uint32_t in_count,
255  const cl::Buffer& input,
257  cl::Buffer& counts,
258  uint32_t bit_shift_right = 0);
259 
260  static void
261  radixSortPairs(
262  uint32_t in_count,
263  cl::Buffer& in_key,
264  cl::Buffer& in_val,
265  uint32_t lsb = -1,
266  uint32_t msb = -1,
267  uint32_t offset = 0, // offset in elems of the in_* arrays
268  uint32_t buffer_nelem = -1);
269 
271  {
272  public:
273  DataCache();
274  ~DataCache();
276 
277  bool hasData() const
278  {
279  return myDataPtr != nullptr;
280  }
281 
282  // WARNING: throws cl::Error exceptions
283  void clear();
284 
285  private:
287  friend class CE_VDBCreate;
288  };
289 
290  template <
291  typename BuildT,
292  typename PtrT,
293  typename BufferT = nanovdb::OclDeviceBuffer>
295  const PtrT d_ijk,
296  uint32_t voxelcount,
297  double voxelsize,
298  const bool activateleaves,
299  const uint32_t leafdilation,
300  const UT_StringHolder& gridname,
301  const nanovdb::GridClass gridclass,
302  const BuildT& bgvalue,
303  cl::Buffer& tilestart,
304  exint& leafcount,
305  exint& lowercount,
306  exint& uppercount,
307  DataCache* datacacheptr);
308 };
309 
310 #undef CEcheckPtr
311 #undef CEcheckBuffer
312 
313 #endif
GLuint GLuint stream
Definition: glcorearb.h:1832
#define CE_API
Definition: CE_API.h:13
#define CEcheckBuffer(buf, msg)
Definition: CE_VDBCreate.h:68
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glcorearb.h:2540
const cl::Buffer & deviceData() const
Retuns a cl::Buffer ref to the device/GPU buffer managed by this allocator.
Definition: CE_VDBCreate.h:142
GridClass
Classes (superset of OpenVDB) that are currently supported by NanoVDB.
Definition: NanoVDB.h:339
int64 exint
Definition: SYS_Types.h:125
#define UTdebugFormatCd(...)
Definition: UT_Debug.h:145
void releaseBuffer(cl::Buffer &&buf, bool use_pool=true)
Release the specified buffer, possibly to the CE_MemoryPool.
#define CEcheckPtr(ptr, msg)
Definition: CE_VDBCreate.h:63
OclDeviceBuffer(uint64_t size=0, bool host=true)
Constructor.
Definition: CE_VDBCreate.h:94
uint8_t * data() const
Retuns a raw pointer to the host/CPU buffer managed by this allocator.
Definition: CE_VDBCreate.h:138
OclDeviceBuffer & operator=(OclDeviceBuffer &&other) noexcept
Move copy assignment operation.
Definition: CE_VDBCreate.h:117
void init(uint64_t size, bool host=true)
Initialize buffer.
Definition: CE_VDBCreate.h:187
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.
OutGridT const XformOp bool bool
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:159
This class serves to manage a buffer containing one or more NanoVDB Grids.
Definition: GridHandle.h:37
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
#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:127
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:181
#define UT_NON_COPYABLE(CLASS)
Define deleted copy constructor and assignment operator inside a class.
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
cl::Buffer allocBuffer(int64 size, bool use_pool=true, bool read=true, bool write=true, uint32 ogl_bind=SYS_UINT32_MAX)
bool isEmpty() const
Returns true if this allocator is empty, i.e. has no allocated memory.
Definition: CE_VDBCreate.h:164
void clear()
De-allocate all memory managed by this allocator and set all pointers to NULL.
Definition: CE_VDBCreate.h:233
static nanovdb::GridHandle< BufferT > oclPointsToGrid(const PtrT d_ijk, uint32_t voxelcount, double voxelsize, const bool activateleaves, const uint32_t leafdilation, const UT_StringHolder &gridname, const nanovdb::GridClass gridclass, const BuildT &bgvalue, cl::Buffer &tilestart, exint &leafcount, exint &lowercount, exint &uppercount, DataCache *datacacheptr)
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:207
GLenum GLsizei GLsizei GLint * values
Definition: glcorearb.h:1602
VULKAN_HPP_CONSTEXPR_14 VULKAN_HPP_INLINE T exchange(T &obj, U &&newValue)
Definition: vulkan_raii.hpp:25
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:220
auto ptr(T p) -> const void *
Definition: format.h:4331
Memory buffer interface.
Definition: cl.hpp:1867
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:165
OclDeviceBuffer(OclDeviceBuffer &&other) noexcept
Move copy-constructor.
Definition: CE_VDBCreate.h:106
bool empty() const
Returns true if this allocator is empty, i.e. has no allocated memory.
Definition: CE_VDBCreate.h:163
png_structrp int png_fixed_point red
Definition: png.h:1083