HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GA_PrimitiveList.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_PrimitiveList.h (GA Library, C++)
7  *
8  * COMMENTS: The list of a detail's primitives.
9  */
10 
11 #pragma once
12 
13 #ifndef __GA_PrimitiveList__
14 #define __GA_PrimitiveList__
15 
16 #include "GA_API.h"
17 #include "GA_OffsetList.h"
18 #include "GA_PageArray.h"
19 #include "GA_PrimitiveTracker.h"
20 #include "GA_PrimitiveTypeId.h"
21 #include "GA_Types.h"
22 #include <UT/UT_Array.h>
23 #include <UT/UT_TaskExclusive.h>
24 #include <SYS/SYS_Inline.h>
25 
26 class GA_Defragment;
27 class GA_Detail;
28 struct GA_JSONUniformBlock;
29 class GA_LoadMap;
30 class GA_MergeMap;
31 class GA_PolyCounts;
32 class GA_Primitive;
34 class GA_SaveMap;
35 
36 class UT_StringRef;
37 class UT_JSONParser;
38 class UT_JSONValue;
39 class UT_JSONWriter;
40 class UT_MemoryCounter;
41 class UT_StringArray;
42 
43 /// @brief A list of primitives
44 ///
45 /// Primitives for a detail are stored in a primitive list. The list stores
46 /// pointers to primitive objects.
47 /// The list is ordered in the same order as the primitive attribute lists.
49 {
50 public:
51  GA_PrimitiveList(GA_Detail &detail);
52 
55  {
56  clear(true);
57  }
58 
60  const GA_Primitive *get(GA_Offset off) const
61  {
62  const GA_Primitive *const*prim_array = myList;
63  if (!prim_array)
64  prim_array = hardenPrimitives();
65  UT_ASSERT_P(GAisValid(off) && off < GA_Offset(getMyListSize()));
66  return prim_array[off];
67  }
70  {
71  GA_Primitive *const*prim_array = myList;
72  if (!prim_array)
73  prim_array = hardenPrimitives();
74  UT_ASSERT_P(GAisValid(off) && off < GA_Offset(getMyListSize()));
75  return prim_array[off];
76  }
77 
78  /// Returns a shallow copy of the vertex list of the primitive at the
79  /// specified primitive offset.
80  /// You must include GA_Primitive.h to use this.
82  GA_OffsetListRef getVertexList(GA_Offset primoff) const;
83 
84  /// Returns the number of vertices in the primitive at the specified
85  /// primitive offset.
86  /// You must include GA_Primitive.h to use this.
88  GA_Size getVertexCount(GA_Offset primoff) const;
89 
90  /// Returns the vertex offset in the primitive at the specified
91  /// primitive offset in vertex list position i.
92  /// If you're accessing all vertex offsets, it'll be faster to
93  /// call getVertexList() once and either read from that or
94  /// call forEach(fucntor) on it.
95  /// You must include GA_Primitive.h to use this.
97  GA_Offset getVertexOffset(GA_Offset primoff, GA_Size i) const;
98 
99  /// Returns the type ID of the primitive at the specified
100  /// primitive offset.
101  /// You must include GA_Primitive.h to use this.
103  int getTypeId(GA_Offset primoff) const;
104 
105  /// Returns the "closed" flag for polygon, NURBS curve, or Bezier curve
106  /// primitives, or false for other primitive types.
107  /// You must include GA_Primitive.h to use this.
109  bool getClosedFlag(GA_Offset primoff) const;
110 
111  /// Sets the "closed" flag for polygon primitives.
112  /// For NURBS curve or Bezier curve primitives, use GEO_Face::close()
113  /// or GEO_Face::open().
114  /// You must include GA_Primitive.h to use this.
116  void setClosedFlag(GA_Offset primoff, bool closed);
117 
118  /// Report on memory usage
119  int64 getMemoryUsage(bool inclusive) const;
120  int64 getDeviceMemoryUsage() const;
121 
122  /// Count memory usage using a UT_MemoryCounter in order to count
123  /// shared memory correctly.
124  /// If inclusive is true, the size of this object is counted,
125  /// else only memory owned by this object is counted.
126  /// If this is pointed to by the calling object, inclusive should be true.
127  /// If this is contained in the calling object, inclusive should be false.
128  /// (Its memory was already counted in the size of the calling object.)
129  void countMemory(UT_MemoryCounter &counter, bool inclusive) const;
130 
131  /// Offset size of the list
133  {
134  return GA_Offset(myList ? getMyListSize() : myVertexLists.size());
135  }
136 
137  /// Set capacity of primitive offsets in the list
138  void adjustArraySize(GA_Offset size);
139  void clear(bool for_deletion);
140 
141  void stashAll();
142  void destroyStashed();
143 
144  /// Returns true iff the primitive list representation is as
145  /// separate allocations for each primitive, instead of using the
146  /// paged array format.
147  bool isFullRepresentation() const
148  {
149  return myList != nullptr;
150  }
151 
152  /// Returns true iff the specified vertex list page is constant.
155  {
156  return !myList && myVertexLists.isPageConstant(UT_PageNum(pagenum));
157  }
158 
159  /// Returns the representative (first) vertex list for a "constant" page.
160  /// The page must be constant-compressed, i.e. isVertexListPageConstant
161  /// must return true.
162  /// NOTE: "constant" in this context really means that the vertex lists
163  /// all have the same vertex count, and represent contiguous vertices.
166  {
167  UT_ASSERT_P(myVertexLists.isPageConstant(pagenum));
168  auto p = myVertexLists.getPageData(pagenum);
169  UT_ASSERT_COMPILETIME(2*sizeof(*p) == sizeof(GA_OffsetListRef));
170  auto po = reinterpret_cast<const GA_OffsetListRef*>(p);
171  return *po;
172  }
173 
174  /// NOTE: This is safe to call from multiple threads as long as they aren't writing
175  /// to the same page, and hardenVertexListPageTable() has been called from
176  /// single-threaded code.
177  /// You must include GA_Primitive.h to use this.
178  /// @{
180  void setVertexList(GA_Offset primoff, const GA_OffsetListRef &vertices);
182  void setVertexList(GA_Offset primoff, const GA_OffsetList &vertices);
184  void setVertexList(GA_Offset primoff, GA_OffsetList &&vertices);
185  /// @}
186 
187  /// NOTE: This is not threadsafe. Also, this just hardens the table, not any pages.
189  {
190  if (!isFullRepresentation())
191  myVertexLists.hardenTable();
192  }
193 
194  /// NOTE: This is not threadsafe. It hardens all vertex list pages, if applicable.
195  void hardenAllVertexListPages();
196 
197  /// NOTE: This will only work if !isFullRepresentation()
198  /// NOTE: This is safe to call from multiple threads as long as pagenum is
199  /// different for each and hardenVertexListPageTable() has been called
200  /// outside threaded code.
201  GA_OffsetList *hardenVertexListPage(GA_PageNum pagenum);
202 
203  void merge(GA_Detail &dgeo, const GA_MergeMap &map);
204 
205  /// NOTE: Since the primitive maps of dstgeo and srcgeo must have already
206  /// been made equal by the time this is called.
207  void replace(GA_Detail &dstgeo, const GA_Detail &srcgeo);
208 
209  /// Called by GA_Detail::defragment when defragmenting the primitive
210  /// index map.
211  /// NOTE: This bumps the primitive list data ID.
212  void defragment(const GA_Defragment &defrag);
213 
214  /// Called by GA_Detail::defragment when defragmenting the vertex
215  /// index map.
216  /// NOTE: This bumps the primitive list data ID.
217  void defragmentVertices(const GA_Defragment &defrag);
218 
219  /// Copy any modified caches from the GPU back to CPU cache.
220  void flushCEWriteCaches(const GA_PrimitiveFactory &f);
221 
222  /// Copy any modified caches from the GPU to CPU. Then delete the GPU
223  /// cache.
224  void flushCECaches(const GA_PrimitiveFactory &f);
225 
226  /// Steal the CE buffers from the source primitive list.
227  void stealCEBuffers(const GA_PrimitiveList &src,
228  const GA_PrimitiveFactory &f);
229 
230  /// Save data to a JSON stream.
231  /// @section JSON-GA_PrimitiveList JSON Schema: GA_PrimitiveList
232  /// @code
233  /// {
234  /// "name" : "GA_PrimitiveList",
235  /// "description" : "An array of primitive objects",
236  /// "type" : "array",
237  /// "items" : { "$ref":"GA_Primitive" },
238  /// }
239  /// @endcode
240  /// @see @ref JSON_FileFormat, GA_Primitive
241  bool jsonSave(UT_JSONWriter &w, const GA_SaveMap &save) const;
242 
243  /// Load from a JSON stream
244  /// @see @ref JSON_FileFormat
245  bool jsonLoad(UT_JSONParser &p, GA_LoadMap &load, GA_Offset &load_end);
246 
247  /// Check to see whether the primitive list contains primitives of a given
248  /// type
250  { return myTracker.contains(type); }
251  /// Check to see whether the primitive list only contains primitives of a
252  /// given type
254  { return myTracker.containsOnly(types); }
255  /// Return the number of primitives of the given type
257  { return myTracker.count(type); }
258  /// Return the number of primitives of the given family
260  { return myTracker.countFamily(family); }
261  /// Test whether the primitive list contains any primitives that have a
262  /// local transform.
263  bool hasLocalTransform(const GA_PrimitiveFactory &factory) const
264  { return myTracker.hasLocalTransform(factory); }
265  /// Return the primitives of the given type. Unlike the functions
266  /// above which use myTracker, this function requires iterating through
267  /// all primitives.
268  bool getPrimitivesOfType(const GA_PrimitiveTypeId &type,
269  UT_Array<const GA_Primitive *> &prims) const;
270 
271  /// Use this to mark primitives or their intrinsic data as dirty.
272  void bumpDataId();
274  { return myDataID; }
275 
277  { return myTracker; }
278 
279  /// Force a rebuild of primitive counts. This is triggered if
280  /// primitives have changed their types without being added/removed
281  /// explicitly. Packed primitives, for example, are polymorphic
282  /// in this manner.
283  void rebuildTracker();
284 
285  /// Goes through the primitive list to confirm that it's in a consistent
286  /// state, returning true if it is, and false if it isn't.
287  /// This is only for debugging purposes.
288  bool validate(const GA_Detail &detail) const;
289 
290  /// Append to a run-length encoded array of pairs of a primitive type ID and
291  /// a count of those primitives. A detail with 5 polygons, followed
292  /// by 3 tetrahedra, followed by 4 polygons will yield:
293  /// {GA_PRIMPOLY, 5}, {GA_PRIMTETRAHEDRON, 3}, {GA_PRIMPOLY, 4}
294  void getPrimitiveTypeCounts(
295  UT_Array<std::pair<int,exint>> &type_count_pairs,
296  const GA_Range *range = nullptr) const;
297 
298  // NOTE: These functor classes must be in the scope of GA_PrimitiveList
299  // so that it can access GA_Primitive::unstashImpl,
300  // GA_PrimitiveDefinition::getConstructor, and
301  // GA_PrimitiveDefinition::getBlockConstructor.
302  // They have to be public so that UTparallelReduce
303  // can be instantiated for GCC with it.
304  class ga_ParallelCreateForMerge;
305  class ga_ParallelCreatePagedForMerge;
306  class ga_ReplacePrimitiveBlockParallel;
307 
308  void initVertexLists(
309  GA_Offset prim_block_start,
310  GA_Offset vertex_block_start,
311  GA_Size nprimitives,
312  GA_Size nvertices_each,
313  bool closed = false);
314  void initVertexLists(
315  GA_Offset prim_block_start,
316  GA_Offset vertex_block_start,
317  const GA_PolyCounts &vertex_counts,
318  bool closed = false);
319  /// First value of closed_span_lengths is the number with closed false.
320  /// To start with closed true, have a value of 0 first, then the number with closed true.
321  /// nullptr means closed false for all primitives.
322  void initVertexLists(
323  GA_Offset prim_block_start,
324  GA_Offset vertex_block_start,
325  const GA_PolyCounts &vertex_counts,
326  const exint *closed_span_lengths = nullptr,
327  const exint ncopies = 1);
328 
329 private:
330  void create(GA_Detail &detail,
331  const GA_PrimitiveDefinition &def,
333  bool check_stash);
334  void createBlock(GA_Detail &detail,
335  const GA_PrimitiveDefinition &def,
336  GA_Size nprimitives,
338  bool check_stash);
339 
340  /// To be called from GA_Detail::sortVertexMapByPrimitiveUse()
341  void sortVertexMapByPrimitiveUse(GA_IndexMap &vertex_map);
342 
343  /// @{
344  /// This class is non-copyable
347  /// @}
348 
349  bool loadPolyOrTetRun(
350  UT_JSONParser &p,
351  int runenum,
352  GA_Offset &primoff,
353  GA_Offset init_vtxoff,
354  GA_Detail &detail);
355  bool createLoadPrimitive(UT_JSONParser &p,
356  GA_LoadMap &load,
357  const UT_StringRef &type,
358  GA_Offset &load_offset,
359  const UT_StringArray *varying,
360  const GA_JSONUniformBlock &uniform);
361 
363  exint getMyListSize() const
364  {
365  return getMyPrimPtrSize(myList);
366  }
368  exint getMyStashedSize() const
369  {
370  return getMyPrimPtrSize(myStashedPrims);
371  }
373  static exint getMyPrimPtrSize(GA_Primitive**p)
374  {
375  UT_ASSERT_P(p);
376  return ((const exint*)p)[-1];
377  }
378  void reallocMyList(exint newsize);
380  void freeMyList();
381 
382  void clearVertexLists();
383  void destroy(GA_Offset off);
384 
385  GA_Primitive *const*hardenPrimitives() const;
386  /// This can be faster than hardenPrimitives, if we're calling from a
387  /// thread-unsafe function already.
388  GA_Primitive *const*hardenPrimitivesThreadUnsafe();
390  GA_Primitive *const*hardenPrimitivesImpl(bool parallel) const;
391  class HardenPrimitivesFunctor;
392 
393  void dump() const;
394 
395  friend class GA_Detail;
396 
397  /// This is nullptr when using myVertexLists and myPrimitiveTypes.
398  /// It has an exint indicating the size immediately before
399  /// where it points in memory.
400  mutable GA_Primitive **myList;
401 
402  GA_Detail &myDetail;
403  GA_PageArray<int,1,false,false> myPrimitiveTypes;
404  GA_PageArray<int64,2,false,false> myVertexLists;
405  mutable UT_TaskExclusive<HardenPrimitivesFunctor> myHardenExclusive;
406 
407  GA_PrimitiveTracker myTracker;
408  GA_DataId myDataID;
409 
410  /// Array of temporarily stashed primitives.
411  /// This is only used to reduce overhead of freeing and
412  /// reallocating primitives if it's likely that the
413  /// detail is going to be rebuilt with the same primitive
414  /// types in the same order as the previous primitives.
415  /// It has an exint indicating the size immediately before
416  /// where it points in memory.
417  mutable GA_Primitive **myStashedPrims;
418 };
419 
420 #endif
A class to manage an ordered array which has fixed offset handles.
Definition: GA_IndexMap.h:63
SYS_FORCE_INLINE GA_OffsetListRef getConstantVertexListPage(GA_PageNum pagenum) const
UT_ASSERT_COMPILETIME(BRAY_EVENT_MAXFLAGS<=32)
GLenum GLint * range
Definition: glcorearb.h:1925
Used to pass options and map offset values during saving.
Definition: GA_SaveMap.h:48
GA_DataId getDataId() const
const GA_PrimitiveTracker & getTracker() const
int64 GA_DataId
Definition: GA_Types.h:696
The merge map keeps track of information when merging details.
Definition: GA_MergeMap.h:53
int64 exint
Definition: SYS_Types.h:125
exint UT_PageNum
Definition: UT_PageArray.h:34
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
SYS_FORCE_INLINE bool GAisValid(GA_Size v)
Definition: GA_Types.h:655
exint GA_Size
Defines the bit width for index and offset types in GA.
Definition: GA_Types.h:236
GA_PrimitiveFamilyMask
GA_Size countTypeFamily(GA_PrimitiveFamilyMask family) const
Return the number of primitives of the given family.
A range of elements in an index-map.
Definition: GA_Range.h:42
GA_Size GA_Offset
Definition: GA_Types.h:646
GA_Size countType(const GA_PrimitiveTypeId &type) const
Return the number of primitives of the given type.
bool containsType(const GA_PrimitiveTypeId &type) const
GLfloat f
Definition: glcorearb.h:1926
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
SYS_FORCE_INLINE ~GA_PrimitiveList()
GLintptr offset
Definition: glcorearb.h:665
Class which keeps counts of each type of primitive.
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:155
std::string OIIO_UTIL_API replace(string_view str, string_view pattern, string_view replacement, bool global=false)
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
long long int64
Definition: SYS_Types.h:116
Options during loading.
Definition: GA_LoadMap.h:42
Defragmentation of IndexMaps.
Definition: GA_Defragment.h:45
A list of primitives.
GLsizeiptr size
Definition: glcorearb.h:664
bool containsOnlyTypes(const UT_Array< GA_PrimitiveTypeId > &types) const
LeafData & operator=(const LeafData &)=delete
GA_Size GA_PageNum
Definition: GA_Types.h:649
bool isFullRepresentation() const
bool hasLocalTransform(const GA_PrimitiveFactory &factory) const
Class to store JSON objects as C++ objects.
Definition: UT_JSONValue.h:99
void hardenVertexListPageTable()
NOTE: This is not threadsafe. Also, this just hardens the table, not any pages.
Container class for all geometry.
Definition: GA_Detail.h:96
GA_Offset offsetSize() const
Offset size of the list.
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
OutGridT XformOp bool bool MergePolicy merge
Definition of a geometric primitive.
GLsizei GLenum GLenum * types
Definition: glcorearb.h:2542
SYS_FORCE_INLINE bool isVertexListPageConstant(GA_PageNum pagenum) const
Returns true iff the specified vertex list page is constant.
GLenum src
Definition: glcorearb.h:1793