HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GR_UtilsVK.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: GR_UtilsVK.h ( GR Library, C++)
7  *
8  * COMMENTS:
9  * Utility functions for Vulkan GR_GeoRenders.
10  */
11 
12 #ifndef GR_UtilsVK_h
13 #define GR_UtilsVK_h
14 
15 #include "GR_API.h"
16 #include "GR_Defines.h"
17 
18 #include <UT/UT_Map.h>
19 #include <UT/UT_StringHolder.h>
20 #include <UT/UT_UniquePtr.h>
21 #include <UT/UT_ScopeExit.h>
22 #include <UT/UT_VectorTypes.h>
23 #include <GT/GT_Primitive.h>
24 #include <GT/GT_Types.h>
25 
26 #include <RV/RV_Type.h>
27 #include <RV/RV_Render.h>
28 
29 #include "GR_Uniforms.h"
30 
31 
32 class GR_DisplayOption;
33 class GR_GeoRender;
34 class GR_UpdateParms;
35 
36 class GT_PrimCurveMesh;
37 
38 class RV_Instance;
39 class RV_Geometry;
40 class RV_Render;
41 class RV_ShaderAtlas;
42 class RV_ShaderBlock;
43 class RV_ShaderProgram;
46 class RV_VKBuffer;
47 
48 
49 class RE_CacheVersion;
50 
51 namespace GR_Utils
52 {
54 {
55  switch(s)
56  {
57  case GT_STORE_UINT8: return RV_GPU_UINT8;
58  case GT_STORE_INT8: return RV_GPU_INT8;
59  case GT_STORE_INT32: return RV_GPU_INT32;
60  case GT_STORE_INT64: return RV_GPU_INT32; // no such 64b type
61  case GT_STORE_REAL16: return RV_GPU_FLOAT16;
62  case GT_STORE_REAL32: return RV_GPU_FLOAT32;
63  case GT_STORE_REAL64: return RV_GPU_FLOAT64;
64  case GT_STORE_STRING: return RV_GPU_INT32; // string indices
65  default:
66  UT_ASSERT(!"No available RV type");
67  return RV_GPU_UINT1;
68  break;
69  }
70 }
71 
72 
73 /// Returns the GPU type and vector size of the attribute based on the
74 /// data array, display option settings and supported Vulkan capabilities.
76  const char *attrib_name,
77  const GT_DataArrayHandle &pa,
78  const GR_DisplayOption &opts,
79  RV_AttributeType array_type,
80  int &out_vsize,
81  bool &out_isnormalized);
82 
83 // Allocate a CPU buffer, convert the data from the GT_Data into the correct
84 // format for upload, and place it in the new buffer
85 GR_API extern void * fillAttribData(RV_Render *r,
86  const char *attrib_name,
87  const GT_DataArrayHandle &pa,
88  const GR_DisplayOption &opts,
89  RV_AttributeType array,
90  bool build_string_tables = true,
91  const UT_Span<uint8> &out_data = UT_Span<uint8>());
92 
94  RV_Geometry *geo,
95  const GR_UpdateParms &p,
96  RE_CacheVersion top_ver,
97  GT_DataArrayHandle prim_id,
98  GT_DataArrayHandle pnt_id,
99  GT_DataArrayHandle vert_id,
100  bool is_offset = true,
101  int inst_per_prim = 1,
102  UT_Array<uint8> *selected = nullptr);
103 
104 GR_API extern bool createOrReuseSet(RV_Render* r,
106  int set_num,
108  bool* created = nullptr,
109  const char* name = nullptr);
110 GR_API extern bool initBuiltinBlock(RV_Render* r,
112  const char* name,
115  uint32_t array_size = 0);
116 GR_API extern void loadAtlas(RV_Instance *inst,
117  RV_ShaderAtlas &atlas,
118  UT_Map<exint,RV_ShaderProgram*> &programmap);
119 
120 
121 GR_API extern void buildCurvePrimInfo(const GT_PrimCurveMesh *cmesh,
122  const GR_UpdateParms &p,
123  RV_Geometry* geo,
124  GR_GeoRender* gr,
125  RE_CacheVersion geo_version,
127  UT_Int32Array* opt_curve_oder = nullptr);
128 
129 template <typename Range, typename Body>
130 void renderParallelFor(RE_RenderContext main_rc, const Range &range, const Body &body,
131  int subscribe_ratio = 2,
132  int min_grain_size = 1)
133 {
134  exint size = UTestimatedNumItems(range);
135  UT_ASSERT(main_rc.isVulkan() || size == 0);
136  if (size == 0)
137  return;
138 
139  if (!main_rc.isVulkan())
140  {
141  body(main_rc, range);
142  return;
143  }
144 
145 #ifdef USE_VULKAN
146  // Vulkan Pre-amble: quite out if task is too small or MT is disabled
147  int nthreads = SYSmin(
148  main_rc.vkRender()->getNumRenderThreads(),
150 
151  // grain size to make tasks 1-to-1 with threads
152  exint grain = SYSmax(1, (size/nthreads + ((size%nthreads) ? 1 : 0)));
153 
154  bool do_parallel = (nthreads > 1) && (grain >= min_grain_size);
155  if (!do_parallel)
156  {
157  body(main_rc, range);
158  return;
159  }
160 
161  RV_Render* main_r = main_rc.vkRender();
162  bool initial_split = main_r->isMainRender();
163  UT_ASSERT(!(main_r->isMainRender() && main_r->isThreading()));
164  UT_ASSERT(!(main_r->isMainRender() && !UT_Thread::isMainThread()));
165 
166  if (initial_split)
167  {
168  main_r->enableThreadedRender();
169  GR_Uniforms::prepareThreadedUniforms(nthreads);
170  }
172  if (initial_split)
173  {
174  GR_Uniforms::returnThreadedUniforms();
175  main_r->endThreadedRender();
176  }
177  });
178 
179  // Copy state for thread -- don't want to grab directly from thread
180  // in case we're called from a worker thread, and it's being modified
181  GR_Uniforms* main_u = main_rc.uniforms();
182  GR_Uniforms::ObjectUniforms objects = main_u->objects();
183  GR_Uniforms::GlobalUniforms globals = main_u->globals();
184 
185  RV_Render::RenderState render_state = main_r->getRenderState();
186 
187  auto parallel_body = [&](const UT_BlockedRange<exint> &range)
188  {
189  int u_count = 0;
190  int r_count = 0;
191  int r_idx = -1;
192  RV_Render* r = main_r->getThreadedRender(r_count, r_idx);
193  GR_Uniforms* u = GR_Uniforms::getForThread(&u_count, r_idx);
194  RE_RenderContext rc(nullptr, r, u);
195 
196  // setup Render
197  exint vk_frame = r->beginFrame();
198  UT_ASSERT( vk_frame >= 2); // should have already been called by `enableThreadedRender()`
199  r->copyRenderState(&render_state);
200 
201  // cleanup Render
202  UT_ScopeExit scope_name([&](){
203  if (vk_frame <= 2)
204  {
205 #ifdef WIP_VULKAN_DEFER_DRAW
206  //// If deferring draws them run them all within current CB
207  if (r->myIsDeferring)
208  {
209  r->runDraws();
210  r->clearDraws();
211  }
212 #endif // WIP_VULKAN_DEFER_DRAW
213  }
214  r->endFrame(vk_frame);
215  r->returnThreadedRender(r_count);
216  });
217 
218  // setup uniform
219  u->init(rc);
220  exint l = u->pushObjectUniforms();
221  u->objects() = objects;
222  if ( memcmp(&((const GR_Uniforms*)u)->globals(), &globals, sizeof(globals)))
223  u->globals() = globals;
224 
225  // cleanup uniform
227  u->popObjectUniforms(l);
228  GR_Uniforms::returnForThread(&u_count);
229  });
230 
231  body(rc, range);
232  };
233 
234 #define USE_ARENA
235 
236 #ifdef USE_ARENA
237  // with arena limit, can oversubscribe tasks
238  // NOTE: still need to specifiy grain size manually, since the
239  // grain calculation in `UTparallelFor` is based on total
240  // processor count, not limited by arena
241  if (subscribe_ratio > 1)
242  grain = SYSmax(min_grain_size, grain / subscribe_ratio);
243 
244  main_r->getTaskArena().execute([&](){
245  UTparallelFor(range, parallel_body, 0, grain);
246  });
247 
248  // need to restore state, most state is pushed/popped in
249  // `parallel_body()`, but some can't be yet, so reset here
250  main_r->copyRenderState(&render_state);
251  if ( memcmp(&((const GR_Uniforms*)main_u)->globals(), &globals, sizeof(globals)))
252  main_u->globals() = globals;
253 #else
254  // use caclulated grain to force grain size
255  // will limit the number of threads used
256  // -- can't call nested though, if it is called
257  // while threading, just run the body directrly
258  if (initial_split)
259  {
260  UTparallelFor(range, parallel_body, 0, grain);
261  }
262  else
263  {
264  body(main_rc, range);
265  }
266 #endif
267 #endif // USE_VULKAN
268 }
269 
270 }
271 
273 {
274 public:
275  GR_InstanceBuffer(const char *name,
277  int vsize,
278  int ninstances,
279  int step = 1,
280  bool normalized = true)
281  : AttribName(name),
282  Type(type),
283  VectorSize(vsize),
284  NumInstances(ninstances),
285  InstanceStep(step),
287  {}
288 
289  void init(RV_Render *r, int entries);
290  void initCPUMapped(RV_Render *r, int entries, bool cpu_mapped = true);
291 
295  int VectorSize = 4;
296  int NumInstances = 1;
297  int InstanceStep = 1;
298  bool NormalizedFormat = true;
299 
301 };
302 
303 #endif
A collection of Vulkan UBO, SSBO, and Image shader bindings (descriptor set)
#define SYSmax(a, b)
Definition: SYS_Math.h:1582
GT_Storage
Definition: GT_Types.h:19
void UTparallelFor(const Range &range, const Body &body, const int subscribe_ratio=2, const int min_grain_size=1, const bool force_use_task_scope=true)
void init(RV_Render *r, int entries)
GA_API size_t UTestimatedNumItems(const GA_PolyCounts::Range &range)
#define UT_AT_SCOPE_EXIT(...)
Definition: UT_ScopeExit.h:95
GR_API void loadAtlas(RV_Instance *inst, RV_ShaderAtlas &atlas, UT_Map< exint, RV_ShaderProgram * > &programmap)
RV_GPUType getRVType(GT_Storage s)
Definition: GR_UtilsVK.h:53
GLenum GLint * range
Definition: glcorearb.h:1925
GR_API void buildCurvePrimInfo(const GT_PrimCurveMesh *cmesh, const GR_UpdateParms &p, RV_Geometry *geo, GR_GeoRender *gr, RE_CacheVersion geo_version, UT_Vector4iArray &data, UT_Int32Array *opt_curve_oder=nullptr)
RV_Render * vkRender()
int64 exint
Definition: SYS_Types.h:125
Object that represents drawable geometry. This object holds vertex, instancing and index buffers for ...
Definition: RV_Geometry.h:165
GLdouble s
Definition: glad.h:3009
UT_ScopeExit which runs the given lambda on destruction.
Definition: UT_ScopeExit.h:28
RV_Render * getThreadedRender(int &out_depth, int &out_idx)
Temporary container for either a RV_Render and an RE_Render.
GR_API bool createOrReuseSet(RV_Render *r, UT_UniquePtr< RV_ShaderVariableSet > &set, int set_num, const RV_ShaderProgramBase *shader, bool *created=nullptr, const char *name=nullptr)
A mesh of curves.
void endFrame(int frame_depth)
int getNumRenderThreads() const
Get desired number of threads to use for parallel rendering.
GR_API void * fillAttribData(RE_Render *r, const char *attrib_name, const GT_DataArrayHandle &pa, const GR_DisplayOption &opts, RE_ArrayType array, bool build_string_tables=true)
void enableThreadedRender()
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
void returnThreadedRender(int depth)
set of parameters sent to GR_Primitive::update()
UT_UniquePtr< RV_VKBuffer > Buffer
Definition: GR_UtilsVK.h:292
int beginFrame()
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
RV_AttributeType
Definition: RV_Type.h:99
constexpr auto set(type rhs) -> int
Definition: core.h:610
bool isMainRender() const
check whether this RV_Render is doing a threaded task
static int getNumProcessors()
#define GR_API
Definition: GR_API.h:10
GLuint const GLchar * name
Definition: glcorearb.h:786
GLint GLenum GLboolean normalized
Definition: glcorearb.h:872
Handle to the main interface of Vulkan.
Definition: RV_Instance.h:44
GR_InstanceBuffer(const char *name, RV_GPUType type, int vsize, int ninstances, int step=1, bool normalized=true)
Definition: GR_UtilsVK.h:275
GR_Uniforms * uniforms()
GLsizeiptr size
Definition: glcorearb.h:664
GLuint shader
Definition: glcorearb.h:785
bool isThreading() const
check whether this RV_Render is doing a threaded task
static int isMainThread()
Definition: UT_Thread.h:116
RV_GPUType
Definition: RV_Type.h:40
GR_API bool initBuiltinBlock(RV_Render *r, UT_UniquePtr< RV_ShaderBlock > &block, const char *name, RV_ShaderVariableSet *set, const RV_ShaderProgramBase *shader, uint32_t array_size=0)
RV_GPUType Type
Definition: GR_UtilsVK.h:294
GR_API RE_GPUType getAttributeType(RE_Render *r, const char *attrib_name, int &vsize, const GT_DataArrayHandle &pa, const GR_DisplayOption &opts, RE_ArrayType array_type)
GR_API GR_SelectMode buildInstSelectInfo(RE_Render *r, RE_Geometry *geo, const GR_UpdateParms &p, RE_CacheVersion top_ver, GT_DataArrayHandle primid, GT_DataArrayHandle vtxid, GT_DataArrayHandle vertid, bool is_offsets=true, int instances_per_prim=1, UT_Array< uint8 > *result=NULL)
UT_StringHolder AttribName
Definition: GR_UtilsVK.h:293
void runDraws()
Simple class for a mutli-integer cache tag.
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
GLboolean r
Definition: glcorearb.h:1222
set of parameters sent to GR_Primitive::update()
Definition: GR_Uniforms.h:56
RenderState getRenderState()
A vulkan buffer object.
Definition: RV_VKBuffer.h:81
void copyRenderState(RV_Render *other)
Copy render state from another RV_Render.
bool myIsDeferring
Definition: RV_Render.h:349
void initCPUMapped(RV_Render *r, int entries, bool cpu_mapped=true)
#define SYSmin(a, b)
Definition: SYS_Math.h:1583
Declare prior to use.
bool isVulkan() const
UT_NON_COPYABLE(GR_InstanceBuffer)
void endThreadedRender()
Definition: format.h:1821
void renderParallelFor(RE_RenderContext main_rc, const Range &range, const Body &body, int subscribe_ratio=2, int min_grain_size=1)
Definition: GR_UtilsVK.h:130
void clearDraws()
GR_SelectMode
Definition: GR_Defines.h:243