HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GA_Attribute.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_Attribute.h ( GA Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #pragma once
12 
13 #ifndef __GA_Attribute__
14 #define __GA_Attribute__
15 
16 #include "GA_API.h"
17 #include "GA_AttributeProxy.h"
18 #include "GA_AttributeType.h"
19 #include "GA_IndexMap.h"
20 #include "GA_Types.h"
21 
22 #include <UT/UT_Assert.h>
23 #include <UT/UT_StringHolder.h>
24 #include <UT/UT_UniquePtr.h>
25 
26 #include <SYS/SYS_StaticAssert.h>
27 #include <SYS/SYS_Inline.h>
28 #include <SYS/SYS_Types.h>
29 
30 #include <string>
31 #include <string.h>
32 
33 class GA_AIFBlindData;
34 class GA_AIFBlob;
35 class GA_AIFBlobArray;
36 class GA_AIFCompare;
37 class GA_AIFCopyData;
38 class GA_AIFDelta;
39 class GA_AIFEdit;
40 class GA_AIFIndexPair;
41 class GA_AIFInterp;
42 class GA_AIFJSON;
43 class GA_AIFMath;
44 class GA_AIFMerge;
45 class GA_AIFNumericArray;
50 class GA_AIFStat;
51 class GA_AIFStringTuple;
52 class GA_AIFTuple;
53 class GA_Attribute;
54 class GA_CEAttribute;
55 class GA_Defragment;
56 class GA_Detail;
57 class GA_IndexMap;
58 class GA_Range;
59 class GA_MergeMap;
60 
61 class UT_JSONParser;
62 class UT_JSONWriter;
63 class UT_MemoryCounter;
64 class UT_OptionEntry;
65 class UT_Options;
66 class UT_String;
67 class UT_WorkBuffer;
68 
70 {
71 public:
74 
76 
77  GA_AttributeOptions &operator=(const GA_AttributeOptions &src);
78 
79  /// Reset to default.
80  void clear();
81 
82  /// Constructs a full UT_Options that includes all symbols that
83  /// are otherwise handled with member variables.
84  void buildFullOptions(UT_Options &fulloptions) const;
85 
86  /// Removes from our myOptions list any options that aren't custom
87  /// and assigns them to local variables. May then delete myOptions
88  /// if it is empty.
89  void extractBuiltinOptions();
90 
91  /// If no custom options are present, create it.
92  UT_Options &createOptions();
93 
94  /// Merges option list on top of our own
95  void mergeOptions(const GA_AttributeOptions &src);
96 
97  /// @{
98  /// Accessors
99  GA_TypeInfo typeInfo() const { return myTypeInfo; }
100  void setTypeInfo(GA_TypeInfo t) { myTypeInfo = t; }
101  bool isNonTransforming() const { return myIsNonTransforming; }
102  void setIsNonTransforming(bool v) { myIsNonTransforming = v; }
103  bool exportToInfoBlock() const { return myExportToInfoBlock; }
104  void setExportToInfoBlock(bool v) { myExportToInfoBlock = v; }
105  bool leaveOnGPU() const { return myLeaveOnGPU; }
106  void setLeaveOnGPU(bool v) { myLeaveOnGPU = v; }
107  /// @}
108 
109  /// Check whether the exportOnMerge() flag has been set, or whether it's at
110  /// its default.
111  bool exportOnMergeSet() const { return myExportOnMergeValid; }
112  /// Check to see whether the export on merge is enabled. If the flag
113  /// hasn't been set, the default value will be used.
114  bool exportOnMerge(bool defval=false) const
115  { return myExportOnMergeValid ? myExportOnMerge : defval; }
116  /// Set the export on merge flag
117  void setExportOnMerge(bool v)
118  {
119  myExportOnMergeValid = true;
120  myExportOnMerge = v;
121  }
122 
123  /// Check whether the exportOnSave() flag has been set, or whether it's at
124  /// its default.
125  bool exportOnSaveSet() const { return myExportOnSaveValid; }
126  /// Check to see whether the export on save is enabled. If the flag
127  /// hasn't been set, the default value will be used.
128  bool exportOnSave(bool defval=false) const
129  { return myExportOnSaveValid ? myExportOnSave : defval; }
130  /// Set the export on save flag
131  void setExportOnSave(bool v)
132  {
133  myExportOnSaveValid = true;
134  myExportOnSave = v;
135  }
136 
137  /// Check to see whether the attribute is a "string set". If the flag
138  /// hasn't been set, the default value will be used.
139  bool isStringSet(bool defval=false) const
140  { return myIsStringSetValid ? myIsStringSet : defval; }
141  /// Set the "string set" flag
142  void setIsStringSet(bool v)
143  {
144  myIsStringSetValid = true;
145  myIsStringSet = v;
146  }
147 
148  /// @{
149  /// Access to options
150  const UT_Options *options() const { return myOptions; }
151  void setOptions(const UT_Options &o);
152  void mergeOptions(const UT_Options &o);
153  void mergeOptions(const UT_Options &o,
154  bool (*match)(const UT_StringHolder &name,
155  const UT_OptionEntry *, void *),
156  void *data);
157  void clearOptions();
158  bool removeOption(const char *name);
159  /// @}
160 
161 private:
162  // Our custom options.
163  UT_Options *myOptions;
164 
165  GA_TypeInfo myTypeInfo;
166 
167  bool myIsNonTransforming : 1;
168  bool myExportOnMergeValid : 1, myExportOnMerge : 1;
169  bool myExportOnSaveValid : 1, myExportOnSave : 1;
170 
171  bool myIsStringSetValid : 1, myIsStringSet : 1;
172 
173  bool myExportToInfoBlock : 1;
174  bool myLeaveOnGPU : 1;
175 
176  bool myDetached : 1;
177 
178  friend class GA_Attribute;
179 };
180 
181 template<typename T>
182 static inline const T *GAgetAIF(const GA_Attribute &attrib)
183 {
185  return NULL;
186 }
187 
188 
189 /// @brief Definition of a geometry attribute
190 ///
191 /// An attribute can be attached to points, vertices, primitives or the detail
192 /// itself. The attribute is responsible for maintaining the data array.
193 ///
194 /// @see @ref Iterators for implications of paged allocation strategies.
195 ///
196 /// The attribute is responsible for providing interfaces (@ref AIF).
197 ///
199 {
200 public:
201  GA_Attribute(
202  const GA_AttributeType &type, const GA_IndexMap &index_map,
203  GA_AttributeScope scope, const UT_StringHolder &name);
204  virtual ~GA_Attribute();
205 
206  SYS_FORCE_INLINE const GA_AttributeType &getType() const { return myType; }
207  SYS_FORCE_INLINE const GA_IndexMap &getIndexMap() const { return myIndexMap; }
208  SYS_FORCE_INLINE const GA_Detail &getDetail() const { return myIndexMap.getDetail(); }
209  SYS_FORCE_INLINE GA_Detail &getDetail() { return myIndexMap.getDetail(); }
210  SYS_FORCE_INLINE GA_AttributeOwner getOwner() const { return myIndexMap.getOwner(); }
211 
212  SYS_FORCE_INLINE GA_AttributeScope getScope() const { return myScope; }
213  SYS_FORCE_INLINE bool isGroup() const { return myScope == GA_SCOPE_GROUP; }
214 
215  /// @{
216  /// Obtains the proxy representative used as a reference holder to this
217  /// attribute. This proxy gets invalidated when the attribute gets deleted.
218  /// Invalidation clears the proxy's pointer to NULL, but the proxy's memory
219  /// stays valid, unlike the memory of the attribute object.
221  { return GA_AttributeProxyHandle(myProxy); }
223  { return GA_ConstAttributeProxyHandle(myProxy); }
224  /// @}
225 
226  /// @{
227  /// Attribute flags store certain mutable properties of the attribute,
228  /// largely used for internal book keeping and semantic error detection
229 
230  enum AttribFlag {
231  FLAG_TAIL_INITIALIZE = 1,
232  FLAG_STREAM_ACTIVE = 2,
233  FLAG_STREAM_NOPREEXIST = 4 // Note inversion of sense!
234  };
235 
236  bool hasFlag(AttribFlag flag) const
237  { return (myAttribFlags & flag) ? true : false; }
238 
239  void setFlag(AttribFlag flag, bool onoff)
240  {
241  if (onoff)
242  myAttribFlags |= (int)flag;
243  else
244  myAttribFlags &= ~(int)flag;
245  }
246 
247  /// @}
248 
249  /// Uses the "type" option to determine type information
250  /// @see getOptions()
253  {
254  return myOptions.myTypeInfo;
255  }
256 
257  /// Set the option. This sets the "type" option on the attribute
258  /// @see getOptions()
261  {
262  myOptions.myTypeInfo = type;
263  }
264 
265  /// Checks if an attribute should be treated as a texture coordinate attribute.
266  /// Ideally, we could rely on the type info being GA_TYPE_TEXTURE_COORD,
267  /// but old files don't have this, and various importers don't set this.
268  /// If a float[3] (optionnally float[2]) attribute's name starts with "uv"
269  /// and is followed by zero or more digits (and nothing else), it's probably
270  /// safe to assume that it should be treated as a texture attribute.
271  bool shouldInterpretAsTexCoord(bool allow_float2=false) const;
272 
273  /// Returns the approximate type of the attribute
274  GA_StorageClass getStorageClass() const;
275 
276  /// Size of the AIFTuple, if it exists. If it doesn't, 1.
277  int getTupleSize() const;
278 
279  // Methods to get intrinsic data
280  // getName() returns the unprefixed name (as opposed to getFullName())
281  // We have separate const char * versions as this is often passed
282  // to sprintf().
283  SYS_FORCE_INLINE const UT_StringHolder &getName() const { return myName; }
284  SYS_FORCE_INLINE const UT_StringHolder &getFullName() const { return myName; }
285 
286  /// The data ID is shared by attributes that represent the same underlying
287  /// data and is used by cache mechanisms to avoid rebuilding when data has
288  /// not really changed. An ID of -1 indicates that this attribute is not
289  /// going to get a new ID when its data is changed, and therefore is not
290  /// participating in this scheme.
291  ///
292  /// Two attributes can share the same data ID even when they don't share
293  /// the same internal data pages or even fragmentation patterns. Note
294  /// however that the data ID is not necessarily changed for topology
295  /// changes, so it is necessary to also compare topology data IDs in order
296  /// to be absolutely sure that two attributes sharing the same data ID
297  /// represent the same data (taking into account defragmentation).
299  GA_DataId getDataId() const { return myDataId; }
302  {
303  myDataId = nextDataId();
304  }
306  void bumpDataId()
307  {
308  if (myDataId != GA_INVALID_DATAID)
309  assignNewDataId();
310  }
312  void clearDataId() { myDataId = GA_INVALID_DATAID; }
313 
314  /// This clones the data ID from src. If src has an invalid data ID,
315  /// which can be the case for details not created by SOP_Node or
316  /// SIM_GeometryCopy, we default to bumping the destination data ID.
317  /// This should be used by functions like GA_Attribute::replace()
318  /// when an attribute's data is replaced with that of src.
319  ///
320  /// NOTE: We must always either clone or bump the data ID if we've
321  /// copied from another attribute, even if that src attribute
322  /// has an invalid data ID. See Bug 79446 and 79438.
324  void cloneDataId(const GA_Attribute &src,
325  bool allow_clear = false)
326  {
327  if (allow_clear || src.myDataId != -1)
328  myDataId = src.myDataId;
329  else
330  bumpDataId();
331  }
332  /// NOTE: Just call cloneDataId(src).
335  bool allow_clear = false)
336  {
337  cloneDataId(src, allow_clear);
338  }
339 
340  /// The method to set array size
341  /// *Must* be implemented in subclasses
342  /// Return true if the attribute was resized.
343  virtual bool setArraySize(GA_Offset size) = 0;
344 
345  /// Try to compress data pages
346  /// Will try to compress *all* pages overlapping the specified offset range.
347  /// *Must* be implemented in subclasses
348  virtual void tryCompressAllPages(
349  GA_Offset start_offset = GA_Offset(0),
350  GA_Offset end_offset = GA_INVALID_OFFSET) = 0;
351 
352  /// Harden data pages
353  /// Will harden *all* pages overlapping the specified offset range.
354  /// Once this is done, multiple threads can write to an attribute in
355  /// parallel at a finer granularity than pages.
356  /// *Must* be implemented in subclasses
357  virtual void hardenAllPages(
358  GA_Offset start_offset = GA_Offset(0),
359  GA_Offset end_offset = GA_INVALID_OFFSET) = 0;
360 
361  /// The various concurrency levels supported by attributes for writing
362  /// per-element data.
364  /// No concurrent writes supported.
366  /// Concurrent writes to separate pages supported.
368  /// Concurrent writes to separate elements supported.
369  WRITE_CONCURRENCE_ELEMENT
370  };
371 
372  virtual WriteConcurrence getSupportedWriteConcurrence() const = 0;
373 
374  /// Return the attribute's copy interface or NULL
375  virtual const GA_AIFCopyData *getAIFCopyData() const;
376  /// Return the attribute's delta interface or NULL
377  virtual const GA_AIFDelta *getAIFDelta() const;
378  /// Return the attribute's tuple interface or NULL
379  virtual const GA_AIFTuple *getAIFTuple() const;
380  /// Return the attribute's math interface or NULL
381  virtual const GA_AIFMath *getAIFMath() const;
382  /// Return the attribute's merge interface or NULL
383  virtual const GA_AIFMerge *getAIFMerge() const;
384  /// Return the attribute's interpolation interface or NULL
385  virtual const GA_AIFInterp *getAIFInterp() const;
386  /// Return the attribute's blob interface or NULL
387  virtual const GA_AIFBlob *getAIFBlob() const;
388  /// Return the attribute's blob array interface or NULL
389  virtual const GA_AIFBlobArray *getAIFBlobArray() const;
390  /// Return the attribute's string tuple interface or NULL
391  virtual const GA_AIFStringTuple *getAIFStringTuple() const;
392  /// Return the attribute's shared string tuple interface or NULL
393  virtual const GA_AIFSharedStringTuple *getAIFSharedStringTuple() const;
394  /// Return the attribute's shared string array interface or NULL
395  virtual const GA_AIFSharedStringArray *getAIFSharedStringArray() const;
396  /// Return the attribute's shared options tuple interface or NULL
397  virtual const GA_AIFSharedDictTuple *getAIFSharedDictTuple() const;
398  /// Return the attribute's shared options tuple interface or NULL
399  virtual const GA_AIFSharedDictArray *getAIFSharedDictArray() const;
400  /// Return the attribute's index pair interface or NULL
401  virtual const GA_AIFIndexPair *getAIFIndexPair() const;
402  /// Return the attribute's blind data interface or NULL
403  virtual const GA_AIFBlindData *getAIFBlindData() const;
404  /// Return the attribute's edit interface or NULL
405  virtual const GA_AIFEdit *getAIFEdit() const;
406  /// Return the attribute's comparison interface or NULL
407  virtual const GA_AIFCompare *getAIFCompare() const;
408  /// Return the attribute's arraydata interface or NULL
409  virtual const GA_AIFNumericArray *getAIFNumericArray() const;
410 
411  /// Return the attribute's stat interface. Unlike other interfaces, this
412  /// method has default behaviour.
413  virtual const GA_AIFStat *getAIFStat() const;
414 
415  /// Generic method for getting an AIF by type
416  template <typename T> const T *getAIF() const { return GAgetAIF<T>(*this); }
417 
418  // Options can be used to associated arbitrary data with an attribute.
419  // Common options are defined in GA_Options.h
420  const GA_AttributeOptions &getOptions() const { return myOptions; }
421  GA_AttributeOptions &getOptions() { return myOptions; }
422 
423  /// Although an attribute may be a "point" or "normal", we may not want to
424  /// transform the point. This is the case with "rest" for example.
425  /// At the current time, this sets the flag corresponding with
426  /// "attribute:non_transforming" in the options.
427  /// @see needsTransform()
428  /// @see getTypeInfo()
430  {
431  myOptions.setIsNonTransforming(val);
432  }
433 
434  /// needTransform() checks whether the attribute is a
435  /// floating-point attribute whose type info is a transforming
436  /// type and whose non-transforming flag is false.
437  bool needsTransform(bool include_P = true) const
438  {
439  return getStorageClass() == GA_STORECLASS_FLOAT
440  && !myOptions.isNonTransforming()
441  && GAisTransformingType(getTypeInfo())
442  && (include_P || strcmp(getName(), "P") != 0);
443  }
444 
445  bool isDetached() const
446  {
447  return myOptions.myDetached;
448  }
449 
450  /// @{
451  /// Houdini forces certain restrictions on attribute names. However,
452  /// external software doesn't always have these restrictions. When
453  /// importing attributes, you can store the "real" attribute name, or use
454  /// the "export" name when exporting.
455  ///
456  /// @c getExportName() will return the attribute name if there's no export
457  /// name set.
458  void setExportName(const char *external_name);
459  bool hasExportName() const;
460  std::string getExportName() const;
461  /// @}
462 
463  /// Merge the options passed in with the options in the attribute
465  { myOptions.mergeOptions(src); }
466 
467  // Check to see the value of a specific option
468  bool importOption(const char *name, int &v) const;
469  bool importOption(const char *name, bool &v) const;
470  bool importOption(const char *name, fpreal32 &v) const;
471  bool importOption(const char *name, fpreal64 &v) const;
472  bool importOption(const char *name, UT_String &v) const;
473 
474  /// Methods which can be overridden from GA_Attribute
475 
476  /// Element destruction event. When an element is destroyed, the attribute
477  /// may be notified of this event.
478  virtual bool needDestruction() const;
479  /// Callback invoked if needsDestruction() returns true
480  virtual void destructElement(GA_Offset offset);
481 
482  /// The GA library expects any elements allocated at the end of the array
483  /// to be set to their default values. If this is not the case, then the
484  /// attribute can register itself for special initialization.
485  void setTailInitialization(bool onoff);
486 
487  /// Check whether the attribute is set to tail initialization
488  bool isTailInitialization() const
489  { return hasFlag(FLAG_TAIL_INITIALIZE); }
490 
491  /// When the array size is grown, attributes should initialize the value
492  /// appropriately. When an element is reused, however, the
493  /// reconstructElement is called. This happens if an element is deleted
494  /// then a new element is allocated (using the existing slot)
496  { reconstructElementBlock(offset, GA_Offset(1)); }
497 
498  /// When the array size is grown, attributes should initialize the value
499  /// appropriately. When elements are reused, however,
500  /// reconstructElementBlock is called. This happens if an element is
501  /// deleted and then a new element is allocated (using the existing slot)
502  virtual void reconstructElementBlock(GA_Offset offset, GA_Offset nelements) = 0;
503 
504  /// A method to "compact" any storage. For example, if there's a string
505  /// table associated with the attribute, this gives the attribute the option
506  /// to adjust the table to be more compact.
507  virtual void compactStorage();
508 
509  /// This method is called before a batch deletion operation. It allows the
510  /// attribute to mark objects as dirty so that there can be lazy computation
511  /// of data. For example, re-computing the number of elements in a group.
512  /// This method may be called multiple times, and so should typically just
513  /// set a flag (not perform a lot of computation).
514  virtual void batchDeletion();
515 
516  /// This method returns a new attribute of the same type with identical
517  /// settings. Attribute data is not copied. Derived classes implement
518  /// this method by overriding the virtual doClone(). Those classes not
519  /// supporting cloning are permitted to return NULL.
520  GA_Attribute *clone(const GA_IndexMap &index_map,
521  const UT_StringHolder &name,
522  bool clone_options) const;
523 
524  /// @section JSON-GA_Attribute JSON Schema: GA_Attribute
525  ///
526  /// The schema for an attribute consists of an array of two items. The
527  /// first entry contains of the definition of the attribute. The second
528  /// entry is the "private" data for the attribute. If there is no data for
529  /// the attribute (i.e. the attribute doesn't provide an AIFJSON), then a
530  /// null will be saved as the second element.
531  ///
532  /// The private data is saved/loaded by the GA_AIFJSON class for the
533  /// attribute.
534  ///
535  /// @code
536  /// [
537  /// "name" : "GA_Attribute",
538  /// "description" :
539  /// "An attribute is defined by an array with two items. The
540  /// first item is the definition of the attribute, the second
541  /// is private data associated with the attribute (may be null).",
542  /// "type" : "array",
543  /// "items" : [
544  /// { "$ref" : "GA_Attribute-Definition" }, // Attribute Definition
545  /// { "$ref" : "GA_Attribute-Data" }, // Specific type data
546  /// ],
547  /// ]
548  /// @endcode
549  ///
550  /// @section JSON-GA_Attribute-Definition JSON Schema: GA_Attribute-Definition
551  /// The attribute definition is a map containing the fields required to
552  /// recreate the attribute.
553  /// @code
554  /// {
555  /// "name" : "GA_Attribute-Definition",
556  /// "description" : "An map defining the attribute",
557  /// "type" : "orderedmap",
558  /// "properties": {
559  /// "scope": {
560  /// "type" : "string",
561  /// "optional" : true,
562  /// "default" : "public",
563  /// "description" : "Scope of the attribute",
564  /// },
565  /// "type": {
566  /// "type" : "string",
567  /// "description" : "Attribute type (ATI name)",
568  /// },
569  /// "name": {
570  /// "type" : "string",
571  /// "description" : "Name of the attribute",
572  /// },
573  /// "version": {
574  /// "type" : "integer",
575  /// "optional" : true,
576  /// "description" : "Version level for save",
577  /// },
578  /// "options": {
579  /// "type" : { "$ref" : "UT_Options" }
580  /// "description" : "Arbitrary options on the attribute",
581  /// },
582  /// },
583  /// }
584  /// @endcode
585  /// @see @ref JSON_FileFormat, GA_AttributeSet, GA_AttributeType
586 
587  /// Save the GA_Attribute-Definition section
588  bool jsonSaveDefinition(UT_JSONWriter &w) const;
589 
590  /// Load the GA_Attribute-Definition section
591  static bool jsonLoadDefinition(UT_JSONParser &p,
592  GA_AttributeScope &scope,
593  UT_WorkBuffer &type,
594  UT_WorkBuffer &name,
595  int64 &version,
596  GA_AttributeOptions &options);
597 
598  /// Return the AIF to handle saving/loading of the private data section
599  virtual const GA_AIFJSON *getAIFJSON() const;
600 
601  /// Return the optional "save" version number. This is passed to the JSON
602  /// attribute loader. If the version is <= 0, the version is not saved to
603  /// the file and 0 will be passed to the loader.
604  virtual int getSaveVersion() const;
605 
606  /// Debug validation of allocated array size
607  virtual bool debugValidateArrayCapacity(GA_Offset sz) const;
608 
609  /// Report the memory usage
610  ///
611  /// NOTE: If you're implementing this in a direct subclass of GA_Attribute,
612  /// call getBaseMemoryUsage() to get the amount of memory in the base
613  /// class. If in a more distant descendant class, call
614  /// Base::getMemoryUsage(false) to count the memory in Base and
615  /// above, excluding sizeof(Base).
616  virtual int64 getMemoryUsage(bool inclusive) const = 0;
617 
618  /// Count memory usage using a UT_MemoryCounter in order to count
619  /// shared memory correctly.
620  /// If inclusive is true, the size of this object is counted,
621  /// else only memory owned by this object is counted.
622  /// If this is pointed to by the calling object, inclusive should be true.
623  /// If this is contained in the calling object, inclusive should be false.
624  /// (Its memory was already counted in the size of the calling object.)
625  ///
626  /// NOTE: If you're implementing this in a direct subclass of GA_Attribute,
627  /// call getBaseMemoryUsage() to get the amount of memory in the base
628  /// class. If in a more distant descendant class, call
629  /// Base::countMemory(counter, false) to count the memory in Base and
630  /// above, excluding sizeof(Base).
631  virtual void countMemory(UT_MemoryCounter &counter, bool inclusive) const = 0;
632 
633  /// @{
634  /// @c defragment() defragments the memory used to store data elements
635  virtual void defragment(const GA_Defragment &defrag) = 0;
636  /// @}
637 
638  /// @private
639  /// Used only for optimizing merging of attributes
640  const GA_Attribute *getMergeSource() const { return myMergeSource; }
641 
642  /// This is only here so that select data outside of GA_Attribute
643  /// can also have data IDs, like GA_PrimitiveList and GA_EdgeGroup.
644  static GA_DataId nextDataId();
645 
646  /// @{
647  /// The attribute data may be moved to the GPU, and hence backed
648  /// by a compute buffer (GA_CEAttribute). Flushing will delete
649  /// our buffer & copy it back from the GPU if it has been marked
650  /// as modified.
651 
652  /// Caches a CE Attribute. If a cache already exists, the cached
653  /// data is returned and the write flag updated. If the cache
654  /// does not exist, an attempt is made to build a buffer. If
655  /// read is true, the buffer is initialized with the geometry data.
656  /// This can return NULL if a failure to build an attribute occurs
657  /// (for example, unsupported type or no GPU)
658  GA_CEAttribute *getCEAttribute(GA_StorageClass storage, int &tuplesize, bool isarray, bool read, bool write)
659  { return getCEAttribute(storage, GA_PRECISION_32, tuplesize, isarray, read, write); }
660  GA_CEAttribute *getCEAttribute(GA_StorageClass storage, GA_Precision precision, int &tuplesize, bool isarray, bool read, bool write);
661 
662  void setCEAttribute(GA_CEAttribute *ceattrib, bool leave_on_gpupu=false);
663 
664  /// Any CE cache which was marked as written to will be copied
665  /// back to the CPU. It will be left on the GPU, however.
666  void flushCEWriteCaches(bool clearwriteback=true);
667  bool hasPendingCEWriteBack() const;
668 
669  /// Remove all CE Caches, copying back any marked as written to.
670  void flushCECaches();
671 
672  /// Steal the CE attribute from the source attribute, leaving the
673  /// src with a null CE attribute.
674  void stealCEAttribute(const GA_Attribute &src);
675  /// @}
676 
677  /// @{
678  /// During streaming operations it can be important to flag which
679  /// attributes are in the process of being modified. This way
680  /// attempts to random-access read them can be detected and thwarted
681  /// as they won't be valid.
682 
683  /// Is this attribute is currently being streamed? No random
684  /// reads should be done to this attribute. Default is that
685  /// it is not streaming.
686  bool isActivelyStreamed() const
687  { return hasFlag(FLAG_STREAM_ACTIVE); }
688 
689  void setActivelyStreamed(bool isstreaming)
690  { setFlag(FLAG_STREAM_ACTIVE, isstreaming); }
691 
692  /// Was this attribute created as a result of the stream operation?
693  /// This allows detection of attributes that only exist as a result
694  /// of the stream beginning. Default is that it existed.
695  bool existedPriorToStream() const
696  { return !hasFlag(FLAG_STREAM_NOPREEXIST); }
697 
698  void setExistedPriorToStream(bool preexisted)
699  { setFlag(FLAG_STREAM_NOPREEXIST, !preexisted); }
700  /// @}
701 
702 protected:
703  /// For use by getMemoryUsage and countMemory in subclasses to count the
704  /// amount of memory used by this base class (NOTE: *always* exclusive)
705  int64 getBaseMemoryUsage() const;
706 
707  /// Only called by GA_AttributeSet and GA_ElementGroup
708  void setDetached(bool detached)
709  {
710  myOptions.myDetached = detached;
711  }
712 
713  /// Determine if we should overwrite our attribute on merge, off for
714  /// detail attributes so the first will win.
715  static bool checkGlobalOverwrite(const GA_MergeMap &map, const GA_Attribute *attrib);
716 
717 private:
718  /// Method called by the GA_AttributeType::create() factory method to
719  /// initialize the object by calling virtual overrides not accessible
720  /// in our constructor.
721  void initialize();
722 
723  /// Create a new attribute of this type.
724  virtual GA_Attribute *doClone(const GA_IndexMap &index_map,
725  const UT_StringHolder &name) const;
726 
729  const UT_StringHolder &,
730  const UT_Options *,
731  const GA_AttributeOptions *) const;
732 
733  /// @{
734  /// @private
735  /// Only called by GA_AttributeSet and GA_ElementGroup.
736  bool setName(const UT_StringHolder &newname);
737  void setProxy(GA_AttributeProxy *proxy);
738  friend class GA_AttributeSet;
739  friend class GA_ElementGroup;
740  friend class GA_MergeMap;
741  /// @}
742 
743 public:
744 
745  /// Returns true iff that is an attribute whose content can be copied
746  /// from this without any type conversions. This is important to
747  /// avoid reallocation of an attribute if its storage type,
748  /// including tuple size, matches the source attribute exactly.
749  /// Subclasses should call this first and return false if
750  /// this returns false.
751  virtual bool matchesStorage(const GA_Attribute *that) const
752  {
753  if (that == NULL)
754  return false;
755  if (getType().getTypeId() != that->getType().getTypeId())
756  return false;
757  return true;
758  }
759  /// In the case that we're copying from an attribute whose storage
760  /// type matches this exactly, this function copies the metadata
761  /// not associated with the storage, e.g. myOptions,
762  /// *excluding* the name and the data ID.
763  /// The attribute class of that must match the attribute class of that.
764  /// Subclasses must call this.
765  virtual void copyNonStorageMetadata(const GA_Attribute *that)
766  {
767  // NOTE: We shouldn't change myScope or myOptions.myDetached.
768  // For example, if we replace the contents of a private or
769  // detached attribute with those of a public one, it shouldn't
770  // (and can't) become public.
771  // myScope is more an indication of where the *detail* is keeping
772  // track of this attribute, (or not tracking, for detached.)
773  bool detached = myOptions.myDetached;
774  myOptions = that->myOptions;
775  myOptions.myDetached = detached;
776 
777  // NOTE: DO NOT set tail initialization here! This is just an
778  // indication of whether there may be data at non-default values
779  // past myIndexMap.myMaxTouchedOffset.
780  // This should be copied in the implementations of replace(),
781  // instead, since that's associated with referencing the data.
782  //setTailInitialization(that->isTailInitialize());
783  }
784 
785  /// This replaces the entirety of this attribute's content and non-
786  /// storage metadata (except the name) with that of the src attribute.
787  /// matchesStorage(src) should already return true.
788  /// This is primarily for use by GA_AttributeSet::replace().
789  /// NOTE: The internal content sizes may not match exactly if the
790  /// attribute type may overallocate, but the sizes should be such
791  /// that any real data will fit in the destination, so be careful
792  /// and deal with the myTailInitialize flag appropriately if
793  /// any extra elements aren't equal to the default.
794  virtual void replace(const GA_Attribute &src) = 0;
795 
796  /// Copy attribute values for a single element.
797  /// NOTE: The default implementation just tries to use GA_AIFCopyData,
798  /// incurring 2 more virtual calls!
799  /// @{
800  virtual bool copy(GA_Offset desti, GA_Offset srci)
801  { return copy(desti, *this, srci); }
802  virtual bool copy(GA_Offset desti, const GA_Attribute &src, GA_Offset srci);
803  /// @}
804 
805  /// Copy attribute values for a range of elements.
806  /// NOTE: The default implementation just tries to use GA_AIFCopyData,
807  /// incurring 2 more virtual calls!
808  /// WARNING: These do not support overlapping ranges within a single attribute!
809  /// @{
810  virtual bool copy(const GA_Range &destrange, const GA_Range &srcrange)
811  { return copy(destrange, *this, srcrange); }
812  virtual bool copy(const GA_Range &destrange, const GA_Attribute &src, const GA_Range &srcrange);
813  /// @}
814 
815  /// Assign all elements of a range from a single attribute value.
816  /// NOTE: The default implementation just tries to use GA_AIFCopyData,
817  /// incurring 2 more virtual calls, falling back on calling copy() for
818  /// each element in the destination range, which incurs the cost of the
819  /// virtual call for each!
820  /// @{
821  virtual bool fill(const GA_Range &destrange, GA_Offset srci)
822  { return fill(destrange, *this, srci); }
823  virtual bool fill(const GA_Range &destrange, const GA_Attribute &src, GA_Offset srci);
824  /// @}
825 private:
826  const GA_AttributeType &myType;
827  const GA_IndexMap &myIndexMap; // For mapping
828  UT_StringHolder myName; // Unprefixed name
829  GA_AttributeScope myScope; // Public or private
830  GA_AttributeOptions myOptions; // Attribute options
831  GA_AttributeProxy *myProxy; // representative referencer
832  int64 myDataId;
833  const GA_Attribute *myMergeSource; // Needed to optimize merging
834  int myAttribFlags;
835  mutable GA_CEAttribute *myCEAttribute; // OpenCL Backing.
836 };
837 
838 #define GA_GET_AIF_SPECIALIZATION(AIF_NAME) \
839  template <> SYS_STATIC_INLINE const GA_##AIF_NAME * \
840  GAgetAIF(const GA_Attribute &attrib) { return attrib.get##AIF_NAME(); } \
841  /**/
842 GA_GET_AIF_SPECIALIZATION(AIFCopyData)
847 GA_GET_AIF_SPECIALIZATION(AIFInterp)
849 GA_GET_AIF_SPECIALIZATION(AIFBlobArray)
850 GA_GET_AIF_SPECIALIZATION(AIFStringTuple)
851 GA_GET_AIF_SPECIALIZATION(AIFSharedDictTuple)
852 GA_GET_AIF_SPECIALIZATION(AIFSharedDictArray)
853 GA_GET_AIF_SPECIALIZATION(AIFSharedStringTuple)
854 GA_GET_AIF_SPECIALIZATION(AIFSharedStringArray)
855 GA_GET_AIF_SPECIALIZATION(AIFIndexPair)
856 GA_GET_AIF_SPECIALIZATION(AIFBlindData)
858 GA_GET_AIF_SPECIALIZATION(AIFCompare)
859 GA_GET_AIF_SPECIALIZATION(AIFNumericArray)
860 #undef GA_GET_AIF_SPECIALIZATION
861 
862 /// @brief Automatically expand attribute data pages for threading
863 ///
864 /// Normally, threading is allowed only if each thread is guaranteed to write
865 /// to an individual page of data. Not all algorithms are amenable to this
866 /// constraint. Using the GA_AutoThreadExpand class will force the attribute
867 /// to harden all its data pages so that multiple threads can write across page
868 /// boundaries. Multiple threads are still prohibited from writing to the same
869 /// offset. In its destructor, the class will automatically call the compress
870 /// method to regain memory efficiency. For example: @code
871 /// void process(GA_RWAttributeRef &write, GA_ROAttributeRef &read)
872 /// {
873 /// GA_AutoHardenForThreading thread_write(*write.getAttribute());
874 /// // There's no need to harden the read-only attribute, but now that
875 /// // we've hardened the write attribute, our threaded algorithm is able
876 /// // to write data across page boundaries.
877 /// UTparallelFor(range, functor(write, read));
878 /// }
879 /// @endcode
881 {
882 public:
884  GA_Offset start_offset = GA_Offset(0),
885  GA_Offset end_offset = GA_INVALID_OFFSET)
886  : myAttribute(attribute)
887  , myStart(start_offset)
888  , myEnd(end_offset)
889  {
890  // Group-scoped attributes aren't thread safe even if hardened,
891  // so if someone is using this "For Threading" they are likely
892  // in trouble.
893  UT_ASSERT(!myAttribute.isGroup());
894  myAttribute.hardenAllPages(myStart, myEnd);
895  }
897  {
898  myAttribute.tryCompressAllPages(myStart, myEnd);
899  }
900 private:
901  GA_Attribute &myAttribute;
902  GA_Offset myStart;
903  GA_Offset myEnd;
904 };
905 
906 /// Utility for updating a data id by combining it with another.
907 /// If 'other' is negative then false is returned without any updates.
908 /// To use this for combining multiple data id's, initialize id with
909 /// -1. For example: @code
910 /// GA_DataId getDataId()
911 /// {
912 /// GA_DataId id = -1;
913 /// if (!mixDataId(id, myDataId0))
914 /// return -1;
915 /// if (!mixDataId(id, myDataId1))
916 /// return -1;
917 /// return id;
918 /// }
919 /// @endcode
920 static inline bool
921 GAcombineDataId(GA_DataId &id, GA_DataId other)
922 {
923  if (other < 0)
924  return false;
925  if (other > id)
926  id = other;
927  return true;
928 }
929 
931 
933 
934 #endif
A class to manage an ordered array which has fixed offset handles.
Definition: GA_IndexMap.h:63
GA_CEAttribute * getCEAttribute(GA_StorageClass storage, int &tuplesize, bool isarray, bool read, bool write)
Definition: GA_Attribute.h:658
UT_UniquePtr< const GA_Attribute > GA_ConstAttributeUPtr
Definition: GA_Attribute.h:932
SYS_FORCE_INLINE void bumpDataId()
Definition: GA_Attribute.h:306
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
SYS_FORCE_INLINE const GA_Detail & getDetail() const
Definition: GA_Attribute.h:208
Definition of a geometry attribute.
Definition: GA_Attribute.h:198
Generic Attribute Interface class to access an attribute as a array.
Generic Attribute Interface class to get/set data as index pairs.
virtual bool copy(const GA_Range &destrange, const GA_Range &srcrange)
Definition: GA_Attribute.h:810
SYS_FORCE_INLINE GA_Detail & getDetail()
Definition: GA_Attribute.h:209
void setTypeInfo(GA_TypeInfo t)
Definition: GA_Attribute.h:100
UT_IntrusivePtr< GA_AttributeProxy > GA_AttributeProxyHandle
UT_IntrusivePtr< const GA_AttributeProxy > GA_ConstAttributeProxyHandle
A specialization of GA_AIFDictTuple to access "shared strings".
bool exportOnSave(bool defval=false) const
Definition: GA_Attribute.h:128
GA_StorageClass
Definition: GA_Types.h:72
getFileOption("OpenEXR:storage") storage
Definition: HDK_Image.dox:276
Attribute Interface class to perform numeric operations on attributes.
Definition: GA_AIFMath.h:88
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
int64 GA_DataId
Definition: GA_Types.h:687
const GLdouble * v
Definition: glcorearb.h:837
GA_Precision
Definition: GA_Types.h:87
SYS_FORCE_INLINE const GA_IndexMap & getIndexMap() const
Definition: GA_Attribute.h:207
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
GA_Attribute * create(const GA_IndexMap &index_map, GA_AttributeScope scope, const UT_StringHolder &name, const UT_Options *creation_options, const GA_AttributeOptions *attribute_options) const
Attribute Interface for accessing generic blob data.
The merge map keeps track of information when merging details.
Definition: GA_MergeMap.h:53
void setExportOnMerge(bool v)
Set the export on merge flag.
Definition: GA_Attribute.h:117
void setExportOnSave(bool v)
Set the export on save flag.
Definition: GA_Attribute.h:131
SYS_FORCE_INLINE GA_AttributeScope getScope() const
Definition: GA_Attribute.h:212
bool hasFlag(AttribFlag flag) const
Definition: GA_Attribute.h:236
void setExportToInfoBlock(bool v)
Definition: GA_Attribute.h:104
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:37
void setExistedPriorToStream(bool preexisted)
Definition: GA_Attribute.h:698
#define GA_INVALID_DATAID
Definition: GA_Types.h:688
virtual bool matchesStorage(const GA_Attribute *that) const
Definition: GA_Attribute.h:751
SYS_FORCE_INLINE int getTypeId() const
float fpreal32
Definition: SYS_Types.h:200
void read(T &in, bool &v)
Definition: ImfXdr.h:502
FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n, const fill_t< Char > &fill) -> OutputIt
Definition: format.h:1262
SYS_FORCE_INLINE const GA_AttributeType & getType() const
Definition: GA_Attribute.h:206
No concurrent writes supported.
Definition: GA_Attribute.h:365
#define GA_INVALID_OFFSET
Definition: GA_Types.h:678
A range of elements in an index-map.
Definition: GA_Range.h:42
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
SYS_FORCE_INLINE const UT_StringHolder & getName() const
Definition: GA_Attribute.h:283
SYS_FORCE_INLINE GA_ConstAttributeProxyHandle getProxy() const
Definition: GA_Attribute.h:222
double fpreal64
Definition: SYS_Types.h:201
GA_Size GA_Offset
Definition: GA_Types.h:641
SYS_FORCE_INLINE void cloneDataId(const GA_Attribute &src, bool allow_clear=false)
Definition: GA_Attribute.h:324
virtual bool fill(const GA_Range &destrange, GA_Offset srci)
Definition: GA_Attribute.h:821
void setFlag(AttribFlag flag, bool onoff)
Definition: GA_Attribute.h:239
GA_AttributeScope
Definition: GA_Types.h:142
GLintptr offset
Definition: glcorearb.h:665
Attribute Interface for accessing generic blob data.
Definition: GA_AIFBlob.h:39
Automatically expand attribute data pages for threading.
Definition: GA_Attribute.h:880
SYS_FORCE_INLINE bool isGroup() const
Definition: GA_Attribute.h:213
Attribute Interface for merging attribute data between details.
Definition: GA_AIFMerge.h:56
PXL_API const char * getName(const ColorSpace *space)
Return the name of the color space.
This class holds a reference to an attribute. Such an indirection level allows an easy way to invalid...
const UT_Options * options() const
Definition: GA_Attribute.h:150
std::string OIIO_UTIL_API replace(string_view str, string_view pattern, string_view replacement, bool global=false)
bool needsTransform(bool include_P=true) const
Definition: GA_Attribute.h:437
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
Class to fill GA_Stat information about an attribute. This AIF is used to fill GA_Stat type informati...
Definition: GA_AIFStat.h:30
A specialization of GA_AIFStringArray to access "shared strings".
GA_AutoHardenForThreading(GA_Attribute &attribute, GA_Offset start_offset=GA_Offset(0), GA_Offset end_offset=GA_INVALID_OFFSET)
Definition: GA_Attribute.h:883
void mergeOptions(const GA_AttributeOptions &src)
Merge the options passed in with the options in the attribute.
Definition: GA_Attribute.h:464
long long int64
Definition: SYS_Types.h:116
Attribute Interface class to perform comparisons on attributes.
Definition: GA_AIFCompare.h:27
Defragmentation of IndexMaps.
Definition: GA_Defragment.h:45
void setLeaveOnGPU(bool v)
Definition: GA_Attribute.h:106
GLuint const GLchar * name
Definition: glcorearb.h:786
OPENVDB_API void initialize()
Global registration of native Grid, Transform, Metadata and Point attribute types. Also initializes blosc (if enabled).
Definition: logging.h:294
SYS_FORCE_INLINE GA_DataId getDataId() const
Definition: GA_Attribute.h:299
GA_AttributeOptions & getOptions()
Definition: GA_Attribute.h:421
SYS_FORCE_INLINE GA_AttributeProxyHandle getProxy()
Definition: GA_Attribute.h:220
virtual void copyNonStorageMetadata(const GA_Attribute *that)
Definition: GA_Attribute.h:765
GA_TypeInfo
Definition: GA_Types.h:100
GLdouble t
Definition: glad.h:2397
UT_UniquePtr< GA_Attribute > GA_AttributeUPtr
Definition: GA_Attribute.h:930
#define GA_GET_AIF_SPECIALIZATION(AIF_NAME)
Definition: GA_Attribute.h:838
bool exportToInfoBlock() const
Definition: GA_Attribute.h:103
GT_API const UT_StringHolder version
GLenum GLint GLint * precision
Definition: glcorearb.h:1925
SYS_FORCE_INLINE const UT_StringHolder & getFullName() const
Definition: GA_Attribute.h:284
SYS_FORCE_INLINE void clearDataId()
Definition: GA_Attribute.h:312
GLsizeiptr size
Definition: glcorearb.h:664
GA_AttributeOwner
Definition: GA_Types.h:34
A map of string to various well defined value types.
Definition: UT_Options.h:84
bool exportOnMergeSet() const
Definition: GA_Attribute.h:111
void setDetached(bool detached)
Only called by GA_AttributeSet and GA_ElementGroup.
Definition: GA_Attribute.h:708
void setActivelyStreamed(bool isstreaming)
Definition: GA_Attribute.h:689
SYS_FORCE_INLINE GA_TypeInfo getTypeInfo() const
Definition: GA_Attribute.h:252
bool leaveOnGPU() const
Definition: GA_Attribute.h:105
virtual bool copy(GA_Offset desti, GA_Offset srci)
Definition: GA_Attribute.h:800
void reconstructElement(GA_Offset offset)
Definition: GA_Attribute.h:495
const T * getAIF() const
Generic method for getting an AIF by type.
Definition: GA_Attribute.h:416
GA_TypeInfo typeInfo() const
Definition: GA_Attribute.h:99
bool isStringSet(bool defval=false) const
Definition: GA_Attribute.h:139
const GA_AttributeOptions & getOptions() const
Definition: GA_Attribute.h:420
A specialization of GA_AIFDictArray to access "shared strings".
A specialization of GA_AIFStringTuple to access "shared strings".
Concurrent writes to separate pages supported.
Definition: GA_Attribute.h:367
GLuint GLfloat * val
Definition: glcorearb.h:1608
Attribute Interface for blind data per element.
bool isNonTransforming() const
Definition: GA_Attribute.h:101
#define SYS_UNIMPLEMENTED_TEMPLATE(T)
OIIO_API bool attribute(string_view name, TypeDesc type, const void *val)
bool exportOnSaveSet() const
Definition: GA_Attribute.h:125
bool isDetached() const
Definition: GA_Attribute.h:445
SYS_FORCE_INLINE GA_AttributeOwner getOwner() const
Definition: GA_Attribute.h:210
Container class for all geometry.
Definition: GA_Detail.h:96
Attribute Interface class to copy attribute data.
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
void setNonTransforming(bool val)
Definition: GA_Attribute.h:429
bool isTailInitialization() const
Check whether the attribute is set to tail initialization.
Definition: GA_Attribute.h:488
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
bool existedPriorToStream() const
Definition: GA_Attribute.h:695
SYS_FORCE_INLINE void assignNewDataId()
Definition: GA_Attribute.h:301
Attribute Interface for file I/O.
Definition: GA_AIFJSON.h:39
void setIsNonTransforming(bool v)
Definition: GA_Attribute.h:102
SYS_FORCE_INLINE void setTypeInfo(GA_TypeInfo type)
Definition: GA_Attribute.h:260
bool exportOnMerge(bool defval=false) const
Definition: GA_Attribute.h:114
void write(T &out, bool v)
Definition: ImfXdr.h:287
type
Definition: core.h:1059
AIF to record changes to attribute values.
Definition: GA_AIFEdit.h:397
SYS_FORCE_INLINE void cloneOrBumpDataId(const GA_Attribute &src, bool allow_clear=false)
NOTE: Just call cloneDataId(src).
Definition: GA_Attribute.h:334
Generic Attribute Interface class to access an attribute as a tuple.
Definition: GA_AIFTuple.h:32
Definition: format.h:895
bool isActivelyStreamed() const
Definition: GA_Attribute.h:686
Generic Attribute Interface class to work with string indices directly, rather than string values...
GLenum src
Definition: glcorearb.h:1793
void setIsStringSet(bool v)
Set the "string set" flag.
Definition: GA_Attribute.h:142