HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RV_VKPipeline.h
Go to the documentation of this file.
1 
2 /*
3  * PROPRIETARY INFORMATION. This software is proprietary to
4  * Side Effects Software Inc., and is not to be reproduced,
5  * transmitted, or disclosed in any way without written permission.
6  *
7  * NAME: RV_VKPipeline.h ( RV Library, C++)
8  *
9  * COMMENTS:
10  * Class to handle creating Vulkan Pipeline Objects
11  */
12 
13 #ifndef RV_VKPipeline_h
14 #define RV_VKPipeline_h
15 
16 #include "RV_API.h"
17 
18 #include <utility>
19 
20 #include <UT/UT_Array.h>
21 #include <UT/UT_Assert.h>
22 #include <UT/UT_FixedArray.h>
23 #include <UT/UT_Rect.h>
24 #include <UT/UT_Set.h>
25 #include <UT/UT_SmallArray.h>
26 #include <UT/UT_Span.h>
27 #include <UT/UT_Tuple.h>
28 
29 #include <VE/VE_VK.h>
30 #include "RV_Type.h"
31 #include "RV_TypePtrs.h"
32 #include "RV_Instance.h"
33 #include "RV_VKEnum.h"
34 #include "RV_VKFramebuffer.h"
35 
36 class RV_VKCommandBuffer;
37 class RV_VKImage;
40 
41 typedef std::pair<float, float> RV_DepthRange;
42 
43 inline VkViewport
45  const UT_DimRect& view_rect,
46  RV_DepthRange depth_range = {0.f, 1.f})
47 {
48  return VkViewport{
49  (float)view_rect.x(),
50  (float)view_rect.y(),
51  (float)view_rect.width(),
52  (float)view_rect.height(),
53  depth_range.first,
54  depth_range.second
55  };
56 }
57 inline VkRect2D RVmakeVkRect(const UT_DimRect& rect)
58 {
59  return VkRect2D {
60  {(int32_t)rect.x(),
61  (int32_t)rect.y()},
62  {(uint32_t)rect.width(),
63  (uint32_t)rect.height()}
64  };
65 }
66 
67 // PipelineStateInfo tracks the rest of the info needed to create a pipeline object such as:
68 // - which proerties are in dynamic state
69 // - Final Ouptut formats (e.g. UINT vs FLOAT, and Multisamples)
70 // - multiview sate
71 // - specialization constants
72 // - etc.
73 //
74 // Where possible, will try to keep properties in dynamic state.
75 // Unlinke OpenGL there are still some Rendering Properties that cannot be set dynamically
76 // and must be baked into the pipeline:
77 // - Blend Function
78 // - Output buffer Format
79 
81 {
82  switch (t)
83  {
85  return RV_TOPOLOGY_POINT;
90  return RV_TOPOLOGY_LINE;
96  return RV_TOPOLOGY_TRIANGLE;
98  return RV_TOPOLOGY_PATCH;
99  default: break;
100  }
101  UT_ASSERT(false && "Unrecognized Topology Type used for Pipeline");
102  return RV_TOPOLOGY_UNKNOWN;
103 }
104 
106 {
107  return RVgetTopologyClass(lhs) == RVgetTopologyClass(rhs);
108 }
109 
110 
111 // Generally you will:
112 // 1) bind vertex buffers
113 // 2) bind output targets
114 // 3) set rendering state (e.g. blend mode)
115 //
116 // 4) and 5) will need separate info/object classes
117 // e.g.
118 // i.e. info that describes the format (needed for creation)
119 //
120 
121 // d) bind pipeline_layout to draw
122 // when you go to draw the fully realized pipeline will be found or created
123 
124 // Output Targets must be specified as:
125 // a) Renderpass + subpass
126 // b) DynamicRendering info during creation
127 // The actual info needed is:
128 // - Array of Color Format
129 // - Depth/stencil/DepthStencil Format
130 // - ResolveAttachment
131 // - MultiSampleState
132 
133 // Using explicit members rather than VkStructs so
134 // that it's more obvious which parameters are used
135 //
136 
137 // Will be used in three places:
138 // 1) Generated from the current Rendering state
139 // 2) Storing the current CommandBuffer state
140 // 3) in the creation/cache of pipeline objects
141 // 1 and 2 will usually be in sync, except in cases
142 // where the CB state is overwritten (e.g. applying a pipeline
143 // with static state, or begining a new CB recording)
144 //
145 // the isXXXDynamic flags mean different things in context:
146 // 1) - It is part of the availible dynamic state. We always
147 // try to keep as much state as we can dynamic
148 // 2) - It has been set as part of the dynamic state in the
149 // CB. It may be undefined when the CB begins recording,
150 // or if it is clobbered by the static state of a pipeline
151 // 3) - It is part of the dynamic state of the pipeline,
152 // so value will be ignored during pipeline creation
153 //
154 // Push/Set commands in the RenderState will update the current state
155 // Just before drawing, a pipeline is selected/built from cache using
156 // Just before drawing, the state in the CB is updated using the current
157 // render state
158 //
160 {
161 public:
162  RV_VKPipelineStateInfo() = default;
163 
166 
167  // Set all state which can be dynamic, to be dynamic
168  // Uses inst to check which Dynamic states are
169  // supported
170  // Used to initilaize Rendering State
171  void initDynamicState(const RV_Instance* inst);
172 
173  // Write the state to a commandBuffer
174  // TODO: maybe should be a func for the CB instead?
175  void updateCBRenderingState(RV_VKCommandBuffer& cb);
176 
177  // ~~~~
178  // Renderpass State
179  // ~~~~
181  {
182  myRenderPassInfo = info;
183  mySampleCount = info.mySamples;
184  }
185 
186  void setRenderRegion(const UT_DimRect& region)
187  {
188  myViewport = region;
189  myScissor = region;
190  }
191 
193 
194  // ~~~~
195  // Vertex Input State
196  // ~~~~
197 
198  // NOTE: the input layout (i.e. the location, names, types) is
199  // part of the pipeline layout, so the location + names
200  // here must match those
201  // Requires `VK_EXT_vertex_input_dynamic_state` to set dynamically
202  // uses `VK_DYNAMIC_STATE_VERTEX_INPUT_EXT`
203  //
204  // Can also set JUST the binding stride dynamically
205  // using `VK_EXT_extended_dynamic_state`
206  bool myIsVertexInputDynamic = false;
207 
208  // ~~~~
209  // Input Assembly
210  // ~~~~
211 
212  // from `VkPipelineInputAssemblyStateCreateInfo`
213  bool myIsTopologyDynamic = false;
215 
216  bool myIsPrimRestartDynamic = false;
217  bool myPrimitiveRestartEnable = false;
218 
219  // from `VkPipelineTesselationStateCreateInfo`
220  bool myHasTesselation = false;
221  bool myIsControlPointsDynamic = false;
222  uint32_t myTessControlPoints = 4;
223 
224  // ~~~~
225  // Viewport State
226  // ~~~~
227 
228  // From `ViewportStateCreateInfo`
229  bool myIsViewportDynamic = false;
231  RV_DepthRange myDepthRange = {0.f ,1.f};
232 
233  bool myIsScissorDynamic = false;
235 
236  // ~~~~
237  // Rasterization State
238  // ~~~~
239 
240  // From `VkPipelineRasterizationStateCreateInfo`
241  bool myDepthClamp = false;
243 
244  bool myIsRasterDiscardDynamic = false;
245  bool myRasterDiscard = false;
246 
247  bool myIsCullModeDynamic = false;
249 
250  bool myIsFrontFaceDynamic= false;
252 
253  bool myIsBiasDynamic = false;
254  bool myDepthBiasEnable = false;
255 
256  bool myIsBiasParamDynamic= false;
257  float myBiasConst = 0.f;
258  float myBiasClamp = 0.f;
259  float myBiasSlope = 0.f;
260 
261  bool myIslineWidthDynamic = false;
262  float myLineWidth = 1.f;
263 
264  // From VkPipelineMultisampleStateCreateInfo
265  int mySampleCount = -1;
266  uint32 mySampleMask = 0xffffffff;
267 
268  // ~~~~
269  // Depth Stencil State
270  // ~~~~
271 
272  // From VkPipelineDepthStencilStateCreateInfo
273  bool myIsDepthTestDynamic = false;
274  bool myDepthTest = true;
275 
276  bool myIsDepthWriteDynamic = false;
277  bool myDepthWrite = true;
278 
279  bool myIsDepthOpDynamic = false;
281 
282  bool myIsDepthBoundsEnableDynamic = false;
283  bool myDepthBoundsTest = false;
284 
285  bool myIsDepthBoundsDynamic = false;
286  float myMinDepth = 0.f;
287  float myMaxDepth = 1.f;
288 
289  bool myIsStencilTestDynamic = false;
290  bool myStencilTest = false;
291 
292  bool myIsStencilOpDynamic = false;
293  bool myIsStencilWriteMaskDynamic = false;
294  bool myIsStencilCompMaskDynamic = false;
295  bool myIsStencilRefDynamic = false;
296 
297  VkStencilOpState myStencilOpFront =
298  {
299  VK_STENCIL_OP_KEEP, /* failOp */
300  VK_STENCIL_OP_KEEP, /* passOp */
301  VK_STENCIL_OP_KEEP, /* depthFailOp */
302  VK_COMPARE_OP_ALWAYS, /* compareOp */
303  0xffffffff, /* compareMask */
304  0xffffffff, /* writeMask */
305  0 /* reference */
306  };
307  VkStencilOpState myStencilOpBack =
308  {
309  VK_STENCIL_OP_KEEP, /* failOp */
310  VK_STENCIL_OP_KEEP, /* passOp */
311  VK_STENCIL_OP_KEEP, /* depthFailOp */
312  VK_COMPARE_OP_ALWAYS, /* compareOp */
313  0xffffffff, /* compareMask */
314  0xffffffff, /* writeMask */
315  0 /* reference */
316  };
317 
318  // ~~~~
319  // Blend State
320  // ~~~~
321  // From VkPipelineColorBlendStateCreateInfo
322  bool myLogicOpEnable = false;
324 
326  VK_FALSE, /* blendEnable */
327  VK_BLEND_FACTOR_ONE, /* srcColorBlendFactor */
328  VK_BLEND_FACTOR_ZERO, /* dstColorBlendFactor */
329  VK_BLEND_OP_ADD, /* colorBlendOp */
330  VK_BLEND_FACTOR_ONE, /* srcAlphaBlendFactor */
331  VK_BLEND_FACTOR_ZERO, /* dstAlphaBlendFactor */
332  VK_BLEND_OP_ADD, /* alphaBlendOp */
336  VK_COLOR_COMPONENT_A_BIT , /* colorWriteMask */
337  };
338 
339  bool myIsBlendConstDynamic = false;
340  float myBlendConst[4] = {0.f, 0.f, 0.f, 0.f};
341 
342  // ~~~~~~
343  // Operators
344  // ~~~~~~
345 
346  friend bool operator==(
347  const RV_VKPipelineStateInfo& lhs,
348  const RV_VKPipelineStateInfo& rhs);
349 
351 };
352 
354 {
356  {
359  }
360 
363 
364  // equivalent to glAttribPointer()
365  /// Add Info for Attribute from Vertex Array
366  /// location is the ID of the attribute set/queried from the shader
367  /// Binding is the binding point of the array to pull data from
368  // Equivalent to
370  {
373  }
375  uint32_t location,
376  uint32_t binding,
378  uint32_t offset)
379  {
380  myInputAttributes.forcedRef(location)
382  {location, binding, format, offset};
383  }
384  //
385  // Adding a new binding is equivalent to using a new array with `glBindVertexArray`
387  uint32_t binding,
388  uint32_t stride,
390  {
391  myInputBindings.forcedRef(binding)
393  { binding, stride, input_rate};
394  }
395 
397  UT_Array<VkVertexInputBindingDescription>& final_bindings) const
398  {
399  // trim bindings to only used ones
400  UT_Set<uint32_t> used_bindings;
401  for (const auto &attr : myInputAttributes)
402  {
403  if (attr.format != VK_FORMAT_UNDEFINED)
404  used_bindings.insert(attr.binding);
405  }
406  final_bindings.setCapacity(used_bindings.size());
407  final_bindings.setSize(0);
408  for (uint32_t binding : used_bindings)
409  {
410  final_bindings.append(myInputBindings[binding]);
411  }
412  }
413 
415  UT_Array<VkVertexInputAttributeDescription>& final_attributes) const
416  {
417  // trim attributes to valid ones
418  final_attributes = myInputAttributes;
419  final_attributes.removeIf([](const VkVertexInputAttributeDescription& attr)
420  {
421  return attr.format == VK_FORMAT_UNDEFINED;
422  });
423  }
424 
425  friend bool operator==(
426  const RV_VKPipelineInputInfo& lhs,
427  const RV_VKPipelineInputInfo& rhs);
428 
429 };
430 
431 // ----------------
432 // RV_VKPipeline
433 //
434 /// RAII wrapper class for VkPipeline
435 //
436 // Doesn't contain the create info used to make the pipeline,
437 // instead an owning class (e.g. RV_ShaderProgram) will keep that
439 {
440 public:
441  VkPipeline getVkPipeline() { return myVkPipeline; }
442 
443  static RV_VKPipelinePtr create(
444  RV_Instance* inst,
445  const RV_VKPipelineLayout& layout_info,
446  const RV_VKPipelineStateInfo& state_info,
447  const RV_VKPipelineInputInfo& input_info);
448 
450  RV_Instance* inst,
451  const RV_VKPipelineLayout& layout);
452 
453  // CAN have null state
455  : myInst(nullptr), myVkPipeline(VK_NULL_HANDLE)
456  {}
457  RV_VKPipeline(RV_Instance* inst, VkPipeline vk_pipeline)
458  : myInst(inst), myVkPipeline(vk_pipeline)
459  {}
460 
461  // disable copy semantics
462  RV_VKPipeline(const RV_VKPipeline&) = delete;
463  RV_VKPipeline& operator=(RV_VKPipeline& ) = delete;
464 
465  // enable move semantics
466  RV_VKPipeline(RV_VKPipeline&& other) noexcept
467  : myInst(other.myInst), myVkPipeline(other.myVkPipeline)
468  {
469  other.myInst = nullptr;
470  other.myVkPipeline = VK_NULL_HANDLE;
471  }
472 
473  // Destroy Resource Handle on destruction
475  {
476  if (myVkPipeline != VK_NULL_HANDLE)
477  {
478  VkDevice vk_dev = myInst->getDevice();
479  ::vkDestroyPipeline(vk_dev, myVkPipeline, nullptr);
480  }
481  }
482 
483 private:
484  RV_Instance* myInst = nullptr;
485  VkPipeline myVkPipeline = VK_NULL_HANDLE;
486 };
487 
488 RV_API
489 void RVloadSpirvFiles(
490  RV_Instance* inst,
491  const UT_StringArray& filenames,
492  UT_Array<RV_VKShaderModulePtr> &shader_modules);
493 
494 RV_API
495 void RVloadSpirvFiles(
496  RV_Instance* inst,
497  const char* filenames,
498  UT_Array<RV_VKShaderModulePtr> &shader_modules);
499 
500 #endif
501 
VkPrimitiveTopology
Definition: vulkan_core.h:1957
Definition: UT_Set.h:58
RV_VKPipeline & operator=(RV_VKPipeline &)=delete
#define VK_NULL_HANDLE
Definition: vulkan_core.h:45
VKAPI_ATTR void VKAPI_CALL vkDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator)
UT_Array< VkVertexInputBindingDescription > myInputBindings
static RV_VKPipelinePtr createCompute(RV_Instance *inst, const RV_VKPipelineLayout &layout)
void addVertexBinding(uint32_t binding, uint32_t stride, VkVertexInputRate input_rate=VK_VERTEX_INPUT_RATE_VERTEX)
static RV_VKPipelinePtr create(RV_Instance *inst, const RV_VKPipelineLayout &layout_info, const RV_VKPipelineStateInfo &state_info, const RV_VKPipelineInputInfo &input_info)
friend bool operator==(const RV_VKPipelineInputInfo &lhs, const RV_VKPipelineInputInfo &rhs)
VkFlags VkCullModeFlags
Definition: vulkan_core.h:2630
RV_VKPipeline(RV_VKPipeline &&other) noexcept
void setCapacity(exint new_capacity)
std::pair< float, float > RV_DepthRange
Definition: RV_VKPipeline.h:39
void setSize(exint newsize)
Definition: UT_Array.h:666
VkPolygonMode
Definition: vulkan_core.h:1972
VkFrontFace
Definition: vulkan_core.h:1945
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:137
void getInputBindings(UT_Array< VkVertexInputBindingDescription > &final_bindings) const
GLintptr offset
Definition: glcorearb.h:665
IMATH_NAMESPACE::V2f float
void addVertexAttribute(uint32_t location, uint32_t binding, VkFormat format, uint32_t offset)
VkCompareOp
Definition: vulkan_core.h:1846
void setRenderRegion(const UT_DimRect &region)
RAII wrapper class for VkPipeline.
GLint GLint GLsizei GLint GLenum format
Definition: glcorearb.h:108
GLint GLenum GLboolean GLsizei stride
Definition: glcorearb.h:872
#define RV_API
Definition: RV_API.h:10
GLint location
Definition: glcorearb.h:805
void setRenderPassInfo(const RV_RenderPassFormatInfo &info)
int x() const
Get lower-left corner.
Definition: UT_Rect.h:226
VkVertexInputRate
Definition: vulkan_core.h:1951
exint removeIf(IsEqual is_equal)
Handle to the main interface of Vulkan.
Definition: RV_Instance.h:38
exint append()
Definition: UT_Array.h:142
GLdouble t
Definition: glad.h:2397
int width() const
Get width/height dimensions.
Definition: UT_Rect.h:248
VkPipeline getVkPipeline()
RV_RenderPassFormatInfo myRenderPassInfo
RV_VKPipeline(RV_Instance *inst, VkPipeline vk_pipeline)
RV_TopologyClass
Definition: RV_Type.h:394
RV_TopologyClass RVgetTopologyClass(VkPrimitiveTopology t)
Definition: RV_VKPipeline.h:80
VkLogicOp
Definition: vulkan_core.h:1992
LeafData & operator=(const LeafData &)=delete
VkRect2D RVmakeVkRect(const UT_DimRect &rect)
Definition: RV_VKPipeline.h:57
int y() const
Get lower-left corner.
Definition: UT_Rect.h:227
VkFormat
Definition: vulkan_core.h:1386
unsigned int uint32
Definition: SYS_Types.h:40
RV_API void RVloadSpirvFiles(RV_Instance *inst, const UT_StringArray &filenames, UT_Array< RV_VKShaderModulePtr > &shader_modules)
VkDevice getDevice()
Get the raw vulkan device assocated with this instance.
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
int height() const
Get width/height dimensions.
Definition: UT_Rect.h:249
UT_UniquePtr< RV_VKPipeline > RV_VKPipelinePtr
Definition: RV_TypePtrs.h:64
bool RVisSameTopologyClass(VkPrimitiveTopology lhs, VkPrimitiveTopology rhs)
T & forcedRef(exint i)
Definition: UT_Array.h:801
UT_Array< VkVertexInputAttributeDescription > myInputAttributes
void clear()
Resets list to an empty list.
Definition: UT_Array.h:729
VkViewport RVmakeViewport(const UT_DimRect &view_rect, RV_DepthRange depth_range={0.f, 1.f})
Definition: RV_VKPipeline.h:44
void getInputAttributes(UT_Array< VkVertexInputAttributeDescription > &final_attributes) const
#define VK_FALSE
Definition: vulkan_core.h:124