xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/pipeline/vktPipelineLibraryTests.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 Tests Verifying Graphics Pipeline Libraries
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktPipelineLibraryTests.hpp"
27 
28 #include "vkDefs.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkObjUtil.hpp"
31 #include "vkTypeUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vkBarrierUtil.hpp"
35 #include "vkBufferWithMemory.hpp"
36 #include "vkImageWithMemory.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkRayTracingUtil.hpp"
39 #include "vktTestCase.hpp"
40 #include "vktTestGroupUtil.hpp"
41 #include "tcuCommandLine.hpp"
42 #include "tcuImageCompare.hpp"
43 #include "tcuTestLog.hpp"
44 #include "tcuRGBA.hpp"
45 
46 #include "../draw/vktDrawCreateInfoUtil.hpp"
47 #include "deMath.h"
48 #include "deRandom.hpp"
49 #include "deClock.h"
50 
51 #include <vector>
52 #include <chrono>
53 #include <set>
54 #include <limits>
55 
56 namespace vkt
57 {
58 namespace pipeline
59 {
60 namespace
61 {
62 using namespace vk;
63 using namespace vkt;
64 using namespace tcu;
65 
66 static const uint32_t RENDER_SIZE_WIDTH  = 16u;
67 static const uint32_t RENDER_SIZE_HEIGHT = 16u;
68 static const VkColorComponentFlags COLOR_COMPONENTS_NO_RED =
69     VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
70 static const VkGraphicsPipelineLibraryFlagBitsEXT GRAPHICS_PIPELINE_LIBRARY_FLAGS[] = {
71     VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT,
72     VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT,
73     VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT,
74     VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT,
75 };
76 static const VkGraphicsPipelineLibraryFlagsEXT ALL_GRAPHICS_PIPELINE_LIBRARY_FLAGS =
77     static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT) |
78     static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) |
79     static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) |
80     static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT);
81 
82 struct PipelineTreeNode
83 {
84     int32_t parentIndex;
85     uint32_t shaderCount;
86 };
87 
88 typedef std::vector<PipelineTreeNode> PipelineTreeConfiguration;
89 
90 struct TestParams
91 {
92     PipelineTreeConfiguration pipelineTreeConfiguration;
93     bool optimize;
94     bool delayedShaderCreate;
95     bool useMaintenance5;
96 };
97 
98 struct RuntimePipelineTreeNode
99 {
100     int32_t parentIndex;
101     VkGraphicsPipelineLibraryFlagsEXT graphicsPipelineLibraryFlags;
102     VkGraphicsPipelineLibraryFlagsEXT subtreeGraphicsPipelineLibraryFlags;
103     Move<VkPipeline> pipeline;
104     std::vector<VkPipeline> pipelineLibraries;
105     // We need to track the linked libraries too, included in VkPipelineLibraryCreateInfoKHR->pLibraries
106     std::vector<VkGraphicsPipelineLibraryFlagsEXT> linkedLibraryFlags;
107 };
108 
109 typedef std::vector<RuntimePipelineTreeNode> RuntimePipelineTreeConfiguration;
110 
ivec2uvec(const IVec4 & ivec)111 inline UVec4 ivec2uvec(const IVec4 &ivec)
112 {
113     return UVec4{
114         static_cast<uint32_t>(ivec[0]),
115         static_cast<uint32_t>(ivec[1]),
116         static_cast<uint32_t>(ivec[2]),
117         static_cast<uint32_t>(ivec[3]),
118     };
119 }
120 
getTestName(const PipelineTreeConfiguration & pipelineTreeConfiguration)121 inline std::string getTestName(const PipelineTreeConfiguration &pipelineTreeConfiguration)
122 {
123     std::string result;
124     int level = pipelineTreeConfiguration[0].parentIndex;
125 
126     for (const auto &node : pipelineTreeConfiguration)
127     {
128         if (level != node.parentIndex)
129         {
130             DE_ASSERT(level < node.parentIndex);
131 
132             result += '_';
133 
134             level = node.parentIndex;
135         }
136 
137         result += de::toString(node.shaderCount);
138     }
139 
140     return result;
141 }
142 
calcPipelineCreateFlags(bool optimize,bool buildLibrary)143 inline VkPipelineCreateFlags calcPipelineCreateFlags(bool optimize, bool buildLibrary)
144 {
145     VkPipelineCreateFlags result = 0;
146 
147     if (buildLibrary)
148         result |= static_cast<VkPipelineCreateFlags>(VK_PIPELINE_CREATE_LIBRARY_BIT_KHR);
149 
150     if (optimize)
151     {
152         if (buildLibrary)
153             result |= static_cast<VkPipelineCreateFlags>(VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT);
154         else
155             result |= static_cast<VkPipelineCreateFlags>(VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT);
156     }
157 
158     return result;
159 }
160 
getRenderPass(VkGraphicsPipelineLibraryFlagsEXT subset,VkRenderPass renderPass)161 inline VkRenderPass getRenderPass(VkGraphicsPipelineLibraryFlagsEXT subset, VkRenderPass renderPass)
162 {
163     static const VkGraphicsPipelineLibraryFlagsEXT subsetRequiresRenderPass =
164         static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) |
165         static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) |
166         static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT);
167     if ((subsetRequiresRenderPass & subset) != 0)
168         return renderPass;
169 
170     return DE_NULL;
171 }
172 
makeGraphicsPipelineLibraryCreateInfo(const VkGraphicsPipelineLibraryFlagsEXT flags)173 inline VkGraphicsPipelineLibraryCreateInfoEXT makeGraphicsPipelineLibraryCreateInfo(
174     const VkGraphicsPipelineLibraryFlagsEXT flags)
175 {
176     const VkGraphicsPipelineLibraryCreateInfoEXT graphicsPipelineLibraryCreateInfo = {
177         VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT, //  VkStructureType sType;
178         DE_NULL,                                                     //  void* pNext;
179         flags,                                                       //  VkGraphicsPipelineLibraryFlagsEXT flags;
180     };
181 
182     return graphicsPipelineLibraryCreateInfo;
183 }
184 
makePipelineLibraryCreateInfo(const std::vector<VkPipeline> & pipelineLibraries)185 inline VkPipelineLibraryCreateInfoKHR makePipelineLibraryCreateInfo(const std::vector<VkPipeline> &pipelineLibraries)
186 {
187     const uint32_t libraryCount                                    = static_cast<uint32_t>(pipelineLibraries.size());
188     const VkPipeline *libraries                                    = de::dataOrNull(pipelineLibraries);
189     const VkPipelineLibraryCreateInfoKHR pipelineLibraryCreateInfo = {
190         VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR, //  VkStructureType sType;
191         DE_NULL,                                            //  const void* pNext;
192         libraryCount,                                       //  uint32_t libraryCount;
193         libraries,                                          //  const VkPipeline* pLibraries;
194     };
195 
196     return pipelineLibraryCreateInfo;
197 }
198 
getGraphicsPipelineLibraryFlagsString(const VkGraphicsPipelineLibraryFlagsEXT flags)199 inline std::string getGraphicsPipelineLibraryFlagsString(const VkGraphicsPipelineLibraryFlagsEXT flags)
200 {
201     std::string result;
202 
203     if ((flags & VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT) != 0)
204         result += "VERTEX_INPUT_INTERFACE ";
205     if ((flags & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) != 0)
206         result += "PRE_RASTERIZATION_SHADERS ";
207     if ((flags & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) != 0)
208         result += "FRAGMENT_SHADER ";
209     if ((flags & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT) != 0)
210         result += "FRAGMENT_OUTPUT_INTERFACE ";
211 
212     if (!result.empty())
213         result.resize(result.size() - 1);
214 
215     return result;
216 };
217 
makeColorImageCreateInfo(const VkFormat format,const uint32_t width,const uint32_t height)218 VkImageCreateInfo makeColorImageCreateInfo(const VkFormat format, const uint32_t width, const uint32_t height)
219 {
220     const VkImageUsageFlags usage     = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
221     const VkImageCreateInfo imageInfo = {
222         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, //  VkStructureType sType;
223         DE_NULL,                             //  const void* pNext;
224         (VkImageCreateFlags)0,               //  VkImageCreateFlags flags;
225         VK_IMAGE_TYPE_2D,                    //  VkImageType imageType;
226         format,                              //  VkFormat format;
227         makeExtent3D(width, height, 1),      //  VkExtent3D extent;
228         1u,                                  //  uint32_t mipLevels;
229         1u,                                  //  uint32_t arrayLayers;
230         VK_SAMPLE_COUNT_1_BIT,               //  VkSampleCountFlagBits samples;
231         VK_IMAGE_TILING_OPTIMAL,             //  VkImageTiling tiling;
232         usage,                               //  VkImageUsageFlags usage;
233         VK_SHARING_MODE_EXCLUSIVE,           //  VkSharingMode sharingMode;
234         0u,                                  //  uint32_t queueFamilyIndexCount;
235         DE_NULL,                             //  const uint32_t* pQueueFamilyIndices;
236         VK_IMAGE_LAYOUT_UNDEFINED,           //  VkImageLayout initialLayout;
237     };
238 
239     return imageInfo;
240 }
241 
makeImageViewCreateInfo(VkImage image,VkFormat format,VkImageAspectFlags aspectMask)242 VkImageViewCreateInfo makeImageViewCreateInfo(VkImage image, VkFormat format, VkImageAspectFlags aspectMask)
243 {
244     const VkComponentMapping components = {
245         VK_COMPONENT_SWIZZLE_R,
246         VK_COMPONENT_SWIZZLE_G,
247         VK_COMPONENT_SWIZZLE_B,
248         VK_COMPONENT_SWIZZLE_A,
249     };
250     const VkImageSubresourceRange subresourceRange = {
251         aspectMask, //  VkImageAspectFlags aspectMask;
252         0,          //  uint32_t baseMipLevel;
253         1,          //  uint32_t levelCount;
254         0,          //  uint32_t baseArrayLayer;
255         1,          //  uint32_t layerCount;
256     };
257     const VkImageViewCreateInfo result = {
258         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, //  VkStructureType sType;
259         DE_NULL,                                  //  const void* pNext;
260         0u,                                       //  VkImageViewCreateFlags flags;
261         image,                                    //  VkImage image;
262         VK_IMAGE_VIEW_TYPE_2D,                    //  VkImageViewType viewType;
263         format,                                   //  VkFormat format;
264         components,                               //  VkComponentMapping components;
265         subresourceRange,                         //  VkImageSubresourceRange subresourceRange;
266     };
267 
268     return result;
269 }
270 
makeDepthImageCreateInfo(const VkFormat format,const uint32_t width,const uint32_t height)271 VkImageCreateInfo makeDepthImageCreateInfo(const VkFormat format, const uint32_t width, const uint32_t height)
272 {
273     const VkImageUsageFlags usage =
274         VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
275     const VkImageCreateInfo imageInfo = {
276         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, //  VkStructureType sType;
277         DE_NULL,                             //  const void* pNext;
278         (VkImageCreateFlags)0,               //  VkImageCreateFlags flags;
279         VK_IMAGE_TYPE_2D,                    //  VkImageType imageType;
280         format,                              //  VkFormat format;
281         makeExtent3D(width, height, 1),      //  VkExtent3D extent;
282         1u,                                  //  uint32_t mipLevels;
283         1u,                                  //  uint32_t arrayLayers;
284         VK_SAMPLE_COUNT_1_BIT,               //  VkSampleCountFlagBits samples;
285         VK_IMAGE_TILING_OPTIMAL,             //  VkImageTiling tiling;
286         usage,                               //  VkImageUsageFlags usage;
287         VK_SHARING_MODE_EXCLUSIVE,           //  VkSharingMode sharingMode;
288         0u,                                  //  uint32_t queueFamilyIndexCount;
289         DE_NULL,                             //  const uint32_t* pQueueFamilyIndices;
290         VK_IMAGE_LAYOUT_UNDEFINED,           //  VkImageLayout initialLayout;
291     };
292 
293     return imageInfo;
294 }
295 
makeFramebufferCreateInfo(const VkRenderPass renderPass,const uint32_t attachmentCount,const VkImageView * attachments,const uint32_t width,const uint32_t height)296 const VkFramebufferCreateInfo makeFramebufferCreateInfo(const VkRenderPass renderPass, const uint32_t attachmentCount,
297                                                         const VkImageView *attachments, const uint32_t width,
298                                                         const uint32_t height)
299 {
300     const VkFramebufferCreateInfo result = {
301         VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, //  VkStructureType sType;
302         DE_NULL,                                   //  const void* pNext;
303         0,                                         //  VkFramebufferCreateFlags flags;
304         renderPass,                                //  VkRenderPass renderPass;
305         attachmentCount,                           //  uint32_t attachmentCount;
306         attachments,                               //  const VkImageView* pAttachments;
307         width,                                     //  uint32_t width;
308         height,                                    //  uint32_t height;
309         1,                                         //  uint32_t layers;
310     };
311 
312     return result;
313 }
314 
makePipelineMultisampleStateCreateInfo(void)315 const VkPipelineMultisampleStateCreateInfo makePipelineMultisampleStateCreateInfo(void)
316 {
317     const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo = {
318         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, //  VkStructureType sType;
319         DE_NULL,                                                  //  const void* pNext;
320         0u,                                                       //  VkPipelineMultisampleStateCreateFlags flags;
321         VK_SAMPLE_COUNT_1_BIT,                                    //  VkSampleCountFlagBits rasterizationSamples;
322         false,                                                    //  VkBool32 sampleShadingEnable;
323         0.0f,                                                     //  float minSampleShading;
324         DE_NULL,                                                  //  const VkSampleMask* pSampleMask;
325         false,                                                    //  VkBool32 alphaToCoverageEnable;
326         false,                                                    //  VkBool32 alphaToOneEnable;
327     };
328 
329     return pipelineMultisampleStateCreateInfo;
330 }
331 
332 class GraphicsPipelineCreateInfo : public ::vkt::Draw::PipelineCreateInfo
333 {
334 public:
GraphicsPipelineCreateInfo(vk::VkPipelineLayout _layout,vk::VkRenderPass _renderPass,int _subpass,vk::VkPipelineCreateFlags _flags)335     GraphicsPipelineCreateInfo(vk::VkPipelineLayout _layout, vk::VkRenderPass _renderPass, int _subpass,
336                                vk::VkPipelineCreateFlags _flags)
337         : ::vkt::Draw::PipelineCreateInfo(_layout, _renderPass, _subpass, _flags)
338         , m_vertexInputBindingDescription()
339         , m_vertexInputAttributeDescription()
340         , m_shaderModuleCreateInfoCount(0)
341         , m_shaderModuleCreateInfo{initVulkanStructure(), initVulkanStructure()}
342         , m_pipelineShaderStageCreateInfo()
343         , m_vertModule()
344         , m_fragModule()
345     {
346     }
347 
348     VkVertexInputBindingDescription m_vertexInputBindingDescription;
349     VkVertexInputAttributeDescription m_vertexInputAttributeDescription;
350     uint32_t m_shaderModuleCreateInfoCount;
351     VkShaderModuleCreateInfo m_shaderModuleCreateInfo[2];
352     std::vector<VkPipelineShaderStageCreateInfo> m_pipelineShaderStageCreateInfo;
353     Move<VkShaderModule> m_vertModule;
354     Move<VkShaderModule> m_fragModule;
355 };
356 
updateVertexInputInterface(Context & context,GraphicsPipelineCreateInfo & graphicsPipelineCreateInfo,VkPrimitiveTopology topology=VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,uint32_t vertexDescriptionCount=1u)357 void updateVertexInputInterface(Context &context, GraphicsPipelineCreateInfo &graphicsPipelineCreateInfo,
358                                 VkPrimitiveTopology topology    = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
359                                 uint32_t vertexDescriptionCount = 1u)
360 {
361     DE_UNREF(context);
362 
363     graphicsPipelineCreateInfo.m_vertexInputBindingDescription = {
364         0u,                          //  uint32_t binding;
365         sizeof(tcu::Vec4),           //  uint32_t strideInBytes;
366         VK_VERTEX_INPUT_RATE_VERTEX, //  VkVertexInputRate inputRate;
367     };
368     graphicsPipelineCreateInfo.m_vertexInputAttributeDescription = {
369         0u,                            //  uint32_t location;
370         0u,                            //  uint32_t binding;
371         VK_FORMAT_R32G32B32A32_SFLOAT, //  VkFormat format;
372         0u                             //  uint32_t offsetInBytes;
373     };
374 
375     const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo{
376         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
377         DE_NULL,                                                   // const void* pNext;
378         0u,                                                        // VkPipelineVertexInputStateCreateFlags flags;
379         vertexDescriptionCount,                                    // uint32_t vertexBindingDescriptionCount;
380         &graphicsPipelineCreateInfo
381              .m_vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
382         vertexDescriptionCount,                // uint32_t vertexAttributeDescriptionCount;
383         &graphicsPipelineCreateInfo
384              .m_vertexInputAttributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
385     };
386     const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo{
387         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
388         DE_NULL,                                                     // const void* pNext;
389         0u,                                                          // VkPipelineInputAssemblyStateCreateFlags flags;
390         topology,                                                    // VkPrimitiveTopology topology;
391         VK_FALSE,                                                    // VkBool32 primitiveRestartEnable;
392     };
393 
394     graphicsPipelineCreateInfo.addState(vertexInputStateCreateInfo);
395     graphicsPipelineCreateInfo.addState(inputAssemblyStateCreateInfo);
396 }
397 
updatePreRasterization(Context & context,GraphicsPipelineCreateInfo & graphicsPipelineCreateInfo,bool delayedShaderCreate,VkPolygonMode polygonMode=VK_POLYGON_MODE_FILL,const VkSpecializationInfo * specializationInfo=DE_NULL)398 void updatePreRasterization(Context &context, GraphicsPipelineCreateInfo &graphicsPipelineCreateInfo,
399                             bool delayedShaderCreate, VkPolygonMode polygonMode = VK_POLYGON_MODE_FILL,
400                             const VkSpecializationInfo *specializationInfo = DE_NULL)
401 {
402     const ProgramBinary &shaderBinary = context.getBinaryCollection().get("vert");
403     VkShaderModuleCreateInfo &shaderModuleCreateInfo =
404         graphicsPipelineCreateInfo.m_shaderModuleCreateInfo[graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount];
405 
406     DE_ASSERT(graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount <
407               DE_LENGTH_OF_ARRAY(graphicsPipelineCreateInfo.m_shaderModuleCreateInfo));
408 
409     shaderModuleCreateInfo = {
410         VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, //  VkStructureType sType;
411         DE_NULL,                                     //  const void* pNext;
412         0u,                                          //  VkShaderModuleCreateFlags flags;
413         (uintptr_t)shaderBinary.getSize(),           //  uintptr_t codeSize;
414         (uint32_t *)shaderBinary.getBinary(),        //  const uint32_t* pCode;
415     };
416 
417     if (!delayedShaderCreate)
418     {
419         const DeviceInterface &vk = context.getDeviceInterface();
420         const VkDevice device     = context.getDevice();
421 
422         graphicsPipelineCreateInfo.m_vertModule = createShaderModule(vk, device, &shaderModuleCreateInfo);
423     }
424 
425     const void *pNext                 = delayedShaderCreate ? &shaderModuleCreateInfo : DE_NULL;
426     const VkShaderModule shaderModule = delayedShaderCreate ? DE_NULL : *graphicsPipelineCreateInfo.m_vertModule;
427     const VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo = {
428         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
429         pNext,                                               // const void* pNext;
430         0u,                                                  // VkPipelineShaderStageCreateFlags flags;
431         VK_SHADER_STAGE_VERTEX_BIT,                          // VkShaderStageFlagBits stage;
432         shaderModule,                                        // VkShaderModule module;
433         "main",                                              // const char* pName;
434         specializationInfo                                   // const VkSpecializationInfo* pSpecializationInfo;
435     };
436 
437     shaderBinary.setUsed();
438 
439     // Within the VkPipelineLayout, all    bindings that affect the specified shader stages
440     const VkViewport viewport = makeViewport(RENDER_SIZE_WIDTH, RENDER_SIZE_HEIGHT);
441     const VkRect2D scissor    = makeRect2D(3 * RENDER_SIZE_WIDTH / 4, RENDER_SIZE_HEIGHT);
442     const VkPipelineViewportStateCreateInfo pipelineViewportStateCreateInfo = {
443         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
444         DE_NULL,                                               // const void* pNext;
445         0u,                                                    // VkPipelineViewportStateCreateFlags flags;
446         1u,                                                    // uint32_t viewportCount;
447         &viewport,                                             // const VkViewport* pViewports;
448         1u,                                                    // uint32_t scissorCount;
449         &scissor                                               // const VkRect2D* pScissors;
450     };
451     const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo = {
452         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
453         DE_NULL,                                                    // const void* pNext;
454         0u,                                                         // VkPipelineRasterizationStateCreateFlags flags;
455         VK_FALSE,                                                   // VkBool32 depthClampEnable;
456         VK_FALSE,                                                   // VkBool32 rasterizerDiscardEnable;
457         polygonMode,                                                // VkPolygonMode polygonMode;
458         VK_CULL_MODE_NONE,                                          // VkCullModeFlags cullMode;
459         VK_FRONT_FACE_COUNTER_CLOCKWISE,                            // VkFrontFace frontFace;
460         VK_FALSE,                                                   // VkBool32 depthBiasEnable;
461         0.0f,                                                       // float depthBiasConstantFactor;
462         0.0f,                                                       // float depthBiasClamp;
463         0.0f,                                                       // float depthBiasSlopeFactor;
464         1.0f,                                                       // float lineWidth;
465     };
466 
467     graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount++;
468 
469     graphicsPipelineCreateInfo.addShader(pipelineShaderStageCreateInfo);
470     graphicsPipelineCreateInfo.addState(pipelineViewportStateCreateInfo);
471     graphicsPipelineCreateInfo.addState(pipelineRasterizationStateCreateInfo);
472 }
473 
updatePostRasterization(Context & context,GraphicsPipelineCreateInfo & graphicsPipelineCreateInfo,bool delayedShaderCreate,bool enableDepth=true,const VkSpecializationInfo * specializationInfo=DE_NULL)474 void updatePostRasterization(Context &context, GraphicsPipelineCreateInfo &graphicsPipelineCreateInfo,
475                              bool delayedShaderCreate, bool enableDepth = true,
476                              const VkSpecializationInfo *specializationInfo = DE_NULL)
477 {
478     const ProgramBinary &shaderBinary = context.getBinaryCollection().get("frag");
479     VkShaderModuleCreateInfo &shaderModuleCreateInfo =
480         graphicsPipelineCreateInfo.m_shaderModuleCreateInfo[graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount];
481 
482     DE_ASSERT(graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount <
483               DE_LENGTH_OF_ARRAY(graphicsPipelineCreateInfo.m_shaderModuleCreateInfo));
484 
485     shaderModuleCreateInfo = {
486         VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, //  VkStructureType sType;
487         DE_NULL,                                     //  const void* pNext;
488         0u,                                          //  VkShaderModuleCreateFlags flags;
489         (uintptr_t)shaderBinary.getSize(),           //  uintptr_t codeSize;
490         (uint32_t *)shaderBinary.getBinary(),        //  const uint32_t* pCode;
491     };
492 
493     if (!delayedShaderCreate)
494     {
495         const DeviceInterface &vk = context.getDeviceInterface();
496         const VkDevice device     = context.getDevice();
497 
498         graphicsPipelineCreateInfo.m_fragModule = createShaderModule(vk, device, &shaderModuleCreateInfo);
499     }
500 
501     const void *pNext                 = delayedShaderCreate ? &shaderModuleCreateInfo : DE_NULL;
502     const VkShaderModule shaderModule = delayedShaderCreate ? DE_NULL : *graphicsPipelineCreateInfo.m_fragModule;
503     const VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo = {
504         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
505         pNext,                                               // const void* pNext;
506         0u,                                                  // VkPipelineShaderStageCreateFlags flags;
507         VK_SHADER_STAGE_FRAGMENT_BIT,                        // VkShaderStageFlagBits stage;
508         shaderModule,                                        // VkShaderModule module;
509         "main",                                              // const char* pName;
510         specializationInfo                                   // const VkSpecializationInfo* pSpecializationInfo;
511     };
512 
513     shaderBinary.setUsed();
514 
515     // Within the VkPipelineLayout, all bindings that affect the fragment shader stage
516 
517     const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo = {
518         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, //  VkStructureType sType;
519         DE_NULL,                                                    //  const void* pNext;
520         0u,                                                         //  VkPipelineDepthStencilStateCreateFlags flags;
521         enableDepth,                                                //  VkBool32 depthTestEnable;
522         enableDepth,                                                //  VkBool32 depthWriteEnable;
523         VK_COMPARE_OP_LESS_OR_EQUAL,                                //  VkCompareOp depthCompareOp;
524         VK_FALSE,                                                   //  VkBool32 depthBoundsTestEnable;
525         VK_FALSE,                                                   //  VkBool32 stencilTestEnable;
526         {
527             //  VkStencilOpState front;
528             VK_STENCIL_OP_KEEP,  // VkStencilOp failOp;
529             VK_STENCIL_OP_KEEP,  // VkStencilOp passOp;
530             VK_STENCIL_OP_KEEP,  // VkStencilOp depthFailOp;
531             VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
532             0u,                  // uint32_t compareMask;
533             0u,                  // uint32_t writeMask;
534             0u,                  // uint32_t reference;
535         },
536         {
537             //  VkStencilOpState back;
538             VK_STENCIL_OP_KEEP,  // VkStencilOp failOp;
539             VK_STENCIL_OP_KEEP,  // VkStencilOp passOp;
540             VK_STENCIL_OP_KEEP,  // VkStencilOp depthFailOp;
541             VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
542             0u,                  // uint32_t compareMask;
543             0u,                  // uint32_t writeMask;
544             0u,                  // uint32_t reference;
545         },
546         0.0f, //  float minDepthBounds;
547         1.0f, //  float maxDepthBounds;
548     };
549 
550     graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount++;
551     graphicsPipelineCreateInfo.addShader(pipelineShaderStageCreateInfo);
552 
553     DE_ASSERT(graphicsPipelineCreateInfo.pDepthStencilState == DE_NULL);
554     graphicsPipelineCreateInfo.addState(pipelineDepthStencilStateCreateInfo);
555 
556     if (graphicsPipelineCreateInfo.pMultisampleState == DE_NULL)
557     {
558         const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo =
559             makePipelineMultisampleStateCreateInfo();
560 
561         graphicsPipelineCreateInfo.addState(pipelineMultisampleStateCreateInfo);
562     }
563 }
564 
updateFragmentOutputInterface(Context & context,GraphicsPipelineCreateInfo & graphicsPipelineCreateInfo,VkColorComponentFlags colorWriteMask=COLOR_COMPONENTS_NO_RED)565 void updateFragmentOutputInterface(Context &context, GraphicsPipelineCreateInfo &graphicsPipelineCreateInfo,
566                                    VkColorComponentFlags colorWriteMask = COLOR_COMPONENTS_NO_RED)
567 {
568     DE_UNREF(context);
569 
570     // Number of blend attachments must equal the number of color attachments during any subpass.
571     const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = {
572         VK_FALSE,             // VkBool32 blendEnable;
573         VK_BLEND_FACTOR_ONE,  // VkBlendFactor srcColorBlendFactor;
574         VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
575         VK_BLEND_OP_ADD,      // VkBlendOp colorBlendOp;
576         VK_BLEND_FACTOR_ONE,  // VkBlendFactor srcAlphaBlendFactor;
577         VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
578         VK_BLEND_OP_ADD,      // VkBlendOp alphaBlendOp;
579         colorWriteMask,       // VkColorComponentFlags colorWriteMask;
580     };
581     const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo = {
582         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
583         DE_NULL,                                                  // const void* pNext;
584         (VkPipelineColorBlendStateCreateFlags)0,                  // VkPipelineColorBlendStateCreateFlags flags;
585         VK_FALSE,                                                 // VkBool32 logicOpEnable;
586         VK_LOGIC_OP_COPY,                                         // VkLogicOp logicOp;
587         1u,                                                       // uint32_t attachmentCount;
588         &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
589         {0.0f, 0.0f, 0.0f, 0.0f},           // float blendConstants[4];
590     };
591 
592     graphicsPipelineCreateInfo.addState(pipelineColorBlendStateCreateInfo);
593 
594     if (graphicsPipelineCreateInfo.pMultisampleState == DE_NULL)
595     {
596         const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo =
597             makePipelineMultisampleStateCreateInfo();
598 
599         graphicsPipelineCreateInfo.addState(pipelineMultisampleStateCreateInfo);
600     }
601 }
602 
603 /*
604     To test that each of graphics pipeline libraries have influence on final pipeline
605     the functions have following features:
606 
607     updateVertexInputInterface
608         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
609         VK_VERTEX_INPUT_RATE_VERTEX
610         Z is read from uniform and written in shader
611 
612     updatePreRasterization
613         VkRect2D scissor = makeRect2D(3 * RENDER_SIZE_WIDTH / 4, RENDER_SIZE_HEIGHT);
614 
615     updatePostRasterization
616         Fragment shader top and bottom colors read from uniform buffer
617 
618     updateFragmentOutputInterface
619         Cut off red component
620 */
621 
622 class PipelineLibraryTestInstance : public TestInstance
623 {
624 public:
625     PipelineLibraryTestInstance(Context &context, const TestParams &data);
626     ~PipelineLibraryTestInstance(void);
627     tcu::TestStatus iterate(void);
628 
629 protected:
630     de::MovePtr<BufferWithMemory> makeVertexBuffer(void);
631     de::MovePtr<BufferWithMemory> makeZCoordBuffer(void);
632     de::MovePtr<BufferWithMemory> makePaletteBuffer(void);
633     Move<VkDescriptorPool> createDescriptorPool(void);
634     Move<VkDescriptorSetLayout> createDescriptorSetLayout(const VkBuffer vertShaderBuffer,
635                                                           const VkBuffer fragShaderBuffer);
636     Move<VkDescriptorSet> createDescriptorSet(const VkDescriptorPool pool, const VkDescriptorSetLayout layout,
637                                               const VkBuffer vertShaderBuffer, const VkBuffer fragShaderBuffer);
638     bool verifyColorImage(const tcu::ConstPixelBufferAccess &pba);
639     bool verifyDepthImage(const tcu::ConstPixelBufferAccess &pba);
640     bool runTest(RuntimePipelineTreeConfiguration &runtimePipelineTreeConfiguration, const bool optimize,
641                  const bool delayedShaderCreate);
642 
643 private:
644     TestParams m_data;
645     std::vector<tcu::Vec4> m_vertexData;
646     std::vector<tcu::Vec4> m_paletteData;
647     std::vector<tcu::Vec4> m_zCoordData;
648 };
649 
PipelineLibraryTestInstance(Context & context,const TestParams & data)650 PipelineLibraryTestInstance::PipelineLibraryTestInstance(Context &context, const TestParams &data)
651     : vkt::TestInstance(context)
652     , m_data(data)
653     , m_vertexData()
654     , m_paletteData()
655 {
656     m_vertexData = {
657         {-1.0f, -1.0f, 0.0f, 1.0f}, {+1.0f, -1.0f, 0.5f, 1.0f}, {-1.0f, +1.0f, 0.5f, 1.0f},
658         {-1.0f, +1.0f, 0.5f, 1.0f}, {+1.0f, -1.0f, 0.5f, 1.0f}, {+1.0f, +1.0f, 1.0f, 1.0f},
659     };
660     m_paletteData = {
661         {0.25f, 1.0f, 0.0f, 1.0f},
662         {0.75f, 0.0f, 1.0f, 1.0f},
663     };
664     m_zCoordData = {
665         {0.25f, 0.75f, 0.0f, 1.0f},
666     };
667 }
668 
~PipelineLibraryTestInstance(void)669 PipelineLibraryTestInstance::~PipelineLibraryTestInstance(void)
670 {
671 }
672 
makeVertexBuffer(void)673 de::MovePtr<BufferWithMemory> PipelineLibraryTestInstance::makeVertexBuffer(void)
674 {
675     const DeviceInterface &vk                 = m_context.getDeviceInterface();
676     const VkDevice device                     = m_context.getDevice();
677     Allocator &allocator                      = m_context.getDefaultAllocator();
678     const size_t bufferDataSize               = de::dataSize(m_vertexData);
679     const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferDataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
680     de::MovePtr<BufferWithMemory> buffer      = de::MovePtr<BufferWithMemory>(
681         new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
682 
683     deMemcpy(buffer->getAllocation().getHostPtr(), m_vertexData.data(), bufferDataSize);
684     flushAlloc(vk, device, buffer->getAllocation());
685 
686     return buffer;
687 }
688 
makeZCoordBuffer(void)689 de::MovePtr<BufferWithMemory> PipelineLibraryTestInstance::makeZCoordBuffer(void)
690 {
691     const DeviceInterface &vk   = m_context.getDeviceInterface();
692     const VkDevice device       = m_context.getDevice();
693     Allocator &allocator        = m_context.getDefaultAllocator();
694     const size_t bufferDataSize = de::dataSize(m_zCoordData);
695     const VkBufferCreateInfo bufferCreateInfo =
696         makeBufferCreateInfo(bufferDataSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
697     de::MovePtr<BufferWithMemory> buffer = de::MovePtr<BufferWithMemory>(
698         new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
699 
700     deMemcpy(buffer->getAllocation().getHostPtr(), m_zCoordData.data(), bufferDataSize);
701     flushAlloc(vk, device, buffer->getAllocation());
702 
703     return buffer;
704 }
705 
makePaletteBuffer(void)706 de::MovePtr<BufferWithMemory> PipelineLibraryTestInstance::makePaletteBuffer(void)
707 {
708     const DeviceInterface &vk   = m_context.getDeviceInterface();
709     const VkDevice device       = m_context.getDevice();
710     Allocator &allocator        = m_context.getDefaultAllocator();
711     const size_t bufferDataSize = de::dataSize(m_paletteData);
712     const VkBufferCreateInfo bufferCreateInfo =
713         makeBufferCreateInfo(bufferDataSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
714     de::MovePtr<BufferWithMemory> buffer = de::MovePtr<BufferWithMemory>(
715         new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
716 
717     deMemcpy(buffer->getAllocation().getHostPtr(), m_paletteData.data(), bufferDataSize);
718     flushAlloc(vk, device, buffer->getAllocation());
719 
720     return buffer;
721 }
722 
createDescriptorPool(void)723 Move<VkDescriptorPool> PipelineLibraryTestInstance::createDescriptorPool(void)
724 {
725     const DeviceInterface &vk = m_context.getDeviceInterface();
726     const VkDevice device     = m_context.getDevice();
727 
728     return DescriptorPoolBuilder()
729         .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4)
730         .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 3);
731 }
732 
createDescriptorSetLayout(const VkBuffer vertShaderBuffer,const VkBuffer fragShaderBuffer)733 Move<VkDescriptorSetLayout> PipelineLibraryTestInstance::createDescriptorSetLayout(const VkBuffer vertShaderBuffer,
734                                                                                    const VkBuffer fragShaderBuffer)
735 {
736     const DeviceInterface &vk = m_context.getDeviceInterface();
737     const VkDevice device     = m_context.getDevice();
738     DescriptorSetLayoutBuilder builder;
739 
740     if (vertShaderBuffer != DE_NULL)
741         builder.addIndexedBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u, VK_SHADER_STAGE_VERTEX_BIT, 0u, DE_NULL);
742 
743     if (fragShaderBuffer != DE_NULL)
744         builder.addIndexedBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u, VK_SHADER_STAGE_FRAGMENT_BIT, 1u, DE_NULL);
745 
746     return builder.build(vk, device);
747 }
748 
createDescriptorSet(const VkDescriptorPool pool,const VkDescriptorSetLayout layout,const VkBuffer vertShaderBuffer,const VkBuffer fragShaderBuffer)749 Move<VkDescriptorSet> PipelineLibraryTestInstance::createDescriptorSet(const VkDescriptorPool pool,
750                                                                        const VkDescriptorSetLayout layout,
751                                                                        const VkBuffer vertShaderBuffer,
752                                                                        const VkBuffer fragShaderBuffer)
753 {
754     const DeviceInterface &vk                   = m_context.getDeviceInterface();
755     const VkDevice device                       = m_context.getDevice();
756     const VkDescriptorSetAllocateInfo allocInfo = {
757         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, //  VkStructureType sType;
758         DE_NULL,                                        //  const void* pNext;
759         pool,                                           //  VkDescriptorPool descriptorPool;
760         1u,                                             //  uint32_t descriptorSetCount;
761         &layout                                         //  const VkDescriptorSetLayout* pSetLayouts;
762     };
763     Move<VkDescriptorSet> descriptorSet = allocateDescriptorSet(vk, device, &allocInfo);
764     DescriptorSetUpdateBuilder builder;
765 
766     if (vertShaderBuffer != DE_NULL)
767     {
768         const VkDeviceSize vertShaderBufferSize = de::dataSize(m_zCoordData);
769         const VkDescriptorBufferInfo vertShaderBufferInfo =
770             makeDescriptorBufferInfo(vertShaderBuffer, 0u, vertShaderBufferSize);
771 
772         builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
773                             VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &vertShaderBufferInfo);
774     }
775 
776     if (fragShaderBuffer != DE_NULL)
777     {
778         const VkDeviceSize fragShaderBufferSize = de::dataSize(m_paletteData);
779         const VkDescriptorBufferInfo fragShaderBufferInfo =
780             makeDescriptorBufferInfo(fragShaderBuffer, 0u, fragShaderBufferSize);
781 
782         builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
783                             VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &fragShaderBufferInfo);
784     }
785 
786     builder.update(vk, device);
787 
788     return descriptorSet;
789 }
790 
getSupportedDepthFormat(const InstanceInterface & vk,const VkPhysicalDevice physicalDevice)791 VkFormat getSupportedDepthFormat(const InstanceInterface &vk, const VkPhysicalDevice physicalDevice)
792 {
793     VkFormatProperties properties;
794 
795     const VkFormat DepthFormats[] = {VK_FORMAT_D32_SFLOAT, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D24_UNORM_S8_UINT,
796                                      VK_FORMAT_D32_SFLOAT_S8_UINT};
797 
798     for (const auto format : DepthFormats)
799     {
800         vk.getPhysicalDeviceFormatProperties(physicalDevice, format, &properties);
801 
802         if (properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
803             return format;
804     }
805 
806     TCU_THROW(NotSupportedError, "Depth format is not supported");
807 }
808 
runTest(RuntimePipelineTreeConfiguration & runtimePipelineTreeConfiguration,const bool optimize,const bool delayedShaderCreate)809 bool PipelineLibraryTestInstance::runTest(RuntimePipelineTreeConfiguration &runtimePipelineTreeConfiguration,
810                                           const bool optimize, const bool delayedShaderCreate)
811 {
812     const DeviceInterface &vk       = m_context.getDeviceInterface();
813     const VkDevice device           = m_context.getDevice();
814     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
815     Allocator &allocator            = m_context.getDefaultAllocator();
816     tcu::TestLog &log               = m_context.getTestContext().getLog();
817     const VkFormat colorFormat      = VK_FORMAT_R8G8B8A8_UNORM;
818     const VkFormat depthFormat =
819         getSupportedDepthFormat(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
820     const VkGraphicsPipelineLibraryFlagsEXT vertPipelineFlags =
821         static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT);
822     const VkGraphicsPipelineLibraryFlagsEXT fragPipelineFlags =
823         static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT);
824     const VkGraphicsPipelineLibraryFlagsEXT samePipelineFlags = vertPipelineFlags | fragPipelineFlags;
825     const int32_t nodeNdxLast           = static_cast<int32_t>(runtimePipelineTreeConfiguration.size()) - 1;
826     const Move<VkRenderPass> renderPass = makeRenderPass(vk, device, colorFormat, depthFormat);
827     const de::MovePtr<BufferWithMemory> zCoordBuffer  = makeZCoordBuffer();
828     const de::MovePtr<BufferWithMemory> paletteBuffer = makePaletteBuffer();
829     const Move<VkDescriptorPool> descriptorPool       = createDescriptorPool();
830 
831     const Move<VkDescriptorSetLayout> descriptorSetLayoutVert = createDescriptorSetLayout(**zCoordBuffer, DE_NULL);
832     const Move<VkDescriptorSetLayout> descriptorSetLayoutFrag = createDescriptorSetLayout(DE_NULL, **paletteBuffer);
833     const Move<VkDescriptorSetLayout> descriptorSetLayoutBoth =
834         createDescriptorSetLayout(**zCoordBuffer, **paletteBuffer);
835     const Move<VkDescriptorSet> descriptorSetVert =
836         createDescriptorSet(*descriptorPool, *descriptorSetLayoutVert, **zCoordBuffer, DE_NULL);
837     const Move<VkDescriptorSet> descriptorSetFrag =
838         createDescriptorSet(*descriptorPool, *descriptorSetLayoutFrag, DE_NULL, **paletteBuffer);
839 
840     VkDescriptorSet vecDescriptorSetBoth[2] = {*descriptorSetVert, *descriptorSetFrag};
841 
842     VkDescriptorSetLayout vecLayoutVert[2] = {*descriptorSetLayoutVert, DE_NULL};
843     VkDescriptorSetLayout vecLayoutFrag[2] = {DE_NULL, *descriptorSetLayoutFrag};
844     VkDescriptorSetLayout vecLayoutBoth[2] = {*descriptorSetLayoutVert, *descriptorSetLayoutFrag};
845 
846     VkPipelineLayoutCreateFlags pipelineLayoutCreateFlag = 0u;
847     if (!m_data.useMaintenance5 && (m_data.delayedShaderCreate || (m_data.pipelineTreeConfiguration.size() > 1)))
848         pipelineLayoutCreateFlag = VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT;
849 
850     const Move<VkCommandPool> cmdPool =
851         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
852     const Move<VkCommandBuffer> cmdBuffer =
853         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
854     const Move<VkPipelineLayout> pipelineLayoutSame =
855         makePipelineLayout(vk, device, 2, vecLayoutBoth, pipelineLayoutCreateFlag);
856     Move<VkPipelineLayout> pipelineLayoutVert;
857     Move<VkPipelineLayout> pipelineLayoutFrag;
858     Move<VkPipeline> rootPipeline;
859 
860     // Go through tree nodes and create library for each up to root
861     for (int32_t nodeNdx = nodeNdxLast; nodeNdx >= 0;
862          --nodeNdx) // We expect only backward node reference, thus build pipielines from end is safe
863     {
864         RuntimePipelineTreeNode &node                   = runtimePipelineTreeConfiguration[nodeNdx];
865         const bool buildLibrary                         = (nodeNdx != 0);
866         const VkPipelineCreateFlags pipelineCreateFlags = calcPipelineCreateFlags(optimize, buildLibrary);
867         const VkGraphicsPipelineLibraryFlagsEXT subtreeGraphicsPipelineLibraryFlags =
868             node.subtreeGraphicsPipelineLibraryFlags | node.graphicsPipelineLibraryFlags;
869         const bool samePipelineLayout = samePipelineFlags == (samePipelineFlags & subtreeGraphicsPipelineLibraryFlags);
870         const bool vertPipelineLayout = vertPipelineFlags == (vertPipelineFlags & subtreeGraphicsPipelineLibraryFlags);
871         const bool fragPipelineLayout = fragPipelineFlags == (fragPipelineFlags & subtreeGraphicsPipelineLibraryFlags);
872 
873         if (samePipelineLayout)
874             ; // pipelineLayoutSame is always built before.
875         else if (vertPipelineLayout)
876         {
877             if (!pipelineLayoutVert)
878                 pipelineLayoutVert = makePipelineLayout(vk, device, 2, vecLayoutVert, pipelineLayoutCreateFlag);
879         }
880         else if (fragPipelineLayout)
881         {
882             if (!pipelineLayoutFrag)
883                 pipelineLayoutFrag = makePipelineLayout(vk, device, 2, vecLayoutFrag, pipelineLayoutCreateFlag);
884         }
885 
886         const VkPipelineLayout pipelineLayout = samePipelineLayout ? *pipelineLayoutSame :
887                                                 vertPipelineLayout ? *pipelineLayoutVert :
888                                                 fragPipelineLayout ? *pipelineLayoutFrag :
889                                                                      DE_NULL;
890         const VkRenderPass renderPassHandle   = getRenderPass(node.graphicsPipelineLibraryFlags, *renderPass);
891         VkGraphicsPipelineLibraryCreateInfoEXT graphicsPipelineLibraryCreateInfo =
892             makeGraphicsPipelineLibraryCreateInfo(node.graphicsPipelineLibraryFlags);
893         VkPipelineLibraryCreateInfoKHR linkingInfo = makePipelineLibraryCreateInfo(node.pipelineLibraries);
894         GraphicsPipelineCreateInfo graphicsPipelineCreateInfo(pipelineLayout, renderPassHandle, 0, pipelineCreateFlags);
895 
896         for (const auto subsetFlag : GRAPHICS_PIPELINE_LIBRARY_FLAGS)
897         {
898             if ((node.graphicsPipelineLibraryFlags & subsetFlag) != 0)
899             {
900                 switch (subsetFlag)
901                 {
902                 case VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT:
903                     updateVertexInputInterface(m_context, graphicsPipelineCreateInfo);
904                     break;
905                 case VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT:
906                     updatePreRasterization(m_context, graphicsPipelineCreateInfo, delayedShaderCreate);
907                     break;
908                 case VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT:
909                     updatePostRasterization(m_context, graphicsPipelineCreateInfo, delayedShaderCreate);
910                     break;
911                 case VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT:
912                     updateFragmentOutputInterface(m_context, graphicsPipelineCreateInfo);
913                     break;
914                 default:
915                     TCU_THROW(InternalError, "Unknown pipeline subset");
916                 }
917             }
918         }
919 
920         VkGraphicsPipelineLibraryFlagsEXT linkedLibrariesFlags = 0;
921 
922         for (auto flag : node.linkedLibraryFlags)
923             linkedLibrariesFlags |= flag;
924 
925         // When pLibraries have any pipeline library with fragment shader state and current pipeline we try to create doesn't,
926         // we need to set a MS info.
927         if ((linkedLibrariesFlags & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) &&
928             !(node.graphicsPipelineLibraryFlags & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) &&
929             (graphicsPipelineCreateInfo.pMultisampleState == DE_NULL))
930         {
931             const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo =
932                 makePipelineMultisampleStateCreateInfo();
933 
934             graphicsPipelineCreateInfo.addState(pipelineMultisampleStateCreateInfo);
935         }
936 
937         if (!m_data.useMaintenance5 && linkedLibrariesFlags != ALL_GRAPHICS_PIPELINE_LIBRARY_FLAGS &&
938             graphicsPipelineLibraryCreateInfo.flags != 0)
939             appendStructurePtrToVulkanChain(&graphicsPipelineCreateInfo.pNext, &graphicsPipelineLibraryCreateInfo);
940 
941         if (linkingInfo.libraryCount != 0)
942         {
943             appendStructurePtrToVulkanChain(&graphicsPipelineCreateInfo.pNext, &linkingInfo);
944             graphicsPipelineCreateInfo.layout = *pipelineLayoutSame;
945         }
946 
947         linkedLibrariesFlags |= node.graphicsPipelineLibraryFlags;
948 
949         // if current pipeline that we try to create and pLibraries have all states of pipelines, we are not allowed to create a pipeline library.
950         if (linkedLibrariesFlags == ALL_GRAPHICS_PIPELINE_LIBRARY_FLAGS)
951         {
952             DE_ASSERT(!buildLibrary);
953             graphicsPipelineCreateInfo.flags &= ~VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
954         }
955 
956         node.pipeline = createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineCreateInfo);
957 
958         if (buildLibrary)
959         {
960             DE_ASSERT(de::inBounds(node.parentIndex, 0, static_cast<int32_t>(runtimePipelineTreeConfiguration.size())));
961 
962             runtimePipelineTreeConfiguration[node.parentIndex].pipelineLibraries.push_back(*node.pipeline);
963             runtimePipelineTreeConfiguration[node.parentIndex].linkedLibraryFlags.push_back(linkedLibrariesFlags);
964         }
965         else
966         {
967             DE_ASSERT(node.parentIndex == -1);
968 
969             rootPipeline = node.pipeline;
970         }
971     }
972 
973     // Queue commands and read results.
974     {
975         const tcu::UVec2 renderSize                      = {RENDER_SIZE_WIDTH, RENDER_SIZE_HEIGHT};
976         const VkRect2D renderArea                        = makeRect2D(renderSize.x(), renderSize.y());
977         const de::MovePtr<BufferWithMemory> vertexBuffer = makeVertexBuffer();
978         const uint32_t vertexCount                       = static_cast<uint32_t>(m_vertexData.size());
979         const VkDeviceSize vertexBufferOffset            = 0;
980         const Vec4 colorClearColor(0.0f, 0.0f, 0.0f, 1.0f);
981         const VkImageCreateInfo colorImageCreateInfo =
982             makeColorImageCreateInfo(colorFormat, renderSize.x(), renderSize.y());
983         const ImageWithMemory colorImage(vk, device, allocator, colorImageCreateInfo, MemoryRequirement::Any);
984         const VkImageViewCreateInfo colorImageViewCreateInfo = makeImageViewCreateInfo(
985             *colorImage, colorFormat, static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_COLOR_BIT));
986         const Move<VkImageView> colorImageView = createImageView(vk, device, &colorImageViewCreateInfo);
987         const VkImageCreateInfo depthImageCreateInfo =
988             makeDepthImageCreateInfo(depthFormat, renderSize.x(), renderSize.y());
989         const ImageWithMemory depthImage(vk, device, allocator, depthImageCreateInfo, MemoryRequirement::Any);
990         const VkImageViewCreateInfo depthImageViewCreateInfo = makeImageViewCreateInfo(
991             *depthImage, depthFormat, static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_DEPTH_BIT));
992         const Move<VkImageView> depthImageView = createImageView(vk, device, &depthImageViewCreateInfo);
993         const float depthClearDepth            = 1.0f;
994         const uint32_t depthClearStencil       = 0u;
995         const VkDeviceSize colorBufferDataSize =
996             static_cast<VkDeviceSize>(renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)));
997         const VkBufferCreateInfo colorBufferCreateInfo = makeBufferCreateInfo(
998             colorBufferDataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
999         const BufferWithMemory colorBuffer(vk, device, allocator, colorBufferCreateInfo,
1000                                            MemoryRequirement::HostVisible);
1001         const VkDeviceSize depthBufferDataSize =
1002             static_cast<VkDeviceSize>(renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(depthFormat)));
1003         const VkBufferCreateInfo depthBufferCreateInfo = makeBufferCreateInfo(
1004             depthBufferDataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1005         const BufferWithMemory depthBuffer(vk, device, allocator, depthBufferCreateInfo,
1006                                            MemoryRequirement::HostVisible);
1007         const VkImageView attachments[]                     = {*colorImageView, *depthImageView};
1008         const VkFramebufferCreateInfo framebufferCreateInfo = makeFramebufferCreateInfo(
1009             *renderPass, DE_LENGTH_OF_ARRAY(attachments), attachments, renderSize.x(), renderSize.y());
1010         const Move<VkFramebuffer> framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
1011 
1012         vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
1013         {
1014             beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, colorClearColor, depthClearDepth,
1015                             depthClearStencil);
1016             {
1017                 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer->get(), &vertexBufferOffset);
1018                 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *rootPipeline);
1019                 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutSame, 0u, 2u,
1020                                          vecDescriptorSetBoth, 0u, DE_NULL);
1021                 vk.cmdDraw(*cmdBuffer, vertexCount, 1u, 0u, 0u);
1022             }
1023             endRenderPass(vk, *cmdBuffer);
1024 
1025             const tcu::IVec2 size = {(int32_t)renderSize.x(), (int32_t)renderSize.y()};
1026             copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, size);
1027             copyImageToBuffer(vk, *cmdBuffer, *depthImage, *depthBuffer, size,
1028                               VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1029                               VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1u, VK_IMAGE_ASPECT_DEPTH_BIT,
1030                               VK_IMAGE_ASPECT_DEPTH_BIT);
1031         }
1032         vk::endCommandBuffer(vk, *cmdBuffer);
1033         vk::submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), cmdBuffer.get());
1034 
1035         vk::invalidateAlloc(vk, device, colorBuffer.getAllocation());
1036         vk::invalidateAlloc(vk, device, depthBuffer.getAllocation());
1037 
1038         const tcu::ConstPixelBufferAccess colorPixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1,
1039                                                            colorBuffer.getAllocation().getHostPtr());
1040         const tcu::ConstPixelBufferAccess depthPixelAccess(mapVkFormat(depthFormat), renderSize.x(), renderSize.y(), 1,
1041                                                            depthBuffer.getAllocation().getHostPtr());
1042 
1043         if (!verifyColorImage(colorPixelAccess))
1044         {
1045             log << tcu::TestLog::Image("color", "Rendered image", colorPixelAccess);
1046 
1047             return false;
1048         }
1049 
1050         if (!verifyDepthImage(depthPixelAccess))
1051         {
1052             log << tcu::TestLog::Image("depth", "Rendered image", depthPixelAccess);
1053 
1054             return false;
1055         }
1056     }
1057 
1058     return true;
1059 }
1060 
verifyColorImage(const ConstPixelBufferAccess & pba)1061 bool PipelineLibraryTestInstance::verifyColorImage(const ConstPixelBufferAccess &pba)
1062 {
1063     tcu::TestLog &log = m_context.getTestContext().getLog();
1064     TextureLevel referenceImage(pba.getFormat(), pba.getWidth(), pba.getHeight());
1065     PixelBufferAccess reference(referenceImage);
1066     const int horzEdge = 3 * reference.getWidth() / 4;
1067     const int vertEdge = reference.getHeight() / 2;
1068     const UVec4 green  = ivec2uvec(RGBA::green().toIVec());
1069     const UVec4 blue   = ivec2uvec(RGBA::blue().toIVec());
1070     const UVec4 black  = ivec2uvec(RGBA::black().toIVec());
1071 
1072     for (int y = 0; y < reference.getHeight(); ++y)
1073     {
1074         for (int x = 0; x < reference.getWidth(); ++x)
1075         {
1076             if (x < horzEdge)
1077             {
1078                 if (y < vertEdge)
1079                     reference.setPixel(green, x, y);
1080                 else
1081                     reference.setPixel(blue, x, y);
1082             }
1083             else
1084                 reference.setPixel(black, x, y);
1085         }
1086     }
1087 
1088     return intThresholdCompare(log, "colorImage", "colorImage", reference, pba, UVec4(), COMPARE_LOG_RESULT);
1089 }
1090 
verifyDepthImage(const ConstPixelBufferAccess & pba)1091 bool PipelineLibraryTestInstance::verifyDepthImage(const ConstPixelBufferAccess &pba)
1092 {
1093     tcu::TestLog &log            = m_context.getTestContext().getLog();
1094     const VkFormat compareFormat = VK_FORMAT_R8_UNORM;
1095     TextureLevel referenceImage(mapVkFormat(compareFormat), pba.getWidth(), pba.getHeight());
1096     PixelBufferAccess reference(referenceImage);
1097     TextureLevel resultImage(mapVkFormat(compareFormat), pba.getWidth(), pba.getHeight());
1098     PixelBufferAccess result(resultImage);
1099     const int horzEdge     = 3 * reference.getWidth() / 4;
1100     const int diagonalEdge = (reference.getWidth() + reference.getHeight()) / 2 - 1;
1101     const UVec4 red100     = ivec2uvec(RGBA::red().toIVec());
1102     const UVec4 red025     = UVec4(red100[0] / 4, red100[1] / 4, red100[2] / 4, red100[3]);
1103     const UVec4 red075     = UVec4(3 * red100[0] / 4, 3 * red100[1] / 4, 3 * red100[2] / 4, red100[3]);
1104 
1105     for (int y = 0; y < result.getHeight(); ++y)
1106         for (int x = 0; x < result.getWidth(); ++x)
1107         {
1108             const UVec4 pix(static_cast<uint32_t>(static_cast<float>(red100[0]) * pba.getPixDepth(x, y)), 0, 0, 0);
1109 
1110             result.setPixel(pix, x, y);
1111         }
1112 
1113     for (int y = 0; y < reference.getHeight(); ++y)
1114     {
1115         for (int x = 0; x < reference.getWidth(); ++x)
1116         {
1117             if (x < horzEdge)
1118             {
1119                 if (x + y < diagonalEdge)
1120                     reference.setPixel(red025, x, y);
1121                 else
1122                     reference.setPixel(red075, x, y);
1123             }
1124             else
1125                 reference.setPixel(red100, x, y);
1126         }
1127     }
1128 
1129     return intThresholdCompare(log, "depthImage", "depthImage", reference, result, UVec4(), COMPARE_LOG_RESULT);
1130 }
1131 
iterate(void)1132 tcu::TestStatus PipelineLibraryTestInstance::iterate(void)
1133 {
1134     VkGraphicsPipelineLibraryFlagBitsEXT graphicsPipelineLibraryFlags[] = {
1135         VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT,
1136         VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT,
1137         VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT,
1138         VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT,
1139     };
1140     const auto graphicsPipelineLibraryFlagsBegin = graphicsPipelineLibraryFlags;
1141     const auto graphicsPipelineLibraryFlagsEnd =
1142         graphicsPipelineLibraryFlags + DE_LENGTH_OF_ARRAY(graphicsPipelineLibraryFlags);
1143     uint32_t permutationId = 0;
1144     std::set<uint32_t> was;
1145     bool result = true;
1146 
1147     do
1148     {
1149         RuntimePipelineTreeConfiguration runtimePipelineTreeConfiguration(m_data.pipelineTreeConfiguration.size());
1150         size_t subsetNdxStart         = 0;
1151         uint32_t uniqueTreeSubsetCode = 0;
1152 
1153         for (size_t nodeNdx = 0; nodeNdx < runtimePipelineTreeConfiguration.size(); ++nodeNdx)
1154         {
1155             const uint32_t shaderCount    = m_data.pipelineTreeConfiguration[nodeNdx].shaderCount;
1156             RuntimePipelineTreeNode &node = runtimePipelineTreeConfiguration[nodeNdx];
1157 
1158             node.parentIndex                  = m_data.pipelineTreeConfiguration[nodeNdx].parentIndex;
1159             node.graphicsPipelineLibraryFlags = 0u;
1160 
1161             for (size_t subsetNdx = 0; subsetNdx < shaderCount; ++subsetNdx)
1162                 node.graphicsPipelineLibraryFlags |= static_cast<VkGraphicsPipelineLibraryFlagsEXT>(
1163                     graphicsPipelineLibraryFlags[subsetNdxStart + subsetNdx]);
1164 
1165             if (node.parentIndex > 0)
1166                 runtimePipelineTreeConfiguration[node.parentIndex].subtreeGraphicsPipelineLibraryFlags |=
1167                     node.graphicsPipelineLibraryFlags;
1168 
1169             // Each shader subset should be tested in each node of tree
1170             subsetNdxStart += shaderCount;
1171 
1172             uniqueTreeSubsetCode = (uniqueTreeSubsetCode << 4) | node.graphicsPipelineLibraryFlags;
1173         }
1174 
1175         // Check whether this configuration has been tried
1176         if (was.find(uniqueTreeSubsetCode) == was.end())
1177             was.insert(uniqueTreeSubsetCode);
1178         else
1179             continue;
1180 
1181         result = result && runTest(runtimePipelineTreeConfiguration, m_data.optimize, m_data.delayedShaderCreate);
1182 
1183         if (!result)
1184         {
1185             tcu::TestLog &log = m_context.getTestContext().getLog();
1186             std::ostringstream ess;
1187 
1188             for (size_t nodeNdx = 0; nodeNdx < runtimePipelineTreeConfiguration.size(); ++nodeNdx)
1189             {
1190                 const RuntimePipelineTreeNode &node = runtimePipelineTreeConfiguration[nodeNdx];
1191 
1192                 ess << node.parentIndex << " {";
1193 
1194                 for (size_t subsetNdx = 0; subsetNdx < DE_LENGTH_OF_ARRAY(graphicsPipelineLibraryFlags); ++subsetNdx)
1195                 {
1196                     if ((node.graphicsPipelineLibraryFlags & graphicsPipelineLibraryFlags[subsetNdx]) == 0)
1197                         continue;
1198 
1199                     ess << getGraphicsPipelineLibraryFlagsString(graphicsPipelineLibraryFlags[subsetNdx]) << " ";
1200                 }
1201 
1202                 ess << "}" << std::endl;
1203             }
1204 
1205             log << tcu::TestLog::Message << ess.str() << tcu::TestLog::EndMessage;
1206 
1207             return tcu::TestStatus::fail("At permutation " + de::toString(permutationId));
1208         }
1209 
1210         ++permutationId;
1211     } while (std::next_permutation(graphicsPipelineLibraryFlagsBegin, graphicsPipelineLibraryFlagsEnd));
1212 
1213     return tcu::TestStatus::pass("OK");
1214 }
1215 
1216 class PipelineLibraryTestCase : public TestCase
1217 {
1218 public:
1219     PipelineLibraryTestCase(tcu::TestContext &context, const char *name, const TestParams data);
1220     ~PipelineLibraryTestCase(void);
1221 
1222     virtual void checkSupport(Context &context) const;
1223     virtual void initPrograms(SourceCollections &programCollection) const;
1224     virtual TestInstance *createInstance(Context &context) const;
1225 
1226 private:
1227     TestParams m_data;
1228 };
1229 
PipelineLibraryTestCase(tcu::TestContext & context,const char * name,const TestParams data)1230 PipelineLibraryTestCase::PipelineLibraryTestCase(tcu::TestContext &context, const char *name, const TestParams data)
1231     : vkt::TestCase(context, name)
1232     , m_data(data)
1233 {
1234 }
1235 
~PipelineLibraryTestCase(void)1236 PipelineLibraryTestCase::~PipelineLibraryTestCase(void)
1237 {
1238 }
1239 
checkSupport(Context & context) const1240 void PipelineLibraryTestCase::checkSupport(Context &context) const
1241 {
1242     if (m_data.useMaintenance5)
1243     {
1244         context.requireDeviceFunctionality("VK_KHR_maintenance5");
1245         return;
1246     }
1247 
1248     context.requireDeviceFunctionality("VK_KHR_pipeline_library");
1249 
1250     if (m_data.delayedShaderCreate || (m_data.pipelineTreeConfiguration.size() > 1))
1251     {
1252         context.requireDeviceFunctionality("VK_EXT_graphics_pipeline_library");
1253 
1254         const VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT &graphicsPipelineLibraryFeaturesEXT =
1255             context.getGraphicsPipelineLibraryFeaturesEXT();
1256 
1257         if (!graphicsPipelineLibraryFeaturesEXT.graphicsPipelineLibrary)
1258             TCU_THROW(NotSupportedError, "graphicsPipelineLibraryFeaturesEXT.graphicsPipelineLibrary required");
1259     }
1260 }
1261 
initPrograms(SourceCollections & programCollection) const1262 void PipelineLibraryTestCase::initPrograms(SourceCollections &programCollection) const
1263 {
1264     std::string vert = "#version 450\n"
1265                        "layout(location = 0) in vec4 in_position;\n"
1266                        "layout(set = 0, binding = 0) uniform buf\n"
1267                        "{\n"
1268                        "  vec4 z_coord;\n"
1269                        "};\n"
1270                        "\n"
1271                        "out gl_PerVertex\n"
1272                        "{\n"
1273                        "  vec4 gl_Position;\n"
1274                        "};\n"
1275                        "\n"
1276                        "void main()\n"
1277                        "{\n"
1278                        "  const float z = gl_VertexIndex < 3 ? z_coord.x : z_coord.y;\n"
1279                        "  gl_Position = vec4(in_position.x, in_position.y, z, 1.0f);\n"
1280                        "}\n";
1281 
1282     programCollection.glslSources.add("vert") << glu::VertexSource(vert);
1283 
1284     std::string frag = "#version 450\n"
1285                        "layout(location = 0) out highp vec4 o_color;\n"
1286                        "layout(set = 1, binding = 1) uniform buf\n"
1287                        "{\n"
1288                        "  vec4 colorTop;\n"
1289                        "  vec4 colorBot;\n"
1290                        "};\n"
1291                        "\n"
1292                        "void main()\n"
1293                        "{\n"
1294                        "  const int middle = " +
1295                        de::toString(RENDER_SIZE_HEIGHT / 2) +
1296                        ";\n"
1297                        "  o_color          = int(gl_FragCoord.y - 0.5f) < middle ? colorTop : colorBot;\n"
1298                        "}\n";
1299 
1300     programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
1301 }
1302 
createInstance(Context & context) const1303 TestInstance *PipelineLibraryTestCase::createInstance(Context &context) const
1304 {
1305     return new PipelineLibraryTestInstance(context, m_data);
1306 }
1307 
1308 enum class MiscTestMode
1309 {
1310     INDEPENDENT_PIPELINE_LAYOUT_SETS_FAST_LINKED = 0,
1311     INDEPENDENT_PIPELINE_LAYOUT_SETS_WITH_LINK_TIME_OPTIMIZATION_UNION_HANDLE,
1312     BIND_NULL_DESCRIPTOR_SET,
1313     BIND_NULL_DESCRIPTOR_SET_IN_MONOLITHIC_PIPELINE,
1314     COMPARE_LINK_TIMES,
1315     SHADER_MODULE_CREATE_INFO_COMP,
1316     SHADER_MODULE_CREATE_INFO_RT,
1317     SHADER_MODULE_CREATE_INFO_RT_LIB,
1318     NULL_RENDERING_CREATE_INFO,
1319 };
1320 
1321 struct MiscTestParams
1322 {
1323     MiscTestMode mode;
1324 
1325     // attributes used in BIND_NULL_DESCRIPTOR_SET mode
1326     uint32_t layoutsCount;
1327     uint32_t layoutsBits;
1328 };
1329 
1330 class PipelineLibraryMiscTestInstance : public TestInstance
1331 {
1332 public:
1333     PipelineLibraryMiscTestInstance(Context &context, const MiscTestParams &params);
1334     ~PipelineLibraryMiscTestInstance(void) = default;
1335     tcu::TestStatus iterate(void);
1336 
1337 protected:
1338     tcu::TestStatus runNullDescriptorSet(void);
1339     tcu::TestStatus runNullDescriptorSetInMonolithicPipeline(void);
1340     tcu::TestStatus runIndependentPipelineLayoutSets(bool useLinkTimeOptimization = false);
1341     tcu::TestStatus runCompareLinkTimes(void);
1342 
1343     struct VerificationData
1344     {
1345         const tcu::IVec2 point;
1346         const tcu::IVec4 color;
1347     };
1348     tcu::TestStatus verifyResult(const std::vector<VerificationData> &verificationData,
1349                                  const tcu::ConstPixelBufferAccess &colorPixelAccess) const;
1350 
1351 private:
1352     MiscTestParams m_testParams;
1353     const VkFormat m_colorFormat;
1354     const Vec4 m_colorClearColor;
1355     const VkRect2D m_renderArea;
1356 
1357     de::MovePtr<ImageWithMemory> m_colorImage;
1358     Move<VkImageView> m_colorImageView;
1359 
1360     Move<VkRenderPass> m_renderPass;
1361     Move<VkFramebuffer> m_framebuffer;
1362 
1363     Move<VkCommandPool> m_cmdPool;
1364     Move<VkCommandBuffer> m_cmdBuffer;
1365 };
1366 
PipelineLibraryMiscTestInstance(Context & context,const MiscTestParams & params)1367 PipelineLibraryMiscTestInstance::PipelineLibraryMiscTestInstance(Context &context, const MiscTestParams &params)
1368     : vkt::TestInstance(context)
1369     , m_testParams(params)
1370     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
1371     , m_colorClearColor(0.0f, 0.0f, 0.0f, 1.0f)
1372     , m_renderArea(makeRect2D(RENDER_SIZE_WIDTH, RENDER_SIZE_HEIGHT))
1373 {
1374 }
1375 
iterate(void)1376 tcu::TestStatus PipelineLibraryMiscTestInstance::iterate(void)
1377 {
1378     const DeviceInterface &vk = m_context.getDeviceInterface();
1379     const VkDevice device     = m_context.getDevice();
1380     Allocator &allocator      = m_context.getDefaultAllocator();
1381 
1382     // create image and image view that will hold rendered frame
1383     const VkImageCreateInfo colorImageCreateInfo =
1384         makeColorImageCreateInfo(m_colorFormat, m_renderArea.extent.width, m_renderArea.extent.height);
1385     m_colorImage = de::MovePtr<ImageWithMemory>(
1386         new ImageWithMemory(vk, device, allocator, colorImageCreateInfo, MemoryRequirement::Any));
1387     const VkImageViewCreateInfo colorImageViewCreateInfo = makeImageViewCreateInfo(
1388         **m_colorImage, m_colorFormat, static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_COLOR_BIT));
1389     const Move<VkImageView> colorImageView = createImageView(vk, device, &colorImageViewCreateInfo);
1390 
1391     // create renderpass and framebuffer
1392     m_renderPass                                        = makeRenderPass(vk, device, m_colorFormat);
1393     const VkFramebufferCreateInfo framebufferCreateInfo = makeFramebufferCreateInfo(
1394         *m_renderPass, 1u, &*colorImageView, m_renderArea.extent.width, m_renderArea.extent.height);
1395     m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
1396 
1397     // create command pool and command buffer
1398     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1399     m_cmdPool   = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
1400     m_cmdBuffer = allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1401 
1402     // run selected test
1403     if (m_testParams.mode == MiscTestMode::BIND_NULL_DESCRIPTOR_SET)
1404         return runNullDescriptorSet();
1405     else if (m_testParams.mode == MiscTestMode::BIND_NULL_DESCRIPTOR_SET_IN_MONOLITHIC_PIPELINE)
1406         return runNullDescriptorSetInMonolithicPipeline();
1407     else if (m_testParams.mode == MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_FAST_LINKED)
1408         return runIndependentPipelineLayoutSets();
1409     else if (m_testParams.mode ==
1410              MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_WITH_LINK_TIME_OPTIMIZATION_UNION_HANDLE)
1411         return runIndependentPipelineLayoutSets(true);
1412     else if (m_testParams.mode == MiscTestMode::COMPARE_LINK_TIMES)
1413         return runCompareLinkTimes();
1414 
1415     DE_ASSERT(false);
1416     return tcu::TestStatus::fail("Fail");
1417 }
1418 
runNullDescriptorSet(void)1419 tcu::TestStatus PipelineLibraryMiscTestInstance::runNullDescriptorSet(void)
1420 {
1421     const DeviceInterface &vk = m_context.getDeviceInterface();
1422     const VkDevice device     = m_context.getDevice();
1423     Allocator &allocator      = m_context.getDefaultAllocator();
1424 
1425     const VkDeviceSize colorBufferDataSize = static_cast<VkDeviceSize>(
1426         m_renderArea.extent.width * m_renderArea.extent.height * tcu::getPixelSize(mapVkFormat(m_colorFormat)));
1427     const VkBufferCreateInfo colorBufferCreateInfo = makeBufferCreateInfo(
1428         colorBufferDataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1429     const BufferWithMemory colorBuffer(vk, device, allocator, colorBufferCreateInfo, MemoryRequirement::HostVisible);
1430 
1431     VkDeviceSize uniformBufferDataSize = sizeof(tcu::Vec4);
1432     const VkBufferCreateInfo uniformBufferCreateInfo =
1433         makeBufferCreateInfo(uniformBufferDataSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1434     de::MovePtr<BufferWithMemory> uniformBuffer[2];
1435 
1436     // setup data in uniform buffers that will give us expected result for validation
1437     const tcu::Vec4 uniformBuffData[]{
1438         {-1.00f, 1.00f, 2.0f, -2.00f},
1439         {0.00f, 0.20f, 0.6f, 0.75f},
1440     };
1441 
1442     for (uint32_t i = 0; i < 2; ++i)
1443     {
1444         uniformBuffer[i] = de::MovePtr<BufferWithMemory>(
1445             new BufferWithMemory(vk, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
1446         deMemcpy(uniformBuffer[i]->getAllocation().getHostPtr(), uniformBuffData[i].getPtr(),
1447                  (size_t)uniformBufferDataSize);
1448         flushAlloc(vk, device, uniformBuffer[i]->getAllocation());
1449     }
1450 
1451     const uint32_t maxBitsCount = 8 * sizeof(m_testParams.layoutsBits);
1452     VkDescriptorSetLayout vertDescriptorSetLayouts[maxBitsCount];
1453     VkDescriptorSetLayout fragDescriptorSetLayouts[maxBitsCount];
1454     VkDescriptorSetLayout allDescriptorSetLayouts[maxBitsCount];
1455 
1456     // set all layouts to NULL
1457     deMemset(&vertDescriptorSetLayouts, DE_NULL, maxBitsCount * sizeof(VkDescriptorSetLayout));
1458     deMemset(&fragDescriptorSetLayouts, DE_NULL, maxBitsCount * sizeof(VkDescriptorSetLayout));
1459 
1460     // create used descriptor set layouts
1461     Move<VkDescriptorSetLayout> usedDescriptorSetLayouts[]{
1462         DescriptorSetLayoutBuilder()
1463             .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT)
1464             .build(vk, device),
1465         DescriptorSetLayoutBuilder()
1466             .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
1467             .build(vk, device)};
1468 
1469     // create descriptor set layouts that are not used by shaders in test - finalPipelineLayout,
1470     // needs to always be the complete pipeline layout with no holes; we can put NULLs in
1471     // DescriptorSetLayouts used by partial pipelines (vertDescriptorSetLayouts and fragDescriptorSetLayouts)
1472     Move<VkDescriptorSetLayout> unusedDescriptorSetLayouts[maxBitsCount];
1473     for (uint32_t i = 0u; i < m_testParams.layoutsCount; ++i)
1474     {
1475         unusedDescriptorSetLayouts[i] = DescriptorSetLayoutBuilder().build(vk, device);
1476 
1477         // by default allDescriptorSetLayouts is filled with unused layouts but later
1478         // if test requires this proper indexes are replaced with used layouts
1479         allDescriptorSetLayouts[i] = *unusedDescriptorSetLayouts[i];
1480     }
1481 
1482     VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = initVulkanStructure();
1483     pipelineLayoutCreateInfo.flags                      = VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT;
1484 
1485     // find set bits
1486     std::vector<uint32_t> bitsThatAreSet;
1487     for (uint32_t i = 0u; i < m_testParams.layoutsCount; ++i)
1488     {
1489         if (m_testParams.layoutsBits & (1 << (maxBitsCount - 1 - i)))
1490             bitsThatAreSet.push_back(i);
1491     }
1492 
1493     uint32_t usedDescriptorSets = static_cast<uint32_t>(bitsThatAreSet.size());
1494     DE_ASSERT(usedDescriptorSets && (usedDescriptorSets < 3u));
1495 
1496     uint32_t vertSetIndex                   = bitsThatAreSet[0];
1497     uint32_t fragSetIndex                   = 0u;
1498     vertDescriptorSetLayouts[vertSetIndex]  = *usedDescriptorSetLayouts[0];
1499     allDescriptorSetLayouts[vertSetIndex]   = *usedDescriptorSetLayouts[0];
1500     pipelineLayoutCreateInfo.setLayoutCount = vertSetIndex + 1u;
1501     pipelineLayoutCreateInfo.pSetLayouts    = vertDescriptorSetLayouts;
1502 
1503     Move<VkPipelineLayout> vertPipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1504     Move<VkPipelineLayout> fragPipelineLayout;
1505 
1506     if (usedDescriptorSets == 2u)
1507     {
1508         fragSetIndex                            = bitsThatAreSet[1];
1509         fragDescriptorSetLayouts[fragSetIndex]  = *usedDescriptorSetLayouts[1];
1510         allDescriptorSetLayouts[fragSetIndex]   = *usedDescriptorSetLayouts[1];
1511         pipelineLayoutCreateInfo.setLayoutCount = fragSetIndex + 1u;
1512         pipelineLayoutCreateInfo.pSetLayouts    = fragDescriptorSetLayouts;
1513 
1514         fragPipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1515     }
1516     else
1517     {
1518         pipelineLayoutCreateInfo.setLayoutCount = 0u;
1519         pipelineLayoutCreateInfo.pSetLayouts    = DE_NULL;
1520         fragPipelineLayout                      = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1521     }
1522 
1523     // create descriptor pool
1524     Move<VkDescriptorPool> descriptorPool =
1525         DescriptorPoolBuilder()
1526             .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, usedDescriptorSets)
1527             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, usedDescriptorSets);
1528 
1529     const VkDescriptorBufferInfo vertShaderBufferInfo =
1530         makeDescriptorBufferInfo(**uniformBuffer[0], 0u, uniformBufferDataSize);
1531     Move<VkDescriptorSet> vertDescriptorSet =
1532         makeDescriptorSet(vk, device, *descriptorPool, *usedDescriptorSetLayouts[0]);
1533     Move<VkDescriptorSet> fragDescriptorSet;
1534 
1535     if (usedDescriptorSets == 1u)
1536     {
1537         // update single descriptors with actual buffer
1538         DescriptorSetUpdateBuilder()
1539             .writeSingle(*vertDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1540                          VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &vertShaderBufferInfo)
1541             .update(vk, device);
1542     }
1543     else
1544     {
1545         const VkDescriptorBufferInfo fragShaderBufferInfo =
1546             makeDescriptorBufferInfo(**uniformBuffer[1], 0u, uniformBufferDataSize);
1547         fragDescriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *usedDescriptorSetLayouts[1]);
1548 
1549         // update both descriptors with actual buffers
1550         DescriptorSetUpdateBuilder()
1551             .writeSingle(*vertDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1552                          VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &vertShaderBufferInfo)
1553             .writeSingle(*fragDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1554                          VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &fragShaderBufferInfo)
1555             .update(vk, device);
1556     }
1557 
1558     pipelineLayoutCreateInfo.setLayoutCount    = m_testParams.layoutsCount;
1559     pipelineLayoutCreateInfo.pSetLayouts       = allDescriptorSetLayouts;
1560     Move<VkPipelineLayout> finalPipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1561 
1562     const uint32_t commonPipelinePartFlags = uint32_t(VK_PIPELINE_CREATE_LIBRARY_BIT_KHR);
1563     GraphicsPipelineCreateInfo partialPipelineCreateInfo[]{
1564         {*vertPipelineLayout, *m_renderPass, 0, commonPipelinePartFlags},
1565         {*fragPipelineLayout, *m_renderPass, 0, commonPipelinePartFlags},
1566     };
1567 
1568     // fill proper portion of pipeline state
1569     updateVertexInputInterface(m_context, partialPipelineCreateInfo[0], VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0u);
1570     updatePreRasterization(m_context, partialPipelineCreateInfo[0], false);
1571     updatePostRasterization(m_context, partialPipelineCreateInfo[1], false);
1572     updateFragmentOutputInterface(m_context, partialPipelineCreateInfo[1]);
1573 
1574     Move<VkPipeline> vertPipelinePart;
1575     Move<VkPipeline> fragPipelinePart;
1576 
1577     // extend pNext chain and create partial pipelines
1578     {
1579         VkGraphicsPipelineLibraryCreateInfoEXT libraryCreateInfo =
1580             makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT |
1581                                                   VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT);
1582         appendStructurePtrToVulkanChain(&partialPipelineCreateInfo[0].pNext, &libraryCreateInfo);
1583         vertPipelinePart = createGraphicsPipeline(vk, device, DE_NULL, &partialPipelineCreateInfo[0]);
1584 
1585         libraryCreateInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT |
1586                                   VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT,
1587         appendStructurePtrToVulkanChain(&partialPipelineCreateInfo[1].pNext, &libraryCreateInfo);
1588         fragPipelinePart = createGraphicsPipeline(vk, device, DE_NULL, &partialPipelineCreateInfo[1]);
1589     }
1590 
1591     // create final pipeline out of two parts
1592     std::vector<VkPipeline> rawParts               = {*vertPipelinePart, *fragPipelinePart};
1593     VkPipelineLibraryCreateInfoKHR linkingInfo     = makePipelineLibraryCreateInfo(rawParts);
1594     VkGraphicsPipelineCreateInfo finalPipelineInfo = initVulkanStructure();
1595 
1596     finalPipelineInfo.layout = *finalPipelineLayout;
1597     appendStructurePtrToVulkanChain(&finalPipelineInfo.pNext, &linkingInfo);
1598     Move<VkPipeline> pipeline = createGraphicsPipeline(vk, device, DE_NULL, &finalPipelineInfo);
1599 
1600     vk::beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1601     {
1602         // change color image layout
1603         const VkImageMemoryBarrier initialImageBarrier = makeImageMemoryBarrier(
1604             0,                                          // VkAccessFlags srcAccessMask;
1605             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,       // VkAccessFlags dstAccessMask;
1606             VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout oldLayout;
1607             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout newLayout;
1608             **m_colorImage,                             // VkImage image;
1609             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
1610         );
1611         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1612                               VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, DE_NULL, 0,
1613                               DE_NULL, 1, &initialImageBarrier);
1614 
1615         // wait for uniform buffers
1616         std::vector<VkBufferMemoryBarrier> initialBufferBarriers(
1617             2u, makeBufferMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT,    // VkAccessFlags2KHR                srcAccessMask
1618                                         VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags2KHR                dstAccessMask
1619                                         uniformBuffer[0]->get(),     // VkBuffer                            buffer
1620                                         0u,                          // VkDeviceSize                        offset
1621                                         uniformBufferDataSize        // VkDeviceSize                        size
1622                                         ));
1623         initialBufferBarriers[1].buffer = uniformBuffer[1]->get();
1624         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1625                               (VkDependencyFlags)0, 0, DE_NULL, 2, initialBufferBarriers.data(), 0, DE_NULL);
1626 
1627         beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, m_renderArea, m_colorClearColor);
1628 
1629         vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1630 
1631         vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *finalPipelineLayout, vertSetIndex, 1u,
1632                                  &*vertDescriptorSet, 0u, DE_NULL);
1633         if (usedDescriptorSets == 2u)
1634             vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *finalPipelineLayout, fragSetIndex,
1635                                      1u, &*fragDescriptorSet, 0u, DE_NULL);
1636 
1637         vk.cmdDraw(*m_cmdBuffer, 4, 1u, 0u, 0u);
1638 
1639         endRenderPass(vk, *m_cmdBuffer);
1640 
1641         const tcu::IVec2 size{(int32_t)m_renderArea.extent.width, (int32_t)m_renderArea.extent.height};
1642         copyImageToBuffer(vk, *m_cmdBuffer, **m_colorImage, *colorBuffer, size);
1643     }
1644     vk::endCommandBuffer(vk, *m_cmdBuffer);
1645     vk::submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *m_cmdBuffer);
1646 
1647     vk::invalidateAlloc(vk, device, colorBuffer.getAllocation());
1648     const tcu::ConstPixelBufferAccess colorPixelAccess(mapVkFormat(m_colorFormat), m_renderArea.extent.width,
1649                                                        m_renderArea.extent.height, 1,
1650                                                        colorBuffer.getAllocation().getHostPtr());
1651 
1652     // verify result
1653     int32_t width  = (int32_t)m_renderArea.extent.width;
1654     int32_t height = (int32_t)m_renderArea.extent.height;
1655     const std::vector<VerificationData> verificationData{
1656         {{1, 1}, {0, 51, 153, 191}}, // note COLOR_COMPONENTS_NO_RED is used
1657         {{width / 2, height / 2}, {0, 51, 153, 191}},
1658         {{width - 2, height - 2}, {0, 0, 0, 255}} // clear color
1659     };
1660     return verifyResult(verificationData, colorPixelAccess);
1661 }
1662 
runNullDescriptorSetInMonolithicPipeline()1663 tcu::TestStatus PipelineLibraryMiscTestInstance::runNullDescriptorSetInMonolithicPipeline()
1664 {
1665     // VK_NULL_HANDLE can be used for descriptor set layouts when creating a pipeline layout whether independent sets are used or not,
1666     // as long as graphics pipeline libraries are enabled; VK_NULL_HANDLE is also alowed for a descriptor set under the same conditions
1667     // when using vkCmdBindDescriptorSets
1668 
1669     const DeviceInterface &vk = m_context.getDeviceInterface();
1670     const VkDevice device     = m_context.getDevice();
1671     Allocator &allocator      = m_context.getDefaultAllocator();
1672 
1673     const VkDeviceSize colorBufferDataSize = static_cast<VkDeviceSize>(
1674         m_renderArea.extent.width * m_renderArea.extent.height * tcu::getPixelSize(mapVkFormat(m_colorFormat)));
1675     const VkBufferCreateInfo colorBufferCreateInfo = makeBufferCreateInfo(
1676         colorBufferDataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1677     const BufferWithMemory colorBuffer(vk, device, allocator, colorBufferCreateInfo, MemoryRequirement::HostVisible);
1678 
1679     const tcu::Vec4 uniformBuffData{0.0f, 0.20f, 0.6f, 0.75f};
1680     VkDeviceSize uniformBufferDataSize = sizeof(tcu::Vec4);
1681     const VkBufferCreateInfo uniformBufferCreateInfo =
1682         makeBufferCreateInfo(uniformBufferDataSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1683 
1684     de::MovePtr<BufferWithMemory> uniformBuffer = de::MovePtr<BufferWithMemory>(
1685         new BufferWithMemory(vk, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
1686     deMemcpy(uniformBuffer->getAllocation().getHostPtr(), uniformBuffData.getPtr(), (size_t)uniformBufferDataSize);
1687     flushAlloc(vk, device, uniformBuffer->getAllocation());
1688 
1689     // create descriptor set layouts - first unused, second used
1690     Move<VkDescriptorSetLayout> descriptorSetLayout{
1691         DescriptorSetLayoutBuilder()
1692             .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
1693             .build(vk, device)};
1694 
1695     Move<VkDescriptorPool> allDescriptorPool =
1696         DescriptorPoolBuilder()
1697             .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1)
1698             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
1699 
1700     // create descriptor set
1701     Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *allDescriptorPool, *descriptorSetLayout);
1702 
1703     // update descriptor with actual buffer
1704     const VkDescriptorBufferInfo shaderBufferInfo =
1705         makeDescriptorBufferInfo(**uniformBuffer, 0u, uniformBufferDataSize);
1706     DescriptorSetUpdateBuilder()
1707         .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1708                      VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &shaderBufferInfo)
1709         .update(vk, device);
1710 
1711     // create a pipeline layout with its first descriptor set layout as VK_NULL_HANDLE
1712     // and a second with a valid descriptor set layout containing a buffer
1713     VkDescriptorSet rawDescriptorSets[]             = {DE_NULL, *descriptorSet};
1714     VkDescriptorSetLayout rawDescriptorSetLayouts[] = {DE_NULL, *descriptorSetLayout};
1715 
1716     VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = initVulkanStructure();
1717     pipelineLayoutCreateInfo.setLayoutCount             = 2u;
1718     pipelineLayoutCreateInfo.pSetLayouts                = rawDescriptorSetLayouts;
1719     Move<VkPipelineLayout> pipelineLayout               = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1720 
1721     // create monolithic graphics pipeline
1722     GraphicsPipelineCreateInfo pipelineCreateInfo(*pipelineLayout, *m_renderPass, 0, 0u);
1723     updateVertexInputInterface(m_context, pipelineCreateInfo, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0u);
1724     updatePreRasterization(m_context, pipelineCreateInfo, false);
1725     updatePostRasterization(m_context, pipelineCreateInfo, false);
1726     updateFragmentOutputInterface(m_context, pipelineCreateInfo);
1727     Move<VkPipeline> pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
1728 
1729     vk::beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1730     {
1731         // change color image layout
1732         const VkImageMemoryBarrier initialImageBarrier = makeImageMemoryBarrier(
1733             0,                                          // VkAccessFlags srcAccessMask;
1734             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,       // VkAccessFlags dstAccessMask;
1735             VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout oldLayout;
1736             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout newLayout;
1737             **m_colorImage,                             // VkImage image;
1738             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
1739         );
1740         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1741                               VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, DE_NULL, 0,
1742                               DE_NULL, 1, &initialImageBarrier);
1743 
1744         // wait for uniform buffer
1745         const VkBufferMemoryBarrier initialBufferBarrier =
1746             makeBufferMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT,   // VkAccessFlags2KHR                srcAccessMask
1747                                     VK_ACCESS_UNIFORM_READ_BIT, // VkAccessFlags2KHR                dstAccessMask
1748                                     uniformBuffer->get(),       // VkBuffer                            buffer
1749                                     0u,                         // VkDeviceSize                        offset
1750                                     uniformBufferDataSize       // VkDeviceSize                        size
1751             );
1752         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
1753                               (VkDependencyFlags)0, 0, DE_NULL, 1, &initialBufferBarrier, 0, DE_NULL);
1754 
1755         beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, m_renderArea, m_colorClearColor);
1756 
1757         vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1758         vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 2u,
1759                                  rawDescriptorSets, 0u, DE_NULL);
1760         vk.cmdDraw(*m_cmdBuffer, 4, 1u, 0u, 0u);
1761 
1762         endRenderPass(vk, *m_cmdBuffer);
1763 
1764         const tcu::IVec2 size{(int32_t)m_renderArea.extent.width, (int32_t)m_renderArea.extent.height};
1765         copyImageToBuffer(vk, *m_cmdBuffer, **m_colorImage, *colorBuffer, size);
1766     }
1767     vk::endCommandBuffer(vk, *m_cmdBuffer);
1768     vk::submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *m_cmdBuffer);
1769 
1770     vk::invalidateAlloc(vk, device, colorBuffer.getAllocation());
1771     const tcu::ConstPixelBufferAccess colorPixelAccess(mapVkFormat(m_colorFormat), m_renderArea.extent.width,
1772                                                        m_renderArea.extent.height, 1,
1773                                                        colorBuffer.getAllocation().getHostPtr());
1774 
1775     // verify result
1776     int32_t width  = (int32_t)m_renderArea.extent.width;
1777     int32_t height = (int32_t)m_renderArea.extent.height;
1778     tcu::IVec4 outColor{0, // r is 0 because COLOR_COMPONENTS_NO_RED is used
1779                         static_cast<int>(uniformBuffData[1] * 255), static_cast<int>(uniformBuffData[2] * 255),
1780                         static_cast<int>(uniformBuffData[3] * 255)};
1781     const std::vector<VerificationData> verificationData{
1782         {{1, 1}, outColor},
1783         {{width / 2, height / 2}, outColor},
1784         {{width - 2, height - 2}, {0, 0, 0, 255}} // clear color
1785     };
1786 
1787     return verifyResult(verificationData, colorPixelAccess);
1788 }
1789 
runIndependentPipelineLayoutSets(bool useLinkTimeOptimization)1790 tcu::TestStatus PipelineLibraryMiscTestInstance::runIndependentPipelineLayoutSets(bool useLinkTimeOptimization)
1791 {
1792     const DeviceInterface &vk = m_context.getDeviceInterface();
1793     const VkDevice device     = m_context.getDevice();
1794     Allocator &allocator      = m_context.getDefaultAllocator();
1795 
1796     const VkDeviceSize colorBufferDataSize = static_cast<VkDeviceSize>(
1797         m_renderArea.extent.width * m_renderArea.extent.height * tcu::getPixelSize(mapVkFormat(m_colorFormat)));
1798     const VkBufferCreateInfo colorBufferCreateInfo = makeBufferCreateInfo(
1799         colorBufferDataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1800     const BufferWithMemory colorBuffer(vk, device, allocator, colorBufferCreateInfo, MemoryRequirement::HostVisible);
1801 
1802     VkDeviceSize uniformBufferDataSize = sizeof(tcu::Vec4);
1803     const VkBufferCreateInfo uniformBufferCreateInfo =
1804         makeBufferCreateInfo(uniformBufferDataSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1805 
1806     de::MovePtr<BufferWithMemory> uniformBuffer[3];
1807 
1808     // setup data in uniform buffers that will give us expected result for validation
1809     const tcu::Vec4 uniformBuffData[3]{
1810         {4.00f, 3.00f, -1.0f, 4.00f},
1811         {0.10f, 0.25f, -0.5f, 0.05f},
1812         {-5.00f, -2.00f, 3.0f, -6.00f},
1813     };
1814 
1815     for (uint32_t i = 0; i < 3; ++i)
1816     {
1817         uniformBuffer[i] = de::MovePtr<BufferWithMemory>(
1818             new BufferWithMemory(vk, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
1819         deMemcpy(uniformBuffer[i]->getAllocation().getHostPtr(), uniformBuffData[i].getPtr(),
1820                  (size_t)uniformBufferDataSize);
1821         flushAlloc(vk, device, uniformBuffer[i]->getAllocation());
1822     }
1823 
1824     // create three descriptor set layouts
1825     Move<VkDescriptorSetLayout> descriptorSetLayouts[3];
1826     descriptorSetLayouts[0] = DescriptorSetLayoutBuilder()
1827                                   .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
1828                                                     VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
1829                                   .build(vk, device);
1830     descriptorSetLayouts[1] = DescriptorSetLayoutBuilder()
1831                                   .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
1832                                   .build(vk, device);
1833     descriptorSetLayouts[2] = DescriptorSetLayoutBuilder()
1834                                   .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT)
1835                                   .build(vk, device);
1836 
1837     // for the link time opt (and when null handle is used) use total pipeline layout recreated without the INDEPENDENT SETS bit
1838     uint32_t allLayoutsFlag = uint32_t(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
1839     if (useLinkTimeOptimization)
1840         allLayoutsFlag = 0u;
1841 
1842     // Pre-rasterization stage library has sets 0, 1, 2
1843     // * set 0 has descriptors
1844     // * set 1 has no descriptors
1845     // * set 2 has descriptors
1846     // Fragment stage library has sets 0, 1
1847     // * set 0 has descriptors
1848     // * set 1 has descriptors
1849     VkDescriptorSetLayout vertDescriptorSetLayouts[] = {*descriptorSetLayouts[0], DE_NULL, *descriptorSetLayouts[2]};
1850     VkDescriptorSetLayout fragDescriptorSetLayouts[] = {*descriptorSetLayouts[0], *descriptorSetLayouts[1]};
1851     VkDescriptorSetLayout allDescriptorSetLayouts[]  = {*descriptorSetLayouts[0], *descriptorSetLayouts[1],
1852                                                         *descriptorSetLayouts[2]};
1853 
1854     VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = initVulkanStructure();
1855     pipelineLayoutCreateInfo.flags                      = allLayoutsFlag;
1856     pipelineLayoutCreateInfo.setLayoutCount             = 3u;
1857     pipelineLayoutCreateInfo.pSetLayouts                = allDescriptorSetLayouts;
1858     Move<VkPipelineLayout> allLayouts                   = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1859     pipelineLayoutCreateInfo.flags                      = uint32_t(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
1860     pipelineLayoutCreateInfo.pSetLayouts                = vertDescriptorSetLayouts;
1861     Move<VkPipelineLayout> vertLayouts                  = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1862     pipelineLayoutCreateInfo.setLayoutCount             = 2u;
1863     pipelineLayoutCreateInfo.pSetLayouts                = fragDescriptorSetLayouts;
1864     Move<VkPipelineLayout> fragLayouts                  = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1865 
1866     Move<VkDescriptorPool> allDescriptorPool =
1867         DescriptorPoolBuilder()
1868             .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3)
1869             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 3);
1870 
1871     // create three descriptor sets
1872     Move<VkDescriptorSet> descriptorSetA = makeDescriptorSet(vk, device, *allDescriptorPool, *descriptorSetLayouts[0]);
1873     Move<VkDescriptorSet> descriptorSetB = makeDescriptorSet(vk, device, *allDescriptorPool, *descriptorSetLayouts[1]);
1874     Move<VkDescriptorSet> descriptorSetC = makeDescriptorSet(vk, device, *allDescriptorPool, *descriptorSetLayouts[2]);
1875     VkDescriptorSet allDescriptorSets[]  = {*descriptorSetA, *descriptorSetB, *descriptorSetC};
1876 
1877     // update descriptors with actual buffers
1878     const VkDescriptorBufferInfo shaderBufferAInfo =
1879         makeDescriptorBufferInfo(**uniformBuffer[0], 0u, uniformBufferDataSize);
1880     const VkDescriptorBufferInfo shaderBufferBInfo =
1881         makeDescriptorBufferInfo(**uniformBuffer[1], 0u, uniformBufferDataSize);
1882     const VkDescriptorBufferInfo shaderBufferCInfo =
1883         makeDescriptorBufferInfo(**uniformBuffer[2], 0u, uniformBufferDataSize);
1884     DescriptorSetUpdateBuilder()
1885         .writeSingle(*descriptorSetA, DescriptorSetUpdateBuilder::Location::binding(0u),
1886                      VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &shaderBufferAInfo)
1887         .writeSingle(*descriptorSetB, DescriptorSetUpdateBuilder::Location::binding(0u),
1888                      VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &shaderBufferBInfo)
1889         .writeSingle(*descriptorSetC, DescriptorSetUpdateBuilder::Location::binding(0u),
1890                      VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &shaderBufferCInfo)
1891         .update(vk, device);
1892 
1893     uint32_t commonPipelinePartFlags = uint32_t(VK_PIPELINE_CREATE_LIBRARY_BIT_KHR);
1894     uint32_t finalPipelineFlag       = 0u;
1895     if (useLinkTimeOptimization)
1896     {
1897         commonPipelinePartFlags |= uint32_t(VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT);
1898         finalPipelineFlag = uint32_t(VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT);
1899     }
1900 
1901     GraphicsPipelineCreateInfo partialPipelineCreateInfo[]{{DE_NULL, *m_renderPass, 0, commonPipelinePartFlags},
1902                                                            {*vertLayouts, *m_renderPass, 0, commonPipelinePartFlags},
1903                                                            {*fragLayouts, *m_renderPass, 0, commonPipelinePartFlags},
1904                                                            {DE_NULL, *m_renderPass, 0, commonPipelinePartFlags}};
1905 
1906     // fill proper portion of pipeline state
1907     updateVertexInputInterface(m_context, partialPipelineCreateInfo[0], VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0u);
1908     updatePreRasterization(m_context, partialPipelineCreateInfo[1], false);
1909     updatePostRasterization(m_context, partialPipelineCreateInfo[2], false);
1910     updateFragmentOutputInterface(m_context, partialPipelineCreateInfo[3]);
1911 
1912     // extend pNext chain and create all partial pipelines
1913     std::vector<VkPipeline> rawParts(4u, DE_NULL);
1914     std::vector<Move<VkPipeline>> pipelineParts;
1915     pipelineParts.reserve(4u);
1916     VkGraphicsPipelineLibraryCreateInfoEXT libraryCreateInfo =
1917         makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT);
1918     for (uint32_t i = 0; i < 4u; ++i)
1919     {
1920         libraryCreateInfo.flags = GRAPHICS_PIPELINE_LIBRARY_FLAGS[i];
1921         appendStructurePtrToVulkanChain(&partialPipelineCreateInfo[i].pNext, &libraryCreateInfo);
1922         pipelineParts.emplace_back(createGraphicsPipeline(vk, device, DE_NULL, &partialPipelineCreateInfo[i]));
1923         rawParts[i] = *pipelineParts[i];
1924     }
1925 
1926     // create final pipeline out of four parts
1927     VkPipelineLibraryCreateInfoKHR linkingInfo     = makePipelineLibraryCreateInfo(rawParts);
1928     VkGraphicsPipelineCreateInfo finalPipelineInfo = initVulkanStructure();
1929 
1930     finalPipelineInfo.flags  = finalPipelineFlag;
1931     finalPipelineInfo.layout = *allLayouts;
1932 
1933     appendStructurePtrToVulkanChain(&finalPipelineInfo.pNext, &linkingInfo);
1934     Move<VkPipeline> pipeline = createGraphicsPipeline(vk, device, DE_NULL, &finalPipelineInfo);
1935 
1936     vk::beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1937     {
1938         // change color image layout
1939         const VkImageMemoryBarrier initialImageBarrier = makeImageMemoryBarrier(
1940             0,                                          // VkAccessFlags srcAccessMask;
1941             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,       // VkAccessFlags dstAccessMask;
1942             VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout oldLayout;
1943             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout newLayout;
1944             **m_colorImage,                             // VkImage image;
1945             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
1946         );
1947         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1948                               VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, DE_NULL, 0,
1949                               DE_NULL, 1, &initialImageBarrier);
1950 
1951         // wait for uniform buffers
1952         std::vector<VkBufferMemoryBarrier> initialBufferBarriers(
1953             3u, makeBufferMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT,   // VkAccessFlags2KHR                srcAccessMask
1954                                         VK_ACCESS_UNIFORM_READ_BIT, // VkAccessFlags2KHR                dstAccessMask
1955                                         uniformBuffer[0]->get(),    // VkBuffer                            buffer
1956                                         0u,                         // VkDeviceSize                        offset
1957                                         uniformBufferDataSize       // VkDeviceSize                        size
1958                                         ));
1959         initialBufferBarriers[1].buffer = uniformBuffer[1]->get();
1960         initialBufferBarriers[2].buffer = uniformBuffer[2]->get();
1961         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
1962                               (VkDependencyFlags)0, 0, DE_NULL, 3, initialBufferBarriers.data(), 0, DE_NULL);
1963 
1964         beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, m_renderArea, m_colorClearColor);
1965 
1966         vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1967         vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *allLayouts, 0u, 3u, allDescriptorSets,
1968                                  0u, DE_NULL);
1969         vk.cmdDraw(*m_cmdBuffer, 4, 1u, 0u, 0u);
1970 
1971         endRenderPass(vk, *m_cmdBuffer);
1972 
1973         const tcu::IVec2 size{(int32_t)m_renderArea.extent.width, (int32_t)m_renderArea.extent.height};
1974         copyImageToBuffer(vk, *m_cmdBuffer, **m_colorImage, *colorBuffer, size);
1975     }
1976     vk::endCommandBuffer(vk, *m_cmdBuffer);
1977     vk::submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *m_cmdBuffer);
1978 
1979     vk::invalidateAlloc(vk, device, colorBuffer.getAllocation());
1980     const tcu::ConstPixelBufferAccess colorPixelAccess(mapVkFormat(m_colorFormat), m_renderArea.extent.width,
1981                                                        m_renderArea.extent.height, 1,
1982                                                        colorBuffer.getAllocation().getHostPtr());
1983 
1984     // verify result
1985     int32_t width  = (int32_t)m_renderArea.extent.width;
1986     int32_t height = (int32_t)m_renderArea.extent.height;
1987     const std::vector<VerificationData> verificationData{
1988         {{1, 1}, {0, 191, 127, 51}}, // note COLOR_COMPONENTS_NO_RED is used
1989         {{width / 2, height / 2}, {0, 191, 127, 51}},
1990         {{width - 2, height - 2}, {0, 0, 0, 255}} // clear color
1991     };
1992     return verifyResult(verificationData, colorPixelAccess);
1993 }
1994 
runCompareLinkTimes(void)1995 tcu::TestStatus PipelineLibraryMiscTestInstance::runCompareLinkTimes(void)
1996 {
1997     const uint32_t uniqueLibrariesCount = 2u;
1998     const uint32_t pipelinesCount       = 4u * uniqueLibrariesCount;
1999 
2000     const DeviceInterface &vk                       = m_context.getDeviceInterface();
2001     const VkDevice device                           = m_context.getDevice();
2002     tcu::TestLog &log                               = m_context.getTestContext().getLog();
2003     bool allChecksPassed                            = true;
2004     VkPipelineLayoutCreateInfo pipelineLayoutParams = initVulkanStructure();
2005     Move<VkPipelineLayout> layout                   = createPipelineLayout(vk, device, &pipelineLayoutParams);
2006 
2007     GraphicsPipelineCreateInfo partialPipelineCreateInfo[]{
2008         {*layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR},
2009         {*layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR},
2010         {*layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR},
2011         {*layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR},
2012         {*layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR},
2013         {*layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR},
2014         {*layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR},
2015         {*layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR},
2016     };
2017 
2018     de::Random rnd(static_cast<uint32_t>(deGetMicroseconds()));
2019 
2020     const uint32_t vertexRandSpecConsts[]   = {rnd.getUint32() * 2, rnd.getUint32() * 2};
2021     const uint32_t fragmentRandSpecConsts[] = {rnd.getUint32() * 2, rnd.getUint32() * 2};
2022 
2023     const VkSpecializationMapEntry entry = {
2024         0,              // uint32_t constantID;
2025         0,              // uint32_t offset;
2026         sizeof(int32_t) // size_t size;
2027     };
2028 
2029     const VkSpecializationInfo vertexSpecializationInfos[] = {
2030         {
2031             1u,                      // uint32_t mapEntryCount;
2032             &entry,                  // const VkSpecializationMapEntry* pMapEntries;
2033             sizeof(int32_t),         // size_t dataSize;
2034             &vertexRandSpecConsts[0] // const void* pData;
2035         },
2036         {
2037             1u,                      // uint32_t mapEntryCount;
2038             &entry,                  // const VkSpecializationMapEntry* pMapEntries;
2039             sizeof(int32_t),         // size_t dataSize;
2040             &vertexRandSpecConsts[1] // const void* pData;
2041         }};
2042 
2043     const VkSpecializationInfo fragmentSpecializationInfos[] = {
2044         {
2045             1u,                        // uint32_t mapEntryCount;
2046             &entry,                    // const VkSpecializationMapEntry* pMapEntries;
2047             sizeof(int32_t),           // size_t dataSize;
2048             &fragmentRandSpecConsts[0] // const void* pData;
2049         },
2050         {
2051             1u,                        // uint32_t mapEntryCount;
2052             &entry,                    // const VkSpecializationMapEntry* pMapEntries;
2053             sizeof(int32_t),           // size_t dataSize;
2054             &fragmentRandSpecConsts[1] // const void* pData;
2055         }};
2056 
2057     // fill proper portion of pipeline state - this cant be easily done in a scalable loop
2058     updateVertexInputInterface(m_context, partialPipelineCreateInfo[0], VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
2059     updateVertexInputInterface(m_context, partialPipelineCreateInfo[1], VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
2060     updatePreRasterization(m_context, partialPipelineCreateInfo[2], false, VK_POLYGON_MODE_FILL,
2061                            &vertexSpecializationInfos[0]);
2062     updatePreRasterization(m_context, partialPipelineCreateInfo[3], false, VK_POLYGON_MODE_LINE,
2063                            &vertexSpecializationInfos[1]);
2064     updatePostRasterization(m_context, partialPipelineCreateInfo[4], false, true, &fragmentSpecializationInfos[0]);
2065     updatePostRasterization(m_context, partialPipelineCreateInfo[5], false, false, &fragmentSpecializationInfos[1]);
2066     updateFragmentOutputInterface(m_context, partialPipelineCreateInfo[6], 0xf);
2067     updateFragmentOutputInterface(m_context, partialPipelineCreateInfo[7]);
2068 
2069     // construct all pipeline parts and mesure time it took
2070     struct PipelinePartData
2071     {
2072         Move<VkPipeline> pipelineHandle;
2073         std::chrono::duration<int64_t, std::nano> creationDuration;
2074     };
2075     std::vector<PipelinePartData> pipelinePartData(pipelinesCount);
2076     VkGraphicsPipelineLibraryCreateInfoEXT libraryCreateInfo =
2077         makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT);
2078     for (uint32_t i = 0; i < pipelinesCount; ++i)
2079     {
2080         appendStructurePtrToVulkanChain(&partialPipelineCreateInfo[i].pNext, &libraryCreateInfo);
2081         libraryCreateInfo.flags = GRAPHICS_PIPELINE_LIBRARY_FLAGS[i / 2];
2082 
2083         auto &partData            = pipelinePartData[i];
2084         auto timeStart            = std::chrono::high_resolution_clock::now();
2085         partData.pipelineHandle   = createGraphicsPipeline(vk, device, DE_NULL, partialPipelineCreateInfo + i);
2086         partData.creationDuration = std::chrono::high_resolution_clock::now() - timeStart;
2087     }
2088 
2089     // iterate over all combinations of parts
2090     for (uint32_t i = 0u; i < (uint32_t)dePow(4, uniqueLibrariesCount); ++i)
2091     {
2092         // select new unique combination of parts
2093         uint32_t vertexInputIndex      = (i) % 2;
2094         uint32_t preRasterizationIndex = (i / 2) % 2;
2095         uint32_t fragmentStateIndex    = (i / 4) % 2;
2096         uint32_t fragmentOutputIndex   = (i / 8) % 2;
2097 
2098         const auto &vertexInputData      = pipelinePartData[vertexInputIndex];
2099         const auto &preRasterizationData = pipelinePartData[uniqueLibrariesCount + preRasterizationIndex];
2100         const auto &fragmentStateData    = pipelinePartData[2 * uniqueLibrariesCount + fragmentStateIndex];
2101         const auto &fragmentOutputData   = pipelinePartData[3 * uniqueLibrariesCount + fragmentOutputIndex];
2102 
2103         std::vector<VkPipeline> pipelinesToLink{
2104             *vertexInputData.pipelineHandle,
2105             *preRasterizationData.pipelineHandle,
2106             *fragmentStateData.pipelineHandle,
2107             *fragmentOutputData.pipelineHandle,
2108         };
2109 
2110         VkPipelineLibraryCreateInfoKHR linkingInfo     = makePipelineLibraryCreateInfo(pipelinesToLink);
2111         VkGraphicsPipelineCreateInfo finalPipelineInfo = initVulkanStructure();
2112         finalPipelineInfo.layout                       = *layout;
2113 
2114         appendStructurePtrToVulkanChain(&finalPipelineInfo.pNext, &linkingInfo);
2115 
2116         // link pipeline without the optimised bit, and record the time taken to link it
2117         auto timeStart            = std::chrono::high_resolution_clock::now();
2118         Move<VkPipeline> pipeline = createGraphicsPipeline(vk, device, DE_NULL, &finalPipelineInfo);
2119         const auto linkingTime    = std::chrono::high_resolution_clock::now() - timeStart;
2120         const auto creationTime   = preRasterizationData.creationDuration + fragmentStateData.creationDuration;
2121 
2122         if (linkingTime > (10 * creationTime))
2123         {
2124             allChecksPassed = false;
2125             log << tcu::TestLog::Message << "Liking time (" << linkingTime.count() << ") of combination " << i
2126                 << " is more then ten times greater than creation of both pre-rasterization and fragment states ("
2127                 << creationTime.count() << ")" << tcu::TestLog::EndMessage;
2128         }
2129     }
2130 
2131     if (allChecksPassed)
2132         return tcu::TestStatus::pass("Pass");
2133 
2134     return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Liking of one or more combinations took to long");
2135 }
2136 
verifyResult(const std::vector<VerificationData> & verificationData,const tcu::ConstPixelBufferAccess & colorPixelAccess) const2137 tcu::TestStatus PipelineLibraryMiscTestInstance::verifyResult(const std::vector<VerificationData> &verificationData,
2138                                                               const tcu::ConstPixelBufferAccess &colorPixelAccess) const
2139 {
2140     const int32_t epsilon = 1;
2141     for (const auto &v : verificationData)
2142     {
2143         const IVec4 pixel = colorPixelAccess.getPixelInt(v.point.x(), v.point.y());
2144         const IVec4 diff  = pixel - v.color;
2145         for (uint32_t compNdx = 0; compNdx < 4u; ++compNdx)
2146         {
2147             if (de::abs(diff[compNdx]) > epsilon)
2148             {
2149                 const Vec4 pixelBias(0.0f);
2150                 const Vec4 pixelScale(1.0f);
2151 
2152                 m_context.getTestContext().getLog()
2153                     << TestLog::Image("Result", "Result", colorPixelAccess, pixelScale, pixelBias)
2154                     << tcu::TestLog::Message << "For texel " << v.point << " expected color " << v.color
2155                     << " got: " << pixel << tcu::TestLog::EndMessage;
2156 
2157                 return tcu::TestStatus::fail("Fail");
2158             }
2159         }
2160     }
2161 
2162     return tcu::TestStatus::pass("Pass");
2163 }
2164 
2165 class PipelineLibraryShaderModuleInfoInstance : public TestInstance
2166 {
2167 public:
PipelineLibraryShaderModuleInfoInstance(Context & context)2168     PipelineLibraryShaderModuleInfoInstance(Context &context)
2169         : TestInstance(context)
2170         , m_vkd(m_context.getDeviceInterface())
2171         , m_device(m_context.getDevice())
2172         , m_alloc(m_context.getDefaultAllocator())
2173         , m_queueIndex(m_context.getUniversalQueueFamilyIndex())
2174         , m_queue(m_context.getUniversalQueue())
2175         , m_outVector(kOutputBufferElements, std::numeric_limits<uint32_t>::max())
2176         , m_cmdBuffer(DE_NULL)
2177     {
2178     }
~PipelineLibraryShaderModuleInfoInstance(void)2179     virtual ~PipelineLibraryShaderModuleInfoInstance(void)
2180     {
2181     }
2182 
2183     static constexpr size_t kOutputBufferElements = 64u;
2184 
2185 protected:
2186     void prepareOutputBuffer(VkShaderStageFlags stages);
2187     void allocateCmdBuffers(void);
2188     void addModule(const std::string &moduleName, VkShaderStageFlagBits stage);
2189     void recordShaderToHostBarrier(VkPipelineStageFlagBits pipelineStage) const;
2190     void verifyOutputBuffer(void);
2191 
2192     using BufferWithMemoryPtr = de::MovePtr<BufferWithMemory>;
2193 
2194     // From the context.
2195     const DeviceInterface &m_vkd;
2196     const VkDevice m_device;
2197     Allocator &m_alloc;
2198     const uint32_t m_queueIndex;
2199     const VkQueue m_queue;
2200 
2201     Move<VkDescriptorSetLayout> m_setLayout;
2202     Move<VkDescriptorPool> m_descriptorPool;
2203     Move<VkDescriptorSet> m_descriptorSet;
2204     std::vector<uint32_t> m_outVector;
2205     BufferWithMemoryPtr m_outputBuffer;
2206 
2207     Move<VkCommandPool> m_cmdPool;
2208     Move<VkCommandBuffer> m_cmdBufferPtr;
2209     VkCommandBuffer m_cmdBuffer;
2210 
2211     std::vector<VkPipelineShaderStageCreateInfo> m_pipelineStageInfos;
2212     std::vector<VkShaderModuleCreateInfo> m_shaderModuleInfos;
2213 };
2214 
prepareOutputBuffer(VkShaderStageFlags stages)2215 void PipelineLibraryShaderModuleInfoInstance::prepareOutputBuffer(VkShaderStageFlags stages)
2216 {
2217     const auto descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2218     const auto poolFlags      = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
2219 
2220     // Create set layout.
2221     DescriptorSetLayoutBuilder layoutBuilder;
2222     layoutBuilder.addSingleBinding(descriptorType, stages);
2223     m_setLayout = layoutBuilder.build(m_vkd, m_device);
2224 
2225     // Create pool and set.
2226     DescriptorPoolBuilder poolBuilder;
2227     poolBuilder.addType(descriptorType);
2228     m_descriptorPool = poolBuilder.build(m_vkd, m_device, poolFlags, 1u);
2229     m_descriptorSet  = makeDescriptorSet(m_vkd, m_device, m_descriptorPool.get(), m_setLayout.get());
2230 
2231     // Create buffer.
2232     const auto outputBufferSize       = static_cast<VkDeviceSize>(de::dataSize(m_outVector));
2233     const auto outputBufferCreateInfo = makeBufferCreateInfo(outputBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2234     m_outputBuffer                    = BufferWithMemoryPtr(
2235         new BufferWithMemory(m_vkd, m_device, m_alloc, outputBufferCreateInfo, MemoryRequirement::HostVisible));
2236 
2237     // Update set.
2238     const auto outputBufferDescInfo = makeDescriptorBufferInfo(m_outputBuffer->get(), 0ull, outputBufferSize);
2239     DescriptorSetUpdateBuilder updateBuilder;
2240     updateBuilder.writeSingle(m_descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
2241                               &outputBufferDescInfo);
2242     updateBuilder.update(m_vkd, m_device);
2243 }
2244 
addModule(const std::string & moduleName,VkShaderStageFlagBits stage)2245 void PipelineLibraryShaderModuleInfoInstance::addModule(const std::string &moduleName, VkShaderStageFlagBits stage)
2246 {
2247     const auto &binary = m_context.getBinaryCollection().get(moduleName);
2248 
2249     const VkShaderModuleCreateInfo modInfo = {
2250         VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,            // VkStructureType sType;
2251         nullptr,                                                // const void* pNext;
2252         0u,                                                     // VkShaderModuleCreateFlags flags;
2253         binary.getSize(),                                       // size_t codeSize;
2254         reinterpret_cast<const uint32_t *>(binary.getBinary()), // const uint32_t* pCode;
2255     };
2256     m_shaderModuleInfos.push_back(modInfo);
2257 
2258     // Note: the pNext pointer will be updated below.
2259     const VkPipelineShaderStageCreateInfo stageInfo = {
2260         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
2261         nullptr,                                             // const void* pNext;
2262         0u,                                                  // VkPipelineShaderStageCreateFlags flags;
2263         stage,                                               // VkShaderStageFlagBits stage;
2264         DE_NULL,                                             // VkShaderModule module;
2265         "main",                                              // const char* pName;
2266         nullptr,                                             // const VkSpecializationInfo* pSpecializationInfo;
2267     };
2268     m_pipelineStageInfos.push_back(stageInfo);
2269 
2270     DE_ASSERT(m_shaderModuleInfos.size() == m_pipelineStageInfos.size());
2271 
2272     // Update pNext pointers after possible reallocation.
2273     for (size_t i = 0u; i < m_shaderModuleInfos.size(); ++i)
2274         m_pipelineStageInfos[i].pNext = &(m_shaderModuleInfos[i]);
2275 }
2276 
recordShaderToHostBarrier(VkPipelineStageFlagBits pipelineStage) const2277 void PipelineLibraryShaderModuleInfoInstance::recordShaderToHostBarrier(VkPipelineStageFlagBits pipelineStage) const
2278 {
2279     const auto postWriteBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2280     cmdPipelineMemoryBarrier(m_vkd, m_cmdBuffer, pipelineStage, VK_PIPELINE_STAGE_HOST_BIT, &postWriteBarrier);
2281 }
2282 
verifyOutputBuffer(void)2283 void PipelineLibraryShaderModuleInfoInstance::verifyOutputBuffer(void)
2284 {
2285     auto &allocation = m_outputBuffer->getAllocation();
2286 
2287     invalidateAlloc(m_vkd, m_device, allocation);
2288     deMemcpy(m_outVector.data(), allocation.getHostPtr(), de::dataSize(m_outVector));
2289 
2290     for (uint32_t i = 0; i < static_cast<uint32_t>(m_outVector.size()); ++i)
2291     {
2292         if (m_outVector[i] != i)
2293         {
2294             std::ostringstream msg;
2295             msg << "Unexpected value found at position " << i << ": " << m_outVector[i];
2296             TCU_FAIL(msg.str());
2297         }
2298     }
2299 }
2300 
allocateCmdBuffers(void)2301 void PipelineLibraryShaderModuleInfoInstance::allocateCmdBuffers(void)
2302 {
2303     m_cmdPool      = makeCommandPool(m_vkd, m_device, m_queueIndex);
2304     m_cmdBufferPtr = allocateCommandBuffer(m_vkd, m_device, m_cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2305     m_cmdBuffer    = m_cmdBufferPtr.get();
2306 }
2307 
2308 class PipelineLibraryShaderModuleInfoCompInstance : public PipelineLibraryShaderModuleInfoInstance
2309 {
2310 public:
PipelineLibraryShaderModuleInfoCompInstance(Context & context)2311     PipelineLibraryShaderModuleInfoCompInstance(Context &context) : PipelineLibraryShaderModuleInfoInstance(context)
2312     {
2313     }
~PipelineLibraryShaderModuleInfoCompInstance(void)2314     virtual ~PipelineLibraryShaderModuleInfoCompInstance(void)
2315     {
2316     }
2317 
2318     tcu::TestStatus iterate(void) override;
2319 };
2320 
iterate(void)2321 tcu::TestStatus PipelineLibraryShaderModuleInfoCompInstance::iterate(void)
2322 {
2323     const auto stage     = VK_SHADER_STAGE_COMPUTE_BIT;
2324     const auto bindPoint = VK_PIPELINE_BIND_POINT_COMPUTE;
2325 
2326     prepareOutputBuffer(stage);
2327     addModule("comp", stage);
2328     allocateCmdBuffers();
2329 
2330     const auto pipelineLayout = makePipelineLayout(m_vkd, m_device, m_setLayout.get());
2331 
2332     const VkComputePipelineCreateInfo pipelineCreateInfo = {
2333         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
2334         nullptr,                                        // const void* pNext;
2335         0u,                                             // VkPipelineCreateFlags flags;
2336         m_pipelineStageInfos.at(0u),                    // VkPipelineShaderStageCreateInfo stage;
2337         pipelineLayout.get(),                           // VkPipelineLayout layout;
2338         DE_NULL,                                        // VkPipeline basePipelineHandle;
2339         0,                                              // int32_t basePipelineIndex;
2340     };
2341 
2342     const auto pipeline = createComputePipeline(m_vkd, m_device, DE_NULL, &pipelineCreateInfo);
2343 
2344     beginCommandBuffer(m_vkd, m_cmdBuffer);
2345     m_vkd.cmdBindDescriptorSets(m_cmdBuffer, bindPoint, pipelineLayout.get(), 0u, 1u, &m_descriptorSet.get(), 0u,
2346                                 nullptr);
2347     m_vkd.cmdBindPipeline(m_cmdBuffer, bindPoint, pipeline.get());
2348     m_vkd.cmdDispatch(m_cmdBuffer, 1u, 1u, 1u);
2349     recordShaderToHostBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
2350     endCommandBuffer(m_vkd, m_cmdBuffer);
2351     submitCommandsAndWait(m_vkd, m_device, m_queue, m_cmdBuffer);
2352     verifyOutputBuffer();
2353 
2354     return tcu::TestStatus::pass("Pass");
2355 }
2356 
2357 class PipelineLibraryShaderModuleInfoRTInstance : public PipelineLibraryShaderModuleInfoInstance
2358 {
2359 public:
PipelineLibraryShaderModuleInfoRTInstance(Context & context,bool withLibrary)2360     PipelineLibraryShaderModuleInfoRTInstance(Context &context, bool withLibrary)
2361         : PipelineLibraryShaderModuleInfoInstance(context)
2362         , m_withLibrary(withLibrary)
2363     {
2364     }
~PipelineLibraryShaderModuleInfoRTInstance(void)2365     virtual ~PipelineLibraryShaderModuleInfoRTInstance(void)
2366     {
2367     }
2368 
2369     tcu::TestStatus iterate(void) override;
2370 
2371 protected:
2372     bool m_withLibrary;
2373 };
2374 
iterate(void)2375 tcu::TestStatus PipelineLibraryShaderModuleInfoRTInstance::iterate(void)
2376 {
2377     const auto stage     = VK_SHADER_STAGE_RAYGEN_BIT_KHR;
2378     const auto bindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
2379 
2380     prepareOutputBuffer(stage);
2381     addModule("rgen", stage);
2382     allocateCmdBuffers();
2383 
2384     const auto pipelineLayout = makePipelineLayout(m_vkd, m_device, m_setLayout.get());
2385 
2386     const VkRayTracingShaderGroupCreateInfoKHR shaderGroupInfo = {
2387         VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR, // VkStructureType sType;
2388         nullptr,                                                    // const void* pNext;
2389         VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR,               // VkRayTracingShaderGroupTypeKHR type;
2390         0u,                                                         // uint32_t generalShader;
2391         VK_SHADER_UNUSED_KHR,                                       // uint32_t closestHitShader;
2392         VK_SHADER_UNUSED_KHR,                                       // uint32_t anyHitShader;
2393         VK_SHADER_UNUSED_KHR,                                       // uint32_t intersectionShader;
2394         nullptr,                                                    // const void* pShaderGroupCaptureReplayHandle;
2395     };
2396 
2397     const VkPipelineCreateFlags createFlags =
2398         (m_withLibrary ? static_cast<VkPipelineCreateFlags>(VK_PIPELINE_CREATE_LIBRARY_BIT_KHR) : 0u);
2399     const VkRayTracingPipelineInterfaceCreateInfoKHR libIfaceInfo   = initVulkanStructure();
2400     const VkRayTracingPipelineInterfaceCreateInfoKHR *pLibraryIface = (m_withLibrary ? &libIfaceInfo : nullptr);
2401 
2402     const VkRayTracingPipelineCreateInfoKHR pipelineCreateInfo = {
2403         VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR, // VkStructureType sType;
2404         nullptr,                                                // const void* pNext;
2405         createFlags,                                            // VkPipelineCreateFlags flags;
2406         de::sizeU32(m_pipelineStageInfos),                      // uint32_t stageCount;
2407         de::dataOrNull(m_pipelineStageInfos),                   // const VkPipelineShaderStageCreateInfo* pStages;
2408         1u,                                                     // uint32_t groupCount;
2409         &shaderGroupInfo,                                       // const VkRayTracingShaderGroupCreateInfoKHR* pGroups;
2410         1u,                                                     // uint32_t maxPipelineRayRecursionDepth;
2411         nullptr,                                                // const VkPipelineLibraryCreateInfoKHR* pLibraryInfo;
2412         pLibraryIface,        // const VkRayTracingPipelineInterfaceCreateInfoKHR* pLibraryInterface;
2413         nullptr,              // const VkPipelineDynamicStateCreateInfo* pDynamicState;
2414         pipelineLayout.get(), // VkPipelineLayout layout;
2415         DE_NULL,              // VkPipeline basePipelineHandle;
2416         0,                    // int32_t basePipelineIndex;
2417     };
2418 
2419     Move<VkPipeline> pipelineLib;
2420     Move<VkPipeline> pipeline;
2421 
2422     if (m_withLibrary)
2423     {
2424         pipelineLib = createRayTracingPipelineKHR(m_vkd, m_device, DE_NULL, DE_NULL, &pipelineCreateInfo);
2425 
2426         const VkPipelineLibraryCreateInfoKHR libraryInfo = {
2427             VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR, // VkStructureType sType;
2428             nullptr,                                            // const void* pNext;
2429             1u,                                                 // uint32_t libraryCount;
2430             &pipelineLib.get(),                                 // const VkPipeline* pLibraries;
2431         };
2432 
2433         const VkRayTracingPipelineCreateInfoKHR nonLibCreateInfo = {
2434             VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR, // VkStructureType sType;
2435             nullptr,                                                // const void* pNext;
2436             0u,                                                     // VkPipelineCreateFlags flags;
2437             0u,                                                     // uint32_t stageCount;
2438             nullptr,                                                // const VkPipelineShaderStageCreateInfo* pStages;
2439             0u,                                                     // uint32_t groupCount;
2440             nullptr,              // const VkRayTracingShaderGroupCreateInfoKHR* pGroups;
2441             1u,                   // uint32_t maxPipelineRayRecursionDepth;
2442             &libraryInfo,         // const VkPipelineLibraryCreateInfoKHR* pLibraryInfo;
2443             pLibraryIface,        // const VkRayTracingPipelineInterfaceCreateInfoKHR* pLibraryInterface;
2444             nullptr,              // const VkPipelineDynamicStateCreateInfo* pDynamicState;
2445             pipelineLayout.get(), // VkPipelineLayout layout;
2446             DE_NULL,              // VkPipeline basePipelineHandle;
2447             0,                    // int32_t basePipelineIndex;
2448         };
2449         pipeline = createRayTracingPipelineKHR(m_vkd, m_device, DE_NULL, DE_NULL, &nonLibCreateInfo);
2450     }
2451     else
2452     {
2453         pipeline = createRayTracingPipelineKHR(m_vkd, m_device, DE_NULL, DE_NULL, &pipelineCreateInfo);
2454     }
2455 
2456     // Make shader binding table.
2457     const auto rtProperties = makeRayTracingProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
2458     const auto rtHandleSize = rtProperties->getShaderGroupHandleSize();
2459     const auto sbtSize      = static_cast<VkDeviceSize>(rtHandleSize);
2460     const auto sbtMemReqs   = (MemoryRequirement::HostVisible | MemoryRequirement::DeviceAddress);
2461     const auto sbtCreateInfo = makeBufferCreateInfo(sbtSize, VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR |
2462                                                                  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
2463     BufferWithMemoryPtr sbt =
2464         BufferWithMemoryPtr(new BufferWithMemory(m_vkd, m_device, m_alloc, sbtCreateInfo, sbtMemReqs));
2465     auto &sbtAlloc = sbt->getAllocation();
2466     void *sbtData  = sbtAlloc.getHostPtr();
2467 
2468     // Copy ray gen shader group handle to the start of  the buffer.
2469     VK_CHECK(m_vkd.getRayTracingShaderGroupHandlesKHR(m_device, pipeline.get(), 0u, 1u, static_cast<size_t>(sbtSize),
2470                                                       sbtData));
2471     flushAlloc(m_vkd, m_device, sbtAlloc);
2472 
2473     // Strided device address regions.
2474     VkStridedDeviceAddressRegionKHR rgenSBTRegion = makeStridedDeviceAddressRegionKHR(
2475         getBufferDeviceAddress(m_vkd, m_device, sbt->get(), 0), rtHandleSize, rtHandleSize);
2476     VkStridedDeviceAddressRegionKHR missSBTRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
2477     VkStridedDeviceAddressRegionKHR hitsSBTRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
2478     VkStridedDeviceAddressRegionKHR callSBTRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
2479 
2480     beginCommandBuffer(m_vkd, m_cmdBuffer);
2481     m_vkd.cmdBindDescriptorSets(m_cmdBuffer, bindPoint, pipelineLayout.get(), 0u, 1u, &m_descriptorSet.get(), 0u,
2482                                 nullptr);
2483     m_vkd.cmdBindPipeline(m_cmdBuffer, bindPoint, pipeline.get());
2484     m_vkd.cmdTraceRaysKHR(m_cmdBuffer, &rgenSBTRegion, &missSBTRegion, &hitsSBTRegion, &callSBTRegion,
2485                           kOutputBufferElements, 1u, 1u);
2486     recordShaderToHostBarrier(VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
2487     endCommandBuffer(m_vkd, m_cmdBuffer);
2488     submitCommandsAndWait(m_vkd, m_device, m_queue, m_cmdBuffer);
2489     verifyOutputBuffer();
2490 
2491     return tcu::TestStatus::pass("Pass");
2492 }
2493 
2494 class NullRenderingCreateInfoInstance : public vkt::TestInstance
2495 {
2496 public:
NullRenderingCreateInfoInstance(Context & context)2497     NullRenderingCreateInfoInstance(Context &context) : vkt::TestInstance(context)
2498     {
2499     }
~NullRenderingCreateInfoInstance(void)2500     virtual ~NullRenderingCreateInfoInstance(void)
2501     {
2502     }
2503 
2504     tcu::TestStatus iterate(void) override;
2505 };
2506 
iterate(void)2507 tcu::TestStatus NullRenderingCreateInfoInstance::iterate(void)
2508 {
2509     const auto ctx = m_context.getContextCommonData();
2510     const tcu::IVec3 colorExtent(1, 1, 1);
2511     const auto imageExtent = makeExtent3D(colorExtent);
2512     const auto colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
2513     const auto tcuFormat   = mapVkFormat(colorFormat);
2514     const auto colorUsage  = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
2515     const auto colorSRR    = makeDefaultImageSubresourceRange();
2516     const auto colorSRL    = makeDefaultImageSubresourceLayers();
2517 
2518     // Color buffer and view.
2519     ImageWithBuffer colorBuffer(ctx.vkd, ctx.device, ctx.allocator, imageExtent, colorFormat, colorUsage,
2520                                 VK_IMAGE_TYPE_2D);
2521     const auto colorView =
2522         makeImageView(ctx.vkd, ctx.device, colorBuffer.getImage(), VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSRR);
2523 
2524     // Verification buffer.
2525     const auto verificationBufferSize =
2526         static_cast<VkDeviceSize>(colorExtent.x() * colorExtent.y() * colorExtent.z() * tcu::getPixelSize(tcuFormat));
2527     const auto verificationBufferInfo = makeBufferCreateInfo(verificationBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2528     BufferWithMemory verificationBuffer(ctx.vkd, ctx.device, ctx.allocator, verificationBufferInfo,
2529                                         MemoryRequirement::HostVisible);
2530     auto &verificationBufferAlloc = verificationBuffer.getAllocation();
2531     void *verificationBufferPtr   = verificationBufferAlloc.getHostPtr();
2532 
2533     const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device);
2534 
2535     const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = initVulkanStructure();
2536     VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo   = initVulkanStructure();
2537     inputAssemblyStateInfo.topology                                 = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
2538 
2539     const std::vector<VkViewport> viewports(1u, makeViewport(imageExtent));
2540     const std::vector<VkRect2D> scissors(1u, makeRect2D(imageExtent));
2541 
2542     const auto &binaries  = m_context.getBinaryCollection();
2543     const auto vertModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("vert"));
2544     const auto fragModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("frag"));
2545 
2546     // We will use a null-filled pipeline rendering info structure for all substates except the fragment output state.
2547     VkPipelineRenderingCreateInfo nullRenderingInfo = initVulkanStructure();
2548     nullRenderingInfo.colorAttachmentCount          = 0;
2549 
2550     VkPipelineRenderingCreateInfo finalRenderingInfo = initVulkanStructure();
2551     finalRenderingInfo.colorAttachmentCount          = 1u;
2552     finalRenderingInfo.pColorAttachmentFormats       = &colorFormat;
2553 
2554     const VkPipelineViewportStateCreateInfo viewportStateInfo = {
2555         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
2556         nullptr,                                               // const void* pNext;
2557         0u,                                                    // VkPipelineViewportStateCreateFlags flags;
2558         de::sizeU32(viewports),                                // uint32_t viewportCount;
2559         de::dataOrNull(viewports),                             // const VkViewport* pViewports;
2560         de::sizeU32(scissors),                                 // uint32_t scissorCount;
2561         de::dataOrNull(scissors),                              // const VkRect2D* pScissors;
2562     };
2563 
2564     const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo = {
2565         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
2566         nullptr,                                                    // const void* pNext;
2567         0u,                                                         // VkPipelineRasterizationStateCreateFlags flags;
2568         VK_FALSE,                                                   // VkBool32 depthClampEnable;
2569         VK_FALSE,                                                   // VkBool32 rasterizerDiscardEnable;
2570         VK_POLYGON_MODE_FILL,                                       // VkPolygonMode polygonMode;
2571         VK_CULL_MODE_BACK_BIT,                                      // VkCullModeFlags cullMode;
2572         VK_FRONT_FACE_COUNTER_CLOCKWISE,                            // VkFrontFace frontFace;
2573         VK_FALSE,                                                   // VkBool32 depthBiasEnable;
2574         0.0f,                                                       // float depthBiasConstantFactor;
2575         0.0f,                                                       // float depthBiasClamp;
2576         0.0f,                                                       // float depthBiasSlopeFactor;
2577         1.0f,                                                       // float lineWidth;
2578     };
2579 
2580     const VkPipelineMultisampleStateCreateInfo multisampleStateInfo = {
2581         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
2582         nullptr,                                                  // const void* pNext;
2583         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
2584         VK_SAMPLE_COUNT_1_BIT,                                    // VkSampleCountFlagBits rasterizationSamples;
2585         VK_FALSE,                                                 // VkBool32 sampleShadingEnable;
2586         1.0f,                                                     // float minSampleShading;
2587         nullptr,                                                  // const VkSampleMask* pSampleMask;
2588         VK_FALSE,                                                 // VkBool32 alphaToCoverageEnable;
2589         VK_FALSE,                                                 // VkBool32 alphaToOneEnable;
2590     };
2591 
2592     const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = initVulkanStructure();
2593 
2594     const VkColorComponentFlags colorComponentFlags =
2595         (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
2596 
2597     const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {
2598         VK_FALSE,             // VkBool32 blendEnable;
2599         VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor;
2600         VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
2601         VK_BLEND_OP_ADD,      // VkBlendOp colorBlendOp;
2602         VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor;
2603         VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
2604         VK_BLEND_OP_ADD,      // VkBlendOp alphaBlendOp;
2605         colorComponentFlags,  // VkColorComponentFlags colorWriteMask;
2606     };
2607 
2608     const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo = {
2609         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
2610         nullptr,                                                  // const void* pNext;
2611         0u,                                                       // VkPipelineColorBlendStateCreateFlags flags;
2612         VK_FALSE,                                                 // VkBool32 logicOpEnable;
2613         VK_LOGIC_OP_CLEAR,                                        // VkLogicOp logicOp;
2614         1u,                                                       // uint32_t attachmentCount;
2615         &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
2616         {0.0f, 0.0f, 0.0f, 0.0f},   // float blendConstants[4];
2617     };
2618 
2619     // Build the different pipeline pieces.
2620     Move<VkPipeline> vertexInputLib;
2621     Move<VkPipeline> preRasterShaderLib;
2622     Move<VkPipeline> fragShaderLib;
2623     Move<VkPipeline> fragOutputLib;
2624 
2625     const VkPipelineCreateFlags libCreationFlags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
2626     const VkPipelineCreateFlags linkFlags        = 0u;
2627 
2628     // Vertex input state library.
2629     {
2630         VkGraphicsPipelineLibraryCreateInfoEXT vertexInputLibInfo = initVulkanStructure();
2631         vertexInputLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT;
2632 
2633         VkGraphicsPipelineCreateInfo vertexInputPipelineInfo = initVulkanStructure(&vertexInputLibInfo);
2634         vertexInputPipelineInfo.flags                        = libCreationFlags;
2635         vertexInputPipelineInfo.pVertexInputState            = &vertexInputStateInfo;
2636         vertexInputPipelineInfo.pInputAssemblyState          = &inputAssemblyStateInfo;
2637 
2638         vertexInputLib = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &vertexInputPipelineInfo);
2639     }
2640 
2641     // Pre-rasterization shader state library.
2642     {
2643         VkGraphicsPipelineLibraryCreateInfoEXT preRasterShaderLibInfo =
2644             initVulkanStructure(&nullRenderingInfo); // What we're testing.
2645         preRasterShaderLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT;
2646 
2647         VkGraphicsPipelineCreateInfo preRasterShaderPipelineInfo = initVulkanStructure(&preRasterShaderLibInfo);
2648         preRasterShaderPipelineInfo.flags                        = libCreationFlags;
2649         preRasterShaderPipelineInfo.layout                       = pipelineLayout.get();
2650         preRasterShaderPipelineInfo.pViewportState               = &viewportStateInfo;
2651         preRasterShaderPipelineInfo.pRasterizationState          = &rasterizationStateInfo;
2652 
2653         const auto vertShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_VERTEX_BIT, vertModule.get());
2654         preRasterShaderPipelineInfo.stageCount = 1u;
2655         preRasterShaderPipelineInfo.pStages    = &vertShaderInfo;
2656 
2657         preRasterShaderLib = createGraphicsPipeline(ctx.vkd, ctx.device, DE_NULL, &preRasterShaderPipelineInfo);
2658     }
2659 
2660     // Fragment shader stage library.
2661     {
2662         VkGraphicsPipelineLibraryCreateInfoEXT fragShaderLibInfo =
2663             initVulkanStructure(&nullRenderingInfo); // What we're testing.
2664         fragShaderLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT;
2665 
2666         VkGraphicsPipelineCreateInfo fragShaderPipelineInfo = initVulkanStructure(&fragShaderLibInfo);
2667         fragShaderPipelineInfo.flags                        = libCreationFlags;
2668         fragShaderPipelineInfo.layout                       = pipelineLayout.get();
2669         fragShaderPipelineInfo.pMultisampleState            = &multisampleStateInfo;
2670         fragShaderPipelineInfo.pDepthStencilState           = &depthStencilStateInfo;
2671 
2672         const auto fragShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, fragModule.get());
2673         fragShaderPipelineInfo.stageCount = 1u;
2674         fragShaderPipelineInfo.pStages    = &fragShaderInfo;
2675 
2676         fragShaderLib = createGraphicsPipeline(ctx.vkd, ctx.device, DE_NULL, &fragShaderPipelineInfo);
2677     }
2678 
2679     // Fragment output library.
2680     {
2681         VkGraphicsPipelineLibraryCreateInfoEXT fragOutputLibInfo =
2682             initVulkanStructure(&finalRenderingInfo); // Good info only in the fragment output substate.
2683         fragOutputLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT;
2684 
2685         VkGraphicsPipelineCreateInfo fragOutputPipelineInfo = initVulkanStructure(&fragOutputLibInfo);
2686         fragOutputPipelineInfo.flags                        = libCreationFlags;
2687         fragOutputPipelineInfo.pColorBlendState             = &colorBlendStateInfo;
2688         fragOutputPipelineInfo.pMultisampleState            = &multisampleStateInfo;
2689 
2690         fragOutputLib = createGraphicsPipeline(ctx.vkd, ctx.device, DE_NULL, &fragOutputPipelineInfo);
2691     }
2692 
2693     // Linked pipeline.
2694     const std::vector<VkPipeline> libraryHandles{
2695         vertexInputLib.get(),
2696         preRasterShaderLib.get(),
2697         fragShaderLib.get(),
2698         fragOutputLib.get(),
2699     };
2700 
2701     VkPipelineLibraryCreateInfoKHR linkedPipelineLibraryInfo = initVulkanStructure();
2702     linkedPipelineLibraryInfo.libraryCount                   = de::sizeU32(libraryHandles);
2703     linkedPipelineLibraryInfo.pLibraries                     = de::dataOrNull(libraryHandles);
2704 
2705     VkGraphicsPipelineCreateInfo linkedPipelineInfo = initVulkanStructure(&linkedPipelineLibraryInfo);
2706     linkedPipelineInfo.flags                        = linkFlags;
2707     linkedPipelineInfo.layout                       = pipelineLayout.get();
2708 
2709     const auto pipeline = createGraphicsPipeline(ctx.vkd, ctx.device, DE_NULL, &linkedPipelineInfo);
2710 
2711     CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, ctx.qfIndex);
2712     const auto cmdBuffer = cmd.cmdBuffer.get();
2713 
2714     const auto clearValue = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f);
2715 
2716     beginCommandBuffer(ctx.vkd, cmdBuffer);
2717 
2718     const auto preRenderBarrier = makeImageMemoryBarrier(
2719         0u, (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), VK_IMAGE_LAYOUT_UNDEFINED,
2720         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, colorBuffer.getImage(), colorSRR);
2721     cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
2722                                   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, &preRenderBarrier);
2723 
2724     beginRendering(ctx.vkd, cmdBuffer, colorView.get(), scissors.at(0u), clearValue,
2725                    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
2726     ctx.vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
2727     ctx.vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
2728     endRendering(ctx.vkd, cmdBuffer);
2729 
2730     const auto color2Transfer = makeImageMemoryBarrier(
2731         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2732         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer.getImage(), colorSRR);
2733     cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2734                                   VK_PIPELINE_STAGE_TRANSFER_BIT, &color2Transfer);
2735     const auto copyRegion = makeBufferImageCopy(imageExtent, colorSRL);
2736     ctx.vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2737                                  verificationBuffer.get(), 1u, &copyRegion);
2738 
2739     const auto transfer2Host = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2740     cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2741                              &transfer2Host);
2742 
2743     endCommandBuffer(ctx.vkd, cmdBuffer);
2744 
2745     submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
2746     invalidateAlloc(ctx.vkd, ctx.device, verificationBufferAlloc);
2747 
2748     auto &testLog = m_context.getTestContext().getLog();
2749     const tcu::Vec4 expectedColor(0.0f, 0.0f, 1.0f, 1.0f); // Must match frag shader.
2750     const tcu::Vec4 threshold(0.0f, 0.0f, 0.0f, 0.0f);
2751     tcu::ConstPixelBufferAccess resultAccess(tcuFormat, colorExtent, verificationBufferPtr);
2752 
2753     if (!tcu::floatThresholdCompare(testLog, "Result", "", expectedColor, resultAccess, threshold,
2754                                     tcu::COMPARE_LOG_ON_ERROR))
2755         return tcu::TestStatus::fail("Unexpected color buffer contents -- check log for details");
2756 
2757     return tcu::TestStatus::pass("Pass");
2758 }
2759 
2760 class PipelineLibraryMiscTestCase : public TestCase
2761 {
2762 public:
2763     PipelineLibraryMiscTestCase(tcu::TestContext &context, const char *name, const MiscTestParams data);
2764     ~PipelineLibraryMiscTestCase(void) = default;
2765 
2766     void checkSupport(Context &context) const;
2767     void initPrograms(SourceCollections &programCollection) const;
2768     TestInstance *createInstance(Context &context) const;
2769 
2770 private:
2771     MiscTestParams m_testParams;
2772 };
2773 
PipelineLibraryMiscTestCase(tcu::TestContext & context,const char * name,const MiscTestParams params)2774 PipelineLibraryMiscTestCase::PipelineLibraryMiscTestCase(tcu::TestContext &context, const char *name,
2775                                                          const MiscTestParams params)
2776     : TestCase(context, name)
2777     , m_testParams(params)
2778 {
2779 }
2780 
checkSupport(Context & context) const2781 void PipelineLibraryMiscTestCase::checkSupport(Context &context) const
2782 {
2783     context.requireDeviceFunctionality("VK_EXT_graphics_pipeline_library");
2784 
2785     if ((m_testParams.mode == MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_FAST_LINKED) &&
2786         !context.getGraphicsPipelineLibraryPropertiesEXT().graphicsPipelineLibraryFastLinking)
2787         TCU_THROW(NotSupportedError, "graphicsPipelineLibraryFastLinking is not supported");
2788 
2789     if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT ||
2790         m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT_LIB)
2791         context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
2792 
2793     if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT_LIB)
2794         context.requireDeviceFunctionality("VK_KHR_pipeline_library");
2795 
2796     if (m_testParams.mode == MiscTestMode::NULL_RENDERING_CREATE_INFO)
2797         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
2798 }
2799 
initPrograms(SourceCollections & programCollection) const2800 void PipelineLibraryMiscTestCase::initPrograms(SourceCollections &programCollection) const
2801 {
2802     if ((m_testParams.mode == MiscTestMode::BIND_NULL_DESCRIPTOR_SET) ||
2803         (m_testParams.mode == MiscTestMode::BIND_NULL_DESCRIPTOR_SET_IN_MONOLITHIC_PIPELINE))
2804     {
2805         std::string vertDefinition = "";
2806         std::string fragDefinition = "";
2807         std::string vertValue      = "  vec4 v = vec4(-1.0, 1.0, 2.0, -2.0);\n";
2808         std::string fragValue      = "  vec4 v = vec4(0.0, 0.2, 0.6, 0.75);\n";
2809 
2810         // define lambda that creates proper uniform buffer definition
2811         auto constructBufferDefinition = [](uint32_t setIndex)
2812         {
2813             return std::string("layout(set = ") + std::to_string(setIndex) +
2814                    ", binding = 0) uniform buf\n"
2815                    "{\n"
2816                    "  vec4 v;\n"
2817                    "};\n\n";
2818         };
2819 
2820         if (m_testParams.mode == MiscTestMode::BIND_NULL_DESCRIPTOR_SET_IN_MONOLITHIC_PIPELINE)
2821         {
2822             // descriptor set 0 will be DE_NULL, descriptor set 1 will be valid buffer with color
2823             fragDefinition = constructBufferDefinition(1);
2824             fragValue      = "";
2825         }
2826         else if (m_testParams.layoutsBits > 0u)
2827         {
2828             std::vector<uint32_t> bitsThatAreSet;
2829             const uint32_t maxBitsCount = 8 * sizeof(m_testParams.layoutsBits);
2830 
2831             // find set bits
2832             for (uint32_t i = 0u; i < m_testParams.layoutsCount; ++i)
2833             {
2834                 if (m_testParams.layoutsBits & (1 << (maxBitsCount - 1 - i)))
2835                     bitsThatAreSet.push_back(i);
2836             }
2837 
2838             // there should be 1 or 2 bits set
2839             DE_ASSERT((bitsThatAreSet.size() > 0) && (bitsThatAreSet.size() < 3));
2840 
2841             vertDefinition = constructBufferDefinition(bitsThatAreSet[0]);
2842             vertValue      = "";
2843 
2844             if (bitsThatAreSet.size() == 2u)
2845             {
2846                 fragDefinition = constructBufferDefinition(bitsThatAreSet[1]);
2847                 fragValue      = "";
2848             }
2849         }
2850 
2851         programCollection.glslSources.add("vert")
2852             << glu::VertexSource(std::string("#version 450\n"
2853                                              "precision mediump int;\nprecision highp float;\n") +
2854                                  vertDefinition +
2855                                  "out gl_PerVertex\n"
2856                                  "{\n"
2857                                  "  vec4 gl_Position;\n"
2858                                  "};\n\n"
2859                                  "void main()\n"
2860                                  "{\n" +
2861                                  vertValue +
2862                                  "  const float x = (v.x+v.z*((gl_VertexIndex & 2)>>1));\n"
2863                                  "  const float y = (v.y+v.w* (gl_VertexIndex % 2));\n"
2864 
2865                                  // note: there won't be full screen quad because of used scissors
2866                                  "  gl_Position = vec4(x, y, 0.0, 1.0);\n"
2867                                  "}\n");
2868 
2869         programCollection.glslSources.add("frag")
2870             << glu::FragmentSource(std::string("#version 450\n"
2871                                                "precision mediump int; precision highp float;"
2872                                                "layout(location = 0) out highp vec4 o_color;\n") +
2873                                    fragDefinition +
2874                                    "void main()\n"
2875                                    "{\n" +
2876                                    fragValue +
2877                                    "  o_color = v;\n"
2878                                    "}\n");
2879     }
2880     else if ((m_testParams.mode == MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_FAST_LINKED) ||
2881              (m_testParams.mode ==
2882               MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_WITH_LINK_TIME_OPTIMIZATION_UNION_HANDLE))
2883     {
2884         programCollection.glslSources.add("vert")
2885             << glu::VertexSource("#version 450\n"
2886                                  "precision mediump int; precision highp float;\n"
2887                                  "layout(set = 0, binding = 0) uniform bufA\n"
2888                                  "{\n"
2889                                  "  vec4 valueA;\n"
2890                                  "};\n"
2891                                  "layout(set = 2, binding = 0) uniform bufC\n"
2892                                  "{\n"
2893                                  "  vec4 valueC;\n"
2894                                  "};\n"
2895                                  "out gl_PerVertex\n"
2896                                  "{\n"
2897                                  "  vec4 gl_Position;\n"
2898                                  "};\n\n"
2899                                  "void main()\n"
2900                                  "{\n"
2901                                  // note: values in buffers were set to get vec4(-1, 1, 2, -2)
2902                                  "  const vec4  v = valueA + valueC;\n"
2903                                  "  const float x = (v.x+v.z*((gl_VertexIndex & 2)>>1));\n"
2904                                  "  const float y = (v.y+v.w* (gl_VertexIndex % 2));\n"
2905 
2906                                  // note: there won't be full screen quad because of used scissors
2907                                  "  gl_Position = vec4(x, y, 0.0, 1.0);\n"
2908                                  "}\n");
2909 
2910         programCollection.glslSources.add("frag")
2911             << glu::FragmentSource("#version 450\n"
2912                                    "precision mediump int; precision highp float;"
2913                                    "layout(location = 0) out highp vec4 o_color;\n"
2914                                    "layout(set = 0, binding = 0) uniform bufA\n"
2915                                    "{\n"
2916                                    "  vec4 valueA;\n"
2917                                    "};\n"
2918                                    "layout(set = 1, binding = 0) uniform bufB\n"
2919                                    "{\n"
2920                                    "  vec4 valueB;\n"
2921                                    "};\n"
2922                                    "void main()\n"
2923                                    "{\n"
2924                                    // note: values in buffers were set to get vec4(0.0, 0.75, 0.5, 0.2)
2925                                    "  o_color = valueA * valueB;\n"
2926                                    "}\n");
2927     }
2928     else if (m_testParams.mode == MiscTestMode::COMPARE_LINK_TIMES)
2929     {
2930         programCollection.glslSources.add("vert") << glu::VertexSource(
2931             "#version 450\n"
2932             "precision mediump int; precision highp float;"
2933             "layout(location = 0) in vec4 in_position;\n"
2934             "out gl_PerVertex\n"
2935             "{\n"
2936             "  vec4 gl_Position;\n"
2937             "};\n"
2938             "layout(constant_id = 0) const int random = 0;\n\n"
2939             "void main()\n"
2940             "{\n"
2941             "   gl_Position = vec4(float(1 - 2 * int(gl_VertexIndex != 1)),\n"
2942             "                      float(1 - 2 * int(gl_VertexIndex > 0)), 0.0, 1.0) + float(random & 1);\n"
2943             "}\n");
2944 
2945         programCollection.glslSources.add("frag")
2946             << glu::FragmentSource("#version 450\n"
2947                                    "precision mediump int; precision highp float;"
2948                                    "layout(location = 0) out highp vec4 o_color;\n"
2949                                    "layout(constant_id = 0) const int random = 0;\n\n"
2950                                    "void main()\n"
2951                                    "{\n"
2952                                    "  o_color = vec4(0.0, 1.0, 0.5, 1.0) + float(random & 1);\n"
2953                                    "}\n");
2954     }
2955     else if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_COMP)
2956     {
2957         std::ostringstream comp;
2958         comp << "#version 450\n"
2959              << "layout (set=0, binding=0, std430) buffer BufferBlock {\n"
2960              << "    uint values[" << PipelineLibraryShaderModuleInfoInstance::kOutputBufferElements << "];\n"
2961              << "} outBuffer;\n"
2962              << "layout (local_size_x=" << PipelineLibraryShaderModuleInfoInstance::kOutputBufferElements
2963              << ", local_size_y=1, local_size_z=1) in;\n"
2964              << "void main (void)\n"
2965              << "{\n"
2966              << "    outBuffer.values[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;\n"
2967              << "}\n";
2968         programCollection.glslSources.add("comp") << glu::ComputeSource(comp.str());
2969     }
2970     else if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT ||
2971              m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT_LIB)
2972     {
2973         const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
2974         std::ostringstream rgen;
2975         rgen << "#version 460 core\n"
2976              << "#extension GL_EXT_ray_tracing : require\n"
2977              << "layout (set=0, binding=0, std430) buffer BufferBlock {\n"
2978              << "    uint values[" << PipelineLibraryShaderModuleInfoInstance::kOutputBufferElements << "];\n"
2979              << "} outBuffer;\n"
2980              << "void main (void)\n"
2981              << "{\n"
2982              << "    outBuffer.values[gl_LaunchIDEXT.x] = gl_LaunchIDEXT.x;\n"
2983              << "}\n";
2984         programCollection.glslSources.add("rgen") << glu::RaygenSource(rgen.str()) << buildOptions;
2985     }
2986     else if (m_testParams.mode == MiscTestMode::NULL_RENDERING_CREATE_INFO)
2987     {
2988         std::ostringstream vert;
2989         vert << "#version 460\n"
2990              << "vec2 positions[3] = vec2[](\n"
2991              << "    vec2(-1.0, -1.0),\n"
2992              << "    vec2(-1.0,  3.0),\n"
2993              << "    vec2( 3.0, -1.0)\n"
2994              << ");\n"
2995              << "void main() {\n"
2996              << "    gl_Position = vec4(positions[gl_VertexIndex % 3], 0.0, 1.0);\n"
2997              << "}\n";
2998         programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
2999 
3000         std::ostringstream frag;
3001         frag << "#version 460\n"
3002              << "layout (location=0) out vec4 color;\n"
3003              << "void main () {\n"
3004              << "    color = vec4(0.0, 0.0, 1.0, 1.0);\n"
3005              << "}\n";
3006         programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
3007     }
3008     else
3009     {
3010         DE_ASSERT(false);
3011     }
3012 }
3013 
createInstance(Context & context) const3014 TestInstance *PipelineLibraryMiscTestCase::createInstance(Context &context) const
3015 {
3016     if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_COMP)
3017         return new PipelineLibraryShaderModuleInfoCompInstance(context);
3018 
3019     if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT)
3020         return new PipelineLibraryShaderModuleInfoRTInstance(context, false /*withLibrary*/);
3021 
3022     if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT_LIB)
3023         return new PipelineLibraryShaderModuleInfoRTInstance(context, true /*withLibrary*/);
3024 
3025     if (m_testParams.mode == MiscTestMode::NULL_RENDERING_CREATE_INFO)
3026         return new NullRenderingCreateInfoInstance(context);
3027 
3028     return new PipelineLibraryMiscTestInstance(context, m_testParams);
3029 }
3030 
addPipelineLibraryConfigurationsTests(tcu::TestCaseGroup * group,bool optimize)3031 void addPipelineLibraryConfigurationsTests(tcu::TestCaseGroup *group, bool optimize)
3032 {
3033     const int R                                                 = -1;
3034     const PipelineTreeConfiguration pipelineTreeConfiguration[] = {
3035         {{
3036             {R, 4}, /*     4     */
3037         }},
3038 
3039         {{
3040             {R, 0}, /*     0     */
3041                     /*  / / \ \  */
3042             {0, 1},
3043             {0, 1},
3044             {0, 1},
3045             {0, 1} /*  1 1 1 1  */
3046         }},
3047 
3048         {{
3049             {R, 0}, /*     0     */
3050                     /*  / / \    */
3051             {0, 1},
3052             {0, 1},
3053             {0, 2} /*  1 1  2   */
3054         }},
3055 
3056         {{
3057             {R, 0}, /*     0     */
3058                     /*  / / \    */
3059             {0, 1},
3060             {0, 2},
3061             {0, 1} /* 1 2   1   */
3062         }},
3063 
3064         {{
3065             {R, 0}, /*     0     */
3066                     /*    / \    */
3067             {0, 2},
3068             {0, 2}, /*   2   2   */
3069         }},
3070 
3071         {{
3072             {R, 1}, /*     1     */
3073                     /*    / \    */
3074             {0, 2},
3075             {0, 1}, /*   2   1   */
3076         }},
3077 
3078         {{
3079             {R, 2}, /*     2     */
3080                     /*    / \    */
3081             {0, 1},
3082             {0, 1}, /*   1   1   */
3083         }},
3084 
3085         {{
3086             {R, 3}, /*     3     */
3087                     /*    /      */
3088             {0, 1}, /*   1       */
3089         }},
3090 
3091         {{
3092             {R, 1}, /*     1     */
3093                     /*    /      */
3094             {0, 3}, /*   3       */
3095         }},
3096 
3097         {{
3098             {R, 0}, /*     0     */
3099                     /*    / \    */
3100             {0, 0},
3101             {0, 0}, /*   0   0   */
3102                     /*  / \ / \  */
3103             {1, 1},
3104             {1, 1},
3105             {2, 1},
3106             {2, 1}, /* 1  1 1  1 */
3107         }},
3108 
3109         {{
3110             {R, 0}, /*     0     */
3111                     /*    / \    */
3112             {0, 0},
3113             {0, 1}, /*   0   1   */
3114                     /*  / \   \  */
3115             {1, 1},
3116             {1, 1},
3117             {2, 1}, /* 1   1   1 */
3118         }},
3119 
3120         {{
3121             {R, 1}, /*     1     */
3122                     /*    / \    */
3123             {0, 0},
3124             {0, 1}, /*   0   1   */
3125                     /*  / \      */
3126             {1, 1},
3127             {1, 1}, /* 1   1     */
3128         }},
3129 
3130         {{
3131             {R, 1}, /*     1     */
3132                     /*    /      */
3133             {0, 1}, /*   1       */
3134                     /*  / \      */
3135             {1, 1},
3136             {1, 1}, /* 1   1     */
3137         }},
3138 
3139         {{
3140             {R, 1}, /*        1  */
3141                     /*       /   */
3142             {0, 1}, /*      1    */
3143                     /*     /     */
3144             {1, 1}, /*    1      */
3145                     /*   /       */
3146             {2, 1}, /*  1        */
3147         }},
3148     };
3149 
3150     for (size_t libConfigNdx = 0; libConfigNdx < DE_LENGTH_OF_ARRAY(pipelineTreeConfiguration); ++libConfigNdx)
3151     {
3152         const bool delayedShaderCreate = (libConfigNdx != 0);
3153         const TestParams testParams    = {
3154             pipelineTreeConfiguration[libConfigNdx], //  PipelineTreeConfiguration pipelineTreeConfiguration;
3155             optimize,                                //  bool optimize;
3156             delayedShaderCreate,                     //  bool delayedShaderCreate;
3157             false                                    //  bool useMaintenance5;
3158         };
3159         const std::string testName = getTestName(pipelineTreeConfiguration[libConfigNdx]);
3160 
3161         if (optimize && testParams.pipelineTreeConfiguration.size() == 1)
3162             continue;
3163 
3164         group->addChild(new PipelineLibraryTestCase(group->getTestContext(), testName.c_str(), testParams));
3165     }
3166 
3167     // repeat first case (one that creates montolithic pipeline) to test VK_KHR_maintenance5;
3168     // VkShaderModule deprecation (tested with delayedShaderCreate) was added to VK_KHR_maintenance5
3169     if (optimize == false)
3170     {
3171         const TestParams testParams{
3172             pipelineTreeConfiguration[0], //  PipelineTreeConfiguration pipelineTreeConfiguration;
3173             false,                        //  bool optimize;
3174             true,                         //  bool delayedShaderCreate;
3175             true                          //  bool useMaintenance5;
3176         };
3177 
3178         group->addChild(new PipelineLibraryTestCase(group->getTestContext(), "maintenance5", testParams));
3179     }
3180 }
3181 
3182 } // namespace
3183 
createPipelineLibraryTests(tcu::TestContext & testCtx)3184 tcu::TestCaseGroup *createPipelineLibraryTests(tcu::TestContext &testCtx)
3185 {
3186     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "graphics_library"));
3187 
3188     // Tests graphics pipeline libraries linkage without optimization
3189     addTestGroup(group.get(), "fast", addPipelineLibraryConfigurationsTests, false);
3190     // Tests graphics pipeline libraries linkage with optimization
3191     addTestGroup(group.get(), "optimize", addPipelineLibraryConfigurationsTests, true);
3192 
3193     de::MovePtr<tcu::TestCaseGroup> miscTests(new tcu::TestCaseGroup(testCtx, "misc"));
3194 
3195     de::MovePtr<tcu::TestCaseGroup> independentLayoutSetsTests(
3196         new tcu::TestCaseGroup(testCtx, "independent_pipeline_layout_sets"));
3197     independentLayoutSetsTests->addChild(new PipelineLibraryMiscTestCase(
3198         testCtx, "fast_linked", {MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_FAST_LINKED, 0u, 0u}));
3199     independentLayoutSetsTests->addChild(new PipelineLibraryMiscTestCase(
3200         testCtx, "link_opt_union_handle",
3201         {MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_WITH_LINK_TIME_OPTIMIZATION_UNION_HANDLE, 0u, 0u}));
3202     miscTests->addChild(independentLayoutSetsTests.release());
3203 
3204     de::MovePtr<tcu::TestCaseGroup> bindNullDescriptorCombinationsTests(
3205         new tcu::TestCaseGroup(testCtx, "bind_null_descriptor_set"));
3206     const std::vector<const char *> bindNullDescriptorCombinations{
3207         // note: there will be as many descriptor sets layouts in pipeline layout as there are chcaracters in the case name;
3208         // '0' represents unused descriptor set layout, '1' represents used one;
3209         // location of first '1' represents index of layout used in vertex shader;
3210         // if present second '1' represents index of layout used in fragment shader
3211         "1",   "11", "01", "10", "101", "1010",
3212         "1001" // descriptor sets layouts for first pipeline part will be (&layoutA, NULL, NULL, NULL),
3213         //                                     for second pipeline part (NULL, NULL, NULL, &layoutB)
3214     };
3215     for (const char *name : bindNullDescriptorCombinations)
3216     {
3217         uint32_t layoutsCount = static_cast<uint32_t>(strlen(name));
3218         uint32_t layoutsBits  = 0u;
3219 
3220         // construct uint32_t with bits sets based on case name
3221         for (uint32_t i = 0; i < layoutsCount; ++i)
3222             layoutsBits |= (name[i] == '1') * (1 << (8 * sizeof(layoutsBits) - i - 1));
3223 
3224         bindNullDescriptorCombinationsTests->addChild(new PipelineLibraryMiscTestCase(
3225             testCtx, name, {MiscTestMode::BIND_NULL_DESCRIPTOR_SET, layoutsCount, layoutsBits}));
3226     }
3227     miscTests->addChild(bindNullDescriptorCombinationsTests.release());
3228 
3229     {
3230         de::MovePtr<tcu::TestCaseGroup> otherTests(new tcu::TestCaseGroup(testCtx, "other"));
3231         otherTests->addChild(
3232             new PipelineLibraryMiscTestCase(testCtx, "compare_link_times", {MiscTestMode::COMPARE_LINK_TIMES, 0u, 0u}));
3233         otherTests->addChild(
3234             new PipelineLibraryMiscTestCase(testCtx, "null_descriptor_set_in_monolithic_pipeline",
3235                                             {MiscTestMode::BIND_NULL_DESCRIPTOR_SET_IN_MONOLITHIC_PIPELINE, 0u, 0u}));
3236         otherTests->addChild(new PipelineLibraryMiscTestCase(testCtx, "null_rendering_create_info",
3237                                                              {MiscTestMode::NULL_RENDERING_CREATE_INFO, 0u, 0u}));
3238         miscTests->addChild(otherTests.release());
3239     }
3240 
3241     {
3242         de::MovePtr<tcu::TestCaseGroup> nonGraphicsTests(new tcu::TestCaseGroup(testCtx, "non_graphics"));
3243         nonGraphicsTests->addChild(new PipelineLibraryMiscTestCase(
3244             testCtx, "shader_module_info_comp", {MiscTestMode::SHADER_MODULE_CREATE_INFO_COMP, 0u, 0u}));
3245         nonGraphicsTests->addChild(new PipelineLibraryMiscTestCase(
3246             testCtx, "shader_module_info_rt", {MiscTestMode::SHADER_MODULE_CREATE_INFO_RT, 0u, 0u}));
3247         nonGraphicsTests->addChild(new PipelineLibraryMiscTestCase(
3248             testCtx, "shader_module_info_rt_lib", {MiscTestMode::SHADER_MODULE_CREATE_INFO_RT_LIB, 0u, 0u}));
3249         miscTests->addChild(nonGraphicsTests.release());
3250     }
3251 
3252     group->addChild(miscTests.release());
3253 
3254     return group.release();
3255 }
3256 
3257 } // namespace pipeline
3258 
3259 } // namespace vkt
3260