• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef _VKPIPELINECONSTRUCTIONUTIL_HPP
2 #define _VKPIPELINECONSTRUCTIONUTIL_HPP
3 /*------------------------------------------------------------------------
4  * Vulkan Conformance Tests
5  * ------------------------
6  *
7  * Copyright (c) 2021 The Khronos Group Inc.
8  * Copyright (c) 2023 LunarG, Inc.
9  * Copyright (c) 2023 Nintendo
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  *
23  *//*!
24  * \file
25  * \brief Wrapper that can construct monolithic pipeline or use
26           VK_EXT_graphics_pipeline_library for pipeline construction or use
27           VK_EXT_shader_object for shader objects.
28  *//*--------------------------------------------------------------------*/
29 
30 #include "vkRef.hpp"
31 #include "vkDefs.hpp"
32 #include "tcuDefs.hpp"
33 #include "deSharedPtr.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkShaderObjectUtil.hpp"
36 #include <vector>
37 #include <stdexcept>
38 
39 namespace vk
40 {
41 
42 enum PipelineConstructionType
43 {
44     PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC = 0, // Construct legacy - monolithic pipeline
45     PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY, // Use VK_EXT_graphics_pipeline_library and construct pipeline out of several pipeline parts.
46     PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY, // Same as PIPELINE_CONSTRUCTION_TYPE_OPTIMISED_LIBRARY but with fast linking
47     PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_UNLINKED_SPIRV, // Use VK_EXT_shader_object unlinked shader objects from spirv
48     PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_UNLINKED_BINARY, // Use VK_EXT_shader_object unlinked shader objects from binary
49     PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_LINKED_SPIRV,  // Use VK_EXT_shader_object linked shader objects from spirv
50     PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_LINKED_BINARY, // Use VK_EXT_shader_object linked shader objects from binary
51 };
52 
53 bool isConstructionTypeLibrary(PipelineConstructionType pipelineConstructionType);
54 bool isConstructionTypeShaderObject(PipelineConstructionType pipelineConstructionType);
55 void checkPipelineConstructionRequirements(const InstanceInterface &vki, VkPhysicalDevice physicalDevice,
56                                            PipelineConstructionType pipelineConstructionType);
57 
58 // This exception may be raised in one of the intermediate steps when using shader module IDs instead of normal module objects.
59 class PipelineCompileRequiredError : public std::runtime_error
60 {
61 public:
PipelineCompileRequiredError(const std::string & msg)62     PipelineCompileRequiredError(const std::string &msg) : std::runtime_error(msg)
63     {
64     }
65 };
66 
67 // PointerWrapper template is used to hide structures that should not be visible for Vulkan SC
68 template <typename T>
69 class PointerWrapper
70 {
71 public:
PointerWrapper()72     PointerWrapper() : ptr(DE_NULL)
73     {
74     }
PointerWrapper(T * p0)75     PointerWrapper(T *p0) : ptr(p0)
76     {
77     }
78     T *ptr;
79 };
80 
81 template <typename T>
82 class ConstPointerWrapper
83 {
84 public:
ConstPointerWrapper()85     ConstPointerWrapper() : ptr(DE_NULL)
86     {
87     }
ConstPointerWrapper(const T * p0)88     ConstPointerWrapper(const T *p0) : ptr(p0)
89     {
90     }
91     const T *ptr;
92 };
93 
94 #ifndef CTS_USES_VULKANSC
95 typedef PointerWrapper<VkPipelineViewportDepthClipControlCreateInfoEXT>
96     PipelineViewportDepthClipControlCreateInfoWrapper;
97 typedef PointerWrapper<VkPipelineRenderingCreateInfoKHR> PipelineRenderingCreateInfoWrapper;
98 typedef PointerWrapper<VkRenderingAttachmentLocationInfoKHR> RenderingAttachmentLocationInfoWrapper;
99 typedef PointerWrapper<VkRenderingInputAttachmentIndexInfoKHR> RenderingInputAttachmentIndexInfoWrapper;
100 typedef PointerWrapper<VkPipelineCreationFeedbackCreateInfoEXT> PipelineCreationFeedbackCreateInfoWrapper;
101 typedef ConstPointerWrapper<VkPipelineShaderStageModuleIdentifierCreateInfoEXT>
102     PipelineShaderStageModuleIdentifierCreateInfoWrapper;
103 typedef PointerWrapper<VkPipelineRepresentativeFragmentTestStateCreateInfoNV>
104     PipelineRepresentativeFragmentTestCreateInfoWrapper;
105 typedef VkPipelineCreateFlags2KHR PipelineCreateFlags2;
106 typedef PointerWrapper<VkPipelineRobustnessCreateInfoEXT> PipelineRobustnessCreateInfoWrapper;
107 #else
108 typedef PointerWrapper<void> PipelineViewportDepthClipControlCreateInfoWrapper;
109 typedef PointerWrapper<void> PipelineRenderingCreateInfoWrapper;
110 typedef PointerWrapper<void> RenderingAttachmentLocationInfoWrapper;
111 typedef PointerWrapper<void> RenderingInputAttachmentIndexInfoWrapper;
112 typedef PointerWrapper<void> PipelineCreationFeedbackCreateInfoWrapper;
113 typedef ConstPointerWrapper<void> PipelineShaderStageModuleIdentifierCreateInfoWrapper;
114 typedef PointerWrapper<void> PipelineRepresentativeFragmentTestCreateInfoWrapper;
115 typedef uint64_t PipelineCreateFlags2;
116 typedef PointerWrapper<void> PipelineRobustnessCreateInfoWrapper;
117 #endif
118 
119 PipelineCreateFlags2 translateCreateFlag(VkPipelineCreateFlags flagToTranslate);
120 
121 class PipelineLayoutWrapper
122 {
123 public:
124     PipelineLayoutWrapper() = default;
125     PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device,
126                           const VkDescriptorSetLayout descriptorSetLayout = DE_NULL,
127                           const VkPushConstantRange *pushConstantRange    = DE_NULL);
128     PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device,
129                           const std::vector<vk::Move<VkDescriptorSetLayout>> &descriptorSetLayout);
130     PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device,
131                           uint32_t setLayoutCount, const VkDescriptorSetLayout *descriptorSetLayout);
132     PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device,
133                           const VkPipelineLayoutCreateInfo *pCreateInfo, const VkAllocationCallbacks * = DE_NULL);
134     PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk,
135                           const VkDevice device, const uint32_t setLayoutCount,
136                           const VkDescriptorSetLayout *descriptorSetLayout, const uint32_t pushConstantRangeCount,
137                           const VkPushConstantRange *pPushConstantRanges,
138                           const VkPipelineLayoutCreateFlags flags = (VkPipelineLayoutCreateFlags)0u);
139     PipelineLayoutWrapper(const PipelineLayoutWrapper &rhs) = delete;
140     PipelineLayoutWrapper(PipelineLayoutWrapper &&rhs) noexcept;
141     ~PipelineLayoutWrapper() = default;
142 
operator *(void) const143     const VkPipelineLayout operator*(void) const
144     {
145         return *m_pipelineLayout;
146     }
get(void) const147     const VkPipelineLayout get(void) const
148     {
149         return *m_pipelineLayout;
150     }
151     PipelineLayoutWrapper &operator=(const PipelineLayoutWrapper &rhs) = delete;
152     PipelineLayoutWrapper &operator=(PipelineLayoutWrapper &&rhs);
destroy(void)153     void destroy(void)
154     {
155         m_pipelineLayout = vk::Move<VkPipelineLayout>{};
156     }
157 
getSetLayoutCount(void) const158     uint32_t getSetLayoutCount(void) const
159     {
160         return m_setLayoutCount;
161     }
getSetLayouts(void) const162     const VkDescriptorSetLayout *getSetLayouts(void) const
163     {
164         return m_setLayouts.data();
165     }
getSetLayout(uint32_t i)166     VkDescriptorSetLayout *getSetLayout(uint32_t i)
167     {
168         return &m_setLayouts[i];
169     }
getPushConstantRangeCount(void) const170     uint32_t getPushConstantRangeCount(void) const
171     {
172         return m_pushConstantRangeCount;
173     }
getPushConstantRanges(void) const174     const VkPushConstantRange *getPushConstantRanges(void) const
175     {
176         return m_pushConstantRanges.data();
177     }
178 
179     void bindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, uint32_t firstSet,
180                             uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets,
181                             uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets) const;
182 
183 private:
184     PipelineConstructionType m_pipelineConstructionType;
185     const DeviceInterface *m_vk;
186     VkDevice m_device;
187     VkPipelineLayoutCreateFlags m_flags;
188     uint32_t m_setLayoutCount;
189     std::vector<VkDescriptorSetLayout> m_setLayouts;
190     uint32_t m_pushConstantRangeCount;
191     std::vector<VkPushConstantRange> m_pushConstantRanges;
192     vk::Move<VkPipelineLayout> m_pipelineLayout;
193 };
194 
195 class RenderPassWrapper
196 {
197 public:
198     RenderPassWrapper() = default;
199     RenderPassWrapper(const DeviceInterface &vk, VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo,
200                       bool dynamicRendering);
201     RenderPassWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device,
202                       const VkRenderPassCreateInfo *pCreateInfo);
203     RenderPassWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk, VkDevice device,
204                       const VkRenderPassCreateInfo2 *pCreateInfo);
205     RenderPassWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk,
206                       const VkDevice device, const VkFormat colorFormat = VK_FORMAT_UNDEFINED,
207                       const VkFormat depthStencilFormat             = VK_FORMAT_UNDEFINED,
208                       const VkAttachmentLoadOp loadOperation        = VK_ATTACHMENT_LOAD_OP_CLEAR,
209                       const VkImageLayout finalLayoutColor          = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
210                       const VkImageLayout finalLayoutDepthStencil   = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
211                       const VkImageLayout subpassLayoutColor        = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
212                       const VkImageLayout subpassLayoutDepthStencil = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
213                       const VkAllocationCallbacks *const allocationCallbacks = DE_NULL);
214 
215     RenderPassWrapper(RenderPassWrapper &&rhs) noexcept;
216     RenderPassWrapper &operator=(RenderPassWrapper &&rhs) noexcept;
217 
218     ~RenderPassWrapper() = default;
219 
operator *(void) const220     const VkRenderPass operator*(void) const
221     {
222         return *m_renderPass;
223     }
get(void) const224     const VkRenderPass get(void) const
225     {
226         return *m_renderPass;
227     }
getFramebuffer(void) const228     const VkFramebuffer getFramebuffer(void) const
229     {
230         return m_framebuffer ? *m_framebuffer : VK_NULL_HANDLE;
231     }
232 
233     void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea,
234                const uint32_t clearValueCount, const VkClearValue *clearValues,
235                const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE, const void *pNext = DE_NULL) const;
236     void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea,
237                const VkClearValue &clearValue, const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE) const;
238     void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea,
239                const tcu::Vec4 &clearColor, const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE) const;
240     void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea,
241                const tcu::Vec4 &clearColor, const float clearDepth, const uint32_t clearStencil,
242                const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE) const;
243     void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea,
244                const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE) const;
245     void begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const VkRect2D &renderArea,
246                const tcu::UVec4 &clearColor, const VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE) const;
247 
248     void end(const DeviceInterface &vk, const VkCommandBuffer commandBuffer) const;
249     void nextSubpass(const DeviceInterface &vk, const VkCommandBuffer commandBuffer,
250                      const VkSubpassContents contents) const;
251 
252     void createFramebuffer(const DeviceInterface &vk, const VkDevice device, const VkFramebufferCreateInfo *pCreateInfo,
253                            const std::vector<vk::VkImage> &images);
254     void createFramebuffer(const DeviceInterface &vk, const VkDevice device, const VkFramebufferCreateInfo *pCreateInfo,
255                            vk::VkImage colorImage, vk::VkImage depthStencilImage = VK_NULL_HANDLE);
256     void createFramebuffer(const DeviceInterface &vk, const VkDevice device, const VkImage colorImage,
257                            const VkImageView colorAttachment, const uint32_t width, const uint32_t height,
258                            const uint32_t layers = 1u);
259     void createFramebuffer(const DeviceInterface &vk, const VkDevice device, const uint32_t attachmentCount,
260                            const VkImage *imagesArray, const VkImageView *attachmentsArray, const uint32_t width,
261                            const uint32_t height, const uint32_t layers = 1u);
262 
263 private:
264     void beginRendering(const DeviceInterface &vk, const VkCommandBuffer commandBuffer) const;
265 
266     bool m_isDynamicRendering;
267     vk::Move<vk::VkRenderPass> m_renderPass;
268     vk::Move<vk::VkFramebuffer> m_framebuffer;
269 
270 #ifndef CTS_USES_VULKANSC
271     struct Subpass
272     {
273         struct Attachment
274         {
275             uint32_t index                               = VK_ATTACHMENT_UNUSED;
276             vk::VkRenderingAttachmentInfo attachmentInfo = {};
277             vk::VkFormat format;
278             vk::VkAttachmentLoadOp stencilLoadOp   = vk::VK_ATTACHMENT_LOAD_OP_LOAD;
279             vk::VkAttachmentStoreOp stencilStoreOp = vk::VK_ATTACHMENT_STORE_OP_STORE;
280         };
281         mutable std::vector<Attachment> m_colorAttachments;
282         mutable Attachment m_depthStencilAttachment;
283         mutable std::vector<Attachment> m_resolveAttachments;
284         mutable VkMultisampledRenderToSingleSampledInfoEXT m_msrtss    = {};
285         mutable VkSubpassDescriptionDepthStencilResolve m_dsr          = {};
286         mutable VkAttachmentReference2 m_depthStencilResolveAttachment = {};
287     };
288     struct SubpassDependency
289     {
290         SubpassDependency(const VkSubpassDependency &dependency);
291         SubpassDependency(const VkSubpassDependency2 &dependency);
292 
293         uint32_t srcSubpass;
294         uint32_t dstSubpass;
295         VkPipelineStageFlags2 srcStageMask;
296         VkPipelineStageFlags2 dstStageMask;
297         VkAccessFlags2 srcAccessMask;
298         VkAccessFlags2 dstAccessMask;
299         VkDependencyFlags dependencyFlags;
300         bool sync2;
301     };
302     std::vector<Subpass> m_subpasses;
303     std::vector<SubpassDependency> m_dependencies;
304     std::vector<vk::VkAttachmentDescription2> m_attachments;
305     std::vector<vk::VkImage> m_images;
306     std::vector<vk::VkImageView> m_imageViews;
307     mutable std::vector<vk::VkClearValue> m_clearValues;
308     mutable std::vector<vk::VkImageLayout> m_layouts;
309     mutable uint32_t m_activeSubpass = 0;
310     mutable vk::VkRenderingInfo m_renderingInfo;
311     uint32_t m_layers = 1;
312     std::vector<uint32_t> m_viewMasks;
313     mutable bool m_secondaryCommandBuffers;
314 
315     void clearAttachments(const DeviceInterface &vk, const VkCommandBuffer commandBuffer) const;
316     void updateLayout(VkImage updatedImage, VkImageLayout newLayout) const;
317     void transitionLayouts(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const Subpass &subpass,
318                            bool renderPassBegin) const;
319     void insertDependencies(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, uint32_t subpassIdx) const;
320 
321 public:
322     void fillInheritanceRenderingInfo(uint32_t subpassIndex, std::vector<vk::VkFormat> *colorFormats,
323                                       vk::VkCommandBufferInheritanceRenderingInfo *inheritanceRenderingInfo) const;
324 
325 private:
326 #endif
327 };
328 
329 class ShaderWrapper
330 {
331 public:
332     ShaderWrapper();
333 
334     ShaderWrapper(const DeviceInterface &vk, VkDevice device, const vk::ProgramBinary &binary,
335                   const vk::VkShaderModuleCreateFlags createFlags = 0u);
336 
337     ShaderWrapper(const ShaderWrapper &rhs) noexcept;
338 
339     ~ShaderWrapper() = default;
340 
341     ShaderWrapper &operator=(const ShaderWrapper &rhs) noexcept;
342 
isSet(void) const343     bool isSet(void) const
344     {
345         return m_binary != DE_NULL;
346     }
347 
348     vk::VkShaderModule getModule(void) const;
349 
350     size_t getCodeSize(void) const;
351     void *getBinary(void) const;
352 
353     void createModule(void);
354     void setLayoutAndSpecialization(const PipelineLayoutWrapper *layout,
355                                     const VkSpecializationInfo *specializationInfo);
356 
getPipelineLayout(void) const357     const PipelineLayoutWrapper *getPipelineLayout(void) const
358     {
359         return m_layout;
360     }
getSpecializationInfo(void) const361     const VkSpecializationInfo *getSpecializationInfo(void) const
362     {
363         return m_specializationInfo;
364     }
365 
366 #ifndef CTS_USES_VULKANSC
getShader(void) const367     vk::VkShaderEXT getShader(void) const
368     {
369         return m_shader ? *m_shader : VK_NULL_HANDLE;
370     }
setShader(Move<VkShaderEXT> shader)371     void setShader(Move<VkShaderEXT> shader)
372     {
373         m_shader = shader;
374     }
375 
addFlags(const VkShaderCreateFlagsEXT flags)376     void addFlags(const VkShaderCreateFlagsEXT flags)
377     {
378         m_shaderCreateFlags |= flags;
379     }
380     void getShaderBinary(void);
getShaderBinaryDataSize(void)381     size_t getShaderBinaryDataSize(void)
382     {
383         return m_binaryDataSize;
384     }
getShaderBinaryData(void)385     void *getShaderBinaryData(void)
386     {
387         return m_binaryData.data();
388     }
389 #endif
390 
391 private:
392     const DeviceInterface *m_vk;
393     VkDevice m_device;
394     const vk::ProgramBinary *m_binary;
395     vk::VkShaderModuleCreateFlags m_moduleCreateFlags;
396     mutable vk::Move<vk::VkShaderModule> m_module;
397     const PipelineLayoutWrapper *m_layout;
398     const VkSpecializationInfo *m_specializationInfo;
399 #ifndef CTS_USES_VULKANSC
400     vk::Move<vk::VkShaderEXT> m_shader;
401     VkShaderCreateFlagsEXT m_shaderCreateFlags;
402     size_t m_binaryDataSize;
403     std::vector<uint8_t> m_binaryData;
404 #endif
405 };
406 
407 // Class that can build monolithic pipeline or fully separated pipeline libraries
408 // depending on PipelineType specified in the constructor.
409 // Rarely needed configuration was extracted to setDefault*/disable* functions while common
410 // state setup is provided as arguments of four setup* functions - one for each state group.
411 class GraphicsPipelineWrapper
412 {
413 public:
414     GraphicsPipelineWrapper(const InstanceInterface &vki, const DeviceInterface &vk, VkPhysicalDevice physicalDevice,
415                             VkDevice device, const std::vector<std::string> &deviceExtensions,
416                             const PipelineConstructionType pipelineConstructionType,
417                             const VkPipelineCreateFlags flags = 0u);
418 
419     GraphicsPipelineWrapper(GraphicsPipelineWrapper &&) noexcept;
420 
421     ~GraphicsPipelineWrapper(void) = default;
422 
423     // By default pipelineLayout used for monotlithic pipeline is taken from layout specified
424     // in setupPreRasterizationShaderState but when there are also descriptor sets needed for fragment
425     // shader bindings then separate pipeline layout for monolithic pipeline must be provided
426     GraphicsPipelineWrapper &setMonolithicPipelineLayout(const PipelineLayoutWrapper &layout);
427 
428     // By default dynamic state has to be specified before specifying other CreateInfo structures
429     GraphicsPipelineWrapper &setDynamicState(const VkPipelineDynamicStateCreateInfo *dynamicState);
430 
431     // Specify the representative fragment test state.
432     GraphicsPipelineWrapper &setRepresentativeFragmentTestState(
433         PipelineRepresentativeFragmentTestCreateInfoWrapper representativeFragmentTestState);
434 
435     // Specify pipeline robustness state
436     GraphicsPipelineWrapper &setPipelineRobustnessState(PipelineRobustnessCreateInfoWrapper pipelineRobustnessState);
437 
438     // Specifying how a pipeline is created using VkPipelineCreateFlags2CreateInfoKHR.
439     GraphicsPipelineWrapper &setPipelineCreateFlags2(PipelineCreateFlags2 pipelineFlags2);
440 
441     // Specify topology that is used by default InputAssemblyState in vertex input state. This needs to be
442     // specified only when there is no custom InputAssemblyState provided in setupVertexInputState and when
443     // topology is diferent then VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST which is used by default.
444     GraphicsPipelineWrapper &setDefaultTopology(const VkPrimitiveTopology topology);
445 
446     // Specify patch control points that is used by default TessellationState in pre-rasterization shader state.
447     // This can to be specified only when there is no custom TessellationState provided in
448     // setupPreRasterizationShaderState and when patchControlPoints is diferent then 3 which is used by default.
449     // A value of std::numeric_limits<uint32_t>::max() forces the tessellation state to be null.
450     GraphicsPipelineWrapper &setDefaultPatchControlPoints(const uint32_t patchControlPoints);
451 
452     // Specify tesellation domain origin, used by the tessellation state in pre-rasterization shader state.
453     GraphicsPipelineWrapper &setDefaultTessellationDomainOrigin(const VkTessellationDomainOrigin domainOrigin,
454                                                                 bool forceExtStruct = false);
455 
456     // Enable discarding of primitives that is used by default RasterizationState in pre-rasterization shader state.
457     // This can be specified only when there is no custom RasterizationState provided in setupPreRasterizationShaderState.
458     GraphicsPipelineWrapper &setDefaultRasterizerDiscardEnable(const bool rasterizerDiscardEnable = true);
459 
460     // When some states are not provided then default structures can be used. This behaviour can be turned on by one of below methods.
461     // Some tests require those states to be NULL so we can't assume using default versions.
462     GraphicsPipelineWrapper &setDefaultRasterizationState(void);
463     GraphicsPipelineWrapper &setDefaultDepthStencilState(void);
464     GraphicsPipelineWrapper &setDefaultColorBlendState(void);
465     GraphicsPipelineWrapper &setDefaultMultisampleState(void);
466     GraphicsPipelineWrapper &setDefaultVertexInputState(const bool useDefaultVertexInputState);
467 
468     // Pre-rasterization shader state uses provieded viewports and scissors to create ViewportState. By default
469     // number of viewports and scissors is same as number of items in vector but when vectors are empty then by
470     // default count of viewports/scissors is set to 1. This can be changed by below functions.
471     GraphicsPipelineWrapper &setDefaultViewportsCount(uint32_t viewportCount = 0u);
472     GraphicsPipelineWrapper &setDefaultScissorsCount(uint32_t scissorCount = 0u);
473 
474     // Pre-rasterization shader state uses default ViewportState, this method extends the internal structure.
475     GraphicsPipelineWrapper &setViewportStatePnext(const void *pNext);
476 
477 #ifndef CTS_USES_VULKANSC
478     GraphicsPipelineWrapper &setRenderingColorAttachmentsInfo(
479         PipelineRenderingCreateInfoWrapper pipelineRenderingCreateInfo);
480 #endif
481 
482     // Pre-rasterization shader state uses provieded viewports and scissors to create ViewportState. When disableViewportState
483     // is used then ViewportState won't be constructed and NULL will be used.
484     GraphicsPipelineWrapper &disableViewportState(const bool disable = true);
485 
486     // Setup vertex input state. When VertexInputState or InputAssemblyState are not provided then default structures will be used.
487     GraphicsPipelineWrapper &setupVertexInputState(
488         const VkPipelineVertexInputStateCreateInfo *vertexInputState     = nullptr,
489         const VkPipelineInputAssemblyStateCreateInfo *inputAssemblyState = nullptr,
490         const VkPipelineCache partPipelineCache                          = DE_NULL,
491         PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback   = PipelineCreationFeedbackCreateInfoWrapper(),
492         const bool useNullPtrs                                           = false);
493 
494     // Setup pre-rasterization shader state.
495     GraphicsPipelineWrapper &setupPreRasterizationShaderState(
496         const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
497         const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass,
498         const ShaderWrapper vertexShaderModule,
499         const VkPipelineRasterizationStateCreateInfo *rasterizationState = DE_NULL,
500         const ShaderWrapper tessellationControlShader                    = ShaderWrapper(),
501         const ShaderWrapper tessellationEvalShader                       = ShaderWrapper(),
502         const ShaderWrapper geometryShader = ShaderWrapper(), const VkSpecializationInfo *specializationInfo = DE_NULL,
503         VkPipelineFragmentShadingRateStateCreateInfoKHR *fragmentShadingRateState = nullptr,
504         PipelineRenderingCreateInfoWrapper rendering                   = PipelineRenderingCreateInfoWrapper(),
505         const VkPipelineCache partPipelineCache                        = DE_NULL,
506         PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper());
507 
508     GraphicsPipelineWrapper &setupPreRasterizationShaderState2(
509         const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
510         const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass,
511         const ShaderWrapper vertexShaderModule,
512         const VkPipelineRasterizationStateCreateInfo *rasterizationState          = nullptr,
513         const ShaderWrapper tessellationControlShader                             = ShaderWrapper(),
514         const ShaderWrapper tessellationEvalShader                                = ShaderWrapper(),
515         const ShaderWrapper geometryShader                                        = ShaderWrapper(),
516         const VkSpecializationInfo *vertSpecializationInfo                        = nullptr,
517         const VkSpecializationInfo *tescSpecializationInfo                        = nullptr,
518         const VkSpecializationInfo *teseSpecializationInfo                        = nullptr,
519         const VkSpecializationInfo *geomSpecializationInfo                        = nullptr,
520         VkPipelineFragmentShadingRateStateCreateInfoKHR *fragmentShadingRateState = nullptr,
521         PipelineRenderingCreateInfoWrapper rendering                   = PipelineRenderingCreateInfoWrapper(),
522         const VkPipelineCache partPipelineCache                        = DE_NULL,
523         PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper());
524 
525     // Note: VkPipelineShaderStageModuleIdentifierCreateInfoEXT::pIdentifier will not be copied. They need to continue to exist outside this wrapper.
526     GraphicsPipelineWrapper &setupPreRasterizationShaderState3(
527         const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
528         const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass,
529         const ShaderWrapper vertexShaderModule,
530         PipelineShaderStageModuleIdentifierCreateInfoWrapper vertShaderModuleId =
531             PipelineShaderStageModuleIdentifierCreateInfoWrapper(),
532         const VkPipelineRasterizationStateCreateInfo *rasterizationState = nullptr,
533         const ShaderWrapper tessellationControlShader                    = ShaderWrapper(),
534         PipelineShaderStageModuleIdentifierCreateInfoWrapper tescShaderModuleId =
535             PipelineShaderStageModuleIdentifierCreateInfoWrapper(),
536         const ShaderWrapper tessellationEvalShader = ShaderWrapper(),
537         PipelineShaderStageModuleIdentifierCreateInfoWrapper teseShaderModuleId =
538             PipelineShaderStageModuleIdentifierCreateInfoWrapper(),
539         const ShaderWrapper geometryShader = ShaderWrapper(),
540         PipelineShaderStageModuleIdentifierCreateInfoWrapper geomShaderModuleId =
541             PipelineShaderStageModuleIdentifierCreateInfoWrapper(),
542         const VkSpecializationInfo *vertSpecializationInfo                        = nullptr,
543         const VkSpecializationInfo *tescSpecializationInfo                        = nullptr,
544         const VkSpecializationInfo *teseSpecializationInfo                        = nullptr,
545         const VkSpecializationInfo *geomSpecializationInfo                        = nullptr,
546         VkPipelineFragmentShadingRateStateCreateInfoKHR *fragmentShadingRateState = nullptr,
547         PipelineRenderingCreateInfoWrapper rendering                   = PipelineRenderingCreateInfoWrapper(),
548         const VkPipelineCache partPipelineCache                        = DE_NULL,
549         PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper());
550 
551 #ifndef CTS_USES_VULKANSC
552     // Setup pre-rasterization shader state, mesh shading version.
553     GraphicsPipelineWrapper &setupPreRasterizationMeshShaderState(
554         const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
555         const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass,
556         const ShaderWrapper taskShader, const ShaderWrapper meshShader,
557         const VkPipelineRasterizationStateCreateInfo *rasterizationState          = nullptr,
558         const VkSpecializationInfo *taskSpecializationInfo                        = nullptr,
559         const VkSpecializationInfo *meshSpecializationInfo                        = nullptr,
560         VkPipelineFragmentShadingRateStateCreateInfoKHR *fragmentShadingRateState = nullptr,
561         PipelineRenderingCreateInfoWrapper rendering                  = PipelineRenderingCreateInfoWrapper(),
562         const VkPipelineCache partPipelineCache                       = DE_NULL,
563         VkPipelineCreationFeedbackCreateInfoEXT *partCreationFeedback = nullptr);
564 #endif // CTS_USES_VULKANSC
565 
566     // Setup fragment shader state.
567     GraphicsPipelineWrapper &setupFragmentShaderState(
568         const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass,
569         const ShaderWrapper fragmentShaderModule,
570         const VkPipelineDepthStencilStateCreateInfo *depthStencilState = DE_NULL,
571         const VkPipelineMultisampleStateCreateInfo *multisampleState   = DE_NULL,
572         const VkSpecializationInfo *specializationInfo = DE_NULL, const VkPipelineCache partPipelineCache = DE_NULL,
573         PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper(),
574         RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfo =
575             RenderingInputAttachmentIndexInfoWrapper());
576 
577     // Note: VkPipelineShaderStageModuleIdentifierCreateInfoEXT::pIdentifier will not be copied. They need to continue to exist outside this wrapper.
578     GraphicsPipelineWrapper &setupFragmentShaderState2(
579         const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass,
580         const ShaderWrapper fragmentShaderModule,
581         PipelineShaderStageModuleIdentifierCreateInfoWrapper fragmentShaderModuleId =
582             PipelineShaderStageModuleIdentifierCreateInfoWrapper(),
583         const VkPipelineDepthStencilStateCreateInfo *depthStencilState = nullptr,
584         const VkPipelineMultisampleStateCreateInfo *multisampleState   = nullptr,
585         const VkSpecializationInfo *specializationInfo = nullptr, const VkPipelineCache partPipelineCache = DE_NULL,
586         PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper(),
587         RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfo =
588             RenderingInputAttachmentIndexInfoWrapper());
589 
590     // Setup fragment output state.
591     GraphicsPipelineWrapper &setupFragmentOutputState(
592         const VkRenderPass renderPass, const uint32_t subpass = 0u,
593         const VkPipelineColorBlendStateCreateInfo *colorBlendState     = DE_NULL,
594         const VkPipelineMultisampleStateCreateInfo *multisampleState   = DE_NULL,
595         const VkPipelineCache partPipelineCache                        = DE_NULL,
596         PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback = PipelineCreationFeedbackCreateInfoWrapper(),
597         RenderingAttachmentLocationInfoWrapper renderingAttachmentLocationInfo =
598             RenderingAttachmentLocationInfoWrapper());
599 
600     // Build pipeline object out of provided state.
601     void buildPipeline(
602         const VkPipelineCache pipelineCache = DE_NULL, const VkPipeline basePipelineHandle = DE_NULL,
603         const int32_t basePipelineIndex                            = 0,
604         PipelineCreationFeedbackCreateInfoWrapper creationFeedback = PipelineCreationFeedbackCreateInfoWrapper());
605     // Create shader objects if used
606 #ifndef CTS_USES_VULKANSC
607     vk::VkShaderStageFlags getNextStages(vk::VkShaderStageFlagBits shaderStage, bool tessellationShaders,
608                                          bool geometryShaders, bool link);
609     vk::VkShaderCreateInfoEXT makeShaderCreateInfo(VkShaderStageFlagBits stage, ShaderWrapper &shader, bool link,
610                                                    bool binary, ShaderWrapper &other);
611     void createShaders(bool linked, bool binary);
612 #endif
613 
614     // Bind pipeline or shader objects
615     void bind(vk::VkCommandBuffer cmdBuffer) const;
616 
617     // Returns true when pipeline was build using buildPipeline method.
618     bool wasBuild(void) const;
619     // Returns true when pipeline or shader objects was built.
620     bool wasPipelineOrShaderObjectBuild(void) const;
621 
622     // Get compleate pipeline. GraphicsPipelineWrapper preserves ovnership and will destroy pipeline in its destructor.
623     vk::VkPipeline getPipeline(void) const;
624 
625     // Destroy compleate pipeline - pipeline parts are not destroyed.
626     void destroyPipeline(void);
627 
628 protected:
629     // No default constructor - use parametrized constructor or emplace_back in case of vectors.
630     GraphicsPipelineWrapper() = default;
631 
632     // Dynamic states that are only dynamic in shader objects
633     bool isShaderObjectDynamic(vk::VkDynamicState dynamicState) const;
634     void setShaderObjectDynamicStates(vk::VkCommandBuffer cmdBuffer) const;
635 
636     struct InternalData;
637 
638 protected:
639     static constexpr size_t kMaxPipelineParts = 4u;
640 
641     // Store partial pipelines when non monolithic construction was used.
642     Move<VkPipeline> m_pipelineParts[kMaxPipelineParts];
643 
644     // Store monolithic pipeline or linked pipeline libraries.
645     Move<VkPipeline> m_pipelineFinal;
646 
647     // Store internal data that is needed only for pipeline construction.
648     de::SharedPtr<InternalData> m_internalData;
649 };
650 
651 } // namespace vk
652 
653 #endif // _VKPIPELINECONSTRUCTIONUTIL_HPP
654