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 
121  /// Count memory usage using a UT_MemoryCounter in order to count
122  /// shared memory correctly.
123  /// If inclusive is true, the size of this object is counted,
124  /// else only memory owned by this object is counted.
125  /// If this is pointed to by the calling object, inclusive should be true.
126  /// If this is contained in the calling object, inclusive should be false.
127  /// (Its memory was already counted in the size of the calling object.)
128  void countMemory(UT_MemoryCounter &counter, bool inclusive) const;
129 
130  /// Offset size of the list
132  {
133  return GA_Offset(myList ? getMyListSize() : myVertexLists.size());
134  }
135 
136  /// Set capacity of primitive offsets in the list
137  void adjustArraySize(GA_Offset size);
138  void clear(bool for_deletion);
139 
140  void stashAll();
141  void destroyStashed();
142 
143  /// Returns true iff the primitive list representation is as
144  /// separate allocations for each primitive, instead of using the
145  /// paged array format.
146  bool isFullRepresentation() const
147  {
148  return myList != nullptr;
149  }
150 
151  /// Returns true iff the specified vertex list page is constant.
154  {
155  return !myList && myVertexLists.isPageConstant(UT_PageNum(pagenum));
156  }
157 
158  /// Returns the representative (first) vertex list for a "constant" page.
159  /// The page must be constant-compressed, i.e. isVertexListPageConstant
160  /// must return true.
161  /// NOTE: "constant" in this context really means that the vertex lists
162  /// all have the same vertex count, and represent contiguous vertices.
165  {
166  UT_ASSERT_P(myVertexLists.isPageConstant(pagenum));
167  auto p = myVertexLists.getPageData(pagenum);
168  UT_ASSERT_COMPILETIME(2*sizeof(*p) == sizeof(GA_OffsetListRef));
169  auto po = reinterpret_cast<const GA_OffsetListRef*>(p);
170  return *po;
171  }
172 
173  /// NOTE: This is safe to call from multiple threads as long as they aren't writing
174  /// to the same page, and hardenVertexListPageTable() has been called from
175  /// single-threaded code.
176  /// You must include GA_Primitive.h to use this.
177  /// @{
179  void setVertexList(GA_Offset primoff, const GA_OffsetListRef &vertices);
181  void setVertexList(GA_Offset primoff, const GA_OffsetList &vertices);
183  void setVertexList(GA_Offset primoff, GA_OffsetList &&vertices);
184  /// @}
185 
186  /// NOTE: This is not threadsafe. Also, this just hardens the table, not any pages.
188  {
189  if (!isFullRepresentation())
190  myVertexLists.hardenTable();
191  }
192 
193  /// NOTE: This is not threadsafe. It hardens all vertex list pages, if applicable.
194  void hardenAllVertexListPages();
195 
196  /// NOTE: This will only work if !isFullRepresentation()
197  /// NOTE: This is safe to call from multiple threads as long as pagenum is
198  /// different for each and hardenVertexListPageTable() has been called
199  /// outside threaded code.
200  GA_OffsetList *hardenVertexListPage(GA_PageNum pagenum);
201 
202  void merge(GA_Detail &dgeo, const GA_MergeMap &map);
203 
204  /// NOTE: Since the primitive maps of dstgeo and srcgeo must have already
205  /// been made equal by the time this is called.
206  void replace(GA_Detail &dstgeo, const GA_Detail &srcgeo);
207 
208  /// Called by GA_Detail::defragment when defragmenting the primitive
209  /// index map.
210  /// NOTE: This bumps the primitive list data ID.
211  void defragment(const GA_Defragment &defrag);
212 
213  /// Called by GA_Detail::defragment when defragmenting the vertex
214  /// index map.
215  /// NOTE: This bumps the primitive list data ID.
216  void defragmentVertices(const GA_Defragment &defrag);
217 
218  /// Copy any modified caches from the GPU back to CPU cache.
219  void flushCEWriteCaches(const GA_PrimitiveFactory &f);
220 
221  /// Copy any modified caches from the GPU to CPU. Then delete the GPU
222  /// cache.
223  void flushCECaches(const GA_PrimitiveFactory &f);
224 
225  /// Steal the CE buffers from the source primitive list.
226  void stealCEBuffers(const GA_PrimitiveList &src,
227  const GA_PrimitiveFactory &f);
228 
229  /// Save data to a JSON stream.
230  /// @section JSON-GA_PrimitiveList JSON Schema: GA_PrimitiveList
231  /// @code
232  /// {
233  /// "name" : "GA_PrimitiveList",
234  /// "description" : "An array of primitive objects",
235  /// "type" : "array",
236  /// "items" : { "$ref":"GA_Primitive" },
237  /// }
238  /// @endcode
239  /// @see @ref JSON_FileFormat, GA_Primitive
240  bool jsonSave(UT_JSONWriter &w, const GA_SaveMap &save) const;
241 
242  /// Load from a JSON stream
243  /// @see @ref JSON_FileFormat
244  bool jsonLoad(UT_JSONParser &p, GA_LoadMap &load, GA_Offset &load_end);
245 
246  /// Check to see whether the primitive list contains primitives of a given
247  /// type
249  { return myTracker.contains(type); }
250  /// Check to see whether the primitive list only contains primitives of a
251  /// given type
253  { return myTracker.containsOnly(types); }
254  /// Return the number of primitives of the given type
256  { return myTracker.count(type); }
257  /// Return the number of primitives of the given family
259  { return myTracker.countFamily(family); }
260  /// Test whether the primitive list contains any primitives that have a
261  /// local transform.
262  bool hasLocalTransform(const GA_PrimitiveFactory &factory) const
263  { return myTracker.hasLocalTransform(factory); }
264  /// Return the primitives of the given type. Unlike the functions
265  /// above which use myTracker, this function requires iterating through
266  /// all primitives.
267  bool getPrimitivesOfType(const GA_PrimitiveTypeId &type,
268  UT_Array<const GA_Primitive *> &prims) const;
269 
270  /// Use this to mark primitives or their intrinsic data as dirty.
271  void bumpDataId();
273  { return myDataID; }
274 
276  { return myTracker; }
277 
278  /// Force a rebuild of primitive counts. This is triggered if
279  /// primitives have changed their types without being added/removed
280  /// explicitly. Packed primitives, for example, are polymorphic
281  /// in this manner.
282  void rebuildTracker();
283 
284  /// Goes through the primitive list to confirm that it's in a consistent
285  /// state, returning true if it is, and false if it isn't.
286  /// This is only for debugging purposes.
287  bool validate(const GA_Detail &detail) const;
288 
289  /// Append to a run-length encoded array of pairs of a primitive type ID and
290  /// a count of those primitives. A detail with 5 polygons, followed
291  /// by 3 tetrahedra, followed by 4 polygons will yield:
292  /// {GA_PRIMPOLY, 5}, {GA_PRIMTETRAHEDRON, 3}, {GA_PRIMPOLY, 4}
293  void getPrimitiveTypeCounts(
294  UT_Array<std::pair<int,exint>> &type_count_pairs,
295  const GA_Range *range = nullptr) const;
296 
297  // NOTE: These functor classes must be in the scope of GA_PrimitiveList
298  // so that it can access GA_Primitive::unstashImpl,
299  // GA_PrimitiveDefinition::getConstructor, and
300  // GA_PrimitiveDefinition::getBlockConstructor.
301  // They have to be public so that UTparallelReduce
302  // can be instantiated for GCC with it.
303  class ga_ParallelCreateForMerge;
304  class ga_ParallelCreatePagedForMerge;
305  class ga_ReplacePrimitiveBlockParallel;
306 
307  void initVertexLists(
308  GA_Offset prim_block_start,
309  GA_Offset vertex_block_start,
310  GA_Size nprimitives,
311  GA_Size nvertices_each,
312  bool closed = false);
313  void initVertexLists(
314  GA_Offset prim_block_start,
315  GA_Offset vertex_block_start,
316  const GA_PolyCounts &vertex_counts,
317  bool closed = false);
318  /// First value of closed_span_lengths is the number with closed false.
319  /// To start with closed true, have a value of 0 first, then the number with closed true.
320  /// nullptr means closed false for all primitives.
321  void initVertexLists(
322  GA_Offset prim_block_start,
323  GA_Offset vertex_block_start,
324  const GA_PolyCounts &vertex_counts,
325  const exint *closed_span_lengths = nullptr,
326  const exint ncopies = 1);
327 
328 private:
329  void create(GA_Detail &detail,
330  const GA_PrimitiveDefinition &def,
332  bool check_stash);
333  void createBlock(GA_Detail &detail,
334  const GA_PrimitiveDefinition &def,
335  GA_Size nprimitives,
337  bool check_stash);
338 
339  /// To be called from GA_Detail::sortVertexMapByPrimitiveUse()
340  void sortVertexMapByPrimitiveUse(GA_IndexMap &vertex_map);
341 
342  /// @{
343  /// This class is non-copyable
345  const GA_PrimitiveList &operator=(const GA_PrimitiveList &);
346  /// @}
347 
348  bool loadPolyOrTetRun(
349  UT_JSONParser &p,
350  int runenum,
351  GA_Offset &primoff,
352  GA_Offset init_vtxoff,
353  GA_Detail &detail);
354  bool createLoadPrimitive(UT_JSONParser &p,
355  GA_LoadMap &load,
356  const UT_StringRef &type,
357  GA_Offset &load_offset,
358  const UT_StringArray *varying,
359  const GA_JSONUniformBlock &uniform);
360 
362  exint getMyListSize() const
363  {
364  return getMyPrimPtrSize(myList);
365  }
367  exint getMyStashedSize() const
368  {
369  return getMyPrimPtrSize(myStashedPrims);
370  }
372  static exint getMyPrimPtrSize(GA_Primitive**p)
373  {
374  UT_ASSERT_P(p);
375  return ((const exint*)p)[-1];
376  }
377  void reallocMyList(exint newsize);
379  void freeMyList();
380 
381  void clearVertexLists();
382  void destroy(GA_Offset off);
383 
384  GA_Primitive *const*hardenPrimitives() const;
385  /// This can be faster than hardenPrimitives, if we're calling from a
386  /// thread-unsafe function already.
387  GA_Primitive *const*hardenPrimitivesThreadUnsafe();
389  GA_Primitive *const*hardenPrimitivesImpl(bool parallel) const;
390  class HardenPrimitivesFunctor;
391 
392  void dump() const;
393 
394  friend class GA_Detail;
395 
396  /// This is nullptr when using myVertexLists and myPrimitiveTypes.
397  /// It has an exint indicating the size immediately before
398  /// where it points in memory.
399  mutable GA_Primitive **myList;
400 
401  GA_Detail &myDetail;
402  GA_PageArray<int,1,false,false> myPrimitiveTypes;
403  GA_PageArray<int64,2,false,false> myVertexLists;
404  mutable UT_TaskExclusive<HardenPrimitivesFunctor> myHardenExclusive;
405 
406  GA_PrimitiveTracker myTracker;
407  GA_DataId myDataID;
408 
409  /// Array of temporarily stashed primitives.
410  /// This is only used to reduce overhead of freeing and
411  /// reallocating primitives if it's likely that the
412  /// detail is going to be rebuilt with the same primitive
413  /// types in the same order as the previous primitives.
414  /// It has an exint indicating the size immediately before
415  /// where it points in memory.
416  mutable GA_Primitive **myStashedPrims;
417 };
418 
419 #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:687
bool GAisValid(GA_Size v)
Definition: GA_Types.h:649
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:35
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
exint GA_Size
Defines the bit width for index and offset types in GA.
Definition: GA_Types.h:235
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:641
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
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
GA_Size GA_PageNum
Definition: GA_Types.h:644
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
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.
type
Definition: core.h:1059
GLenum src
Definition: glcorearb.h:1793