xref: /aosp_15_r20/external/deqp/external/vulkancts/framework/vulkan/vkPipelineConstructionUtil.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 The Khronos Group Inc.
6  * Copyright (c) 2023 LunarG, Inc.
7  * Copyright (c) 2023 Nintendo
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Wrapper that can construct monolithic pipeline or use
24           VK_EXT_graphics_pipeline_library for pipeline construction or use
25           VK_EXT_shader_object for shader objects.
26  *//*--------------------------------------------------------------------*/
27 
28 #include "vkRefUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "deSharedPtr.hpp"
31 #include "deSTLUtil.hpp"
32 #include "tcuVector.hpp"
33 #include "tcuVectorType.hpp"
34 #include "tcuMaybe.hpp"
35 #include "vkRefUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkObjUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "vkImageUtil.hpp"
41 #include "vkPipelineConstructionUtil.hpp"
42 #include "vkBarrierUtil.hpp"
43 
44 #include <memory>
45 #include <set>
46 #include <map>
47 
48 namespace vk
49 {
50 
51 namespace
52 {
53 
54 enum PipelineSetupState
55 {
56     PSS_NONE                      = 0x00000000,
57     PSS_VERTEX_INPUT_INTERFACE    = 0x00000001,
58     PSS_PRE_RASTERIZATION_SHADERS = 0x00000002,
59     PSS_FRAGMENT_SHADER           = 0x00000004,
60     PSS_FRAGMENT_OUTPUT_INTERFACE = 0x00000008,
61 };
62 
63 using TessellationDomainOriginStatePtr = std::unique_ptr<VkPipelineTessellationDomainOriginStateCreateInfo>;
64 
65 } // anonymous namespace
66 
67 static const VkVertexInputBindingDescription defaultVertexInputBindingDescription{
68     0u,                          // uint32_t                                        binding
69     sizeof(tcu::Vec4),           // uint32_t                                        stride
70     VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate                            inputRate
71 };
72 
73 static const VkVertexInputAttributeDescription defaultVertexInputAttributeDescription{
74     0u,                            // uint32_t                                        location
75     0u,                            // uint32_t                                        binding
76     VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat                                        format
77     0u                             // uint32_t                                        offset
78 };
79 
80 static const VkPipelineVertexInputStateCreateInfo defaultVertexInputState{
81     VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType                                sType
82     DE_NULL,                                                   // const void*                                    pNext
83     (VkPipelineVertexInputStateCreateFlags)0,                  // VkPipelineVertexInputStateCreateFlags        flags
84     1u, // uint32_t                                        vertexBindingDescriptionCount
85     &defaultVertexInputBindingDescription, // const VkVertexInputBindingDescription*        pVertexBindingDescriptions
86     1u, // uint32_t                                        vertexAttributeDescriptionCount
87     &defaultVertexInputAttributeDescription // const VkVertexInputAttributeDescription*        pVertexAttributeDescriptions
88 };
89 
90 static const VkStencilOpState defaultStencilOpState{
91     VK_STENCIL_OP_KEEP,  // VkStencilOp                                    failOp
92     VK_STENCIL_OP_KEEP,  // VkStencilOp                                    passOp
93     VK_STENCIL_OP_KEEP,  // VkStencilOp                                    depthFailOp
94     VK_COMPARE_OP_NEVER, // VkCompareOp                                    compareOp
95     0u,                  // uint32_t                                        compareMask
96     0u,                  // uint32_t                                        writeMask
97     0u                   // uint32_t                                        reference
98 };
99 
100 static const VkPipelineDepthStencilStateCreateInfo defaultDepthStencilState{
101     VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType                                sType
102     DE_NULL,                                                    // const void*                                    pNext
103     0u,                                                         // VkPipelineDepthStencilStateCreateFlags        flags
104     VK_FALSE,                    // VkBool32                                        depthTestEnable
105     VK_FALSE,                    // VkBool32                                        depthWriteEnable
106     VK_COMPARE_OP_LESS_OR_EQUAL, // VkCompareOp                                    depthCompareOp
107     VK_FALSE,                    // VkBool32                                        depthBoundsTestEnable
108     VK_FALSE,                    // VkBool32                                        stencilTestEnable
109     defaultStencilOpState,       // VkStencilOpState                                front
110     defaultStencilOpState,       // VkStencilOpState                                back
111     0.0f,                        // float                                        minDepthBounds
112     1.0f,                        // float                                        maxDepthBounds
113 };
114 
115 static const VkPipelineMultisampleStateCreateInfo defaultMultisampleState{
116     VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType                                sType
117     DE_NULL,                                                  // const void*                                    pNext
118     0u,                                                       // VkPipelineMultisampleStateCreateFlags        flags
119     VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits                        rasterizationSamples
120     VK_FALSE,              // VkBool32                                        sampleShadingEnable
121     1.0f,                  // float                                        minSampleShading
122     DE_NULL,               // const VkSampleMask*                            pSampleMask
123     VK_FALSE,              // VkBool32                                        alphaToCoverageEnable
124     VK_FALSE               // VkBool32                                        alphaToOneEnable
125 };
126 
127 static const VkPipelineColorBlendAttachmentState defaultColorBlendAttachmentState{
128     VK_FALSE,             // VkBool32                                        blendEnable
129     VK_BLEND_FACTOR_ZERO, // VkBlendFactor                                srcColorBlendFactor
130     VK_BLEND_FACTOR_ZERO, // VkBlendFactor                                dstColorBlendFactor
131     VK_BLEND_OP_ADD,      // VkBlendOp                                    colorBlendOp
132     VK_BLEND_FACTOR_ZERO, // VkBlendFactor                                srcAlphaBlendFactor
133     VK_BLEND_FACTOR_ZERO, // VkBlendFactor                                dstAlphaBlendFactor
134     VK_BLEND_OP_ADD,      // VkBlendOp                                    alphaBlendOp
135     0xf                   // VkColorComponentFlags                        colorWriteMask
136 };
137 
138 static const VkPipelineColorBlendStateCreateInfo defaultColorBlendState{
139     VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType                                sType
140     DE_NULL,                                                  // const void*                                    pNext
141     0u,                                                       // VkPipelineColorBlendStateCreateFlags            flags
142     VK_FALSE,                          // VkBool32                                        logicOpEnable
143     VK_LOGIC_OP_CLEAR,                 // VkLogicOp                                    logicOp
144     1u,                                // uint32_t                                        attachmentCount
145     &defaultColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState*    pAttachments
146     {0.0f, 0.0f, 0.0f, 0.0f}           // float                                        blendConstants[4]
147 };
148 
149 namespace
150 {
151 #ifndef CTS_USES_VULKANSC
makeGraphicsPipelineLibraryCreateInfo(const VkGraphicsPipelineLibraryFlagsEXT flags)152 VkGraphicsPipelineLibraryCreateInfoEXT makeGraphicsPipelineLibraryCreateInfo(
153     const VkGraphicsPipelineLibraryFlagsEXT flags)
154 {
155     return {
156         VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT, // VkStructureType sType;
157         DE_NULL,                                                     // void* pNext;
158         flags,                                                       // VkGraphicsPipelineLibraryFlagsEXT flags;
159     };
160 }
161 #endif // CTS_USES_VULKANSC
162 
makeGraphicsPipeline(const DeviceInterface & vk,VkDevice device,VkPipelineCache pipelineCache,const VkGraphicsPipelineCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator=nullptr)163 Move<VkPipeline> makeGraphicsPipeline(const DeviceInterface &vk, VkDevice device, VkPipelineCache pipelineCache,
164                                       const VkGraphicsPipelineCreateInfo *pCreateInfo,
165                                       const VkAllocationCallbacks *pAllocator = nullptr)
166 {
167     VkPipeline object  = 0;
168     const auto retcode = vk.createGraphicsPipelines(device, pipelineCache, 1u, pCreateInfo, pAllocator, &object);
169 
170 #ifndef CTS_USES_VULKANSC
171     const bool allowCompileRequired =
172         ((pCreateInfo->flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT) != 0u);
173 
174     if (allowCompileRequired && retcode == VK_PIPELINE_COMPILE_REQUIRED)
175         throw PipelineCompileRequiredError("createGraphicsPipelines returned VK_PIPELINE_COMPILE_REQUIRED");
176 #endif // CTS_USES_VULKANSC
177 
178     VK_CHECK(retcode);
179     return Move<VkPipeline>(check<VkPipeline>(object), Deleter<VkPipeline>(vk, device, pAllocator));
180 }
181 
182 } // namespace
183 
isConstructionTypeLibrary(PipelineConstructionType pipelineConstructionType)184 bool isConstructionTypeLibrary(PipelineConstructionType pipelineConstructionType)
185 {
186     return pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY ||
187            pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY;
188 }
189 
isConstructionTypeShaderObject(PipelineConstructionType pipelineConstructionType)190 bool isConstructionTypeShaderObject(PipelineConstructionType pipelineConstructionType)
191 {
192     return pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_UNLINKED_SPIRV ||
193            pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_UNLINKED_BINARY ||
194            pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_LINKED_SPIRV ||
195            pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_LINKED_BINARY;
196 }
197 
checkPipelineConstructionRequirements(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,PipelineConstructionType pipelineConstructionType)198 void checkPipelineConstructionRequirements(const InstanceInterface &vki, VkPhysicalDevice physicalDevice,
199                                            PipelineConstructionType pipelineConstructionType)
200 {
201     if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
202         return;
203 
204     const auto &supportedExtensions = enumerateCachedDeviceExtensionProperties(vki, physicalDevice);
205 
206     if (isConstructionTypeShaderObject(pipelineConstructionType))
207     {
208         if (!isExtensionStructSupported(supportedExtensions, RequiredExtension("VK_EXT_shader_object")))
209             TCU_THROW(NotSupportedError, "VK_EXT_shader_object not supported");
210         return;
211     }
212 
213     if (!isExtensionStructSupported(supportedExtensions, RequiredExtension("VK_EXT_graphics_pipeline_library")))
214         TCU_THROW(NotSupportedError, "VK_EXT_graphics_pipeline_library not supported");
215 }
216 
translateCreateFlag(VkPipelineCreateFlags flagToTranslate)217 PipelineCreateFlags2 translateCreateFlag(VkPipelineCreateFlags flagToTranslate)
218 {
219     return (PipelineCreateFlags2)flagToTranslate;
220 }
221 
addToChain(void ** structThatStartsChain,void * structToAddAtTheEnd)222 void addToChain(void **structThatStartsChain, void *structToAddAtTheEnd)
223 {
224     DE_ASSERT(structThatStartsChain);
225 
226     if (structToAddAtTheEnd == DE_NULL)
227         return;
228 
229     // Cast to the base out structure which has a non-const pNext pointer.
230     auto *structToAddAtTheEndCasted = reinterpret_cast<VkBaseOutStructure *>(structToAddAtTheEnd);
231 
232     // make sure that pNext pointer of structure that is added to chain is empty;
233     // we are construting chains on our own and there are cases that use same
234     // structure for multiple instances of GraphicsPipelineWrapper
235     structToAddAtTheEndCasted->pNext = DE_NULL;
236 
237     uint32_t safetyCouter = 10u;
238     void **structInChain  = structThatStartsChain;
239 
240     do
241     {
242         // check if this is free spot
243         if (*structInChain == DE_NULL)
244         {
245             // attach new structure at the end
246             *structInChain = structToAddAtTheEndCasted;
247             return;
248         }
249 
250         // Cast to the base out structure which has a non-const pNext pointer.
251         auto *gpl = reinterpret_cast<VkBaseOutStructure *>(*structInChain);
252 
253         // move structure pointer one position down the pNext chain
254         structInChain = reinterpret_cast<void **>(&gpl->pNext);
255     } while (--safetyCouter);
256 
257     // probably safetyCouter is to small
258     DE_ASSERT(false);
259 }
260 
261 namespace
262 {
263 using PipelineShaderStageModuleIdPtr = std::unique_ptr<PipelineShaderStageModuleIdentifierCreateInfoWrapper>;
264 }
265 
PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType,const DeviceInterface & vk,VkDevice device,const std::vector<vk::Move<VkDescriptorSetLayout>> & descriptorSetLayout)266 PipelineLayoutWrapper::PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType,
267                                              const DeviceInterface &vk, VkDevice device,
268                                              const std::vector<vk::Move<VkDescriptorSetLayout>> &descriptorSetLayout)
269     : m_pipelineConstructionType(pipelineConstructionType)
270     , m_vk(&vk)
271     , m_device(device)
272     , m_flags((VkPipelineLayoutCreateFlags)0u)
273     , m_setLayoutCount((uint32_t)descriptorSetLayout.size())
274     , m_pushConstantRangeCount(0u)
275     , m_pushConstantRanges()
276 {
277 #ifndef CTS_USES_VULKANSC
278     if (isConstructionTypeShaderObject(pipelineConstructionType))
279         m_flags &= ~(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
280 #endif
281 
282     m_setLayouts.resize(m_setLayoutCount);
283     for (uint32_t i = 0; i < m_setLayoutCount; ++i)
284         m_setLayouts[i] = *descriptorSetLayout[i];
285 
286     VkPipelineLayoutCreateInfo createInfo = vk::initVulkanStructure();
287     createInfo.flags                      = m_flags;
288     createInfo.setLayoutCount             = m_setLayoutCount;
289     createInfo.pSetLayouts                = de::dataOrNull(m_setLayouts);
290     createInfo.pushConstantRangeCount     = m_pushConstantRangeCount;
291     createInfo.pPushConstantRanges        = de::dataOrNull(m_pushConstantRanges);
292     m_pipelineLayout                      = createPipelineLayout(vk, device, &createInfo);
293 }
294 
PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType,const DeviceInterface & vk,VkDevice device,uint32_t setLayoutCount,const VkDescriptorSetLayout * descriptorSetLayout)295 PipelineLayoutWrapper::PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType,
296                                              const DeviceInterface &vk, VkDevice device, uint32_t setLayoutCount,
297                                              const VkDescriptorSetLayout *descriptorSetLayout)
298     : m_pipelineConstructionType(pipelineConstructionType)
299     , m_vk(&vk)
300     , m_device(device)
301     , m_flags((VkPipelineLayoutCreateFlags)0u)
302     , m_setLayoutCount(setLayoutCount)
303     , m_pushConstantRangeCount(0u)
304     , m_pushConstantRanges()
305 {
306 #ifndef CTS_USES_VULKANSC
307     if (isConstructionTypeShaderObject(pipelineConstructionType))
308         m_flags &= ~(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
309 #endif
310 
311     m_setLayouts.resize(m_setLayoutCount);
312     for (uint32_t i = 0; i < m_setLayoutCount; ++i)
313         m_setLayouts[i] = descriptorSetLayout[i];
314 
315     VkPipelineLayoutCreateInfo createInfo = vk::initVulkanStructure();
316     createInfo.flags                      = m_flags;
317     createInfo.setLayoutCount             = m_setLayoutCount;
318     createInfo.pSetLayouts                = de::dataOrNull(m_setLayouts);
319     createInfo.pushConstantRangeCount     = m_pushConstantRangeCount;
320     createInfo.pPushConstantRanges        = de::dataOrNull(m_pushConstantRanges);
321     m_pipelineLayout                      = createPipelineLayout(vk, device, &createInfo);
322 }
323 
PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType,const DeviceInterface & vk,VkDevice device,const VkDescriptorSetLayout descriptorSetLayout,const VkPushConstantRange * pushConstantRange)324 PipelineLayoutWrapper::PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType,
325                                              const DeviceInterface &vk, VkDevice device,
326                                              const VkDescriptorSetLayout descriptorSetLayout,
327                                              const VkPushConstantRange *pushConstantRange)
328     : m_pipelineConstructionType(pipelineConstructionType)
329     , m_vk(&vk)
330     , m_device(device)
331     , m_flags((VkPipelineLayoutCreateFlags)0u)
332 {
333 #ifndef CTS_USES_VULKANSC
334     if (isConstructionTypeShaderObject(pipelineConstructionType))
335         m_flags &= ~(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
336 #endif
337 
338     if (descriptorSetLayout == VK_NULL_HANDLE)
339     {
340         m_setLayoutCount = 0;
341     }
342     else
343     {
344         m_setLayoutCount = 1;
345         m_setLayouts.resize(1);
346         m_setLayouts[0] = descriptorSetLayout;
347     }
348     if (pushConstantRange == DE_NULL)
349     {
350         m_pushConstantRangeCount = 0;
351     }
352     else
353     {
354         m_pushConstantRangeCount = 1;
355         m_pushConstantRanges.resize(1);
356         m_pushConstantRanges[0] = *pushConstantRange;
357     }
358 
359     VkPipelineLayoutCreateInfo createInfo = vk::initVulkanStructure();
360     createInfo.flags                      = m_flags;
361     createInfo.setLayoutCount             = m_setLayoutCount;
362     createInfo.pSetLayouts                = de::dataOrNull(m_setLayouts);
363     createInfo.pushConstantRangeCount     = m_pushConstantRangeCount;
364     createInfo.pPushConstantRanges        = de::dataOrNull(m_pushConstantRanges);
365     m_pipelineLayout                      = createPipelineLayout(vk, device, &createInfo);
366 }
367 
PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType,const DeviceInterface & vk,VkDevice device,const VkPipelineLayoutCreateInfo * pCreateInfo,const VkAllocationCallbacks *)368 PipelineLayoutWrapper::PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType,
369                                              const DeviceInterface &vk, VkDevice device,
370                                              const VkPipelineLayoutCreateInfo *pCreateInfo,
371                                              const VkAllocationCallbacks *)
372     : m_pipelineConstructionType(pipelineConstructionType)
373     , m_vk(&vk)
374     , m_device(device)
375     , m_flags(pCreateInfo->flags)
376     , m_setLayoutCount(pCreateInfo->setLayoutCount)
377     , m_pushConstantRangeCount(pCreateInfo->pushConstantRangeCount)
378 {
379 #ifndef CTS_USES_VULKANSC
380     if (isConstructionTypeShaderObject(pipelineConstructionType))
381         m_flags &= ~(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
382 #endif
383 
384     m_setLayouts.resize(pCreateInfo->setLayoutCount);
385     for (uint32_t i = 0; i < pCreateInfo->setLayoutCount; ++i)
386         m_setLayouts[i] = pCreateInfo->pSetLayouts[i];
387     m_pushConstantRanges.resize(pCreateInfo->pushConstantRangeCount);
388     for (uint32_t i = 0; i < pCreateInfo->pushConstantRangeCount; ++i)
389         m_pushConstantRanges[i] = pCreateInfo->pPushConstantRanges[i];
390 
391     VkPipelineLayoutCreateInfo createInfo = vk::initVulkanStructure();
392     createInfo.flags                      = m_flags;
393     createInfo.setLayoutCount             = m_setLayoutCount;
394     createInfo.pSetLayouts                = m_setLayouts.data();
395     createInfo.pushConstantRangeCount     = m_pushConstantRangeCount;
396     createInfo.pPushConstantRanges        = m_pushConstantRanges.data();
397     m_pipelineLayout                      = createPipelineLayout(vk, device, &createInfo);
398 }
399 
PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType,const DeviceInterface & vk,const VkDevice device,const uint32_t setLayoutCount,const VkDescriptorSetLayout * descriptorSetLayout,const uint32_t pushConstantRangeCount,const VkPushConstantRange * pPushConstantRanges,const VkPipelineLayoutCreateFlags flags)400 PipelineLayoutWrapper::PipelineLayoutWrapper(PipelineConstructionType pipelineConstructionType,
401                                              const DeviceInterface &vk, const VkDevice device,
402                                              const uint32_t setLayoutCount,
403                                              const VkDescriptorSetLayout *descriptorSetLayout,
404                                              const uint32_t pushConstantRangeCount,
405                                              const VkPushConstantRange *pPushConstantRanges,
406                                              const VkPipelineLayoutCreateFlags flags)
407     : m_pipelineConstructionType(pipelineConstructionType)
408     , m_vk(&vk)
409     , m_device(device)
410     , m_flags(flags)
411     , m_setLayoutCount(setLayoutCount)
412     , m_pushConstantRangeCount(pushConstantRangeCount)
413 {
414 #ifndef CTS_USES_VULKANSC
415     if (isConstructionTypeShaderObject(pipelineConstructionType))
416         m_flags &= ~(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
417 #endif
418 
419     m_setLayouts.resize(m_setLayoutCount);
420     m_pushConstantRanges.resize(m_pushConstantRangeCount);
421     for (uint32_t i = 0; i < m_setLayoutCount; ++i)
422         m_setLayouts[i] = descriptorSetLayout[i];
423     for (uint32_t i = 0; i < m_pushConstantRangeCount; ++i)
424         m_pushConstantRanges[i] = pPushConstantRanges[i];
425 
426     VkPipelineLayoutCreateInfo createInfo = vk::initVulkanStructure();
427     createInfo.flags                      = m_flags;
428     createInfo.setLayoutCount             = m_setLayoutCount;
429     createInfo.pSetLayouts                = m_setLayouts.data();
430     createInfo.pushConstantRangeCount     = m_pushConstantRangeCount;
431     createInfo.pPushConstantRanges        = m_pushConstantRanges.data();
432     m_pipelineLayout                      = createPipelineLayout(vk, device, &createInfo);
433 }
434 
PipelineLayoutWrapper(PipelineLayoutWrapper && rhs)435 PipelineLayoutWrapper::PipelineLayoutWrapper(PipelineLayoutWrapper &&rhs) noexcept
436     : m_pipelineConstructionType(rhs.m_pipelineConstructionType)
437     , m_vk(rhs.m_vk)
438     , m_device(rhs.m_device)
439     , m_flags(rhs.m_flags)
440     , m_setLayoutCount(rhs.m_setLayoutCount)
441     , m_setLayouts(std::move(rhs.m_setLayouts))
442     , m_pushConstantRangeCount(rhs.m_pushConstantRangeCount)
443     , m_pushConstantRanges(std::move(rhs.m_pushConstantRanges))
444     , m_pipelineLayout(rhs.m_pipelineLayout)
445 {
446 }
447 
operator =(PipelineLayoutWrapper && rhs)448 PipelineLayoutWrapper &PipelineLayoutWrapper::operator=(PipelineLayoutWrapper &&rhs)
449 {
450     m_pipelineConstructionType = rhs.m_pipelineConstructionType;
451     m_vk                       = rhs.m_vk;
452     m_device                   = rhs.m_device;
453     m_flags                    = rhs.m_flags;
454     m_setLayoutCount           = rhs.m_setLayoutCount;
455     m_setLayouts               = std::move(rhs.m_setLayouts);
456     m_pushConstantRangeCount   = rhs.m_pushConstantRangeCount;
457     m_pushConstantRanges       = std::move(rhs.m_pushConstantRanges);
458     m_pipelineLayout           = rhs.m_pipelineLayout;
459 
460     return *this;
461 }
462 
bindDescriptorSets(VkCommandBuffer commandBuffer,VkPipelineBindPoint pipelineBindPoint,uint32_t firstSet,uint32_t descriptorSetCount,const VkDescriptorSet * pDescriptorSets,uint32_t dynamicOffsetCount,const uint32_t * pDynamicOffsets) const463 void PipelineLayoutWrapper::bindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
464                                                uint32_t firstSet, uint32_t descriptorSetCount,
465                                                const VkDescriptorSet *pDescriptorSets, uint32_t dynamicOffsetCount,
466                                                const uint32_t *pDynamicOffsets) const
467 {
468     if (!isConstructionTypeShaderObject(m_pipelineConstructionType))
469     {
470         m_vk->cmdBindDescriptorSets(commandBuffer, pipelineBindPoint, *m_pipelineLayout, firstSet, descriptorSetCount,
471                                     pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
472     }
473     else
474     {
475         //m_vk->cmdBindDescriptorSets2EXT(commandBuffer, &m_setLayouts[firstSet], vk::VK_SHADER_STAGE_ALL_GRAPHICS, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
476         m_vk->cmdBindDescriptorSets(commandBuffer, pipelineBindPoint, *m_pipelineLayout, firstSet, descriptorSetCount,
477                                     pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
478     }
479 }
480 
481 #ifndef CTS_USES_VULKANSC
SubpassDependency(const VkSubpassDependency & dependency)482 RenderPassWrapper::SubpassDependency::SubpassDependency(const VkSubpassDependency &dependency)
483     : srcSubpass(dependency.srcSubpass)
484     , dstSubpass(dependency.dstSubpass)
485     , srcStageMask(dependency.srcStageMask)
486     , dstStageMask(dependency.dstStageMask)
487     , srcAccessMask(dependency.srcAccessMask)
488     , dstAccessMask(dependency.dstAccessMask)
489     , dependencyFlags(dependency.dependencyFlags)
490     , sync2(false)
491 {
492 }
493 
SubpassDependency(const VkSubpassDependency2 & dependency)494 RenderPassWrapper::SubpassDependency::SubpassDependency(const VkSubpassDependency2 &dependency)
495     : srcSubpass(dependency.srcSubpass)
496     , dstSubpass(dependency.dstSubpass)
497     , srcStageMask(0u)
498     , dstStageMask(0u)
499     , srcAccessMask(0u)
500     , dstAccessMask(0u)
501     , dependencyFlags(dependency.dependencyFlags)
502     , sync2(false)
503 {
504     DE_ASSERT(dependency.viewOffset == 0);
505     const auto memBarrier = findStructure<VkMemoryBarrier2>(dependency.pNext);
506     if (memBarrier)
507     {
508         srcStageMask  = memBarrier->srcStageMask;
509         dstStageMask  = memBarrier->dstStageMask;
510         srcAccessMask = memBarrier->srcAccessMask;
511         dstAccessMask = memBarrier->dstAccessMask;
512         sync2         = true;
513     }
514     else
515     {
516         srcStageMask  = dependency.srcStageMask;
517         dstStageMask  = dependency.dstStageMask;
518         srcAccessMask = dependency.srcAccessMask;
519         dstAccessMask = dependency.dstAccessMask;
520     }
521 }
522 #endif // CTS_USES_VULKANSC
523 
RenderPassWrapper(PipelineConstructionType pipelineConstructionType,const DeviceInterface & vk,VkDevice device,const VkRenderPassCreateInfo * pCreateInfo)524 RenderPassWrapper::RenderPassWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk,
525                                      VkDevice device, const VkRenderPassCreateInfo *pCreateInfo)
526     : m_isDynamicRendering(vk::isConstructionTypeShaderObject(pipelineConstructionType))
527 #ifndef CTS_USES_VULKANSC
528     , m_renderingInfo()
529     , m_secondaryCommandBuffers(false)
530 #endif
531 {
532     if (!m_isDynamicRendering)
533     {
534         m_renderPass = vk::createRenderPass(vk, device, pCreateInfo);
535     }
536     else
537     {
538 #ifndef CTS_USES_VULKANSC
539         const auto multiView = findStructure<VkRenderPassMultiviewCreateInfo>(pCreateInfo->pNext);
540         if (multiView)
541         {
542             for (uint32_t i = 0; i < multiView->subpassCount; ++i)
543                 m_viewMasks.push_back(multiView->pViewMasks[i]);
544         }
545 
546         m_attachments.resize(pCreateInfo->attachmentCount);
547         m_layouts.resize(pCreateInfo->attachmentCount);
548         for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i)
549         {
550             m_attachments[i]                = vk::initVulkanStructure();
551             m_attachments[i].flags          = pCreateInfo->pAttachments[i].flags;
552             m_attachments[i].format         = pCreateInfo->pAttachments[i].format;
553             m_attachments[i].samples        = pCreateInfo->pAttachments[i].samples;
554             m_attachments[i].loadOp         = pCreateInfo->pAttachments[i].loadOp;
555             m_attachments[i].storeOp        = pCreateInfo->pAttachments[i].storeOp;
556             m_attachments[i].stencilLoadOp  = pCreateInfo->pAttachments[i].stencilLoadOp;
557             m_attachments[i].stencilStoreOp = pCreateInfo->pAttachments[i].stencilStoreOp;
558             m_attachments[i].initialLayout  = pCreateInfo->pAttachments[i].initialLayout;
559             m_attachments[i].finalLayout    = pCreateInfo->pAttachments[i].finalLayout;
560             m_layouts[i]                    = pCreateInfo->pAttachments[i].initialLayout;
561         }
562 
563         m_subpasses.resize(pCreateInfo->subpassCount);
564         for (uint32_t s = 0; s < pCreateInfo->subpassCount; ++s)
565         {
566             // Input attachments are not supported with dynamic rendering
567             DE_ASSERT(pCreateInfo->pSubpasses[s].inputAttachmentCount == 0);
568             auto &subpass = m_subpasses[s];
569             subpass.m_colorAttachments.resize(pCreateInfo->pSubpasses[s].colorAttachmentCount);
570 
571             for (uint32_t i = 0; i < pCreateInfo->pSubpasses[s].colorAttachmentCount; ++i)
572             {
573                 uint32_t j = pCreateInfo->pSubpasses[s].pColorAttachments[i].attachment;
574                 if (j < pCreateInfo->attachmentCount)
575                 {
576                     subpass.m_colorAttachments[i].attachmentInfo = vk::initVulkanStructure();
577                     subpass.m_colorAttachments[i].index          = j;
578                     subpass.m_colorAttachments[i].format         = pCreateInfo->pAttachments[j].format;
579 
580                     subpass.m_colorAttachments[i].attachmentInfo.imageView = DE_NULL;
581                     subpass.m_colorAttachments[i].attachmentInfo.imageLayout =
582                         pCreateInfo->pSubpasses[s].pColorAttachments[i].layout;
583                     subpass.m_colorAttachments[i].attachmentInfo.resolveMode        = vk::VK_RESOLVE_MODE_NONE;
584                     subpass.m_colorAttachments[i].attachmentInfo.resolveImageView   = DE_NULL;
585                     subpass.m_colorAttachments[i].attachmentInfo.resolveImageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
586                     subpass.m_colorAttachments[i].attachmentInfo.loadOp     = pCreateInfo->pAttachments[j].loadOp;
587                     subpass.m_colorAttachments[i].attachmentInfo.storeOp    = pCreateInfo->pAttachments[j].storeOp;
588                     subpass.m_colorAttachments[i].attachmentInfo.clearValue = {};
589                 }
590                 else
591                 {
592                     subpass.m_colorAttachments[i].index = VK_ATTACHMENT_UNUSED;
593                 }
594             }
595 
596             if (pCreateInfo->pSubpasses[s].pDepthStencilAttachment != DE_NULL)
597             {
598                 uint32_t j = pCreateInfo->pSubpasses[s].pDepthStencilAttachment->attachment;
599                 if (j < pCreateInfo->attachmentCount)
600                 {
601                     subpass.m_depthStencilAttachment.attachmentInfo = vk::initVulkanStructure();
602                     subpass.m_depthStencilAttachment.index          = j;
603                     subpass.m_depthStencilAttachment.format         = pCreateInfo->pAttachments[j].format;
604 
605                     subpass.m_depthStencilAttachment.attachmentInfo.imageView = DE_NULL;
606                     subpass.m_depthStencilAttachment.attachmentInfo.imageLayout =
607                         pCreateInfo->pSubpasses[s].pDepthStencilAttachment->layout;
608                     subpass.m_depthStencilAttachment.attachmentInfo.resolveMode        = vk::VK_RESOLVE_MODE_NONE;
609                     subpass.m_depthStencilAttachment.attachmentInfo.resolveImageView   = DE_NULL;
610                     subpass.m_depthStencilAttachment.attachmentInfo.resolveImageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
611                     subpass.m_depthStencilAttachment.attachmentInfo.loadOp     = pCreateInfo->pAttachments[j].loadOp;
612                     subpass.m_depthStencilAttachment.attachmentInfo.storeOp    = pCreateInfo->pAttachments[j].storeOp;
613                     subpass.m_depthStencilAttachment.attachmentInfo.clearValue = {};
614                     subpass.m_depthStencilAttachment.stencilLoadOp  = pCreateInfo->pAttachments[j].stencilLoadOp;
615                     subpass.m_depthStencilAttachment.stencilStoreOp = pCreateInfo->pAttachments[j].stencilStoreOp;
616                 }
617                 else
618                 {
619                     subpass.m_depthStencilAttachment.index = VK_ATTACHMENT_UNUSED;
620                 }
621             }
622 
623             if (pCreateInfo->pSubpasses[s].pResolveAttachments != DE_NULL)
624             {
625                 subpass.m_resolveAttachments.resize(pCreateInfo->pSubpasses[s].colorAttachmentCount);
626                 for (uint32_t i = 0; i < pCreateInfo->pSubpasses[s].colorAttachmentCount; ++i)
627                 {
628                     uint32_t j = pCreateInfo->pSubpasses[s].pResolveAttachments[i].attachment;
629                     if (j < pCreateInfo->attachmentCount)
630                     {
631                         subpass.m_resolveAttachments[i].attachmentInfo = vk::initVulkanStructure();
632                         subpass.m_resolveAttachments[i].index          = j;
633                         subpass.m_resolveAttachments[i].format         = pCreateInfo->pAttachments[j].format;
634 
635                         subpass.m_resolveAttachments[i].attachmentInfo.imageView = DE_NULL;
636                         subpass.m_resolveAttachments[i].attachmentInfo.imageLayout =
637                             pCreateInfo->pSubpasses[s].pResolveAttachments[i].layout;
638                         subpass.m_resolveAttachments[i].attachmentInfo.resolveMode      = vk::VK_RESOLVE_MODE_NONE;
639                         subpass.m_resolveAttachments[i].attachmentInfo.resolveImageView = DE_NULL;
640                         subpass.m_resolveAttachments[i].attachmentInfo.resolveImageLayout =
641                             vk::VK_IMAGE_LAYOUT_UNDEFINED;
642                         subpass.m_resolveAttachments[i].attachmentInfo.loadOp  = pCreateInfo->pAttachments[j].loadOp;
643                         subpass.m_resolveAttachments[i].attachmentInfo.storeOp = pCreateInfo->pAttachments[j].storeOp;
644                         subpass.m_resolveAttachments[i].attachmentInfo.clearValue = {};
645                     }
646                     else
647                     {
648                         subpass.m_resolveAttachments[i].index = VK_ATTACHMENT_UNUSED;
649                     }
650                 }
651             }
652         }
653 
654         m_dependencies.reserve(pCreateInfo->dependencyCount);
655         for (uint32_t depIdx = 0u; depIdx < pCreateInfo->dependencyCount; ++depIdx)
656             m_dependencies.emplace_back(pCreateInfo->pDependencies[depIdx]);
657 #endif
658     }
659 }
660 
RenderPassWrapper(PipelineConstructionType pipelineConstructionType,const DeviceInterface & vk,VkDevice device,const VkRenderPassCreateInfo2 * pCreateInfo)661 RenderPassWrapper::RenderPassWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk,
662                                      VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo)
663     : RenderPassWrapper(vk, device, pCreateInfo, isConstructionTypeShaderObject(pipelineConstructionType))
664 {
665 }
666 
RenderPassWrapper(const DeviceInterface & vk,VkDevice device,const VkRenderPassCreateInfo2 * pCreateInfo,bool dynamicRendering)667 RenderPassWrapper::RenderPassWrapper(const DeviceInterface &vk, VkDevice device,
668                                      const VkRenderPassCreateInfo2 *pCreateInfo, bool dynamicRendering)
669     : m_isDynamicRendering(dynamicRendering)
670 #ifndef CTS_USES_VULKANSC
671     , m_renderingInfo()
672     , m_secondaryCommandBuffers(false)
673 #endif
674 {
675 
676     if (!m_isDynamicRendering)
677     {
678         m_renderPass = vk::createRenderPass2(vk, device, pCreateInfo);
679     }
680     else
681     {
682 #ifndef CTS_USES_VULKANSC
683         const auto multiView = findStructure<VkRenderPassMultiviewCreateInfo>(pCreateInfo->pNext);
684         if (multiView)
685         {
686             for (uint32_t i = 0; i < multiView->subpassCount; ++i)
687                 m_viewMasks.push_back(multiView->pViewMasks[i]);
688         }
689 
690         m_attachments.resize(pCreateInfo->attachmentCount);
691         m_layouts.resize(pCreateInfo->attachmentCount);
692         for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i)
693         {
694             m_attachments[i] = pCreateInfo->pAttachments[i];
695             m_layouts[i]     = pCreateInfo->pAttachments[i].initialLayout;
696         }
697 
698         m_subpasses.resize(pCreateInfo->subpassCount);
699         for (uint32_t s = 0; s < pCreateInfo->subpassCount; ++s)
700         {
701             // Input attachments are not supported with dynamic rendering
702             DE_ASSERT(pCreateInfo->pSubpasses[s].inputAttachmentCount == 0);
703             auto &subpass = m_subpasses[s];
704             subpass.m_colorAttachments.resize(pCreateInfo->pSubpasses[s].colorAttachmentCount);
705 
706             const auto msrtss =
707                 findStructure<VkMultisampledRenderToSingleSampledInfoEXT>(pCreateInfo->pSubpasses[s].pNext);
708             if (msrtss)
709                 subpass.m_msrtss = *msrtss;
710 
711             const auto dsr = findStructure<VkSubpassDescriptionDepthStencilResolve>(pCreateInfo->pSubpasses[s].pNext);
712             if (dsr)
713             {
714                 subpass.m_dsr = *dsr;
715                 if (dsr->pDepthStencilResolveAttachment)
716                 {
717                     subpass.m_depthStencilResolveAttachment      = *dsr->pDepthStencilResolveAttachment;
718                     subpass.m_dsr.pDepthStencilResolveAttachment = &subpass.m_depthStencilResolveAttachment;
719                 }
720             }
721 
722             for (uint32_t i = 0; i < pCreateInfo->pSubpasses[s].colorAttachmentCount; ++i)
723             {
724                 uint32_t j = pCreateInfo->pSubpasses[s].pColorAttachments[i].attachment;
725                 if (j < pCreateInfo->attachmentCount)
726                 {
727                     subpass.m_colorAttachments[i].attachmentInfo = vk::initVulkanStructure();
728                     subpass.m_colorAttachments[i].index          = j;
729                     subpass.m_colorAttachments[i].format         = pCreateInfo->pAttachments[j].format;
730 
731                     subpass.m_colorAttachments[i].attachmentInfo.imageView = DE_NULL;
732                     subpass.m_colorAttachments[i].attachmentInfo.imageLayout =
733                         pCreateInfo->pSubpasses[s].pColorAttachments[i].layout;
734                     subpass.m_colorAttachments[i].attachmentInfo.resolveMode        = vk::VK_RESOLVE_MODE_NONE;
735                     subpass.m_colorAttachments[i].attachmentInfo.resolveImageView   = DE_NULL;
736                     subpass.m_colorAttachments[i].attachmentInfo.resolveImageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
737                     subpass.m_colorAttachments[i].attachmentInfo.loadOp     = pCreateInfo->pAttachments[j].loadOp;
738                     subpass.m_colorAttachments[i].attachmentInfo.storeOp    = pCreateInfo->pAttachments[j].storeOp;
739                     subpass.m_colorAttachments[i].attachmentInfo.clearValue = {};
740                 }
741                 else
742                 {
743                     subpass.m_colorAttachments[i].index = VK_ATTACHMENT_UNUSED;
744                 }
745             }
746 
747             if (pCreateInfo->pSubpasses[s].pDepthStencilAttachment != DE_NULL)
748             {
749                 uint32_t j = pCreateInfo->pSubpasses[s].pDepthStencilAttachment->attachment;
750                 if (j < pCreateInfo->attachmentCount)
751                 {
752                     subpass.m_depthStencilAttachment.attachmentInfo = vk::initVulkanStructure();
753                     subpass.m_depthStencilAttachment.index          = j;
754                     subpass.m_depthStencilAttachment.format         = pCreateInfo->pAttachments[j].format;
755 
756                     subpass.m_depthStencilAttachment.attachmentInfo.imageView = DE_NULL;
757                     subpass.m_depthStencilAttachment.attachmentInfo.imageLayout =
758                         pCreateInfo->pSubpasses[s].pDepthStencilAttachment->layout;
759                     subpass.m_depthStencilAttachment.attachmentInfo.resolveMode        = vk::VK_RESOLVE_MODE_NONE;
760                     subpass.m_depthStencilAttachment.attachmentInfo.resolveImageView   = DE_NULL;
761                     subpass.m_depthStencilAttachment.attachmentInfo.resolveImageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
762                     subpass.m_depthStencilAttachment.attachmentInfo.loadOp     = pCreateInfo->pAttachments[j].loadOp;
763                     subpass.m_depthStencilAttachment.attachmentInfo.storeOp    = pCreateInfo->pAttachments[j].storeOp;
764                     subpass.m_depthStencilAttachment.attachmentInfo.clearValue = {};
765                     subpass.m_depthStencilAttachment.stencilLoadOp  = pCreateInfo->pAttachments[j].stencilLoadOp;
766                     subpass.m_depthStencilAttachment.stencilStoreOp = pCreateInfo->pAttachments[j].stencilStoreOp;
767                 }
768                 else
769                 {
770                     subpass.m_depthStencilAttachment.index = VK_ATTACHMENT_UNUSED;
771                 }
772             }
773 
774             if (pCreateInfo->pSubpasses[s].pResolveAttachments != DE_NULL)
775             {
776                 subpass.m_resolveAttachments.resize(pCreateInfo->pSubpasses[s].colorAttachmentCount);
777                 for (uint32_t i = 0; i < pCreateInfo->pSubpasses[s].colorAttachmentCount; ++i)
778                 {
779                     uint32_t j = pCreateInfo->pSubpasses[s].pResolveAttachments[i].attachment;
780                     if (j < pCreateInfo->attachmentCount)
781                     {
782                         subpass.m_resolveAttachments[i].attachmentInfo = vk::initVulkanStructure();
783                         subpass.m_resolveAttachments[i].index          = j;
784                         subpass.m_resolveAttachments[i].format         = pCreateInfo->pAttachments[j].format;
785 
786                         subpass.m_resolveAttachments[i].attachmentInfo.imageView = DE_NULL;
787                         subpass.m_resolveAttachments[i].attachmentInfo.imageLayout =
788                             pCreateInfo->pSubpasses[s].pResolveAttachments[i].layout;
789                         subpass.m_resolveAttachments[i].attachmentInfo.resolveMode      = vk::VK_RESOLVE_MODE_NONE;
790                         subpass.m_resolveAttachments[i].attachmentInfo.resolveImageView = DE_NULL;
791                         subpass.m_resolveAttachments[i].attachmentInfo.resolveImageLayout =
792                             vk::VK_IMAGE_LAYOUT_UNDEFINED;
793                         subpass.m_resolveAttachments[i].attachmentInfo.loadOp  = pCreateInfo->pAttachments[j].loadOp;
794                         subpass.m_resolveAttachments[i].attachmentInfo.storeOp = pCreateInfo->pAttachments[j].storeOp;
795                         subpass.m_resolveAttachments[i].attachmentInfo.clearValue = {};
796                     }
797                     else
798                     {
799                         subpass.m_resolveAttachments[i].index = VK_ATTACHMENT_UNUSED;
800                     }
801                 }
802             }
803         }
804 
805         m_dependencies.reserve(pCreateInfo->dependencyCount);
806         for (uint32_t depIdx = 0u; depIdx < pCreateInfo->dependencyCount; ++depIdx)
807             m_dependencies.emplace_back(pCreateInfo->pDependencies[depIdx]);
808 #endif
809     }
810 }
811 
RenderPassWrapper(PipelineConstructionType pipelineConstructionType,const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat depthStencilFormat,const VkAttachmentLoadOp loadOperation,const VkImageLayout finalLayoutColor,const VkImageLayout finalLayoutDepthStencil,const VkImageLayout subpassLayoutColor,const VkImageLayout subpassLayoutDepthStencil,const VkAllocationCallbacks * const allocationCallbacks)812 RenderPassWrapper::RenderPassWrapper(PipelineConstructionType pipelineConstructionType, const DeviceInterface &vk,
813                                      const VkDevice device, const VkFormat colorFormat,
814                                      const VkFormat depthStencilFormat, const VkAttachmentLoadOp loadOperation,
815                                      const VkImageLayout finalLayoutColor, const VkImageLayout finalLayoutDepthStencil,
816                                      const VkImageLayout subpassLayoutColor,
817                                      const VkImageLayout subpassLayoutDepthStencil,
818                                      const VkAllocationCallbacks *const allocationCallbacks)
819     : m_isDynamicRendering(isConstructionTypeShaderObject(pipelineConstructionType))
820 #ifndef CTS_USES_VULKANSC
821     , m_renderingInfo()
822 #endif
823 {
824 
825     if (!m_isDynamicRendering)
826     {
827         m_renderPass = vk::makeRenderPass(vk, device, colorFormat, depthStencilFormat, loadOperation, finalLayoutColor,
828                                           finalLayoutDepthStencil, subpassLayoutColor, subpassLayoutDepthStencil,
829                                           allocationCallbacks);
830     }
831     else
832     {
833 #ifndef CTS_USES_VULKANSC
834         const bool hasColor                           = colorFormat != VK_FORMAT_UNDEFINED;
835         const bool hasDepthStencil                    = depthStencilFormat != VK_FORMAT_UNDEFINED;
836         const VkImageLayout initialLayoutColor        = loadOperation == VK_ATTACHMENT_LOAD_OP_LOAD ?
837                                                             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL :
838                                                             VK_IMAGE_LAYOUT_UNDEFINED;
839         const VkImageLayout initialLayoutDepthStencil = loadOperation == VK_ATTACHMENT_LOAD_OP_LOAD ?
840                                                             VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL :
841                                                             VK_IMAGE_LAYOUT_UNDEFINED;
842 
843         m_subpasses.resize(1);
844         auto &subpass = m_subpasses[0];
845 
846         if (hasColor)
847         {
848             subpass.m_colorAttachments.resize(1);
849             subpass.m_colorAttachments[0].attachmentInfo = vk::initVulkanStructure();
850             subpass.m_colorAttachments[0].index          = 0u;
851             subpass.m_colorAttachments[0].format         = colorFormat;
852 
853             subpass.m_colorAttachments[0].attachmentInfo.imageView          = DE_NULL;
854             subpass.m_colorAttachments[0].attachmentInfo.imageLayout        = subpassLayoutColor;
855             subpass.m_colorAttachments[0].attachmentInfo.resolveMode        = vk::VK_RESOLVE_MODE_NONE;
856             subpass.m_colorAttachments[0].attachmentInfo.resolveImageView   = DE_NULL;
857             subpass.m_colorAttachments[0].attachmentInfo.resolveImageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
858             subpass.m_colorAttachments[0].attachmentInfo.loadOp             = loadOperation;
859             subpass.m_colorAttachments[0].attachmentInfo.storeOp            = VK_ATTACHMENT_STORE_OP_STORE;
860             subpass.m_colorAttachments[0].attachmentInfo.clearValue         = {};
861 
862             const VkAttachmentDescription2 colorAttachmentDescription = {
863                 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
864                 DE_NULL,
865                 (VkAttachmentDescriptionFlags)0,  // VkAttachmentDescriptionFlags    flags
866                 colorFormat,                      // VkFormat                        format
867                 VK_SAMPLE_COUNT_1_BIT,            // VkSampleCountFlagBits           samples
868                 loadOperation,                    // VkAttachmentLoadOp              loadOp
869                 VK_ATTACHMENT_STORE_OP_STORE,     // VkAttachmentStoreOp             storeOp
870                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,  // VkAttachmentLoadOp              stencilLoadOp
871                 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp             stencilStoreOp
872                 initialLayoutColor,               // VkImageLayout                   initialLayout
873                 finalLayoutColor                  // VkImageLayout                   finalLayout
874             };
875             m_attachments.push_back(colorAttachmentDescription);
876             m_layouts.push_back(colorAttachmentDescription.initialLayout);
877         }
878         if (hasDepthStencil)
879         {
880             subpass.m_depthStencilAttachment.attachmentInfo = vk::initVulkanStructure();
881             subpass.m_depthStencilAttachment.index          = hasColor ? 1u : 0u;
882             subpass.m_depthStencilAttachment.format         = depthStencilFormat;
883 
884             subpass.m_depthStencilAttachment.attachmentInfo.imageView          = DE_NULL;
885             subpass.m_depthStencilAttachment.attachmentInfo.imageLayout        = subpassLayoutDepthStencil;
886             subpass.m_depthStencilAttachment.attachmentInfo.resolveMode        = vk::VK_RESOLVE_MODE_NONE;
887             subpass.m_depthStencilAttachment.attachmentInfo.resolveImageView   = DE_NULL;
888             subpass.m_depthStencilAttachment.attachmentInfo.resolveImageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
889             subpass.m_depthStencilAttachment.attachmentInfo.loadOp             = loadOperation;
890             subpass.m_depthStencilAttachment.attachmentInfo.storeOp            = VK_ATTACHMENT_STORE_OP_STORE;
891             subpass.m_depthStencilAttachment.attachmentInfo.clearValue         = {};
892             subpass.m_depthStencilAttachment.stencilLoadOp                     = loadOperation;
893             subpass.m_depthStencilAttachment.stencilStoreOp                    = VK_ATTACHMENT_STORE_OP_STORE;
894 
895             const VkAttachmentDescription2 depthStencilAttachmentDescription = {
896                 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
897                 DE_NULL,
898                 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags    flags
899                 depthStencilFormat,              // VkFormat                        format
900                 VK_SAMPLE_COUNT_1_BIT,           // VkSampleCountFlagBits           samples
901                 loadOperation,                   // VkAttachmentLoadOp              loadOp
902                 VK_ATTACHMENT_STORE_OP_STORE,    // VkAttachmentStoreOp             storeOp
903                 loadOperation,                   // VkAttachmentLoadOp              stencilLoadOp
904                 VK_ATTACHMENT_STORE_OP_STORE,    // VkAttachmentStoreOp             stencilStoreOp
905                 initialLayoutDepthStencil,       // VkImageLayout                   initialLayout
906                 finalLayoutDepthStencil          // VkImageLayout                   finalLayout
907             };
908             m_attachments.push_back(depthStencilAttachmentDescription);
909             m_layouts.push_back(depthStencilAttachmentDescription.initialLayout);
910         }
911 #endif
912     }
913 }
914 
RenderPassWrapper(RenderPassWrapper && rhs)915 RenderPassWrapper::RenderPassWrapper(RenderPassWrapper &&rhs) noexcept
916     : m_isDynamicRendering(rhs.m_isDynamicRendering)
917     , m_renderPass(rhs.m_renderPass)
918     , m_framebuffer(rhs.m_framebuffer)
919 #ifndef CTS_USES_VULKANSC
920     , m_subpasses(std::move(rhs.m_subpasses))
921     , m_dependencies(std::move(rhs.m_dependencies))
922     , m_attachments(std::move(rhs.m_attachments))
923     , m_images(std::move(rhs.m_images))
924     , m_imageViews(std::move(rhs.m_imageViews))
925     , m_clearValues(std::move(rhs.m_clearValues))
926     , m_layouts(std::move(rhs.m_layouts))
927     , m_activeSubpass(rhs.m_activeSubpass)
928     , m_renderingInfo(rhs.m_renderingInfo)
929     , m_layers(rhs.m_layers)
930     , m_viewMasks(std::move(rhs.m_viewMasks))
931     , m_secondaryCommandBuffers(rhs.m_secondaryCommandBuffers)
932 #endif
933 {
934 }
935 
operator =(RenderPassWrapper && rhs)936 RenderPassWrapper &RenderPassWrapper::operator=(RenderPassWrapper &&rhs) noexcept
937 {
938     m_isDynamicRendering = rhs.m_isDynamicRendering;
939     m_renderPass         = rhs.m_renderPass;
940     m_framebuffer        = rhs.m_framebuffer;
941 #ifndef CTS_USES_VULKANSC
942     m_subpasses               = std::move(rhs.m_subpasses);
943     m_dependencies            = std::move(rhs.m_dependencies);
944     m_attachments             = std::move(rhs.m_attachments);
945     m_images                  = std::move(rhs.m_images);
946     m_imageViews              = std::move(rhs.m_imageViews);
947     m_clearValues             = std::move(rhs.m_clearValues);
948     m_layouts                 = std::move(rhs.m_layouts);
949     m_activeSubpass           = rhs.m_activeSubpass;
950     m_renderingInfo           = rhs.m_renderingInfo;
951     m_layers                  = rhs.m_layers;
952     m_viewMasks               = std::move(rhs.m_viewMasks);
953     m_secondaryCommandBuffers = rhs.m_secondaryCommandBuffers;
954 #endif
955     return *this;
956 }
957 
958 #ifndef CTS_USES_VULKANSC
959 
clearAttachments(const DeviceInterface & vk,const VkCommandBuffer commandBuffer) const960 void RenderPassWrapper::clearAttachments(const DeviceInterface &vk, const VkCommandBuffer commandBuffer) const
961 {
962     for (uint32_t i = 0; i < (uint32_t)m_attachments.size() && i < (uint32_t)m_clearValues.size(); ++i)
963     {
964         const auto tcuFormat  = vk::mapVkFormat(m_attachments[i].format);
965         bool hasDepthAspect   = tcu::hasDepthComponent(tcuFormat.order);
966         bool hasStencilAspect = tcu::hasStencilComponent(tcuFormat.order);
967 
968         if (m_attachments[i].loadOp != vk::VK_ATTACHMENT_LOAD_OP_CLEAR &&
969             !(hasStencilAspect && m_attachments[i].stencilLoadOp == vk::VK_ATTACHMENT_LOAD_OP_CLEAR))
970             continue;
971 
972         vk::VkRenderingInfo renderingInfo = vk::initVulkanStructure();
973         renderingInfo.renderArea          = m_renderingInfo.renderArea;
974         renderingInfo.layerCount          = m_renderingInfo.layerCount;
975 
976         vk::VkRenderingAttachmentInfo attachment = vk::initVulkanStructure();
977         attachment.imageView                     = m_imageViews[i];
978         attachment.imageLayout                   = m_layouts[i];
979         attachment.loadOp                        = vk::VK_ATTACHMENT_LOAD_OP_CLEAR;
980         attachment.storeOp                       = vk::VK_ATTACHMENT_STORE_OP_STORE;
981         attachment.clearValue                    = m_clearValues[i];
982 
983         if (hasDepthAspect || hasStencilAspect)
984         {
985             renderingInfo.pDepthAttachment   = hasDepthAspect ? &attachment : DE_NULL;
986             renderingInfo.pStencilAttachment = hasStencilAspect ? &attachment : DE_NULL;
987         }
988         else
989         {
990             renderingInfo.colorAttachmentCount = 1u;
991             renderingInfo.pColorAttachments    = &attachment;
992         }
993 
994         vk.cmdBeginRendering(commandBuffer, &renderingInfo);
995         vk.cmdEndRendering(commandBuffer);
996     }
997 }
998 
updateLayout(VkImage updatedImage,VkImageLayout newLayout) const999 void RenderPassWrapper::updateLayout(VkImage updatedImage, VkImageLayout newLayout) const
1000 {
1001     for (uint32_t i = 0; i < (uint32_t)m_images.size(); ++i)
1002         if (m_images[i] == updatedImage)
1003             m_layouts[i] = newLayout;
1004 }
1005 
1006 namespace
1007 {
1008 
recordImageBarrier(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const bool sync2,const VkPipelineStageFlags2 srcStageMask,const VkAccessFlags2 srcAccessMask,const VkPipelineStageFlags2 dstStageMask,const VkAccessFlags2 dstAccessMask,const VkImageLayout prevLayout,const VkImageLayout newLayout,const VkImage image,const VkImageSubresourceRange & subresourceRange)1009 void recordImageBarrier(const DeviceInterface &vk, const VkCommandBuffer commandBuffer, const bool sync2,
1010                         const VkPipelineStageFlags2 srcStageMask, const VkAccessFlags2 srcAccessMask,
1011                         const VkPipelineStageFlags2 dstStageMask, const VkAccessFlags2 dstAccessMask,
1012                         const VkImageLayout prevLayout, const VkImageLayout newLayout, const VkImage image,
1013                         const VkImageSubresourceRange &subresourceRange)
1014 {
1015     if (sync2)
1016     {
1017         const auto barrier = makeImageMemoryBarrier2(srcStageMask, srcAccessMask, dstStageMask, dstAccessMask,
1018                                                      prevLayout, newLayout, image, subresourceRange);
1019 
1020         const VkDependencyInfo depInfo = {
1021             VK_STRUCTURE_TYPE_DEPENDENCY_INFO, // VkStructureType sType;
1022             nullptr,                           // const void* pNext;
1023             0u,                                // VkDependencyFlags dependencyFlags;
1024             0u,                                // uint32_t memoryBarrierCount;
1025             nullptr,                           // const VkMemoryBarrier2* pMemoryBarriers;
1026             0u,                                // uint32_t bufferMemoryBarrierCount;
1027             nullptr,                           // const VkBufferMemoryBarrier2* pBufferMemoryBarriers;
1028             1u,                                // uint32_t imageMemoryBarrierCount;
1029             &barrier,                          // const VkImageMemoryBarrier2* pImageMemoryBarriers;
1030         };
1031 
1032         vk.cmdPipelineBarrier2(commandBuffer, &depInfo);
1033     }
1034     else
1035     {
1036         const auto barrier =
1037             makeImageMemoryBarrier(static_cast<VkAccessFlags>(srcAccessMask), static_cast<VkAccessFlags>(dstAccessMask),
1038                                    prevLayout, newLayout, image, subresourceRange);
1039 
1040         vk.cmdPipelineBarrier(commandBuffer, static_cast<VkPipelineStageFlags>(srcStageMask),
1041                               static_cast<VkPipelineStageFlags>(dstStageMask), 0u, 0u, nullptr, 0u, nullptr, 1u,
1042                               &barrier);
1043     }
1044 }
1045 
1046 } // anonymous namespace
1047 
transitionLayouts(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const Subpass & subpass,bool renderPassBegin) const1048 void RenderPassWrapper::transitionLayouts(const DeviceInterface &vk, const VkCommandBuffer commandBuffer,
1049                                           const Subpass &subpass, bool renderPassBegin) const
1050 {
1051     // Use the access and stage flags for dependencies on external subpasses in
1052     // the initial layout transitions for images.
1053     VkAccessFlags2 externalAccessFlags       = 0u;
1054     VkPipelineStageFlags2 externalStageFlags = 0u;
1055     bool sync2                               = false;
1056 
1057     if (renderPassBegin)
1058     {
1059         for (const auto &dep : m_dependencies)
1060         {
1061             if (dep.srcSubpass == VK_SUBPASS_EXTERNAL)
1062             {
1063                 externalAccessFlags |= dep.srcAccessMask;
1064                 externalStageFlags |= dep.srcStageMask;
1065             }
1066 
1067             if (dep.sync2)
1068                 sync2 = true;
1069         }
1070     }
1071 
1072     for (uint32_t i = 0; i < (uint32_t)m_attachments.size(); ++i)
1073     {
1074         // renderPassBegin is true when vkCmdBeginRenderPass should be called in a normal renderPass, and it is false when vkCmdNextSupass should be called
1075         // Every image is transioned from VK_IMAGE_LAYOUT_UNDEFINED to it's first used layout, so that all images can be cleared in the beginning
1076         if (renderPassBegin && m_layouts[i] != vk::VK_IMAGE_LAYOUT_UNDEFINED)
1077             continue;
1078 
1079         if (m_images[i] != VK_NULL_HANDLE)
1080         {
1081             for (uint32_t j = 0; j < (uint32_t)subpass.m_colorAttachments.size(); ++j)
1082             {
1083                 if (subpass.m_colorAttachments[j].index == i)
1084                 {
1085                     const auto subresourceRange = makeImageSubresourceRange(
1086                         vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, VK_REMAINING_MIP_LEVELS, 0u, VK_REMAINING_ARRAY_LAYERS);
1087 
1088                     const VkPipelineStageFlags2 srcStageMask =
1089                         (vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | externalStageFlags);
1090                     const VkAccessFlags2 srcAccessMask       = externalAccessFlags;
1091                     const VkPipelineStageFlags2 dstStageMask = vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1092                     const VkAccessFlags2 dstAccessMask       = vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1093                     const VkImageLayout newLayout            = subpass.m_colorAttachments[j].attachmentInfo.imageLayout;
1094 
1095                     recordImageBarrier(vk, commandBuffer, sync2, srcStageMask, srcAccessMask, dstStageMask,
1096                                        dstAccessMask, m_layouts[i], newLayout, m_images[i], subresourceRange);
1097 
1098                     updateLayout(m_images[i], newLayout);
1099                 }
1100             }
1101             if (subpass.m_depthStencilAttachment.index == i)
1102             {
1103                 const auto tcuFormat        = vk::mapVkFormat(subpass.m_depthStencilAttachment.format);
1104                 const bool hasDepthAspect   = tcu::hasDepthComponent(tcuFormat.order);
1105                 const bool hasStencilAspect = tcu::hasStencilComponent(tcuFormat.order);
1106 
1107                 VkImageAspectFlags aspect = (VkImageAspectFlags)0u;
1108                 if (hasDepthAspect)
1109                     aspect |= vk::VK_IMAGE_ASPECT_DEPTH_BIT;
1110                 if (hasStencilAspect)
1111                     aspect |= vk::VK_IMAGE_ASPECT_STENCIL_BIT;
1112 
1113                 const auto subresourceRange =
1114                     makeImageSubresourceRange(aspect, 0u, VK_REMAINING_MIP_LEVELS, 0u, VK_REMAINING_ARRAY_LAYERS);
1115 
1116                 const VkPipelineStageFlags2 srcStageMask = (vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | externalStageFlags);
1117                 const VkAccessFlags2 srcAccessMask       = externalAccessFlags;
1118                 const VkPipelineStageFlags2 dstStageMask =
1119                     (vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1120                 const VkAccessFlags2 dstAccessMask = (vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
1121                                                       vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
1122                 const VkImageLayout newLayout      = subpass.m_depthStencilAttachment.attachmentInfo.imageLayout;
1123 
1124                 recordImageBarrier(vk, commandBuffer, sync2, srcStageMask, srcAccessMask, dstStageMask, dstAccessMask,
1125                                    m_layouts[i], newLayout, m_images[i], subresourceRange);
1126 
1127                 updateLayout(m_images[i], newLayout);
1128             }
1129             for (uint32_t j = 0; j < (uint32_t)subpass.m_resolveAttachments.size(); ++j)
1130             {
1131                 if (subpass.m_resolveAttachments[j].index == i)
1132                 {
1133                     const auto subresourceRange = makeImageSubresourceRange(
1134                         vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, VK_REMAINING_MIP_LEVELS, 0u, VK_REMAINING_ARRAY_LAYERS);
1135 
1136                     const VkPipelineStageFlags2 srcStageMask =
1137                         (vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | externalStageFlags);
1138                     const VkAccessFlags2 srcAccessMask       = externalAccessFlags;
1139                     const VkPipelineStageFlags2 dstStageMask = vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1140                     const VkAccessFlags2 dstAccessMask       = vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1141                     const VkImageLayout newLayout = subpass.m_resolveAttachments[j].attachmentInfo.imageLayout;
1142 
1143                     recordImageBarrier(vk, commandBuffer, sync2, srcStageMask, srcAccessMask, dstStageMask,
1144                                        dstAccessMask, m_layouts[i], newLayout, m_images[i], subresourceRange);
1145 
1146                     updateLayout(m_images[i], newLayout);
1147                 }
1148             }
1149             if (subpass.m_dsr.sType == vk::VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE)
1150             {
1151                 if (subpass.m_dsr.pDepthStencilResolveAttachment &&
1152                     i == subpass.m_dsr.pDepthStencilResolveAttachment->attachment)
1153                 {
1154                     const auto tcuFormat        = vk::mapVkFormat(subpass.m_depthStencilAttachment.format);
1155                     const bool hasDepthAspect   = tcu::hasDepthComponent(tcuFormat.order);
1156                     const bool hasStencilAspect = tcu::hasStencilComponent(tcuFormat.order);
1157 
1158                     VkImageAspectFlags aspect = (VkImageAspectFlags)0u;
1159                     if (hasDepthAspect)
1160                         aspect |= vk::VK_IMAGE_ASPECT_DEPTH_BIT;
1161                     if (hasStencilAspect)
1162                         aspect |= vk::VK_IMAGE_ASPECT_STENCIL_BIT;
1163 
1164                     const auto subresourceRange =
1165                         makeImageSubresourceRange(aspect, 0u, VK_REMAINING_MIP_LEVELS, 0u, VK_REMAINING_ARRAY_LAYERS);
1166 
1167                     const VkPipelineStageFlags2 srcStageMask =
1168                         (vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | externalStageFlags);
1169                     const VkAccessFlags2 srcAccessMask       = externalAccessFlags;
1170                     const VkPipelineStageFlags2 dstStageMask = (vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
1171                                                                 vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1172                     const VkAccessFlags2 dstAccessMask       = vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
1173                                                          vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
1174                     const VkImageLayout newLayout = subpass.m_dsr.pDepthStencilResolveAttachment->layout;
1175 
1176                     recordImageBarrier(vk, commandBuffer, sync2, srcStageMask, srcAccessMask, dstStageMask,
1177                                        dstAccessMask, m_layouts[i], newLayout, m_images[i], subresourceRange);
1178 
1179                     updateLayout(m_images[i], newLayout);
1180                 }
1181             }
1182         }
1183     }
1184 }
1185 
insertDependencies(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,uint32_t subpassIdx) const1186 void RenderPassWrapper::insertDependencies(const DeviceInterface &vk, const VkCommandBuffer commandBuffer,
1187                                            uint32_t subpassIdx) const
1188 {
1189     for (const auto &dep : m_dependencies)
1190     {
1191         // Subpass self-dependencies should be handled with manual barriers inside the render pass.
1192         if (dep.dstSubpass != subpassIdx || dep.srcSubpass == subpassIdx)
1193             continue;
1194 
1195         if (dep.sync2)
1196         {
1197             const VkMemoryBarrier2 barrier = {
1198                 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType;
1199                 nullptr,                          // const void* pNext;
1200                 dep.srcStageMask,                 // VkPipelineStageFlags2 srcStageMask;
1201                 dep.srcAccessMask,                // VkAccessFlags2 srcAccessMask;
1202                 dep.dstStageMask,                 // VkPipelineStageFlags2 dstStageMask;
1203                 dep.dstAccessMask,                // VkAccessFlags2 dstAccessMask;
1204             };
1205             const VkDependencyInfo depInfo = {
1206                 VK_STRUCTURE_TYPE_DEPENDENCY_INFO, // VkStructureType sType;
1207                 nullptr,                           // const void* pNext;
1208                 dep.dependencyFlags,               // VkDependencyFlags dependencyFlags;
1209                 1u,                                // uint32_t memoryBarrierCount;
1210                 &barrier,                          // const VkMemoryBarrier2* pMemoryBarriers;
1211                 0u,                                // uint32_t bufferMemoryBarrierCount;
1212                 nullptr,                           // const VkBufferMemoryBarrier2* pBufferMemoryBarriers;
1213                 0u,                                // uint32_t imageMemoryBarrierCount;
1214                 nullptr,                           // const VkImageMemoryBarrier2* pImageMemoryBarriers;
1215             };
1216             vk.cmdPipelineBarrier2(commandBuffer, &depInfo);
1217         }
1218         else
1219         {
1220             const VkMemoryBarrier barrier = {
1221                 VK_STRUCTURE_TYPE_MEMORY_BARRIER,              // VkStructureType sType;
1222                 nullptr,                                       // const void* pNext;
1223                 static_cast<VkAccessFlags>(dep.srcAccessMask), // VkAccessFlags srcAccessMask;
1224                 static_cast<VkAccessFlags>(dep.dstAccessMask), // VkAccessFlags dstAccessMask;
1225             };
1226             vk.cmdPipelineBarrier(commandBuffer, static_cast<VkPipelineStageFlags>(dep.srcStageMask),
1227                                   static_cast<VkPipelineStageFlags>(dep.dstStageMask), dep.dependencyFlags, 1u,
1228                                   &barrier, 0u, nullptr, 0u, nullptr);
1229         }
1230     }
1231 }
1232 
fillInheritanceRenderingInfo(uint32_t subpassIndex,std::vector<vk::VkFormat> * colorFormats,vk::VkCommandBufferInheritanceRenderingInfo * inheritanceRenderingInfo) const1233 void RenderPassWrapper::fillInheritanceRenderingInfo(
1234     uint32_t subpassIndex, std::vector<vk::VkFormat> *colorFormats,
1235     vk::VkCommandBufferInheritanceRenderingInfo *inheritanceRenderingInfo) const
1236 {
1237     const auto &subpass = m_subpasses[subpassIndex];
1238     colorFormats->resize(subpass.m_colorAttachments.size());
1239     for (uint32_t i = 0; i < (uint32_t)subpass.m_colorAttachments.size(); ++i)
1240         (*colorFormats)[i] = subpass.m_colorAttachments[i].format;
1241 
1242     inheritanceRenderingInfo->colorAttachmentCount    = (uint32_t)subpass.m_colorAttachments.size();
1243     inheritanceRenderingInfo->pColorAttachmentFormats = colorFormats->data();
1244 
1245     if (subpass.m_depthStencilAttachment.format != vk::VK_FORMAT_UNDEFINED)
1246     {
1247         const auto tcuFormat = vk::mapVkFormat(subpass.m_depthStencilAttachment.format);
1248         if (tcu::hasDepthComponent(tcuFormat.order))
1249             inheritanceRenderingInfo->depthAttachmentFormat = subpass.m_depthStencilAttachment.format;
1250         if (tcu::hasStencilComponent(tcuFormat.order))
1251             inheritanceRenderingInfo->stencilAttachmentFormat = subpass.m_depthStencilAttachment.format;
1252     }
1253 
1254     if (subpassIndex < (uint32_t)m_viewMasks.size())
1255         inheritanceRenderingInfo->viewMask = m_viewMasks[subpassIndex];
1256 }
1257 
1258 #endif
1259 
1260 // If a render pass is reused, image layouts have to be reset so that when vkCmdBeginRenderPass is called image layouts are transitioned correctly
resetLayouts(void)1261 void RenderPassWrapper::resetLayouts(void)
1262 {
1263 #ifndef CTS_USES_VULKANSC
1264     for (auto &layout : m_layouts)
1265         layout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
1266 #endif
1267 }
1268 
begin(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkRect2D & renderArea,const uint32_t clearValueCount,const VkClearValue * clearValues,const VkSubpassContents contents,const void * pNext) const1269 void RenderPassWrapper::begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer,
1270                               const VkRect2D &renderArea, const uint32_t clearValueCount,
1271                               const VkClearValue *clearValues, const VkSubpassContents contents,
1272                               const void *pNext) const
1273 {
1274     if (!m_isDynamicRendering)
1275     {
1276         beginRenderPass(vk, commandBuffer, *m_renderPass, *m_framebuffer, renderArea, clearValueCount, clearValues,
1277                         contents, pNext);
1278     }
1279     else
1280     {
1281 #ifndef CTS_USES_VULKANSC
1282         m_activeSubpass = 0;
1283 
1284         m_clearValues.resize(clearValueCount);
1285         for (uint32_t i = 0; i < clearValueCount; ++i)
1286             m_clearValues[i] = clearValues[i];
1287 
1288         for (uint32_t i = 0; i < (uint32_t)m_subpasses.size(); ++i)
1289             transitionLayouts(vk, commandBuffer, m_subpasses[i], true);
1290 
1291         insertDependencies(vk, commandBuffer, 0u);
1292 
1293         m_secondaryCommandBuffers = contents == vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
1294 
1295         m_renderingInfo            = vk::initVulkanStructure();
1296         m_renderingInfo.flags      = (vk::VkRenderingFlags)0u;
1297         m_renderingInfo.renderArea = renderArea;
1298         m_renderingInfo.layerCount = m_layers;
1299         m_renderingInfo.viewMask   = 0x0;
1300 
1301         clearAttachments(vk, commandBuffer);
1302 
1303         beginRendering(vk, commandBuffer);
1304 #endif
1305     }
1306 }
1307 
begin(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkRect2D & renderArea,const VkClearValue & clearValue,const VkSubpassContents contents) const1308 void RenderPassWrapper::begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer,
1309                               const VkRect2D &renderArea, const VkClearValue &clearValue,
1310                               const VkSubpassContents contents) const
1311 {
1312     begin(vk, commandBuffer, renderArea, 1u, &clearValue, contents);
1313 }
1314 
begin(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkRect2D & renderArea,const tcu::Vec4 & clearColor,const VkSubpassContents contents) const1315 void RenderPassWrapper::begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer,
1316                               const VkRect2D &renderArea, const tcu::Vec4 &clearColor,
1317                               const VkSubpassContents contents) const
1318 {
1319     const VkClearValue clearValue = makeClearValueColor(clearColor);
1320     begin(vk, commandBuffer, renderArea, clearValue, contents);
1321 }
1322 
begin(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkRect2D & renderArea,const tcu::Vec4 & clearColor,const float clearDepth,const uint32_t clearStencil,const VkSubpassContents contents) const1323 void RenderPassWrapper::begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer,
1324                               const VkRect2D &renderArea, const tcu::Vec4 &clearColor, const float clearDepth,
1325                               const uint32_t clearStencil, const VkSubpassContents contents) const
1326 {
1327     const VkClearValue clearValues[] = {
1328         makeClearValueColor(clearColor),                      // attachment 0
1329         makeClearValueDepthStencil(clearDepth, clearStencil), // attachment 1
1330     };
1331     begin(vk, commandBuffer, renderArea, 2, clearValues, contents);
1332 }
1333 
begin(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkRect2D & renderArea,const VkSubpassContents contents) const1334 void RenderPassWrapper::begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer,
1335                               const VkRect2D &renderArea, const VkSubpassContents contents) const
1336 {
1337     begin(vk, commandBuffer, renderArea, 0u, DE_NULL, contents);
1338 }
1339 
begin(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkRect2D & renderArea,const tcu::UVec4 & clearColor,const VkSubpassContents contents) const1340 void RenderPassWrapper::begin(const DeviceInterface &vk, const VkCommandBuffer commandBuffer,
1341                               const VkRect2D &renderArea, const tcu::UVec4 &clearColor,
1342                               const VkSubpassContents contents) const
1343 {
1344     const VkClearValue clearValue =
1345         makeClearValueColorU32(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
1346 
1347     begin(vk, commandBuffer, renderArea, clearValue, contents);
1348 }
1349 
end(const DeviceInterface & vk,const VkCommandBuffer commandBuffer) const1350 void RenderPassWrapper::end(const DeviceInterface &vk, const VkCommandBuffer commandBuffer) const
1351 {
1352     if (!m_isDynamicRendering)
1353     {
1354         vk.cmdEndRenderPass(commandBuffer);
1355     }
1356     else
1357     {
1358 #ifndef CTS_USES_VULKANSC
1359         vk.cmdEndRendering(commandBuffer);
1360 
1361         // Use dependencies for external subpasses to extract destination access
1362         // flags and pipeline stage flags for the final layout transition
1363         // barriers.
1364         VkAccessFlags2 externalAccessFlags       = 0u;
1365         VkPipelineStageFlags2 externalStageFlags = 0u;
1366         bool sync2                               = false;
1367 
1368         for (const auto &dep : m_dependencies)
1369         {
1370             if (dep.dstSubpass == VK_SUBPASS_EXTERNAL)
1371             {
1372                 externalAccessFlags |= dep.dstAccessMask;
1373                 externalStageFlags |= dep.dstStageMask;
1374             }
1375             if (dep.sync2)
1376                 sync2 = true;
1377         }
1378 
1379         for (uint32_t i = 0; i < (uint32_t)m_attachments.size(); ++i)
1380         {
1381             if (m_layouts[i] == m_attachments[i].finalLayout)
1382                 continue;
1383 
1384             const bool color = !vk::isDepthStencilFormat(m_attachments[i].format);
1385             VkImageAspectFlags aspect =
1386                 color ? (vk::VkImageAspectFlags)vk::VK_IMAGE_ASPECT_COLOR_BIT : (vk::VkImageAspectFlags)0u;
1387 
1388             if (!color)
1389             {
1390                 const bool hasDepthAspect   = tcu::hasDepthComponent(vk::mapVkFormat(m_attachments[i].format).order);
1391                 const bool hasStencilAspect = tcu::hasStencilComponent(vk::mapVkFormat(m_attachments[i].format).order);
1392 
1393                 if (hasDepthAspect)
1394                     aspect |= vk::VK_IMAGE_ASPECT_DEPTH_BIT;
1395                 if (hasStencilAspect)
1396                     aspect |= vk::VK_IMAGE_ASPECT_STENCIL_BIT;
1397             }
1398 
1399             const auto subresourceRange =
1400                 makeImageSubresourceRange(aspect, 0u, VK_REMAINING_MIP_LEVELS, 0u, VK_REMAINING_ARRAY_LAYERS);
1401 
1402             const VkPipelineStageFlags2 srcStageMask = (color ? vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT :
1403                                                                 vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1404             const VkAccessFlags2 srcAccessMask =
1405                 (color ? vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT : vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
1406             const VkPipelineStageFlags2 dstStageMask = (vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT | externalStageFlags);
1407             const VkAccessFlags2 dstAccessMask       = externalAccessFlags;
1408             const VkImageLayout newLayout            = m_attachments[i].finalLayout;
1409 
1410             recordImageBarrier(vk, commandBuffer, sync2, srcStageMask, srcAccessMask, dstStageMask, dstAccessMask,
1411                                m_layouts[i], newLayout, m_images[i], subresourceRange);
1412         }
1413 
1414         insertDependencies(vk, commandBuffer, VK_SUBPASS_EXTERNAL);
1415 #endif
1416     }
1417 }
1418 
beginRendering(const DeviceInterface & vk,const VkCommandBuffer commandBuffer) const1419 void RenderPassWrapper::beginRendering(const DeviceInterface &vk, const VkCommandBuffer commandBuffer) const
1420 {
1421     DE_UNREF(vk);
1422     DE_UNREF(commandBuffer);
1423 #ifndef CTS_USES_VULKANSC
1424     const auto &subpass = m_subpasses[m_activeSubpass];
1425     std::vector<vk::VkRenderingAttachmentInfo> colorAttachments;
1426     for (uint32_t i = 0; i < (uint32_t)subpass.m_colorAttachments.size(); ++i)
1427     {
1428         colorAttachments.emplace_back();
1429         auto &colorAttachment = colorAttachments.back();
1430         colorAttachment       = vk::initVulkanStructure();
1431         if (subpass.m_colorAttachments[i].index == VK_ATTACHMENT_UNUSED)
1432             continue;
1433         colorAttachment        = subpass.m_colorAttachments[i].attachmentInfo;
1434         colorAttachment.loadOp = vk::VK_ATTACHMENT_LOAD_OP_LOAD;
1435         if (!subpass.m_resolveAttachments.empty() && subpass.m_resolveAttachments[i].index != VK_ATTACHMENT_UNUSED)
1436         {
1437             if (isUintFormat(subpass.m_resolveAttachments[i].format) ||
1438                 isIntFormat(subpass.m_resolveAttachments[i].format))
1439                 colorAttachment.resolveMode = vk::VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
1440             else
1441                 colorAttachment.resolveMode = vk::VK_RESOLVE_MODE_AVERAGE_BIT;
1442             colorAttachment.resolveImageView   = subpass.m_resolveAttachments[i].attachmentInfo.imageView;
1443             colorAttachment.resolveImageLayout = subpass.m_resolveAttachments[i].attachmentInfo.imageLayout;
1444         }
1445     }
1446 
1447     m_renderingInfo.colorAttachmentCount = (uint32_t)colorAttachments.size();
1448     m_renderingInfo.pColorAttachments    = colorAttachments.data();
1449 
1450     subpass.m_depthStencilAttachment.attachmentInfo.loadOp = vk::VK_ATTACHMENT_LOAD_OP_LOAD;
1451     VkRenderingAttachmentInfo depthAttachment              = subpass.m_depthStencilAttachment.attachmentInfo;
1452     VkRenderingAttachmentInfo stencilAttachment            = subpass.m_depthStencilAttachment.attachmentInfo;
1453     stencilAttachment.storeOp                              = subpass.m_depthStencilAttachment.stencilStoreOp;
1454 
1455     if (depthAttachment.imageView != VK_NULL_HANDLE)
1456     {
1457         const auto tcuFormat               = vk::mapVkFormat(subpass.m_depthStencilAttachment.format);
1458         bool hasDepthAspect                = tcu::hasDepthComponent(tcuFormat.order);
1459         bool hasStencilAspect              = tcu::hasStencilComponent(tcuFormat.order);
1460         m_renderingInfo.pDepthAttachment   = hasDepthAspect ? &depthAttachment : DE_NULL;
1461         m_renderingInfo.pStencilAttachment = hasStencilAspect ? &stencilAttachment : DE_NULL;
1462     }
1463     else
1464     {
1465         m_renderingInfo.pDepthAttachment   = DE_NULL;
1466         m_renderingInfo.pStencilAttachment = DE_NULL;
1467     }
1468 
1469     if (m_activeSubpass < (uint32_t)m_viewMasks.size())
1470         m_renderingInfo.viewMask = m_viewMasks[m_activeSubpass];
1471 
1472     m_renderingInfo.pNext = DE_NULL;
1473     if (subpass.m_msrtss.sType == VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT)
1474     {
1475         subpass.m_msrtss.pNext = DE_NULL;
1476         m_renderingInfo.pNext  = &subpass.m_msrtss;
1477     }
1478 
1479     if (subpass.m_dsr.sType == VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE)
1480     {
1481         depthAttachment.resolveMode   = subpass.m_dsr.depthResolveMode;
1482         stencilAttachment.resolveMode = subpass.m_dsr.stencilResolveMode;
1483         if (subpass.m_dsr.pDepthStencilResolveAttachment)
1484         {
1485             depthAttachment.resolveImageView   = m_imageViews[subpass.m_dsr.pDepthStencilResolveAttachment->attachment];
1486             depthAttachment.resolveImageLayout = subpass.m_dsr.pDepthStencilResolveAttachment->layout;
1487             stencilAttachment.resolveImageView = m_imageViews[subpass.m_dsr.pDepthStencilResolveAttachment->attachment];
1488             stencilAttachment.resolveImageLayout = subpass.m_dsr.pDepthStencilResolveAttachment->layout;
1489         }
1490     }
1491 
1492     m_renderingInfo.flags = (VkRenderingFlags)0u;
1493 
1494     if (m_secondaryCommandBuffers)
1495         m_renderingInfo.flags |= VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT;
1496 
1497     vk.cmdBeginRendering(commandBuffer, &m_renderingInfo);
1498 #endif
1499 }
1500 
nextSubpass(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkSubpassContents contents) const1501 void RenderPassWrapper::nextSubpass(const DeviceInterface &vk, const VkCommandBuffer commandBuffer,
1502                                     const VkSubpassContents contents) const
1503 {
1504     if (!m_isDynamicRendering)
1505     {
1506         vk.cmdNextSubpass(commandBuffer, contents);
1507     }
1508     else
1509     {
1510 #ifndef CTS_USES_VULKANSC
1511         vk.cmdEndRendering(commandBuffer);
1512         ++m_activeSubpass;
1513         DE_ASSERT(m_activeSubpass < (uint32_t)m_subpasses.size());
1514 
1515         const auto &subpass = m_subpasses[m_activeSubpass];
1516 
1517         transitionLayouts(vk, commandBuffer, subpass, false);
1518 
1519         insertDependencies(vk, commandBuffer, m_activeSubpass);
1520 
1521         beginRendering(vk, commandBuffer);
1522 #endif
1523     }
1524 }
1525 
createFramebuffer(const DeviceInterface & vk,const VkDevice device,const VkFramebufferCreateInfo * pCreateInfo,const std::vector<vk::VkImage> & images)1526 void RenderPassWrapper::createFramebuffer(const DeviceInterface &vk, const VkDevice device,
1527                                           const VkFramebufferCreateInfo *pCreateInfo,
1528                                           const std::vector<vk::VkImage> &images)
1529 {
1530     DE_UNREF(images);
1531     if (!m_isDynamicRendering)
1532     {
1533         m_framebuffer = vk::createFramebuffer(vk, device, pCreateInfo);
1534     }
1535     else
1536     {
1537 #ifndef CTS_USES_VULKANSC
1538         m_images = images;
1539         m_imageViews.resize(pCreateInfo->attachmentCount);
1540         for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i)
1541             m_imageViews[i] = pCreateInfo->pAttachments[i];
1542 
1543         for (auto &subpass : m_subpasses)
1544         {
1545             for (uint32_t i = 0; i < (uint32_t)subpass.m_colorAttachments.size(); ++i)
1546             {
1547                 if (subpass.m_colorAttachments[i].index != VK_ATTACHMENT_UNUSED)
1548                     subpass.m_colorAttachments[i].attachmentInfo.imageView =
1549                         pCreateInfo->pAttachments[subpass.m_colorAttachments[i].index];
1550             }
1551 
1552             if (subpass.m_depthStencilAttachment.attachmentInfo.imageLayout != VK_IMAGE_LAYOUT_UNDEFINED)
1553             {
1554                 if (subpass.m_depthStencilAttachment.index != VK_ATTACHMENT_UNUSED)
1555                     subpass.m_depthStencilAttachment.attachmentInfo.imageView =
1556                         pCreateInfo->pAttachments[subpass.m_depthStencilAttachment.index];
1557             }
1558 
1559             for (uint32_t i = 0; i < (uint32_t)subpass.m_resolveAttachments.size(); ++i)
1560             {
1561                 if (subpass.m_resolveAttachments[i].index != VK_ATTACHMENT_UNUSED)
1562                     subpass.m_resolveAttachments[i].attachmentInfo.imageView =
1563                         pCreateInfo->pAttachments[subpass.m_resolveAttachments[i].index];
1564             }
1565         }
1566         m_layers = pCreateInfo->layers;
1567 #endif
1568     }
1569 }
1570 
createFramebuffer(const DeviceInterface & vk,const VkDevice device,const VkFramebufferCreateInfo * pCreateInfo,vk::VkImage colorImage,vk::VkImage depthStencilImage)1571 void RenderPassWrapper::createFramebuffer(const DeviceInterface &vk, const VkDevice device,
1572                                           const VkFramebufferCreateInfo *pCreateInfo, vk::VkImage colorImage,
1573                                           vk::VkImage depthStencilImage)
1574 {
1575     DE_UNREF(colorImage);
1576     DE_UNREF(depthStencilImage);
1577     if (!m_isDynamicRendering)
1578     {
1579         m_framebuffer = vk::createFramebuffer(vk, device, pCreateInfo);
1580     }
1581     else
1582     {
1583 #ifndef CTS_USES_VULKANSC
1584         if (colorImage != VK_NULL_HANDLE)
1585         {
1586             m_images.push_back(colorImage);
1587             DE_ASSERT(pCreateInfo->attachmentCount > 0);
1588             m_imageViews.push_back(pCreateInfo->pAttachments[0]);
1589         }
1590         if (depthStencilImage != VK_NULL_HANDLE)
1591             m_images.push_back(depthStencilImage);
1592         for (auto &subpass : m_subpasses)
1593         {
1594             DE_ASSERT(subpass.m_colorAttachments.size() <= 1);
1595             if (pCreateInfo->pAttachments)
1596             {
1597                 if (!subpass.m_colorAttachments.empty() &&
1598                     subpass.m_colorAttachments[0].index < pCreateInfo->attachmentCount)
1599                     subpass.m_colorAttachments[0].attachmentInfo.imageView =
1600                         pCreateInfo->pAttachments[subpass.m_colorAttachments[0].index];
1601                 if (subpass.m_depthStencilAttachment.index < pCreateInfo->attachmentCount)
1602                     subpass.m_depthStencilAttachment.attachmentInfo.imageView =
1603                         pCreateInfo->pAttachments[subpass.m_depthStencilAttachment.index];
1604             }
1605         }
1606 #endif
1607     }
1608 }
1609 
createFramebuffer(const DeviceInterface & vk,const VkDevice device,const VkImage colorImage,const VkImageView colorAttachment,const uint32_t width,const uint32_t height,const uint32_t layers)1610 void RenderPassWrapper::createFramebuffer(const DeviceInterface &vk, const VkDevice device, const VkImage colorImage,
1611                                           const VkImageView colorAttachment, const uint32_t width,
1612                                           const uint32_t height, const uint32_t layers)
1613 {
1614     DE_UNREF(colorImage);
1615     if (!m_isDynamicRendering)
1616     {
1617         VkFramebufferCreateInfo createInfo = initVulkanStructure();
1618         createInfo.flags                   = (VkFramebufferCreateFlags)0u;
1619         createInfo.renderPass              = *m_renderPass;
1620         createInfo.attachmentCount         = (colorAttachment != VK_NULL_HANDLE) ? 1u : 0u;
1621         createInfo.pAttachments            = &colorAttachment;
1622         createInfo.width                   = width;
1623         createInfo.height                  = height;
1624         createInfo.layers                  = layers;
1625         m_framebuffer                      = vk::createFramebuffer(vk, device, &createInfo);
1626     }
1627     else
1628     {
1629 #ifndef CTS_USES_VULKANSC
1630         m_images.push_back(colorImage);
1631         m_imageViews.push_back(colorAttachment);
1632         if (colorImage != VK_NULL_HANDLE)
1633         {
1634             for (auto &subpass : m_subpasses)
1635             {
1636                 DE_ASSERT(subpass.m_colorAttachments.size() == 1);
1637                 subpass.m_colorAttachments[0].attachmentInfo.imageView = colorAttachment;
1638             }
1639         }
1640 #endif
1641     }
1642 }
1643 
createFramebuffer(const DeviceInterface & vk,const VkDevice device,const uint32_t attachmentCount,const VkImage * imagesArray,const VkImageView * attachmentsArray,const uint32_t width,const uint32_t height,const uint32_t layers)1644 void RenderPassWrapper::createFramebuffer(const DeviceInterface &vk, const VkDevice device,
1645                                           const uint32_t attachmentCount, const VkImage *imagesArray,
1646                                           const VkImageView *attachmentsArray, const uint32_t width,
1647                                           const uint32_t height, const uint32_t layers)
1648 {
1649     DE_UNREF(imagesArray);
1650     if (!m_isDynamicRendering)
1651     {
1652         VkFramebufferCreateInfo createInfo = initVulkanStructure();
1653         createInfo.flags                   = (VkFramebufferCreateFlags)0u;
1654         createInfo.renderPass              = *m_renderPass;
1655         createInfo.attachmentCount         = attachmentCount;
1656         createInfo.pAttachments            = attachmentsArray;
1657         createInfo.width                   = width;
1658         createInfo.height                  = height;
1659         createInfo.layers                  = layers;
1660         m_framebuffer                      = vk::createFramebuffer(vk, device, &createInfo);
1661     }
1662     else
1663     {
1664 #ifndef CTS_USES_VULKANSC
1665         for (uint32_t i = 0; i < attachmentCount; ++i)
1666         {
1667             m_images.push_back(imagesArray[i]);
1668             m_imageViews.push_back(attachmentsArray[i]);
1669         }
1670         for (auto &subpass : m_subpasses)
1671         {
1672             for (uint32_t i = 0; i < (uint32_t)subpass.m_colorAttachments.size(); ++i)
1673             {
1674                 if (subpass.m_colorAttachments[i].index != VK_ATTACHMENT_UNUSED)
1675                     subpass.m_colorAttachments[i].attachmentInfo.imageView =
1676                         attachmentsArray[subpass.m_colorAttachments[i].index];
1677             }
1678             if (subpass.m_depthStencilAttachment.attachmentInfo.imageLayout != VK_IMAGE_LAYOUT_UNDEFINED)
1679             {
1680                 if (subpass.m_depthStencilAttachment.index != VK_ATTACHMENT_UNUSED)
1681                     subpass.m_depthStencilAttachment.attachmentInfo.imageView =
1682                         attachmentsArray[subpass.m_depthStencilAttachment.index];
1683             }
1684             for (uint32_t i = 0; i < (uint32_t)subpass.m_resolveAttachments.size(); ++i)
1685             {
1686                 if (subpass.m_resolveAttachments[i].index != VK_ATTACHMENT_UNUSED)
1687                     subpass.m_resolveAttachments[i].attachmentInfo.imageView =
1688                         attachmentsArray[subpass.m_resolveAttachments[i].index];
1689             }
1690         }
1691 #endif
1692     }
1693 }
1694 
ShaderWrapper()1695 ShaderWrapper::ShaderWrapper()
1696     : m_vk(DE_NULL)
1697     , m_device(VK_NULL_HANDLE)
1698     , m_binary(DE_NULL)
1699     , m_moduleCreateFlags((VkShaderModuleCreateFlags)0u)
1700     , m_layout(DE_NULL)
1701     , m_specializationInfo(DE_NULL)
1702 #ifndef CTS_USES_VULKANSC
1703     , m_shaderCreateFlags((VkShaderCreateFlagsEXT)0u)
1704     , m_binaryDataSize(0u)
1705 #endif
1706 {
1707 }
1708 
ShaderWrapper(const DeviceInterface & vk,VkDevice device,const vk::ProgramBinary & binary,const vk::VkShaderModuleCreateFlags createFlags)1709 ShaderWrapper::ShaderWrapper(const DeviceInterface &vk, VkDevice device, const vk::ProgramBinary &binary,
1710                              const vk::VkShaderModuleCreateFlags createFlags)
1711     : m_vk(&vk)
1712     , m_device(device)
1713     , m_binary(&binary)
1714     , m_moduleCreateFlags(createFlags)
1715     , m_layout(DE_NULL)
1716     , m_specializationInfo(DE_NULL)
1717 #ifndef CTS_USES_VULKANSC
1718     , m_shaderCreateFlags((VkShaderCreateFlagsEXT)0u)
1719     , m_binaryDataSize(0u)
1720 #endif
1721 {
1722 }
1723 
ShaderWrapper(const ShaderWrapper & rhs)1724 ShaderWrapper::ShaderWrapper(const ShaderWrapper &rhs) noexcept
1725     : m_vk(rhs.m_vk)
1726     , m_device(rhs.m_device)
1727     , m_binary(rhs.m_binary)
1728     , m_moduleCreateFlags(rhs.m_moduleCreateFlags)
1729     , m_layout(rhs.m_layout)
1730     , m_specializationInfo(rhs.m_specializationInfo)
1731 #ifndef CTS_USES_VULKANSC
1732     , m_shaderCreateFlags(rhs.m_shaderCreateFlags)
1733     , m_binaryDataSize(rhs.m_binaryDataSize)
1734     , m_binaryData(rhs.m_binaryData)
1735 #endif
1736 {
1737 }
1738 
operator =(const ShaderWrapper & rhs)1739 ShaderWrapper &ShaderWrapper::operator=(const ShaderWrapper &rhs) noexcept
1740 {
1741     m_vk                 = rhs.m_vk;
1742     m_device             = rhs.m_device;
1743     m_binary             = rhs.m_binary;
1744     m_moduleCreateFlags  = rhs.m_moduleCreateFlags;
1745     m_layout             = rhs.m_layout;
1746     m_specializationInfo = rhs.m_specializationInfo;
1747 #ifndef CTS_USES_VULKANSC
1748     m_shaderCreateFlags = rhs.m_shaderCreateFlags;
1749     m_binaryDataSize    = rhs.m_binaryDataSize;
1750     m_binaryData        = rhs.m_binaryData;
1751 #endif
1752 
1753     return *this;
1754 }
1755 
getModule(void) const1756 vk::VkShaderModule ShaderWrapper::getModule(void) const
1757 {
1758     if (!m_module)
1759     {
1760         if (!m_vk)
1761             return DE_NULL;
1762         m_module = createShaderModule(*m_vk, m_device, *m_binary, m_moduleCreateFlags);
1763     }
1764     return *m_module;
1765 }
1766 
getCodeSize(void) const1767 size_t ShaderWrapper::getCodeSize(void) const
1768 {
1769     return m_binary->getSize();
1770 }
1771 
getBinary(void) const1772 void *ShaderWrapper::getBinary(void) const
1773 {
1774     return (void *)m_binary->getBinary();
1775 }
1776 
createModule(void)1777 void ShaderWrapper::createModule(void)
1778 {
1779     if (m_vk)
1780         m_module = createShaderModule(*m_vk, m_device, *m_binary, m_moduleCreateFlags);
1781 }
1782 
setLayoutAndSpecialization(const PipelineLayoutWrapper * layout,const VkSpecializationInfo * specializationInfo)1783 void ShaderWrapper::setLayoutAndSpecialization(const PipelineLayoutWrapper *layout,
1784                                                const VkSpecializationInfo *specializationInfo)
1785 {
1786     m_layout             = layout;
1787     m_specializationInfo = specializationInfo;
1788 }
1789 
1790 #ifndef CTS_USES_VULKANSC
getShaderBinary(void)1791 void ShaderWrapper::getShaderBinary(void)
1792 {
1793     m_vk->getShaderBinaryDataEXT(m_device, *m_shader, &m_binaryDataSize, DE_NULL);
1794     m_binaryData.resize(m_binaryDataSize);
1795     m_vk->getShaderBinaryDataEXT(m_device, *m_shader, &m_binaryDataSize, m_binaryData.data());
1796 }
1797 #endif
1798 
1799 // Structure storing *CreateInfo structures that do not need to exist in memory after pipeline was constructed.
1800 struct GraphicsPipelineWrapper::InternalData
1801 {
1802     const InstanceInterface &vki;
1803     const DeviceInterface &vk;
1804     VkPhysicalDevice physicalDevice;
1805     VkDevice device;
1806     const std::vector<std::string> &deviceExtensions;
1807     const PipelineConstructionType pipelineConstructionType;
1808     const VkPipelineCreateFlags pipelineFlags;
1809     PipelineCreateFlags2 pipelineFlags2;
1810 
1811     // attribute used for making sure pipeline is configured in correct order
1812     int setupState;
1813 
1814     std::vector<PipelineShaderStageModuleIdPtr> pipelineShaderIdentifiers;
1815     std::vector<VkPipelineShaderStageCreateInfo> pipelineShaderStages;
1816     VkPipelineInputAssemblyStateCreateInfo inputAssemblyState;
1817     VkPipelineRasterizationStateCreateInfo defaultRasterizationState;
1818     VkPipelineViewportStateCreateInfo viewportState;
1819     VkPipelineTessellationStateCreateInfo tessellationState;
1820     VkPipelineFragmentShadingRateStateCreateInfoKHR *pFragmentShadingRateState;
1821     PipelineRenderingCreateInfoWrapper pRenderingState;
1822     RenderingAttachmentLocationInfoWrapper pRenderingAttachmentLocation;
1823     RenderingInputAttachmentIndexInfoWrapper pRenderingInputAttachmentIndex;
1824     const VkPipelineDynamicStateCreateInfo *pDynamicState;
1825     PipelineRepresentativeFragmentTestCreateInfoWrapper pRepresentativeFragmentTestState;
1826     PipelineRobustnessCreateInfoWrapper pPipelineRobustnessState;
1827 
1828     TessellationDomainOriginStatePtr pTessellationDomainOrigin;
1829     bool useViewportState;
1830     bool useDefaultRasterizationState;
1831     bool useDefaultDepthStencilState;
1832     bool useDefaultColorBlendState;
1833     bool useDefaultMultisampleState;
1834     bool useDefaultVertexInputState;
1835     bool failOnCompileWhenLinking;
1836 
1837     bool explicitLinkPipelineLayoutSet;
1838     VkGraphicsPipelineCreateInfo monolithicPipelineCreateInfo;
1839 
1840     ShaderWrapper vertexShader;
1841     ShaderWrapper tessellationControlShader;
1842     ShaderWrapper tessellationEvaluationShader;
1843     ShaderWrapper geometryShader;
1844     ShaderWrapper fragmentShader;
1845 
1846     ShaderWrapper meshShader;
1847     ShaderWrapper taskShader;
1848 
1849     bool tessellationShaderFeature;
1850     bool geometryShaderFeature;
1851     bool taskShaderFeature;
1852     bool meshShaderFeature;
1853 
1854     // Store all dynamic state that are used with shader objects
1855     std::vector<vk::VkDynamicState> shaderObjectDynamicStates;
1856 
1857 #ifndef CTS_USES_VULKANSC
1858     // Store the state that a pipeline would be created with, but shader objects have to set dynamically
1859     struct PipelineCreateState
1860     {
1861         std::vector<VkViewport> viewports;
1862         std::vector<VkRect2D> scissors;
1863         float lineWidth = 1.0f;
1864         VkDepthBiasRepresentationEXT depthBiasRepresentation =
1865             vk::VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORMAT_EXT;
1866         VkBool32 depthBiasExact       = VK_FALSE;
1867         float depthBiasConstantFactor = 0.0f;
1868         float depthBiasClamp          = 0.0f;
1869         float depthBiasSlopeFactor    = 1.0f;
1870         float blendConstants[4]       = {0.0f, 0.0f, 0.0f, 0.0f};
1871         float minDepthBounds          = 0.0f;
1872         float maxDepthBounds          = 1.0f;
1873         VkStencilOpState stencilFront = {
1874             VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_NEVER, 0, 0, 0};
1875         VkStencilOpState stencilBack = {
1876             VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_NEVER, 0, 0, 0};
1877         VkCullModeFlags cullMode     = VK_CULL_MODE_NONE;
1878         bool depthTestEnable         = VK_FALSE;
1879         bool depthWriteEnable        = VK_FALSE;
1880         VkCompareOp depthCompareOp   = VK_COMPARE_OP_NEVER;
1881         bool depthBoundsTestEnable   = VK_FALSE;
1882         VkFrontFace frontFace        = VK_FRONT_FACE_COUNTER_CLOCKWISE;
1883         VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
1884         bool stencilTestEnable       = VK_FALSE;
1885         std::vector<VkVertexInputAttributeDescription2EXT> attributes;
1886         std::vector<VkVertexInputBindingDescription2EXT> bindings;
1887         bool depthBiasEnable         = VK_FALSE;
1888         VkLogicOp logicOp            = VK_LOGIC_OP_CLEAR;
1889         uint32_t patchControlPoints  = 1;
1890         bool primitiveRestartEnable  = VK_FALSE;
1891         bool rasterizerDiscardEnable = VK_FALSE;
1892         bool alphaToCoverageEnable   = VK_FALSE;
1893         bool alphaToOneEnable        = VK_FALSE;
1894         std::vector<VkColorBlendAdvancedEXT> colorBlendAdvanced;
1895         std::vector<VkBool32> colorBlendEnables;
1896         std::vector<VkColorBlendEquationEXT> blendEquations;
1897         std::vector<VkColorComponentFlags> colorWriteMasks;
1898         VkConservativeRasterizationModeEXT conservativeRasterizationMode =
1899             VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
1900         VkCoverageModulationModeNV coverageModulationMode = VK_COVERAGE_MODULATION_MODE_NONE_NV;
1901         bool coverageModulationTableEnable                = VK_FALSE;
1902         std::vector<float> coverageModulationTable;
1903         VkCoverageReductionModeNV coverageReductionMode = VK_COVERAGE_REDUCTION_MODE_MERGE_NV;
1904         bool coverageToColorEnable                      = VK_FALSE;
1905         uint32_t coverageToColorLocation                = 0;
1906         bool depthClampEnable                           = VK_FALSE;
1907         bool depthClipEnable                            = VK_FALSE;
1908         bool negativeOneToOne                           = VK_FALSE;
1909         uint32_t colorWriteEnableAttachmentCount        = 0;
1910         std::vector<VkBool32> colorWriteEnables;
1911         float extraPrimitiveOverestimationSize            = 0.0f;
1912         VkLineRasterizationModeEXT lineRasterizationMode  = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
1913         bool stippledLineEnable                           = VK_FALSE;
1914         uint32_t lineStippleFactor                        = 1;
1915         uint16_t lineStipplePattern                       = 0x1;
1916         bool logicOpEnable                                = VK_FALSE;
1917         VkPolygonMode polygonMode                         = VK_POLYGON_MODE_FILL;
1918         VkProvokingVertexModeEXT provokingVertexMode      = VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
1919         VkSampleCountFlagBits rasterizationSamples        = VK_SAMPLE_COUNT_1_BIT;
1920         VkExtent2D fragmentShadingRateSize                = {1u, 1u};
1921         VkFragmentShadingRateCombinerOpKHR combinerOps[2] = {VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
1922                                                              VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR};
1923         uint32_t rasterizationStream                      = 0;
1924         bool representativeFragmentTestEnable             = VK_FALSE;
1925         bool sampleLocationsEnable                        = VK_FALSE;
1926         std::vector<VkSampleLocationEXT> pSampleLocations;
1927         VkSampleLocationsInfoEXT sampleLocationsInfo = vk::initVulkanStructure();
1928         std::vector<VkSampleMask> sampleMasks;
1929         bool shadingRateImageEnable             = VK_FALSE;
1930         VkTessellationDomainOrigin domainOrigin = VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT;
1931         std::vector<VkViewportSwizzleNV> viewportSwizzles;
1932         bool viewportWScalingEnable    = VK_FALSE;
1933         uint32_t viewportWScalingCount = 0;
1934         std::vector<VkViewportWScalingNV> viewportWScalings;
1935         VkCoarseSampleOrderTypeNV coarseSampleOrderType = VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV;
1936         uint32_t coarseCustomSampleOrderCount           = 0;
1937         std::vector<std::vector<VkCoarseSampleLocationNV>> coarseSampleLocations;
1938         std::vector<VkCoarseSampleOrderCustomNV> coarseCustomSampleOrders;
1939         uint32_t shadingRatePaletteCount = 0;
1940         std::vector<std::vector<VkShadingRatePaletteEntryNV>> shadingRatePaletteEntries;
1941         std::vector<VkShadingRatePaletteNV> shadingRatePalettes;
1942         uint32_t exclusiveScissorCount = 0;
1943         std::vector<VkRect2D> exclussiveScissors;
1944         bool discardRectangleEnable = VK_FALSE;
1945         std::vector<VkRect2D> discardRectangles;
1946         VkDiscardRectangleModeEXT discardRectangleMode  = VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT;
1947         VkImageAspectFlags attachmentFeedbackLoopEnable = VK_IMAGE_ASPECT_NONE;
1948     } pipelineCreateState;
1949 #endif
1950 
1951     // initialize with most common values
InternalDatavk::GraphicsPipelineWrapper::InternalData1952     InternalData(const InstanceInterface& instanceInterface, const DeviceInterface& vkd, VkPhysicalDevice physDevice, VkDevice vkDevice, const std::vector<std::string>& deviceExts, const PipelineConstructionType constructionType, const VkPipelineCreateFlags pipelineCreateFlags)
1953         : vki                        (instanceInterface)
1954         , vk                        (vkd)
1955         , physicalDevice            (physDevice)
1956         , device                    (vkDevice)
1957         , deviceExtensions            (deviceExts)
1958         , pipelineConstructionType    (constructionType)
1959         , pipelineFlags                (pipelineCreateFlags)
1960         , pipelineFlags2            (0u)
1961         , setupState                (PSS_NONE)
1962         , inputAssemblyState
1963         {
1964             VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType                                sType
1965             DE_NULL, // const void*                                    pNext
1966             0u, // VkPipelineInputAssemblyStateCreateFlags        flags
1967             VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology                            topology
1968             VK_FALSE                                                        // VkBool32                                        primitiveRestartEnable
1969         }
1970         , defaultRasterizationState
1971         {
1972             VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType                                sType
1973             DE_NULL, // const void*                                    pNext
1974             0u, // VkPipelineRasterizationStateCreateFlags        flags
1975             VK_FALSE, // VkBool32                                        depthClampEnable
1976             VK_FALSE, // VkBool32                                        rasterizerDiscardEnable
1977             VK_POLYGON_MODE_FILL, // VkPolygonMode                                polygonMode
1978             VK_CULL_MODE_NONE, // VkCullModeFlags                                cullMode
1979             VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace                                    frontFace
1980             VK_FALSE, // VkBool32                                        depthBiasEnable
1981             0.0f, // float                                        depthBiasConstantFactor
1982             0.0f, // float                                        depthBiasClamp
1983             0.0f, // float                                        depthBiasSlopeFactor
1984             1.0f                                                            // float                                        lineWidth
1985         }
1986         , viewportState
1987         {
1988             VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType                                sType
1989             DE_NULL, // const void*                                    pNext
1990             (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags            flags
1991             1u, // uint32_t                                        viewportCount
1992             DE_NULL, // const VkViewport*                            pViewports
1993             1u, // uint32_t                                        scissorCount
1994             DE_NULL                                                            // const VkRect2D*                                pScissors
1995         }
1996         , tessellationState
1997         {
1998             VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType                                sType
1999             DE_NULL, // const void*                                    pNext
2000             0u, // VkPipelineTessellationStateCreateFlags        flags
2001             3u                                                                // uint32_t                                        patchControlPoints
2002         }
2003         , pFragmentShadingRateState        (nullptr)
2004         , pDynamicState                    (DE_NULL)
2005         , pRepresentativeFragmentTestState(nullptr)
2006         , pPipelineRobustnessState          (nullptr)
2007         , pTessellationDomainOrigin        ()
2008         , useViewportState                (true)
2009         , useDefaultRasterizationState    (false)
2010         , useDefaultDepthStencilState    (false)
2011         , useDefaultColorBlendState        (false)
2012         , useDefaultMultisampleState    (false)
2013         , useDefaultVertexInputState    (true)
2014         , failOnCompileWhenLinking        (false)
2015         , explicitLinkPipelineLayoutSet    (false)
2016         , tessellationShaderFeature        (false)
2017         , geometryShaderFeature            (false)
2018         , taskShaderFeature                (false)
2019         , meshShaderFeature                (false)
2020     {
2021         monolithicPipelineCreateInfo = initVulkanStructure();
2022     }
2023 
extensionEnabledvk::GraphicsPipelineWrapper::InternalData2024     bool extensionEnabled(const std::string &ext) const
2025     {
2026         return std::find(deviceExtensions.begin(), deviceExtensions.end(), ext) != deviceExtensions.end();
2027     }
2028 };
2029 
GraphicsPipelineWrapper(const InstanceInterface & vki,const DeviceInterface & vk,VkPhysicalDevice physicalDevice,VkDevice device,const std::vector<std::string> & deviceExtensions,const PipelineConstructionType pipelineConstructionType,const VkPipelineCreateFlags flags)2030 GraphicsPipelineWrapper::GraphicsPipelineWrapper(const InstanceInterface &vki, const DeviceInterface &vk,
2031                                                  VkPhysicalDevice physicalDevice, VkDevice device,
2032                                                  const std::vector<std::string> &deviceExtensions,
2033                                                  const PipelineConstructionType pipelineConstructionType,
2034                                                  const VkPipelineCreateFlags flags)
2035     : m_internalData(
2036           new InternalData(vki, vk, physicalDevice, device, deviceExtensions, pipelineConstructionType, flags))
2037 {
2038 }
2039 
GraphicsPipelineWrapper(GraphicsPipelineWrapper && pw)2040 GraphicsPipelineWrapper::GraphicsPipelineWrapper(GraphicsPipelineWrapper &&pw) noexcept
2041     : m_pipelineFinal(pw.m_pipelineFinal)
2042     , m_internalData(pw.m_internalData)
2043 {
2044     std::move(pw.m_pipelineParts, pw.m_pipelineParts + de::arrayLength(pw.m_pipelineParts), m_pipelineParts);
2045 }
2046 
setMonolithicPipelineLayout(const PipelineLayoutWrapper & layout)2047 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setMonolithicPipelineLayout(const PipelineLayoutWrapper &layout)
2048 {
2049     // make sure pipeline was not already built
2050     DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
2051 
2052     m_internalData->monolithicPipelineCreateInfo.layout = *layout;
2053     m_internalData->explicitLinkPipelineLayoutSet       = true;
2054 
2055     return *this;
2056 }
2057 
setDynamicState(const VkPipelineDynamicStateCreateInfo * dynamicState)2058 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setDynamicState(const VkPipelineDynamicStateCreateInfo *dynamicState)
2059 {
2060     // make sure states are not yet setup - all pipeline states must know about dynamic state
2061     DE_ASSERT(m_internalData && m_internalData->setupState == PSS_NONE);
2062 
2063     m_internalData->pDynamicState                              = dynamicState;
2064     m_internalData->monolithicPipelineCreateInfo.pDynamicState = dynamicState;
2065 
2066     return *this;
2067 }
2068 
setRepresentativeFragmentTestState(PipelineRepresentativeFragmentTestCreateInfoWrapper representativeFragmentTestState)2069 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setRepresentativeFragmentTestState(
2070     PipelineRepresentativeFragmentTestCreateInfoWrapper representativeFragmentTestState)
2071 {
2072     // Representative fragment test state is needed by the fragment shader state.
2073     DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_FRAGMENT_SHADER));
2074 
2075     m_internalData->pRepresentativeFragmentTestState = representativeFragmentTestState;
2076     return *this;
2077 }
2078 
setPipelineCreateFlags2(PipelineCreateFlags2 pipelineFlags2)2079 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setPipelineCreateFlags2(PipelineCreateFlags2 pipelineFlags2)
2080 {
2081     // make sure states are not yet setup - all pipeline states must know about createFlags2
2082     DE_ASSERT(m_internalData && m_internalData->setupState == PSS_NONE);
2083 
2084     m_internalData->pipelineFlags2 = pipelineFlags2;
2085     return *this;
2086 }
2087 
setPipelineRobustnessState(PipelineRobustnessCreateInfoWrapper pipelineRobustnessState)2088 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setPipelineRobustnessState(
2089     PipelineRobustnessCreateInfoWrapper pipelineRobustnessState)
2090 {
2091     // pipeline robustness is needed by vertex input state, make sure vertex input state was not setup yet
2092     DE_ASSERT(m_internalData && (m_internalData->setupState == PSS_NONE));
2093 
2094     m_internalData->pPipelineRobustnessState = pipelineRobustnessState;
2095     return *this;
2096 }
2097 
getDynamicStates(const VkPipelineDynamicStateCreateInfo * dynamicStateInfo,uint32_t setupState)2098 std::vector<VkDynamicState> getDynamicStates(const VkPipelineDynamicStateCreateInfo *dynamicStateInfo,
2099                                              uint32_t setupState)
2100 {
2101     static const std::set<VkDynamicState> vertexInputStates{
2102         VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT,
2103         VK_DYNAMIC_STATE_VERTEX_INPUT_EXT,
2104         VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT,
2105         VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT,
2106     };
2107 
2108     static const std::set<VkDynamicState> preRastStates{
2109         VK_DYNAMIC_STATE_VIEWPORT,
2110         VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT,
2111         VK_DYNAMIC_STATE_SCISSOR,
2112         VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT,
2113         VK_DYNAMIC_STATE_LINE_WIDTH,
2114         VK_DYNAMIC_STATE_LINE_STIPPLE_EXT,
2115         VK_DYNAMIC_STATE_CULL_MODE_EXT,
2116         VK_DYNAMIC_STATE_FRONT_FACE_EXT,
2117         VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT,
2118         VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT,
2119         VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT,
2120         VK_DYNAMIC_STATE_DEPTH_BIAS,
2121         VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT,
2122         VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR,
2123 #ifndef CTS_USES_VULKANSC
2124         VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT,
2125         VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT,
2126         VK_DYNAMIC_STATE_POLYGON_MODE_EXT,
2127         VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT,
2128         VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT,
2129         VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT,
2130         VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT,
2131         VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT,
2132         VK_DYNAMIC_STATE_LINE_STIPPLE_EXT,
2133         VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT,
2134         VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT,
2135         VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT,
2136         VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV,
2137         VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV,
2138         VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV,
2139         VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV,
2140         VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV,
2141         VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV,
2142         VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV,
2143 #endif
2144     };
2145 
2146     static const std::set<VkDynamicState> fragShaderStates{
2147         VK_DYNAMIC_STATE_DEPTH_BOUNDS,
2148         VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,
2149         VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
2150         VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,
2151         VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT,
2152         VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
2153         VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
2154         VK_DYNAMIC_STATE_STENCIL_REFERENCE,
2155         VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT,
2156         VK_DYNAMIC_STATE_STENCIL_OP_EXT,
2157         VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR,
2158         // Needs MSAA info here as well as fragment output state
2159         VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT,
2160 #ifndef CTS_USES_VULKANSC
2161         VK_DYNAMIC_STATE_SAMPLE_MASK_EXT,
2162         VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT,
2163         VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT,
2164         VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT,
2165         VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT,
2166         VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV,
2167         VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV,
2168         VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV,
2169         VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV,
2170         VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV,
2171         VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV,
2172         VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV,
2173 #endif
2174     };
2175 
2176     static const std::set<VkDynamicState> fragOutputStates{
2177         VK_DYNAMIC_STATE_LOGIC_OP_EXT,
2178         VK_DYNAMIC_STATE_BLEND_CONSTANTS,
2179         VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT,
2180         VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR,
2181         VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT,
2182 #ifndef CTS_USES_VULKANSC
2183         VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT,
2184         VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT,
2185         VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT,
2186         VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT,
2187         VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT,
2188         VK_DYNAMIC_STATE_SAMPLE_MASK_EXT,
2189         VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT,
2190         VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT,
2191         VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT,
2192         VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT,
2193         VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV,
2194         VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV,
2195         VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV,
2196         VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV,
2197         VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV,
2198         VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV,
2199         VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV,
2200         VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT,
2201 #endif
2202     };
2203 
2204     const std::set<VkDynamicState> dynamicStates(
2205         dynamicStateInfo->pDynamicStates, dynamicStateInfo->pDynamicStates + dynamicStateInfo->dynamicStateCount);
2206 
2207     // Verify all passed states are contained in at least one of the vectors above, so they won't get lost.
2208     for (const auto dynState : dynamicStates)
2209     {
2210         DE_UNREF(dynState); // For release builds.
2211         DE_ASSERT(de::contains(vertexInputStates.begin(), vertexInputStates.end(), dynState) ||
2212                   de::contains(preRastStates.begin(), preRastStates.end(), dynState) ||
2213                   de::contains(fragShaderStates.begin(), fragShaderStates.end(), dynState) ||
2214                   de::contains(fragOutputStates.begin(), fragOutputStates.end(), dynState));
2215     }
2216 
2217     std::set<VkDynamicState> intersectedStates;
2218 
2219     if (setupState & PSS_VERTEX_INPUT_INTERFACE)
2220         std::set_intersection(vertexInputStates.begin(), vertexInputStates.end(), dynamicStates.begin(),
2221                               dynamicStates.end(), std::inserter(intersectedStates, intersectedStates.end()));
2222 
2223     if (setupState & PSS_PRE_RASTERIZATION_SHADERS)
2224         std::set_intersection(preRastStates.begin(), preRastStates.end(), dynamicStates.begin(), dynamicStates.end(),
2225                               std::inserter(intersectedStates, intersectedStates.end()));
2226 
2227     if (setupState & PSS_FRAGMENT_SHADER)
2228         std::set_intersection(fragShaderStates.begin(), fragShaderStates.end(), dynamicStates.begin(),
2229                               dynamicStates.end(), std::inserter(intersectedStates, intersectedStates.end()));
2230 
2231     if (setupState & PSS_FRAGMENT_OUTPUT_INTERFACE)
2232         std::set_intersection(fragOutputStates.begin(), fragOutputStates.end(), dynamicStates.begin(),
2233                               dynamicStates.end(), std::inserter(intersectedStates, intersectedStates.end()));
2234 
2235     const std::vector<VkDynamicState> returnedStates(begin(intersectedStates), end(intersectedStates));
2236 
2237     return returnedStates;
2238 }
2239 
setDefaultTopology(const VkPrimitiveTopology topology)2240 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setDefaultTopology(const VkPrimitiveTopology topology)
2241 {
2242     // topology is needed by vertex input state, make sure vertex input state was not setup yet
2243     DE_ASSERT(m_internalData && (m_internalData->setupState == PSS_NONE));
2244 
2245     m_internalData->inputAssemblyState.topology = topology;
2246 
2247     return *this;
2248 }
2249 
setDefaultPatchControlPoints(const uint32_t patchControlPoints)2250 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setDefaultPatchControlPoints(const uint32_t patchControlPoints)
2251 {
2252     // patchControlPoints are needed by pre-rasterization shader state, make sure pre-rasterization state was not setup yet
2253     DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
2254 
2255     m_internalData->tessellationState.patchControlPoints = patchControlPoints;
2256 
2257     return *this;
2258 }
2259 
setDefaultTessellationDomainOrigin(const VkTessellationDomainOrigin domainOrigin,bool forceExtStruct)2260 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setDefaultTessellationDomainOrigin(
2261     const VkTessellationDomainOrigin domainOrigin, bool forceExtStruct)
2262 {
2263     // Tessellation domain origin is needed by pre-rasterization shader state, make sure pre-rasterization state was not setup yet
2264     DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
2265 
2266     // We need the extension structure when:
2267     // - We want to force it.
2268     // - The domain origin is not the default value.
2269     // - We have already hooked the extension structure.
2270     if (forceExtStruct || domainOrigin != VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT ||
2271         m_internalData->pTessellationDomainOrigin)
2272     {
2273         if (!m_internalData->pTessellationDomainOrigin)
2274         {
2275             m_internalData->pTessellationDomainOrigin.reset(
2276                 new VkPipelineTessellationDomainOriginStateCreateInfo(initVulkanStructure()));
2277             m_internalData->tessellationState.pNext = m_internalData->pTessellationDomainOrigin.get();
2278         }
2279         m_internalData->pTessellationDomainOrigin->domainOrigin = domainOrigin;
2280     }
2281 
2282     return *this;
2283 }
2284 
setDefaultRasterizerDiscardEnable(const bool rasterizerDiscardEnable)2285 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setDefaultRasterizerDiscardEnable(const bool rasterizerDiscardEnable)
2286 {
2287     // rasterizerDiscardEnable is used in pre-rasterization shader state, make sure pre-rasterization state was not setup yet
2288     DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
2289 
2290     m_internalData->defaultRasterizationState.rasterizerDiscardEnable = rasterizerDiscardEnable;
2291 
2292     return *this;
2293 }
2294 
setDefaultRasterizationState()2295 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setDefaultRasterizationState()
2296 {
2297     // RasterizationState is used in pre-rasterization shader state, make sure this state was not setup yet
2298     DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
2299 
2300     m_internalData->useDefaultRasterizationState = true;
2301 
2302     return *this;
2303 }
2304 
setDefaultDepthStencilState()2305 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setDefaultDepthStencilState()
2306 {
2307     // DepthStencilState is used in fragment shader state, make sure fragment shader state was not setup yet
2308     DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_FRAGMENT_SHADER));
2309 
2310     m_internalData->useDefaultDepthStencilState = true;
2311 
2312     return *this;
2313 }
2314 
setDefaultColorBlendState()2315 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setDefaultColorBlendState()
2316 {
2317     // ColorBlendState is used in fragment shader state, make sure fragment shader state was not setup yet
2318     DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_FRAGMENT_SHADER));
2319 
2320     m_internalData->useDefaultColorBlendState = true;
2321 
2322     return *this;
2323 }
2324 
setDefaultMultisampleState()2325 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setDefaultMultisampleState()
2326 {
2327     // MultisampleState is used in fragment shader state, make sure fragment shader state was not setup yet
2328     DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_FRAGMENT_SHADER));
2329 
2330     m_internalData->useDefaultMultisampleState = true;
2331 
2332     return *this;
2333 }
2334 
setDefaultVertexInputState(const bool useDefaultVertexInputState)2335 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setDefaultVertexInputState(const bool useDefaultVertexInputState)
2336 {
2337     // Make sure vertex input state was not setup yet.
2338     DE_ASSERT(m_internalData && (m_internalData->setupState == PSS_NONE));
2339 
2340     m_internalData->useDefaultVertexInputState = useDefaultVertexInputState;
2341 
2342     return *this;
2343 }
2344 
setDefaultViewportsCount(uint32_t viewportCount)2345 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setDefaultViewportsCount(uint32_t viewportCount)
2346 {
2347     // ViewportState is used in pre-rasterization shader state, make sure pre-rasterization state was not setup yet
2348     DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
2349 
2350     m_internalData->viewportState.viewportCount = viewportCount;
2351 
2352     return *this;
2353 }
2354 
setDefaultScissorsCount(uint32_t scissorCount)2355 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setDefaultScissorsCount(uint32_t scissorCount)
2356 {
2357     // ViewportState is used in pre-rasterization shader state, make sure pre-rasterization state was not setup yet
2358     DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
2359 
2360     m_internalData->viewportState.scissorCount = scissorCount;
2361 
2362     return *this;
2363 }
2364 
setViewportStatePnext(const void * pNext)2365 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setViewportStatePnext(const void *pNext)
2366 {
2367     // ViewportState is used in pre-rasterization shader state, make sure pre-rasterization state was not setup yet
2368     DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
2369 
2370     m_internalData->viewportState.pNext = pNext;
2371 
2372     return *this;
2373 }
2374 
2375 #ifndef CTS_USES_VULKANSC
setRenderingColorAttachmentsInfo(PipelineRenderingCreateInfoWrapper pipelineRenderingCreateInfo)2376 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setRenderingColorAttachmentsInfo(
2377     PipelineRenderingCreateInfoWrapper pipelineRenderingCreateInfo)
2378 {
2379     /* When both graphics pipeline library and dynamic rendering enabled, we just need only viewMask of VkPipelineRenderingCreateInfo
2380      * on non-fragment stages. But we need the rest info for setting up fragment output states.
2381      * This method provides a way to verify this condition.
2382      */
2383     if (!m_internalData->pRenderingState.ptr || !isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
2384         return *this;
2385 
2386     DE_ASSERT(m_internalData && (m_internalData->setupState > PSS_VERTEX_INPUT_INTERFACE) &&
2387               (m_internalData->setupState < PSS_FRAGMENT_OUTPUT_INTERFACE) &&
2388               (m_internalData->pRenderingState.ptr->viewMask == pipelineRenderingCreateInfo.ptr->viewMask));
2389 
2390     m_internalData->pRenderingState.ptr = pipelineRenderingCreateInfo.ptr;
2391 
2392     return *this;
2393 }
2394 #endif
2395 
disableViewportState(const bool disable)2396 GraphicsPipelineWrapper &GraphicsPipelineWrapper::disableViewportState(const bool disable)
2397 {
2398     // ViewportState is used in pre-rasterization shader state, make sure pre-rasterization state was not setup yet
2399     DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
2400 
2401     m_internalData->useViewportState = !disable;
2402 
2403     return *this;
2404 }
2405 
setupVertexInputState(const VkPipelineVertexInputStateCreateInfo * vertexInputState,const VkPipelineInputAssemblyStateCreateInfo * inputAssemblyState,const VkPipelineCache partPipelineCache,PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback,const bool useNullPtrs)2406 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setupVertexInputState(
2407     const VkPipelineVertexInputStateCreateInfo *vertexInputState,
2408     const VkPipelineInputAssemblyStateCreateInfo *inputAssemblyState, const VkPipelineCache partPipelineCache,
2409     PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback, const bool useNullPtrs)
2410 {
2411     // make sure pipeline was not already build
2412     DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
2413 
2414     // make sure states are set in order - no need to complicate logic to support out of order specification - this state needs to be set first
2415     DE_ASSERT(m_internalData && (m_internalData->setupState == PSS_NONE));
2416 
2417     // Unreference variables that are not used in Vulkan SC. No need to put this in ifdef.
2418     DE_UNREF(partPipelineCache);
2419     DE_UNREF(partCreationFeedback);
2420 
2421     m_internalData->setupState = PSS_VERTEX_INPUT_INTERFACE;
2422 
2423     const auto pVertexInputState =
2424         ((vertexInputState || useNullPtrs || !m_internalData->useDefaultVertexInputState) ? vertexInputState :
2425                                                                                             &defaultVertexInputState);
2426     const auto pInputAssemblyState =
2427         ((inputAssemblyState || useNullPtrs) ? inputAssemblyState : &m_internalData->inputAssemblyState);
2428 
2429     if (!isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
2430     {
2431         m_internalData->monolithicPipelineCreateInfo.pVertexInputState   = pVertexInputState;
2432         m_internalData->monolithicPipelineCreateInfo.pInputAssemblyState = pInputAssemblyState;
2433     }
2434 
2435 #ifndef CTS_USES_VULKANSC
2436     // note we could just use else to if statement above but sinc
2437     // this section is cut out for Vulkan SC its cleaner with separate if
2438     if (isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
2439     {
2440         auto libraryCreateInfo =
2441             makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT);
2442         void *firstStructInChain = reinterpret_cast<void *>(&libraryCreateInfo);
2443         addToChain(&firstStructInChain, partCreationFeedback.ptr);
2444         addToChain(&firstStructInChain, m_internalData->pPipelineRobustnessState.ptr);
2445 
2446         VkPipelineDynamicStateCreateInfo pickedDynamicStateInfo = initVulkanStructure();
2447         std::vector<VkDynamicState> states;
2448 
2449         if (m_internalData->pDynamicState)
2450         {
2451             states = getDynamicStates(m_internalData->pDynamicState, m_internalData->setupState);
2452 
2453             pickedDynamicStateInfo.pDynamicStates    = states.data();
2454             pickedDynamicStateInfo.dynamicStateCount = static_cast<uint32_t>(states.size());
2455         }
2456 
2457         VkGraphicsPipelineCreateInfo pipelinePartCreateInfo = initVulkanStructure();
2458         pipelinePartCreateInfo.pNext                        = firstStructInChain;
2459         pipelinePartCreateInfo.flags =
2460             (m_internalData->pipelineFlags | VK_PIPELINE_CREATE_LIBRARY_BIT_KHR) & ~VK_PIPELINE_CREATE_DERIVATIVE_BIT;
2461         pipelinePartCreateInfo.pVertexInputState   = pVertexInputState;
2462         pipelinePartCreateInfo.pInputAssemblyState = pInputAssemblyState;
2463         pipelinePartCreateInfo.pDynamicState       = &pickedDynamicStateInfo;
2464 
2465         if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
2466             pipelinePartCreateInfo.flags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
2467 
2468         VkPipelineCreateFlags2CreateInfoKHR pipelineFlags2CreateInfo = initVulkanStructure();
2469         if (m_internalData->pipelineFlags2)
2470         {
2471             pipelineFlags2CreateInfo.flags =
2472                 m_internalData->pipelineFlags2 | translateCreateFlag(pipelinePartCreateInfo.flags);
2473             addToChain(&firstStructInChain, &pipelineFlags2CreateInfo);
2474             pipelinePartCreateInfo.flags = 0u;
2475         }
2476 
2477         m_pipelineParts[0] = makeGraphicsPipeline(m_internalData->vk, m_internalData->device, partPipelineCache,
2478                                                   &pipelinePartCreateInfo);
2479     }
2480 #endif // CTS_USES_VULKANSC
2481 
2482     return *this;
2483 }
2484 
setupPreRasterizationShaderState(const std::vector<VkViewport> & viewports,const std::vector<VkRect2D> & scissors,const PipelineLayoutWrapper & layout,const VkRenderPass renderPass,const uint32_t subpass,const ShaderWrapper vertexShader,const VkPipelineRasterizationStateCreateInfo * rasterizationState,const ShaderWrapper tessellationControlShader,const ShaderWrapper tessellationEvalShader,const ShaderWrapper geometryShader,const VkSpecializationInfo * specializationInfo,VkPipelineFragmentShadingRateStateCreateInfoKHR * fragmentShadingRateState,PipelineRenderingCreateInfoWrapper rendering,const VkPipelineCache partPipelineCache,PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback)2485 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setupPreRasterizationShaderState(
2486     const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
2487     const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass,
2488     const ShaderWrapper vertexShader, const VkPipelineRasterizationStateCreateInfo *rasterizationState,
2489     const ShaderWrapper tessellationControlShader, const ShaderWrapper tessellationEvalShader,
2490     const ShaderWrapper geometryShader, const VkSpecializationInfo *specializationInfo,
2491     VkPipelineFragmentShadingRateStateCreateInfoKHR *fragmentShadingRateState,
2492     PipelineRenderingCreateInfoWrapper rendering, const VkPipelineCache partPipelineCache,
2493     PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback)
2494 {
2495     return setupPreRasterizationShaderState2(
2496         viewports, scissors, layout, renderPass, subpass, vertexShader, rasterizationState, tessellationControlShader,
2497         tessellationEvalShader, geometryShader,
2498         // Reuse the same specialization info for all stages.
2499         specializationInfo, specializationInfo, specializationInfo, specializationInfo, fragmentShadingRateState,
2500         rendering, partPipelineCache, partCreationFeedback);
2501 }
2502 
setupPreRasterizationShaderState2(const std::vector<VkViewport> & viewports,const std::vector<VkRect2D> & scissors,const PipelineLayoutWrapper & layout,const VkRenderPass renderPass,const uint32_t subpass,const ShaderWrapper vertexShader,const VkPipelineRasterizationStateCreateInfo * rasterizationState,const ShaderWrapper tessellationControlShader,const ShaderWrapper tessellationEvalShader,const ShaderWrapper geometryShader,const VkSpecializationInfo * vertSpecializationInfo,const VkSpecializationInfo * tescSpecializationInfo,const VkSpecializationInfo * teseSpecializationInfo,const VkSpecializationInfo * geomSpecializationInfo,VkPipelineFragmentShadingRateStateCreateInfoKHR * fragmentShadingRateState,PipelineRenderingCreateInfoWrapper rendering,const VkPipelineCache partPipelineCache,PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback)2503 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setupPreRasterizationShaderState2(
2504     const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
2505     const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass,
2506     const ShaderWrapper vertexShader, const VkPipelineRasterizationStateCreateInfo *rasterizationState,
2507     const ShaderWrapper tessellationControlShader, const ShaderWrapper tessellationEvalShader,
2508     const ShaderWrapper geometryShader, const VkSpecializationInfo *vertSpecializationInfo,
2509     const VkSpecializationInfo *tescSpecializationInfo, const VkSpecializationInfo *teseSpecializationInfo,
2510     const VkSpecializationInfo *geomSpecializationInfo,
2511     VkPipelineFragmentShadingRateStateCreateInfoKHR *fragmentShadingRateState,
2512     PipelineRenderingCreateInfoWrapper rendering, const VkPipelineCache partPipelineCache,
2513     PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback)
2514 {
2515     return setupPreRasterizationShaderState3(
2516         viewports, scissors, layout, renderPass, subpass, vertexShader,
2517         PipelineShaderStageModuleIdentifierCreateInfoWrapper(), rasterizationState, tessellationControlShader,
2518         PipelineShaderStageModuleIdentifierCreateInfoWrapper(), tessellationEvalShader,
2519         PipelineShaderStageModuleIdentifierCreateInfoWrapper(), geometryShader,
2520         PipelineShaderStageModuleIdentifierCreateInfoWrapper(), vertSpecializationInfo, tescSpecializationInfo,
2521         teseSpecializationInfo, geomSpecializationInfo, fragmentShadingRateState, rendering, partPipelineCache,
2522         partCreationFeedback);
2523 }
2524 
setupPreRasterizationShaderState3(const std::vector<VkViewport> & viewports,const std::vector<VkRect2D> & scissors,const PipelineLayoutWrapper & layout,const VkRenderPass renderPass,const uint32_t subpass,const ShaderWrapper vertexShader,PipelineShaderStageModuleIdentifierCreateInfoWrapper vertShaderModuleId,const VkPipelineRasterizationStateCreateInfo * rasterizationState,const ShaderWrapper tessellationControlShader,PipelineShaderStageModuleIdentifierCreateInfoWrapper tescShaderModuleId,const ShaderWrapper tessellationEvalShader,PipelineShaderStageModuleIdentifierCreateInfoWrapper teseShaderModuleId,const ShaderWrapper geometryShader,PipelineShaderStageModuleIdentifierCreateInfoWrapper geomShaderModuleId,const VkSpecializationInfo * vertSpecializationInfo,const VkSpecializationInfo * tescSpecializationInfo,const VkSpecializationInfo * teseSpecializationInfo,const VkSpecializationInfo * geomSpecializationInfo,VkPipelineFragmentShadingRateStateCreateInfoKHR * fragmentShadingRateState,PipelineRenderingCreateInfoWrapper rendering,const VkPipelineCache partPipelineCache,PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback)2525 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setupPreRasterizationShaderState3(
2526     const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
2527     const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass,
2528     const ShaderWrapper vertexShader, PipelineShaderStageModuleIdentifierCreateInfoWrapper vertShaderModuleId,
2529     const VkPipelineRasterizationStateCreateInfo *rasterizationState, const ShaderWrapper tessellationControlShader,
2530     PipelineShaderStageModuleIdentifierCreateInfoWrapper tescShaderModuleId, const ShaderWrapper tessellationEvalShader,
2531     PipelineShaderStageModuleIdentifierCreateInfoWrapper teseShaderModuleId, const ShaderWrapper geometryShader,
2532     PipelineShaderStageModuleIdentifierCreateInfoWrapper geomShaderModuleId,
2533     const VkSpecializationInfo *vertSpecializationInfo, const VkSpecializationInfo *tescSpecializationInfo,
2534     const VkSpecializationInfo *teseSpecializationInfo, const VkSpecializationInfo *geomSpecializationInfo,
2535     VkPipelineFragmentShadingRateStateCreateInfoKHR *fragmentShadingRateState,
2536     PipelineRenderingCreateInfoWrapper rendering, const VkPipelineCache partPipelineCache,
2537     PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback)
2538 {
2539     // make sure pipeline was not already build
2540     DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
2541 
2542     // make sure states are set in order - no need to complicate logic to support out of order specification - this state needs to be set second
2543     DE_ASSERT(m_internalData && (m_internalData->setupState == PSS_VERTEX_INPUT_INTERFACE));
2544 
2545     // Unreference variables that are not used in Vulkan SC. No need to put this in ifdef.
2546     DE_UNREF(partPipelineCache);
2547     DE_UNREF(partCreationFeedback);
2548     DE_UNREF(vertShaderModuleId);
2549     DE_UNREF(tescShaderModuleId);
2550     DE_UNREF(teseShaderModuleId);
2551     DE_UNREF(geomShaderModuleId);
2552 
2553     m_internalData->setupState |= PSS_PRE_RASTERIZATION_SHADERS;
2554     m_internalData->pFragmentShadingRateState = fragmentShadingRateState;
2555     m_internalData->pRenderingState.ptr       = rendering.ptr;
2556 
2557     const bool hasTesc = (tessellationControlShader.isSet() || tescShaderModuleId.ptr);
2558     const bool hasTese = (tessellationEvalShader.isSet() || teseShaderModuleId.ptr);
2559     const bool hasGeom = (geometryShader.isSet() || geomShaderModuleId.ptr);
2560 
2561     const auto pRasterizationState =
2562         rasterizationState ?
2563             rasterizationState :
2564             (m_internalData->useDefaultRasterizationState ? &m_internalData->defaultRasterizationState : DE_NULL);
2565     const bool forceNullTessState =
2566         (m_internalData->tessellationState.patchControlPoints == std::numeric_limits<uint32_t>::max());
2567     const auto pTessellationState =
2568         ((hasTesc || hasTese) && !forceNullTessState) ? &m_internalData->tessellationState : nullptr;
2569     const auto pViewportState = m_internalData->useViewportState ? &m_internalData->viewportState : DE_NULL;
2570 
2571     VkPipelineCreateFlags shaderModuleIdFlags = 0u;
2572 
2573     m_internalData->vertexShader = vertexShader;
2574     m_internalData->vertexShader.setLayoutAndSpecialization(&layout, vertSpecializationInfo);
2575     if (!isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
2576         m_internalData->vertexShader.createModule();
2577 
2578     // reserve space for all stages including fragment - this is needed when we create monolithic pipeline
2579     m_internalData->pipelineShaderStages = std::vector<VkPipelineShaderStageCreateInfo>(
2580         2u + hasTesc + hasTese + hasGeom,
2581         {
2582             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType                        sType
2583             DE_NULL,                                             // const void*                            pNext
2584             0u,                                                  // VkPipelineShaderStageCreateFlags        flags
2585             VK_SHADER_STAGE_VERTEX_BIT,                          // VkShaderStageFlagBits                stage
2586             m_internalData->vertexShader.getModule(),            // VkShaderModule                        module
2587             "main",                                              // const char*                            pName
2588             vertSpecializationInfo // const VkSpecializationInfo*            pSpecializationInfo
2589         });
2590 
2591 #ifndef CTS_USES_VULKANSC
2592     if (vertShaderModuleId.ptr)
2593     {
2594         m_internalData->pipelineShaderIdentifiers.emplace_back(
2595             new PipelineShaderStageModuleIdentifierCreateInfoWrapper(vertShaderModuleId.ptr));
2596         m_internalData->pipelineShaderStages[0].pNext = m_internalData->pipelineShaderIdentifiers.back().get()->ptr;
2597 
2598         if (!vertexShader.isSet())
2599             shaderModuleIdFlags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
2600     }
2601 #endif // CTS_USES_VULKANSC
2602 
2603     std::vector<VkPipelineShaderStageCreateInfo>::iterator currStage = m_internalData->pipelineShaderStages.begin() + 1;
2604 
2605     if (hasTesc)
2606     {
2607         m_internalData->tessellationControlShader = tessellationControlShader;
2608         m_internalData->tessellationControlShader.setLayoutAndSpecialization(&layout, tescSpecializationInfo);
2609         if (!isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
2610             m_internalData->tessellationControlShader.createModule();
2611 
2612         currStage->stage               = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
2613         currStage->module              = m_internalData->tessellationControlShader.getModule();
2614         currStage->pSpecializationInfo = tescSpecializationInfo;
2615 
2616 #ifndef CTS_USES_VULKANSC
2617         if (tescShaderModuleId.ptr)
2618         {
2619             m_internalData->pipelineShaderIdentifiers.emplace_back(
2620                 new PipelineShaderStageModuleIdentifierCreateInfoWrapper(tescShaderModuleId.ptr));
2621             currStage->pNext = m_internalData->pipelineShaderIdentifiers.back().get()->ptr;
2622 
2623             if (!tessellationControlShader.isSet())
2624                 shaderModuleIdFlags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
2625         }
2626 #endif // CTS_USES_VULKANSC
2627 
2628         ++currStage;
2629     }
2630 
2631     if (hasTese)
2632     {
2633         m_internalData->tessellationEvaluationShader = tessellationEvalShader;
2634         m_internalData->tessellationEvaluationShader.setLayoutAndSpecialization(&layout, teseSpecializationInfo);
2635         if (!isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
2636             m_internalData->tessellationEvaluationShader.createModule();
2637 
2638         currStage->stage               = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
2639         currStage->module              = m_internalData->tessellationEvaluationShader.getModule();
2640         currStage->pSpecializationInfo = teseSpecializationInfo;
2641 
2642 #ifndef CTS_USES_VULKANSC
2643         if (teseShaderModuleId.ptr)
2644         {
2645             m_internalData->pipelineShaderIdentifiers.emplace_back(
2646                 new PipelineShaderStageModuleIdentifierCreateInfoWrapper(teseShaderModuleId.ptr));
2647             currStage->pNext = m_internalData->pipelineShaderIdentifiers.back().get()->ptr;
2648 
2649             if (!tessellationEvalShader.isSet())
2650                 shaderModuleIdFlags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
2651         }
2652 #endif // CTS_USES_VULKANSC
2653 
2654         ++currStage;
2655     }
2656 
2657     if (hasGeom)
2658     {
2659         m_internalData->geometryShader = geometryShader;
2660         m_internalData->geometryShader.setLayoutAndSpecialization(&layout, geomSpecializationInfo);
2661         if (!isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
2662             m_internalData->geometryShader.createModule();
2663 
2664         currStage->stage               = VK_SHADER_STAGE_GEOMETRY_BIT;
2665         currStage->module              = m_internalData->geometryShader.getModule();
2666         currStage->pSpecializationInfo = geomSpecializationInfo;
2667 
2668 #ifndef CTS_USES_VULKANSC
2669         if (geomShaderModuleId.ptr)
2670         {
2671             m_internalData->pipelineShaderIdentifiers.emplace_back(
2672                 new PipelineShaderStageModuleIdentifierCreateInfoWrapper(geomShaderModuleId.ptr));
2673             currStage->pNext = m_internalData->pipelineShaderIdentifiers.back().get()->ptr;
2674 
2675             if (!geometryShader.isSet())
2676                 shaderModuleIdFlags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
2677         }
2678 #endif // CTS_USES_VULKANSC
2679     }
2680 
2681     if (pViewportState)
2682     {
2683         if (!viewports.empty())
2684         {
2685             pViewportState->viewportCount = (uint32_t)viewports.size();
2686             pViewportState->pViewports    = &viewports[0];
2687         }
2688         if (!scissors.empty())
2689         {
2690             pViewportState->scissorCount = (uint32_t)scissors.size();
2691             pViewportState->pScissors    = &scissors[0];
2692         }
2693     }
2694 
2695     // if pipeline layout was not specified with setupMonolithicPipelineLayout
2696     // then use layout from setupPreRasterizationShaderState for link pipeline
2697     if (!m_internalData->explicitLinkPipelineLayoutSet)
2698         m_internalData->monolithicPipelineCreateInfo.layout = *layout;
2699 
2700     if (!isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
2701     {
2702         m_internalData->monolithicPipelineCreateInfo.renderPass          = renderPass;
2703         m_internalData->monolithicPipelineCreateInfo.subpass             = subpass;
2704         m_internalData->monolithicPipelineCreateInfo.pRasterizationState = pRasterizationState;
2705         m_internalData->monolithicPipelineCreateInfo.pViewportState      = pViewportState;
2706         m_internalData->monolithicPipelineCreateInfo.stageCount          = 1u + hasTesc + hasTese + hasGeom;
2707         m_internalData->monolithicPipelineCreateInfo.pStages             = m_internalData->pipelineShaderStages.data();
2708         m_internalData->monolithicPipelineCreateInfo.pTessellationState  = pTessellationState;
2709         m_internalData->monolithicPipelineCreateInfo.flags |= shaderModuleIdFlags;
2710     }
2711 
2712 #ifndef CTS_USES_VULKANSC
2713     // note we could just use else to if statement above but sinc
2714     // this section is cut out for Vulkan SC its cleaner with separate if
2715     if (isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
2716     {
2717         auto libraryCreateInfo =
2718             makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT);
2719         void *firstStructInChain = reinterpret_cast<void *>(&libraryCreateInfo);
2720         addToChain(&firstStructInChain, m_internalData->pFragmentShadingRateState);
2721         addToChain(&firstStructInChain, m_internalData->pRenderingState.ptr);
2722         addToChain(&firstStructInChain, partCreationFeedback.ptr);
2723         addToChain(&firstStructInChain, m_internalData->pPipelineRobustnessState.ptr);
2724 
2725         VkPipelineDynamicStateCreateInfo pickedDynamicStateInfo = initVulkanStructure();
2726         std::vector<VkDynamicState> states;
2727 
2728         if (m_internalData->pDynamicState)
2729         {
2730             states = getDynamicStates(m_internalData->pDynamicState, m_internalData->setupState);
2731 
2732             pickedDynamicStateInfo.pDynamicStates    = states.data();
2733             pickedDynamicStateInfo.dynamicStateCount = static_cast<uint32_t>(states.size());
2734         }
2735 
2736         VkGraphicsPipelineCreateInfo pipelinePartCreateInfo = initVulkanStructure();
2737         pipelinePartCreateInfo.pNext                        = firstStructInChain;
2738         pipelinePartCreateInfo.flags =
2739             (m_internalData->pipelineFlags | VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | shaderModuleIdFlags) &
2740             ~VK_PIPELINE_CREATE_DERIVATIVE_BIT;
2741         pipelinePartCreateInfo.layout              = *layout;
2742         pipelinePartCreateInfo.renderPass          = renderPass;
2743         pipelinePartCreateInfo.subpass             = subpass;
2744         pipelinePartCreateInfo.pRasterizationState = pRasterizationState;
2745         pipelinePartCreateInfo.pViewportState      = pViewportState;
2746         pipelinePartCreateInfo.stageCount          = 1u + hasTesc + hasTese + hasGeom;
2747         pipelinePartCreateInfo.pStages             = m_internalData->pipelineShaderStages.data();
2748         pipelinePartCreateInfo.pTessellationState  = pTessellationState;
2749         pipelinePartCreateInfo.pDynamicState       = &pickedDynamicStateInfo;
2750 
2751         if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
2752             pipelinePartCreateInfo.flags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
2753 
2754         if ((shaderModuleIdFlags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT) != 0)
2755             m_internalData->failOnCompileWhenLinking = true;
2756 
2757         VkPipelineCreateFlags2CreateInfoKHR pipelineFlags2CreateInfo = initVulkanStructure();
2758         if (m_internalData->pipelineFlags2)
2759         {
2760             pipelineFlags2CreateInfo.flags =
2761                 m_internalData->pipelineFlags2 | translateCreateFlag(pipelinePartCreateInfo.flags);
2762             addToChain(&firstStructInChain, &pipelineFlags2CreateInfo);
2763             pipelinePartCreateInfo.flags = 0u;
2764         }
2765 
2766         m_pipelineParts[1] = makeGraphicsPipeline(m_internalData->vk, m_internalData->device, partPipelineCache,
2767                                                   &pipelinePartCreateInfo);
2768     }
2769 #endif // CTS_USES_VULKANSC
2770 
2771     return *this;
2772 }
2773 
2774 #ifndef CTS_USES_VULKANSC
setupPreRasterizationMeshShaderState(const std::vector<VkViewport> & viewports,const std::vector<VkRect2D> & scissors,const PipelineLayoutWrapper & layout,const VkRenderPass renderPass,const uint32_t subpass,const ShaderWrapper taskShader,const ShaderWrapper meshShader,const VkPipelineRasterizationStateCreateInfo * rasterizationState,const VkSpecializationInfo * taskSpecializationInfo,const VkSpecializationInfo * meshSpecializationInfo,VkPipelineFragmentShadingRateStateCreateInfoKHR * fragmentShadingRateState,PipelineRenderingCreateInfoWrapper rendering,const VkPipelineCache partPipelineCache,VkPipelineCreationFeedbackCreateInfoEXT * partCreationFeedback)2775 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setupPreRasterizationMeshShaderState(
2776     const std::vector<VkViewport> &viewports, const std::vector<VkRect2D> &scissors,
2777     const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass,
2778     const ShaderWrapper taskShader, const ShaderWrapper meshShader,
2779     const VkPipelineRasterizationStateCreateInfo *rasterizationState,
2780     const VkSpecializationInfo *taskSpecializationInfo, const VkSpecializationInfo *meshSpecializationInfo,
2781     VkPipelineFragmentShadingRateStateCreateInfoKHR *fragmentShadingRateState,
2782     PipelineRenderingCreateInfoWrapper rendering, const VkPipelineCache partPipelineCache,
2783     VkPipelineCreationFeedbackCreateInfoEXT *partCreationFeedback)
2784 {
2785     // Make sure pipeline was not already built.
2786     DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
2787 
2788     // Make sure states are set in order - this state needs to be set first or second.
2789     DE_ASSERT(m_internalData && (m_internalData->setupState < PSS_PRE_RASTERIZATION_SHADERS));
2790 
2791     // The vertex input interface is not needed for mesh shading pipelines, so we're going to mark it as ready here.
2792     m_internalData->setupState |= (PSS_VERTEX_INPUT_INTERFACE | PSS_PRE_RASTERIZATION_SHADERS);
2793     m_internalData->pFragmentShadingRateState = fragmentShadingRateState;
2794     m_internalData->pRenderingState           = rendering;
2795 
2796     const bool hasTask         = (taskShader.isSet());
2797     const auto taskShaderCount = static_cast<uint32_t>(hasTask);
2798     const auto pRasterizationState =
2799         rasterizationState ?
2800             rasterizationState :
2801             (m_internalData->useDefaultRasterizationState ? &m_internalData->defaultRasterizationState : nullptr);
2802     const auto pTessellationState = nullptr;
2803     const auto pViewportState     = m_internalData->useViewportState ? &m_internalData->viewportState : DE_NULL;
2804 
2805     // Reserve space for all stages including fragment. This is needed when we create monolithic pipeline.
2806     m_internalData->pipelineShaderStages = std::vector<VkPipelineShaderStageCreateInfo>(
2807         2u + taskShaderCount,
2808         {
2809             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType                        sType
2810             nullptr,                                             // const void*                            pNext
2811             0u,                                                  // VkPipelineShaderStageCreateFlags        flags
2812             VK_SHADER_STAGE_VERTEX_BIT,                          // VkShaderStageFlagBits                stage
2813             DE_NULL,                                             // VkShaderModule                        module
2814             "main",                                              // const char*                            pName
2815             nullptr, // const VkSpecializationInfo*            pSpecializationInfo
2816         });
2817 
2818     // Mesh shader.
2819     auto currStage = m_internalData->pipelineShaderStages.begin();
2820     {
2821         m_internalData->meshShader = meshShader;
2822         m_internalData->meshShader.setLayoutAndSpecialization(&layout, meshSpecializationInfo);
2823         if (!isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
2824             m_internalData->meshShader.createModule();
2825 
2826         auto &stageInfo = *currStage;
2827 
2828         stageInfo.stage               = VK_SHADER_STAGE_MESH_BIT_EXT;
2829         stageInfo.module              = m_internalData->meshShader.getModule();
2830         stageInfo.pSpecializationInfo = meshSpecializationInfo;
2831 
2832         ++currStage;
2833     }
2834 
2835     if (hasTask)
2836     {
2837         m_internalData->taskShader = taskShader;
2838         m_internalData->taskShader.setLayoutAndSpecialization(&layout, taskSpecializationInfo);
2839         if (!isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
2840             m_internalData->taskShader.createModule();
2841 
2842         auto &stageInfo = *currStage;
2843 
2844         stageInfo.stage               = VK_SHADER_STAGE_TASK_BIT_EXT;
2845         stageInfo.module              = m_internalData->taskShader.getModule();
2846         stageInfo.pSpecializationInfo = taskSpecializationInfo;
2847 
2848         ++currStage;
2849     }
2850 
2851     if (pViewportState)
2852     {
2853         if (!viewports.empty())
2854         {
2855             pViewportState->viewportCount = (uint32_t)viewports.size();
2856             pViewportState->pViewports    = &viewports[0];
2857         }
2858         if (!scissors.empty())
2859         {
2860             pViewportState->scissorCount = (uint32_t)scissors.size();
2861             pViewportState->pScissors    = &scissors[0];
2862         }
2863     }
2864 
2865     // if pipeline layout was not specified with setupMonolithicPipelineLayout
2866     // then use layout from setupPreRasterizationMeshShaderState for link pipeline
2867     if (!m_internalData->explicitLinkPipelineLayoutSet)
2868         m_internalData->monolithicPipelineCreateInfo.layout = *layout;
2869 
2870     if (!isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
2871     {
2872         m_internalData->monolithicPipelineCreateInfo.renderPass          = renderPass;
2873         m_internalData->monolithicPipelineCreateInfo.subpass             = subpass;
2874         m_internalData->monolithicPipelineCreateInfo.pRasterizationState = pRasterizationState;
2875         m_internalData->monolithicPipelineCreateInfo.pViewportState      = pViewportState;
2876         m_internalData->monolithicPipelineCreateInfo.stageCount          = 1u + taskShaderCount;
2877         m_internalData->monolithicPipelineCreateInfo.pStages             = m_internalData->pipelineShaderStages.data();
2878         m_internalData->monolithicPipelineCreateInfo.pTessellationState  = pTessellationState;
2879     }
2880     else
2881     {
2882         auto libraryCreateInfo =
2883             makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT);
2884         void *firstStructInChain = reinterpret_cast<void *>(&libraryCreateInfo);
2885         addToChain(&firstStructInChain, m_internalData->pFragmentShadingRateState);
2886         addToChain(&firstStructInChain, m_internalData->pRenderingState.ptr);
2887         addToChain(&firstStructInChain, partCreationFeedback);
2888         addToChain(&firstStructInChain, m_internalData->pPipelineRobustnessState.ptr);
2889 
2890         VkPipelineDynamicStateCreateInfo pickedDynamicStateInfo = initVulkanStructure();
2891         std::vector<VkDynamicState> states;
2892 
2893         if (m_internalData->pDynamicState)
2894         {
2895             states = getDynamicStates(m_internalData->pDynamicState, m_internalData->setupState);
2896 
2897             pickedDynamicStateInfo.pDynamicStates    = states.data();
2898             pickedDynamicStateInfo.dynamicStateCount = static_cast<uint32_t>(states.size());
2899         }
2900 
2901         VkGraphicsPipelineCreateInfo pipelinePartCreateInfo = initVulkanStructure();
2902         pipelinePartCreateInfo.pNext                        = firstStructInChain;
2903         pipelinePartCreateInfo.flags               = m_internalData->pipelineFlags | VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
2904         pipelinePartCreateInfo.layout              = *layout;
2905         pipelinePartCreateInfo.renderPass          = renderPass;
2906         pipelinePartCreateInfo.subpass             = subpass;
2907         pipelinePartCreateInfo.pRasterizationState = pRasterizationState;
2908         pipelinePartCreateInfo.pViewportState      = pViewportState;
2909         pipelinePartCreateInfo.stageCount          = 1u + taskShaderCount;
2910         pipelinePartCreateInfo.pStages             = m_internalData->pipelineShaderStages.data();
2911         pipelinePartCreateInfo.pTessellationState  = pTessellationState;
2912         pipelinePartCreateInfo.pDynamicState       = &pickedDynamicStateInfo;
2913 
2914         if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
2915             pipelinePartCreateInfo.flags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
2916 
2917         VkPipelineCreateFlags2CreateInfoKHR pipelineFlags2CreateInfo = initVulkanStructure();
2918         if (m_internalData->pipelineFlags2)
2919         {
2920             pipelineFlags2CreateInfo.flags =
2921                 m_internalData->pipelineFlags2 | translateCreateFlag(pipelinePartCreateInfo.flags);
2922             addToChain(&firstStructInChain, &pipelineFlags2CreateInfo);
2923             pipelinePartCreateInfo.flags = 0u;
2924         }
2925 
2926         m_pipelineParts[1] = createGraphicsPipeline(m_internalData->vk, m_internalData->device, partPipelineCache,
2927                                                     &pipelinePartCreateInfo);
2928     }
2929 
2930     return *this;
2931 }
2932 #endif // CTS_USES_VULKANSC
2933 
setupFragmentShaderState(const PipelineLayoutWrapper & layout,const VkRenderPass renderPass,const uint32_t subpass,const ShaderWrapper fragmentShader,const VkPipelineDepthStencilStateCreateInfo * depthStencilState,const VkPipelineMultisampleStateCreateInfo * multisampleState,const VkSpecializationInfo * specializationInfo,const VkPipelineCache partPipelineCache,PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback,RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfo)2934 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setupFragmentShaderState(
2935     const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass,
2936     const ShaderWrapper fragmentShader, const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
2937     const VkPipelineMultisampleStateCreateInfo *multisampleState, const VkSpecializationInfo *specializationInfo,
2938     const VkPipelineCache partPipelineCache, PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback,
2939     RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfo)
2940 {
2941     return setupFragmentShaderState2(layout, renderPass, subpass, fragmentShader,
2942                                      PipelineShaderStageModuleIdentifierCreateInfoWrapper(), depthStencilState,
2943                                      multisampleState, specializationInfo, partPipelineCache, partCreationFeedback,
2944                                      renderingInputAttachmentIndexInfo);
2945 }
2946 
setupFragmentShaderState2(const PipelineLayoutWrapper & layout,const VkRenderPass renderPass,const uint32_t subpass,const ShaderWrapper fragmentShader,PipelineShaderStageModuleIdentifierCreateInfoWrapper fragmentShaderModuleId,const VkPipelineDepthStencilStateCreateInfo * depthStencilState,const VkPipelineMultisampleStateCreateInfo * multisampleState,const VkSpecializationInfo * specializationInfo,const VkPipelineCache partPipelineCache,PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback,RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfo)2947 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setupFragmentShaderState2(
2948     const PipelineLayoutWrapper &layout, const VkRenderPass renderPass, const uint32_t subpass,
2949     const ShaderWrapper fragmentShader, PipelineShaderStageModuleIdentifierCreateInfoWrapper fragmentShaderModuleId,
2950     const VkPipelineDepthStencilStateCreateInfo *depthStencilState,
2951     const VkPipelineMultisampleStateCreateInfo *multisampleState, const VkSpecializationInfo *specializationInfo,
2952     const VkPipelineCache partPipelineCache, PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback,
2953     RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfo)
2954 {
2955     // make sure pipeline was not already build
2956     DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
2957 
2958     // make sure states are set in order - no need to complicate logic to support out of order specification - this state needs to be set third
2959     DE_ASSERT(m_internalData &&
2960               (m_internalData->setupState == (PSS_VERTEX_INPUT_INTERFACE | PSS_PRE_RASTERIZATION_SHADERS)));
2961 
2962     // Unreference variables that are not used in Vulkan SC. No need to put this in ifdef.
2963     DE_UNREF(layout);
2964     DE_UNREF(renderPass);
2965     DE_UNREF(subpass);
2966     DE_UNREF(partPipelineCache);
2967     DE_UNREF(partCreationFeedback);
2968     DE_UNREF(fragmentShaderModuleId);
2969 
2970     m_internalData->setupState |= PSS_FRAGMENT_SHADER;
2971     m_internalData->pRenderingInputAttachmentIndex.ptr = renderingInputAttachmentIndexInfo.ptr;
2972 
2973     const auto pDepthStencilState =
2974         depthStencilState ? depthStencilState :
2975                             (m_internalData->useDefaultDepthStencilState ? &defaultDepthStencilState : DE_NULL);
2976     const auto pMultisampleState =
2977         multisampleState ? multisampleState :
2978                            (m_internalData->useDefaultMultisampleState ? &defaultMultisampleState : DE_NULL);
2979     const bool hasFrag = (fragmentShader.isSet() || fragmentShaderModuleId.ptr);
2980 
2981     VkPipelineCreateFlags shaderModuleIdFlags = 0u;
2982 
2983     uint32_t stageIndex = 1;
2984     if (hasFrag)
2985     {
2986         // find free space for fragment shader
2987         for (; stageIndex < 5; ++stageIndex)
2988         {
2989             if (m_internalData->pipelineShaderStages[stageIndex].stage == VK_SHADER_STAGE_VERTEX_BIT)
2990             {
2991                 m_internalData->fragmentShader = fragmentShader;
2992                 m_internalData->fragmentShader.setLayoutAndSpecialization(&layout, specializationInfo);
2993                 if (!isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
2994                     m_internalData->fragmentShader.createModule();
2995 
2996                 m_internalData->pipelineShaderStages[stageIndex].stage  = VK_SHADER_STAGE_FRAGMENT_BIT;
2997                 m_internalData->pipelineShaderStages[stageIndex].module = m_internalData->fragmentShader.getModule();
2998                 m_internalData->pipelineShaderStages[stageIndex].pSpecializationInfo = specializationInfo;
2999 #ifndef CTS_USES_VULKANSC
3000                 if (fragmentShaderModuleId.ptr)
3001                 {
3002                     m_internalData->pipelineShaderIdentifiers.emplace_back(
3003                         new PipelineShaderStageModuleIdentifierCreateInfoWrapper(fragmentShaderModuleId.ptr));
3004                     m_internalData->pipelineShaderStages[stageIndex].pNext =
3005                         m_internalData->pipelineShaderIdentifiers.back().get()->ptr;
3006 
3007                     if (!fragmentShader.isSet())
3008                         shaderModuleIdFlags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
3009                 }
3010 #endif // CTS_USES_VULKANSC
3011                 break;
3012             }
3013         }
3014     }
3015 
3016     if (!isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
3017     {
3018         m_internalData->monolithicPipelineCreateInfo.pDepthStencilState = pDepthStencilState;
3019         m_internalData->monolithicPipelineCreateInfo.pMultisampleState  = pMultisampleState;
3020         m_internalData->monolithicPipelineCreateInfo.stageCount += (hasFrag ? 1u : 0u);
3021         m_internalData->monolithicPipelineCreateInfo.flags |= shaderModuleIdFlags;
3022     }
3023 
3024 #ifndef CTS_USES_VULKANSC
3025     // note we could just use else to if statement above but sinc
3026     // this section is cut out for Vulkan SC its cleaner with separate if
3027     if (isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
3028     {
3029         auto libraryCreateInfo =
3030             makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT);
3031         void *firstStructInChain = reinterpret_cast<void *>(&libraryCreateInfo);
3032         addToChain(&firstStructInChain, m_internalData->pFragmentShadingRateState);
3033         addToChain(&firstStructInChain, m_internalData->pRenderingState.ptr);
3034         addToChain(&firstStructInChain, m_internalData->pRenderingInputAttachmentIndex.ptr);
3035         addToChain(&firstStructInChain, partCreationFeedback.ptr);
3036         addToChain(&firstStructInChain, m_internalData->pRepresentativeFragmentTestState.ptr);
3037         addToChain(&firstStructInChain, m_internalData->pPipelineRobustnessState.ptr);
3038 
3039         VkPipelineDynamicStateCreateInfo pickedDynamicStateInfo = initVulkanStructure();
3040         std::vector<VkDynamicState> states;
3041 
3042         if (m_internalData->pDynamicState)
3043         {
3044             states = getDynamicStates(m_internalData->pDynamicState, m_internalData->setupState);
3045 
3046             pickedDynamicStateInfo.pDynamicStates    = states.data();
3047             pickedDynamicStateInfo.dynamicStateCount = static_cast<uint32_t>(states.size());
3048         }
3049 
3050         VkGraphicsPipelineCreateInfo pipelinePartCreateInfo = initVulkanStructure();
3051         pipelinePartCreateInfo.pNext                        = firstStructInChain;
3052         pipelinePartCreateInfo.flags =
3053             (m_internalData->pipelineFlags | VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | shaderModuleIdFlags) &
3054             ~VK_PIPELINE_CREATE_DERIVATIVE_BIT;
3055         pipelinePartCreateInfo.layout             = *layout;
3056         pipelinePartCreateInfo.renderPass         = renderPass;
3057         pipelinePartCreateInfo.subpass            = subpass;
3058         pipelinePartCreateInfo.pDepthStencilState = pDepthStencilState;
3059         pipelinePartCreateInfo.pMultisampleState  = pMultisampleState;
3060         pipelinePartCreateInfo.stageCount         = hasFrag;
3061         pipelinePartCreateInfo.pStages       = hasFrag ? &m_internalData->pipelineShaderStages[stageIndex] : DE_NULL;
3062         pipelinePartCreateInfo.pDynamicState = &pickedDynamicStateInfo;
3063 
3064         if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
3065             pipelinePartCreateInfo.flags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
3066 
3067         if ((shaderModuleIdFlags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT) != 0)
3068             m_internalData->failOnCompileWhenLinking = true;
3069 
3070         VkPipelineCreateFlags2CreateInfoKHR pipelineFlags2CreateInfo = initVulkanStructure();
3071         if (m_internalData->pipelineFlags2)
3072         {
3073             pipelineFlags2CreateInfo.flags =
3074                 m_internalData->pipelineFlags2 | translateCreateFlag(pipelinePartCreateInfo.flags);
3075             addToChain(&firstStructInChain, &pipelineFlags2CreateInfo);
3076             pipelinePartCreateInfo.flags = 0u;
3077         }
3078 
3079         m_pipelineParts[2] = makeGraphicsPipeline(m_internalData->vk, m_internalData->device, partPipelineCache,
3080                                                   &pipelinePartCreateInfo);
3081     }
3082 #endif // CTS_USES_VULKANSC
3083 
3084     return *this;
3085 }
3086 
setupFragmentOutputState(const VkRenderPass renderPass,const uint32_t subpass,const VkPipelineColorBlendStateCreateInfo * colorBlendState,const VkPipelineMultisampleStateCreateInfo * multisampleState,const VkPipelineCache partPipelineCache,PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback,RenderingAttachmentLocationInfoWrapper renderingAttachmentLocationInfo)3087 GraphicsPipelineWrapper &GraphicsPipelineWrapper::setupFragmentOutputState(
3088     const VkRenderPass renderPass, const uint32_t subpass, const VkPipelineColorBlendStateCreateInfo *colorBlendState,
3089     const VkPipelineMultisampleStateCreateInfo *multisampleState, const VkPipelineCache partPipelineCache,
3090     PipelineCreationFeedbackCreateInfoWrapper partCreationFeedback,
3091     RenderingAttachmentLocationInfoWrapper renderingAttachmentLocationInfo)
3092 {
3093     // make sure pipeline was not already build
3094     DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
3095 
3096     // make sure states are set in order - no need to complicate logic to support out of order specification - this state needs to be set last
3097     DE_ASSERT(m_internalData && (m_internalData->setupState ==
3098                                  (PSS_VERTEX_INPUT_INTERFACE | PSS_PRE_RASTERIZATION_SHADERS | PSS_FRAGMENT_SHADER)));
3099     m_internalData->setupState |= PSS_FRAGMENT_OUTPUT_INTERFACE;
3100     m_internalData->pRenderingAttachmentLocation.ptr = renderingAttachmentLocationInfo.ptr;
3101 
3102     // Unreference variables that are not used in Vulkan SC. No need to put this in ifdef.
3103     DE_UNREF(renderPass);
3104     DE_UNREF(subpass);
3105     DE_UNREF(partPipelineCache);
3106     DE_UNREF(partCreationFeedback);
3107 
3108     void *firstStructInChain = DE_NULL;
3109     addToChain(&firstStructInChain, m_internalData->pFragmentShadingRateState);
3110 
3111 #ifndef CTS_USES_VULKANSC
3112     addToChain(&firstStructInChain, m_internalData->pRenderingState.ptr);
3113 #endif // CTS_USES_VULKANSC
3114 
3115     const auto pColorBlendState = colorBlendState ?
3116                                       colorBlendState :
3117                                       (m_internalData->useDefaultColorBlendState ? &defaultColorBlendState : DE_NULL);
3118     const auto pMultisampleState =
3119         multisampleState ? multisampleState :
3120                            (m_internalData->useDefaultMultisampleState ? &defaultMultisampleState : DE_NULL);
3121 
3122     if (!isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
3123     {
3124         m_internalData->monolithicPipelineCreateInfo.pNext = firstStructInChain;
3125         m_internalData->monolithicPipelineCreateInfo.flags |= m_internalData->pipelineFlags;
3126         m_internalData->monolithicPipelineCreateInfo.pColorBlendState  = pColorBlendState;
3127         m_internalData->monolithicPipelineCreateInfo.pMultisampleState = pMultisampleState;
3128     }
3129 
3130 #ifndef CTS_USES_VULKANSC
3131     // note we could just use else to if statement above but sinc
3132     // this section is cut out for Vulkan SC its cleaner with separate if
3133     if (isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
3134     {
3135         auto libraryCreateInfo =
3136             makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT);
3137         addToChain(&firstStructInChain, &libraryCreateInfo);
3138         addToChain(&firstStructInChain, partCreationFeedback.ptr);
3139         addToChain(&firstStructInChain, m_internalData->pRenderingAttachmentLocation.ptr);
3140         addToChain(&firstStructInChain, m_internalData->pPipelineRobustnessState.ptr);
3141 
3142         VkPipelineDynamicStateCreateInfo pickedDynamicStateInfo = initVulkanStructure();
3143         std::vector<VkDynamicState> states;
3144 
3145         if (m_internalData->pDynamicState)
3146         {
3147             states = getDynamicStates(m_internalData->pDynamicState, m_internalData->setupState);
3148 
3149             pickedDynamicStateInfo.pDynamicStates    = states.data();
3150             pickedDynamicStateInfo.dynamicStateCount = static_cast<uint32_t>(states.size());
3151         }
3152 
3153         VkGraphicsPipelineCreateInfo pipelinePartCreateInfo = initVulkanStructure();
3154         pipelinePartCreateInfo.pNext                        = firstStructInChain;
3155         pipelinePartCreateInfo.flags =
3156             (m_internalData->pipelineFlags | VK_PIPELINE_CREATE_LIBRARY_BIT_KHR) & ~VK_PIPELINE_CREATE_DERIVATIVE_BIT;
3157         pipelinePartCreateInfo.renderPass        = renderPass;
3158         pipelinePartCreateInfo.subpass           = subpass;
3159         pipelinePartCreateInfo.pColorBlendState  = pColorBlendState;
3160         pipelinePartCreateInfo.pMultisampleState = pMultisampleState;
3161         pipelinePartCreateInfo.pDynamicState     = &pickedDynamicStateInfo;
3162 
3163         if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
3164             pipelinePartCreateInfo.flags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
3165 
3166         VkPipelineCreateFlags2CreateInfoKHR pipelineFlags2CreateInfo = initVulkanStructure();
3167         if (m_internalData->pipelineFlags2)
3168         {
3169             pipelineFlags2CreateInfo.flags =
3170                 m_internalData->pipelineFlags2 | translateCreateFlag(pipelinePartCreateInfo.flags);
3171             addToChain(&firstStructInChain, &pipelineFlags2CreateInfo);
3172             pipelinePartCreateInfo.flags = 0u;
3173         }
3174 
3175         m_pipelineParts[3] = makeGraphicsPipeline(m_internalData->vk, m_internalData->device, partPipelineCache,
3176                                                   &pipelinePartCreateInfo);
3177     }
3178 #endif // CTS_USES_VULKANSC
3179 
3180     return *this;
3181 }
3182 
3183 #ifndef CTS_USES_VULKANSC
getNextStages(vk::VkShaderStageFlagBits shaderStage,bool tessellationShaders,bool geometryShaders,bool link)3184 vk::VkShaderStageFlags GraphicsPipelineWrapper::getNextStages(vk::VkShaderStageFlagBits shaderStage,
3185                                                               bool tessellationShaders, bool geometryShaders, bool link)
3186 {
3187     if (link)
3188     {
3189         if (shaderStage == vk::VK_SHADER_STAGE_VERTEX_BIT)
3190         {
3191             if (m_internalData->tessellationControlShader.isSet())
3192                 return vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
3193             if (m_internalData->geometryShader.isSet())
3194                 return vk::VK_SHADER_STAGE_GEOMETRY_BIT;
3195             if (m_internalData->fragmentShader.isSet())
3196                 return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
3197         }
3198         if (shaderStage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
3199             return vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
3200         if (shaderStage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
3201         {
3202             if (m_internalData->geometryShader.isSet())
3203                 return vk::VK_SHADER_STAGE_GEOMETRY_BIT;
3204             if (m_internalData->fragmentShader.isSet())
3205                 return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
3206         }
3207         if (shaderStage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
3208         {
3209             if (m_internalData->fragmentShader.isSet())
3210                 return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
3211         }
3212         if (shaderStage == vk::VK_SHADER_STAGE_TASK_BIT_EXT)
3213         {
3214             if (m_internalData->meshShader.isSet())
3215                 return vk::VK_SHADER_STAGE_MESH_BIT_EXT;
3216             if (m_internalData->fragmentShader.isSet())
3217                 return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
3218         }
3219         if (shaderStage == vk::VK_SHADER_STAGE_MESH_BIT_EXT)
3220         {
3221             if (m_internalData->fragmentShader.isSet())
3222                 return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
3223         }
3224     }
3225     else
3226     {
3227         if (shaderStage == vk::VK_SHADER_STAGE_VERTEX_BIT)
3228         {
3229             VkShaderStageFlags flags = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
3230             if (tessellationShaders)
3231                 flags |= vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
3232             if (geometryShaders)
3233                 flags |= vk::VK_SHADER_STAGE_GEOMETRY_BIT;
3234             return flags;
3235         }
3236         else if (shaderStage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
3237         {
3238             return vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
3239         }
3240         else if (shaderStage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
3241         {
3242             VkShaderStageFlags flags = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
3243             if (geometryShaders)
3244                 flags |= vk::VK_SHADER_STAGE_GEOMETRY_BIT;
3245             return flags;
3246         }
3247         else if (shaderStage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
3248         {
3249             return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
3250         }
3251         else if (shaderStage == vk::VK_SHADER_STAGE_TASK_BIT_EXT)
3252         {
3253             return vk::VK_SHADER_STAGE_MESH_BIT_EXT;
3254         }
3255         else if (shaderStage == vk::VK_SHADER_STAGE_MESH_BIT_EXT)
3256         {
3257             return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
3258         }
3259     }
3260     return 0;
3261 }
3262 
makeShaderCreateInfo(VkShaderStageFlagBits stage,ShaderWrapper & shader,bool link,bool binary,ShaderWrapper & other)3263 vk::VkShaderCreateInfoEXT GraphicsPipelineWrapper::makeShaderCreateInfo(VkShaderStageFlagBits stage,
3264                                                                         ShaderWrapper &shader, bool link, bool binary,
3265                                                                         ShaderWrapper &other)
3266 {
3267     if (binary)
3268         shader.getShaderBinary();
3269 
3270     vk::VkShaderCreateInfoEXT shaderCreateInfo = vk::initVulkanStructure();
3271     shaderCreateInfo.flags =
3272         link ? (vk::VkShaderCreateFlagsEXT)vk::VK_SHADER_CREATE_LINK_STAGE_BIT_EXT : (vk::VkShaderCreateFlagsEXT)0u;
3273     shaderCreateInfo.stage = stage;
3274     shaderCreateInfo.nextStage =
3275         getNextStages(stage, m_internalData->tessellationShaderFeature, m_internalData->geometryShaderFeature, link);
3276     if (binary)
3277     {
3278         shaderCreateInfo.codeType = vk::VK_SHADER_CODE_TYPE_BINARY_EXT;
3279         shaderCreateInfo.codeSize = shader.getShaderBinaryDataSize();
3280         shaderCreateInfo.pCode    = shader.getShaderBinaryData();
3281     }
3282     else
3283     {
3284         shaderCreateInfo.codeType = vk::VK_SHADER_CODE_TYPE_SPIRV_EXT;
3285         shaderCreateInfo.codeSize = shader.getCodeSize();
3286         shaderCreateInfo.pCode    = shader.getBinary();
3287     }
3288     shaderCreateInfo.pName = "main";
3289     if (shader.getPipelineLayout() != DE_NULL)
3290     {
3291         shaderCreateInfo.setLayoutCount         = shader.getPipelineLayout()->getSetLayoutCount();
3292         shaderCreateInfo.pSetLayouts            = shader.getPipelineLayout()->getSetLayouts();
3293         shaderCreateInfo.pushConstantRangeCount = shader.getPipelineLayout()->getPushConstantRangeCount();
3294         shaderCreateInfo.pPushConstantRanges    = shader.getPipelineLayout()->getPushConstantRanges();
3295     }
3296     // Pipeline layouts and push constant ranges must match between shaders that are used together
3297     if (other.isSet() && shaderCreateInfo.setLayoutCount == 0)
3298     {
3299         shaderCreateInfo.setLayoutCount = other.getPipelineLayout()->getSetLayoutCount();
3300         shaderCreateInfo.pSetLayouts    = other.getPipelineLayout()->getSetLayouts();
3301     }
3302     if (other.isSet() && shaderCreateInfo.pushConstantRangeCount == 0)
3303     {
3304         shaderCreateInfo.pushConstantRangeCount = other.getPipelineLayout()->getPushConstantRangeCount();
3305         shaderCreateInfo.pPushConstantRanges    = other.getPipelineLayout()->getPushConstantRanges();
3306     }
3307     shaderCreateInfo.pSpecializationInfo = shader.getSpecializationInfo();
3308     return shaderCreateInfo;
3309 }
3310 
createShaders(bool linked,bool binary)3311 void GraphicsPipelineWrapper::createShaders(bool linked, bool binary)
3312 {
3313     std::vector<vk::VkShaderCreateInfoEXT> createInfos;
3314     if (m_internalData->vertexShader.isSet())
3315         createInfos.push_back(makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, m_internalData->vertexShader, linked,
3316                                                    binary, m_internalData->fragmentShader));
3317     if (m_internalData->tessellationControlShader.isSet())
3318         createInfos.push_back(makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
3319                                                    m_internalData->tessellationControlShader, linked, binary,
3320                                                    m_internalData->fragmentShader));
3321     if (m_internalData->tessellationEvaluationShader.isSet())
3322         createInfos.push_back(makeShaderCreateInfo(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
3323                                                    m_internalData->tessellationEvaluationShader, linked, binary,
3324                                                    m_internalData->fragmentShader));
3325     if (m_internalData->geometryShader.isSet())
3326         createInfos.push_back(makeShaderCreateInfo(vk::VK_SHADER_STAGE_GEOMETRY_BIT, m_internalData->geometryShader,
3327                                                    linked, binary, m_internalData->fragmentShader));
3328     if (m_internalData->fragmentShader.isSet())
3329         createInfos.push_back(makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, m_internalData->fragmentShader,
3330                                                    linked, binary, m_internalData->vertexShader));
3331     if (m_internalData->taskShader.isSet())
3332         createInfos.push_back(makeShaderCreateInfo(vk::VK_SHADER_STAGE_TASK_BIT_EXT, m_internalData->taskShader, linked,
3333                                                    binary, m_internalData->fragmentShader));
3334     if (m_internalData->meshShader.isSet())
3335     {
3336         createInfos.push_back(makeShaderCreateInfo(vk::VK_SHADER_STAGE_MESH_BIT_EXT, m_internalData->meshShader, linked,
3337                                                    binary, m_internalData->fragmentShader));
3338         if (!m_internalData->taskShader.isSet())
3339             createInfos.back().flags |= vk::VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT;
3340     }
3341 
3342     std::vector<VkShaderEXT> shaders(createInfos.size());
3343     m_internalData->vk.createShadersEXT(m_internalData->device, (uint32_t)createInfos.size(), createInfos.data(),
3344                                         DE_NULL, shaders.data());
3345     uint32_t shaderIndex = 0;
3346     if (m_internalData->vertexShader.isSet())
3347         m_internalData->vertexShader.setShader(
3348             Move<VkShaderEXT>(check<VkShaderEXT>(shaders[shaderIndex++]),
3349                               Deleter<VkShaderEXT>(m_internalData->vk, m_internalData->device, DE_NULL)));
3350     if (m_internalData->tessellationControlShader.isSet())
3351         m_internalData->tessellationControlShader.setShader(
3352             Move<VkShaderEXT>(check<VkShaderEXT>(shaders[shaderIndex++]),
3353                               Deleter<VkShaderEXT>(m_internalData->vk, m_internalData->device, DE_NULL)));
3354     if (m_internalData->tessellationEvaluationShader.isSet())
3355         m_internalData->tessellationEvaluationShader.setShader(
3356             Move<VkShaderEXT>(check<VkShaderEXT>(shaders[shaderIndex++]),
3357                               Deleter<VkShaderEXT>(m_internalData->vk, m_internalData->device, DE_NULL)));
3358     if (m_internalData->geometryShader.isSet())
3359         m_internalData->geometryShader.setShader(
3360             Move<VkShaderEXT>(check<VkShaderEXT>(shaders[shaderIndex++]),
3361                               Deleter<VkShaderEXT>(m_internalData->vk, m_internalData->device, DE_NULL)));
3362     if (m_internalData->fragmentShader.isSet())
3363         m_internalData->fragmentShader.setShader(
3364             Move<VkShaderEXT>(check<VkShaderEXT>(shaders[shaderIndex++]),
3365                               Deleter<VkShaderEXT>(m_internalData->vk, m_internalData->device, DE_NULL)));
3366     if (m_internalData->taskShader.isSet())
3367         m_internalData->taskShader.setShader(
3368             Move<VkShaderEXT>(check<VkShaderEXT>(shaders[shaderIndex++]),
3369                               Deleter<VkShaderEXT>(m_internalData->vk, m_internalData->device, DE_NULL)));
3370     if (m_internalData->meshShader.isSet())
3371         m_internalData->meshShader.setShader(
3372             Move<VkShaderEXT>(check<VkShaderEXT>(shaders[shaderIndex++]),
3373                               Deleter<VkShaderEXT>(m_internalData->vk, m_internalData->device, DE_NULL)));
3374 }
3375 #endif
3376 
buildPipeline(const VkPipelineCache pipelineCache,const VkPipeline basePipelineHandle,const int32_t basePipelineIndex,PipelineCreationFeedbackCreateInfoWrapper creationFeedback)3377 void GraphicsPipelineWrapper::buildPipeline(const VkPipelineCache pipelineCache, const VkPipeline basePipelineHandle,
3378                                             const int32_t basePipelineIndex,
3379                                             PipelineCreationFeedbackCreateInfoWrapper creationFeedback)
3380 {
3381     // make sure we are not trying to build pipeline second time
3382     DE_ASSERT(m_pipelineFinal.get() == DE_NULL);
3383 
3384     // make sure all states were set
3385     DE_ASSERT(m_internalData &&
3386               (m_internalData->setupState == (PSS_VERTEX_INPUT_INTERFACE | PSS_PRE_RASTERIZATION_SHADERS |
3387                                               PSS_FRAGMENT_SHADER | PSS_FRAGMENT_OUTPUT_INTERFACE)));
3388 
3389     // Unreference variables that are not used in Vulkan SC. No need to put this in ifdef.
3390     DE_UNREF(creationFeedback);
3391 
3392     VkGraphicsPipelineCreateInfo *pointerToCreateInfo = &m_internalData->monolithicPipelineCreateInfo;
3393 
3394     if (isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
3395     {
3396 #ifndef CTS_USES_VULKANSC
3397         // Dynamic states that don't require additional extensions
3398         std::vector<vk::VkDynamicState> dynamicStates = {
3399             vk::VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT,
3400             vk::VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT,
3401             vk::VK_DYNAMIC_STATE_LINE_WIDTH,
3402             vk::VK_DYNAMIC_STATE_DEPTH_BIAS,
3403             vk::VK_DYNAMIC_STATE_BLEND_CONSTANTS,
3404             vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS,
3405             vk::VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
3406             vk::VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
3407             vk::VK_DYNAMIC_STATE_STENCIL_REFERENCE,
3408             vk::VK_DYNAMIC_STATE_CULL_MODE_EXT,
3409             vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT,
3410             vk::VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,
3411             vk::VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,
3412             vk::VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
3413             vk::VK_DYNAMIC_STATE_FRONT_FACE_EXT,
3414             vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT,
3415             vk::VK_DYNAMIC_STATE_STENCIL_OP_EXT,
3416             vk::VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT,
3417             vk::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT,
3418             vk::VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT,
3419             vk::VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT,
3420             vk::VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT,
3421             vk::VK_DYNAMIC_STATE_LOGIC_OP_EXT,
3422             vk::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT,
3423             vk::VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT,
3424             vk::VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT,
3425             vk::VK_DYNAMIC_STATE_POLYGON_MODE_EXT,
3426             vk::VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT,
3427             vk::VK_DYNAMIC_STATE_SAMPLE_MASK_EXT,
3428             vk::VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT,
3429             vk::VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT,
3430             vk::VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT,
3431             vk::VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT,
3432             vk::VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT,
3433             vk::VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT,
3434             vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT,
3435         };
3436 
3437         vk::VkPhysicalDeviceMeshShaderFeaturesEXT meshShaderFeatures = initVulkanStructure();
3438         vk::VkPhysicalDeviceFeatures2 features                       = initVulkanStructure(&meshShaderFeatures);
3439         m_internalData->vki.getPhysicalDeviceFeatures2(m_internalData->physicalDevice, &features);
3440 
3441         m_internalData->tessellationShaderFeature = features.features.tessellationShader;
3442         m_internalData->geometryShaderFeature     = features.features.geometryShader;
3443         m_internalData->taskShaderFeature         = meshShaderFeatures.taskShader;
3444         m_internalData->meshShaderFeature         = meshShaderFeatures.meshShader;
3445 
3446         DE_ASSERT(m_internalData->extensionEnabled("VK_EXT_shader_object"));
3447 
3448         // Add dynamic states that are required for each enabled extension
3449         if (m_internalData->extensionEnabled("VK_EXT_transform_feedback"))
3450             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT);
3451         if (m_internalData->extensionEnabled("VK_EXT_blend_operation_advanced"))
3452             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT);
3453         if (m_internalData->extensionEnabled("VK_EXT_conservative_rasterization"))
3454             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT);
3455         if (m_internalData->extensionEnabled("VK_NV_framebuffer_mixed_samples"))
3456             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV);
3457         if (m_internalData->extensionEnabled("VK_NV_framebuffer_mixed_samples"))
3458             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV);
3459         if (m_internalData->extensionEnabled("VK_NV_framebuffer_mixed_samples"))
3460             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV);
3461         if (m_internalData->extensionEnabled("VK_NV_coverage_reduction_mode"))
3462             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV);
3463         if (m_internalData->extensionEnabled("VK_NV_fragment_coverage_to_color"))
3464             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV);
3465         if (m_internalData->extensionEnabled("VK_NV_fragment_coverage_to_color"))
3466             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV);
3467         if (m_internalData->extensionEnabled("VK_EXT_depth_clip_enable"))
3468             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT);
3469         if (m_internalData->extensionEnabled("VK_EXT_depth_clip_control"))
3470             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT);
3471         if (m_internalData->extensionEnabled("VK_EXT_color_write_enable"))
3472             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT);
3473         if (m_internalData->extensionEnabled("VK_EXT_conservative_rasterization"))
3474             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT);
3475         if (m_internalData->extensionEnabled("VK_KHR_line_rasterization") ||
3476             m_internalData->extensionEnabled("VK_EXT_line_rasterization"))
3477             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT);
3478         if (m_internalData->extensionEnabled("VK_KHR_line_rasterization") ||
3479             m_internalData->extensionEnabled("VK_EXT_line_rasterization"))
3480             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT);
3481         if (m_internalData->extensionEnabled("VK_KHR_line_rasterization") ||
3482             m_internalData->extensionEnabled("VK_EXT_line_rasterization"))
3483             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_KHR);
3484         if (m_internalData->extensionEnabled("VK_EXT_provoking_vertex"))
3485             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT);
3486         if (m_internalData->extensionEnabled("VK_KHR_fragment_shading_rate"))
3487             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR);
3488         if (m_internalData->extensionEnabled("VK_NV_representative_fragment_test"))
3489             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV);
3490         if (m_internalData->extensionEnabled("VK_EXT_sample_locations"))
3491             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT);
3492         if (m_internalData->extensionEnabled("VK_EXT_sample_locations"))
3493             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
3494         // Not working with VK_KHR_fragment_shading_rate
3495         /*if (m_internalData->extensionEnabled("VK_NV_shading_rate_image"))
3496             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV);
3497         if (m_internalData->extensionEnabled("VK_NV_shading_rate_image"))
3498             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV);
3499         if (m_internalData->extensionEnabled("VK_NV_shading_rate_image"))
3500             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV);*/
3501         if (m_internalData->extensionEnabled("VK_NV_viewport_swizzle"))
3502             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV);
3503         if (m_internalData->extensionEnabled("VK_NV_clip_space_w_scaling"))
3504             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV);
3505         if (m_internalData->extensionEnabled("VK_NV_clip_space_w_scaling"))
3506             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV);
3507         if (m_internalData->extensionEnabled("VK_NV_scissor_exclusive"))
3508             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_ENABLE_NV);
3509         if (m_internalData->extensionEnabled("VK_NV_scissor_exclusive"))
3510             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV);
3511         if (m_internalData->extensionEnabled("VK_EXT_discard_rectangles"))
3512             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT);
3513         if (m_internalData->extensionEnabled("VK_EXT_discard_rectangles"))
3514             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT);
3515         if (m_internalData->extensionEnabled("VK_EXT_discard_rectangles"))
3516             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT);
3517         if (m_internalData->extensionEnabled("VK_EXT_attachment_feedback_loop_dynamic_state"))
3518             dynamicStates.push_back(vk::VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT);
3519 
3520         // Remove dynamic states that were already set as dynamic for the pipeline
3521         // These dynamic state will already be set in the tests
3522         bool depthClampEnableDynamic = false;
3523         if (pointerToCreateInfo->pDynamicState)
3524         {
3525             for (uint32_t i = 0; i < pointerToCreateInfo->pDynamicState->dynamicStateCount; ++i)
3526             {
3527                 if (pointerToCreateInfo->pDynamicState->pDynamicStates[i] == vk::VK_DYNAMIC_STATE_VIEWPORT)
3528                     dynamicStates.erase(std::remove(dynamicStates.begin(), dynamicStates.end(),
3529                                                     vk::VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT),
3530                                         dynamicStates.end());
3531                 else if (pointerToCreateInfo->pDynamicState->pDynamicStates[i] == vk::VK_DYNAMIC_STATE_SCISSOR)
3532                     dynamicStates.erase(std::remove(dynamicStates.begin(), dynamicStates.end(),
3533                                                     vk::VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT),
3534                                         dynamicStates.end());
3535                 else if (pointerToCreateInfo->pDynamicState->pDynamicStates[i] ==
3536                          vk::VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT)
3537                 {
3538                     dynamicStates.erase(std::remove(dynamicStates.begin(), dynamicStates.end(),
3539                                                     vk::VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT),
3540                                         dynamicStates.end());
3541                     dynamicStates.erase(std::remove(dynamicStates.begin(), dynamicStates.end(),
3542                                                     vk::VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT),
3543                                         dynamicStates.end());
3544                 }
3545                 else if (pointerToCreateInfo->pDynamicState->pDynamicStates[i] == vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT)
3546                 {
3547                     dynamicStates.erase(
3548                         std::remove(dynamicStates.begin(), dynamicStates.end(), vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT),
3549                         dynamicStates.end());
3550                     dynamicStates.erase(std::remove(dynamicStates.begin(), dynamicStates.end(),
3551                                                     vk::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT),
3552                                         dynamicStates.end());
3553                 }
3554                 else
3555                     dynamicStates.erase(std::remove(dynamicStates.begin(), dynamicStates.end(),
3556                                                     pointerToCreateInfo->pDynamicState->pDynamicStates[i]),
3557                                         dynamicStates.end());
3558 
3559                 if (pointerToCreateInfo->pDynamicState->pDynamicStates[i] ==
3560                     vk::VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT)
3561                     depthClampEnableDynamic = true;
3562             }
3563         }
3564 
3565         m_internalData->shaderObjectDynamicStates = dynamicStates;
3566 
3567         // Save state needed for setting shader object dynamic state
3568         auto state = &m_internalData->pipelineCreateState;
3569         if (pointerToCreateInfo->pViewportState)
3570         {
3571             if (pointerToCreateInfo->pViewportState->pViewports)
3572             {
3573                 state->viewports.resize(pointerToCreateInfo->pViewportState->viewportCount);
3574                 for (uint32_t i = 0; i < pointerToCreateInfo->pViewportState->viewportCount; ++i)
3575                     state->viewports[i] = pointerToCreateInfo->pViewportState->pViewports[i];
3576             }
3577 
3578             if (pointerToCreateInfo->pViewportState->pScissors)
3579             {
3580                 state->scissors.resize(pointerToCreateInfo->pViewportState->scissorCount);
3581                 for (uint32_t i = 0; i < pointerToCreateInfo->pViewportState->scissorCount; ++i)
3582                     state->scissors[i] = pointerToCreateInfo->pViewportState->pScissors[i];
3583             }
3584 
3585             const auto depthClipControl = findStructure<VkPipelineViewportDepthClipControlCreateInfoEXT>(
3586                 pointerToCreateInfo->pViewportState->pNext);
3587             if (depthClipControl)
3588                 state->negativeOneToOne = depthClipControl->negativeOneToOne;
3589             const auto viewportShadingRate = findStructure<VkPipelineViewportShadingRateImageStateCreateInfoNV>(
3590                 pointerToCreateInfo->pViewportState->pNext);
3591             if (viewportShadingRate)
3592             {
3593                 state->shadingRateImageEnable  = viewportShadingRate->shadingRateImageEnable;
3594                 state->shadingRatePaletteCount = viewportShadingRate->viewportCount;
3595                 state->shadingRatePalettes.resize(viewportShadingRate->viewportCount);
3596                 state->shadingRatePaletteEntries.resize(viewportShadingRate->viewportCount);
3597                 for (uint32_t i = 0; i < viewportShadingRate->viewportCount; ++i)
3598                 {
3599                     state->shadingRatePalettes[i] = viewportShadingRate->pShadingRatePalettes[i];
3600                     state->shadingRatePaletteEntries[i].resize(
3601                         viewportShadingRate->pShadingRatePalettes[i].shadingRatePaletteEntryCount);
3602                     for (uint32_t j = 0; j < viewportShadingRate->pShadingRatePalettes[i].shadingRatePaletteEntryCount;
3603                          ++j)
3604                         state->shadingRatePaletteEntries[i][j] =
3605                             viewportShadingRate->pShadingRatePalettes[i].pShadingRatePaletteEntries[j];
3606                     state->shadingRatePalettes[i].pShadingRatePaletteEntries =
3607                         state->shadingRatePaletteEntries[i].data();
3608                 }
3609             }
3610             const auto viewportSwizzle =
3611                 findStructure<VkPipelineViewportSwizzleStateCreateInfoNV>(pointerToCreateInfo->pViewportState->pNext);
3612             if (viewportSwizzle)
3613             {
3614                 state->viewportSwizzles.resize(viewportSwizzle->viewportCount);
3615                 for (uint32_t i = 0; i < viewportSwizzle->viewportCount; ++i)
3616                     state->viewportSwizzles[i] = viewportSwizzle->pViewportSwizzles[i];
3617             }
3618             const auto viewportWScaling =
3619                 findStructure<VkPipelineViewportWScalingStateCreateInfoNV>(pointerToCreateInfo->pViewportState->pNext);
3620             if (viewportWScaling)
3621             {
3622                 state->viewportWScalingEnable = viewportWScaling->viewportWScalingEnable;
3623                 state->viewportWScalingCount  = viewportWScaling->viewportCount;
3624                 state->viewportWScalings.resize(viewportWScaling->viewportCount);
3625                 for (uint32_t i = 0; i < viewportWScaling->viewportCount; ++i)
3626                     state->viewportWScalings[i] = viewportWScaling->pViewportWScalings[i];
3627             }
3628             const auto coarseSampleOrder = findStructure<VkPipelineViewportCoarseSampleOrderStateCreateInfoNV>(
3629                 pointerToCreateInfo->pViewportState->pNext);
3630             if (coarseSampleOrder)
3631             {
3632                 state->coarseSampleOrderType        = coarseSampleOrder->sampleOrderType;
3633                 state->coarseCustomSampleOrderCount = coarseSampleOrder->customSampleOrderCount;
3634                 state->coarseCustomSampleOrders.resize(coarseSampleOrder->customSampleOrderCount);
3635                 state->coarseSampleLocations.resize(coarseSampleOrder->customSampleOrderCount);
3636                 for (uint32_t i = 0; i < coarseSampleOrder->customSampleOrderCount; ++i)
3637                 {
3638                     state->coarseCustomSampleOrders[i] = coarseSampleOrder->pCustomSampleOrders[i];
3639                     state->coarseSampleLocations[i].resize(coarseSampleOrder->pCustomSampleOrders[i].sampleCount);
3640                     for (uint32_t j = 0; j < coarseSampleOrder->pCustomSampleOrders[i].sampleCount; ++j)
3641                         state->coarseSampleLocations[i][j] =
3642                             coarseSampleOrder->pCustomSampleOrders[i].pSampleLocations[j];
3643                     state->coarseCustomSampleOrders[i].pSampleLocations = state->coarseSampleLocations[i].data();
3644                 }
3645             }
3646         }
3647 
3648         if (pointerToCreateInfo->pRasterizationState)
3649         {
3650             state->lineWidth               = pointerToCreateInfo->pRasterizationState->lineWidth;
3651             state->depthBiasConstantFactor = pointerToCreateInfo->pRasterizationState->depthBiasConstantFactor;
3652             state->depthBiasClamp          = pointerToCreateInfo->pRasterizationState->depthBiasClamp;
3653             state->depthBiasSlopeFactor    = pointerToCreateInfo->pRasterizationState->depthBiasSlopeFactor;
3654             state->cullMode                = pointerToCreateInfo->pRasterizationState->cullMode;
3655             state->frontFace               = pointerToCreateInfo->pRasterizationState->frontFace;
3656             state->depthBiasEnable         = pointerToCreateInfo->pRasterizationState->depthBiasEnable;
3657             state->rasterizerDiscardEnable = pointerToCreateInfo->pRasterizationState->rasterizerDiscardEnable;
3658             const auto conservative        = findStructure<VkPipelineRasterizationConservativeStateCreateInfoEXT>(
3659                 pointerToCreateInfo->pRasterizationState->pNext);
3660             if (conservative)
3661             {
3662                 state->conservativeRasterizationMode    = conservative->conservativeRasterizationMode;
3663                 state->extraPrimitiveOverestimationSize = conservative->extraPrimitiveOverestimationSize;
3664             }
3665             state->depthClampEnable = pointerToCreateInfo->pRasterizationState->depthClampEnable;
3666             const auto depthClip    = findStructure<VkPipelineRasterizationDepthClipStateCreateInfoEXT>(
3667                 pointerToCreateInfo->pRasterizationState->pNext);
3668             if (depthClip)
3669                 state->depthClipEnable = depthClip->depthClipEnable;
3670             else
3671                 state->depthClipEnable =
3672                     !pointerToCreateInfo->pRasterizationState->depthClampEnable && !depthClampEnableDynamic;
3673 
3674             const auto rasterizationLine = findStructure<VkPipelineRasterizationLineStateCreateInfoEXT>(
3675                 pointerToCreateInfo->pRasterizationState->pNext);
3676             if (rasterizationLine)
3677             {
3678                 state->lineRasterizationMode = rasterizationLine->lineRasterizationMode;
3679                 state->stippledLineEnable    = rasterizationLine->stippledLineEnable;
3680                 state->lineStippleFactor     = rasterizationLine->lineStippleFactor;
3681                 state->lineStipplePattern    = rasterizationLine->lineStipplePattern;
3682             }
3683             const auto rasterizationStream = findStructure<VkPipelineRasterizationStateStreamCreateInfoEXT>(
3684                 pointerToCreateInfo->pRasterizationState->pNext);
3685             if (rasterizationStream)
3686                 state->rasterizationStream = rasterizationStream->rasterizationStream;
3687             state->polygonMode         = pointerToCreateInfo->pRasterizationState->polygonMode;
3688             const auto provokingVertex = findStructure<VkPipelineRasterizationProvokingVertexStateCreateInfoEXT>(
3689                 pointerToCreateInfo->pRasterizationState->pNext);
3690             if (provokingVertex)
3691                 state->provokingVertexMode = provokingVertex->provokingVertexMode;
3692             const auto depthBiasRepresentationInfo =
3693                 findStructure<VkDepthBiasRepresentationInfoEXT>(pointerToCreateInfo->pRasterizationState->pNext);
3694             if (depthBiasRepresentationInfo)
3695             {
3696                 state->depthBiasRepresentation = depthBiasRepresentationInfo->depthBiasRepresentation;
3697                 state->depthBiasExact          = depthBiasRepresentationInfo->depthBiasExact;
3698             }
3699         }
3700         if (pointerToCreateInfo->pColorBlendState)
3701         {
3702             memcpy(&state->blendConstants, pointerToCreateInfo->pColorBlendState->blendConstants, sizeof(float) * 4);
3703             state->logicOp                = pointerToCreateInfo->pColorBlendState->logicOp;
3704             const auto blendAdvancedState = findStructure<VkPipelineColorBlendAdvancedStateCreateInfoEXT>(
3705                 pointerToCreateInfo->pColorBlendState->pNext);
3706             if (blendAdvancedState)
3707             {
3708                 state->colorBlendAdvanced.resize(pointerToCreateInfo->pColorBlendState->attachmentCount);
3709                 for (uint32_t i = 0; i < pointerToCreateInfo->pColorBlendState->attachmentCount; ++i)
3710                 {
3711                     if (pointerToCreateInfo->pColorBlendState->pAttachments)
3712                         state->colorBlendAdvanced[i].advancedBlendOp =
3713                             pointerToCreateInfo->pColorBlendState->pAttachments[i].colorBlendOp;
3714                     state->colorBlendAdvanced[i].srcPremultiplied = blendAdvancedState->srcPremultiplied;
3715                     state->colorBlendAdvanced[i].dstPremultiplied = blendAdvancedState->dstPremultiplied;
3716                     state->colorBlendAdvanced[i].blendOverlap     = blendAdvancedState->blendOverlap;
3717                     state->colorBlendAdvanced[i].clampResults     = VK_FALSE;
3718                 }
3719             }
3720             state->colorBlendEnables.resize(pointerToCreateInfo->pColorBlendState->attachmentCount);
3721             state->blendEquations.resize(pointerToCreateInfo->pColorBlendState->attachmentCount);
3722             state->colorWriteMasks.resize(pointerToCreateInfo->pColorBlendState->attachmentCount);
3723             for (uint32_t i = 0; i < (uint32_t)pointerToCreateInfo->pColorBlendState->attachmentCount; ++i)
3724             {
3725                 if (pointerToCreateInfo->pColorBlendState->pAttachments)
3726                 {
3727                     state->colorBlendEnables[i] = pointerToCreateInfo->pColorBlendState->pAttachments[i].blendEnable;
3728                     state->blendEquations[i].srcColorBlendFactor =
3729                         pointerToCreateInfo->pColorBlendState->pAttachments[i].srcColorBlendFactor;
3730                     state->blendEquations[i].dstColorBlendFactor =
3731                         pointerToCreateInfo->pColorBlendState->pAttachments[i].dstColorBlendFactor;
3732                     state->blendEquations[i].colorBlendOp =
3733                         pointerToCreateInfo->pColorBlendState->pAttachments[i].colorBlendOp;
3734                     state->blendEquations[i].srcAlphaBlendFactor =
3735                         pointerToCreateInfo->pColorBlendState->pAttachments[i].srcAlphaBlendFactor;
3736                     state->blendEquations[i].dstAlphaBlendFactor =
3737                         pointerToCreateInfo->pColorBlendState->pAttachments[i].dstAlphaBlendFactor;
3738                     state->blendEquations[i].alphaBlendOp =
3739                         pointerToCreateInfo->pColorBlendState->pAttachments[i].alphaBlendOp;
3740                     state->colorWriteMasks[i] = pointerToCreateInfo->pColorBlendState->pAttachments[i].colorWriteMask;
3741                 }
3742 
3743                 // colorBlendOp and alphaBlendOp must not be advanced blend operations and they will be set with colorBlendAdvanced
3744                 if (blendAdvancedState)
3745                 {
3746                     state->blendEquations[i].colorBlendOp = vk::VK_BLEND_OP_ADD;
3747                     state->blendEquations[i].alphaBlendOp = vk::VK_BLEND_OP_ADD;
3748                 }
3749             }
3750             state->logicOpEnable = pointerToCreateInfo->pColorBlendState->logicOpEnable;
3751             const auto colorWrite =
3752                 findStructure<VkPipelineColorWriteCreateInfoEXT>(pointerToCreateInfo->pColorBlendState->pNext);
3753             if (colorWrite)
3754             {
3755                 state->colorWriteEnableAttachmentCount = colorWrite->attachmentCount;
3756                 state->colorWriteEnables.resize(colorWrite->attachmentCount);
3757                 for (uint32_t i = 0; i < colorWrite->attachmentCount; ++i)
3758                     state->colorWriteEnables[i] = colorWrite->pColorWriteEnables[i];
3759             }
3760         }
3761         if (pointerToCreateInfo->pDepthStencilState)
3762         {
3763             state->minDepthBounds        = pointerToCreateInfo->pDepthStencilState->minDepthBounds;
3764             state->maxDepthBounds        = pointerToCreateInfo->pDepthStencilState->maxDepthBounds;
3765             state->stencilFront          = pointerToCreateInfo->pDepthStencilState->front;
3766             state->stencilBack           = pointerToCreateInfo->pDepthStencilState->back;
3767             state->depthBoundsTestEnable = pointerToCreateInfo->pDepthStencilState->depthBoundsTestEnable;
3768             state->depthCompareOp        = pointerToCreateInfo->pDepthStencilState->depthCompareOp;
3769             state->depthTestEnable       = pointerToCreateInfo->pDepthStencilState->depthTestEnable;
3770             state->depthWriteEnable      = pointerToCreateInfo->pDepthStencilState->depthWriteEnable;
3771             state->stencilTestEnable     = pointerToCreateInfo->pDepthStencilState->stencilTestEnable;
3772         }
3773         if (pointerToCreateInfo->pInputAssemblyState)
3774         {
3775             state->topology               = pointerToCreateInfo->pInputAssemblyState->topology;
3776             state->primitiveRestartEnable = pointerToCreateInfo->pInputAssemblyState->primitiveRestartEnable;
3777         }
3778         if (pointerToCreateInfo->pVertexInputState)
3779         {
3780             state->attributes.resize(pointerToCreateInfo->pVertexInputState->vertexAttributeDescriptionCount);
3781             state->bindings.resize(pointerToCreateInfo->pVertexInputState->vertexBindingDescriptionCount);
3782             for (uint32_t i = 0; i < pointerToCreateInfo->pVertexInputState->vertexAttributeDescriptionCount; ++i)
3783             {
3784                 state->attributes[i] = initVulkanStructure();
3785                 state->attributes[i].location =
3786                     pointerToCreateInfo->pVertexInputState->pVertexAttributeDescriptions[i].location;
3787                 state->attributes[i].binding =
3788                     pointerToCreateInfo->pVertexInputState->pVertexAttributeDescriptions[i].binding;
3789                 state->attributes[i].format =
3790                     pointerToCreateInfo->pVertexInputState->pVertexAttributeDescriptions[i].format;
3791                 state->attributes[i].offset =
3792                     pointerToCreateInfo->pVertexInputState->pVertexAttributeDescriptions[i].offset;
3793             }
3794 
3795             const auto divisorInfo = findStructure<VkPipelineVertexInputDivisorStateCreateInfoEXT>(
3796                 pointerToCreateInfo->pVertexInputState->pNext);
3797 
3798             for (uint32_t i = 0; i < pointerToCreateInfo->pVertexInputState->vertexBindingDescriptionCount; ++i)
3799             {
3800                 state->bindings[i] = initVulkanStructure();
3801                 state->bindings[i].binding =
3802                     pointerToCreateInfo->pVertexInputState->pVertexBindingDescriptions[i].binding;
3803                 state->bindings[i].stride =
3804                     pointerToCreateInfo->pVertexInputState->pVertexBindingDescriptions[i].stride;
3805                 state->bindings[i].inputRate =
3806                     pointerToCreateInfo->pVertexInputState->pVertexBindingDescriptions[i].inputRate;
3807                 state->bindings[i].divisor = 1;
3808                 if (divisorInfo)
3809                 {
3810                     for (uint32_t j = 0; j < divisorInfo->vertexBindingDivisorCount; ++j)
3811                     {
3812                         if (state->bindings[i].binding == divisorInfo->pVertexBindingDivisors[j].binding)
3813                         {
3814                             state->bindings[i].divisor = divisorInfo->pVertexBindingDivisors[i].divisor;
3815                         }
3816                     }
3817                 }
3818             }
3819         }
3820         if (pointerToCreateInfo->pTessellationState)
3821         {
3822             state->patchControlPoints           = pointerToCreateInfo->pTessellationState->patchControlPoints;
3823             const auto tessellationDomainOrigin = findStructure<VkPipelineTessellationDomainOriginStateCreateInfo>(
3824                 pointerToCreateInfo->pTessellationState->pNext);
3825             if (tessellationDomainOrigin)
3826                 state->domainOrigin = tessellationDomainOrigin->domainOrigin;
3827         }
3828         if (pointerToCreateInfo->pMultisampleState)
3829         {
3830             state->alphaToCoverageEnable  = pointerToCreateInfo->pMultisampleState->alphaToCoverageEnable;
3831             state->alphaToOneEnable       = pointerToCreateInfo->pMultisampleState->alphaToOneEnable;
3832             const auto coverageModulation = findStructure<VkPipelineCoverageModulationStateCreateInfoNV>(
3833                 pointerToCreateInfo->pMultisampleState->pNext);
3834             if (coverageModulation)
3835             {
3836                 state->coverageModulationMode        = coverageModulation->coverageModulationMode;
3837                 state->coverageModulationTableEnable = coverageModulation->coverageModulationTableEnable;
3838                 state->coverageModulationTable.resize(coverageModulation->coverageModulationTableCount);
3839                 for (uint32_t i = 0; i < (uint32_t)coverageModulation->coverageModulationTableCount; ++i)
3840                     state->coverageModulationTable[i] = coverageModulation->pCoverageModulationTable[i];
3841             }
3842             const auto coverageReduction = findStructure<VkPipelineCoverageReductionStateCreateInfoNV>(
3843                 pointerToCreateInfo->pMultisampleState->pNext);
3844             if (coverageReduction)
3845                 state->coverageReductionMode = coverageReduction->coverageReductionMode;
3846             const auto coverageToColor = findStructure<VkPipelineCoverageToColorStateCreateInfoNV>(
3847                 pointerToCreateInfo->pMultisampleState->pNext);
3848             if (coverageToColor)
3849             {
3850                 state->coverageToColorEnable   = coverageToColor->coverageToColorEnable;
3851                 state->coverageToColorLocation = coverageToColor->coverageToColorLocation;
3852             }
3853             state->rasterizationSamples = pointerToCreateInfo->pMultisampleState->rasterizationSamples;
3854             const auto sampleLocations  = findStructure<VkPipelineSampleLocationsStateCreateInfoEXT>(
3855                 pointerToCreateInfo->pMultisampleState->pNext);
3856             if (sampleLocations)
3857             {
3858                 state->sampleLocationsEnable = sampleLocations->sampleLocationsEnable;
3859                 state->sampleLocationsInfo   = sampleLocations->sampleLocationsInfo;
3860                 state->pSampleLocations.resize(sampleLocations->sampleLocationsInfo.sampleLocationsCount);
3861                 for (uint32_t i = 0; i < sampleLocations->sampleLocationsInfo.sampleLocationsCount; ++i)
3862                     state->pSampleLocations[i] = sampleLocations->sampleLocationsInfo.pSampleLocations[i];
3863                 state->sampleLocationsInfo.pSampleLocations = state->pSampleLocations.data();
3864             }
3865             state->rasterizationSamples = pointerToCreateInfo->pMultisampleState->rasterizationSamples;
3866             uint32_t count =
3867                 (pointerToCreateInfo->pMultisampleState->rasterizationSamples > vk::VK_SAMPLE_COUNT_32_BIT) ? 2 : 1;
3868             state->sampleMasks.resize(count, 0);
3869             for (uint32_t i = 0; i < count; ++i)
3870                 if (pointerToCreateInfo->pMultisampleState->pSampleMask)
3871                     state->sampleMasks[i] = pointerToCreateInfo->pMultisampleState->pSampleMask[i];
3872                 else
3873                     state->sampleMasks[i] =
3874                         0xFF; // If pSampleMask is NULL, it is treated as if the mask has all bits set to 1
3875         }
3876         const auto representativeFragment =
3877             findStructure<VkPipelineRepresentativeFragmentTestStateCreateInfoNV>(pointerToCreateInfo->pNext);
3878         if (representativeFragment)
3879         {
3880             state->representativeFragmentTestEnable = representativeFragment->representativeFragmentTestEnable;
3881         }
3882         const auto fragmentShadingRate =
3883             findStructure<VkPipelineFragmentShadingRateStateCreateInfoKHR>(pointerToCreateInfo->pNext);
3884         if (fragmentShadingRate)
3885         {
3886             state->fragmentShadingRateSize = fragmentShadingRate->fragmentSize;
3887             state->combinerOps[0]          = fragmentShadingRate->combinerOps[0];
3888             state->combinerOps[1]          = fragmentShadingRate->combinerOps[1];
3889         }
3890         const auto exclusiveScissor =
3891             findStructure<VkPipelineViewportExclusiveScissorStateCreateInfoNV>(pointerToCreateInfo->pNext);
3892         if (exclusiveScissor)
3893         {
3894             state->exclusiveScissorCount = exclusiveScissor->exclusiveScissorCount;
3895             state->exclussiveScissors.resize(exclusiveScissor->exclusiveScissorCount);
3896             for (uint32_t i = 0; i < exclusiveScissor->exclusiveScissorCount; ++i)
3897                 state->exclussiveScissors[i] = exclusiveScissor->pExclusiveScissors[i];
3898         }
3899         const auto discardRectangle =
3900             findStructure<VkPipelineDiscardRectangleStateCreateInfoEXT>(pointerToCreateInfo->pNext);
3901         if (discardRectangle)
3902         {
3903             state->discardRectangleEnable = discardRectangle->discardRectangleCount > 0;
3904             state->discardRectangles.resize(discardRectangle->discardRectangleCount);
3905             for (uint32_t i = 0; i < discardRectangle->discardRectangleCount; ++i)
3906                 state->discardRectangles[i] = discardRectangle->pDiscardRectangles[i];
3907             state->discardRectangleMode = discardRectangle->discardRectangleMode;
3908         }
3909         if (pointerToCreateInfo->flags & VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT)
3910             state->attachmentFeedbackLoopEnable |= VK_IMAGE_ASPECT_COLOR_BIT;
3911         if (pointerToCreateInfo->flags & VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT)
3912             state->attachmentFeedbackLoopEnable |= VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
3913 
3914         bool linked =
3915             m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_LINKED_SPIRV ||
3916             m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_LINKED_BINARY;
3917         bool binary =
3918             m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_UNLINKED_BINARY ||
3919             m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_LINKED_BINARY;
3920         createShaders(linked, false);
3921         if (binary)
3922         {
3923             createShaders(linked, true);
3924         }
3925 #endif
3926     }
3927     else
3928     {
3929 #ifndef CTS_USES_VULKANSC
3930         VkGraphicsPipelineCreateInfo linkedCreateInfo = initVulkanStructure();
3931         std::vector<VkPipeline> rawPipelines;
3932         VkPipelineLibraryCreateInfoKHR linkingInfo{
3933             VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR, // VkStructureType sType;
3934             creationFeedback.ptr,                               // const void* pNext;
3935             0u,                                                 // uint32_t libraryCount;
3936             nullptr,                                            // const VkPipeline* pLibraries;
3937         };
3938 
3939         if (isConstructionTypeLibrary(m_internalData->pipelineConstructionType))
3940         {
3941             for (const auto &pipelinePtr : m_pipelineParts)
3942             {
3943                 const auto &pipeline = pipelinePtr.get();
3944                 if (pipeline != DE_NULL)
3945                     rawPipelines.push_back(pipeline);
3946             }
3947 
3948             linkingInfo.libraryCount = static_cast<uint32_t>(rawPipelines.size());
3949             linkingInfo.pLibraries   = de::dataOrNull(rawPipelines);
3950 
3951             // If a test hits the following assert, it's likely missing a call
3952             // to the setMonolithicPipelineLayout() method. Related VUs:
3953             //   * VUID-VkGraphicsPipelineCreateInfo-flags-06642
3954             //   * VUID-VkGraphicsPipelineCreateInfo-None-07826
3955             //   * VUID-VkGraphicsPipelineCreateInfo-layout-07827
3956             //   * VUID-VkGraphicsPipelineCreateInfo-flags-06729
3957             //   * VUID-VkGraphicsPipelineCreateInfo-flags-06730
3958             DE_ASSERT(m_internalData->monolithicPipelineCreateInfo.layout != VK_NULL_HANDLE);
3959             linkedCreateInfo.layout = m_internalData->monolithicPipelineCreateInfo.layout;
3960             linkedCreateInfo.flags  = m_internalData->pipelineFlags;
3961             linkedCreateInfo.pNext  = &linkingInfo;
3962 
3963             pointerToCreateInfo = &linkedCreateInfo;
3964 
3965             if (m_internalData->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY)
3966                 linkedCreateInfo.flags |= VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT;
3967 
3968             if (m_internalData->failOnCompileWhenLinking)
3969                 linkedCreateInfo.flags |= VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT;
3970         }
3971         else
3972         {
3973             // note: there might be other structures in the chain already
3974             void *firstStructInChain = static_cast<void *>(pointerToCreateInfo);
3975             addToChain(&firstStructInChain, creationFeedback.ptr);
3976             addToChain(&firstStructInChain, m_internalData->pRepresentativeFragmentTestState.ptr);
3977             addToChain(&firstStructInChain, m_internalData->pRenderingInputAttachmentIndex.ptr);
3978             addToChain(&firstStructInChain, m_internalData->pRenderingAttachmentLocation.ptr);
3979             addToChain(&firstStructInChain, m_internalData->pPipelineRobustnessState.ptr);
3980         }
3981 
3982         VkPipelineCreateFlags2CreateInfoKHR pipelineFlags2CreateInfo = initVulkanStructure();
3983         if (m_internalData->pipelineFlags2)
3984         {
3985             void *firstStructInChain = static_cast<void *>(pointerToCreateInfo);
3986             pipelineFlags2CreateInfo.flags =
3987                 m_internalData->pipelineFlags2 | translateCreateFlag(pointerToCreateInfo->flags);
3988             addToChain(&firstStructInChain, &pipelineFlags2CreateInfo);
3989             pointerToCreateInfo->flags = 0u;
3990         }
3991 #endif // CTS_USES_VULKANSC
3992 
3993         pointerToCreateInfo->basePipelineHandle = basePipelineHandle;
3994         pointerToCreateInfo->basePipelineIndex  = basePipelineIndex;
3995 
3996         m_pipelineFinal =
3997             makeGraphicsPipeline(m_internalData->vk, m_internalData->device, pipelineCache, pointerToCreateInfo);
3998     }
3999 }
4000 
isShaderObjectDynamic(vk::VkDynamicState dynamicState) const4001 bool GraphicsPipelineWrapper::isShaderObjectDynamic(vk::VkDynamicState dynamicState) const
4002 {
4003     return std::find(m_internalData->shaderObjectDynamicStates.begin(), m_internalData->shaderObjectDynamicStates.end(),
4004                      dynamicState) != m_internalData->shaderObjectDynamicStates.end();
4005 }
4006 
setShaderObjectDynamicStates(vk::VkCommandBuffer cmdBuffer) const4007 void GraphicsPipelineWrapper::setShaderObjectDynamicStates(vk::VkCommandBuffer cmdBuffer) const
4008 {
4009     DE_UNREF(cmdBuffer);
4010 #ifndef CTS_USES_VULKANSC
4011     const auto &vk   = m_internalData->vk;
4012     const auto state = &m_internalData->pipelineCreateState;
4013 
4014     // Some dynamic state only need to be set when these conditions are met
4015     const bool meshOrTask        = m_internalData->meshShader.isSet() || m_internalData->taskShader.isSet();
4016     const bool tese              = m_internalData->tessellationEvaluationShader.isSet();
4017     const bool topologyPatchList = !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY) ||
4018                                    state->topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
4019     const bool rasterizerDiscardDisabled =
4020         !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE) || !state->rasterizerDiscardEnable;
4021     const bool polygonModeLine =
4022         !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_POLYGON_MODE_EXT) || state->polygonMode == vk::VK_POLYGON_MODE_LINE;
4023     const bool topologyLine = !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY) ||
4024                               state->topology == vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST ||
4025                               state->topology == vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY ||
4026                               state->topology == vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP ||
4027                               state->topology == vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY;
4028     const bool depthTestEnabled =
4029         !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE) || state->depthTestEnable;
4030     const bool depthBoundsTestEnabled =
4031         !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE) || state->depthBoundsTestEnable;
4032     const bool depthBiasEnabled =
4033         !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE) || state->depthBiasEnable;
4034     const bool stencilTestEnabled =
4035         !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE) || state->stencilTestEnable;
4036     const bool logicOpEnabled =
4037         !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT) || state->logicOpEnable;
4038     const bool discardRectangle =
4039         !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT) || state->discardRectangleEnable;
4040     const bool sampleLocationsEnabled =
4041         !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT) || state->sampleLocationsEnable;
4042     const bool stippledLineEnabled =
4043         !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT) || state->stippledLineEnable;
4044     bool blendFactorConstant = !isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
4045     for (const auto &blend : state->blendEquations)
4046     {
4047         if (blend.srcColorBlendFactor == vk::VK_BLEND_FACTOR_CONSTANT_COLOR ||
4048             blend.srcColorBlendFactor == vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR ||
4049             blend.srcColorBlendFactor == vk::VK_BLEND_FACTOR_CONSTANT_ALPHA ||
4050             blend.srcColorBlendFactor == vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA ||
4051             blend.dstColorBlendFactor == vk::VK_BLEND_FACTOR_CONSTANT_COLOR ||
4052             blend.dstColorBlendFactor == vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR ||
4053             blend.dstColorBlendFactor == vk::VK_BLEND_FACTOR_CONSTANT_ALPHA ||
4054             blend.dstColorBlendFactor == vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA ||
4055             blend.srcAlphaBlendFactor == vk::VK_BLEND_FACTOR_CONSTANT_COLOR ||
4056             blend.srcAlphaBlendFactor == vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR ||
4057             blend.srcAlphaBlendFactor == vk::VK_BLEND_FACTOR_CONSTANT_ALPHA ||
4058             blend.srcAlphaBlendFactor == vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA ||
4059             blend.dstAlphaBlendFactor == vk::VK_BLEND_FACTOR_CONSTANT_COLOR ||
4060             blend.dstAlphaBlendFactor == vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR ||
4061             blend.dstAlphaBlendFactor == vk::VK_BLEND_FACTOR_CONSTANT_ALPHA ||
4062             blend.dstAlphaBlendFactor == vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)
4063 
4064             blendFactorConstant = true;
4065     }
4066 
4067     for (const auto dynamicState : m_internalData->shaderObjectDynamicStates)
4068     {
4069         switch (dynamicState)
4070         {
4071         case vk::VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT:
4072             if (!state->viewports.empty())
4073                 vk.cmdSetViewportWithCount(cmdBuffer, (uint32_t)state->viewports.size(), state->viewports.data());
4074             break;
4075         case vk::VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT:
4076             if (!state->scissors.empty())
4077                 vk.cmdSetScissorWithCount(cmdBuffer, (uint32_t)state->scissors.size(), state->scissors.data());
4078             break;
4079         case vk::VK_DYNAMIC_STATE_LINE_WIDTH:
4080             if (polygonModeLine || topologyLine)
4081                 vk.cmdSetLineWidth(cmdBuffer, state->lineWidth);
4082             break;
4083         case vk::VK_DYNAMIC_STATE_DEPTH_BIAS:
4084             if (rasterizerDiscardDisabled && depthBiasEnabled)
4085             {
4086                 if (m_internalData->extensionEnabled("VK_EXT_depth_bias_control"))
4087                 {
4088                     VkDepthBiasRepresentationInfoEXT depthBiasRepresentationInfo = vk::initVulkanStructure();
4089                     depthBiasRepresentationInfo.depthBiasRepresentation          = state->depthBiasRepresentation;
4090                     depthBiasRepresentationInfo.depthBiasExact                   = state->depthBiasExact;
4091 
4092                     vk::VkDepthBiasInfoEXT depthBiasInfo  = vk::initVulkanStructure(&depthBiasRepresentationInfo);
4093                     depthBiasInfo.depthBiasConstantFactor = state->depthBiasConstantFactor;
4094                     depthBiasInfo.depthBiasClamp          = state->depthBiasClamp;
4095                     depthBiasInfo.depthBiasSlopeFactor    = state->depthBiasSlopeFactor;
4096                     vk.cmdSetDepthBias2EXT(cmdBuffer, &depthBiasInfo);
4097                 }
4098                 else
4099                 {
4100                     vk.cmdSetDepthBias(cmdBuffer, state->depthBiasConstantFactor, state->depthBiasClamp,
4101                                        state->depthBiasSlopeFactor);
4102                 }
4103             }
4104             break;
4105         case vk::VK_DYNAMIC_STATE_BLEND_CONSTANTS:
4106             if (rasterizerDiscardDisabled && blendFactorConstant)
4107                 vk.cmdSetBlendConstants(cmdBuffer, state->blendConstants);
4108             break;
4109         case vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS:
4110             if (rasterizerDiscardDisabled && depthBoundsTestEnabled)
4111                 vk.cmdSetDepthBounds(cmdBuffer, state->minDepthBounds, state->maxDepthBounds);
4112             break;
4113         case vk::VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
4114         {
4115             vk.cmdSetStencilCompareMask(cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, state->stencilFront.compareMask);
4116             vk.cmdSetStencilCompareMask(cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, state->stencilBack.compareMask);
4117         }
4118         break;
4119         case vk::VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
4120         {
4121             vk.cmdSetStencilWriteMask(cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, state->stencilFront.writeMask);
4122             vk.cmdSetStencilWriteMask(cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, state->stencilBack.writeMask);
4123         }
4124         break;
4125         case vk::VK_DYNAMIC_STATE_STENCIL_REFERENCE:
4126         {
4127             vk.cmdSetStencilReference(cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, state->stencilFront.reference);
4128             vk.cmdSetStencilReference(cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, state->stencilBack.reference);
4129         }
4130         break;
4131         case vk::VK_DYNAMIC_STATE_CULL_MODE_EXT:
4132             vk.cmdSetCullMode(cmdBuffer, state->cullMode);
4133             break;
4134         case vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT:
4135             if (rasterizerDiscardDisabled)
4136                 vk.cmdSetDepthBoundsTestEnable(cmdBuffer, state->depthBoundsTestEnable);
4137             break;
4138         case vk::VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT:
4139             if (rasterizerDiscardDisabled && depthTestEnabled)
4140                 vk.cmdSetDepthCompareOp(cmdBuffer, state->depthCompareOp);
4141             break;
4142         case vk::VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT:
4143             if (rasterizerDiscardDisabled)
4144                 vk.cmdSetDepthTestEnable(cmdBuffer, state->depthTestEnable);
4145             break;
4146         case vk::VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT:
4147             if (rasterizerDiscardDisabled)
4148                 vk.cmdSetDepthWriteEnable(cmdBuffer, state->depthWriteEnable);
4149             break;
4150         case vk::VK_DYNAMIC_STATE_FRONT_FACE_EXT:
4151             vk.cmdSetFrontFace(cmdBuffer, state->frontFace);
4152             break;
4153         case vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT:
4154             if (!meshOrTask)
4155                 vk.cmdSetPrimitiveTopology(cmdBuffer, state->topology);
4156             break;
4157         case vk::VK_DYNAMIC_STATE_STENCIL_OP_EXT:
4158             if (rasterizerDiscardDisabled && stencilTestEnabled)
4159             {
4160                 vk.cmdSetStencilOp(cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, state->stencilFront.failOp,
4161                                    state->stencilFront.passOp, state->stencilFront.depthFailOp,
4162                                    state->stencilFront.compareOp);
4163                 vk.cmdSetStencilOp(cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, state->stencilBack.failOp,
4164                                    state->stencilBack.passOp, state->stencilBack.depthFailOp,
4165                                    state->stencilBack.compareOp);
4166             }
4167             break;
4168         case vk::VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT:
4169             if (rasterizerDiscardDisabled)
4170                 vk.cmdSetStencilTestEnable(cmdBuffer, state->stencilTestEnable);
4171             break;
4172         case vk::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT:
4173             if (!meshOrTask)
4174                 vk.cmdSetVertexInputEXT(cmdBuffer, (uint32_t)state->bindings.size(), state->bindings.data(),
4175                                         (uint32_t)state->attributes.size(), state->attributes.data());
4176             break;
4177         case vk::VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT:
4178             if (rasterizerDiscardDisabled)
4179                 vk.cmdSetDepthBiasEnable(cmdBuffer, state->depthBiasEnable);
4180             break;
4181         case vk::VK_DYNAMIC_STATE_LOGIC_OP_EXT:
4182             if (rasterizerDiscardDisabled && logicOpEnabled)
4183                 vk.cmdSetLogicOpEXT(cmdBuffer, state->logicOp);
4184             break;
4185         case vk::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT:
4186             if (topologyPatchList && !meshOrTask && tese)
4187                 vk.cmdSetPatchControlPointsEXT(cmdBuffer, state->patchControlPoints);
4188             break;
4189         case vk::VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT:
4190             if (!meshOrTask)
4191                 vk.cmdSetPrimitiveRestartEnable(cmdBuffer, state->primitiveRestartEnable);
4192             break;
4193         case vk::VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT:
4194             vk.cmdSetRasterizerDiscardEnable(cmdBuffer, state->rasterizerDiscardEnable);
4195             break;
4196         case vk::VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT:
4197             vk.cmdSetAlphaToCoverageEnableEXT(cmdBuffer, state->alphaToCoverageEnable);
4198             break;
4199         case vk::VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT:
4200             vk.cmdSetAlphaToOneEnableEXT(cmdBuffer, state->alphaToOneEnable);
4201             break;
4202         case vk::VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT:
4203             if (!state->colorBlendAdvanced.empty())
4204             {
4205                 for (uint32_t i = 0; i < (uint32_t)state->colorBlendAdvanced.size(); ++i)
4206                     if (!isShaderObjectDynamic(vk::VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT) ||
4207                         state->colorBlendEnables[i])
4208                         vk.cmdSetColorBlendAdvancedEXT(cmdBuffer, i, 1, &state->colorBlendAdvanced[i]);
4209             }
4210             break;
4211         case vk::VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT:
4212             if (rasterizerDiscardDisabled)
4213             {
4214                 if (!state->colorBlendEnables.empty())
4215                 {
4216                     vk.cmdSetColorBlendEnableEXT(cmdBuffer, 0, (uint32_t)state->colorBlendEnables.size(),
4217                                                  state->colorBlendEnables.data());
4218                 }
4219                 else
4220                 {
4221                     VkBool32 disable = VK_FALSE;
4222                     vk.cmdSetColorBlendEnableEXT(cmdBuffer, 0, 1u, &disable);
4223                 }
4224             }
4225             break;
4226         case vk::VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT:
4227             if (rasterizerDiscardDisabled)
4228             {
4229                 if (!state->blendEquations.empty())
4230                 {
4231                     vk.cmdSetColorBlendEquationEXT(cmdBuffer, 0, (uint32_t)state->blendEquations.size(),
4232                                                    state->blendEquations.data());
4233                 }
4234                 else
4235                 {
4236                     vk::VkColorBlendEquationEXT blendEquation = {
4237                         VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcColorBlendFactor;
4238                         VK_BLEND_FACTOR_DST_ALPHA, // VkBlendFactor dstColorBlendFactor;
4239                         VK_BLEND_OP_ADD,           // VkBlendOp colorBlendOp;
4240                         VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcAlphaBlendFactor;
4241                         VK_BLEND_FACTOR_DST_ALPHA, // VkBlendFactor dstAlphaBlendFactor;
4242                         VK_BLEND_OP_ADD,           // VkBlendOp alphaBlendOp;
4243                     };
4244                     vk.cmdSetColorBlendEquationEXT(cmdBuffer, 0, 1u, &blendEquation);
4245                 }
4246             }
4247             break;
4248         case vk::VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT:
4249             if (rasterizerDiscardDisabled)
4250             {
4251                 if (!state->colorWriteMasks.empty())
4252                 {
4253                     vk.cmdSetColorWriteMaskEXT(cmdBuffer, 0, (uint32_t)state->colorWriteMasks.size(),
4254                                                state->colorWriteMasks.data());
4255                 }
4256                 else
4257                 {
4258                     VkColorComponentFlags colorWriteMask = 0u;
4259                     vk.cmdSetColorWriteMaskEXT(cmdBuffer, 0, 1u, &colorWriteMask);
4260                 }
4261             }
4262             break;
4263         case vk::VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT:
4264             vk.cmdSetConservativeRasterizationModeEXT(cmdBuffer, state->conservativeRasterizationMode);
4265             break;
4266         case vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV:
4267             vk.cmdSetCoverageModulationModeNV(cmdBuffer, state->coverageModulationMode);
4268             break;
4269         case vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV:
4270             vk.cmdSetCoverageModulationTableEnableNV(cmdBuffer, state->coverageModulationTableEnable);
4271             break;
4272         case vk::VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV:
4273             if (!state->coverageModulationTable.empty())
4274                 vk.cmdSetCoverageModulationTableNV(cmdBuffer, (uint32_t)state->coverageModulationTable.size(),
4275                                                    state->coverageModulationTable.data());
4276             break;
4277         case vk::VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV:
4278             vk.cmdSetCoverageReductionModeNV(cmdBuffer, state->coverageReductionMode);
4279             break;
4280         case vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV:
4281             vk.cmdSetCoverageToColorEnableNV(cmdBuffer, state->coverageToColorEnable);
4282             break;
4283         case vk::VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV:
4284             vk.cmdSetCoverageToColorLocationNV(cmdBuffer, state->coverageToColorLocation);
4285             break;
4286         case vk::VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT:
4287             if (rasterizerDiscardDisabled)
4288                 vk.cmdSetDepthClampEnableEXT(cmdBuffer, state->depthClampEnable);
4289             break;
4290         case vk::VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT:
4291             vk.cmdSetDepthClipEnableEXT(cmdBuffer, state->depthClipEnable);
4292             break;
4293         case vk::VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT:
4294             vk.cmdSetDepthClipNegativeOneToOneEXT(cmdBuffer, state->negativeOneToOne);
4295             break;
4296         case vk::VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT:
4297             if (state->colorWriteEnableAttachmentCount > 0)
4298                 vk.cmdSetColorWriteEnableEXT(cmdBuffer, state->colorWriteEnableAttachmentCount,
4299                                              state->colorWriteEnables.data());
4300             else
4301             {
4302                 std::vector<VkBool32> enable(state->colorBlendEnables.empty() ? 1u : state->colorBlendEnables.size(),
4303                                              VK_TRUE);
4304                 vk.cmdSetColorWriteEnableEXT(cmdBuffer, (uint32_t)enable.size(), enable.data());
4305             }
4306             break;
4307         case vk::VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT:
4308             vk.cmdSetExtraPrimitiveOverestimationSizeEXT(cmdBuffer, state->extraPrimitiveOverestimationSize);
4309             break;
4310         case vk::VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT:
4311             vk.cmdSetLineRasterizationModeEXT(cmdBuffer, state->lineRasterizationMode);
4312             break;
4313         case vk::VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT:
4314             vk.cmdSetLineStippleEnableEXT(cmdBuffer, state->stippledLineEnable);
4315             break;
4316         case vk::VK_DYNAMIC_STATE_LINE_STIPPLE_EXT:
4317             if (stippledLineEnabled)
4318                 vk.cmdSetLineStippleKHR(cmdBuffer, state->lineStippleFactor, state->lineStipplePattern);
4319             break;
4320         case vk::VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT:
4321             if (rasterizerDiscardDisabled)
4322                 vk.cmdSetLogicOpEnableEXT(cmdBuffer, state->logicOpEnable);
4323             break;
4324         case vk::VK_DYNAMIC_STATE_POLYGON_MODE_EXT:
4325             vk.cmdSetPolygonModeEXT(cmdBuffer, state->polygonMode);
4326             break;
4327         case vk::VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT:
4328             vk.cmdSetProvokingVertexModeEXT(cmdBuffer, state->provokingVertexMode);
4329             break;
4330         case vk::VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT:
4331             vk.cmdSetRasterizationSamplesEXT(cmdBuffer, state->rasterizationSamples);
4332             break;
4333         case vk::VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR:
4334             vk.cmdSetFragmentShadingRateKHR(cmdBuffer, &state->fragmentShadingRateSize, state->combinerOps);
4335             break;
4336         case vk::VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT:
4337             vk.cmdSetRasterizationStreamEXT(cmdBuffer, state->rasterizationStream);
4338             break;
4339         case vk::VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV:
4340             vk.cmdSetRepresentativeFragmentTestEnableNV(cmdBuffer, state->representativeFragmentTestEnable);
4341             break;
4342         case vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT:
4343             vk.cmdSetSampleLocationsEnableEXT(cmdBuffer, state->sampleLocationsEnable);
4344             break;
4345         case vk::VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT:
4346             if (sampleLocationsEnabled)
4347                 vk.cmdSetSampleLocationsEXT(cmdBuffer, &state->sampleLocationsInfo);
4348             break;
4349         case vk::VK_DYNAMIC_STATE_SAMPLE_MASK_EXT:
4350             if (!state->sampleMasks.empty())
4351                 vk.cmdSetSampleMaskEXT(cmdBuffer, state->rasterizationSamples, state->sampleMasks.data());
4352             break;
4353         case vk::VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV:
4354             vk.cmdSetShadingRateImageEnableNV(cmdBuffer, state->shadingRateImageEnable);
4355             break;
4356         case vk::VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT:
4357             if (tese)
4358                 vk.cmdSetTessellationDomainOriginEXT(cmdBuffer, state->domainOrigin);
4359             break;
4360         case vk::VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV:
4361             if (!state->viewportSwizzles.empty())
4362             {
4363                 vk.cmdSetViewportSwizzleNV(cmdBuffer, 0, (uint32_t)state->viewportSwizzles.size(),
4364                                            state->viewportSwizzles.data());
4365             }
4366             else
4367             {
4368                 std::vector<vk::VkViewportSwizzleNV> idSwizzles(4u);
4369                 for (auto &swizzle : idSwizzles)
4370                 {
4371                     swizzle = {
4372                         vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV,
4373                         vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV,
4374                         vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV,
4375                         vk::VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV,
4376                     };
4377                 }
4378                 vk.cmdSetViewportSwizzleNV(cmdBuffer, 0u, (uint32_t)idSwizzles.size(), idSwizzles.data());
4379             }
4380             break;
4381         case vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV:
4382             vk.cmdSetViewportWScalingEnableNV(cmdBuffer, state->viewportWScalingEnable);
4383             break;
4384         case vk::VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV:
4385             if (state->viewportWScalingCount > 0)
4386                 vk.cmdSetViewportWScalingNV(cmdBuffer, 0, state->viewportWScalingCount,
4387                                             state->viewportWScalings.data());
4388             break;
4389         case vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT:
4390             if (!meshOrTask)
4391                 vk.cmdSetVertexInputEXT(cmdBuffer, (uint32_t)state->bindings.size(), state->bindings.data(),
4392                                         (uint32_t)state->attributes.size(), state->attributes.data());
4393             break;
4394         case vk::VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV:
4395             vk.cmdSetCoarseSampleOrderNV(cmdBuffer, state->coarseSampleOrderType, state->coarseCustomSampleOrderCount,
4396                                          state->coarseCustomSampleOrders.data());
4397             break;
4398         case vk::VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV:
4399             if (state->shadingRatePaletteCount > 0)
4400                 vk.cmdSetViewportShadingRatePaletteNV(cmdBuffer, 0, state->shadingRatePaletteCount,
4401                                                       state->shadingRatePalettes.data());
4402             break;
4403         case vk::VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_ENABLE_NV:
4404         {
4405             if (state->exclusiveScissorCount > 0)
4406             {
4407                 std::vector<VkBool32> exclusiveScissorEnable(state->exclusiveScissorCount, VK_TRUE);
4408                 vk.cmdSetExclusiveScissorEnableNV(cmdBuffer, 0u, state->exclusiveScissorCount,
4409                                                   exclusiveScissorEnable.data());
4410             }
4411             else
4412             {
4413                 VkBool32 enable = VK_FALSE;
4414                 vk.cmdSetExclusiveScissorEnableNV(cmdBuffer, 0u, 1u, &enable);
4415             }
4416             break;
4417         }
4418         case vk::VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV:
4419             if (state->exclusiveScissorCount > 0)
4420                 vk.cmdSetExclusiveScissorNV(cmdBuffer, 0u, state->exclusiveScissorCount,
4421                                             state->exclussiveScissors.data());
4422             break;
4423         case vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT:
4424             vk.cmdSetDiscardRectangleEnableEXT(cmdBuffer, state->discardRectangleEnable);
4425             break;
4426         case vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT:
4427             if (discardRectangle)
4428                 vk.cmdSetDiscardRectangleEXT(cmdBuffer, 0, (uint32_t)state->discardRectangles.size(),
4429                                              state->discardRectangles.data());
4430             break;
4431         case vk::VK_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT:
4432             if (discardRectangle)
4433                 vk.cmdSetDiscardRectangleModeEXT(cmdBuffer, state->discardRectangleMode);
4434             break;
4435         case vk::VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT:
4436             vk.cmdSetAttachmentFeedbackLoopEnableEXT(cmdBuffer, state->attachmentFeedbackLoopEnable);
4437             break;
4438         default:
4439             break;
4440         }
4441     }
4442 #endif // CTS_USES_VULKANSC
4443 }
4444 
bind(vk::VkCommandBuffer cmdBuffer) const4445 void GraphicsPipelineWrapper::bind(vk::VkCommandBuffer cmdBuffer) const
4446 {
4447     const auto &vk = m_internalData->vk;
4448     if (!isConstructionTypeShaderObject(m_internalData->pipelineConstructionType))
4449     {
4450         vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, getPipeline());
4451     }
4452     else
4453     {
4454 #ifndef CTS_USES_VULKANSC
4455         const VkShaderStageFlagBits vertStage = vk::VK_SHADER_STAGE_VERTEX_BIT;
4456         VkShaderEXT vertShader                = m_internalData->vertexShader.getShader();
4457         vk.cmdBindShadersEXT(cmdBuffer, 1, &vertStage, &vertShader);
4458         const VkShaderStageFlagBits tescStage = vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
4459         VkShaderEXT tescShader                = m_internalData->tessellationControlShader.getShader();
4460         vk.cmdBindShadersEXT(cmdBuffer, 1, &tescStage, &tescShader);
4461         const VkShaderStageFlagBits teseStage = vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
4462         VkShaderEXT teseShader                = m_internalData->tessellationEvaluationShader.getShader();
4463         vk.cmdBindShadersEXT(cmdBuffer, 1, &teseStage, &teseShader);
4464         const VkShaderStageFlagBits geomStage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
4465         VkShaderEXT geomShader                = m_internalData->geometryShader.getShader();
4466         vk.cmdBindShadersEXT(cmdBuffer, 1, &geomStage, &geomShader);
4467         const VkShaderStageFlagBits fragStage = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
4468         VkShaderEXT fragShader                = m_internalData->fragmentShader.getShader();
4469         vk.cmdBindShadersEXT(cmdBuffer, 1, &fragStage, &fragShader);
4470         if (m_internalData->meshShaderFeature)
4471         {
4472             const VkShaderStageFlagBits meshStage = vk::VK_SHADER_STAGE_MESH_BIT_EXT;
4473             VkShaderEXT meshShader                = m_internalData->meshShader.getShader();
4474             vk.cmdBindShadersEXT(cmdBuffer, 1, &meshStage, &meshShader);
4475         }
4476         if (m_internalData->taskShaderFeature)
4477         {
4478             const VkShaderStageFlagBits taskStage = vk::VK_SHADER_STAGE_TASK_BIT_EXT;
4479             VkShaderEXT taskShader                = m_internalData->taskShader.getShader();
4480             vk.cmdBindShadersEXT(cmdBuffer, 1, &taskStage, &taskShader);
4481         }
4482         // Set all dynamic state that would otherwise have been set with the pipeline
4483         setShaderObjectDynamicStates(cmdBuffer);
4484 #endif
4485     }
4486 }
4487 
wasBuild() const4488 bool GraphicsPipelineWrapper::wasBuild() const
4489 {
4490     return !!m_pipelineFinal.get();
4491 }
4492 
wasPipelineOrShaderObjectBuild(void) const4493 bool GraphicsPipelineWrapper::wasPipelineOrShaderObjectBuild(void) const
4494 {
4495     if (!!m_pipelineFinal.get())
4496         return true;
4497 
4498 #ifndef CTS_USES_VULKANSC
4499     if (!!m_internalData->vertexShader.getShader() || !!m_internalData->tessellationControlShader.getShader() ||
4500         !!m_internalData->tessellationEvaluationShader.getShader() || !!m_internalData->geometryShader.getShader() ||
4501         !!m_internalData->fragmentShader.getShader() || !!m_internalData->taskShader.getShader() ||
4502         !!m_internalData->meshShader.getShader())
4503         return true;
4504 #endif
4505 
4506     return false;
4507 }
4508 
getPipeline(void) const4509 VkPipeline GraphicsPipelineWrapper::getPipeline(void) const
4510 {
4511     DE_ASSERT(m_pipelineFinal.get() != DE_NULL);
4512     return m_pipelineFinal.get();
4513 }
4514 
destroyPipeline(void)4515 void GraphicsPipelineWrapper::destroyPipeline(void)
4516 {
4517     DE_ASSERT(m_pipelineFinal.get() != DE_NULL);
4518 
4519     m_pipelineFinal = Move<VkPipeline>();
4520 }
4521 
4522 } // namespace vk
4523