HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GA_CEAttribute.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: GA_CEAttribute.h ( GA Library, C++)
7  *
8  * COMMENTS:
9  * A GA_Attribute backed on the Compute Engine
10  */
11 
12 #ifndef __GA_CEAttribute__
13 #define __GA_CEAttribute__
14 
15 #include "GA_API.h"
16 
17 #include <CE/CE_Context.h>
18 #include <CE/CE_BufferDevice.h>
19 #include <CE/CE_HotSwapPoolEntry.h>
20 #include "GA_Detail.h"
21 #include "GA_Attribute.h"
22 #include <UT/UT_WorkBuffer.h>
23 
24 class GA_CEAttribute;
28 
31 
33 {
34 public:
36 
37  /// Create an attribute from existing buffers.
39  GA_Size tuplesize, bool isarray,
40  cl::Buffer buffer, cl::Buffer indexbuffer,
41  bool leave_on_gpu = false);
42 
43  /// Construct unallocated array of this size and type
44  GA_CEAttribute(GA_Size entries, GA_StorageClass storage, GA_Precision precision,
45  GA_Size tuplesize, bool isarray);
46 
47  GA_CEAttribute(const GA_CEAttribute &other) { copy(other); }
48  GA_CEAttribute(GA_CEAttribute && other) noexcept { swap(other); }
49 
50  virtual ~GA_CEAttribute() override;
51 
52  EntryType poolTypeID() const override { return EntryType::ATTRIBUTE; }
53 
54  void copy(const GA_CEAttribute &other);
55  GA_CEAttribute &operator=(const GA_CEAttribute &other) { copy(other); return *this; }
56 
57  void swap(GA_CEAttribute &other);
58  GA_CEAttribute &operator=(GA_CEAttribute &&other) { swap(other); return *this; }
59 
60  /// Returns true for successful save.
61  bool saveJSON(UT_JSONWriter &w) const;
62  bool rawData(UT_WorkBuffer &data) const;
63  bool setRawData(const char *data, exint length);
64 
65  /// Returns a newly created VDB loaded from the stream, or null
66  /// if load failure.
67  static GA_CEAttributeUPtr loadJSON(UT_JSONParser &p);
68 
69  void clearBuffers();
70 
71  bool isValid() const
72  {
73  // Valid if we have cpu or gpu buffer.
74  return isOnGPU() || isOnCPU();
75  }
76 
77  bool isOnGPU() const
78  { return myOnGPU; }
79  bool isOnCPU() const
80  { return myOnCPU; }
81 
82  /// Ensures the CPU version of the attribute is valid.
83  void copyToCPU()
84  { unloadFromGPU(); }
85 
86  int64 getDeviceMemoryUsage() const;
87  int64 getMemoryUsage(bool inclusive=false) const;
88 
89  /// Acquire accessors to the GPU data. Extend the liftetime of
90  /// these until any kernels they are bound to are dispatched.
91  /// These handle pinning the GPU buffer from eviction from the
92  /// hot swap pool, and also extending the cl::Buffer lifetime.
93  /// You must test to see if these are null. If they are non-null,
94  /// they will be isValid().
95  static GA_CEAttributeAccessorPtr makeAccessor(GA_CEAttributePtr attrib, bool read, bool write);
96  static GA_CEAttributeAccessorPtr makeAccessorR(GA_CEAttributeConstPtr attrib) { return makeAccessor(UTconst_pointer_cast<GA_CEAttribute>(attrib), true, false); }
97  static GA_CEAttributeAccessorPtr makeAccessorRW(GA_CEAttributePtr attrib) { return makeAccessor(attrib, true, true); }
98  static GA_CEAttributeAccessorPtr makeAccessorW(GA_CEAttributePtr attrib) { return makeAccessor(attrib, false, true); }
99 
100  GA_Size entries() const { return myEntries; }
101  int tupleSize() const { return myTupleSize; }
102  GA_StorageClass storage() const { return myStorage; }
103  GA_Precision precision() const { return myPrecision; }
104  bool isArray() const { return myIsArray; }
105 
106  ///
107  /// attributeToOCL populates our own data from the attribute.
108  /// It will be loaded onto the GPU.
109  /// If it fails, returns false.
110  ///
111  bool attributeToOCL(const GA_Detail *gdp,
112  GA_AttributeOwner owner,
113  const char *aname,
114  GA_StorageClass storage,
115  int &tuplesize,
116  bool isarray,
117  bool docopy = true)
118  {
119  return attributeToOCL(gdp, owner, aname, storage, GA_PRECISION_32,
120  tuplesize, isarray, docopy);
121  }
122  bool attributeToOCL(const GA_Detail *gdp,
123  GA_AttributeOwner owner,
124  const char *aname,
125  GA_StorageClass storage,
126  GA_Precision precision,
127  int &tuplesize,
128  bool isarray,
129  bool docopy = true)
130  {
131  if (!gdp) return false;
132  if (!UTisstring(aname))
133  return false;
134  const GA_Attribute *attrib = gdp->getAttributes().findAttribute(owner, aname);
135  if (!attrib)
136  return false;
137  return attributeToOCL(attrib, storage, precision, tuplesize, isarray, docopy);
138  }
139  bool attributeToOCL(const GA_Attribute *attrib,
140  GA_StorageClass storage,
141  GA_Precision precision,
142  int &tuplesize,
143  bool isarray,
144  bool docopy = true);
145 
146  ///
147  /// The int*ToOCL copy integer data into our own data.
148  /// It will beloaded onto the GPU.
149  /// If it fails, returns false.
150  ///
151  bool intToOCL(const UT_Array<int64> &data,
152  GA_StorageClass storage,
153  GA_Precision precision,
154  bool docopy = true);
155 
156  bool intArrayToOCL(const UT_Array<UT_Array<int64>> &data,
157  GA_StorageClass storage,
158  GA_Precision precision,
159  bool docopy = true);
160 
161  bool packedIntArrayToOCL(
163  GA_StorageClass storage,
164  GA_Precision precision,
165  bool docopy = true);
166 
167  ///
168  /// oclToAttribute writes back our data to the specified attribute.
169  /// If it is not compatible, returns false.
170  ///
171  bool oclToAttribute(GA_Detail *gdp, GA_AttributeOwner owner, const char *aname)
172  {
173  if (!gdp) return false;
174  if (!UTisstring(aname))
175  return false;
176  GA_Attribute *attrib = gdp->getAttributes().findAttribute(owner, aname);
177  if (!attrib)
178  return false;
179  return oclToAttribute(attrib);
180  }
181  bool oclToAttribute(GA_Attribute *attrib);
182 
183  bool isWriteBackRequired() const { return myWriteBackRequired; }
184  void setWriteBackRequired(bool isrequired) { myWriteBackRequired = isrequired; }
185 
186 protected:
187  /// bufferRW() will ensure COW is respected and create a new GPU
188  /// buffer if this was shared. It also resets the OnCPU flag as
189  /// it is assumed the data will be written to.
190  /// bufferW() ensures the GPU buffer is unique, but does not copy
191  /// the data when doing so.
192  /// bufferR() will return a shared buffer without uniquing. Caution
193  /// should be taken to ensure you don't get both a read & write buffer,
194  /// as your read buffer may be then orphaned (If you hold onto the
195  /// cl::Buffer object it is safe other than out of date data. NOTE:
196  /// binding to a kernel does NOT preserve the cl::Buffer object)
197  cl::Buffer bufferW() { return buffer(false, true); }
198  cl::Buffer bufferRW() { return buffer(true, true); }
199  cl::Buffer bufferR() const { return SYSconst_cast(this)->buffer(true, false); }
200  cl::Buffer buffer(bool read, bool write);
201 
202  /// Index buffer is immutable, so no writable variant:
203  cl::Buffer indexBufferR() const { return myIndexBuffer ? myIndexBuffer->buffer() : cl::Buffer(); }
204 
205  /// These implement methods required by the pool.
206  /// Resets the GPU Buffer pointer.
207  void poolResetGPUBuffer() override
208  {
209  myBuffer.reset();
210  }
211  /// Update OnGPU
212  void poolSetOnGPU(bool ongpu) override
213  {
214  myOnGPU = ongpu;
215  }
216  /// True if the gpu buffer is null.
217  bool poolIsGPUBufferEmpty() const override
218  {
219  return myBuffer.get() == nullptr;
220  }
221  /// True if the gpu buffer is not null and valid.
222  bool poolIsGPUBufferValid() const override
223  {
224  return myBuffer.get() && !myBuffer->isEmpty();
225  }
226  /// True if the swap does something
227  bool poolSwapGPUBuffer(CE_HotSwapPoolEntry *otherbase) override
228  {
229  GA_CEAttribute *other = UTverify_cast<GA_CEAttribute *>(otherbase);
230 
231  if (myBuffer == other->myBuffer)
232  return false;
233 
234  myBuffer.swap(other->myBuffer);
235  return true;
236  }
237  /// Shallow copy
238  void poolShallowCopyGPUBuffer(const CE_HotSwapPoolEntry *srcbase) override
239  {
240  const GA_CEAttribute *src = UTverify_cast<const GA_CEAttribute *>(srcbase);
241 
242  myBuffer = src->myBuffer;
243  }
244  /// Queues up commands that transfer this buffer's GPU storage to main
245  /// memory.
246  void unloadFromGPU() override;
247 
248 protected:
249 
250  // Utility to trigger a callback on the correct data array type.
251  template <typename OP>
252  void dispatchToArray(const OP &op)
253  {
254  switch (myStorage)
255  {
256  case GA_STORECLASS_FLOAT:
257  switch (myPrecision)
258  {
259  case GA_PRECISION_16: op(myFloat16Array); break;
260  case GA_PRECISION_32: op(myFloat32Array); break;
261  case GA_PRECISION_64: op(myFloat64Array); break;
262  default: break;
263  }
264  break;
265  case GA_STORECLASS_INT:
266  switch (myPrecision)
267  {
268  case GA_PRECISION_1: op(myInt8Array); break;
269  case GA_PRECISION_8: op(myInt8Array); break;
270  case GA_PRECISION_16: op(myInt16Array); break;
271  case GA_PRECISION_32: op(myInt32Array); break;
272  case GA_PRECISION_64: op(myInt64Array); break;
273  default: break;
274  }
275  break;
276  default:
277  break;
278  }
279  }
280  template <typename OP>
281  void dispatchToArray(const OP &op) const
282  {
283  switch (myStorage)
284  {
285  case GA_STORECLASS_FLOAT:
286  switch (myPrecision)
287  {
288  case GA_PRECISION_16: op(myFloat16Array); break;
289  case GA_PRECISION_32: op(myFloat32Array); break;
290  case GA_PRECISION_64: op(myFloat64Array); break;
291  default: break;
292  }
293  break;
294  case GA_STORECLASS_INT:
295  switch (myPrecision)
296  {
297  case GA_PRECISION_1: op(myInt8Array); break;
298  case GA_PRECISION_8: op(myInt8Array); break;
299  case GA_PRECISION_16: op(myInt16Array); break;
300  case GA_PRECISION_32: op(myInt32Array); break;
301  case GA_PRECISION_64: op(myInt64Array); break;
302  default: break;
303  }
304  break;
305  default:
306  break;
307  }
308  }
309 
310  /// Transfers this CPU data onto the GPU. Will set myOnGPu true
311  /// on success, if docopy is false we only allocate the gpu buffer.
312  void loadToGPU(bool docopy);
313 
314  // GPU Buffers:
315  /// All changes to this member (the shared pointer) must be done by the
316  /// memory pool!!!
318  // Currently not part of pool?
320 
321  // CPU Buffers:
322  // Note that index arrays are considered to be immutable, so always
323  // are on the CPU.
325  // It would be much more proper to use cl_half here, but that
326  // is not a computable type so it is easy to accidentally cast
327  // fprealy16 to short silently. Instead we rely on bit equivalency.
335 
336  // Number of entries.
337  GA_Size myEntries = 0;
338  GA_Size myDataEntries = 0;
339  GA_Size myTupleSize = 0;
342  bool myIsArray = false;
343 
344  // GA_CEAttributes are (usually) a clone of some GA_Attribute.
345  // It is important to track where the authorative information lies.
346  // If the GA_CEAttribute is written to, the GA_Attribute is out of date.
347  // If the GA_Attribute is written to, it is expected for the
348  // GA_CEAttribute to be cleared. (This is why naive algorithms should
349  // flush all ce buffers)
350 
351  // The WriteBackRequired flag marks that the GA_Atttribute is out of
352  // date.
353  // The OnGPU and OnCPU track where the GA_CEAttribute currently lives.
354  // So it is possible for the GA_CEAttribute data itself to be only on the
355  // CPU, but out of date on the GA_Attribute.
356 
357  /// This pair stores whether correct data is on the CPU or GPU buffers
358  /// or both.
359  bool myOnCPU = false;
360  bool myOnGPU = false;
361 
362  /// Whether the buffer has been written to by CE. This implies
363  /// GA_Attribute is out of date.
364  bool myWriteBackRequired = false;
365 
367 };
368 
370 {
371 public:
372  GA_CEAttributeAccessor() = default; // Invalid reader.
373  GA_CEAttributeAccessor(GA_CEAttributePtr ceattrib, bool read, bool write);
375 
376  /// These should exist, along with move constructors, but do require
377  /// work to ensure the gpuinuse flag is handled.
380 
381  cl::Buffer bufferR() const { return buffer(true, false); }
382  cl::Buffer indexBufferR() const { return myIndexBuffer; }
383  cl::Buffer bufferW() const { return buffer(false, true); }
384  cl::Buffer bufferRW() const { return buffer(true, true); }
385  cl::Buffer buffer(bool read, bool write) const;
386 
387  bool isValid() const
388  {
389  if (!myCEAttrib) return false;
390  if (!myBuffer()) return false;
391  return true;
392  }
393  bool isInvalid() const { return !isValid(); }
394 
395  GA_Size entries() const { return myCEAttrib ? myCEAttrib->entries() : 0; }
396  int tupleSize() const { return myCEAttrib ? myCEAttrib->tupleSize() : 0; }
397  GA_StorageClass storage() const { return myCEAttrib ? myCEAttrib->storage() : GA_STORECLASS_INVALID; }
398  GA_Precision precision() const { return myCEAttrib ? myCEAttrib->precision() : GA_PRECISION_INVALID; }
399  bool isArray() const { return myCEAttrib ? myCEAttrib->isArray() : false; }
400 
401 protected:
402  /// We extend lifetime of our attribute that we have our
403  /// in-use flag for.
405 
406 
407  /// Whether we have been acquired for read or write, this is
408  /// used to allow run-time validation of our requirments.
409  bool myRead = false;
410  bool myWrite = false;
411 
412  /// We explcitly extend the cl::Buffer lifetimes as this
413  /// must be done until the kernel is executed, so this allows
414  /// one to only extend one thing.
416 };
417 
418 #endif
int tupleSize() const
UT_SharedPtr< GA_CEAttribute > GA_CEAttributePtr
Definition: GA_Attribute.h:56
bool isOnCPU() const
bool attributeToOCL(const GA_Detail *gdp, GA_AttributeOwner owner, const char *aname, GA_StorageClass storage, int &tuplesize, bool isarray, bool docopy=true)
Definition of a geometry attribute.
Definition: GA_Attribute.h:203
void copyToCPU()
Ensures the CPU version of the attribute is valid.
bool isOnGPU() const
UT_SharedPtr< UT_Array< cl_long > > myInt64Array
GA_StorageClass
Definition: GA_Types.h:75
UT_SharedPtr< UT_Array< cl_int > > myInt32Array
void poolShallowCopyGPUBuffer(const CE_HotSwapPoolEntry *srcbase) override
Shallow copy.
getFileOption("OpenEXR:storage") storage
Definition: HDK_Image.dox:276
bool poolSwapGPUBuffer(CE_HotSwapPoolEntry *otherbase) override
True if the swap does something.
GA_Precision
Definition: GA_Types.h:91
SYS_FORCE_INLINE T * SYSconst_cast(const T *foo)
Definition: SYS_Types.h:136
bool attributeToOCL(const GA_Detail *gdp, GA_AttributeOwner owner, const char *aname, GA_StorageClass storage, GA_Precision precision, int &tuplesize, bool isarray, bool docopy=true)
UT_SharedPtr< UT_Array< fpreal16 > > myFloat16Array
int64 exint
Definition: SYS_Types.h:125
UT_SharedPtr< UT_Array< cl_char > > myInt8Array
static GA_CEAttributeAccessorPtr makeAccessorR(GA_CEAttributeConstPtr attrib)
cl::Buffer bufferR() const
GA_Precision precision() const
void swap(T &lhs, T &rhs)
Definition: pugixml.cpp:7440
EntryType poolTypeID() const override
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:795
cl::Buffer bufferR() const
JSON reader class which handles parsing of JSON or bJSON files.
Definition: UT_JSONParser.h:87
#define GA_API
Definition: GA_API.h:14
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:39
SYS_FORCE_INLINE TO_T UTverify_cast(FROM_T from)
Definition: UT_Assert.h:242
UT_SharedPtr< CE_BufferDeviceByte > myIndexBuffer
GLuint buffer
Definition: glcorearb.h:660
UT_UniquePtr< GA_CEAttribute > GA_CEAttributeUPtr
exint GA_Size
Defines the bit width for index and offset types in GA.
Definition: GA_Types.h:243
cl::Buffer indexBufferR() const
GA_CEAttribute(const GA_CEAttribute &other)
GA_CEAttribute & operator=(GA_CEAttribute &&other)
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
GA_StorageClass storage() const
static GA_CEAttributeAccessorPtr makeAccessorW(GA_CEAttributePtr attrib)
GA_CEAttribute & operator=(const GA_CEAttribute &other)
bool poolIsGPUBufferValid() const override
True if the gpu buffer is not null and valid.
cl::Buffer bufferW()
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
Definition: UT_SharedPtr.h:36
bool isWriteBackRequired() const
UT_SharedPtr< UT_Array< cl_int > > myIndexArray
GA_CEAttribute(GA_CEAttribute &&other) noexcept
GA_CEAttributePtr myCEAttrib
UT_SharedPtr< const GA_CEAttribute > GA_CEAttributeConstPtr
Definition: GA_Attribute.h:57
cl::Buffer bufferW() const
GA_AttributeSet & getAttributes()
Definition: GA_Detail.h:808
bool isArray() const
EntryType
To avoid the need for dynamic casts:
bool isValid() const
long long int64
Definition: SYS_Types.h:116
UT_SharedPtr< UT_Array< cl_float > > myFloat32Array
GA_Size entries() const
bool poolIsGPUBufferEmpty() const override
True if the gpu buffer is null.
GA_StorageClass storage() const
void swap(GA_CEAttribute &other)
UT_SharedPtr< GA_CEAttributeAccessor > GA_CEAttributeAccessorPtr
Definition: GA_Attribute.h:59
GLenum GLint GLint * precision
Definition: glcorearb.h:1925
void dispatchToArray(const OP &op)
GA_AttributeOwner
Definition: GA_Types.h:35
GA_Precision precision() const
void poolSetOnGPU(bool ongpu) override
Update OnGPU.
cl::Buffer indexBufferR() const
Index buffer is immutable, so no writable variant:
LeafData & operator=(const LeafData &)=delete
void poolResetGPUBuffer() override
SYS_FORCE_INLINE bool UTisstring(const char *s)
UT_SharedPtr< CE_BufferDeviceByte > myBuffer
GA_Size entries() const
Memory buffer interface.
Definition: cl.hpp:1867
UT_SharedPtr< UT_Array< cl_double > > myFloat64Array
cl::Buffer bufferRW()
Container class for all geometry.
Definition: GA_Detail.h:105
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
bool oclToAttribute(GA_Detail *gdp, GA_AttributeOwner owner, const char *aname)
cl::Buffer bufferRW() const
UT_SharedPtr< UT_Array< cl_short > > myInt16Array
SYS_FORCE_INLINE const GA_Attribute * findAttribute(GA_AttributeScope scope, const UT_StringRef &name, const GA_AttributeOwner search_order[], int search_order_size) const
static GA_CEAttributeAccessorPtr makeAccessorRW(GA_CEAttributePtr attrib)
void dispatchToArray(const OP &op) const
virtual void unloadFromGPU()=0
Definition: format.h:1821
GLenum src
Definition: glcorearb.h:1793
void setWriteBackRequired(bool isrequired)