HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
IMX_VDB.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: IMX_VDB.h
7  *
8  * COMMENTS:
9  * Holder for NanoVDBs, either on GPU or CPU
10  */
11 
12 #ifndef __IMX_VDB_h__
13 #define __IMX_VDB_h__
14 
15 #include "IMX_API.h"
16 #include "IMX_Types.h"
17 #include "IMX_PoolEntry.h"
18 #include <CE/CE_BufferHost.h>
19 
20 #include <GA/GA_PrimVolumeXform.h>
21 #include <CE/CE_VDBGrid.h>
22 #include <UT/UT_Lock.h>
23 #include <UT/UT_SharedPtr.h>
24 #include <UT/UT_UniquePtr.h>
25 #include <UT/UT_Options.h>
26 #include <SYS/SYS_AtomicInt.h>
27 
28 #include <openvdb/Platform.h>
29 #include <openvdb/openvdb.h>
30 
31 
32 class IMX_VDB;
35 
37 {
38 public:
39  /// An un-allocated null-VDB, but with default meta data.
40  IMX_VDB();
41 
42  IMX_VDB(const IMX_VDB &other) { copy(other); }
43  IMX_VDB(IMX_VDB && other) noexcept { swap(other); }
44 
45  ~IMX_VDB() override;
46 
47  EntryType poolTypeID() const override { return EntryType::VDB; }
48 
49  /// Assignment operators
50  void copy(const IMX_VDB &other);
51  IMX_VDB &operator=(const IMX_VDB &other) { copy(other); return *this; }
52 
53  void swap(IMX_VDB &other);
54  IMX_VDB &operator=(IMX_VDB &&other) { swap(other); return *this; }
55 
56  /// Conversion to/from openvdb.
57  /// Can throw CE exceptions.
58  openvdb::GridBase::Ptr createVDB() const;
59 
60  /// Returns true for successful save.
61  bool save(std::ostream &os) const;
62  bool saveJSON(UT_JSONWriter &w) const;
63 
64  /// Returns a newly created VDB loaded from the stream, or null
65  /// if load failure.
66  static IMX_VDBPtr load(UT_IStream &is);
67  static IMX_VDBPtr loadJSON(UT_JSONParser &p);
68 
69  /// Write our fields into the provided options:
70  /// THis does not include attributes.
71  void copyMetadataToOptions(UT_Options &opt) const;
72  /// Load ourselves from the options, ignoring fields we don't know
73  void updateMetadataFromOptions(const UT_Options &opt);
74 
75  /// Copies a VDB into ourselves, creating both CPU and GPU buffers
76  /// by default.
77  /// Can throw CE exceptions.
78  void copyFromVDB(const openvdb::GridBase &vdb,
79  const UT_Vector3 &voxelsize,
80  const GA_PrimVolumeXform &indexspace,
81  bool ontocpu=true, bool ontogppu=true);
82  void cpuCopyFromVDB(const openvdb::GridBase &vdb,
83  const UT_Vector3 &voxelsize,
84  const GA_PrimVolumeXform &indexspace)
85  { copyFromVDB(vdb, voxelsize, indexspace, true, false); }
86  void gpuCopyFromVDB(const openvdb::GridBase &vdb,
87  const UT_Vector3 &voxelsize,
88  const GA_PrimVolumeXform &indexspace)
89  { copyFromVDB(vdb, voxelsize, indexspace, false, true); }
90 
91  /// Replaces self with a vdb using the provided source's
92  /// topology.
93  /// If same type this is just a copy(). Otherewise it is zeroed.
94  /// Copies transform & metadata options.
95  void buildFromTopology(UT_VDBType storage,
96  const IMX_VDB *refvdb);
97 
98  /// Returns this vdb's GPU storage object. If read is true, isDirty must
99  /// be false. If write is true then it turns off isDirty by setting
100  /// isOnGPU() and turning off isOnCPU() (it is assuming caller will actually
101  /// write the buffer)
102  /// When using one of these methods, this buffer must be guarded with the
103  /// in-use GPU flag. See setInUseGPUFlag() documentation for more
104  /// information.
105  /// Can throw CE exceptions.
106  CE_VDBGrid *getGPUBuffer(bool read, bool write);
107  const CE_VDBGrid *getGPUBufferR() const;
108  CE_VDBGrid *getGPUBufferW() { return getGPUBuffer(false, true); }
109 
110  UT_VDBType storageType() const { return myStorageType; }
111  int getChannels() const;
112  static const char *cnanovdbStorageDefine(UT_VDBType storagetype);
113 
114  void setTypeInfo(IMX_TypeInfo typeinfo) { myTypeInfo = typeinfo; }
115  IMX_TypeInfo typeInfo() const { return myTypeInfo; }
116 
117 
118  UT_Vector3 voxelSize() const { return myVoxelSize; }
119  UT_Vector3 origin() const { return myIndexSpace.myCenter; }
120  GA_PrimVolumeXform indexSpace() const { return myIndexSpace; }
121 
122  /// True if the two vdbs map the same indices to the same positions.
123  bool isAligned(const IMX_VDB *vdb) const
124  { return indexSpace() == vdb->indexSpace(); }
125 
126  /// Transform the vdb, this REQUIRES updating the nanovdb
127  /// structure so will run OpenCL.
128  void transform(const UT_Matrix4D& m);
129 
130  /// Sets the underlying GPU buffer to provided grid, taking
131  /// ownership of it.
132  void adoptGrid(UT_UniquePtr<CE_VDBGrid> grid,
133  cl::Buffer tilestarts,
134  exint leafcount,
135  exint lowercount,
136  exint uppercount,
137  const UT_Vector3 &voxelsize,
138  const GA_PrimVolumeXform &indexspace);
139 
140  /// If onCPU, returns a shared pointer to the cpu buffer
141  /// If onGPU, copy to CPU and return the shared pointer, keeping
142  /// GPU copy.
143  /// If dirty, return null.
144  /// Can throw CE exceptions.
145  UT_SharedPtr<CE_BufferHostByte> getCPUBufferR() const;
146 
147  /// If onCPU, ensure unique and return the raw pointer that is
148  /// our own buffer.
149  /// If onGPU, copies to the CPU and returns that, resetting onGPU to false
150  /// If dirty, return null.
151  CE_BufferHostByte *getCPUBufferRW();
152 
153  /// Returns true if this vdb's data is currently on the GPU.
154  bool isOnGPU() const
155  {
156  return myOnGPU;
157  }
158 
159  /// Returns true if this vdb's data is currently on the CPU (this is not
160  /// necessarily !isOnGPU()).
161  bool isOnCPU() const
162  {
163  return myOnCPU;
164  }
165 
166  /// True if data in this buffer may be stolen from (or changed) by the verbs
167  /// even if it's an input.
168  bool stealable() const { return myStealable; }
169 
170  /// Can be used to control what stealable() subsequently returns. If set to
171  /// true, indicates to the verbs that this buffer may be stolen from.
172  void setStealable(bool v) const { myStealable = v; }
173 
174  bool hasTopology() const; // No topology is an incomplete vdb
175  exint leafCount() const
176  { return myTopology ? myTopology->leafCount() : 0; }
177  exint lowerCount() const
178  { return myTopology ? myTopology->lowerCount() : 0; }
179  exint upperCount() const
180  { return myTopology ? myTopology->upperCount() : 0; }
181 
182  /// Build topology from provided grid. These are built onto
183  /// the GPU & CPU. This could be delayed since we share
184  /// the topology pointer so would only upload once.
185  void buildTopology(const openvdb::GridBase &grid);
186 
187  /// Build topology from our own cpu buffer.
188  void buildTopologyFromCPU(bool denseleaves);
189 
190  /// Return a gpu version
192  { if (myTopology) return myTopology->getGPUTileStarts(tilecount);
193  tilecount = 0; return {}; }
195  { if (myTopology) return myTopology->getCPUTileStarts();
196  return {}; }
197 
198  /// If we know all leaves are fully activated, we can avoid
199  /// doing activation tests per voxel. This can be set at build
200  /// time and then cleared if any topology change op occurs.
201  bool denseLeaves() const
202  { return myTopology ? myTopology->denseLeaves() : true; }
203  void setDenseLeaves(bool dense)
204  { UT_ASSERT(myTopology); if (myTopology) myTopology->setDenseLeaves(dense); }
205 
206  /// True if there are no VDB grids on GPU or CPU
207  bool isDirty() const { return !myOnGPU && !myOnCPU; }
208 
209  /// Flag all grids as dirty without freeing them.
210  void setDirty() { myOnGPU = myOnCPU = false; }
211 
212  /// Frees all buffers and marks dirty.
213  void freeBuffers();
214 
215  /// Frees all the memory
216  void destroy();
217 
218  /// True if there are any CPU or GPU buffers, they may not have
219  /// valid data - use isDirty() to see that.
220  bool allocated() const { return myCPUBuffer || myGPUBuffer; }
221 
222  int64 getMemoryUsage() const;
223  int64 getDeviceMemoryUsage() const;
224 
225  void setAttributes(const UT_OptionsHolder &attrib)
226  { myAttributes = attrib; }
228  { return myAttributes; }
229 
230  /// Updates the contents of the attributes, first making sure it is
231  /// unique. The provided operator should take a reference to
232  /// a UT_Options that it will update.
233  /// this->update([](UT_Options &opt) { opt.setOptionS("test", "bar"); });
234  template <typename OP>
235  void updateAttributes(const OP &op)
236  { myAttributes.update(op); }
237 
238  /// VDB registration to allow vdbs to be converted
239  /// to integers across HOM boundaries.
240 
241  /// Registers & returns the handle, adding the handle to the registered
242  /// list
243  static int registerVDB(IMX_VDBConstPtr vdb, UT_IntArray &registered);
244  /// Unregister all vdbs corresponding to the provided list,
245  /// erase the list afterwards. Assertion if handle wasn't regsitered
246  static void unregisterVDBs(UT_IntArray &registered);
247  /// Look up a registered vdb by handle.
248  static IMX_VDBConstPtr lookupVDB(int handle);
249 
250  class Topology
251  {
252  public:
253  Topology() = default;
254  Topology(cl::Buffer tilestarts,
255  exint leafcount, exint lowercount, exint uppercount)
256  {
257  myGPUTileStarts = tilestarts;
258  myGPUTileStartsCount = leafcount;
259  myLeafCount = leafcount;
260  myLowerCount = lowercount;
261  myUpperCount = uppercount;
262  }
263  Topology(const openvdb::GridBase &grid);
264  Topology(const CE_BufferHostByte *cpugrid);
265  ~Topology();
266 
267  /// Return a gpu version
268  cl::Buffer getGPUTileStarts(exint &tilecount) const;
269  UT_SharedPtr<UT_Array<UT_Vector3i>> getCPUTileStarts() const;;
270 
271  void setDenseLeaves(bool isdense) { myDenseLeaves = isdense; }
272  bool denseLeaves() const { return myDenseLeaves; }
273 
274  exint leafCount() const { return myLeafCount; }
275  exint lowerCount() const { return myLowerCount; }
276  exint upperCount() const { return myUpperCount; }
277 
278  int64 getMemoryUsage() const;
279  int64 getDeviceMemoryUsage() const;
280 
281  protected:
283  /// Tile starts is a shared buffer, so isn't re-written to
285  exint myGPUTileStartsCount = -1;
286 
287  /// Required to rebuild:
288  exint myLeafCount = 0;
289  exint myLowerCount = 0;
290  exint myUpperCount = 0;
291 
292  // True if all the leaves are dense.
293  bool myDenseLeaves = false;
294  };
295 
296 protected:
297  /// These implement methods required by the pool.
298  /// Resets the GPU Buffer pointer.
299  void poolResetGPUBuffer() override
300  {
301  myGPUBuffer.reset();
302  }
303  /// Update OnGPU
304  void poolSetOnGPU(bool ongpu) override
305  {
306  myOnGPU = ongpu;
307  }
308  /// True if the gpu buffer is null.
309  bool poolIsGPUBufferEmpty() const override
310  {
311  return myGPUBuffer.get() == nullptr;
312  }
313  /// True if the gpu buffer is not null and valid.
314  bool poolIsGPUBufferValid() const override
315  {
316  return myGPUBuffer.get() && myGPUBuffer->isValid();
317  }
318  /// True if the swap does something
319  bool poolSwapGPUBuffer(IMX_PoolEntry *otherbase) override
320  {
321  IMX_VDB *other = UTverify_cast<IMX_VDB *>(otherbase);
322 
323  if (myGPUBuffer == other->myGPUBuffer)
324  return false;
325 
326  myGPUBuffer.swap(other->myGPUBuffer);
327  return true;
328  }
329  /// Shallow copy
330  void poolShallowCopyGPUBuffer(const IMX_PoolEntry *srcbase) override
331  {
332  const IMX_VDB *src = UTverify_cast<const IMX_VDB *>(srcbase);
333 
334  myGPUBuffer = src->myGPUBuffer;
335  }
336  /// Queues up commands that transfer this buffer's GPU storage to main
337  /// memory.
338  void unloadFromGPU() override;
339 
340  UT_SharedPtr<CE_BufferHostByte> getCPUBufferRInternal();
341 
343 
344  /// Tracks the leaf starts & node counts. Stores GPU and CPU
345  /// versions of these.
347 
348  /// Because the nanovdb buffers are somewhat opaque, we store
349  /// some meta data locally.
352 
353  /// All changes to this member (the shared pointer) must be done by the
354  /// memory pool!!!
356 
359 
360  /// The type of the grid so we can avoid unpacking it to find out.
361  /// Note this is ALSO on the CE_VDBGrid, but that might not exist
362  /// for CPU buffers so it is duplicated here.
363  UT_VDBType myStorageType = UT_VDB_INVALID;
364 
365  /// This pair of flags hold the state of data that lives in the two storage
366  /// spots.
367  bool myOnCPU = false;
368  bool myOnGPU = false;
369 
370  /// Can data of this buffer be stolen by the verbs? TODO: who should reset
371  /// this and when?
372  mutable bool myStealable = true;
373 
374  friend IMX_API size_t format(char *buffer, size_t buffer_size, const IMX_VDB &v);
375 };
376 
378 
379 IMX_API size_t format(char *buffer, size_t buffer_size, const IMX_VDB &v);
380 
381 #endif
382 
383 
bool poolIsGPUBufferEmpty() const override
True if the gpu buffer is null.
Definition: IMX_VDB.h:309
void setDenseLeaves(bool dense)
Definition: IMX_VDB.h:203
void setAttributes(const UT_OptionsHolder &attrib)
Definition: IMX_VDB.h:225
UT_SharedPtr< Topology > myTopology
Definition: IMX_VDB.h:346
UT_OptionsHolder attributes() const
Definition: IMX_VDB.h:227
void setDenseLeaves(bool isdense)
Definition: IMX_VDB.h:271
void cpuCopyFromVDB(const openvdb::GridBase &vdb, const UT_Vector3 &voxelsize, const GA_PrimVolumeXform &indexspace)
Definition: IMX_VDB.h:82
void poolResetGPUBuffer() override
Definition: IMX_VDB.h:299
GA_PrimVolumeXform indexSpace() const
Definition: IMX_VDB.h:120
getFileOption("OpenEXR:storage") storage
Definition: HDK_Image.dox:276
bool isDirty() const
True if there are no VDB grids on GPU or CPU.
Definition: IMX_VDB.h:207
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
const GLdouble * v
Definition: glcorearb.h:837
Definition: IMX_PoolEntry.h:23
void gpuCopyFromVDB(const openvdb::GridBase &vdb, const UT_Vector3 &voxelsize, const GA_PrimVolumeXform &indexspace)
Definition: IMX_VDB.h:86
UT_SharedPtr< CE_BufferHostByte > myCPUBuffer
Definition: IMX_VDB.h:342
exint leafCount() const
Definition: IMX_VDB.h:274
IMX_VDB & operator=(IMX_VDB &&other)
Definition: IMX_VDB.h:54
IMX_TypeInfo
Definition: IMX_Types.h:34
Topology(cl::Buffer tilestarts, exint leafcount, exint lowercount, exint uppercount)
Definition: IMX_VDB.h:254
int64 exint
Definition: SYS_Types.h:125
bool poolIsGPUBufferValid() const override
True if the gpu buffer is not null and valid.
Definition: IMX_VDB.h:314
void swap(T &lhs, T &rhs)
Definition: pugixml.cpp:7440
EntryType
To avoid the need for dynamic casts:
Definition: IMX_PoolEntry.h:27
JSON reader class which handles parsing of JSON or bJSON files.
Definition: UT_JSONParser.h:87
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:37
bool denseLeaves() const
Definition: IMX_VDB.h:272
SYS_FORCE_INLINE TO_T UTverify_cast(FROM_T from)
Definition: UT_Assert.h:229
UT_VDBType
Definition: UT_VDBUtils.h:25
bool isOnGPU() const
Returns true if this vdb's data is currently on the GPU.
Definition: IMX_VDB.h:154
bool stealable() const
Definition: IMX_VDB.h:168
GLuint buffer
Definition: glcorearb.h:660
UT_OptionsHolder myAttributes
Definition: IMX_VDB.h:357
IMX_TypeInfo typeInfo() const
Definition: IMX_VDB.h:115
UT_SharedPtr< CE_VDBGrid > myGPUBuffer
Definition: IMX_VDB.h:355
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
void setStealable(bool v) const
Definition: IMX_VDB.h:172
exint upperCount() const
Definition: IMX_VDB.h:276
void poolSetOnGPU(bool ongpu) override
Update OnGPU.
Definition: IMX_VDB.h:304
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
Definition: UT_SharedPtr.h:36
UT_VDBType storageType() const
Definition: IMX_VDB.h:110
IMX_VDB(IMX_VDB &&other) noexcept
Definition: IMX_VDB.h:43
UT_SharedPtr< const IMX_VDB > IMX_VDBConstPtr
Definition: IMX_VDB.h:34
IMX_VDB(const IMX_VDB &other)
Definition: IMX_VDB.h:42
UT_SharedPtr< UT_Array< UT_Vector3i > > myCPUTileStarts
Definition: IMX_VDB.h:282
virtual void unloadFromGPU()=0
long long int64
Definition: SYS_Types.h:116
exint leafCount() const
Definition: IMX_VDB.h:175
IMX_VDB & operator=(const IMX_VDB &other)
Definition: IMX_VDB.h:51
GA_API const UT_StringHolder transform
GA_PrimVolumeXform myIndexSpace
Definition: IMX_VDB.h:351
exint upperCount() const
Definition: IMX_VDB.h:179
UT_Vector3 origin() const
Definition: IMX_VDB.h:119
A map of string to various well defined value types.
Definition: UT_Options.h:84
EntryType poolTypeID() const override
Definition: IMX_VDB.h:47
bool isOnCPU() const
Definition: IMX_VDB.h:161
void setDirty()
Flag all grids as dirty without freeing them.
Definition: IMX_VDB.h:210
exint lowerCount() const
Definition: IMX_VDB.h:275
UT_Vector3 myVoxelSize
Definition: IMX_VDB.h:350
void poolShallowCopyGPUBuffer(const IMX_PoolEntry *srcbase) override
Shallow copy.
Definition: IMX_VDB.h:330
Memory buffer interface.
Definition: cl.hpp:1867
cl::Buffer getGPUTileStarts(exint &tilecount) const
Return a gpu version.
Definition: IMX_VDB.h:191
#define IMX_API
Definition: IMX_API.h:8
cl::Buffer myGPUTileStarts
Tile starts is a shared buffer, so isn't re-written to.
Definition: IMX_VDB.h:284
bool denseLeaves() const
Definition: IMX_VDB.h:201
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
CE_VDBGrid * getGPUBufferW()
Definition: IMX_VDB.h:108
bool poolSwapGPUBuffer(IMX_PoolEntry *otherbase) override
True if the swap does something.
Definition: IMX_VDB.h:319
IMX_API size_t format(char *buffer, size_t buffer_size, const IMX_VDB &v)
UT_SharedPtr< IMX_VDB > IMX_VDBPtr
Definition: IMX_VDB.h:33
void updateAttributes(const OP &op)
Definition: IMX_VDB.h:235
bool isAligned(const IMX_VDB *vdb) const
True if the two vdbs map the same indices to the same positions.
Definition: IMX_VDB.h:123
UT_SharedPtr< UT_Array< UT_Vector3i > > getCPUTileStarts() const
Definition: IMX_VDB.h:194
bool allocated() const
Definition: IMX_VDB.h:220
void setTypeInfo(IMX_TypeInfo typeinfo)
Definition: IMX_VDB.h:114
void swap(IMX_VDB &other)
UT_Vector3 voxelSize() const
Definition: IMX_VDB.h:118
exint lowerCount() const
Definition: IMX_VDB.h:177
GLenum src
Definition: glcorearb.h:1793