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