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