• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "tcuTextureUtil.hpp"
29 #include "vkDefs.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkObjUtil.hpp"
32 #include "vkTypeUtil.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36 #include "vkBufferWithMemory.hpp"
37 #include "vkImageWithMemory.hpp"
38 #include "vkBuilderUtil.hpp"
39 #include "vkRayTracingUtil.hpp"
40 #include "vktTestCase.hpp"
41 #include "vktTestGroupUtil.hpp"
42 #include "vktCustomInstancesDevices.hpp"
43 #include "tcuCommandLine.hpp"
44 #include "tcuImageCompare.hpp"
45 #include "tcuTestLog.hpp"
46 #include "tcuRGBA.hpp"
47 
48 #include "../draw/vktDrawCreateInfoUtil.hpp"
49 #include "deMath.h"
50 #include "deRandom.hpp"
51 #include "deClock.h"
52 
53 #include <vector>
54 #include <chrono>
55 #include <set>
56 #include <limits>
57 
58 namespace vkt
59 {
60 namespace pipeline
61 {
62 namespace
63 {
64 using namespace vk;
65 using namespace vkt;
66 using namespace tcu;
67 
68 static const uint32_t RENDER_SIZE_WIDTH  = 16u;
69 static const uint32_t RENDER_SIZE_HEIGHT = 16u;
70 static const VkColorComponentFlags COLOR_COMPONENTS_NO_RED =
71     VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
72 static const VkColorComponentFlags ALL_COLOR_COMPONENTS =
73     VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
74 static const int numClipDistances                                                   = 5;
75 static const int numCullDistances                                                   = 3;
76 static const VkGraphicsPipelineLibraryFlagBitsEXT GRAPHICS_PIPELINE_LIBRARY_FLAGS[] = {
77     VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT,
78     VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT,
79     VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT,
80     VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT,
81 };
82 static const VkGraphicsPipelineLibraryFlagsEXT ALL_GRAPHICS_PIPELINE_LIBRARY_FLAGS =
83     static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT) |
84     static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) |
85     static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) |
86     static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT);
87 
88 struct PipelineTreeNode
89 {
90     int32_t parentIndex;
91     uint32_t shaderCount;
92 };
93 
94 typedef std::vector<PipelineTreeNode> PipelineTreeConfiguration;
95 
96 struct TestParams
97 {
98     PipelineTreeConfiguration pipelineTreeConfiguration;
99     bool optimize;
100     bool delayedShaderCreate;
101     bool useMaintenance5;
102 };
103 
104 struct RuntimePipelineTreeNode
105 {
106     int32_t parentIndex;
107     VkGraphicsPipelineLibraryFlagsEXT graphicsPipelineLibraryFlags;
108     VkGraphicsPipelineLibraryFlagsEXT subtreeGraphicsPipelineLibraryFlags;
109     Move<VkPipeline> pipeline;
110     std::vector<VkPipeline> pipelineLibraries;
111     // We need to track the linked libraries too, included in VkPipelineLibraryCreateInfoKHR->pLibraries
112     std::vector<VkGraphicsPipelineLibraryFlagsEXT> linkedLibraryFlags;
113 };
114 
115 typedef std::vector<RuntimePipelineTreeNode> RuntimePipelineTreeConfiguration;
116 
ivec2uvec(const IVec4 & ivec)117 inline UVec4 ivec2uvec(const IVec4 &ivec)
118 {
119     return UVec4{
120         static_cast<uint32_t>(ivec[0]),
121         static_cast<uint32_t>(ivec[1]),
122         static_cast<uint32_t>(ivec[2]),
123         static_cast<uint32_t>(ivec[3]),
124     };
125 }
126 
getTestName(const PipelineTreeConfiguration & pipelineTreeConfiguration)127 inline std::string getTestName(const PipelineTreeConfiguration &pipelineTreeConfiguration)
128 {
129     std::string result;
130     int level = pipelineTreeConfiguration[0].parentIndex;
131 
132     for (const auto &node : pipelineTreeConfiguration)
133     {
134         if (level != node.parentIndex)
135         {
136             DE_ASSERT(level < node.parentIndex);
137 
138             result += '_';
139 
140             level = node.parentIndex;
141         }
142 
143         result += de::toString(node.shaderCount);
144     }
145 
146     return result;
147 }
148 
calcPipelineCreateFlags(bool optimize,bool buildLibrary)149 inline VkPipelineCreateFlags calcPipelineCreateFlags(bool optimize, bool buildLibrary)
150 {
151     VkPipelineCreateFlags result = 0;
152 
153     if (buildLibrary)
154         result |= static_cast<VkPipelineCreateFlags>(VK_PIPELINE_CREATE_LIBRARY_BIT_KHR);
155 
156     if (optimize)
157     {
158         if (buildLibrary)
159             result |= static_cast<VkPipelineCreateFlags>(VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT);
160         else
161             result |= static_cast<VkPipelineCreateFlags>(VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT);
162     }
163 
164     return result;
165 }
166 
getRenderPass(VkGraphicsPipelineLibraryFlagsEXT subset,VkRenderPass renderPass)167 inline VkRenderPass getRenderPass(VkGraphicsPipelineLibraryFlagsEXT subset, VkRenderPass renderPass)
168 {
169     static const VkGraphicsPipelineLibraryFlagsEXT subsetRequiresRenderPass =
170         static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) |
171         static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) |
172         static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT);
173     if ((subsetRequiresRenderPass & subset) != 0)
174         return renderPass;
175 
176     return VK_NULL_HANDLE;
177 }
178 
makeGraphicsPipelineLibraryCreateInfo(const VkGraphicsPipelineLibraryFlagsEXT flags)179 inline VkGraphicsPipelineLibraryCreateInfoEXT makeGraphicsPipelineLibraryCreateInfo(
180     const VkGraphicsPipelineLibraryFlagsEXT flags)
181 {
182     const VkGraphicsPipelineLibraryCreateInfoEXT graphicsPipelineLibraryCreateInfo = {
183         VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT, //  VkStructureType sType;
184         nullptr,                                                     //  void* pNext;
185         flags,                                                       //  VkGraphicsPipelineLibraryFlagsEXT flags;
186     };
187 
188     return graphicsPipelineLibraryCreateInfo;
189 }
190 
makePipelineLibraryCreateInfo(const std::vector<VkPipeline> & pipelineLibraries)191 inline VkPipelineLibraryCreateInfoKHR makePipelineLibraryCreateInfo(const std::vector<VkPipeline> &pipelineLibraries)
192 {
193     const uint32_t libraryCount                                    = static_cast<uint32_t>(pipelineLibraries.size());
194     const VkPipeline *libraries                                    = de::dataOrNull(pipelineLibraries);
195     const VkPipelineLibraryCreateInfoKHR pipelineLibraryCreateInfo = {
196         VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR, //  VkStructureType sType;
197         nullptr,                                            //  const void* pNext;
198         libraryCount,                                       //  uint32_t libraryCount;
199         libraries,                                          //  const VkPipeline* pLibraries;
200     };
201 
202     return pipelineLibraryCreateInfo;
203 }
204 
getGraphicsPipelineLibraryFlagsString(const VkGraphicsPipelineLibraryFlagsEXT flags)205 inline std::string getGraphicsPipelineLibraryFlagsString(const VkGraphicsPipelineLibraryFlagsEXT flags)
206 {
207     std::string result;
208 
209     if ((flags & VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT) != 0)
210         result += "VERTEX_INPUT_INTERFACE ";
211     if ((flags & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) != 0)
212         result += "PRE_RASTERIZATION_SHADERS ";
213     if ((flags & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) != 0)
214         result += "FRAGMENT_SHADER ";
215     if ((flags & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT) != 0)
216         result += "FRAGMENT_OUTPUT_INTERFACE ";
217 
218     if (!result.empty())
219         result.resize(result.size() - 1);
220 
221     return result;
222 };
223 
makeColorImageCreateInfo(const VkFormat format,const uint32_t width,const uint32_t height)224 VkImageCreateInfo makeColorImageCreateInfo(const VkFormat format, const uint32_t width, const uint32_t height)
225 {
226     const VkImageUsageFlags usage     = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
227     const VkImageCreateInfo imageInfo = {
228         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, //  VkStructureType sType;
229         nullptr,                             //  const void* pNext;
230         (VkImageCreateFlags)0,               //  VkImageCreateFlags flags;
231         VK_IMAGE_TYPE_2D,                    //  VkImageType imageType;
232         format,                              //  VkFormat format;
233         makeExtent3D(width, height, 1),      //  VkExtent3D extent;
234         1u,                                  //  uint32_t mipLevels;
235         1u,                                  //  uint32_t arrayLayers;
236         VK_SAMPLE_COUNT_1_BIT,               //  VkSampleCountFlagBits samples;
237         VK_IMAGE_TILING_OPTIMAL,             //  VkImageTiling tiling;
238         usage,                               //  VkImageUsageFlags usage;
239         VK_SHARING_MODE_EXCLUSIVE,           //  VkSharingMode sharingMode;
240         0u,                                  //  uint32_t queueFamilyIndexCount;
241         nullptr,                             //  const uint32_t* pQueueFamilyIndices;
242         VK_IMAGE_LAYOUT_UNDEFINED,           //  VkImageLayout initialLayout;
243     };
244 
245     return imageInfo;
246 }
247 
makeImageViewCreateInfo(VkImage image,VkFormat format,VkImageAspectFlags aspectMask)248 VkImageViewCreateInfo makeImageViewCreateInfo(VkImage image, VkFormat format, VkImageAspectFlags aspectMask)
249 {
250     const VkComponentMapping components = {
251         VK_COMPONENT_SWIZZLE_R,
252         VK_COMPONENT_SWIZZLE_G,
253         VK_COMPONENT_SWIZZLE_B,
254         VK_COMPONENT_SWIZZLE_A,
255     };
256     const VkImageSubresourceRange subresourceRange = {
257         aspectMask, //  VkImageAspectFlags aspectMask;
258         0,          //  uint32_t baseMipLevel;
259         1,          //  uint32_t levelCount;
260         0,          //  uint32_t baseArrayLayer;
261         1,          //  uint32_t layerCount;
262     };
263     const VkImageViewCreateInfo result = {
264         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, //  VkStructureType sType;
265         nullptr,                                  //  const void* pNext;
266         0u,                                       //  VkImageViewCreateFlags flags;
267         image,                                    //  VkImage image;
268         VK_IMAGE_VIEW_TYPE_2D,                    //  VkImageViewType viewType;
269         format,                                   //  VkFormat format;
270         components,                               //  VkComponentMapping components;
271         subresourceRange,                         //  VkImageSubresourceRange subresourceRange;
272     };
273 
274     return result;
275 }
276 
makeDepthImageCreateInfo(const VkFormat format,const uint32_t width,const uint32_t height)277 VkImageCreateInfo makeDepthImageCreateInfo(const VkFormat format, const uint32_t width, const uint32_t height)
278 {
279     const VkImageUsageFlags usage =
280         VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
281     const VkImageCreateInfo imageInfo = {
282         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, //  VkStructureType sType;
283         nullptr,                             //  const void* pNext;
284         (VkImageCreateFlags)0,               //  VkImageCreateFlags flags;
285         VK_IMAGE_TYPE_2D,                    //  VkImageType imageType;
286         format,                              //  VkFormat format;
287         makeExtent3D(width, height, 1),      //  VkExtent3D extent;
288         1u,                                  //  uint32_t mipLevels;
289         1u,                                  //  uint32_t arrayLayers;
290         VK_SAMPLE_COUNT_1_BIT,               //  VkSampleCountFlagBits samples;
291         VK_IMAGE_TILING_OPTIMAL,             //  VkImageTiling tiling;
292         usage,                               //  VkImageUsageFlags usage;
293         VK_SHARING_MODE_EXCLUSIVE,           //  VkSharingMode sharingMode;
294         0u,                                  //  uint32_t queueFamilyIndexCount;
295         nullptr,                             //  const uint32_t* pQueueFamilyIndices;
296         VK_IMAGE_LAYOUT_UNDEFINED,           //  VkImageLayout initialLayout;
297     };
298 
299     return imageInfo;
300 }
301 
makeFramebufferCreateInfo(const VkRenderPass renderPass,const uint32_t attachmentCount,const VkImageView * attachments,const uint32_t width,const uint32_t height)302 const VkFramebufferCreateInfo makeFramebufferCreateInfo(const VkRenderPass renderPass, const uint32_t attachmentCount,
303                                                         const VkImageView *attachments, const uint32_t width,
304                                                         const uint32_t height)
305 {
306     const VkFramebufferCreateInfo result = {
307         VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, //  VkStructureType sType;
308         nullptr,                                   //  const void* pNext;
309         0,                                         //  VkFramebufferCreateFlags flags;
310         renderPass,                                //  VkRenderPass renderPass;
311         attachmentCount,                           //  uint32_t attachmentCount;
312         attachments,                               //  const VkImageView* pAttachments;
313         width,                                     //  uint32_t width;
314         height,                                    //  uint32_t height;
315         1,                                         //  uint32_t layers;
316     };
317 
318     return result;
319 }
320 
makePipelineMultisampleStateCreateInfo(void)321 const VkPipelineMultisampleStateCreateInfo makePipelineMultisampleStateCreateInfo(void)
322 {
323     const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo = {
324         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, //  VkStructureType sType;
325         nullptr,                                                  //  const void* pNext;
326         0u,                                                       //  VkPipelineMultisampleStateCreateFlags flags;
327         VK_SAMPLE_COUNT_1_BIT,                                    //  VkSampleCountFlagBits rasterizationSamples;
328         false,                                                    //  VkBool32 sampleShadingEnable;
329         0.0f,                                                     //  float minSampleShading;
330         nullptr,                                                  //  const VkSampleMask* pSampleMask;
331         false,                                                    //  VkBool32 alphaToCoverageEnable;
332         false,                                                    //  VkBool32 alphaToOneEnable;
333     };
334 
335     return pipelineMultisampleStateCreateInfo;
336 }
337 
338 class GraphicsPipelineCreateInfo : public ::vkt::Draw::PipelineCreateInfo
339 {
340 public:
GraphicsPipelineCreateInfo(vk::VkPipelineLayout _layout,vk::VkRenderPass _renderPass,int _subpass,vk::VkPipelineCreateFlags _flags)341     GraphicsPipelineCreateInfo(vk::VkPipelineLayout _layout, vk::VkRenderPass _renderPass, int _subpass,
342                                vk::VkPipelineCreateFlags _flags)
343         : ::vkt::Draw::PipelineCreateInfo(_layout, _renderPass, _subpass, _flags)
344         , m_vertexInputBindingDescription()
345         , m_vertexInputAttributeDescription()
346         , m_shaderModuleCreateInfoCount(0)
347         , m_shaderModuleCreateInfo{initVulkanStructure(), initVulkanStructure()}
348         , m_pipelineShaderStageCreateInfo()
349         , m_vertModule()
350         , m_fragModule()
351     {
352     }
353 
354     VkVertexInputBindingDescription m_vertexInputBindingDescription;
355     VkVertexInputAttributeDescription m_vertexInputAttributeDescription;
356     uint32_t m_shaderModuleCreateInfoCount;
357     VkShaderModuleCreateInfo m_shaderModuleCreateInfo[2];
358     std::vector<VkPipelineShaderStageCreateInfo> m_pipelineShaderStageCreateInfo;
359     Move<VkShaderModule> m_vertModule;
360     Move<VkShaderModule> m_fragModule;
361     Move<VkShaderModule> m_meshModule;
362 };
363 
updateVertexInputInterface(Context & context,GraphicsPipelineCreateInfo & graphicsPipelineCreateInfo,VkPrimitiveTopology topology=VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,uint32_t vertexDescriptionCount=1u)364 void updateVertexInputInterface(Context &context, GraphicsPipelineCreateInfo &graphicsPipelineCreateInfo,
365                                 VkPrimitiveTopology topology    = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
366                                 uint32_t vertexDescriptionCount = 1u)
367 {
368     DE_UNREF(context);
369 
370     graphicsPipelineCreateInfo.m_vertexInputBindingDescription = {
371         0u,                          //  uint32_t binding;
372         sizeof(tcu::Vec4),           //  uint32_t strideInBytes;
373         VK_VERTEX_INPUT_RATE_VERTEX, //  VkVertexInputRate inputRate;
374     };
375     graphicsPipelineCreateInfo.m_vertexInputAttributeDescription = {
376         0u,                            //  uint32_t location;
377         0u,                            //  uint32_t binding;
378         VK_FORMAT_R32G32B32A32_SFLOAT, //  VkFormat format;
379         0u                             //  uint32_t offsetInBytes;
380     };
381 
382     const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo{
383         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
384         nullptr,                                                   // const void* pNext;
385         0u,                                                        // VkPipelineVertexInputStateCreateFlags flags;
386         vertexDescriptionCount,                                    // uint32_t vertexBindingDescriptionCount;
387         &graphicsPipelineCreateInfo
388              .m_vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
389         vertexDescriptionCount,                // uint32_t vertexAttributeDescriptionCount;
390         &graphicsPipelineCreateInfo
391              .m_vertexInputAttributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
392     };
393     const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo{
394         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
395         nullptr,                                                     // const void* pNext;
396         0u,                                                          // VkPipelineInputAssemblyStateCreateFlags flags;
397         topology,                                                    // VkPrimitiveTopology topology;
398         VK_FALSE,                                                    // VkBool32 primitiveRestartEnable;
399     };
400 
401     graphicsPipelineCreateInfo.addState(vertexInputStateCreateInfo);
402     graphicsPipelineCreateInfo.addState(inputAssemblyStateCreateInfo);
403 }
404 
updatePreRasterization(Context & context,GraphicsPipelineCreateInfo & graphicsPipelineCreateInfo,bool delayedShaderCreate,bool useDynamicViewPort=false,bool useMeshShader=false,VkPolygonMode polygonMode=VK_POLYGON_MODE_FILL,const VkSpecializationInfo * specializationInfo=nullptr)405 void updatePreRasterization(Context &context, GraphicsPipelineCreateInfo &graphicsPipelineCreateInfo,
406                             bool delayedShaderCreate, bool useDynamicViewPort = false, bool useMeshShader = false,
407                             VkPolygonMode polygonMode                      = VK_POLYGON_MODE_FILL,
408                             const VkSpecializationInfo *specializationInfo = nullptr)
409 {
410     const std::string shaderName      = (useMeshShader ? "mesh" : "vert");
411     const ProgramBinary &shaderBinary = context.getBinaryCollection().get(shaderName);
412     VkShaderModuleCreateInfo &shaderModuleCreateInfo =
413         graphicsPipelineCreateInfo.m_shaderModuleCreateInfo[graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount];
414 
415     DE_ASSERT(graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount <
416               DE_LENGTH_OF_ARRAY(graphicsPipelineCreateInfo.m_shaderModuleCreateInfo));
417 
418     shaderModuleCreateInfo = {
419         VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, //  VkStructureType sType;
420         nullptr,                                     //  const void* pNext;
421         0u,                                          //  VkShaderModuleCreateFlags flags;
422         (uintptr_t)shaderBinary.getSize(),           //  uintptr_t codeSize;
423         (uint32_t *)shaderBinary.getBinary(),        //  const uint32_t* pCode;
424     };
425 
426     if (!delayedShaderCreate)
427     {
428         const DeviceInterface &vk = context.getDeviceInterface();
429         const VkDevice device     = context.getDevice();
430 
431         Move<VkShaderModule> shaderMod = createShaderModule(vk, device, &shaderModuleCreateInfo);
432         if (useMeshShader)
433             graphicsPipelineCreateInfo.m_meshModule = shaderMod;
434         else
435             graphicsPipelineCreateInfo.m_vertModule = shaderMod;
436     }
437 
438     const void *pNext = delayedShaderCreate ? &shaderModuleCreateInfo : nullptr;
439     const VkShaderModule shaderModule =
440         delayedShaderCreate ?
441             VK_NULL_HANDLE :
442             (useMeshShader ? *graphicsPipelineCreateInfo.m_meshModule : *graphicsPipelineCreateInfo.m_vertModule);
443     const VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo = {
444         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
445         pNext,                                               // const void* pNext;
446         0u,                                                  // VkPipelineShaderStageCreateFlags flags;
447         (useMeshShader ? VK_SHADER_STAGE_MESH_BIT_EXT        // VkShaderStageFlagBits stage;
448                          :
449                          VK_SHADER_STAGE_VERTEX_BIT),
450         shaderModule,      // VkShaderModule module;
451         "main",            // const char* pName;
452         specializationInfo // const VkSpecializationInfo* pSpecializationInfo;
453     };
454 
455     shaderBinary.setUsed();
456 
457     // Within the VkPipelineLayout, all    bindings that affect the specified shader stages
458     const VkViewport viewport = makeViewport(RENDER_SIZE_WIDTH, RENDER_SIZE_HEIGHT);
459     const VkRect2D scissor    = makeRect2D(3 * RENDER_SIZE_WIDTH / 4, RENDER_SIZE_HEIGHT);
460     const VkPipelineViewportStateCreateInfo pipelineViewportStateCreateInfo = {
461         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
462         nullptr,                                               // const void* pNext;
463         0u,                                                    // VkPipelineViewportStateCreateFlags flags;
464         1u,                                                    // uint32_t viewportCount;
465         &viewport,                                             // const VkViewport* pViewports;
466         1u,                                                    // uint32_t scissorCount;
467         &scissor                                               // const VkRect2D* pScissors;
468     };
469     std::vector<VkDynamicState> dynamicStates                   = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
470     const VkPipelineDynamicStateCreateInfo pipelineDynamicState = {
471         VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
472         nullptr,                                              // const void* pNext;
473         0u,                                                   // VkPipelineDynamicStateCreateFlags flags;
474         de::sizeU32(dynamicStates),                           // uint32_t dynamicStateCount;
475         de::dataOrNull(dynamicStates)                         // const VkDynamicState* pDynamicStates;
476     };
477     const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo = {
478         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
479         nullptr,                                                    // const void* pNext;
480         0u,                                                         // VkPipelineRasterizationStateCreateFlags flags;
481         VK_FALSE,                                                   // VkBool32 depthClampEnable;
482         VK_FALSE,                                                   // VkBool32 rasterizerDiscardEnable;
483         polygonMode,                                                // VkPolygonMode polygonMode;
484         VK_CULL_MODE_NONE,                                          // VkCullModeFlags cullMode;
485         VK_FRONT_FACE_COUNTER_CLOCKWISE,                            // VkFrontFace frontFace;
486         VK_FALSE,                                                   // VkBool32 depthBiasEnable;
487         0.0f,                                                       // float depthBiasConstantFactor;
488         0.0f,                                                       // float depthBiasClamp;
489         0.0f,                                                       // float depthBiasSlopeFactor;
490         1.0f,                                                       // float lineWidth;
491     };
492 
493     graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount++;
494 
495     graphicsPipelineCreateInfo.addShader(pipelineShaderStageCreateInfo);
496     graphicsPipelineCreateInfo.addState(pipelineViewportStateCreateInfo);
497     graphicsPipelineCreateInfo.addState(pipelineRasterizationStateCreateInfo);
498 
499     if (useDynamicViewPort)
500         graphicsPipelineCreateInfo.addState(pipelineDynamicState);
501 }
502 
updatePostRasterization(Context & context,GraphicsPipelineCreateInfo & graphicsPipelineCreateInfo,bool delayedShaderCreate,bool enableDepth=true,const VkSpecializationInfo * specializationInfo=nullptr)503 void updatePostRasterization(Context &context, GraphicsPipelineCreateInfo &graphicsPipelineCreateInfo,
504                              bool delayedShaderCreate, bool enableDepth = true,
505                              const VkSpecializationInfo *specializationInfo = nullptr)
506 {
507     const ProgramBinary &shaderBinary = context.getBinaryCollection().get("frag");
508     VkShaderModuleCreateInfo &shaderModuleCreateInfo =
509         graphicsPipelineCreateInfo.m_shaderModuleCreateInfo[graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount];
510 
511     DE_ASSERT(graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount <
512               DE_LENGTH_OF_ARRAY(graphicsPipelineCreateInfo.m_shaderModuleCreateInfo));
513 
514     shaderModuleCreateInfo = {
515         VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, //  VkStructureType sType;
516         nullptr,                                     //  const void* pNext;
517         0u,                                          //  VkShaderModuleCreateFlags flags;
518         (uintptr_t)shaderBinary.getSize(),           //  uintptr_t codeSize;
519         (uint32_t *)shaderBinary.getBinary(),        //  const uint32_t* pCode;
520     };
521 
522     if (!delayedShaderCreate)
523     {
524         const DeviceInterface &vk = context.getDeviceInterface();
525         const VkDevice device     = context.getDevice();
526 
527         graphicsPipelineCreateInfo.m_fragModule = createShaderModule(vk, device, &shaderModuleCreateInfo);
528     }
529 
530     const void *pNext                 = delayedShaderCreate ? &shaderModuleCreateInfo : nullptr;
531     const VkShaderModule shaderModule = delayedShaderCreate ? VK_NULL_HANDLE : *graphicsPipelineCreateInfo.m_fragModule;
532     const VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo = {
533         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
534         pNext,                                               // const void* pNext;
535         0u,                                                  // VkPipelineShaderStageCreateFlags flags;
536         VK_SHADER_STAGE_FRAGMENT_BIT,                        // VkShaderStageFlagBits stage;
537         shaderModule,                                        // VkShaderModule module;
538         "main",                                              // const char* pName;
539         specializationInfo                                   // const VkSpecializationInfo* pSpecializationInfo;
540     };
541 
542     shaderBinary.setUsed();
543 
544     // Within the VkPipelineLayout, all bindings that affect the fragment shader stage
545 
546     const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo = {
547         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, //  VkStructureType sType;
548         nullptr,                                                    //  const void* pNext;
549         0u,                                                         //  VkPipelineDepthStencilStateCreateFlags flags;
550         enableDepth,                                                //  VkBool32 depthTestEnable;
551         enableDepth,                                                //  VkBool32 depthWriteEnable;
552         VK_COMPARE_OP_LESS_OR_EQUAL,                                //  VkCompareOp depthCompareOp;
553         VK_FALSE,                                                   //  VkBool32 depthBoundsTestEnable;
554         VK_FALSE,                                                   //  VkBool32 stencilTestEnable;
555         {
556             //  VkStencilOpState front;
557             VK_STENCIL_OP_KEEP,  // VkStencilOp failOp;
558             VK_STENCIL_OP_KEEP,  // VkStencilOp passOp;
559             VK_STENCIL_OP_KEEP,  // VkStencilOp depthFailOp;
560             VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
561             0u,                  // uint32_t compareMask;
562             0u,                  // uint32_t writeMask;
563             0u,                  // uint32_t reference;
564         },
565         {
566             //  VkStencilOpState back;
567             VK_STENCIL_OP_KEEP,  // VkStencilOp failOp;
568             VK_STENCIL_OP_KEEP,  // VkStencilOp passOp;
569             VK_STENCIL_OP_KEEP,  // VkStencilOp depthFailOp;
570             VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
571             0u,                  // uint32_t compareMask;
572             0u,                  // uint32_t writeMask;
573             0u,                  // uint32_t reference;
574         },
575         0.0f, //  float minDepthBounds;
576         1.0f, //  float maxDepthBounds;
577     };
578 
579     graphicsPipelineCreateInfo.m_shaderModuleCreateInfoCount++;
580     graphicsPipelineCreateInfo.addShader(pipelineShaderStageCreateInfo);
581 
582     DE_ASSERT(graphicsPipelineCreateInfo.pDepthStencilState == nullptr);
583     graphicsPipelineCreateInfo.addState(pipelineDepthStencilStateCreateInfo);
584 
585     if (graphicsPipelineCreateInfo.pMultisampleState == nullptr)
586     {
587         const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo =
588             makePipelineMultisampleStateCreateInfo();
589 
590         graphicsPipelineCreateInfo.addState(pipelineMultisampleStateCreateInfo);
591     }
592 }
593 
updateFragmentOutputInterface(Context & context,GraphicsPipelineCreateInfo & graphicsPipelineCreateInfo,VkColorComponentFlags colorWriteMask=COLOR_COMPONENTS_NO_RED)594 void updateFragmentOutputInterface(Context &context, GraphicsPipelineCreateInfo &graphicsPipelineCreateInfo,
595                                    VkColorComponentFlags colorWriteMask = COLOR_COMPONENTS_NO_RED)
596 {
597     DE_UNREF(context);
598 
599     // Number of blend attachments must equal the number of color attachments during any subpass.
600     const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = {
601         VK_FALSE,             // VkBool32 blendEnable;
602         VK_BLEND_FACTOR_ONE,  // VkBlendFactor srcColorBlendFactor;
603         VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
604         VK_BLEND_OP_ADD,      // VkBlendOp colorBlendOp;
605         VK_BLEND_FACTOR_ONE,  // VkBlendFactor srcAlphaBlendFactor;
606         VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
607         VK_BLEND_OP_ADD,      // VkBlendOp alphaBlendOp;
608         colorWriteMask,       // VkColorComponentFlags colorWriteMask;
609     };
610     const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo = {
611         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
612         nullptr,                                                  // const void* pNext;
613         (VkPipelineColorBlendStateCreateFlags)0,                  // VkPipelineColorBlendStateCreateFlags flags;
614         VK_FALSE,                                                 // VkBool32 logicOpEnable;
615         VK_LOGIC_OP_COPY,                                         // VkLogicOp logicOp;
616         1u,                                                       // uint32_t attachmentCount;
617         &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
618         {0.0f, 0.0f, 0.0f, 0.0f},           // float blendConstants[4];
619     };
620 
621     graphicsPipelineCreateInfo.addState(pipelineColorBlendStateCreateInfo);
622 
623     if (graphicsPipelineCreateInfo.pMultisampleState == nullptr)
624     {
625         const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo =
626             makePipelineMultisampleStateCreateInfo();
627 
628         graphicsPipelineCreateInfo.addState(pipelineMultisampleStateCreateInfo);
629     }
630 }
631 
632 /*
633     To test that each of graphics pipeline libraries have influence on final pipeline
634     the functions have following features:
635 
636     updateVertexInputInterface
637         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
638         VK_VERTEX_INPUT_RATE_VERTEX
639         Z is read from uniform and written in shader
640 
641     updatePreRasterization
642         VkRect2D scissor = makeRect2D(3 * RENDER_SIZE_WIDTH / 4, RENDER_SIZE_HEIGHT);
643 
644     updatePostRasterization
645         Fragment shader top and bottom colors read from uniform buffer
646 
647     updateFragmentOutputInterface
648         Cut off red component
649 */
650 
651 class PipelineLibraryTestInstance : public TestInstance
652 {
653 public:
654     PipelineLibraryTestInstance(Context &context, const TestParams &data);
655     ~PipelineLibraryTestInstance(void);
656     tcu::TestStatus iterate(void);
657 
658 protected:
659     de::MovePtr<BufferWithMemory> makeVertexBuffer(void);
660     de::MovePtr<BufferWithMemory> makeZCoordBuffer(void);
661     de::MovePtr<BufferWithMemory> makePaletteBuffer(void);
662     Move<VkDescriptorPool> createDescriptorPool(void);
663     Move<VkDescriptorSetLayout> createDescriptorSetLayout(const VkBuffer vertShaderBuffer,
664                                                           const VkBuffer fragShaderBuffer);
665     Move<VkDescriptorSet> createDescriptorSet(const VkDescriptorPool pool, const VkDescriptorSetLayout layout,
666                                               const VkBuffer vertShaderBuffer, const VkBuffer fragShaderBuffer);
667     bool verifyColorImage(const tcu::ConstPixelBufferAccess &pba);
668     bool verifyDepthImage(const tcu::ConstPixelBufferAccess &pba);
669     bool runTest(RuntimePipelineTreeConfiguration &runtimePipelineTreeConfiguration, const bool optimize,
670                  const bool delayedShaderCreate);
671 
672 private:
673     TestParams m_data;
674     std::vector<tcu::Vec4> m_vertexData;
675     std::vector<tcu::Vec4> m_paletteData;
676     std::vector<tcu::Vec4> m_zCoordData;
677 };
678 
PipelineLibraryTestInstance(Context & context,const TestParams & data)679 PipelineLibraryTestInstance::PipelineLibraryTestInstance(Context &context, const TestParams &data)
680     : vkt::TestInstance(context)
681     , m_data(data)
682     , m_vertexData()
683     , m_paletteData()
684 {
685     m_vertexData = {
686         {-1.0f, -1.0f, 0.0f, 1.0f}, {+1.0f, -1.0f, 0.5f, 1.0f}, {-1.0f, +1.0f, 0.5f, 1.0f},
687         {-1.0f, +1.0f, 0.5f, 1.0f}, {+1.0f, -1.0f, 0.5f, 1.0f}, {+1.0f, +1.0f, 1.0f, 1.0f},
688     };
689     m_paletteData = {
690         {0.25f, 1.0f, 0.0f, 1.0f},
691         {0.75f, 0.0f, 1.0f, 1.0f},
692     };
693     m_zCoordData = {
694         {0.25f, 0.75f, 0.0f, 1.0f},
695     };
696 }
697 
~PipelineLibraryTestInstance(void)698 PipelineLibraryTestInstance::~PipelineLibraryTestInstance(void)
699 {
700 }
701 
makeVertexBuffer(void)702 de::MovePtr<BufferWithMemory> PipelineLibraryTestInstance::makeVertexBuffer(void)
703 {
704     const DeviceInterface &vk                 = m_context.getDeviceInterface();
705     const VkDevice device                     = m_context.getDevice();
706     Allocator &allocator                      = m_context.getDefaultAllocator();
707     const size_t bufferDataSize               = de::dataSize(m_vertexData);
708     const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferDataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
709     de::MovePtr<BufferWithMemory> buffer      = de::MovePtr<BufferWithMemory>(
710         new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
711 
712     deMemcpy(buffer->getAllocation().getHostPtr(), m_vertexData.data(), bufferDataSize);
713     flushAlloc(vk, device, buffer->getAllocation());
714 
715     return buffer;
716 }
717 
makeZCoordBuffer(void)718 de::MovePtr<BufferWithMemory> PipelineLibraryTestInstance::makeZCoordBuffer(void)
719 {
720     const DeviceInterface &vk   = m_context.getDeviceInterface();
721     const VkDevice device       = m_context.getDevice();
722     Allocator &allocator        = m_context.getDefaultAllocator();
723     const size_t bufferDataSize = de::dataSize(m_zCoordData);
724     const VkBufferCreateInfo bufferCreateInfo =
725         makeBufferCreateInfo(bufferDataSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
726     de::MovePtr<BufferWithMemory> buffer = de::MovePtr<BufferWithMemory>(
727         new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
728 
729     deMemcpy(buffer->getAllocation().getHostPtr(), m_zCoordData.data(), bufferDataSize);
730     flushAlloc(vk, device, buffer->getAllocation());
731 
732     return buffer;
733 }
734 
makePaletteBuffer(void)735 de::MovePtr<BufferWithMemory> PipelineLibraryTestInstance::makePaletteBuffer(void)
736 {
737     const DeviceInterface &vk   = m_context.getDeviceInterface();
738     const VkDevice device       = m_context.getDevice();
739     Allocator &allocator        = m_context.getDefaultAllocator();
740     const size_t bufferDataSize = de::dataSize(m_paletteData);
741     const VkBufferCreateInfo bufferCreateInfo =
742         makeBufferCreateInfo(bufferDataSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
743     de::MovePtr<BufferWithMemory> buffer = de::MovePtr<BufferWithMemory>(
744         new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
745 
746     deMemcpy(buffer->getAllocation().getHostPtr(), m_paletteData.data(), bufferDataSize);
747     flushAlloc(vk, device, buffer->getAllocation());
748 
749     return buffer;
750 }
751 
createDescriptorPool(void)752 Move<VkDescriptorPool> PipelineLibraryTestInstance::createDescriptorPool(void)
753 {
754     const DeviceInterface &vk = m_context.getDeviceInterface();
755     const VkDevice device     = m_context.getDevice();
756 
757     return DescriptorPoolBuilder()
758         .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4)
759         .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 3);
760 }
761 
createDescriptorSetLayout(const VkBuffer vertShaderBuffer,const VkBuffer fragShaderBuffer)762 Move<VkDescriptorSetLayout> PipelineLibraryTestInstance::createDescriptorSetLayout(const VkBuffer vertShaderBuffer,
763                                                                                    const VkBuffer fragShaderBuffer)
764 {
765     const DeviceInterface &vk = m_context.getDeviceInterface();
766     const VkDevice device     = m_context.getDevice();
767     DescriptorSetLayoutBuilder builder;
768 
769     if (vertShaderBuffer != VK_NULL_HANDLE)
770         builder.addIndexedBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u, VK_SHADER_STAGE_VERTEX_BIT, 0u, nullptr);
771 
772     if (fragShaderBuffer != VK_NULL_HANDLE)
773         builder.addIndexedBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u, VK_SHADER_STAGE_FRAGMENT_BIT, 1u, nullptr);
774 
775     return builder.build(vk, device);
776 }
777 
createDescriptorSet(const VkDescriptorPool pool,const VkDescriptorSetLayout layout,const VkBuffer vertShaderBuffer,const VkBuffer fragShaderBuffer)778 Move<VkDescriptorSet> PipelineLibraryTestInstance::createDescriptorSet(const VkDescriptorPool pool,
779                                                                        const VkDescriptorSetLayout layout,
780                                                                        const VkBuffer vertShaderBuffer,
781                                                                        const VkBuffer fragShaderBuffer)
782 {
783     const DeviceInterface &vk                   = m_context.getDeviceInterface();
784     const VkDevice device                       = m_context.getDevice();
785     const VkDescriptorSetAllocateInfo allocInfo = {
786         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, //  VkStructureType sType;
787         nullptr,                                        //  const void* pNext;
788         pool,                                           //  VkDescriptorPool descriptorPool;
789         1u,                                             //  uint32_t descriptorSetCount;
790         &layout                                         //  const VkDescriptorSetLayout* pSetLayouts;
791     };
792     Move<VkDescriptorSet> descriptorSet = allocateDescriptorSet(vk, device, &allocInfo);
793     DescriptorSetUpdateBuilder builder;
794 
795     if (vertShaderBuffer != VK_NULL_HANDLE)
796     {
797         const VkDeviceSize vertShaderBufferSize = de::dataSize(m_zCoordData);
798         const VkDescriptorBufferInfo vertShaderBufferInfo =
799             makeDescriptorBufferInfo(vertShaderBuffer, 0u, vertShaderBufferSize);
800 
801         builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
802                             VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &vertShaderBufferInfo);
803     }
804 
805     if (fragShaderBuffer != VK_NULL_HANDLE)
806     {
807         const VkDeviceSize fragShaderBufferSize = de::dataSize(m_paletteData);
808         const VkDescriptorBufferInfo fragShaderBufferInfo =
809             makeDescriptorBufferInfo(fragShaderBuffer, 0u, fragShaderBufferSize);
810 
811         builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
812                             VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &fragShaderBufferInfo);
813     }
814 
815     builder.update(vk, device);
816 
817     return descriptorSet;
818 }
819 
getSupportedDepthFormat(const InstanceInterface & vk,const VkPhysicalDevice physicalDevice)820 VkFormat getSupportedDepthFormat(const InstanceInterface &vk, const VkPhysicalDevice physicalDevice)
821 {
822     VkFormatProperties properties;
823 
824     const VkFormat DepthFormats[] = {VK_FORMAT_D32_SFLOAT, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D24_UNORM_S8_UINT,
825                                      VK_FORMAT_D32_SFLOAT_S8_UINT};
826 
827     for (const auto format : DepthFormats)
828     {
829         vk.getPhysicalDeviceFormatProperties(physicalDevice, format, &properties);
830 
831         if (properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
832             return format;
833     }
834 
835     TCU_THROW(NotSupportedError, "Depth format is not supported");
836 }
837 
runTest(RuntimePipelineTreeConfiguration & runtimePipelineTreeConfiguration,const bool optimize,const bool delayedShaderCreate)838 bool PipelineLibraryTestInstance::runTest(RuntimePipelineTreeConfiguration &runtimePipelineTreeConfiguration,
839                                           const bool optimize, const bool delayedShaderCreate)
840 {
841     const DeviceInterface &vk       = m_context.getDeviceInterface();
842     const VkDevice device           = m_context.getDevice();
843     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
844     Allocator &allocator            = m_context.getDefaultAllocator();
845     tcu::TestLog &log               = m_context.getTestContext().getLog();
846     const VkFormat colorFormat      = VK_FORMAT_R8G8B8A8_UNORM;
847     const VkFormat depthFormat =
848         getSupportedDepthFormat(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
849     const VkGraphicsPipelineLibraryFlagsEXT vertPipelineFlags =
850         static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT);
851     const VkGraphicsPipelineLibraryFlagsEXT fragPipelineFlags =
852         static_cast<VkGraphicsPipelineLibraryFlagsEXT>(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT);
853     const VkGraphicsPipelineLibraryFlagsEXT samePipelineFlags = vertPipelineFlags | fragPipelineFlags;
854     const int32_t nodeNdxLast           = static_cast<int32_t>(runtimePipelineTreeConfiguration.size()) - 1;
855     const Move<VkRenderPass> renderPass = makeRenderPass(vk, device, colorFormat, depthFormat);
856     const de::MovePtr<BufferWithMemory> zCoordBuffer  = makeZCoordBuffer();
857     const de::MovePtr<BufferWithMemory> paletteBuffer = makePaletteBuffer();
858     const Move<VkDescriptorPool> descriptorPool       = createDescriptorPool();
859 
860     const Move<VkDescriptorSetLayout> descriptorSetLayoutVert =
861         createDescriptorSetLayout(**zCoordBuffer, VK_NULL_HANDLE);
862     const Move<VkDescriptorSetLayout> descriptorSetLayoutFrag =
863         createDescriptorSetLayout(VK_NULL_HANDLE, **paletteBuffer);
864     const Move<VkDescriptorSetLayout> descriptorSetLayoutBoth =
865         createDescriptorSetLayout(**zCoordBuffer, **paletteBuffer);
866     const Move<VkDescriptorSet> descriptorSetVert =
867         createDescriptorSet(*descriptorPool, *descriptorSetLayoutVert, **zCoordBuffer, VK_NULL_HANDLE);
868     const Move<VkDescriptorSet> descriptorSetFrag =
869         createDescriptorSet(*descriptorPool, *descriptorSetLayoutFrag, VK_NULL_HANDLE, **paletteBuffer);
870 
871     VkDescriptorSet vecDescriptorSetBoth[2] = {*descriptorSetVert, *descriptorSetFrag};
872 
873     VkDescriptorSetLayout vecLayoutVert[2] = {*descriptorSetLayoutVert, VK_NULL_HANDLE};
874     VkDescriptorSetLayout vecLayoutFrag[2] = {VK_NULL_HANDLE, *descriptorSetLayoutFrag};
875     VkDescriptorSetLayout vecLayoutBoth[2] = {*descriptorSetLayoutVert, *descriptorSetLayoutFrag};
876 
877     VkPipelineLayoutCreateFlags pipelineLayoutCreateFlag = 0u;
878     if (!m_data.useMaintenance5 && (m_data.delayedShaderCreate || (m_data.pipelineTreeConfiguration.size() > 1)))
879         pipelineLayoutCreateFlag = VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT;
880 
881     const Move<VkCommandPool> cmdPool =
882         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
883     const Move<VkCommandBuffer> cmdBuffer =
884         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
885     const Move<VkPipelineLayout> pipelineLayoutSame =
886         makePipelineLayout(vk, device, 2, vecLayoutBoth, pipelineLayoutCreateFlag);
887     Move<VkPipelineLayout> pipelineLayoutVert;
888     Move<VkPipelineLayout> pipelineLayoutFrag;
889     Move<VkPipeline> rootPipeline;
890 
891     // Go through tree nodes and create library for each up to root
892     for (int32_t nodeNdx = nodeNdxLast; nodeNdx >= 0;
893          --nodeNdx) // We expect only backward node reference, thus build pipielines from end is safe
894     {
895         RuntimePipelineTreeNode &node                   = runtimePipelineTreeConfiguration[nodeNdx];
896         const bool buildLibrary                         = (nodeNdx != 0);
897         const VkPipelineCreateFlags pipelineCreateFlags = calcPipelineCreateFlags(optimize, buildLibrary);
898         const VkGraphicsPipelineLibraryFlagsEXT subtreeGraphicsPipelineLibraryFlags =
899             node.subtreeGraphicsPipelineLibraryFlags | node.graphicsPipelineLibraryFlags;
900         const bool samePipelineLayout = samePipelineFlags == (samePipelineFlags & subtreeGraphicsPipelineLibraryFlags);
901         const bool vertPipelineLayout = vertPipelineFlags == (vertPipelineFlags & subtreeGraphicsPipelineLibraryFlags);
902         const bool fragPipelineLayout = fragPipelineFlags == (fragPipelineFlags & subtreeGraphicsPipelineLibraryFlags);
903 
904         if (samePipelineLayout)
905             ; // pipelineLayoutSame is always built before.
906         else if (vertPipelineLayout)
907         {
908             if (!pipelineLayoutVert)
909                 pipelineLayoutVert = makePipelineLayout(vk, device, 2, vecLayoutVert, pipelineLayoutCreateFlag);
910         }
911         else if (fragPipelineLayout)
912         {
913             if (!pipelineLayoutFrag)
914                 pipelineLayoutFrag = makePipelineLayout(vk, device, 2, vecLayoutFrag, pipelineLayoutCreateFlag);
915         }
916 
917         const VkPipelineLayout pipelineLayout = samePipelineLayout ? *pipelineLayoutSame :
918                                                 vertPipelineLayout ? *pipelineLayoutVert :
919                                                 fragPipelineLayout ? *pipelineLayoutFrag :
920                                                                      VK_NULL_HANDLE;
921         const VkRenderPass renderPassHandle   = getRenderPass(node.graphicsPipelineLibraryFlags, *renderPass);
922         VkGraphicsPipelineLibraryCreateInfoEXT graphicsPipelineLibraryCreateInfo =
923             makeGraphicsPipelineLibraryCreateInfo(node.graphicsPipelineLibraryFlags);
924         VkPipelineLibraryCreateInfoKHR linkingInfo = makePipelineLibraryCreateInfo(node.pipelineLibraries);
925         GraphicsPipelineCreateInfo graphicsPipelineCreateInfo(pipelineLayout, renderPassHandle, 0, pipelineCreateFlags);
926 
927         for (const auto subsetFlag : GRAPHICS_PIPELINE_LIBRARY_FLAGS)
928         {
929             if ((node.graphicsPipelineLibraryFlags & subsetFlag) != 0)
930             {
931                 switch (subsetFlag)
932                 {
933                 case VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT:
934                     updateVertexInputInterface(m_context, graphicsPipelineCreateInfo);
935                     break;
936                 case VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT:
937                     updatePreRasterization(m_context, graphicsPipelineCreateInfo, delayedShaderCreate);
938                     break;
939                 case VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT:
940                     updatePostRasterization(m_context, graphicsPipelineCreateInfo, delayedShaderCreate);
941                     break;
942                 case VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT:
943                     updateFragmentOutputInterface(m_context, graphicsPipelineCreateInfo);
944                     break;
945                 default:
946                     TCU_THROW(InternalError, "Unknown pipeline subset");
947                 }
948             }
949         }
950 
951         VkGraphicsPipelineLibraryFlagsEXT linkedLibrariesFlags = 0;
952 
953         for (auto flag : node.linkedLibraryFlags)
954             linkedLibrariesFlags |= flag;
955 
956         // When pLibraries have any pipeline library with fragment shader state and current pipeline we try to create doesn't,
957         // we need to set a MS info.
958         if ((linkedLibrariesFlags & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) &&
959             !(node.graphicsPipelineLibraryFlags & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) &&
960             (graphicsPipelineCreateInfo.pMultisampleState == nullptr))
961         {
962             const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo =
963                 makePipelineMultisampleStateCreateInfo();
964 
965             graphicsPipelineCreateInfo.addState(pipelineMultisampleStateCreateInfo);
966         }
967 
968         if (!m_data.useMaintenance5 && linkedLibrariesFlags != ALL_GRAPHICS_PIPELINE_LIBRARY_FLAGS &&
969             graphicsPipelineLibraryCreateInfo.flags != 0)
970             appendStructurePtrToVulkanChain(&graphicsPipelineCreateInfo.pNext, &graphicsPipelineLibraryCreateInfo);
971 
972         if (linkingInfo.libraryCount != 0)
973         {
974             appendStructurePtrToVulkanChain(&graphicsPipelineCreateInfo.pNext, &linkingInfo);
975             graphicsPipelineCreateInfo.layout = *pipelineLayoutSame;
976         }
977 
978         linkedLibrariesFlags |= node.graphicsPipelineLibraryFlags;
979 
980         // if current pipeline that we try to create and pLibraries have all states of pipelines, we are not allowed to create a pipeline library.
981         if (linkedLibrariesFlags == ALL_GRAPHICS_PIPELINE_LIBRARY_FLAGS)
982         {
983             DE_ASSERT(!buildLibrary);
984             graphicsPipelineCreateInfo.flags &= ~VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
985         }
986 
987         node.pipeline = createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &graphicsPipelineCreateInfo);
988 
989         if (buildLibrary)
990         {
991             DE_ASSERT(de::inBounds(node.parentIndex, 0, static_cast<int32_t>(runtimePipelineTreeConfiguration.size())));
992 
993             runtimePipelineTreeConfiguration[node.parentIndex].pipelineLibraries.push_back(*node.pipeline);
994             runtimePipelineTreeConfiguration[node.parentIndex].linkedLibraryFlags.push_back(linkedLibrariesFlags);
995         }
996         else
997         {
998             DE_ASSERT(node.parentIndex == -1);
999 
1000             rootPipeline = node.pipeline;
1001         }
1002     }
1003 
1004     // Queue commands and read results.
1005     {
1006         const tcu::UVec2 renderSize                      = {RENDER_SIZE_WIDTH, RENDER_SIZE_HEIGHT};
1007         const VkRect2D renderArea                        = makeRect2D(renderSize.x(), renderSize.y());
1008         const de::MovePtr<BufferWithMemory> vertexBuffer = makeVertexBuffer();
1009         const uint32_t vertexCount                       = static_cast<uint32_t>(m_vertexData.size());
1010         const VkDeviceSize vertexBufferOffset            = 0;
1011         const Vec4 colorClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1012         const VkImageCreateInfo colorImageCreateInfo =
1013             makeColorImageCreateInfo(colorFormat, renderSize.x(), renderSize.y());
1014         const ImageWithMemory colorImage(vk, device, allocator, colorImageCreateInfo, MemoryRequirement::Any);
1015         const VkImageViewCreateInfo colorImageViewCreateInfo = makeImageViewCreateInfo(
1016             *colorImage, colorFormat, static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_COLOR_BIT));
1017         const Move<VkImageView> colorImageView = createImageView(vk, device, &colorImageViewCreateInfo);
1018         const VkImageCreateInfo depthImageCreateInfo =
1019             makeDepthImageCreateInfo(depthFormat, renderSize.x(), renderSize.y());
1020         const ImageWithMemory depthImage(vk, device, allocator, depthImageCreateInfo, MemoryRequirement::Any);
1021         const VkImageViewCreateInfo depthImageViewCreateInfo = makeImageViewCreateInfo(
1022             *depthImage, depthFormat, static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_DEPTH_BIT));
1023         const Move<VkImageView> depthImageView = createImageView(vk, device, &depthImageViewCreateInfo);
1024         const float depthClearDepth            = 1.0f;
1025         const uint32_t depthClearStencil       = 0u;
1026         const VkDeviceSize colorBufferDataSize =
1027             static_cast<VkDeviceSize>(renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)));
1028         const VkBufferCreateInfo colorBufferCreateInfo = makeBufferCreateInfo(
1029             colorBufferDataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1030         const BufferWithMemory colorBuffer(vk, device, allocator, colorBufferCreateInfo,
1031                                            MemoryRequirement::HostVisible);
1032         const VkDeviceSize depthBufferDataSize =
1033             static_cast<VkDeviceSize>(renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(depthFormat)));
1034         const VkBufferCreateInfo depthBufferCreateInfo = makeBufferCreateInfo(
1035             depthBufferDataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1036         const BufferWithMemory depthBuffer(vk, device, allocator, depthBufferCreateInfo,
1037                                            MemoryRequirement::HostVisible);
1038         const VkImageView attachments[]                     = {*colorImageView, *depthImageView};
1039         const VkFramebufferCreateInfo framebufferCreateInfo = makeFramebufferCreateInfo(
1040             *renderPass, DE_LENGTH_OF_ARRAY(attachments), attachments, renderSize.x(), renderSize.y());
1041         const Move<VkFramebuffer> framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
1042 
1043         vk::beginCommandBuffer(vk, *cmdBuffer, 0u);
1044         {
1045             beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, colorClearColor, depthClearDepth,
1046                             depthClearStencil);
1047             {
1048                 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer->get(), &vertexBufferOffset);
1049                 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *rootPipeline);
1050                 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayoutSame, 0u, 2u,
1051                                          vecDescriptorSetBoth, 0u, nullptr);
1052                 vk.cmdDraw(*cmdBuffer, vertexCount, 1u, 0u, 0u);
1053             }
1054             endRenderPass(vk, *cmdBuffer);
1055 
1056             const tcu::IVec2 size = {(int32_t)renderSize.x(), (int32_t)renderSize.y()};
1057             copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, size);
1058             copyImageToBuffer(vk, *cmdBuffer, *depthImage, *depthBuffer, size,
1059                               VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1060                               VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1u, VK_IMAGE_ASPECT_DEPTH_BIT,
1061                               VK_IMAGE_ASPECT_DEPTH_BIT);
1062         }
1063         vk::endCommandBuffer(vk, *cmdBuffer);
1064         vk::submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), cmdBuffer.get());
1065 
1066         vk::invalidateAlloc(vk, device, colorBuffer.getAllocation());
1067         vk::invalidateAlloc(vk, device, depthBuffer.getAllocation());
1068 
1069         const tcu::ConstPixelBufferAccess colorPixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1,
1070                                                            colorBuffer.getAllocation().getHostPtr());
1071         const tcu::ConstPixelBufferAccess depthPixelAccess(mapVkFormat(depthFormat), renderSize.x(), renderSize.y(), 1,
1072                                                            depthBuffer.getAllocation().getHostPtr());
1073 
1074         if (!verifyColorImage(colorPixelAccess))
1075         {
1076             log << tcu::TestLog::Image("color", "Rendered image", colorPixelAccess);
1077 
1078             return false;
1079         }
1080 
1081         if (!verifyDepthImage(depthPixelAccess))
1082         {
1083             log << tcu::TestLog::Image("depth", "Rendered image", depthPixelAccess);
1084 
1085             return false;
1086         }
1087     }
1088 
1089     return true;
1090 }
1091 
verifyColorImage(const ConstPixelBufferAccess & pba)1092 bool PipelineLibraryTestInstance::verifyColorImage(const ConstPixelBufferAccess &pba)
1093 {
1094     tcu::TestLog &log = m_context.getTestContext().getLog();
1095     TextureLevel referenceImage(pba.getFormat(), pba.getWidth(), pba.getHeight());
1096     PixelBufferAccess reference(referenceImage);
1097     const int horzEdge = 3 * reference.getWidth() / 4;
1098     const int vertEdge = reference.getHeight() / 2;
1099     const UVec4 green  = ivec2uvec(RGBA::green().toIVec());
1100     const UVec4 blue   = ivec2uvec(RGBA::blue().toIVec());
1101     const UVec4 black  = ivec2uvec(RGBA::black().toIVec());
1102 
1103     for (int y = 0; y < reference.getHeight(); ++y)
1104     {
1105         for (int x = 0; x < reference.getWidth(); ++x)
1106         {
1107             if (x < horzEdge)
1108             {
1109                 if (y < vertEdge)
1110                     reference.setPixel(green, x, y);
1111                 else
1112                     reference.setPixel(blue, x, y);
1113             }
1114             else
1115                 reference.setPixel(black, x, y);
1116         }
1117     }
1118 
1119     return intThresholdCompare(log, "colorImage", "colorImage", reference, pba, UVec4(), COMPARE_LOG_RESULT);
1120 }
1121 
verifyDepthImage(const ConstPixelBufferAccess & pba)1122 bool PipelineLibraryTestInstance::verifyDepthImage(const ConstPixelBufferAccess &pba)
1123 {
1124     tcu::TestLog &log            = m_context.getTestContext().getLog();
1125     const VkFormat compareFormat = VK_FORMAT_R8_UNORM;
1126     TextureLevel referenceImage(mapVkFormat(compareFormat), pba.getWidth(), pba.getHeight());
1127     PixelBufferAccess reference(referenceImage);
1128     TextureLevel resultImage(mapVkFormat(compareFormat), pba.getWidth(), pba.getHeight());
1129     PixelBufferAccess result(resultImage);
1130     const int horzEdge     = 3 * reference.getWidth() / 4;
1131     const int diagonalEdge = (reference.getWidth() + reference.getHeight()) / 2 - 1;
1132     const UVec4 red100     = ivec2uvec(RGBA::red().toIVec());
1133     const UVec4 red025     = UVec4(red100[0] / 4, red100[1] / 4, red100[2] / 4, red100[3]);
1134     const UVec4 red075     = UVec4(3 * red100[0] / 4, 3 * red100[1] / 4, 3 * red100[2] / 4, red100[3]);
1135 
1136     for (int y = 0; y < result.getHeight(); ++y)
1137         for (int x = 0; x < result.getWidth(); ++x)
1138         {
1139             const UVec4 pix(static_cast<uint32_t>(static_cast<float>(red100[0]) * pba.getPixDepth(x, y)), 0, 0, 0);
1140 
1141             result.setPixel(pix, x, y);
1142         }
1143 
1144     for (int y = 0; y < reference.getHeight(); ++y)
1145     {
1146         for (int x = 0; x < reference.getWidth(); ++x)
1147         {
1148             if (x < horzEdge)
1149             {
1150                 if (x + y < diagonalEdge)
1151                     reference.setPixel(red025, x, y);
1152                 else
1153                     reference.setPixel(red075, x, y);
1154             }
1155             else
1156                 reference.setPixel(red100, x, y);
1157         }
1158     }
1159 
1160     return intThresholdCompare(log, "depthImage", "depthImage", reference, result, UVec4(), COMPARE_LOG_RESULT);
1161 }
1162 
iterate(void)1163 tcu::TestStatus PipelineLibraryTestInstance::iterate(void)
1164 {
1165     VkGraphicsPipelineLibraryFlagBitsEXT graphicsPipelineLibraryFlags[] = {
1166         VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT,
1167         VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT,
1168         VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT,
1169         VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT,
1170     };
1171     const auto graphicsPipelineLibraryFlagsBegin = graphicsPipelineLibraryFlags;
1172     const auto graphicsPipelineLibraryFlagsEnd =
1173         graphicsPipelineLibraryFlags + DE_LENGTH_OF_ARRAY(graphicsPipelineLibraryFlags);
1174     uint32_t permutationId = 0;
1175     std::set<uint32_t> was;
1176     bool result = true;
1177 
1178     do
1179     {
1180         RuntimePipelineTreeConfiguration runtimePipelineTreeConfiguration(m_data.pipelineTreeConfiguration.size());
1181         size_t subsetNdxStart         = 0;
1182         uint32_t uniqueTreeSubsetCode = 0;
1183 
1184         for (size_t nodeNdx = 0; nodeNdx < runtimePipelineTreeConfiguration.size(); ++nodeNdx)
1185         {
1186             const uint32_t shaderCount    = m_data.pipelineTreeConfiguration[nodeNdx].shaderCount;
1187             RuntimePipelineTreeNode &node = runtimePipelineTreeConfiguration[nodeNdx];
1188 
1189             node.parentIndex                  = m_data.pipelineTreeConfiguration[nodeNdx].parentIndex;
1190             node.graphicsPipelineLibraryFlags = 0u;
1191 
1192             for (size_t subsetNdx = 0; subsetNdx < shaderCount; ++subsetNdx)
1193                 node.graphicsPipelineLibraryFlags |= static_cast<VkGraphicsPipelineLibraryFlagsEXT>(
1194                     graphicsPipelineLibraryFlags[subsetNdxStart + subsetNdx]);
1195 
1196             if (node.parentIndex > 0)
1197                 runtimePipelineTreeConfiguration[node.parentIndex].subtreeGraphicsPipelineLibraryFlags |=
1198                     node.graphicsPipelineLibraryFlags;
1199 
1200             // Each shader subset should be tested in each node of tree
1201             subsetNdxStart += shaderCount;
1202 
1203             uniqueTreeSubsetCode = (uniqueTreeSubsetCode << 4) | node.graphicsPipelineLibraryFlags;
1204         }
1205 
1206         // Check whether this configuration has been tried
1207         if (was.find(uniqueTreeSubsetCode) == was.end())
1208             was.insert(uniqueTreeSubsetCode);
1209         else
1210             continue;
1211 
1212         result = result && runTest(runtimePipelineTreeConfiguration, m_data.optimize, m_data.delayedShaderCreate);
1213 
1214         if (!result)
1215         {
1216             tcu::TestLog &log = m_context.getTestContext().getLog();
1217             std::ostringstream ess;
1218 
1219             for (size_t nodeNdx = 0; nodeNdx < runtimePipelineTreeConfiguration.size(); ++nodeNdx)
1220             {
1221                 const RuntimePipelineTreeNode &node = runtimePipelineTreeConfiguration[nodeNdx];
1222 
1223                 ess << node.parentIndex << " {";
1224 
1225                 for (size_t subsetNdx = 0; subsetNdx < DE_LENGTH_OF_ARRAY(graphicsPipelineLibraryFlags); ++subsetNdx)
1226                 {
1227                     if ((node.graphicsPipelineLibraryFlags & graphicsPipelineLibraryFlags[subsetNdx]) == 0)
1228                         continue;
1229 
1230                     ess << getGraphicsPipelineLibraryFlagsString(graphicsPipelineLibraryFlags[subsetNdx]) << " ";
1231                 }
1232 
1233                 ess << "}" << std::endl;
1234             }
1235 
1236             log << tcu::TestLog::Message << ess.str() << tcu::TestLog::EndMessage;
1237 
1238             return tcu::TestStatus::fail("At permutation " + de::toString(permutationId));
1239         }
1240 
1241         ++permutationId;
1242     } while (std::next_permutation(graphicsPipelineLibraryFlagsBegin, graphicsPipelineLibraryFlagsEnd));
1243 
1244     return tcu::TestStatus::pass("OK");
1245 }
1246 
1247 class PipelineLibraryTestCase : public TestCase
1248 {
1249 public:
1250     PipelineLibraryTestCase(tcu::TestContext &context, const char *name, const TestParams data);
1251     ~PipelineLibraryTestCase(void);
1252 
1253     virtual void checkSupport(Context &context) const;
1254     virtual void initPrograms(SourceCollections &programCollection) const;
1255     virtual TestInstance *createInstance(Context &context) const;
1256 
1257 private:
1258     TestParams m_data;
1259 };
1260 
PipelineLibraryTestCase(tcu::TestContext & context,const char * name,const TestParams data)1261 PipelineLibraryTestCase::PipelineLibraryTestCase(tcu::TestContext &context, const char *name, const TestParams data)
1262     : vkt::TestCase(context, name)
1263     , m_data(data)
1264 {
1265 }
1266 
~PipelineLibraryTestCase(void)1267 PipelineLibraryTestCase::~PipelineLibraryTestCase(void)
1268 {
1269 }
1270 
checkSupport(Context & context) const1271 void PipelineLibraryTestCase::checkSupport(Context &context) const
1272 {
1273     if (m_data.useMaintenance5)
1274     {
1275         context.requireDeviceFunctionality("VK_KHR_maintenance5");
1276         return;
1277     }
1278 
1279     context.requireDeviceFunctionality("VK_KHR_pipeline_library");
1280 
1281     if (m_data.delayedShaderCreate || (m_data.pipelineTreeConfiguration.size() > 1))
1282     {
1283         context.requireDeviceFunctionality("VK_EXT_graphics_pipeline_library");
1284 
1285         const VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT &graphicsPipelineLibraryFeaturesEXT =
1286             context.getGraphicsPipelineLibraryFeaturesEXT();
1287 
1288         if (!graphicsPipelineLibraryFeaturesEXT.graphicsPipelineLibrary)
1289             TCU_THROW(NotSupportedError, "graphicsPipelineLibraryFeaturesEXT.graphicsPipelineLibrary required");
1290     }
1291 }
1292 
initPrograms(SourceCollections & programCollection) const1293 void PipelineLibraryTestCase::initPrograms(SourceCollections &programCollection) const
1294 {
1295     std::string vert = "#version 450\n"
1296                        "layout(location = 0) in vec4 in_position;\n"
1297                        "layout(set = 0, binding = 0) uniform buf\n"
1298                        "{\n"
1299                        "  vec4 z_coord;\n"
1300                        "};\n"
1301                        "\n"
1302                        "out gl_PerVertex\n"
1303                        "{\n"
1304                        "  vec4 gl_Position;\n"
1305                        "};\n"
1306                        "\n"
1307                        "void main()\n"
1308                        "{\n"
1309                        "  const float z = gl_VertexIndex < 3 ? z_coord.x : z_coord.y;\n"
1310                        "  gl_Position = vec4(in_position.x, in_position.y, z, 1.0f);\n"
1311                        "}\n";
1312 
1313     programCollection.glslSources.add("vert") << glu::VertexSource(vert);
1314 
1315     std::string frag = "#version 450\n"
1316                        "layout(location = 0) out highp vec4 o_color;\n"
1317                        "layout(set = 1, binding = 1) uniform buf\n"
1318                        "{\n"
1319                        "  vec4 colorTop;\n"
1320                        "  vec4 colorBot;\n"
1321                        "};\n"
1322                        "\n"
1323                        "void main()\n"
1324                        "{\n"
1325                        "  const int middle = " +
1326                        de::toString(RENDER_SIZE_HEIGHT / 2) +
1327                        ";\n"
1328                        "  o_color          = int(gl_FragCoord.y - 0.5f) < middle ? colorTop : colorBot;\n"
1329                        "}\n";
1330 
1331     programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
1332 }
1333 
createInstance(Context & context) const1334 TestInstance *PipelineLibraryTestCase::createInstance(Context &context) const
1335 {
1336     return new PipelineLibraryTestInstance(context, m_data);
1337 }
1338 
1339 enum class MiscTestMode
1340 {
1341     INDEPENDENT_PIPELINE_LAYOUT_SETS_FAST_LINKED = 0,
1342     INDEPENDENT_PIPELINE_LAYOUT_SETS_WITH_LINK_TIME_OPTIMIZATION_UNION_HANDLE,
1343     BIND_NULL_DESCRIPTOR_SET,
1344     BIND_NULL_DESCRIPTOR_SET_IN_MONOLITHIC_PIPELINE,
1345     COMPARE_LINK_TIMES,
1346     SHADER_MODULE_CREATE_INFO_COMP,
1347     SHADER_MODULE_CREATE_INFO_RT,
1348     SHADER_MODULE_CREATE_INFO_RT_LIB,
1349     NULL_RENDERING_CREATE_INFO,
1350     COMMON_FRAG_LIBRARY,
1351     VIEW_INDEX_FROM_DEVICE_INDEX_IN_ALL_STAGES,
1352     VIEW_INDEX_FROM_DEVICE_INDEX_IN_PRE_RASTERIZATION,
1353     VIEW_INDEX_FROM_DEVICE_INDEX_IN_FRAGMENT,
1354     VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_STAGES,
1355     VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_PRE_RASTERIZATION,
1356     VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_FRAGMENT,
1357     UNUSUAL_MULTISAMPLE_STATE,
1358 };
1359 
1360 struct MiscTestParams
1361 {
1362     MiscTestMode mode;
1363 
1364     // attributes used in BIND_NULL_DESCRIPTOR_SET mode
1365     uint32_t layoutsCount;
1366     uint32_t layoutsBits;
1367 };
1368 
1369 class PipelineLibraryMiscTestInstance : public TestInstance
1370 {
1371 public:
1372     PipelineLibraryMiscTestInstance(Context &context, const MiscTestParams &params);
1373     ~PipelineLibraryMiscTestInstance(void) = default;
1374     tcu::TestStatus iterate(void);
1375 
1376 protected:
1377     tcu::TestStatus runNullDescriptorSet(void);
1378     tcu::TestStatus runNullDescriptorSetInMonolithicPipeline(void);
1379     tcu::TestStatus runIndependentPipelineLayoutSets(bool useLinkTimeOptimization = false);
1380     tcu::TestStatus runCompareLinkTimes(void);
1381     tcu::TestStatus runCommonFragLibraryTest(void);
1382 
1383     struct VerificationData
1384     {
1385         const tcu::IVec2 point;
1386         const tcu::IVec4 color;
1387     };
1388     tcu::TestStatus verifyResult(const std::vector<VerificationData> &verificationData,
1389                                  const tcu::ConstPixelBufferAccess &colorPixelAccess) const;
1390     // verification for test mode: COMMON_FRAG_LIBRARY_FAST_LINKED
1391     bool verifyOnePipelineLibraryResult(const tcu::ConstPixelBufferAccess &colorPixelAccess, const int numBars) const;
1392 
1393 private:
1394     MiscTestParams m_testParams;
1395     const VkFormat m_colorFormat;
1396     const Vec4 m_colorClearColor;
1397     const VkRect2D m_renderArea;
1398 
1399     de::MovePtr<ImageWithMemory> m_colorImage;
1400     Move<VkImageView> m_colorImageView;
1401 
1402     Move<VkRenderPass> m_renderPass;
1403     Move<VkFramebuffer> m_framebuffer;
1404 
1405     Move<VkCommandPool> m_cmdPool;
1406     Move<VkCommandBuffer> m_cmdBuffer;
1407 };
1408 
PipelineLibraryMiscTestInstance(Context & context,const MiscTestParams & params)1409 PipelineLibraryMiscTestInstance::PipelineLibraryMiscTestInstance(Context &context, const MiscTestParams &params)
1410     : vkt::TestInstance(context)
1411     , m_testParams(params)
1412     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
1413     , m_colorClearColor(0.0f, 0.0f, 0.0f, 1.0f)
1414     , m_renderArea(makeRect2D(RENDER_SIZE_WIDTH, RENDER_SIZE_HEIGHT))
1415 {
1416 }
1417 
iterate(void)1418 tcu::TestStatus PipelineLibraryMiscTestInstance::iterate(void)
1419 {
1420     const DeviceInterface &vk = m_context.getDeviceInterface();
1421     const VkDevice device     = m_context.getDevice();
1422     Allocator &allocator      = m_context.getDefaultAllocator();
1423 
1424     // create image and image view that will hold rendered frame
1425     const VkImageCreateInfo colorImageCreateInfo =
1426         makeColorImageCreateInfo(m_colorFormat, m_renderArea.extent.width, m_renderArea.extent.height);
1427     m_colorImage = de::MovePtr<ImageWithMemory>(
1428         new ImageWithMemory(vk, device, allocator, colorImageCreateInfo, MemoryRequirement::Any));
1429     const VkImageViewCreateInfo colorImageViewCreateInfo = makeImageViewCreateInfo(
1430         **m_colorImage, m_colorFormat, static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_COLOR_BIT));
1431     const Move<VkImageView> colorImageView = createImageView(vk, device, &colorImageViewCreateInfo);
1432 
1433     // create renderpass and framebuffer
1434     m_renderPass                                        = makeRenderPass(vk, device, m_colorFormat);
1435     const VkFramebufferCreateInfo framebufferCreateInfo = makeFramebufferCreateInfo(
1436         *m_renderPass, 1u, &*colorImageView, m_renderArea.extent.width, m_renderArea.extent.height);
1437     m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
1438 
1439     // create command pool and command buffer
1440     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1441     m_cmdPool   = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
1442     m_cmdBuffer = allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1443 
1444     // run selected test
1445     if (m_testParams.mode == MiscTestMode::BIND_NULL_DESCRIPTOR_SET)
1446         return runNullDescriptorSet();
1447     else if (m_testParams.mode == MiscTestMode::BIND_NULL_DESCRIPTOR_SET_IN_MONOLITHIC_PIPELINE)
1448         return runNullDescriptorSetInMonolithicPipeline();
1449     else if (m_testParams.mode == MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_FAST_LINKED)
1450         return runIndependentPipelineLayoutSets();
1451     else if (m_testParams.mode ==
1452              MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_WITH_LINK_TIME_OPTIMIZATION_UNION_HANDLE)
1453         return runIndependentPipelineLayoutSets(true);
1454     else if (m_testParams.mode == MiscTestMode::COMPARE_LINK_TIMES)
1455         return runCompareLinkTimes();
1456     else if (m_testParams.mode == MiscTestMode::COMMON_FRAG_LIBRARY)
1457         return runCommonFragLibraryTest();
1458 
1459     DE_ASSERT(false);
1460     return tcu::TestStatus::fail("Fail");
1461 }
1462 
runNullDescriptorSet(void)1463 tcu::TestStatus PipelineLibraryMiscTestInstance::runNullDescriptorSet(void)
1464 {
1465     const DeviceInterface &vk = m_context.getDeviceInterface();
1466     const VkDevice device     = m_context.getDevice();
1467     Allocator &allocator      = m_context.getDefaultAllocator();
1468 
1469     const VkDeviceSize colorBufferDataSize = static_cast<VkDeviceSize>(
1470         m_renderArea.extent.width * m_renderArea.extent.height * tcu::getPixelSize(mapVkFormat(m_colorFormat)));
1471     const VkBufferCreateInfo colorBufferCreateInfo = makeBufferCreateInfo(
1472         colorBufferDataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1473     const BufferWithMemory colorBuffer(vk, device, allocator, colorBufferCreateInfo, MemoryRequirement::HostVisible);
1474 
1475     VkDeviceSize uniformBufferDataSize = sizeof(tcu::Vec4);
1476     const VkBufferCreateInfo uniformBufferCreateInfo =
1477         makeBufferCreateInfo(uniformBufferDataSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1478     de::MovePtr<BufferWithMemory> uniformBuffer[2];
1479 
1480     // setup data in uniform buffers that will give us expected result for validation
1481     const tcu::Vec4 uniformBuffData[]{
1482         {-1.00f, 1.00f, 2.0f, -2.00f},
1483         {0.00f, 0.20f, 0.6f, 0.75f},
1484     };
1485 
1486     for (uint32_t i = 0; i < 2; ++i)
1487     {
1488         uniformBuffer[i] = de::MovePtr<BufferWithMemory>(
1489             new BufferWithMemory(vk, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
1490         deMemcpy(uniformBuffer[i]->getAllocation().getHostPtr(), uniformBuffData[i].getPtr(),
1491                  (size_t)uniformBufferDataSize);
1492         flushAlloc(vk, device, uniformBuffer[i]->getAllocation());
1493     }
1494 
1495     const uint32_t maxBitsCount = 8 * sizeof(m_testParams.layoutsBits);
1496     VkDescriptorSetLayout vertDescriptorSetLayouts[maxBitsCount];
1497     VkDescriptorSetLayout fragDescriptorSetLayouts[maxBitsCount];
1498     VkDescriptorSetLayout allDescriptorSetLayouts[maxBitsCount];
1499 
1500     // set all layouts to NULL
1501     deMemset(&vertDescriptorSetLayouts, 0, maxBitsCount * sizeof(VkDescriptorSetLayout));
1502     deMemset(&fragDescriptorSetLayouts, 0, maxBitsCount * sizeof(VkDescriptorSetLayout));
1503 
1504     // create used descriptor set layouts
1505     Move<VkDescriptorSetLayout> usedDescriptorSetLayouts[]{
1506         DescriptorSetLayoutBuilder()
1507             .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT)
1508             .build(vk, device),
1509         DescriptorSetLayoutBuilder()
1510             .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
1511             .build(vk, device)};
1512 
1513     // create descriptor set layouts that are not used by shaders in test - finalPipelineLayout,
1514     // needs to always be the complete pipeline layout with no holes; we can put NULLs in
1515     // DescriptorSetLayouts used by partial pipelines (vertDescriptorSetLayouts and fragDescriptorSetLayouts)
1516     Move<VkDescriptorSetLayout> unusedDescriptorSetLayouts[maxBitsCount];
1517     for (uint32_t i = 0u; i < m_testParams.layoutsCount; ++i)
1518     {
1519         unusedDescriptorSetLayouts[i] = DescriptorSetLayoutBuilder().build(vk, device);
1520 
1521         // by default allDescriptorSetLayouts is filled with unused layouts but later
1522         // if test requires this proper indexes are replaced with used layouts
1523         allDescriptorSetLayouts[i] = *unusedDescriptorSetLayouts[i];
1524     }
1525 
1526     VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = initVulkanStructure();
1527     pipelineLayoutCreateInfo.flags                      = VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT;
1528 
1529     // find set bits
1530     std::vector<uint32_t> bitsThatAreSet;
1531     for (uint32_t i = 0u; i < m_testParams.layoutsCount; ++i)
1532     {
1533         if (m_testParams.layoutsBits & (1 << (maxBitsCount - 1 - i)))
1534             bitsThatAreSet.push_back(i);
1535     }
1536 
1537     uint32_t usedDescriptorSets = static_cast<uint32_t>(bitsThatAreSet.size());
1538     DE_ASSERT(usedDescriptorSets && (usedDescriptorSets < 3u));
1539 
1540     uint32_t vertSetIndex                   = bitsThatAreSet[0];
1541     uint32_t fragSetIndex                   = 0u;
1542     vertDescriptorSetLayouts[vertSetIndex]  = *usedDescriptorSetLayouts[0];
1543     allDescriptorSetLayouts[vertSetIndex]   = *usedDescriptorSetLayouts[0];
1544     pipelineLayoutCreateInfo.setLayoutCount = vertSetIndex + 1u;
1545     pipelineLayoutCreateInfo.pSetLayouts    = vertDescriptorSetLayouts;
1546 
1547     Move<VkPipelineLayout> vertPipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1548     Move<VkPipelineLayout> fragPipelineLayout;
1549 
1550     if (usedDescriptorSets == 2u)
1551     {
1552         fragSetIndex                            = bitsThatAreSet[1];
1553         fragDescriptorSetLayouts[fragSetIndex]  = *usedDescriptorSetLayouts[1];
1554         allDescriptorSetLayouts[fragSetIndex]   = *usedDescriptorSetLayouts[1];
1555         pipelineLayoutCreateInfo.setLayoutCount = fragSetIndex + 1u;
1556         pipelineLayoutCreateInfo.pSetLayouts    = fragDescriptorSetLayouts;
1557 
1558         fragPipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1559     }
1560     else
1561     {
1562         pipelineLayoutCreateInfo.setLayoutCount = 0u;
1563         pipelineLayoutCreateInfo.pSetLayouts    = nullptr;
1564         fragPipelineLayout                      = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1565     }
1566 
1567     // create descriptor pool
1568     Move<VkDescriptorPool> descriptorPool =
1569         DescriptorPoolBuilder()
1570             .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, usedDescriptorSets)
1571             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, usedDescriptorSets);
1572 
1573     const VkDescriptorBufferInfo vertShaderBufferInfo =
1574         makeDescriptorBufferInfo(**uniformBuffer[0], 0u, uniformBufferDataSize);
1575     Move<VkDescriptorSet> vertDescriptorSet =
1576         makeDescriptorSet(vk, device, *descriptorPool, *usedDescriptorSetLayouts[0]);
1577     Move<VkDescriptorSet> fragDescriptorSet;
1578 
1579     if (usedDescriptorSets == 1u)
1580     {
1581         // update single descriptors with actual buffer
1582         DescriptorSetUpdateBuilder()
1583             .writeSingle(*vertDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1584                          VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &vertShaderBufferInfo)
1585             .update(vk, device);
1586     }
1587     else
1588     {
1589         const VkDescriptorBufferInfo fragShaderBufferInfo =
1590             makeDescriptorBufferInfo(**uniformBuffer[1], 0u, uniformBufferDataSize);
1591         fragDescriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *usedDescriptorSetLayouts[1]);
1592 
1593         // update both descriptors with actual buffers
1594         DescriptorSetUpdateBuilder()
1595             .writeSingle(*vertDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1596                          VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &vertShaderBufferInfo)
1597             .writeSingle(*fragDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1598                          VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &fragShaderBufferInfo)
1599             .update(vk, device);
1600     }
1601 
1602     pipelineLayoutCreateInfo.setLayoutCount    = m_testParams.layoutsCount;
1603     pipelineLayoutCreateInfo.pSetLayouts       = allDescriptorSetLayouts;
1604     Move<VkPipelineLayout> finalPipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1605 
1606     const uint32_t commonPipelinePartFlags = uint32_t(VK_PIPELINE_CREATE_LIBRARY_BIT_KHR);
1607     GraphicsPipelineCreateInfo partialPipelineCreateInfo[]{
1608         {*vertPipelineLayout, *m_renderPass, 0, commonPipelinePartFlags},
1609         {*fragPipelineLayout, *m_renderPass, 0, commonPipelinePartFlags},
1610     };
1611 
1612     // fill proper portion of pipeline state
1613     updateVertexInputInterface(m_context, partialPipelineCreateInfo[0], VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0u);
1614     updatePreRasterization(m_context, partialPipelineCreateInfo[0], false);
1615     updatePostRasterization(m_context, partialPipelineCreateInfo[1], false);
1616     updateFragmentOutputInterface(m_context, partialPipelineCreateInfo[1]);
1617 
1618     Move<VkPipeline> vertPipelinePart;
1619     Move<VkPipeline> fragPipelinePart;
1620 
1621     // extend pNext chain and create partial pipelines
1622     {
1623         VkGraphicsPipelineLibraryCreateInfoEXT libraryCreateInfo =
1624             makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT |
1625                                                   VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT);
1626         appendStructurePtrToVulkanChain(&partialPipelineCreateInfo[0].pNext, &libraryCreateInfo);
1627         vertPipelinePart = createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &partialPipelineCreateInfo[0]);
1628 
1629         libraryCreateInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT |
1630                                   VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT,
1631         appendStructurePtrToVulkanChain(&partialPipelineCreateInfo[1].pNext, &libraryCreateInfo);
1632         fragPipelinePart = createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &partialPipelineCreateInfo[1]);
1633     }
1634 
1635     // create final pipeline out of two parts
1636     std::vector<VkPipeline> rawParts               = {*vertPipelinePart, *fragPipelinePart};
1637     VkPipelineLibraryCreateInfoKHR linkingInfo     = makePipelineLibraryCreateInfo(rawParts);
1638     VkGraphicsPipelineCreateInfo finalPipelineInfo = initVulkanStructure();
1639 
1640     finalPipelineInfo.layout = *finalPipelineLayout;
1641     appendStructurePtrToVulkanChain(&finalPipelineInfo.pNext, &linkingInfo);
1642     Move<VkPipeline> pipeline = createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &finalPipelineInfo);
1643 
1644     vk::beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1645     {
1646         // change color image layout
1647         const VkImageMemoryBarrier initialImageBarrier = makeImageMemoryBarrier(
1648             0,                                          // VkAccessFlags srcAccessMask;
1649             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,       // VkAccessFlags dstAccessMask;
1650             VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout oldLayout;
1651             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout newLayout;
1652             **m_colorImage,                             // VkImage image;
1653             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
1654         );
1655         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1656                               VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, nullptr, 0,
1657                               nullptr, 1, &initialImageBarrier);
1658 
1659         // wait for uniform buffers
1660         std::vector<VkBufferMemoryBarrier> initialBufferBarriers(
1661             2u, makeBufferMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT,    // VkAccessFlags2KHR                srcAccessMask
1662                                         VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags2KHR                dstAccessMask
1663                                         uniformBuffer[0]->get(),     // VkBuffer                            buffer
1664                                         0u,                          // VkDeviceSize                        offset
1665                                         uniformBufferDataSize        // VkDeviceSize                        size
1666                                         ));
1667         initialBufferBarriers[1].buffer = uniformBuffer[1]->get();
1668         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1669                               (VkDependencyFlags)0, 0, nullptr, 2, initialBufferBarriers.data(), 0, nullptr);
1670 
1671         beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, m_renderArea, m_colorClearColor);
1672 
1673         vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1674 
1675         vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *finalPipelineLayout, vertSetIndex, 1u,
1676                                  &*vertDescriptorSet, 0u, nullptr);
1677         if (usedDescriptorSets == 2u)
1678             vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *finalPipelineLayout, fragSetIndex,
1679                                      1u, &*fragDescriptorSet, 0u, nullptr);
1680 
1681         vk.cmdDraw(*m_cmdBuffer, 4, 1u, 0u, 0u);
1682 
1683         endRenderPass(vk, *m_cmdBuffer);
1684 
1685         const tcu::IVec2 size{(int32_t)m_renderArea.extent.width, (int32_t)m_renderArea.extent.height};
1686         copyImageToBuffer(vk, *m_cmdBuffer, **m_colorImage, *colorBuffer, size);
1687     }
1688     vk::endCommandBuffer(vk, *m_cmdBuffer);
1689     vk::submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *m_cmdBuffer);
1690 
1691     vk::invalidateAlloc(vk, device, colorBuffer.getAllocation());
1692     const tcu::ConstPixelBufferAccess colorPixelAccess(mapVkFormat(m_colorFormat), m_renderArea.extent.width,
1693                                                        m_renderArea.extent.height, 1,
1694                                                        colorBuffer.getAllocation().getHostPtr());
1695 
1696     // verify result
1697     int32_t width  = (int32_t)m_renderArea.extent.width;
1698     int32_t height = (int32_t)m_renderArea.extent.height;
1699     const std::vector<VerificationData> verificationData{
1700         {{1, 1}, {0, 51, 153, 191}}, // note COLOR_COMPONENTS_NO_RED is used
1701         {{width / 2, height / 2}, {0, 51, 153, 191}},
1702         {{width - 2, height - 2}, {0, 0, 0, 255}} // clear color
1703     };
1704     return verifyResult(verificationData, colorPixelAccess);
1705 }
1706 
runNullDescriptorSetInMonolithicPipeline()1707 tcu::TestStatus PipelineLibraryMiscTestInstance::runNullDescriptorSetInMonolithicPipeline()
1708 {
1709     // VK_NULL_HANDLE can be used for descriptor set layouts when creating a pipeline layout whether independent sets are used or not,
1710     // as long as graphics pipeline libraries are enabled; VK_NULL_HANDLE is also alowed for a descriptor set under the same conditions
1711     // when using vkCmdBindDescriptorSets
1712 
1713     const DeviceInterface &vk = m_context.getDeviceInterface();
1714     const VkDevice device     = m_context.getDevice();
1715     Allocator &allocator      = m_context.getDefaultAllocator();
1716 
1717     const VkDeviceSize colorBufferDataSize = static_cast<VkDeviceSize>(
1718         m_renderArea.extent.width * m_renderArea.extent.height * tcu::getPixelSize(mapVkFormat(m_colorFormat)));
1719     const VkBufferCreateInfo colorBufferCreateInfo = makeBufferCreateInfo(
1720         colorBufferDataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1721     const BufferWithMemory colorBuffer(vk, device, allocator, colorBufferCreateInfo, MemoryRequirement::HostVisible);
1722 
1723     const tcu::Vec4 uniformBuffData{0.0f, 0.20f, 0.6f, 0.75f};
1724     VkDeviceSize uniformBufferDataSize = sizeof(tcu::Vec4);
1725     const VkBufferCreateInfo uniformBufferCreateInfo =
1726         makeBufferCreateInfo(uniformBufferDataSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1727 
1728     de::MovePtr<BufferWithMemory> uniformBuffer = de::MovePtr<BufferWithMemory>(
1729         new BufferWithMemory(vk, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
1730     deMemcpy(uniformBuffer->getAllocation().getHostPtr(), uniformBuffData.getPtr(), (size_t)uniformBufferDataSize);
1731     flushAlloc(vk, device, uniformBuffer->getAllocation());
1732 
1733     // create descriptor set layouts - first unused, second used
1734     Move<VkDescriptorSetLayout> descriptorSetLayout{
1735         DescriptorSetLayoutBuilder()
1736             .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
1737             .build(vk, device)};
1738 
1739     Move<VkDescriptorPool> allDescriptorPool =
1740         DescriptorPoolBuilder()
1741             .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1)
1742             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
1743 
1744     // create descriptor set
1745     Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *allDescriptorPool, *descriptorSetLayout);
1746 
1747     // update descriptor with actual buffer
1748     const VkDescriptorBufferInfo shaderBufferInfo =
1749         makeDescriptorBufferInfo(**uniformBuffer, 0u, uniformBufferDataSize);
1750     DescriptorSetUpdateBuilder()
1751         .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1752                      VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &shaderBufferInfo)
1753         .update(vk, device);
1754 
1755     // create a pipeline layout with its first descriptor set layout as VK_NULL_HANDLE
1756     // and a second with a valid descriptor set layout containing a buffer
1757     VkDescriptorSet rawDescriptorSets[]             = {VK_NULL_HANDLE, *descriptorSet};
1758     VkDescriptorSetLayout rawDescriptorSetLayouts[] = {VK_NULL_HANDLE, *descriptorSetLayout};
1759 
1760     VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = initVulkanStructure();
1761     pipelineLayoutCreateInfo.setLayoutCount             = 2u;
1762     pipelineLayoutCreateInfo.pSetLayouts                = rawDescriptorSetLayouts;
1763     Move<VkPipelineLayout> pipelineLayout               = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1764 
1765     // create monolithic graphics pipeline
1766     GraphicsPipelineCreateInfo pipelineCreateInfo(*pipelineLayout, *m_renderPass, 0, 0u);
1767     updateVertexInputInterface(m_context, pipelineCreateInfo, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0u);
1768     updatePreRasterization(m_context, pipelineCreateInfo, false);
1769     updatePostRasterization(m_context, pipelineCreateInfo, false);
1770     updateFragmentOutputInterface(m_context, pipelineCreateInfo);
1771     Move<VkPipeline> pipeline = createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &pipelineCreateInfo);
1772 
1773     vk::beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1774     {
1775         // change color image layout
1776         const VkImageMemoryBarrier initialImageBarrier = makeImageMemoryBarrier(
1777             0,                                          // VkAccessFlags srcAccessMask;
1778             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,       // VkAccessFlags dstAccessMask;
1779             VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout oldLayout;
1780             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout newLayout;
1781             **m_colorImage,                             // VkImage image;
1782             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
1783         );
1784         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1785                               VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, nullptr, 0,
1786                               nullptr, 1, &initialImageBarrier);
1787 
1788         // wait for uniform buffer
1789         const VkBufferMemoryBarrier initialBufferBarrier =
1790             makeBufferMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT,   // VkAccessFlags2KHR                srcAccessMask
1791                                     VK_ACCESS_UNIFORM_READ_BIT, // VkAccessFlags2KHR                dstAccessMask
1792                                     uniformBuffer->get(),       // VkBuffer                            buffer
1793                                     0u,                         // VkDeviceSize                        offset
1794                                     uniformBufferDataSize       // VkDeviceSize                        size
1795             );
1796         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
1797                               (VkDependencyFlags)0, 0, nullptr, 1, &initialBufferBarrier, 0, nullptr);
1798 
1799         beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, m_renderArea, m_colorClearColor);
1800 
1801         vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1802         vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 2u,
1803                                  rawDescriptorSets, 0u, nullptr);
1804         vk.cmdDraw(*m_cmdBuffer, 4, 1u, 0u, 0u);
1805 
1806         endRenderPass(vk, *m_cmdBuffer);
1807 
1808         const tcu::IVec2 size{(int32_t)m_renderArea.extent.width, (int32_t)m_renderArea.extent.height};
1809         copyImageToBuffer(vk, *m_cmdBuffer, **m_colorImage, *colorBuffer, size);
1810     }
1811     vk::endCommandBuffer(vk, *m_cmdBuffer);
1812     vk::submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *m_cmdBuffer);
1813 
1814     vk::invalidateAlloc(vk, device, colorBuffer.getAllocation());
1815     const tcu::ConstPixelBufferAccess colorPixelAccess(mapVkFormat(m_colorFormat), m_renderArea.extent.width,
1816                                                        m_renderArea.extent.height, 1,
1817                                                        colorBuffer.getAllocation().getHostPtr());
1818 
1819     // verify result
1820     int32_t width  = (int32_t)m_renderArea.extent.width;
1821     int32_t height = (int32_t)m_renderArea.extent.height;
1822     tcu::IVec4 outColor{0, // r is 0 because COLOR_COMPONENTS_NO_RED is used
1823                         static_cast<int>(uniformBuffData[1] * 255), static_cast<int>(uniformBuffData[2] * 255),
1824                         static_cast<int>(uniformBuffData[3] * 255)};
1825     const std::vector<VerificationData> verificationData{
1826         {{1, 1}, outColor},
1827         {{width / 2, height / 2}, outColor},
1828         {{width - 2, height - 2}, {0, 0, 0, 255}} // clear color
1829     };
1830 
1831     return verifyResult(verificationData, colorPixelAccess);
1832 }
1833 
runIndependentPipelineLayoutSets(bool useLinkTimeOptimization)1834 tcu::TestStatus PipelineLibraryMiscTestInstance::runIndependentPipelineLayoutSets(bool useLinkTimeOptimization)
1835 {
1836     const DeviceInterface &vk = m_context.getDeviceInterface();
1837     const VkDevice device     = m_context.getDevice();
1838     Allocator &allocator      = m_context.getDefaultAllocator();
1839 
1840     const VkDeviceSize colorBufferDataSize = static_cast<VkDeviceSize>(
1841         m_renderArea.extent.width * m_renderArea.extent.height * tcu::getPixelSize(mapVkFormat(m_colorFormat)));
1842     const VkBufferCreateInfo colorBufferCreateInfo = makeBufferCreateInfo(
1843         colorBufferDataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1844     const BufferWithMemory colorBuffer(vk, device, allocator, colorBufferCreateInfo, MemoryRequirement::HostVisible);
1845 
1846     VkDeviceSize uniformBufferDataSize = sizeof(tcu::Vec4);
1847     const VkBufferCreateInfo uniformBufferCreateInfo =
1848         makeBufferCreateInfo(uniformBufferDataSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1849 
1850     de::MovePtr<BufferWithMemory> uniformBuffer[3];
1851 
1852     // setup data in uniform buffers that will give us expected result for validation
1853     const tcu::Vec4 uniformBuffData[3]{
1854         {4.00f, 3.00f, -1.0f, 4.00f},
1855         {0.10f, 0.25f, -0.5f, 0.05f},
1856         {-5.00f, -2.00f, 3.0f, -6.00f},
1857     };
1858 
1859     for (uint32_t i = 0; i < 3; ++i)
1860     {
1861         uniformBuffer[i] = de::MovePtr<BufferWithMemory>(
1862             new BufferWithMemory(vk, device, allocator, uniformBufferCreateInfo, MemoryRequirement::HostVisible));
1863         deMemcpy(uniformBuffer[i]->getAllocation().getHostPtr(), uniformBuffData[i].getPtr(),
1864                  (size_t)uniformBufferDataSize);
1865         flushAlloc(vk, device, uniformBuffer[i]->getAllocation());
1866     }
1867 
1868     // create three descriptor set layouts
1869     Move<VkDescriptorSetLayout> descriptorSetLayouts[3];
1870     descriptorSetLayouts[0] = DescriptorSetLayoutBuilder()
1871                                   .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
1872                                                     VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
1873                                   .build(vk, device);
1874     descriptorSetLayouts[1] = DescriptorSetLayoutBuilder()
1875                                   .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
1876                                   .build(vk, device);
1877     descriptorSetLayouts[2] = DescriptorSetLayoutBuilder()
1878                                   .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT)
1879                                   .build(vk, device);
1880 
1881     // for the link time opt (and when null handle is used) use total pipeline layout recreated without the INDEPENDENT SETS bit
1882     uint32_t allLayoutsFlag = uint32_t(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
1883     if (useLinkTimeOptimization)
1884         allLayoutsFlag = 0u;
1885 
1886     // Pre-rasterization stage library has sets 0, 1, 2
1887     // * set 0 has descriptors
1888     // * set 1 has no descriptors
1889     // * set 2 has descriptors
1890     // Fragment stage library has sets 0, 1
1891     // * set 0 has descriptors
1892     // * set 1 has descriptors
1893     VkDescriptorSetLayout vertDescriptorSetLayouts[] = {*descriptorSetLayouts[0], VK_NULL_HANDLE,
1894                                                         *descriptorSetLayouts[2]};
1895     VkDescriptorSetLayout fragDescriptorSetLayouts[] = {*descriptorSetLayouts[0], *descriptorSetLayouts[1]};
1896     VkDescriptorSetLayout allDescriptorSetLayouts[]  = {*descriptorSetLayouts[0], *descriptorSetLayouts[1],
1897                                                         *descriptorSetLayouts[2]};
1898 
1899     VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = initVulkanStructure();
1900     pipelineLayoutCreateInfo.flags                      = allLayoutsFlag;
1901     pipelineLayoutCreateInfo.setLayoutCount             = 3u;
1902     pipelineLayoutCreateInfo.pSetLayouts                = allDescriptorSetLayouts;
1903     Move<VkPipelineLayout> allLayouts                   = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1904     pipelineLayoutCreateInfo.flags                      = uint32_t(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT);
1905     pipelineLayoutCreateInfo.pSetLayouts                = vertDescriptorSetLayouts;
1906     Move<VkPipelineLayout> vertLayouts                  = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1907     pipelineLayoutCreateInfo.setLayoutCount             = 2u;
1908     pipelineLayoutCreateInfo.pSetLayouts                = fragDescriptorSetLayouts;
1909     Move<VkPipelineLayout> fragLayouts                  = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
1910 
1911     Move<VkDescriptorPool> allDescriptorPool =
1912         DescriptorPoolBuilder()
1913             .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3)
1914             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 3);
1915 
1916     // create three descriptor sets
1917     Move<VkDescriptorSet> descriptorSetA = makeDescriptorSet(vk, device, *allDescriptorPool, *descriptorSetLayouts[0]);
1918     Move<VkDescriptorSet> descriptorSetB = makeDescriptorSet(vk, device, *allDescriptorPool, *descriptorSetLayouts[1]);
1919     Move<VkDescriptorSet> descriptorSetC = makeDescriptorSet(vk, device, *allDescriptorPool, *descriptorSetLayouts[2]);
1920     VkDescriptorSet allDescriptorSets[]  = {*descriptorSetA, *descriptorSetB, *descriptorSetC};
1921 
1922     // update descriptors with actual buffers
1923     const VkDescriptorBufferInfo shaderBufferAInfo =
1924         makeDescriptorBufferInfo(**uniformBuffer[0], 0u, uniformBufferDataSize);
1925     const VkDescriptorBufferInfo shaderBufferBInfo =
1926         makeDescriptorBufferInfo(**uniformBuffer[1], 0u, uniformBufferDataSize);
1927     const VkDescriptorBufferInfo shaderBufferCInfo =
1928         makeDescriptorBufferInfo(**uniformBuffer[2], 0u, uniformBufferDataSize);
1929     DescriptorSetUpdateBuilder()
1930         .writeSingle(*descriptorSetA, DescriptorSetUpdateBuilder::Location::binding(0u),
1931                      VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &shaderBufferAInfo)
1932         .writeSingle(*descriptorSetB, DescriptorSetUpdateBuilder::Location::binding(0u),
1933                      VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &shaderBufferBInfo)
1934         .writeSingle(*descriptorSetC, DescriptorSetUpdateBuilder::Location::binding(0u),
1935                      VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &shaderBufferCInfo)
1936         .update(vk, device);
1937 
1938     uint32_t commonPipelinePartFlags = uint32_t(VK_PIPELINE_CREATE_LIBRARY_BIT_KHR);
1939     uint32_t finalPipelineFlag       = 0u;
1940     if (useLinkTimeOptimization)
1941     {
1942         commonPipelinePartFlags |= uint32_t(VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT);
1943         finalPipelineFlag = uint32_t(VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT);
1944     }
1945 
1946     GraphicsPipelineCreateInfo partialPipelineCreateInfo[]{{VK_NULL_HANDLE, *m_renderPass, 0, commonPipelinePartFlags},
1947                                                            {*vertLayouts, *m_renderPass, 0, commonPipelinePartFlags},
1948                                                            {*fragLayouts, *m_renderPass, 0, commonPipelinePartFlags},
1949                                                            {VK_NULL_HANDLE, *m_renderPass, 0, commonPipelinePartFlags}};
1950 
1951     // fill proper portion of pipeline state
1952     updateVertexInputInterface(m_context, partialPipelineCreateInfo[0], VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0u);
1953     updatePreRasterization(m_context, partialPipelineCreateInfo[1], false);
1954     updatePostRasterization(m_context, partialPipelineCreateInfo[2], false);
1955     updateFragmentOutputInterface(m_context, partialPipelineCreateInfo[3]);
1956 
1957     // extend pNext chain and create all partial pipelines
1958     std::vector<VkPipeline> rawParts(4u, VK_NULL_HANDLE);
1959     std::vector<Move<VkPipeline>> pipelineParts;
1960     pipelineParts.reserve(4u);
1961     VkGraphicsPipelineLibraryCreateInfoEXT libraryCreateInfo =
1962         makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT);
1963     for (uint32_t i = 0; i < 4u; ++i)
1964     {
1965         libraryCreateInfo.flags = GRAPHICS_PIPELINE_LIBRARY_FLAGS[i];
1966         appendStructurePtrToVulkanChain(&partialPipelineCreateInfo[i].pNext, &libraryCreateInfo);
1967         pipelineParts.emplace_back(createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &partialPipelineCreateInfo[i]));
1968         rawParts[i] = *pipelineParts[i];
1969     }
1970 
1971     // create final pipeline out of four parts
1972     VkPipelineLibraryCreateInfoKHR linkingInfo     = makePipelineLibraryCreateInfo(rawParts);
1973     VkGraphicsPipelineCreateInfo finalPipelineInfo = initVulkanStructure();
1974 
1975     finalPipelineInfo.flags  = finalPipelineFlag;
1976     finalPipelineInfo.layout = *allLayouts;
1977 
1978     appendStructurePtrToVulkanChain(&finalPipelineInfo.pNext, &linkingInfo);
1979     Move<VkPipeline> pipeline = createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &finalPipelineInfo);
1980 
1981     vk::beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1982     {
1983         // change color image layout
1984         const VkImageMemoryBarrier initialImageBarrier = makeImageMemoryBarrier(
1985             0,                                          // VkAccessFlags srcAccessMask;
1986             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,       // VkAccessFlags dstAccessMask;
1987             VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout oldLayout;
1988             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout newLayout;
1989             **m_colorImage,                             // VkImage image;
1990             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
1991         );
1992         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1993                               VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, nullptr, 0,
1994                               nullptr, 1, &initialImageBarrier);
1995 
1996         // wait for uniform buffers
1997         std::vector<VkBufferMemoryBarrier> initialBufferBarriers(
1998             3u, makeBufferMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT,   // VkAccessFlags2KHR                srcAccessMask
1999                                         VK_ACCESS_UNIFORM_READ_BIT, // VkAccessFlags2KHR                dstAccessMask
2000                                         uniformBuffer[0]->get(),    // VkBuffer                            buffer
2001                                         0u,                         // VkDeviceSize                        offset
2002                                         uniformBufferDataSize       // VkDeviceSize                        size
2003                                         ));
2004         initialBufferBarriers[1].buffer = uniformBuffer[1]->get();
2005         initialBufferBarriers[2].buffer = uniformBuffer[2]->get();
2006         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
2007                               (VkDependencyFlags)0, 0, nullptr, 3, initialBufferBarriers.data(), 0, nullptr);
2008 
2009         beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, m_renderArea, m_colorClearColor);
2010 
2011         vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2012         vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *allLayouts, 0u, 3u, allDescriptorSets,
2013                                  0u, nullptr);
2014         vk.cmdDraw(*m_cmdBuffer, 4, 1u, 0u, 0u);
2015 
2016         endRenderPass(vk, *m_cmdBuffer);
2017 
2018         const tcu::IVec2 size{(int32_t)m_renderArea.extent.width, (int32_t)m_renderArea.extent.height};
2019         copyImageToBuffer(vk, *m_cmdBuffer, **m_colorImage, *colorBuffer, size);
2020     }
2021     vk::endCommandBuffer(vk, *m_cmdBuffer);
2022     vk::submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *m_cmdBuffer);
2023 
2024     vk::invalidateAlloc(vk, device, colorBuffer.getAllocation());
2025     const tcu::ConstPixelBufferAccess colorPixelAccess(mapVkFormat(m_colorFormat), m_renderArea.extent.width,
2026                                                        m_renderArea.extent.height, 1,
2027                                                        colorBuffer.getAllocation().getHostPtr());
2028 
2029     // verify result
2030     int32_t width  = (int32_t)m_renderArea.extent.width;
2031     int32_t height = (int32_t)m_renderArea.extent.height;
2032     const std::vector<VerificationData> verificationData{
2033         {{1, 1}, {0, 191, 127, 51}}, // note COLOR_COMPONENTS_NO_RED is used
2034         {{width / 2, height / 2}, {0, 191, 127, 51}},
2035         {{width - 2, height - 2}, {0, 0, 0, 255}} // clear color
2036     };
2037     return verifyResult(verificationData, colorPixelAccess);
2038 }
2039 
runCompareLinkTimes(void)2040 tcu::TestStatus PipelineLibraryMiscTestInstance::runCompareLinkTimes(void)
2041 {
2042     const uint32_t uniqueLibrariesCount = 2u;
2043     const uint32_t pipelinesCount       = 4u * uniqueLibrariesCount;
2044 
2045     const DeviceInterface &vk                       = m_context.getDeviceInterface();
2046     const VkDevice device                           = m_context.getDevice();
2047     tcu::TestLog &log                               = m_context.getTestContext().getLog();
2048     bool allChecksPassed                            = true;
2049     VkPipelineLayoutCreateInfo pipelineLayoutParams = initVulkanStructure();
2050     Move<VkPipelineLayout> layout                   = createPipelineLayout(vk, device, &pipelineLayoutParams);
2051 
2052     GraphicsPipelineCreateInfo partialPipelineCreateInfo[]{
2053         {*layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR},
2054         {*layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR},
2055         {*layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR},
2056         {*layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR},
2057         {*layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR},
2058         {*layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR},
2059         {*layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR},
2060         {*layout, *m_renderPass, 0, VK_PIPELINE_CREATE_LIBRARY_BIT_KHR},
2061     };
2062 
2063     de::Random rnd(static_cast<uint32_t>(deGetMicroseconds()));
2064 
2065     const uint32_t vertexRandSpecConsts[]   = {rnd.getUint32() * 2, rnd.getUint32() * 2};
2066     const uint32_t fragmentRandSpecConsts[] = {rnd.getUint32() * 2, rnd.getUint32() * 2};
2067 
2068     const VkSpecializationMapEntry entry = {
2069         0,              // uint32_t constantID;
2070         0,              // uint32_t offset;
2071         sizeof(int32_t) // size_t size;
2072     };
2073 
2074     const VkSpecializationInfo vertexSpecializationInfos[] = {
2075         {
2076             1u,                      // uint32_t mapEntryCount;
2077             &entry,                  // const VkSpecializationMapEntry* pMapEntries;
2078             sizeof(int32_t),         // size_t dataSize;
2079             &vertexRandSpecConsts[0] // const void* pData;
2080         },
2081         {
2082             1u,                      // uint32_t mapEntryCount;
2083             &entry,                  // const VkSpecializationMapEntry* pMapEntries;
2084             sizeof(int32_t),         // size_t dataSize;
2085             &vertexRandSpecConsts[1] // const void* pData;
2086         }};
2087 
2088     const VkSpecializationInfo fragmentSpecializationInfos[] = {
2089         {
2090             1u,                        // uint32_t mapEntryCount;
2091             &entry,                    // const VkSpecializationMapEntry* pMapEntries;
2092             sizeof(int32_t),           // size_t dataSize;
2093             &fragmentRandSpecConsts[0] // const void* pData;
2094         },
2095         {
2096             1u,                        // uint32_t mapEntryCount;
2097             &entry,                    // const VkSpecializationMapEntry* pMapEntries;
2098             sizeof(int32_t),           // size_t dataSize;
2099             &fragmentRandSpecConsts[1] // const void* pData;
2100         }};
2101 
2102     // fill proper portion of pipeline state - this cant be easily done in a scalable loop
2103     updateVertexInputInterface(m_context, partialPipelineCreateInfo[0], VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
2104     updateVertexInputInterface(m_context, partialPipelineCreateInfo[1], VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
2105     updatePreRasterization(m_context, partialPipelineCreateInfo[2], false, false, false, VK_POLYGON_MODE_FILL,
2106                            &vertexSpecializationInfos[0]);
2107     updatePreRasterization(m_context, partialPipelineCreateInfo[3], false, false, false, VK_POLYGON_MODE_LINE,
2108                            &vertexSpecializationInfos[1]);
2109     updatePostRasterization(m_context, partialPipelineCreateInfo[4], false, true, &fragmentSpecializationInfos[0]);
2110     updatePostRasterization(m_context, partialPipelineCreateInfo[5], false, false, &fragmentSpecializationInfos[1]);
2111     updateFragmentOutputInterface(m_context, partialPipelineCreateInfo[6], 0xf);
2112     updateFragmentOutputInterface(m_context, partialPipelineCreateInfo[7]);
2113 
2114     // construct all pipeline parts and mesure time it took
2115     struct PipelinePartData
2116     {
2117         Move<VkPipeline> pipelineHandle;
2118         std::chrono::duration<int64_t, std::nano> creationDuration;
2119     };
2120     std::vector<PipelinePartData> pipelinePartData(pipelinesCount);
2121     VkGraphicsPipelineLibraryCreateInfoEXT libraryCreateInfo =
2122         makeGraphicsPipelineLibraryCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT);
2123     for (uint32_t i = 0; i < pipelinesCount; ++i)
2124     {
2125         appendStructurePtrToVulkanChain(&partialPipelineCreateInfo[i].pNext, &libraryCreateInfo);
2126         libraryCreateInfo.flags = GRAPHICS_PIPELINE_LIBRARY_FLAGS[i / 2];
2127 
2128         auto &partData            = pipelinePartData[i];
2129         auto timeStart            = std::chrono::high_resolution_clock::now();
2130         partData.pipelineHandle   = createGraphicsPipeline(vk, device, VK_NULL_HANDLE, partialPipelineCreateInfo + i);
2131         partData.creationDuration = std::chrono::high_resolution_clock::now() - timeStart;
2132     }
2133 
2134     // iterate over all combinations of parts
2135     for (uint32_t i = 0u; i < (uint32_t)dePow(4, uniqueLibrariesCount); ++i)
2136     {
2137         // select new unique combination of parts
2138         uint32_t vertexInputIndex      = (i) % 2;
2139         uint32_t preRasterizationIndex = (i / 2) % 2;
2140         uint32_t fragmentStateIndex    = (i / 4) % 2;
2141         uint32_t fragmentOutputIndex   = (i / 8) % 2;
2142 
2143         const auto &vertexInputData      = pipelinePartData[vertexInputIndex];
2144         const auto &preRasterizationData = pipelinePartData[uniqueLibrariesCount + preRasterizationIndex];
2145         const auto &fragmentStateData    = pipelinePartData[2 * uniqueLibrariesCount + fragmentStateIndex];
2146         const auto &fragmentOutputData   = pipelinePartData[3 * uniqueLibrariesCount + fragmentOutputIndex];
2147 
2148         std::vector<VkPipeline> pipelinesToLink{
2149             *vertexInputData.pipelineHandle,
2150             *preRasterizationData.pipelineHandle,
2151             *fragmentStateData.pipelineHandle,
2152             *fragmentOutputData.pipelineHandle,
2153         };
2154 
2155         VkPipelineLibraryCreateInfoKHR linkingInfo     = makePipelineLibraryCreateInfo(pipelinesToLink);
2156         VkGraphicsPipelineCreateInfo finalPipelineInfo = initVulkanStructure();
2157         finalPipelineInfo.layout                       = *layout;
2158 
2159         appendStructurePtrToVulkanChain(&finalPipelineInfo.pNext, &linkingInfo);
2160 
2161         // link pipeline without the optimised bit, and record the time taken to link it
2162         auto timeStart            = std::chrono::high_resolution_clock::now();
2163         Move<VkPipeline> pipeline = createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &finalPipelineInfo);
2164         const auto linkingTime    = std::chrono::high_resolution_clock::now() - timeStart;
2165         const auto creationTime   = preRasterizationData.creationDuration + fragmentStateData.creationDuration;
2166 
2167         if (linkingTime > (10 * creationTime))
2168         {
2169             allChecksPassed = false;
2170             log << tcu::TestLog::Message << "Liking time (" << linkingTime.count() << ") of combination " << i
2171                 << " is more then ten times greater than creation of both pre-rasterization and fragment states ("
2172                 << creationTime.count() << ")" << tcu::TestLog::EndMessage;
2173         }
2174     }
2175 
2176     if (allChecksPassed)
2177         return tcu::TestStatus::pass("Pass");
2178 
2179     return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Liking of one or more combinations took to long");
2180 }
2181 
2182 /*
2183 Middle bar should contain clip distance with linear values between 0 and 1.
2184 Cull distance is always 0.5 when enabled.
2185 */
makeReferenceImage(tcu::PixelBufferAccess & reference,IVec2 clipRegion,const int numBars,int barIdx,const tcu::Vec4 & clipAreaColor)2186 void makeReferenceImage(tcu::PixelBufferAccess &reference, IVec2 clipRegion, const int numBars, int barIdx,
2187                         const tcu::Vec4 &clipAreaColor)
2188 {
2189     for (int y = 0; y < reference.getHeight(); ++y)
2190         for (int x = 0; x < reference.getWidth(); ++x)
2191         {
2192             if (x < clipRegion.x() && y < clipRegion.y())
2193             {
2194                 reference.setPixel(clipAreaColor, x, y);
2195                 continue;
2196             }
2197 
2198             const int barWidth   = reference.getWidth() / numBars;
2199             const bool insideBar = x >= barWidth * barIdx && x < barWidth * (barIdx + 1);
2200             const float expectedClipDistance =
2201                 insideBar ? (((((float)y + 0.5f) / (float)reference.getHeight()) - 0.5f) * 2.0f) : 0.0f;
2202             float expectedCullDistance = 0.5f;
2203             const float height         = (float)reference.getHeight();
2204 
2205             if (y >= (reference.getHeight() / 2))
2206                 expectedCullDistance = expectedCullDistance * (1.0f + (2.0f * (float)y) - height) / height;
2207             else
2208                 expectedCullDistance = 0.0f;
2209 
2210             const tcu::Vec4 expectedColor = Vec4(1.0, expectedClipDistance, expectedCullDistance, 1.0);
2211             reference.setPixel(expectedColor, x, y);
2212         }
2213 }
2214 
makeVertexBuffer(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,std::vector<tcu::Vec4> & vertexData,VkBufferUsageFlagBits usageFlags)2215 de::MovePtr<BufferWithMemory> makeVertexBuffer(const DeviceInterface &vk, const VkDevice device, Allocator &allocator,
2216                                                std::vector<tcu::Vec4> &vertexData, VkBufferUsageFlagBits usageFlags)
2217 {
2218     const size_t bufferDataSize               = de::dataSize(vertexData);
2219     const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferDataSize, usageFlags);
2220     de::MovePtr<BufferWithMemory> buffer      = de::MovePtr<BufferWithMemory>(
2221         new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
2222 
2223     deMemcpy(buffer->getAllocation().getHostPtr(), vertexData.data(), bufferDataSize);
2224     flushAlloc(vk, device, buffer->getAllocation());
2225 
2226     return buffer;
2227 }
2228 
2229 /*
2230 Pipeline libraries:
2231     Compile a fragment only pipeline library L1.
2232     Compile a mesh only pipeline library L2.
2233     Compile a vertex only pipeline library L3.
2234     Fast link L2 & L1.
2235     Fast link L3 & L1.
2236 Shaders:
2237     Vertex and mesh shaders write clip distance and cull distance.
2238     Fragment shader reads clip distance and cull distance.
2239     Clip and cull tests taken from vktClippingTests.
2240 */
runCommonFragLibraryTest(void)2241 tcu::TestStatus PipelineLibraryMiscTestInstance::runCommonFragLibraryTest(void)
2242 {
2243     const DeviceInterface &vk = m_context.getDeviceInterface();
2244     const VkDevice device     = m_context.getDevice();
2245     Allocator &allocator      = m_context.getDefaultAllocator();
2246 
2247     // create output buffer for verification
2248     const VkDeviceSize outputBufferDataSize = static_cast<VkDeviceSize>(
2249         m_renderArea.extent.width * m_renderArea.extent.height * tcu::getPixelSize(mapVkFormat(m_colorFormat)));
2250     const VkBufferCreateInfo outputBufferCreateInfo = makeBufferCreateInfo(
2251         outputBufferDataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2252     const BufferWithMemory outputBuffer(vk, device, allocator, outputBufferCreateInfo, MemoryRequirement::HostVisible);
2253 
2254     const int numBars = numClipDistances + numCullDistances;
2255 
2256     // vertex shader input
2257     std::vector<Vec4> vertices;
2258     {
2259         const float dx = 2.0f / numBars;
2260         for (int i = 0; i < numBars; ++i)
2261         {
2262             const float x = -1.0f + dx * static_cast<float>(i);
2263 
2264             vertices.push_back(Vec4(x, -1.0f, 0.0f, 1.0f));
2265             vertices.push_back(Vec4(x, 1.0f, 0.0f, 1.0f));
2266             vertices.push_back(Vec4(x + dx, -1.0f, 0.0f, 1.0f));
2267 
2268             vertices.push_back(Vec4(x, 1.0f, 0.0f, 1.0f));
2269             vertices.push_back(Vec4(x + dx, 1.0f, 0.0f, 1.0f));
2270             vertices.push_back(Vec4(x + dx, -1.0f, 0.0f, 1.0f));
2271         }
2272     }
2273 
2274     const auto vertexBufferStages = (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_MESH_BIT_EXT);
2275     const auto vertexBufferSize   = static_cast<VkDeviceSize>(de::dataSize(vertices));
2276     const auto vertexCount        = de::sizeU32(vertices);
2277     const auto vertexBufferUsage  = (VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
2278     const auto vertexBufferLoc    = DescriptorSetUpdateBuilder::Location::binding(0u);
2279     const auto vertexBufferType   = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
2280 
2281     // Vertex buffer.
2282     const de::MovePtr<BufferWithMemory> vertexBuffer =
2283         makeVertexBuffer(vk, device, allocator, vertices, (VkBufferUsageFlagBits)vertexBufferUsage);
2284 
2285     // for the link time opt (and when null handle is used) use total pipeline layout recreated without the INDEPENDENT SETS bit
2286     const auto allLayoutsFlag = VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT;
2287 
2288     // Set layout.
2289     DescriptorSetLayoutBuilder layoutBuilder;
2290     layoutBuilder.addSingleBinding(vertexBufferType, vertexBufferStages);
2291     const auto descriptorSetLayout = layoutBuilder.build(vk, device);
2292 
2293     // Descriptor pool.
2294     DescriptorPoolBuilder poolBuilder;
2295     poolBuilder.addType(vertexBufferType);
2296     const auto descriptorPool = poolBuilder.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2297 
2298     // Descriptor set.
2299     const auto descriptorSet = makeDescriptorSet(vk, device, descriptorPool.get(), descriptorSetLayout.get());
2300 
2301     // Update descriptor set.
2302     DescriptorSetUpdateBuilder updateBuilder;
2303     const auto vertexBufferDescInfo = makeDescriptorBufferInfo(vertexBuffer->get(), 0ull, vertexBufferSize);
2304     updateBuilder.writeSingle(descriptorSet.get(), vertexBufferLoc, vertexBufferType, &vertexBufferDescInfo);
2305     updateBuilder.update(vk, device);
2306 
2307     // Setup pipeline libraries
2308     VkDescriptorSet allDescriptorSets[] = {*descriptorSet};
2309 
2310     VkDescriptorSetLayout meshDescriptorSetLayouts[] = {*descriptorSetLayout};
2311     VkDescriptorSetLayout allDescriptorSetLayouts[]  = {*descriptorSetLayout};
2312 
2313     VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = initVulkanStructure();
2314     pipelineLayoutCreateInfo.flags                      = allLayoutsFlag;
2315     pipelineLayoutCreateInfo.setLayoutCount             = 1u;
2316     pipelineLayoutCreateInfo.pSetLayouts                = allDescriptorSetLayouts;
2317     Move<VkPipelineLayout> allLayouts                   = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
2318 
2319     pipelineLayoutCreateInfo.pSetLayouts = meshDescriptorSetLayouts;
2320     Move<VkPipelineLayout> meshLayouts   = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
2321 
2322     pipelineLayoutCreateInfo.setLayoutCount = 0u;
2323     pipelineLayoutCreateInfo.pSetLayouts    = nullptr;
2324     Move<VkPipelineLayout> vertLayouts      = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
2325     Move<VkPipelineLayout> fragLayouts      = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
2326     Move<VkPipelineLayout> nullLayout       = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
2327 
2328     const uint32_t commonPipelinePartFlags = uint32_t(VK_PIPELINE_CREATE_LIBRARY_BIT_KHR);
2329 
2330     enum
2331     {
2332         PIPELINE_CREATEINFO_IDX_VII = 0,
2333         PIPELINE_CREATEINFO_IDX_PRERAST_VERT,
2334         PIPELINE_CREATEINFO_IDX_PRERAST_MESH,
2335         PIPELINE_CREATEINFO_IDX_POSTRAST,
2336         PIPELINE_CREATEINFO_IDX_FO,
2337         PIPELINE_CREATEINFO_IDX_MAX
2338     };
2339 
2340     const VkGraphicsPipelineLibraryFlagBitsEXT map_pipeline_createinfo_to_flags[PIPELINE_CREATEINFO_IDX_MAX] = {
2341         VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT,
2342         VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT, // pre-rasterization (vert)
2343         VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT, // pre-rasterization (mesh)
2344         VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT,
2345         VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT};
2346 
2347     GraphicsPipelineCreateInfo allPipelineCreateInfos[]{
2348         {VK_NULL_HANDLE, *m_renderPass, 0,
2349          commonPipelinePartFlags}, // [PIPELINE_CREATEINFO_IDX_VII]: vertex input interface
2350         {*vertLayouts, *m_renderPass, 0,
2351          commonPipelinePartFlags}, // [PIPELINE_CREATEINFO_IDX_PRERAST_VERT]: pre-rasterization (vert)
2352         {*meshLayouts, *m_renderPass, 0,
2353          commonPipelinePartFlags}, // [PIPELINE_CREATEINFO_IDX_PRERAST_MESH]: pre-rasterization (mesh)
2354         {*fragLayouts, *m_renderPass, 0,
2355          commonPipelinePartFlags}, // [PIPELINE_CREATEINFO_IDX_POSTRAST]: post-rasterization (frag)
2356         {VK_NULL_HANDLE, *m_renderPass, 0,
2357          commonPipelinePartFlags}, // [PIPELINE_CREATEINFO_IDX_FO]: frag output interface
2358     };
2359 
2360     // initialize VkGraphicsPipelineLibraryCreateInfoEXT for each library
2361     std::vector<VkGraphicsPipelineLibraryCreateInfoEXT> libraryCreateInfos;
2362     for (uint32_t i = 0; i < PIPELINE_CREATEINFO_IDX_MAX; i++)
2363     {
2364         VkGraphicsPipelineLibraryFlagBitsEXT flag = map_pipeline_createinfo_to_flags[i];
2365         libraryCreateInfos.push_back(makeGraphicsPipelineLibraryCreateInfo(flag));
2366     }
2367 
2368     // vertex-only pipeline parts
2369     uint32_t pipelineCreateInfoIdx = PIPELINE_CREATEINFO_IDX_VII;
2370     updateVertexInputInterface(m_context, allPipelineCreateInfos[pipelineCreateInfoIdx],
2371                                VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 1u);
2372     appendStructurePtrToVulkanChain(&allPipelineCreateInfos[pipelineCreateInfoIdx].pNext,
2373                                     &libraryCreateInfos[pipelineCreateInfoIdx]);
2374 
2375     pipelineCreateInfoIdx = PIPELINE_CREATEINFO_IDX_PRERAST_VERT;
2376     updatePreRasterization(m_context, allPipelineCreateInfos[pipelineCreateInfoIdx], false, true);
2377     appendStructurePtrToVulkanChain(&allPipelineCreateInfos[pipelineCreateInfoIdx].pNext,
2378                                     &libraryCreateInfos[pipelineCreateInfoIdx]);
2379 
2380     // mesh-only pipeline parts
2381     pipelineCreateInfoIdx = PIPELINE_CREATEINFO_IDX_PRERAST_MESH;
2382     updatePreRasterization(m_context, allPipelineCreateInfos[pipelineCreateInfoIdx], false, true, true);
2383     appendStructurePtrToVulkanChain(&allPipelineCreateInfos[pipelineCreateInfoIdx].pNext,
2384                                     &libraryCreateInfos[pipelineCreateInfoIdx]);
2385 
2386     // fragment-only pipeline parts, always linked
2387     pipelineCreateInfoIdx = PIPELINE_CREATEINFO_IDX_POSTRAST;
2388     updatePostRasterization(m_context, allPipelineCreateInfos[PIPELINE_CREATEINFO_IDX_POSTRAST], false, false);
2389     appendStructurePtrToVulkanChain(&allPipelineCreateInfos[pipelineCreateInfoIdx].pNext,
2390                                     &libraryCreateInfos[pipelineCreateInfoIdx]);
2391 
2392     pipelineCreateInfoIdx = PIPELINE_CREATEINFO_IDX_FO;
2393     updateFragmentOutputInterface(m_context, allPipelineCreateInfos[pipelineCreateInfoIdx], ALL_COLOR_COMPONENTS);
2394     appendStructurePtrToVulkanChain(&allPipelineCreateInfos[pipelineCreateInfoIdx].pNext,
2395                                     &libraryCreateInfos[pipelineCreateInfoIdx]);
2396 
2397     // final pipeline libraries, pipelines[0]: vertex+frag and pipelines[1]: mesh+frag
2398     std::vector<Move<VkPipeline>> pipelines;
2399     pipelines.reserve(2u);
2400 
2401     enum
2402     {
2403         PIPELINE_LIB_VERT_FRAG = 0,
2404         PIPELINE_LIB_MESH_FRAG,
2405         PIPELINE_LIB_MAX
2406     };
2407 
2408     // create parts of each of the two final pipelines and then create the final pipelines
2409     std::vector<VkPipeline> rawParts[PIPELINE_LIB_MAX];
2410     std::vector<Move<VkPipeline>> pipelineParts[PIPELINE_LIB_MAX];
2411     for (uint32_t combo = PIPELINE_LIB_VERT_FRAG; combo < PIPELINE_LIB_MAX; combo++)
2412     {
2413         uint32_t numParts = 0;
2414         std::vector<uint32_t> createInfoIndices;
2415         VkGraphicsPipelineCreateInfo finalPipelineInfo = initVulkanStructure();
2416         finalPipelineInfo.flags                        = 0u;
2417 
2418         if (combo == PIPELINE_LIB_VERT_FRAG)
2419         {
2420             // pipeline parts are 4 for vertex+frag pipeline
2421             // vertex inout interface, pre-rasterization (vertex), post-rasterization, frag output interface
2422             numParts                 = 4u;
2423             finalPipelineInfo.layout = *nullLayout;
2424             createInfoIndices.push_back(PIPELINE_CREATEINFO_IDX_VII);
2425             createInfoIndices.push_back(PIPELINE_CREATEINFO_IDX_PRERAST_VERT);
2426             createInfoIndices.push_back(PIPELINE_CREATEINFO_IDX_POSTRAST);
2427             createInfoIndices.push_back(PIPELINE_CREATEINFO_IDX_FO);
2428         }
2429         else
2430         {
2431             // pipeline parts are 3 for mesh+frag pipeline
2432             // pre-rasterization (mesh), post-rasterization, frag output interface
2433             numParts                 = 3u;
2434             finalPipelineInfo.layout = *allLayouts;
2435             createInfoIndices.push_back(PIPELINE_CREATEINFO_IDX_PRERAST_MESH);
2436             createInfoIndices.push_back(PIPELINE_CREATEINFO_IDX_POSTRAST);
2437             createInfoIndices.push_back(PIPELINE_CREATEINFO_IDX_FO);
2438         }
2439 
2440         // extend pNext chain and create all partial pipelines
2441         rawParts[combo].resize(numParts, VK_NULL_HANDLE);
2442         pipelineParts[combo].reserve(numParts);
2443 
2444         uint32_t partsIdx = 0;
2445         for (const auto &idx : createInfoIndices)
2446         {
2447             pipelineParts[combo].emplace_back(
2448                 createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &allPipelineCreateInfos[idx]));
2449             rawParts[combo][partsIdx] = *(pipelineParts[combo][partsIdx]);
2450             partsIdx++;
2451         }
2452 
2453         // create final pipeline out of the parts
2454         VkPipelineLibraryCreateInfoKHR linkingInfo = makePipelineLibraryCreateInfo(rawParts[combo]);
2455         appendStructurePtrToVulkanChain(&finalPipelineInfo.pNext, &linkingInfo);
2456         pipelines.emplace_back(createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &finalPipelineInfo));
2457     }
2458 
2459     // execute both pipelines one after the other and verify the result of each
2460     bool testOk               = true;
2461     const VkViewport viewport = makeViewport(m_renderArea.extent.width, m_renderArea.extent.height);
2462     const VkRect2D scissor    = makeRect2D(m_renderArea.extent.width, m_renderArea.extent.height);
2463 
2464     for (uint32_t combo = PIPELINE_LIB_VERT_FRAG; (combo < PIPELINE_LIB_MAX) && (testOk != false); combo++)
2465     {
2466         // only the render pass is shared between the two pipelines
2467         const VkImageCreateInfo colorImageCreateInfo =
2468             makeColorImageCreateInfo(m_colorFormat, m_renderArea.extent.width, m_renderArea.extent.height);
2469         de::MovePtr<ImageWithMemory> localColorImage = de::MovePtr<ImageWithMemory>(
2470             new ImageWithMemory(vk, device, allocator, colorImageCreateInfo, MemoryRequirement::Any));
2471         const VkImageViewCreateInfo colorImageViewCreateInfo = makeImageViewCreateInfo(
2472             **localColorImage, m_colorFormat, static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_COLOR_BIT));
2473         const Move<VkImageView> colorImageView = createImageView(vk, device, &colorImageViewCreateInfo);
2474 
2475         const VkFramebufferCreateInfo framebufferCreateInfo = makeFramebufferCreateInfo(
2476             *m_renderPass, 1u, &*colorImageView, m_renderArea.extent.width, m_renderArea.extent.height);
2477         Move<VkFramebuffer> localFramebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
2478 
2479         Move<VkCommandBuffer> localCmdBuffer =
2480             allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2481 
2482         vk::beginCommandBuffer(vk, *localCmdBuffer, 0u);
2483         {
2484 
2485             const VkDeviceSize zeroOffset = 0ull;
2486             beginRenderPass(vk, *localCmdBuffer, *m_renderPass, *localFramebuffer, m_renderArea, m_colorClearColor);
2487 
2488             vk.cmdBindPipeline(*localCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelines[combo]);
2489             vk.cmdSetViewport(*localCmdBuffer, 0, 1, &viewport);
2490             vk.cmdSetScissor(*localCmdBuffer, 0, 1, &scissor);
2491 
2492             if (combo == PIPELINE_LIB_VERT_FRAG)
2493             {
2494                 vk.cmdBindVertexBuffers(*localCmdBuffer, 0u, 1u, &vertexBuffer->get(), &zeroOffset);
2495                 vk.cmdDraw(*localCmdBuffer, vertexCount, 1u, 0u, 0u);
2496             }
2497             else
2498             {
2499                 vk.cmdBindDescriptorSets(*localCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *allLayouts, 0u, 1u,
2500                                          allDescriptorSets, 0u, nullptr);
2501                 uint32_t num_workgroups = 1u;
2502                 vk.cmdDrawMeshTasksEXT(*localCmdBuffer, num_workgroups, 1u, 1u);
2503             }
2504 
2505             endRenderPass(vk, *localCmdBuffer);
2506 
2507             const tcu::IVec2 size{(int32_t)m_renderArea.extent.width, (int32_t)m_renderArea.extent.height};
2508             copyImageToBuffer(vk, *localCmdBuffer, **localColorImage, *outputBuffer, size);
2509         }
2510         vk::endCommandBuffer(vk, *localCmdBuffer);
2511         vk::submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *localCmdBuffer);
2512 
2513         {
2514             vk::invalidateAlloc(vk, device, outputBuffer.getAllocation());
2515 
2516             const tcu::TextureFormat tcuFormat = vk::mapVkFormat(m_colorFormat);
2517             const tcu::ConstPixelBufferAccess resultAccess(tcuFormat, m_renderArea.extent.width,
2518                                                            m_renderArea.extent.height, 1,
2519                                                            outputBuffer.getAllocation().getHostPtr());
2520             testOk = verifyOnePipelineLibraryResult(resultAccess, numBars);
2521         }
2522     }
2523 
2524     return (testOk == true ? tcu::TestStatus::pass("OK") : tcu::TestStatus::fail("Rendered image(s) are incorrect"));
2525 }
2526 
verifyResult(const std::vector<VerificationData> & verificationData,const tcu::ConstPixelBufferAccess & colorPixelAccess) const2527 tcu::TestStatus PipelineLibraryMiscTestInstance::verifyResult(const std::vector<VerificationData> &verificationData,
2528                                                               const tcu::ConstPixelBufferAccess &colorPixelAccess) const
2529 {
2530     const int32_t epsilon = 1;
2531     for (const auto &v : verificationData)
2532     {
2533         const IVec4 pixel = colorPixelAccess.getPixelInt(v.point.x(), v.point.y());
2534         const IVec4 diff  = pixel - v.color;
2535         for (uint32_t compNdx = 0; compNdx < 4u; ++compNdx)
2536         {
2537             if (de::abs(diff[compNdx]) > epsilon)
2538             {
2539                 const Vec4 pixelBias(0.0f);
2540                 const Vec4 pixelScale(1.0f);
2541 
2542                 m_context.getTestContext().getLog()
2543                     << TestLog::Image("Result", "Result", colorPixelAccess, pixelScale, pixelBias)
2544                     << tcu::TestLog::Message << "For texel " << v.point << " expected color " << v.color
2545                     << " got: " << pixel << tcu::TestLog::EndMessage;
2546 
2547                 return tcu::TestStatus::fail("Fail");
2548             }
2549         }
2550     }
2551 
2552     return tcu::TestStatus::pass("Pass");
2553 }
2554 
verifyOnePipelineLibraryResult(const tcu::ConstPixelBufferAccess & resultAccess,const int numBars) const2555 bool PipelineLibraryMiscTestInstance::verifyOnePipelineLibraryResult(const tcu::ConstPixelBufferAccess &resultAccess,
2556                                                                      const int numBars) const
2557 {
2558     bool testOk       = true;
2559     tcu::TestLog &log = m_context.getTestContext().getLog();
2560 
2561     const tcu::TextureFormat tcuFormat = vk::mapVkFormat(m_colorFormat);
2562     tcu::TextureLevel referenceLevel(tcuFormat, m_renderArea.extent.width, m_renderArea.extent.height);
2563     auto referenceAccess          = referenceLevel.getAccess();
2564     const tcu::Vec4 bgColor       = Vec4(1.0f, 0.0f, 0.0f, 1.0f); // red
2565     const tcu::Vec4 clipAreaColor = Vec4(0.0f, 0.0f, 0.0f, 1.0f); // black
2566     const IVec2 clipRegion =
2567         IVec2(numClipDistances * m_renderArea.extent.width / numBars, m_renderArea.extent.height / 2);
2568     tcu::clear(referenceAccess, bgColor);
2569     makeReferenceImage(referenceAccess, clipRegion, numBars, numClipDistances / 2, clipAreaColor);
2570 
2571     const float colorThres = 0.005f; // 1/255 < 0.005 < 2/255
2572     const tcu::Vec4 threshold(0.0f, colorThres, colorThres, 0.0f);
2573 
2574     if (!tcu::floatThresholdCompare(log, "Result", "Reference", referenceAccess, resultAccess, threshold,
2575                                     tcu::COMPARE_LOG_ON_ERROR))
2576         testOk = false;
2577 
2578     return testOk;
2579 }
2580 
2581 class PipelineLibraryShaderModuleInfoInstance : public TestInstance
2582 {
2583 public:
PipelineLibraryShaderModuleInfoInstance(Context & context)2584     PipelineLibraryShaderModuleInfoInstance(Context &context)
2585         : TestInstance(context)
2586         , m_vkd(m_context.getDeviceInterface())
2587         , m_device(m_context.getDevice())
2588         , m_alloc(m_context.getDefaultAllocator())
2589         , m_queueIndex(m_context.getUniversalQueueFamilyIndex())
2590         , m_queue(m_context.getUniversalQueue())
2591         , m_outVector(kOutputBufferElements, std::numeric_limits<uint32_t>::max())
2592         , m_cmdBuffer(nullptr)
2593     {
2594     }
~PipelineLibraryShaderModuleInfoInstance(void)2595     virtual ~PipelineLibraryShaderModuleInfoInstance(void)
2596     {
2597     }
2598 
2599     static constexpr size_t kOutputBufferElements = 64u;
2600 
2601 protected:
2602     void prepareOutputBuffer(VkShaderStageFlags stages);
2603     void allocateCmdBuffers(void);
2604     void addModule(const std::string &moduleName, VkShaderStageFlagBits stage);
2605     void recordShaderToHostBarrier(VkPipelineStageFlagBits pipelineStage) const;
2606     void verifyOutputBuffer(void);
2607 
2608     using BufferWithMemoryPtr = de::MovePtr<BufferWithMemory>;
2609 
2610     // From the context.
2611     const DeviceInterface &m_vkd;
2612     const VkDevice m_device;
2613     Allocator &m_alloc;
2614     const uint32_t m_queueIndex;
2615     const VkQueue m_queue;
2616 
2617     Move<VkDescriptorSetLayout> m_setLayout;
2618     Move<VkDescriptorPool> m_descriptorPool;
2619     Move<VkDescriptorSet> m_descriptorSet;
2620     std::vector<uint32_t> m_outVector;
2621     BufferWithMemoryPtr m_outputBuffer;
2622 
2623     Move<VkCommandPool> m_cmdPool;
2624     Move<VkCommandBuffer> m_cmdBufferPtr;
2625     VkCommandBuffer m_cmdBuffer;
2626 
2627     std::vector<VkPipelineShaderStageCreateInfo> m_pipelineStageInfos;
2628     std::vector<VkShaderModuleCreateInfo> m_shaderModuleInfos;
2629 };
2630 
prepareOutputBuffer(VkShaderStageFlags stages)2631 void PipelineLibraryShaderModuleInfoInstance::prepareOutputBuffer(VkShaderStageFlags stages)
2632 {
2633     const auto descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2634     const auto poolFlags      = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
2635 
2636     // Create set layout.
2637     DescriptorSetLayoutBuilder layoutBuilder;
2638     layoutBuilder.addSingleBinding(descriptorType, stages);
2639     m_setLayout = layoutBuilder.build(m_vkd, m_device);
2640 
2641     // Create pool and set.
2642     DescriptorPoolBuilder poolBuilder;
2643     poolBuilder.addType(descriptorType);
2644     m_descriptorPool = poolBuilder.build(m_vkd, m_device, poolFlags, 1u);
2645     m_descriptorSet  = makeDescriptorSet(m_vkd, m_device, m_descriptorPool.get(), m_setLayout.get());
2646 
2647     // Create buffer.
2648     const auto outputBufferSize       = static_cast<VkDeviceSize>(de::dataSize(m_outVector));
2649     const auto outputBufferCreateInfo = makeBufferCreateInfo(outputBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2650     m_outputBuffer                    = BufferWithMemoryPtr(
2651         new BufferWithMemory(m_vkd, m_device, m_alloc, outputBufferCreateInfo, MemoryRequirement::HostVisible));
2652 
2653     // Update set.
2654     const auto outputBufferDescInfo = makeDescriptorBufferInfo(m_outputBuffer->get(), 0ull, outputBufferSize);
2655     DescriptorSetUpdateBuilder updateBuilder;
2656     updateBuilder.writeSingle(m_descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
2657                               &outputBufferDescInfo);
2658     updateBuilder.update(m_vkd, m_device);
2659 }
2660 
addModule(const std::string & moduleName,VkShaderStageFlagBits stage)2661 void PipelineLibraryShaderModuleInfoInstance::addModule(const std::string &moduleName, VkShaderStageFlagBits stage)
2662 {
2663     const auto &binary = m_context.getBinaryCollection().get(moduleName);
2664 
2665     const VkShaderModuleCreateInfo modInfo = {
2666         VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,            // VkStructureType sType;
2667         nullptr,                                                // const void* pNext;
2668         0u,                                                     // VkShaderModuleCreateFlags flags;
2669         binary.getSize(),                                       // size_t codeSize;
2670         reinterpret_cast<const uint32_t *>(binary.getBinary()), // const uint32_t* pCode;
2671     };
2672     m_shaderModuleInfos.push_back(modInfo);
2673 
2674     // Note: the pNext pointer will be updated below.
2675     const VkPipelineShaderStageCreateInfo stageInfo = {
2676         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
2677         nullptr,                                             // const void* pNext;
2678         0u,                                                  // VkPipelineShaderStageCreateFlags flags;
2679         stage,                                               // VkShaderStageFlagBits stage;
2680         VK_NULL_HANDLE,                                      // VkShaderModule module;
2681         "main",                                              // const char* pName;
2682         nullptr,                                             // const VkSpecializationInfo* pSpecializationInfo;
2683     };
2684     m_pipelineStageInfos.push_back(stageInfo);
2685 
2686     DE_ASSERT(m_shaderModuleInfos.size() == m_pipelineStageInfos.size());
2687 
2688     // Update pNext pointers after possible reallocation.
2689     for (size_t i = 0u; i < m_shaderModuleInfos.size(); ++i)
2690         m_pipelineStageInfos[i].pNext = &(m_shaderModuleInfos[i]);
2691 }
2692 
recordShaderToHostBarrier(VkPipelineStageFlagBits pipelineStage) const2693 void PipelineLibraryShaderModuleInfoInstance::recordShaderToHostBarrier(VkPipelineStageFlagBits pipelineStage) const
2694 {
2695     const auto postWriteBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2696     cmdPipelineMemoryBarrier(m_vkd, m_cmdBuffer, pipelineStage, VK_PIPELINE_STAGE_HOST_BIT, &postWriteBarrier);
2697 }
2698 
verifyOutputBuffer(void)2699 void PipelineLibraryShaderModuleInfoInstance::verifyOutputBuffer(void)
2700 {
2701     auto &allocation = m_outputBuffer->getAllocation();
2702 
2703     invalidateAlloc(m_vkd, m_device, allocation);
2704     deMemcpy(m_outVector.data(), allocation.getHostPtr(), de::dataSize(m_outVector));
2705 
2706     for (uint32_t i = 0; i < static_cast<uint32_t>(m_outVector.size()); ++i)
2707     {
2708         if (m_outVector[i] != i)
2709         {
2710             std::ostringstream msg;
2711             msg << "Unexpected value found at position " << i << ": " << m_outVector[i];
2712             TCU_FAIL(msg.str());
2713         }
2714     }
2715 }
2716 
allocateCmdBuffers(void)2717 void PipelineLibraryShaderModuleInfoInstance::allocateCmdBuffers(void)
2718 {
2719     m_cmdPool      = makeCommandPool(m_vkd, m_device, m_queueIndex);
2720     m_cmdBufferPtr = allocateCommandBuffer(m_vkd, m_device, m_cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2721     m_cmdBuffer    = m_cmdBufferPtr.get();
2722 }
2723 
2724 class PipelineLibraryShaderModuleInfoCompInstance : public PipelineLibraryShaderModuleInfoInstance
2725 {
2726 public:
PipelineLibraryShaderModuleInfoCompInstance(Context & context)2727     PipelineLibraryShaderModuleInfoCompInstance(Context &context) : PipelineLibraryShaderModuleInfoInstance(context)
2728     {
2729     }
~PipelineLibraryShaderModuleInfoCompInstance(void)2730     virtual ~PipelineLibraryShaderModuleInfoCompInstance(void)
2731     {
2732     }
2733 
2734     tcu::TestStatus iterate(void) override;
2735 };
2736 
iterate(void)2737 tcu::TestStatus PipelineLibraryShaderModuleInfoCompInstance::iterate(void)
2738 {
2739     const auto stage     = VK_SHADER_STAGE_COMPUTE_BIT;
2740     const auto bindPoint = VK_PIPELINE_BIND_POINT_COMPUTE;
2741 
2742     prepareOutputBuffer(stage);
2743     addModule("comp", stage);
2744     allocateCmdBuffers();
2745 
2746     const auto pipelineLayout = makePipelineLayout(m_vkd, m_device, m_setLayout.get());
2747 
2748     const VkComputePipelineCreateInfo pipelineCreateInfo = {
2749         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
2750         nullptr,                                        // const void* pNext;
2751         0u,                                             // VkPipelineCreateFlags flags;
2752         m_pipelineStageInfos.at(0u),                    // VkPipelineShaderStageCreateInfo stage;
2753         pipelineLayout.get(),                           // VkPipelineLayout layout;
2754         VK_NULL_HANDLE,                                 // VkPipeline basePipelineHandle;
2755         0,                                              // int32_t basePipelineIndex;
2756     };
2757 
2758     const auto pipeline = createComputePipeline(m_vkd, m_device, VK_NULL_HANDLE, &pipelineCreateInfo);
2759 
2760     beginCommandBuffer(m_vkd, m_cmdBuffer);
2761     m_vkd.cmdBindDescriptorSets(m_cmdBuffer, bindPoint, pipelineLayout.get(), 0u, 1u, &m_descriptorSet.get(), 0u,
2762                                 nullptr);
2763     m_vkd.cmdBindPipeline(m_cmdBuffer, bindPoint, pipeline.get());
2764     m_vkd.cmdDispatch(m_cmdBuffer, 1u, 1u, 1u);
2765     recordShaderToHostBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
2766     endCommandBuffer(m_vkd, m_cmdBuffer);
2767     submitCommandsAndWait(m_vkd, m_device, m_queue, m_cmdBuffer);
2768     verifyOutputBuffer();
2769 
2770     return tcu::TestStatus::pass("Pass");
2771 }
2772 
2773 class PipelineLibraryShaderModuleInfoRTInstance : public PipelineLibraryShaderModuleInfoInstance
2774 {
2775 public:
PipelineLibraryShaderModuleInfoRTInstance(Context & context,bool withLibrary)2776     PipelineLibraryShaderModuleInfoRTInstance(Context &context, bool withLibrary)
2777         : PipelineLibraryShaderModuleInfoInstance(context)
2778         , m_withLibrary(withLibrary)
2779     {
2780     }
~PipelineLibraryShaderModuleInfoRTInstance(void)2781     virtual ~PipelineLibraryShaderModuleInfoRTInstance(void)
2782     {
2783     }
2784 
2785     tcu::TestStatus iterate(void) override;
2786 
2787 protected:
2788     bool m_withLibrary;
2789 };
2790 
iterate(void)2791 tcu::TestStatus PipelineLibraryShaderModuleInfoRTInstance::iterate(void)
2792 {
2793     const auto stage     = VK_SHADER_STAGE_RAYGEN_BIT_KHR;
2794     const auto bindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR;
2795 
2796     prepareOutputBuffer(stage);
2797     addModule("rgen", stage);
2798     allocateCmdBuffers();
2799 
2800     const auto pipelineLayout = makePipelineLayout(m_vkd, m_device, m_setLayout.get());
2801 
2802     const VkRayTracingShaderGroupCreateInfoKHR shaderGroupInfo = {
2803         VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR, // VkStructureType sType;
2804         nullptr,                                                    // const void* pNext;
2805         VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR,               // VkRayTracingShaderGroupTypeKHR type;
2806         0u,                                                         // uint32_t generalShader;
2807         VK_SHADER_UNUSED_KHR,                                       // uint32_t closestHitShader;
2808         VK_SHADER_UNUSED_KHR,                                       // uint32_t anyHitShader;
2809         VK_SHADER_UNUSED_KHR,                                       // uint32_t intersectionShader;
2810         nullptr,                                                    // const void* pShaderGroupCaptureReplayHandle;
2811     };
2812 
2813     const VkPipelineCreateFlags createFlags =
2814         (m_withLibrary ? static_cast<VkPipelineCreateFlags>(VK_PIPELINE_CREATE_LIBRARY_BIT_KHR) : 0u);
2815     const VkRayTracingPipelineInterfaceCreateInfoKHR libIfaceInfo   = initVulkanStructure();
2816     const VkRayTracingPipelineInterfaceCreateInfoKHR *pLibraryIface = (m_withLibrary ? &libIfaceInfo : nullptr);
2817 
2818     const VkRayTracingPipelineCreateInfoKHR pipelineCreateInfo = {
2819         VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR, // VkStructureType sType;
2820         nullptr,                                                // const void* pNext;
2821         createFlags,                                            // VkPipelineCreateFlags flags;
2822         de::sizeU32(m_pipelineStageInfos),                      // uint32_t stageCount;
2823         de::dataOrNull(m_pipelineStageInfos),                   // const VkPipelineShaderStageCreateInfo* pStages;
2824         1u,                                                     // uint32_t groupCount;
2825         &shaderGroupInfo,                                       // const VkRayTracingShaderGroupCreateInfoKHR* pGroups;
2826         1u,                                                     // uint32_t maxPipelineRayRecursionDepth;
2827         nullptr,                                                // const VkPipelineLibraryCreateInfoKHR* pLibraryInfo;
2828         pLibraryIface,        // const VkRayTracingPipelineInterfaceCreateInfoKHR* pLibraryInterface;
2829         nullptr,              // const VkPipelineDynamicStateCreateInfo* pDynamicState;
2830         pipelineLayout.get(), // VkPipelineLayout layout;
2831         VK_NULL_HANDLE,       // VkPipeline basePipelineHandle;
2832         0,                    // int32_t basePipelineIndex;
2833     };
2834 
2835     Move<VkPipeline> pipelineLib;
2836     Move<VkPipeline> pipeline;
2837 
2838     if (m_withLibrary)
2839     {
2840         pipelineLib = createRayTracingPipelineKHR(m_vkd, m_device, VK_NULL_HANDLE, VK_NULL_HANDLE, &pipelineCreateInfo);
2841 
2842         const VkPipelineLibraryCreateInfoKHR libraryInfo = {
2843             VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR, // VkStructureType sType;
2844             nullptr,                                            // const void* pNext;
2845             1u,                                                 // uint32_t libraryCount;
2846             &pipelineLib.get(),                                 // const VkPipeline* pLibraries;
2847         };
2848 
2849         const VkRayTracingPipelineCreateInfoKHR nonLibCreateInfo = {
2850             VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR, // VkStructureType sType;
2851             nullptr,                                                // const void* pNext;
2852             0u,                                                     // VkPipelineCreateFlags flags;
2853             0u,                                                     // uint32_t stageCount;
2854             nullptr,                                                // const VkPipelineShaderStageCreateInfo* pStages;
2855             0u,                                                     // uint32_t groupCount;
2856             nullptr,              // const VkRayTracingShaderGroupCreateInfoKHR* pGroups;
2857             1u,                   // uint32_t maxPipelineRayRecursionDepth;
2858             &libraryInfo,         // const VkPipelineLibraryCreateInfoKHR* pLibraryInfo;
2859             pLibraryIface,        // const VkRayTracingPipelineInterfaceCreateInfoKHR* pLibraryInterface;
2860             nullptr,              // const VkPipelineDynamicStateCreateInfo* pDynamicState;
2861             pipelineLayout.get(), // VkPipelineLayout layout;
2862             VK_NULL_HANDLE,       // VkPipeline basePipelineHandle;
2863             0,                    // int32_t basePipelineIndex;
2864         };
2865         pipeline = createRayTracingPipelineKHR(m_vkd, m_device, VK_NULL_HANDLE, VK_NULL_HANDLE, &nonLibCreateInfo);
2866     }
2867     else
2868     {
2869         pipeline = createRayTracingPipelineKHR(m_vkd, m_device, VK_NULL_HANDLE, VK_NULL_HANDLE, &pipelineCreateInfo);
2870     }
2871 
2872     // Make shader binding table.
2873     const auto rtProperties = makeRayTracingProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice());
2874     const auto rtHandleSize = rtProperties->getShaderGroupHandleSize();
2875     const auto sbtSize      = static_cast<VkDeviceSize>(rtHandleSize);
2876     const auto sbtMemReqs   = (MemoryRequirement::HostVisible | MemoryRequirement::DeviceAddress);
2877     const auto sbtCreateInfo = makeBufferCreateInfo(sbtSize, VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR |
2878                                                                  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
2879     BufferWithMemoryPtr sbt =
2880         BufferWithMemoryPtr(new BufferWithMemory(m_vkd, m_device, m_alloc, sbtCreateInfo, sbtMemReqs));
2881     auto &sbtAlloc = sbt->getAllocation();
2882     void *sbtData  = sbtAlloc.getHostPtr();
2883 
2884     // Copy ray gen shader group handle to the start of  the buffer.
2885     VK_CHECK(m_vkd.getRayTracingShaderGroupHandlesKHR(m_device, pipeline.get(), 0u, 1u, static_cast<size_t>(sbtSize),
2886                                                       sbtData));
2887     flushAlloc(m_vkd, m_device, sbtAlloc);
2888 
2889     // Strided device address regions.
2890     VkStridedDeviceAddressRegionKHR rgenSBTRegion = makeStridedDeviceAddressRegionKHR(
2891         getBufferDeviceAddress(m_vkd, m_device, sbt->get(), 0), rtHandleSize, rtHandleSize);
2892     VkStridedDeviceAddressRegionKHR missSBTRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0);
2893     VkStridedDeviceAddressRegionKHR hitsSBTRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0);
2894     VkStridedDeviceAddressRegionKHR callSBTRegion = makeStridedDeviceAddressRegionKHR(0, 0, 0);
2895 
2896     beginCommandBuffer(m_vkd, m_cmdBuffer);
2897     m_vkd.cmdBindDescriptorSets(m_cmdBuffer, bindPoint, pipelineLayout.get(), 0u, 1u, &m_descriptorSet.get(), 0u,
2898                                 nullptr);
2899     m_vkd.cmdBindPipeline(m_cmdBuffer, bindPoint, pipeline.get());
2900     m_vkd.cmdTraceRaysKHR(m_cmdBuffer, &rgenSBTRegion, &missSBTRegion, &hitsSBTRegion, &callSBTRegion,
2901                           kOutputBufferElements, 1u, 1u);
2902     recordShaderToHostBarrier(VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
2903     endCommandBuffer(m_vkd, m_cmdBuffer);
2904     submitCommandsAndWait(m_vkd, m_device, m_queue, m_cmdBuffer);
2905     verifyOutputBuffer();
2906 
2907     return tcu::TestStatus::pass("Pass");
2908 }
2909 
2910 class NullRenderingCreateInfoInstance : public vkt::TestInstance
2911 {
2912 public:
NullRenderingCreateInfoInstance(Context & context)2913     NullRenderingCreateInfoInstance(Context &context) : vkt::TestInstance(context)
2914     {
2915     }
2916     virtual ~NullRenderingCreateInfoInstance(void) = default;
2917 
2918     tcu::TestStatus iterate(void) override;
2919 };
2920 
iterate(void)2921 tcu::TestStatus NullRenderingCreateInfoInstance::iterate(void)
2922 {
2923     const auto ctx = m_context.getContextCommonData();
2924     const tcu::IVec3 colorExtent(1, 1, 1);
2925     const auto imageExtent = makeExtent3D(colorExtent);
2926     const auto colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
2927     const auto tcuFormat   = mapVkFormat(colorFormat);
2928     const auto colorUsage  = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
2929     const auto colorSRR    = makeDefaultImageSubresourceRange();
2930     const auto colorSRL    = makeDefaultImageSubresourceLayers();
2931 
2932     // Color buffer and view.
2933     ImageWithBuffer colorBuffer(ctx.vkd, ctx.device, ctx.allocator, imageExtent, colorFormat, colorUsage,
2934                                 VK_IMAGE_TYPE_2D);
2935     const auto colorView =
2936         makeImageView(ctx.vkd, ctx.device, colorBuffer.getImage(), VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSRR);
2937 
2938     // Verification buffer.
2939     const auto verificationBufferSize =
2940         static_cast<VkDeviceSize>(colorExtent.x() * colorExtent.y() * colorExtent.z() * tcu::getPixelSize(tcuFormat));
2941     const auto verificationBufferInfo = makeBufferCreateInfo(verificationBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2942     BufferWithMemory verificationBuffer(ctx.vkd, ctx.device, ctx.allocator, verificationBufferInfo,
2943                                         MemoryRequirement::HostVisible);
2944     auto &verificationBufferAlloc = verificationBuffer.getAllocation();
2945     void *verificationBufferPtr   = verificationBufferAlloc.getHostPtr();
2946 
2947     const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device);
2948 
2949     const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = initVulkanStructure();
2950     VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo   = initVulkanStructure();
2951     inputAssemblyStateInfo.topology                                 = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
2952 
2953     const std::vector<VkViewport> viewports(1u, makeViewport(imageExtent));
2954     const std::vector<VkRect2D> scissors(1u, makeRect2D(imageExtent));
2955 
2956     const auto &binaries  = m_context.getBinaryCollection();
2957     const auto vertModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("vert"));
2958     const auto fragModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("frag"));
2959 
2960     // We will use a null-filled pipeline rendering info structure for all substates except the fragment output state.
2961     VkPipelineRenderingCreateInfo nullRenderingInfo = initVulkanStructure();
2962     nullRenderingInfo.colorAttachmentCount          = 0;
2963 
2964     VkPipelineRenderingCreateInfo finalRenderingInfo = initVulkanStructure();
2965     finalRenderingInfo.colorAttachmentCount          = 1u;
2966     finalRenderingInfo.pColorAttachmentFormats       = &colorFormat;
2967 
2968     const VkPipelineViewportStateCreateInfo viewportStateInfo = {
2969         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
2970         nullptr,                                               // const void* pNext;
2971         0u,                                                    // VkPipelineViewportStateCreateFlags flags;
2972         de::sizeU32(viewports),                                // uint32_t viewportCount;
2973         de::dataOrNull(viewports),                             // const VkViewport* pViewports;
2974         de::sizeU32(scissors),                                 // uint32_t scissorCount;
2975         de::dataOrNull(scissors),                              // const VkRect2D* pScissors;
2976     };
2977 
2978     const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo = {
2979         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
2980         nullptr,                                                    // const void* pNext;
2981         0u,                                                         // VkPipelineRasterizationStateCreateFlags flags;
2982         VK_FALSE,                                                   // VkBool32 depthClampEnable;
2983         VK_FALSE,                                                   // VkBool32 rasterizerDiscardEnable;
2984         VK_POLYGON_MODE_FILL,                                       // VkPolygonMode polygonMode;
2985         VK_CULL_MODE_BACK_BIT,                                      // VkCullModeFlags cullMode;
2986         VK_FRONT_FACE_COUNTER_CLOCKWISE,                            // VkFrontFace frontFace;
2987         VK_FALSE,                                                   // VkBool32 depthBiasEnable;
2988         0.0f,                                                       // float depthBiasConstantFactor;
2989         0.0f,                                                       // float depthBiasClamp;
2990         0.0f,                                                       // float depthBiasSlopeFactor;
2991         1.0f,                                                       // float lineWidth;
2992     };
2993 
2994     const VkPipelineMultisampleStateCreateInfo multisampleStateInfo = {
2995         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
2996         nullptr,                                                  // const void* pNext;
2997         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
2998         VK_SAMPLE_COUNT_1_BIT,                                    // VkSampleCountFlagBits rasterizationSamples;
2999         VK_FALSE,                                                 // VkBool32 sampleShadingEnable;
3000         1.0f,                                                     // float minSampleShading;
3001         nullptr,                                                  // const VkSampleMask* pSampleMask;
3002         VK_FALSE,                                                 // VkBool32 alphaToCoverageEnable;
3003         VK_FALSE,                                                 // VkBool32 alphaToOneEnable;
3004     };
3005 
3006     const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = initVulkanStructure();
3007 
3008     const VkColorComponentFlags colorComponentFlags =
3009         (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
3010 
3011     const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {
3012         VK_FALSE,             // VkBool32 blendEnable;
3013         VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor;
3014         VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
3015         VK_BLEND_OP_ADD,      // VkBlendOp colorBlendOp;
3016         VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor;
3017         VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
3018         VK_BLEND_OP_ADD,      // VkBlendOp alphaBlendOp;
3019         colorComponentFlags,  // VkColorComponentFlags colorWriteMask;
3020     };
3021 
3022     const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo = {
3023         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
3024         nullptr,                                                  // const void* pNext;
3025         0u,                                                       // VkPipelineColorBlendStateCreateFlags flags;
3026         VK_FALSE,                                                 // VkBool32 logicOpEnable;
3027         VK_LOGIC_OP_CLEAR,                                        // VkLogicOp logicOp;
3028         1u,                                                       // uint32_t attachmentCount;
3029         &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
3030         {0.0f, 0.0f, 0.0f, 0.0f},   // float blendConstants[4];
3031     };
3032 
3033     // Build the different pipeline pieces.
3034     Move<VkPipeline> vertexInputLib;
3035     Move<VkPipeline> preRasterShaderLib;
3036     Move<VkPipeline> fragShaderLib;
3037     Move<VkPipeline> fragOutputLib;
3038 
3039     const VkPipelineCreateFlags libCreationFlags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
3040     const VkPipelineCreateFlags linkFlags        = 0u;
3041 
3042     // Vertex input state library.
3043     {
3044         VkGraphicsPipelineLibraryCreateInfoEXT vertexInputLibInfo = initVulkanStructure();
3045         vertexInputLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT;
3046 
3047         VkGraphicsPipelineCreateInfo vertexInputPipelineInfo = initVulkanStructure(&vertexInputLibInfo);
3048         vertexInputPipelineInfo.flags                        = libCreationFlags;
3049         vertexInputPipelineInfo.pVertexInputState            = &vertexInputStateInfo;
3050         vertexInputPipelineInfo.pInputAssemblyState          = &inputAssemblyStateInfo;
3051 
3052         vertexInputLib = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &vertexInputPipelineInfo);
3053     }
3054 
3055     // Pre-rasterization shader state library.
3056     {
3057         VkGraphicsPipelineLibraryCreateInfoEXT preRasterShaderLibInfo =
3058             initVulkanStructure(&nullRenderingInfo); // What we're testing.
3059         preRasterShaderLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT;
3060 
3061         VkGraphicsPipelineCreateInfo preRasterShaderPipelineInfo = initVulkanStructure(&preRasterShaderLibInfo);
3062         preRasterShaderPipelineInfo.flags                        = libCreationFlags;
3063         preRasterShaderPipelineInfo.layout                       = pipelineLayout.get();
3064         preRasterShaderPipelineInfo.pViewportState               = &viewportStateInfo;
3065         preRasterShaderPipelineInfo.pRasterizationState          = &rasterizationStateInfo;
3066 
3067         const auto vertShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_VERTEX_BIT, vertModule.get());
3068         preRasterShaderPipelineInfo.stageCount = 1u;
3069         preRasterShaderPipelineInfo.pStages    = &vertShaderInfo;
3070 
3071         preRasterShaderLib = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &preRasterShaderPipelineInfo);
3072     }
3073 
3074     // Fragment shader stage library.
3075     {
3076         VkGraphicsPipelineLibraryCreateInfoEXT fragShaderLibInfo =
3077             initVulkanStructure(&nullRenderingInfo); // What we're testing.
3078         fragShaderLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT;
3079 
3080         VkGraphicsPipelineCreateInfo fragShaderPipelineInfo = initVulkanStructure(&fragShaderLibInfo);
3081         fragShaderPipelineInfo.flags                        = libCreationFlags;
3082         fragShaderPipelineInfo.layout                       = pipelineLayout.get();
3083         fragShaderPipelineInfo.pMultisampleState            = &multisampleStateInfo;
3084         fragShaderPipelineInfo.pDepthStencilState           = &depthStencilStateInfo;
3085 
3086         const auto fragShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, fragModule.get());
3087         fragShaderPipelineInfo.stageCount = 1u;
3088         fragShaderPipelineInfo.pStages    = &fragShaderInfo;
3089 
3090         fragShaderLib = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &fragShaderPipelineInfo);
3091     }
3092 
3093     // Fragment output library.
3094     {
3095         VkGraphicsPipelineLibraryCreateInfoEXT fragOutputLibInfo =
3096             initVulkanStructure(&finalRenderingInfo); // Good info only in the fragment output substate.
3097         fragOutputLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT;
3098 
3099         VkGraphicsPipelineCreateInfo fragOutputPipelineInfo = initVulkanStructure(&fragOutputLibInfo);
3100         fragOutputPipelineInfo.flags                        = libCreationFlags;
3101         fragOutputPipelineInfo.pColorBlendState             = &colorBlendStateInfo;
3102         fragOutputPipelineInfo.pMultisampleState            = &multisampleStateInfo;
3103 
3104         fragOutputLib = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &fragOutputPipelineInfo);
3105     }
3106 
3107     // Linked pipeline.
3108     const std::vector<VkPipeline> libraryHandles{
3109         vertexInputLib.get(),
3110         preRasterShaderLib.get(),
3111         fragShaderLib.get(),
3112         fragOutputLib.get(),
3113     };
3114 
3115     VkPipelineLibraryCreateInfoKHR linkedPipelineLibraryInfo = initVulkanStructure();
3116     linkedPipelineLibraryInfo.libraryCount                   = de::sizeU32(libraryHandles);
3117     linkedPipelineLibraryInfo.pLibraries                     = de::dataOrNull(libraryHandles);
3118 
3119     VkGraphicsPipelineCreateInfo linkedPipelineInfo = initVulkanStructure(&linkedPipelineLibraryInfo);
3120     linkedPipelineInfo.flags                        = linkFlags;
3121     linkedPipelineInfo.layout                       = pipelineLayout.get();
3122 
3123     const auto pipeline = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &linkedPipelineInfo);
3124 
3125     CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, ctx.qfIndex);
3126     const auto cmdBuffer = cmd.cmdBuffer.get();
3127 
3128     const auto clearValue = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f);
3129 
3130     beginCommandBuffer(ctx.vkd, cmdBuffer);
3131 
3132     const auto preRenderBarrier = makeImageMemoryBarrier(
3133         0u, (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), VK_IMAGE_LAYOUT_UNDEFINED,
3134         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, colorBuffer.getImage(), colorSRR);
3135     cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
3136                                   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, &preRenderBarrier);
3137 
3138     beginRendering(ctx.vkd, cmdBuffer, colorView.get(), scissors.at(0u), clearValue,
3139                    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
3140     ctx.vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
3141     ctx.vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
3142     endRendering(ctx.vkd, cmdBuffer);
3143 
3144     const auto color2Transfer = makeImageMemoryBarrier(
3145         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
3146         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer.getImage(), colorSRR);
3147     cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
3148                                   VK_PIPELINE_STAGE_TRANSFER_BIT, &color2Transfer);
3149     const auto copyRegion = makeBufferImageCopy(imageExtent, colorSRL);
3150     ctx.vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3151                                  verificationBuffer.get(), 1u, &copyRegion);
3152 
3153     const auto transfer2Host = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
3154     cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
3155                              &transfer2Host);
3156 
3157     endCommandBuffer(ctx.vkd, cmdBuffer);
3158 
3159     submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
3160     invalidateAlloc(ctx.vkd, ctx.device, verificationBufferAlloc);
3161 
3162     auto &testLog = m_context.getTestContext().getLog();
3163     const tcu::Vec4 expectedColor(0.0f, 0.0f, 1.0f, 1.0f); // Must match frag shader.
3164     const tcu::Vec4 threshold(0.0f, 0.0f, 0.0f, 0.0f);
3165     tcu::ConstPixelBufferAccess resultAccess(tcuFormat, colorExtent, verificationBufferPtr);
3166 
3167     if (!tcu::floatThresholdCompare(testLog, "Result", "", expectedColor, resultAccess, threshold,
3168                                     tcu::COMPARE_LOG_ON_ERROR))
3169         return tcu::TestStatus::fail("Unexpected color buffer contents -- check log for details");
3170 
3171     return tcu::TestStatus::pass("Pass");
3172 }
3173 
3174 class CreateViewIndexFromDeviceIndexInstance : public vkt::TestInstance
3175 {
3176 public:
3177     CreateViewIndexFromDeviceIndexInstance(Context &context, const MiscTestParams &params);
3178     virtual ~CreateViewIndexFromDeviceIndexInstance(void) = default;
3179 
3180     tcu::TestStatus iterate(void) override;
3181 
3182 protected:
3183     bool createDeviceGroup(void);
3184 
3185 private:
3186     MiscTestParams m_testParams;
3187 
3188     uint32_t m_deviceGroupQueueFamilyIndex;
3189     CustomInstance m_deviceGroupInstance;
3190     vk::Move<vk::VkDevice> m_deviceGroupLogicalDevice;
3191     std::vector<vk::VkPhysicalDevice> m_deviceGroupPhysicalDevices;
3192     de::MovePtr<vk::DeviceDriver> m_deviceGroupVk;
3193     de::MovePtr<Allocator> m_deviceGroupAllocator;
3194 };
3195 
CreateViewIndexFromDeviceIndexInstance(Context & context,const MiscTestParams & params)3196 CreateViewIndexFromDeviceIndexInstance::CreateViewIndexFromDeviceIndexInstance(Context &context,
3197                                                                                const MiscTestParams &params)
3198     : vkt::TestInstance(context)
3199     , m_testParams(params)
3200 {
3201 }
3202 
iterate()3203 tcu::TestStatus CreateViewIndexFromDeviceIndexInstance::iterate()
3204 {
3205     const bool useDeviceGroup = createDeviceGroup();
3206     const auto &vk            = useDeviceGroup ? *m_deviceGroupVk : m_context.getDeviceInterface();
3207     const auto device         = useDeviceGroup ? *m_deviceGroupLogicalDevice : m_context.getDevice();
3208     Allocator &allocator      = useDeviceGroup ? *m_deviceGroupAllocator : m_context.getDefaultAllocator();
3209     uint32_t queueFamilyIndex =
3210         useDeviceGroup ? m_deviceGroupQueueFamilyIndex : m_context.getUniversalQueueFamilyIndex();
3211     const auto deviceCount = useDeviceGroup ? m_deviceGroupPhysicalDevices.size() : 1u;
3212     const auto viewCount   = 3u;
3213     const auto imageSize   = 8u;
3214     const auto colorFormat = VK_FORMAT_R8G8B8A8_UINT;
3215     const auto extent      = makeExtent3D(imageSize, imageSize, 1u);
3216 
3217     bool useMeshShader = (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_STAGES) ||
3218                          (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_PRE_RASTERIZATION) ||
3219                          (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_FRAGMENT);
3220     VkPipelineCreateFlags preRasterPipelineFlags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
3221     VkPipelineCreateFlags fragmentPipelineFlags  = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
3222     if ((m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_ALL_STAGES) ||
3223         (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_PRE_RASTERIZATION) ||
3224         (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_STAGES) ||
3225         (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_PRE_RASTERIZATION))
3226         preRasterPipelineFlags |= VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT;
3227     if ((m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_ALL_STAGES) ||
3228         (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_FRAGMENT) ||
3229         (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_STAGES) ||
3230         (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_FRAGMENT))
3231         fragmentPipelineFlags |= VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT;
3232 
3233     // fill structures that are needed for pipeline creation
3234     const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo     = initVulkanStructure();
3235     VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo       = initVulkanStructure();
3236     inputAssemblyStateInfo.topology                                     = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
3237     const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo = initVulkanStructure();
3238 
3239     const auto viewport                                 = makeViewport(extent);
3240     const auto scissor                                  = makeRect2D(extent);
3241     VkPipelineViewportStateCreateInfo viewportStateInfo = initVulkanStructure();
3242     viewportStateInfo.viewportCount                     = 1u;
3243     viewportStateInfo.pViewports                        = &viewport;
3244     viewportStateInfo.scissorCount                      = 1u;
3245     viewportStateInfo.pScissors                         = &scissor;
3246 
3247     VkPipelineMultisampleStateCreateInfo multisampleStateInfo         = initVulkanStructure();
3248     multisampleStateInfo.rasterizationSamples                         = VK_SAMPLE_COUNT_1_BIT;
3249     const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = initVulkanStructure();
3250 
3251     VkPipelineColorBlendAttachmentState colorBlendAttachmentState;
3252     deMemset(&colorBlendAttachmentState, 0x00, sizeof(VkPipelineColorBlendAttachmentState));
3253     colorBlendAttachmentState.colorWriteMask = 0xFu;
3254     VkPipelineColorBlendAttachmentState colorBlendAttachmentStates[viewCount];
3255     std::fill(colorBlendAttachmentStates, colorBlendAttachmentStates + viewCount, colorBlendAttachmentState);
3256 
3257     VkPipelineColorBlendStateCreateInfo colorBlendStateInfo = initVulkanStructure();
3258     colorBlendStateInfo.attachmentCount                     = 1;
3259     colorBlendStateInfo.pAttachments                        = colorBlendAttachmentStates;
3260 
3261     VkPipelineTessellationStateCreateInfo tessellationStateInfo = initVulkanStructure();
3262     tessellationStateInfo.patchControlPoints                    = 3u;
3263 
3264     // create color attachment with required number of layers
3265     const auto imageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, viewCount);
3266     const VkImageUsageFlags imageUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
3267     ImageWithBuffer imageWithBuffer(vk, device, allocator, extent, colorFormat, imageUsage, VK_IMAGE_TYPE_2D,
3268                                     imageSubresourceRange, viewCount);
3269     Move<VkImageView> imageView = makeImageView(vk, device, imageWithBuffer.getImage(), VK_IMAGE_VIEW_TYPE_2D_ARRAY,
3270                                                 colorFormat, imageSubresourceRange);
3271 
3272     const auto &multiviewFeatures(m_context.getMultiviewFeatures());
3273     const auto srl(makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, viewCount));
3274     const auto copyRegion(makeBufferImageCopy(extent, srl));
3275     const auto beforeCopyBarrier(makeMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT));
3276     const auto clearValue(makeClearValueColor(tcu::Vec4(0.0f)));
3277 
3278     const auto pipelineLayout(makePipelineLayout(vk, device));
3279     auto &bc(m_context.getBinaryCollection());
3280     uint32_t preRasterShaderStages = 1;
3281     Move<VkShaderModule> preRasterModules[4];
3282     VkPipelineShaderStageCreateInfo preRasterShaderInfos[4];
3283 
3284     if (useMeshShader)
3285     {
3286         preRasterModules[0]     = createShaderModule(vk, device, bc.get("mesh"));
3287         preRasterShaderInfos[0] = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_MESH_BIT_EXT, *preRasterModules[0]);
3288     }
3289     else
3290     {
3291         std::string moduleNames[4]{"vert", "tesc", "tese", "geom"};
3292         VkShaderStageFlagBits shaderStages[4]{VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
3293                                               VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
3294                                               VK_SHADER_STAGE_GEOMETRY_BIT};
3295 
3296         if (multiviewFeatures.multiviewTessellationShader)
3297         {
3298             inputAssemblyStateInfo.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
3299             preRasterShaderStages += 2;
3300         }
3301 
3302         if (multiviewFeatures.multiviewGeometryShader)
3303         {
3304             moduleNames[preRasterShaderStages]  = "geom";
3305             shaderStages[preRasterShaderStages] = VK_SHADER_STAGE_GEOMETRY_BIT;
3306             ++preRasterShaderStages;
3307         }
3308 
3309         for (uint32_t i = 0u; i < preRasterShaderStages; ++i)
3310         {
3311             preRasterModules[i]     = createShaderModule(vk, device, bc.get(moduleNames[i]));
3312             preRasterShaderInfos[i] = makePipelineShaderStageCreateInfo(shaderStages[i], *preRasterModules[i]);
3313         }
3314     }
3315     const auto fragModule(createShaderModule(vk, device, bc.get("frag")));
3316     const auto fragShaderInfo(makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, *fragModule));
3317 
3318     // create renderpass and framebuffer
3319     uint32_t viewMask        = 0u;
3320     uint32_t correlationMask = 0u;
3321     for (uint32_t i = 0u; i < viewCount; ++i)
3322     {
3323         viewMask |= (1 << i);
3324         correlationMask |= (1 << i);
3325     }
3326     VkRenderPassMultiviewCreateInfo multiviewInfo = initVulkanStructure();
3327     multiviewInfo.subpassCount                    = 1u;
3328     multiviewInfo.pViewMasks                      = &viewMask;
3329     multiviewInfo.correlationMaskCount            = 1u;
3330     multiviewInfo.pCorrelationMasks               = &correlationMask;
3331 
3332     auto renderPass = makeRenderPass(
3333         vk, device, colorFormat, VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3334         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
3335         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 0, &multiviewInfo);
3336 
3337     const auto framebufferCreateInfo = makeFramebufferCreateInfo(*renderPass, 1u, &*imageView, imageSize, imageSize);
3338     auto framebuffer                 = createFramebuffer(vk, device, &framebufferCreateInfo);
3339 
3340     // create pre-raster pipeline part
3341     VkGraphicsPipelineLibraryCreateInfoEXT preRasterLibraryInfo = initVulkanStructure();
3342     preRasterLibraryInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT |
3343                                  VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT;
3344     VkGraphicsPipelineCreateInfo preRasterPipelineInfo = initVulkanStructure(&preRasterLibraryInfo);
3345     preRasterPipelineInfo.flags                        = preRasterPipelineFlags;
3346     preRasterPipelineInfo.layout                       = *pipelineLayout;
3347     preRasterPipelineInfo.renderPass                   = *renderPass;
3348     preRasterPipelineInfo.pVertexInputState            = &vertexInputStateInfo;
3349     preRasterPipelineInfo.pInputAssemblyState          = &inputAssemblyStateInfo;
3350     preRasterPipelineInfo.pViewportState               = &viewportStateInfo;
3351     preRasterPipelineInfo.pRasterizationState          = &rasterizationStateInfo;
3352     preRasterPipelineInfo.pTessellationState           = &tessellationStateInfo;
3353     preRasterPipelineInfo.stageCount                   = preRasterShaderStages;
3354     preRasterPipelineInfo.pStages                      = preRasterShaderInfos;
3355     auto preRasterPipelinePart = createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &preRasterPipelineInfo);
3356 
3357     // create fragment pipeline part
3358     VkGraphicsPipelineLibraryCreateInfoEXT fragShaderLibInfo = initVulkanStructure();
3359     fragShaderLibInfo.flags                                  = VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT |
3360                               VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT;
3361     VkGraphicsPipelineCreateInfo fragmentPipelineInfo = initVulkanStructure(&fragShaderLibInfo);
3362     fragmentPipelineInfo.flags                        = fragmentPipelineFlags;
3363     fragmentPipelineInfo.layout                       = pipelineLayout.get();
3364     fragmentPipelineInfo.renderPass                   = *renderPass;
3365     fragmentPipelineInfo.pMultisampleState            = &multisampleStateInfo;
3366     fragmentPipelineInfo.pDepthStencilState           = &depthStencilStateInfo;
3367     fragmentPipelineInfo.pColorBlendState             = &colorBlendStateInfo;
3368     fragmentPipelineInfo.stageCount                   = 1u;
3369     fragmentPipelineInfo.pStages                      = &fragShaderInfo;
3370     auto fragmentPipelinePart = createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &fragmentPipelineInfo);
3371 
3372     // merge pipelines
3373     const VkPipeline libraryHandles[]{
3374         *preRasterPipelinePart,
3375         *fragmentPipelinePart,
3376     };
3377     VkPipelineLibraryCreateInfoKHR linkedPipelineLibraryInfo = initVulkanStructure();
3378     linkedPipelineLibraryInfo.libraryCount                   = 2u;
3379     linkedPipelineLibraryInfo.pLibraries                     = libraryHandles;
3380     VkGraphicsPipelineCreateInfo linkedPipelineInfo          = initVulkanStructure(&linkedPipelineLibraryInfo);
3381     linkedPipelineInfo.layout                                = *pipelineLayout;
3382     const auto pipeline = createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &linkedPipelineInfo);
3383 
3384     const auto cmdPool(
3385         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
3386     const auto cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3387 
3388     // render triangle that covers whole color attachments
3389     beginCommandBuffer(vk, *cmdBuffer);
3390 
3391     beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, scissor, 1, &clearValue);
3392     vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
3393 
3394     if (useMeshShader)
3395         vk.cmdDrawMeshTasksEXT(*cmdBuffer, 1u, 1u, 1u);
3396     else
3397         vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);
3398 
3399     endRenderPass(vk, *cmdBuffer);
3400 
3401     vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1,
3402                           &beforeCopyBarrier, 0, 0, 0, 0);
3403 
3404     vk.cmdCopyImageToBuffer(*cmdBuffer, imageWithBuffer.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
3405                             imageWithBuffer.getBuffer(), 1u, &copyRegion);
3406 
3407     endCommandBuffer(vk, *cmdBuffer);
3408     const VkQueue queue = getDeviceQueue(vk, device, queueFamilyIndex, 0);
3409     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
3410 
3411     const auto &bufferAllocation = imageWithBuffer.getBufferAllocation();
3412     invalidateAlloc(vk, device, bufferAllocation);
3413 
3414     bool resurtIsCorrect      = true;
3415     const auto fragmentCount  = imageSize * imageSize;
3416     const auto componentCount = 4u;
3417     std::vector<uint8_t> allowedValueSets(deviceCount * componentCount, 0);
3418 
3419     for (uint8_t v = 0; v < static_cast<uint8_t>(viewCount); ++v)
3420     {
3421         // calculate allowed set of result values
3422         for (uint8_t d = 0; d < static_cast<uint8_t>(deviceCount); ++d)
3423         {
3424             uint8_t *allowedValuesPtr = allowedValueSets.data() + d * componentCount;
3425             if (preRasterPipelineFlags == fragmentPipelineFlags)
3426             {
3427                 allowedValuesPtr[0] = d;
3428                 allowedValuesPtr[1] = static_cast<uint8_t>(d + d);
3429                 allowedValuesPtr[2] = d;
3430                 allowedValuesPtr[3] = d;
3431             }
3432             else if (fragmentPipelineFlags & VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT)
3433             {
3434                 allowedValuesPtr[0] = v;
3435                 allowedValuesPtr[1] = static_cast<uint8_t>(v + v);
3436                 allowedValuesPtr[2] = v;
3437                 allowedValuesPtr[3] = d;
3438             }
3439             else
3440             {
3441                 allowedValuesPtr[0] = d;
3442                 allowedValuesPtr[1] = static_cast<uint8_t>(d + d);
3443                 allowedValuesPtr[2] = d;
3444                 allowedValuesPtr[3] = v;
3445             }
3446 
3447             // ignore tesselation and/or geometry stages when those features are not available
3448             if (!multiviewFeatures.multiviewTessellationShader || useMeshShader)
3449                 allowedValuesPtr[1] = 0;
3450             if (!multiviewFeatures.multiviewGeometryShader || useMeshShader)
3451                 allowedValuesPtr[2] = 0;
3452         }
3453 
3454         uint8_t *bufferPtr = static_cast<uint8_t *>(bufferAllocation.getHostPtr()) + v * fragmentCount * componentCount;
3455         for (uint32_t f = 0; f < fragmentCount; ++f)
3456         {
3457             uint8_t *fragmentColor = bufferPtr + f * componentCount;
3458             resurtIsCorrect        = false;
3459 
3460             // compare with all accepted values (if device group is used each device will produce different  result)
3461             for (uint8_t d = 0; d < static_cast<uint8_t>(deviceCount); ++d)
3462             {
3463                 uint8_t *allowedValuesPtr = allowedValueSets.data() + d * componentCount;
3464                 resurtIsCorrect           = (deMemCmp(fragmentColor, allowedValuesPtr, componentCount) == 0);
3465 
3466                 // when fragment is corret we can skip checking other allowed values
3467                 if (resurtIsCorrect)
3468                     break;
3469             }
3470 
3471             // when fragment is not corret we can skip checking other fragments
3472             if (!resurtIsCorrect)
3473                 break;
3474         }
3475 
3476         // when fragment was not corret we can skip checking other views
3477         if (!resurtIsCorrect)
3478             break;
3479     }
3480 
3481     if (resurtIsCorrect)
3482         return tcu::TestStatus::pass("Pass");
3483 
3484     // log images
3485     auto &log = m_context.getTestContext().getLog();
3486     log << tcu::TestLog::ImageSet("Result", "");
3487     for (uint32_t v = 0; v < viewCount; ++v)
3488     {
3489         uint8_t *bufferPtr = static_cast<uint8_t *>(bufferAllocation.getHostPtr()) + v * fragmentCount * componentCount;
3490         tcu::PixelBufferAccess resultAccess(mapVkFormat(colorFormat), imageSize, imageSize, 1, bufferPtr);
3491         log << tcu::TestLog::Image(std::to_string(v), "", resultAccess);
3492     }
3493     log << tcu::TestLog::EndImageSet;
3494 
3495     return tcu::TestStatus::fail("Fail");
3496 }
3497 
createDeviceGroup(void)3498 bool CreateViewIndexFromDeviceIndexInstance::createDeviceGroup(void)
3499 {
3500     const auto &vki                 = m_context.getInstanceInterface();
3501     const tcu::CommandLine &cmdLine = m_context.getTestContext().getCommandLine();
3502     const uint32_t deviceGroupIndex = cmdLine.getVKDeviceGroupId() - 1;
3503     const float queuePriority       = 1.0f;
3504 
3505     // create vulkan instance, list all device groups and select proper one
3506     m_deviceGroupInstance         = createCustomInstanceWithExtension(m_context, "VK_KHR_device_group_creation");
3507     auto allDeviceGroupProperties = enumeratePhysicalDeviceGroups(vki, m_deviceGroupInstance);
3508     auto &devGroupProperties      = allDeviceGroupProperties[deviceGroupIndex];
3509     if (devGroupProperties.physicalDeviceCount == 1)
3510         return false;
3511 
3512     const InstanceDriver &instance(m_deviceGroupInstance.getDriver());
3513     VkPhysicalDeviceFeatures2 deviceFeatures2     = initVulkanStructure();
3514     VkDeviceGroupDeviceCreateInfo deviceGroupInfo = initVulkanStructure(&deviceFeatures2);
3515     deviceGroupInfo.physicalDeviceCount           = devGroupProperties.physicalDeviceCount;
3516     deviceGroupInfo.pPhysicalDevices              = devGroupProperties.physicalDevices;
3517 
3518     uint32_t physicalDeviceIndex = cmdLine.getVKDeviceId() - 1;
3519     if (physicalDeviceIndex >= deviceGroupInfo.physicalDeviceCount)
3520         physicalDeviceIndex = 0;
3521 
3522     const VkPhysicalDeviceFeatures deviceFeatures =
3523         getPhysicalDeviceFeatures(instance, deviceGroupInfo.pPhysicalDevices[physicalDeviceIndex]);
3524     deviceFeatures2.features = deviceFeatures;
3525     const std::vector<VkQueueFamilyProperties> queueProps =
3526         getPhysicalDeviceQueueFamilyProperties(instance, devGroupProperties.physicalDevices[physicalDeviceIndex]);
3527 
3528     VkPhysicalDeviceMultiviewFeatures multiviewFeatures            = m_context.getMultiviewFeatures();
3529     VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT gplFeatures = m_context.getGraphicsPipelineLibraryFeaturesEXT();
3530     VkPhysicalDeviceMeshShaderFeaturesEXT meshShaderFeatures       = m_context.getMeshShaderFeaturesEXT();
3531 
3532     std::vector<const char *> deviceExtensions{"VK_KHR_pipeline_library", "VK_EXT_graphics_pipeline_library",
3533                                                "VK_KHR_multiview"};
3534     if (!isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_device_group"))
3535         deviceExtensions.push_back("VK_KHR_device_group");
3536 
3537     meshShaderFeatures.pNext = nullptr;
3538     multiviewFeatures.pNext  = nullptr;
3539     gplFeatures.pNext        = &multiviewFeatures;
3540     if ((m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_STAGES) ||
3541         (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_PRE_RASTERIZATION) ||
3542         (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_FRAGMENT))
3543     {
3544         deviceExtensions.push_back("VK_EXT_mesh_shader");
3545         multiviewFeatures.pNext = &meshShaderFeatures;
3546     }
3547     deviceFeatures2.pNext = &gplFeatures;
3548 
3549     m_deviceGroupPhysicalDevices.resize(devGroupProperties.physicalDeviceCount);
3550     for (uint32_t pd = 0; pd < devGroupProperties.physicalDeviceCount; pd++)
3551         m_deviceGroupPhysicalDevices[pd] = devGroupProperties.physicalDevices[pd];
3552 
3553     for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
3554     {
3555         if (queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
3556             m_deviceGroupQueueFamilyIndex = (uint32_t)queueNdx;
3557     }
3558 
3559     VkDeviceQueueCreateInfo queueInfo{
3560         VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
3561         nullptr,                                    // const void* pNext;
3562         (VkDeviceQueueCreateFlags)0u,               // VkDeviceQueueCreateFlags flags;
3563         m_deviceGroupQueueFamilyIndex,              // uint32_t queueFamilyIndex;
3564         1u,                                         // uint32_t queueCount;
3565         &queuePriority                              // const float* pQueuePriorities;
3566     };
3567 
3568     const VkDeviceCreateInfo deviceInfo{
3569         VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
3570         &deviceGroupInfo,                     // const void* pNext;
3571         (VkDeviceCreateFlags)0,               // VkDeviceCreateFlags flags;
3572         1u,                                   // uint32_t queueCreateInfoCount;
3573         &queueInfo,                           // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
3574         0u,                                   // uint32_t enabledLayerCount;
3575         nullptr,                              // const char* const* ppEnabledLayerNames;
3576         uint32_t(deviceExtensions.size()),    // uint32_t enabledExtensionCount;
3577         deviceExtensions.data(),              // const char* const* ppEnabledExtensionNames;
3578         nullptr,                              // const VkPhysicalDeviceFeatures* pEnabledFeatures;
3579     };
3580 
3581     m_deviceGroupLogicalDevice = createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(),
3582                                                     m_context.getPlatformInterface(), m_deviceGroupInstance, instance,
3583                                                     deviceGroupInfo.pPhysicalDevices[physicalDeviceIndex], &deviceInfo);
3584 
3585     m_deviceGroupVk = de::MovePtr<DeviceDriver>(
3586         new DeviceDriver(m_context.getPlatformInterface(), m_deviceGroupInstance, *m_deviceGroupLogicalDevice,
3587                          m_context.getUsedApiVersion(), m_context.getTestContext().getCommandLine()));
3588 
3589     m_deviceGroupAllocator = de::MovePtr<Allocator>(
3590         new SimpleAllocator(*m_deviceGroupVk, *m_deviceGroupLogicalDevice,
3591                             getPhysicalDeviceMemoryProperties(instance, m_deviceGroupPhysicalDevices[0])));
3592 
3593     return true;
3594 }
3595 
3596 class CreateUnusualMultisampleStatesInstance : public vkt::TestInstance
3597 {
3598 public:
3599     CreateUnusualMultisampleStatesInstance(Context &context);
3600     virtual ~CreateUnusualMultisampleStatesInstance(void) = default;
3601 
3602     tcu::TestStatus iterate(void) override;
3603 };
3604 
CreateUnusualMultisampleStatesInstance(Context & context)3605 CreateUnusualMultisampleStatesInstance::CreateUnusualMultisampleStatesInstance(Context &context)
3606     : vkt::TestInstance(context)
3607 {
3608 }
3609 
iterate()3610 tcu::TestStatus CreateUnusualMultisampleStatesInstance::iterate()
3611 {
3612     const auto &vk            = m_context.getDeviceInterface();
3613     const auto device         = m_context.getDevice();
3614     Allocator &allocator      = m_context.getDefaultAllocator();
3615     uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
3616 
3617     const auto imageSize    = 8u;
3618     const auto colorFormat  = VK_FORMAT_R8G8B8A8_UNORM;
3619     const auto colorSamples = VK_SAMPLE_COUNT_4_BIT;
3620     const auto extent       = makeExtent3D(imageSize, imageSize, 1u);
3621 
3622     // fill structures that are needed for pipeline creation
3623     const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = initVulkanStructure();
3624     VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo   = initVulkanStructure();
3625     inputAssemblyStateInfo.topology                                 = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
3626     VkPipelineRasterizationStateCreateInfo rasterizationStateInfo   = initVulkanStructure();
3627 
3628     const auto viewport                                 = makeViewport(extent);
3629     const auto scissor                                  = makeRect2D(extent);
3630     VkPipelineViewportStateCreateInfo viewportStateInfo = initVulkanStructure();
3631     viewportStateInfo.viewportCount                     = 1u;
3632     viewportStateInfo.pViewports                        = &viewport;
3633     viewportStateInfo.scissorCount                      = 1u;
3634     viewportStateInfo.pScissors                         = &scissor;
3635 
3636     // purpose of this test is to use multisample image sampling with sample shading disabled
3637     VkPipelineMultisampleStateCreateInfo multisampleStateInfo         = initVulkanStructure();
3638     multisampleStateInfo.rasterizationSamples                         = colorSamples;
3639     const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = initVulkanStructure();
3640 
3641     VkPipelineColorBlendAttachmentState colorBlendAttachmentState;
3642     deMemset(&colorBlendAttachmentState, 0x00, sizeof(VkPipelineColorBlendAttachmentState));
3643     colorBlendAttachmentState.colorWriteMask = 0xFu;
3644 
3645     VkPipelineColorBlendStateCreateInfo colorBlendStateInfo = initVulkanStructure();
3646     colorBlendStateInfo.attachmentCount                     = 1;
3647     colorBlendStateInfo.pAttachments                        = &colorBlendAttachmentState;
3648 
3649     // create multisampled color attachment
3650     const auto imageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
3651     const VkImageUsageFlags imageUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
3652                                        VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
3653     auto imageInfo    = makeColorImageCreateInfo(colorFormat, imageSize, imageSize);
3654     imageInfo.usage   = imageUsage;
3655     imageInfo.samples = colorSamples;
3656     ImageWithMemory imageWithMemory(vk, device, allocator, imageInfo, MemoryRequirement::Local);
3657     Move<VkImageView> imageView =
3658         makeImageView(vk, device, *imageWithMemory, VK_IMAGE_VIEW_TYPE_2D, colorFormat, imageSubresourceRange);
3659 
3660     // create buffer that will hold resolved multisampled attachment
3661     const VkBufferUsageFlags bufferUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
3662     const auto bufferInfo = makeBufferCreateInfo(imageSize * imageSize * colorSamples * 4 * sizeof(float), bufferUsage);
3663     BufferWithMemory bufferWithMemory(vk, device, allocator, bufferInfo, MemoryRequirement::HostVisible);
3664 
3665     // create renderpass with two subpasses; in first subpass we change
3666     // specified samples of multisampled image and in second we copy data
3667     // of all samples to ssbo
3668     VkAttachmentDescription attachmentDescription{
3669         (VkAttachmentDescriptionFlags)0,  // VkAttachmentDescriptionFlags    flags
3670         colorFormat,                      // VkFormat                        format
3671         colorSamples,                     // VkSampleCountFlagBits           samples
3672         VK_ATTACHMENT_LOAD_OP_CLEAR,      // VkAttachmentLoadOp              loadOp
3673         VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp             storeOp
3674         VK_ATTACHMENT_LOAD_OP_DONT_CARE,  // VkAttachmentLoadOp              stencilLoadOp
3675         VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp             stencilStoreOp
3676         VK_IMAGE_LAYOUT_UNDEFINED,        // VkImageLayout                   initialLayout
3677         VK_IMAGE_LAYOUT_GENERAL           // VkImageLayout                   finalLayout
3678     };
3679     const VkAttachmentReference attachmentRef{
3680         0u,                     // uint32_t         attachment
3681         VK_IMAGE_LAYOUT_GENERAL // VkImageLayout    layout
3682     };
3683     VkSubpassDescription subpassDescriptions[2];
3684     deMemset(&subpassDescriptions, 0x00, 2 * sizeof(VkSubpassDescription));
3685     subpassDescriptions[0].pipelineBindPoint    = VK_PIPELINE_BIND_POINT_GRAPHICS;
3686     subpassDescriptions[0].colorAttachmentCount = 1;
3687     subpassDescriptions[0].pColorAttachments    = &attachmentRef;
3688     subpassDescriptions[1].pipelineBindPoint    = VK_PIPELINE_BIND_POINT_GRAPHICS;
3689     subpassDescriptions[1].inputAttachmentCount = 1;
3690     subpassDescriptions[1].pInputAttachments    = &attachmentRef;
3691 
3692     const VkSubpassDependency subpassDependency{0,
3693                                                 1,
3694                                                 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
3695                                                 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
3696                                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
3697                                                 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
3698                                                 VK_DEPENDENCY_BY_REGION_BIT};
3699 
3700     VkRenderPassCreateInfo renderPassInfo = initVulkanStructure();
3701     renderPassInfo.attachmentCount        = 1u;
3702     renderPassInfo.pAttachments           = &attachmentDescription;
3703     renderPassInfo.subpassCount           = 2u;
3704     renderPassInfo.pSubpasses             = subpassDescriptions;
3705     renderPassInfo.dependencyCount        = 1u;
3706     renderPassInfo.pDependencies          = &subpassDependency;
3707     auto renderPass                       = createRenderPass(vk, device, &renderPassInfo);
3708 
3709     // create framebuffer
3710     const auto framebufferCreateInfo = makeFramebufferCreateInfo(*renderPass, 1u, &*imageView, imageSize, imageSize);
3711     auto framebuffer                 = createFramebuffer(vk, device, &framebufferCreateInfo);
3712 
3713     // create descriptor for second subpass
3714     auto descriptorPool = DescriptorPoolBuilder()
3715                               .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1)
3716                               .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1)
3717                               .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
3718     auto descriptorSetLayout = DescriptorSetLayoutBuilder()
3719                                    .addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT)
3720                                    .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
3721                                    .build(vk, device);
3722     auto descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
3723     auto dii           = makeDescriptorImageInfo(VK_NULL_HANDLE, *imageView, VK_IMAGE_LAYOUT_GENERAL);
3724     auto dbi           = makeDescriptorBufferInfo(*bufferWithMemory, 0, VK_WHOLE_SIZE);
3725     using DSUB         = DescriptorSetUpdateBuilder;
3726     DSUB()
3727         .writeSingle(*descriptorSet, DSUB::Location::binding(0), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &dii)
3728         .writeSingle(*descriptorSet, DSUB::Location::binding(1), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &dbi)
3729         .update(vk, device);
3730 
3731     const auto writePipelineLayout(makePipelineLayout(vk, device));
3732     const auto readPipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
3733     auto &bc(m_context.getBinaryCollection());
3734     auto vertModule  = createShaderModule(vk, device, bc.get("vert"));
3735     auto frag0Module = createShaderModule(vk, device, bc.get("frag0"));
3736     auto frag1Module = createShaderModule(vk, device, bc.get("frag1"));
3737     VkPipelineShaderStageCreateInfo shaderInfo[2]{
3738         makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_VERTEX_BIT, *vertModule),
3739         makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, *frag0Module)};
3740 
3741     // create pre-raster pipeline part
3742     VkGraphicsPipelineLibraryCreateInfoEXT preRasterLibraryInfo = initVulkanStructure();
3743     preRasterLibraryInfo.flags = VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT |
3744                                  VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT;
3745     VkGraphicsPipelineCreateInfo pipelineInfo = initVulkanStructure(&preRasterLibraryInfo);
3746     pipelineInfo.flags                        = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
3747     pipelineInfo.layout                       = *writePipelineLayout;
3748     pipelineInfo.renderPass                   = *renderPass;
3749     pipelineInfo.pVertexInputState            = &vertexInputStateInfo;
3750     pipelineInfo.pInputAssemblyState          = &inputAssemblyStateInfo;
3751     pipelineInfo.pViewportState               = &viewportStateInfo;
3752     pipelineInfo.pRasterizationState          = &rasterizationStateInfo;
3753     pipelineInfo.stageCount                   = 1u;
3754     pipelineInfo.pStages                      = shaderInfo;
3755     auto preRasterPipelinePart                = createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &pipelineInfo);
3756 
3757     // create fragment pipeline part
3758     VkGraphicsPipelineLibraryCreateInfoEXT fragShaderLibInfo = initVulkanStructure();
3759     fragShaderLibInfo.flags                                  = VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT |
3760                               VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT;
3761     pipelineInfo                    = initVulkanStructure(&fragShaderLibInfo);
3762     pipelineInfo.flags              = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
3763     pipelineInfo.layout             = *writePipelineLayout;
3764     pipelineInfo.renderPass         = *renderPass;
3765     pipelineInfo.pMultisampleState  = &multisampleStateInfo;
3766     pipelineInfo.pDepthStencilState = &depthStencilStateInfo;
3767     pipelineInfo.pColorBlendState   = &colorBlendStateInfo;
3768     pipelineInfo.stageCount         = 1u;
3769     pipelineInfo.pStages            = &shaderInfo[1];
3770     auto fragmentPipelinePart       = createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &pipelineInfo);
3771 
3772     // merge pipelines into writePipeline
3773     const VkPipeline libraryHandles[]{
3774         *preRasterPipelinePart,
3775         *fragmentPipelinePart,
3776     };
3777     VkPipelineLibraryCreateInfoKHR linkedPipelineLibraryInfo = initVulkanStructure();
3778     linkedPipelineLibraryInfo.libraryCount                   = 2u;
3779     linkedPipelineLibraryInfo.pLibraries                     = libraryHandles;
3780     VkGraphicsPipelineCreateInfo linkedPipelineInfo          = initVulkanStructure(&linkedPipelineLibraryInfo);
3781     linkedPipelineInfo.layout                                = *writePipelineLayout;
3782     const auto writePipeline = createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &linkedPipelineInfo);
3783 
3784     // create readPipeline
3785     pipelineInfo.pNext               = nullptr;
3786     pipelineInfo.flags               = 0;
3787     pipelineInfo.layout              = *readPipelineLayout;
3788     shaderInfo[1].module             = *frag1Module;
3789     pipelineInfo.pVertexInputState   = &vertexInputStateInfo;
3790     pipelineInfo.pInputAssemblyState = &inputAssemblyStateInfo;
3791     pipelineInfo.pViewportState      = &viewportStateInfo;
3792     pipelineInfo.pRasterizationState = &rasterizationStateInfo;
3793     pipelineInfo.stageCount          = 2u;
3794     pipelineInfo.pStages             = shaderInfo;
3795     pipelineInfo.subpass             = 1;
3796     auto readPipeline                = createGraphicsPipeline(vk, device, VK_NULL_HANDLE, &pipelineInfo);
3797 
3798     VkPipelineBindPoint bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
3799     const auto poolCreateFlags    = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
3800     const auto cmdPool(createCommandPool(vk, device, poolCreateFlags, queueFamilyIndex));
3801     const auto cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3802     const auto clearValue(makeClearValueColor(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)));
3803 
3804     // render triangle that covers whole color attachment
3805     beginCommandBuffer(vk, *cmdBuffer);
3806 
3807     beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, scissor, 1, &clearValue);
3808     vk.cmdBindPipeline(*cmdBuffer, bindPoint, *writePipeline);
3809     vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);
3810     vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
3811     vk.cmdBindPipeline(*cmdBuffer, bindPoint, *readPipeline);
3812     vk.cmdBindDescriptorSets(*cmdBuffer, bindPoint, *readPipelineLayout, 0u, 1u, &*descriptorSet, 0u, nullptr);
3813     vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);
3814     endRenderPass(vk, *cmdBuffer);
3815 
3816     endCommandBuffer(vk, *cmdBuffer);
3817     const VkQueue queue = getDeviceQueue(vk, device, queueFamilyIndex, 0);
3818     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
3819 
3820     uint32_t wrongSampleCount    = 0;
3821     const uint32_t sampleMask    = 4321; // same sample mask is used also in the shader
3822     const auto &bufferAllocation = bufferWithMemory.getAllocation();
3823     invalidateAlloc(vk, device, bufferAllocation);
3824     tcu::Vec4 redColor(1.0f, 0.0f, 0.0f, 1.0f);
3825     tcu::Vec4 clearColor(clearValue.color.float32);
3826     float *bufferPtr = static_cast<float *>(bufferAllocation.getHostPtr());
3827     for (uint32_t f = 0; f < imageSize * imageSize; ++f)
3828     {
3829         for (uint32_t sample = 0; sample < colorSamples; ++sample)
3830         {
3831             // make sure only those samples where the sample mask bit is non-zero have the "red" pixel values
3832             const float *color = bufferPtr + (f * colorSamples + sample) * 4; // there are 4 color components
3833             tcu::Vec4 sampleColor(color[0], color[1], color[2], color[3]);
3834             const tcu::Vec4 &expectedColor = (sampleMask & (1 << sample)) ? redColor : clearColor;
3835             wrongSampleCount += (sampleColor != expectedColor);
3836         }
3837     }
3838 
3839     if (wrongSampleCount == 0)
3840         return tcu::TestStatus::pass("Pass");
3841 
3842     // log image
3843     tcu::PixelBufferAccess resultAccess(mapVkFormat(VK_FORMAT_R32G32B32A32_SFLOAT), imageSize * colorSamples, imageSize,
3844                                         1, bufferPtr);
3845     m_context.getTestContext().getLog() << tcu::LogImage("image", "", resultAccess);
3846 
3847     return tcu::TestStatus::fail(std::to_string(wrongSampleCount) + " wrong samples values out of " +
3848                                  std::to_string(imageSize * imageSize * colorSamples));
3849 }
3850 
3851 class PipelineLibraryMiscTestCase : public TestCase
3852 {
3853 public:
3854     PipelineLibraryMiscTestCase(tcu::TestContext &context, const char *name, const MiscTestParams data);
3855     ~PipelineLibraryMiscTestCase(void) = default;
3856 
3857     void checkSupport(Context &context) const;
3858     void initPrograms(SourceCollections &programCollection) const;
3859     TestInstance *createInstance(Context &context) const;
3860 
3861 private:
3862     MiscTestParams m_testParams;
3863 };
3864 
PipelineLibraryMiscTestCase(tcu::TestContext & context,const char * name,const MiscTestParams params)3865 PipelineLibraryMiscTestCase::PipelineLibraryMiscTestCase(tcu::TestContext &context, const char *name,
3866                                                          const MiscTestParams params)
3867     : TestCase(context, name)
3868     , m_testParams(params)
3869 {
3870 }
3871 
checkSupport(Context & context) const3872 void PipelineLibraryMiscTestCase::checkSupport(Context &context) const
3873 {
3874     context.requireDeviceFunctionality("VK_EXT_graphics_pipeline_library");
3875 
3876     if ((m_testParams.mode == MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_FAST_LINKED) &&
3877         !context.getGraphicsPipelineLibraryPropertiesEXT().graphicsPipelineLibraryFastLinking)
3878         TCU_THROW(NotSupportedError, "graphicsPipelineLibraryFastLinking is not supported");
3879 
3880     if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT ||
3881         m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT_LIB)
3882         context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
3883 
3884     if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT_LIB)
3885         context.requireDeviceFunctionality("VK_KHR_pipeline_library");
3886 
3887     if (m_testParams.mode == MiscTestMode::NULL_RENDERING_CREATE_INFO)
3888         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
3889 
3890     if (m_testParams.mode == MiscTestMode::COMMON_FRAG_LIBRARY)
3891     {
3892         context.requireDeviceFunctionality("VK_EXT_mesh_shader");
3893 
3894         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_CLIP_DISTANCE);
3895         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_CULL_DISTANCE);
3896 
3897         // Check limits for clip and cull distances
3898         const VkPhysicalDeviceLimits limits =
3899             getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice()).limits;
3900         if ((numClipDistances > limits.maxClipDistances) || (numCullDistances > limits.maxCullDistances) ||
3901             ((numClipDistances + numCullDistances) > limits.maxCombinedClipAndCullDistances))
3902             TCU_THROW(NotSupportedError, "Specified values of clip or cull distances are not supported");
3903     }
3904 
3905     if ((m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_ALL_STAGES) ||
3906         (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_PRE_RASTERIZATION) ||
3907         (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_FRAGMENT))
3908         context.requireDeviceFunctionality("VK_KHR_multiview");
3909     else if ((m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_STAGES) ||
3910              (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_PRE_RASTERIZATION) ||
3911              (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_FRAGMENT))
3912     {
3913         context.requireDeviceFunctionality("VK_KHR_multiview");
3914         context.requireDeviceFunctionality("VK_EXT_mesh_shader");
3915         const auto &meshShaderFeatures = context.getMeshShaderFeaturesEXT();
3916         if (!meshShaderFeatures.multiviewMeshShader)
3917             TCU_THROW(NotSupportedError, "multiviewMeshShader not supported");
3918     }
3919 }
3920 
initPrograms(SourceCollections & programCollection) const3921 void PipelineLibraryMiscTestCase::initPrograms(SourceCollections &programCollection) const
3922 {
3923     if ((m_testParams.mode == MiscTestMode::BIND_NULL_DESCRIPTOR_SET) ||
3924         (m_testParams.mode == MiscTestMode::BIND_NULL_DESCRIPTOR_SET_IN_MONOLITHIC_PIPELINE))
3925     {
3926         std::string vertDefinition = "";
3927         std::string fragDefinition = "";
3928         std::string vertValue      = "  vec4 v = vec4(-1.0, 1.0, 2.0, -2.0);\n";
3929         std::string fragValue      = "  vec4 v = vec4(0.0, 0.2, 0.6, 0.75);\n";
3930 
3931         // define lambda that creates proper uniform buffer definition
3932         auto constructBufferDefinition = [](uint32_t setIndex)
3933         {
3934             return std::string("layout(set = ") + std::to_string(setIndex) +
3935                    ", binding = 0) uniform buf\n"
3936                    "{\n"
3937                    "  vec4 v;\n"
3938                    "};\n\n";
3939         };
3940 
3941         if (m_testParams.mode == MiscTestMode::BIND_NULL_DESCRIPTOR_SET_IN_MONOLITHIC_PIPELINE)
3942         {
3943             // descriptor set 0 will be nullptr, descriptor set 1 will be valid buffer with color
3944             fragDefinition = constructBufferDefinition(1);
3945             fragValue      = "";
3946         }
3947         else if (m_testParams.layoutsBits > 0u)
3948         {
3949             std::vector<uint32_t> bitsThatAreSet;
3950             const uint32_t maxBitsCount = 8 * sizeof(m_testParams.layoutsBits);
3951 
3952             // find set bits
3953             for (uint32_t i = 0u; i < m_testParams.layoutsCount; ++i)
3954             {
3955                 if (m_testParams.layoutsBits & (1 << (maxBitsCount - 1 - i)))
3956                     bitsThatAreSet.push_back(i);
3957             }
3958 
3959             // there should be 1 or 2 bits set
3960             DE_ASSERT((bitsThatAreSet.size() > 0) && (bitsThatAreSet.size() < 3));
3961 
3962             vertDefinition = constructBufferDefinition(bitsThatAreSet[0]);
3963             vertValue      = "";
3964 
3965             if (bitsThatAreSet.size() == 2u)
3966             {
3967                 fragDefinition = constructBufferDefinition(bitsThatAreSet[1]);
3968                 fragValue      = "";
3969             }
3970         }
3971 
3972         programCollection.glslSources.add("vert")
3973             << glu::VertexSource(std::string("#version 450\n"
3974                                              "precision mediump int;\nprecision highp float;\n") +
3975                                  vertDefinition +
3976                                  "out gl_PerVertex\n"
3977                                  "{\n"
3978                                  "  vec4 gl_Position;\n"
3979                                  "};\n\n"
3980                                  "void main()\n"
3981                                  "{\n" +
3982                                  vertValue +
3983                                  "  const float x = (v.x+v.z*((gl_VertexIndex & 2)>>1));\n"
3984                                  "  const float y = (v.y+v.w* (gl_VertexIndex % 2));\n"
3985 
3986                                  // note: there won't be full screen quad because of used scissors
3987                                  "  gl_Position = vec4(x, y, 0.0, 1.0);\n"
3988                                  "}\n");
3989 
3990         programCollection.glslSources.add("frag")
3991             << glu::FragmentSource(std::string("#version 450\n"
3992                                                "precision mediump int; precision highp float;"
3993                                                "layout(location = 0) out highp vec4 o_color;\n") +
3994                                    fragDefinition +
3995                                    "void main()\n"
3996                                    "{\n" +
3997                                    fragValue +
3998                                    "  o_color = v;\n"
3999                                    "}\n");
4000     }
4001     else if ((m_testParams.mode == MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_FAST_LINKED) ||
4002              (m_testParams.mode ==
4003               MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_WITH_LINK_TIME_OPTIMIZATION_UNION_HANDLE))
4004     {
4005         programCollection.glslSources.add("vert")
4006             << glu::VertexSource("#version 450\n"
4007                                  "precision mediump int; precision highp float;\n"
4008                                  "layout(set = 0, binding = 0) uniform bufA\n"
4009                                  "{\n"
4010                                  "  vec4 valueA;\n"
4011                                  "};\n"
4012                                  "layout(set = 2, binding = 0) uniform bufC\n"
4013                                  "{\n"
4014                                  "  vec4 valueC;\n"
4015                                  "};\n"
4016                                  "out gl_PerVertex\n"
4017                                  "{\n"
4018                                  "  vec4 gl_Position;\n"
4019                                  "};\n\n"
4020                                  "void main()\n"
4021                                  "{\n"
4022                                  // note: values in buffers were set to get vec4(-1, 1, 2, -2)
4023                                  "  const vec4  v = valueA + valueC;\n"
4024                                  "  const float x = (v.x+v.z*((gl_VertexIndex & 2)>>1));\n"
4025                                  "  const float y = (v.y+v.w* (gl_VertexIndex % 2));\n"
4026 
4027                                  // note: there won't be full screen quad because of used scissors
4028                                  "  gl_Position = vec4(x, y, 0.0, 1.0);\n"
4029                                  "}\n");
4030 
4031         programCollection.glslSources.add("frag")
4032             << glu::FragmentSource("#version 450\n"
4033                                    "precision mediump int; precision highp float;"
4034                                    "layout(location = 0) out highp vec4 o_color;\n"
4035                                    "layout(set = 0, binding = 0) uniform bufA\n"
4036                                    "{\n"
4037                                    "  vec4 valueA;\n"
4038                                    "};\n"
4039                                    "layout(set = 1, binding = 0) uniform bufB\n"
4040                                    "{\n"
4041                                    "  vec4 valueB;\n"
4042                                    "};\n"
4043                                    "void main()\n"
4044                                    "{\n"
4045                                    // note: values in buffers were set to get vec4(0.0, 0.75, 0.5, 0.2)
4046                                    "  o_color = valueA * valueB;\n"
4047                                    "}\n");
4048     }
4049     else if (m_testParams.mode == MiscTestMode::COMPARE_LINK_TIMES)
4050     {
4051         programCollection.glslSources.add("vert") << glu::VertexSource(
4052             "#version 450\n"
4053             "precision mediump int; precision highp float;"
4054             "layout(location = 0) in vec4 in_position;\n"
4055             "out gl_PerVertex\n"
4056             "{\n"
4057             "  vec4 gl_Position;\n"
4058             "};\n"
4059             "layout(constant_id = 0) const int random = 0;\n\n"
4060             "void main()\n"
4061             "{\n"
4062             "   gl_Position = vec4(float(1 - 2 * int(gl_VertexIndex != 1)),\n"
4063             "                      float(1 - 2 * int(gl_VertexIndex > 0)), 0.0, 1.0) + float(random & 1);\n"
4064             "}\n");
4065 
4066         programCollection.glslSources.add("frag")
4067             << glu::FragmentSource("#version 450\n"
4068                                    "precision mediump int; precision highp float;"
4069                                    "layout(location = 0) out highp vec4 o_color;\n"
4070                                    "layout(constant_id = 0) const int random = 0;\n\n"
4071                                    "void main()\n"
4072                                    "{\n"
4073                                    "  o_color = vec4(0.0, 1.0, 0.5, 1.0) + float(random & 1);\n"
4074                                    "}\n");
4075     }
4076     else if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_COMP)
4077     {
4078         std::ostringstream comp;
4079         comp << "#version 450\n"
4080              << "layout (set=0, binding=0, std430) buffer BufferBlock {\n"
4081              << "    uint values[" << PipelineLibraryShaderModuleInfoInstance::kOutputBufferElements << "];\n"
4082              << "} outBuffer;\n"
4083              << "layout (local_size_x=" << PipelineLibraryShaderModuleInfoInstance::kOutputBufferElements
4084              << ", local_size_y=1, local_size_z=1) in;\n"
4085              << "void main (void)\n"
4086              << "{\n"
4087              << "    outBuffer.values[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;\n"
4088              << "}\n";
4089         programCollection.glslSources.add("comp") << glu::ComputeSource(comp.str());
4090     }
4091     else if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT ||
4092              m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT_LIB)
4093     {
4094         const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
4095         std::ostringstream rgen;
4096         rgen << "#version 460 core\n"
4097              << "#extension GL_EXT_ray_tracing : require\n"
4098              << "layout (set=0, binding=0, std430) buffer BufferBlock {\n"
4099              << "    uint values[" << PipelineLibraryShaderModuleInfoInstance::kOutputBufferElements << "];\n"
4100              << "} outBuffer;\n"
4101              << "void main (void)\n"
4102              << "{\n"
4103              << "    outBuffer.values[gl_LaunchIDEXT.x] = gl_LaunchIDEXT.x;\n"
4104              << "}\n";
4105         programCollection.glslSources.add("rgen") << glu::RaygenSource(rgen.str()) << buildOptions;
4106     }
4107     else if (m_testParams.mode == MiscTestMode::NULL_RENDERING_CREATE_INFO)
4108     {
4109         std::ostringstream vert;
4110         vert << "#version 460\n"
4111              << "vec2 positions[3] = vec2[](\n"
4112              << "    vec2(-1.0, -1.0),\n"
4113              << "    vec2(-1.0,  3.0),\n"
4114              << "    vec2( 3.0, -1.0)\n"
4115              << ");\n"
4116              << "void main() {\n"
4117              << "    gl_Position = vec4(positions[gl_VertexIndex % 3], 0.0, 1.0);\n"
4118              << "}\n";
4119         programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
4120 
4121         std::ostringstream frag;
4122         frag << "#version 460\n"
4123              << "layout (location=0) out vec4 color;\n"
4124              << "void main () {\n"
4125              << "    color = vec4(0.0, 0.0, 1.0, 1.0);\n"
4126              << "}\n";
4127         programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
4128     }
4129     else if (m_testParams.mode == MiscTestMode::COMMON_FRAG_LIBRARY)
4130     {
4131         std::ostringstream vert;
4132         {
4133             std::string perVertexBlock;
4134             {
4135                 std::ostringstream str;
4136                 str << "gl_PerVertex {\n"
4137                     << "    vec4  gl_Position;\n";
4138                 str << "    float gl_ClipDistance[" << numClipDistances << "];\n";
4139                 str << "    float gl_CullDistance[" << numCullDistances << "];\n";
4140                 str << "}";
4141                 perVertexBlock = str.str();
4142             }
4143 
4144             vert << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4145                  << "\n"
4146                  << "layout(location = 0) in  vec4 v_position;\n"
4147                  << "layout(location = 0) out vec4 out_color;\n"
4148                  << "\n"
4149                  << "out " << perVertexBlock << ";\n"
4150                  << "\n"
4151                  << "void main (void)\n"
4152                  << "{\n"
4153                  << "    gl_Position = v_position;\n"
4154                  << "    out_color   = vec4(1.0, 0.5 * (v_position.x + 1.0), 0.0, 1.0);\n"
4155                  << "\n"
4156                  << "    const int barNdx = gl_VertexIndex / 6;\n"
4157                  << "    for (int i = 0; i < " << numClipDistances << "; ++i)\n"
4158                  << "      gl_ClipDistance[i] = (barNdx == i ? v_position.y : 0.0);\n"
4159                  << "    for (int i = 0; i < " << numCullDistances << "; ++i)\n"
4160                  << "    gl_CullDistance[i] = (gl_Position.y < 0) ? -0.5f : 0.5f;\n"
4161                  << "}\n";
4162         }
4163         programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
4164 
4165         const auto buildOptions =
4166             vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
4167         std::ostringstream mesh;
4168         {
4169             mesh << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4170                  << "#extension GL_EXT_mesh_shader : enable\n"
4171                  << "\n"
4172                  << "layout(local_size_x = 16) in;\n"
4173                  << "layout(triangles, max_vertices = 48, max_primitives = 16) out;\n"
4174                  << "\n"
4175                  << "layout (set=0, binding=0) uniform CoordsBuffer {\n"
4176                  << "    vec4 coords[48];\n"
4177                  << "} cb;\n"
4178                  << "\n"
4179                  << "layout (location = 0) out PerVertexData {\n"
4180                  << "    vec4 color;\n"
4181                  << "} v_out[];\n"
4182                  << "\n"
4183 
4184                  << "out gl_MeshPerVertexEXT {\n"
4185                  << "  vec4  gl_Position;\n"
4186                  << "  float gl_PointSize;\n"
4187                  << "  float gl_ClipDistance[" << numClipDistances << "];\n"
4188                  << "  float gl_CullDistance[" << numCullDistances << "];\n"
4189                  << "} gl_MeshVerticesEXT[];\n"
4190 
4191                  << "void main ()\n"
4192                  << "{\n"
4193                  << "  SetMeshOutputsEXT(48u, 16u);\n"
4194                  << "  uint idx = gl_LocalInvocationIndex * 3;\n"
4195                  << "  for (uint j = 0; j < 3; j++) {\n"
4196                  << "    uint vIdx = idx+j;\n"
4197                  << "    gl_MeshVerticesEXT[vIdx].gl_Position = cb.coords[vIdx];\n"
4198                  << "    uint barNdx = vIdx / 6;\n"
4199 
4200                  << "    for (int i = 0; i < " << numClipDistances << "; ++i)\n"
4201                  << "      gl_MeshVerticesEXT[vIdx].gl_ClipDistance[i] = ((barNdx == i) ? cb.coords[vIdx].y : 0);\n"
4202 
4203                  << "    for (int i = 0; i < " << numCullDistances << "; ++i)\n"
4204                  << "      gl_MeshVerticesEXT[vIdx].gl_CullDistance[i] = ((cb.coords[vIdx].y < 0) ? -0.5 : 0.5);\n"
4205 
4206                  << "    float xx = cb.coords[vIdx].x;\n"
4207                  << "    v_out[vIdx].color = vec4(1.0, 0.5 * (xx + 1.0), 0.0, 1.0);\n"
4208                  << "  }\n"
4209                  << "  gl_PrimitiveTriangleIndicesEXT[gl_LocalInvocationIndex] = uvec3(idx, idx+1, idx+2);\n"
4210                  << "}\n";
4211         }
4212         programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
4213 
4214         std::ostringstream frag;
4215 
4216         {
4217             frag << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4218                  << "\n"
4219                  << "layout(location = 0) in flat vec4 in_color;\n"
4220                  << "layout(location = 0) out vec4 o_color;\n";
4221             frag << "in float gl_ClipDistance[" << numClipDistances << "];\n";
4222             frag << "in float gl_CullDistance[" << numCullDistances << "];\n";
4223 
4224             frag << "\n"
4225                  << "void main (void)\n"
4226                  << "{\n";
4227 
4228             frag << "    o_color = vec4(in_color.r, "
4229                  << "    gl_ClipDistance[" << (numClipDistances / 2) << "], "
4230                  << "    gl_CullDistance[" << (numCullDistances / 2) << "], "
4231                  << "    1.0);\n";
4232             frag << "}\n";
4233         }
4234         programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
4235     }
4236     else if ((m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_ALL_STAGES) ||
4237              (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_PRE_RASTERIZATION) ||
4238              (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_FRAGMENT))
4239     {
4240         std::string vert("#version 460\n"
4241                          "#extension GL_EXT_multiview : require\n"
4242                          "layout(location = 0) flat out uvec4 vViewIndex;"
4243                          "void main() {\n"
4244                          "  const float x = -1.0 + 4.0 * ((gl_VertexIndex & 2)>>1);\n"
4245                          "  const float y = -1.0 + 4.0 * (gl_VertexIndex % 2);\n"
4246                          "  gl_Position = vec4(x, y, 0.0, 1.0);\n"
4247                          "  vViewIndex = uvec4(0);\n"
4248                          "  vViewIndex.x = gl_ViewIndex;\n"
4249                          "}\n");
4250         programCollection.glslSources.add("vert") << glu::VertexSource(vert);
4251 
4252         std::string tesc("#version 450\n"
4253                          "#extension GL_EXT_multiview : require\n"
4254                          "layout (vertices = 3) out;\n"
4255                          "layout(location = 0) flat in uvec4 vViewIndex[];\n"
4256                          "layout(location = 0) flat out uvec4 vtcViewIndex[];\n"
4257                          "void main (void)\n"
4258                          "{\n"
4259                          "  gl_TessLevelInner[0] = 1.0;\n"
4260                          "  gl_TessLevelInner[1] = 1.0;\n"
4261                          "  gl_TessLevelOuter[0] = 1.0;\n"
4262                          "  gl_TessLevelOuter[1] = 1.0;\n"
4263                          "  gl_TessLevelOuter[2] = 1.0;\n"
4264                          "  gl_TessLevelOuter[3] = 1.0;\n"
4265                          "  vtcViewIndex[gl_InvocationID] = vViewIndex[gl_InvocationID];\n"
4266                          "  vtcViewIndex[gl_InvocationID].y = gl_ViewIndex;\n"
4267                          "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
4268                          "}\n");
4269         programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tesc);
4270 
4271         std::string tese("#version 450\n"
4272                          "#extension GL_EXT_multiview : require\n"
4273                          "layout(triangles, fractional_odd_spacing, cw) in;\n"
4274                          "layout(location = 0) flat in uvec4 vtcViewIndex[];\n"
4275                          "layout(location = 0) flat out uvec4 vtViewIndex;\n"
4276                          "void main (void)\n"
4277                          "{\n"
4278                          "  gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) +\n"
4279                          "                (gl_TessCoord.y * gl_in[1].gl_Position) +\n"
4280                          "                (gl_TessCoord.z * gl_in[2].gl_Position);\n"
4281                          "  vtViewIndex = vtcViewIndex[0];\n"
4282                          "  vtViewIndex.y += gl_ViewIndex;\n"
4283                          "}\n");
4284         programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(tese);
4285 
4286         std::string geom("#version 450\n"
4287                          "#extension GL_EXT_multiview : require\n"
4288                          "layout (triangles) in;\n"
4289                          "layout (triangle_strip, max_vertices=3) out;\n"
4290                          "layout(location = 0) flat in uvec4 vtViewIndex[];\n"
4291                          "layout(location = 0) flat out uvec4 vtgViewIndex;\n"
4292                          "void main (void)\n"
4293                          "{\n"
4294                          "  for (int i = 0; i < 3; i++)\n"
4295                          "  {\n"
4296                          "    gl_Position = gl_in[i].gl_Position;\n"
4297                          "    vtgViewIndex = vtViewIndex[i];\n"
4298                          "    vtgViewIndex.z = gl_ViewIndex;\n"
4299                          "    EmitVertex();\n"
4300                          "  }\n"
4301                          "}\n");
4302         programCollection.glslSources.add("geom") << glu::GeometrySource(geom);
4303 
4304         std::string frag("#version 460\n"
4305                          "#extension GL_EXT_multiview : require\n"
4306                          "layout(location = 0) flat in uvec4 vtgViewIndex;\n"
4307                          "layout (location=0) out uvec4 color;\n"
4308                          "void main () {\n"
4309                          "  color = vtgViewIndex;\n"
4310                          "  color.a = gl_ViewIndex;\n"
4311                          "}\n");
4312         programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
4313     }
4314     else if ((m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_STAGES) ||
4315              (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_PRE_RASTERIZATION) ||
4316              (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_FRAGMENT))
4317     {
4318         const auto buildOptions =
4319             vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0, true);
4320 
4321         std::string mesh("#version 450\n"
4322                          "#extension GL_EXT_mesh_shader : enable\n"
4323                          "#extension GL_EXT_multiview : require\n"
4324                          "layout(local_size_x=3) in;\n"
4325                          "layout(triangles) out;\n"
4326                          "layout(max_vertices=3, max_primitives=1) out;\n"
4327                          "layout(location = 0) perprimitiveEXT flat out uvec4 mViewIndex[];\n"
4328                          "void main() {\n"
4329                          "  SetMeshOutputsEXT(3u, 1u);\n"
4330                          "  const uint idx = gl_LocalInvocationIndex;\n"
4331                          "  const float x = -1.0 + 4.0 * ((idx & 2)>>1);\n"
4332                          "  const float y = -1.0 + 4.0 * (idx % 2);\n"
4333                          "  gl_MeshVerticesEXT[idx].gl_Position = vec4(x, y, 0.0, 1.0);\n"
4334                          "  gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
4335                          "  mViewIndex[idx] = uvec4(0);\n"
4336                          "  mViewIndex[idx].x = gl_ViewIndex;\n"
4337                          "}\n");
4338         programCollection.glslSources.add("mesh") << glu::MeshSource(mesh) << buildOptions;
4339 
4340         std::string frag("#version 460\n"
4341                          "#extension GL_EXT_multiview : require\n"
4342                          "#extension GL_EXT_mesh_shader : enable\n"
4343                          "layout(location = 0) perprimitiveEXT flat in uvec4 mViewIndex;\n"
4344                          "layout (location=0) out uvec4 color;\n"
4345                          "void main () {\n"
4346                          "  color = mViewIndex;\n"
4347                          "  color.a = gl_ViewIndex;\n"
4348                          "}\n");
4349         programCollection.glslSources.add("frag") << glu::FragmentSource(frag) << buildOptions;
4350     }
4351     else if (m_testParams.mode == MiscTestMode::UNUSUAL_MULTISAMPLE_STATE)
4352     {
4353         programCollection.glslSources.add("vert")
4354             << glu::VertexSource("#version 460\n"
4355                                  "void main() {\n"
4356                                  "  const float x = -1.0 + 4.0 * ((gl_VertexIndex & 2)>>1);\n"
4357                                  "  const float y = -1.0 + 4.0 * (gl_VertexIndex % 2);\n"
4358                                  "  gl_Position = vec4(x, y, 0.0, 1.0);\n"
4359                                  "}\n");
4360         programCollection.glslSources.add("frag0")
4361             << glu::FragmentSource("#version 460\n"
4362                                    "layout(location = 0) out highp vec4 o_color;\n"
4363                                    "void main()\n"
4364                                    "{\n"
4365                                    "    const int numSamples = 4;\n"
4366                                    "    const int sampleMask = 4321;\n"
4367                                    "    for (int i = 0; i < (numSamples + 31) / 32; ++i) {\n"
4368                                    "        gl_SampleMask[i] = sampleMask & gl_SampleMaskIn[i];\n"
4369                                    "    }\n"
4370                                    "    o_color = vec4(1, 0, 0, 1);\n"
4371                                    "}\n");
4372         programCollection.glslSources.add("frag1") << glu::FragmentSource(
4373             "#version 460\n"
4374             "layout (input_attachment_index=0, binding = 0) uniform subpassInputMS inputAttachment;\n"
4375             "layout (binding = 1) buffer resultBuffer { vec4 v[]; };\n"
4376             "void main()\n"
4377             "{\n"
4378             "    const int numSamples = 4;\n"
4379             "    const int imageWidth = 8;\n"
4380             "    const ivec2 coord = ivec2(int(gl_FragCoord.x), gl_FragCoord.y);\n"
4381             "    const uint fIndex = (coord.y * imageWidth + coord.x) * numSamples;\n"
4382             "    for (int sampleId = 0; sampleId < numSamples; ++sampleId) {\n"
4383             "        v[fIndex + sampleId] = subpassLoad(inputAttachment, sampleId);\n"
4384             "    }\n"
4385             "}\n");
4386     }
4387     else
4388     {
4389         DE_ASSERT(false);
4390     }
4391 }
4392 
createInstance(Context & context) const4393 TestInstance *PipelineLibraryMiscTestCase::createInstance(Context &context) const
4394 {
4395     if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_COMP)
4396         return new PipelineLibraryShaderModuleInfoCompInstance(context);
4397 
4398     if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT)
4399         return new PipelineLibraryShaderModuleInfoRTInstance(context, false /*withLibrary*/);
4400 
4401     if (m_testParams.mode == MiscTestMode::SHADER_MODULE_CREATE_INFO_RT_LIB)
4402         return new PipelineLibraryShaderModuleInfoRTInstance(context, true /*withLibrary*/);
4403 
4404     if (m_testParams.mode == MiscTestMode::NULL_RENDERING_CREATE_INFO)
4405         return new NullRenderingCreateInfoInstance(context);
4406 
4407     if ((m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_ALL_STAGES) ||
4408         (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_PRE_RASTERIZATION) ||
4409         (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_FRAGMENT) ||
4410         (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_STAGES) ||
4411         (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_PRE_RASTERIZATION) ||
4412         (m_testParams.mode == MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_FRAGMENT))
4413         return new CreateViewIndexFromDeviceIndexInstance(context, m_testParams);
4414 
4415     if (m_testParams.mode == MiscTestMode::UNUSUAL_MULTISAMPLE_STATE)
4416         return new CreateUnusualMultisampleStatesInstance(context);
4417 
4418     return new PipelineLibraryMiscTestInstance(context, m_testParams);
4419 }
4420 
addPipelineLibraryConfigurationsTests(tcu::TestCaseGroup * group,bool optimize)4421 void addPipelineLibraryConfigurationsTests(tcu::TestCaseGroup *group, bool optimize)
4422 {
4423     const int R                                                 = -1;
4424     const PipelineTreeConfiguration pipelineTreeConfiguration[] = {
4425         {{
4426             {R, 4}, /*     4     */
4427         }},
4428 
4429         {{
4430             {R, 0}, /*     0     */
4431                     /*  / / \ \  */
4432             {0, 1},
4433             {0, 1},
4434             {0, 1},
4435             {0, 1} /*  1 1 1 1  */
4436         }},
4437 
4438         {{
4439             {R, 0}, /*     0     */
4440                     /*  / / \    */
4441             {0, 1},
4442             {0, 1},
4443             {0, 2} /*  1 1  2   */
4444         }},
4445 
4446         {{
4447             {R, 0}, /*     0     */
4448                     /*  / / \    */
4449             {0, 1},
4450             {0, 2},
4451             {0, 1} /* 1 2   1   */
4452         }},
4453 
4454         {{
4455             {R, 0}, /*     0     */
4456                     /*    / \    */
4457             {0, 2},
4458             {0, 2}, /*   2   2   */
4459         }},
4460 
4461         {{
4462             {R, 1}, /*     1     */
4463                     /*    / \    */
4464             {0, 2},
4465             {0, 1}, /*   2   1   */
4466         }},
4467 
4468         {{
4469             {R, 2}, /*     2     */
4470                     /*    / \    */
4471             {0, 1},
4472             {0, 1}, /*   1   1   */
4473         }},
4474 
4475         {{
4476             {R, 3}, /*     3     */
4477                     /*    /      */
4478             {0, 1}, /*   1       */
4479         }},
4480 
4481         {{
4482             {R, 1}, /*     1     */
4483                     /*    /      */
4484             {0, 3}, /*   3       */
4485         }},
4486 
4487         {{
4488             {R, 0}, /*     0     */
4489                     /*    / \    */
4490             {0, 0},
4491             {0, 0}, /*   0   0   */
4492                     /*  / \ / \  */
4493             {1, 1},
4494             {1, 1},
4495             {2, 1},
4496             {2, 1}, /* 1  1 1  1 */
4497         }},
4498 
4499         {{
4500             {R, 0}, /*     0     */
4501                     /*    / \    */
4502             {0, 0},
4503             {0, 1}, /*   0   1   */
4504                     /*  / \   \  */
4505             {1, 1},
4506             {1, 1},
4507             {2, 1}, /* 1   1   1 */
4508         }},
4509 
4510         {{
4511             {R, 1}, /*     1     */
4512                     /*    / \    */
4513             {0, 0},
4514             {0, 1}, /*   0   1   */
4515                     /*  / \      */
4516             {1, 1},
4517             {1, 1}, /* 1   1     */
4518         }},
4519 
4520         {{
4521             {R, 1}, /*     1     */
4522                     /*    /      */
4523             {0, 1}, /*   1       */
4524                     /*  / \      */
4525             {1, 1},
4526             {1, 1}, /* 1   1     */
4527         }},
4528 
4529         {{
4530             {R, 1}, /*        1  */
4531                     /*       /   */
4532             {0, 1}, /*      1    */
4533                     /*     /     */
4534             {1, 1}, /*    1      */
4535                     /*   /       */
4536             {2, 1}, /*  1        */
4537         }},
4538     };
4539 
4540     for (size_t libConfigNdx = 0; libConfigNdx < DE_LENGTH_OF_ARRAY(pipelineTreeConfiguration); ++libConfigNdx)
4541     {
4542         const bool delayedShaderCreate = (libConfigNdx != 0);
4543         const TestParams testParams    = {
4544             pipelineTreeConfiguration[libConfigNdx], //  PipelineTreeConfiguration pipelineTreeConfiguration;
4545             optimize,                                //  bool optimize;
4546             delayedShaderCreate,                     //  bool delayedShaderCreate;
4547             false                                    //  bool useMaintenance5;
4548         };
4549         const std::string testName = getTestName(pipelineTreeConfiguration[libConfigNdx]);
4550 
4551         if (optimize && testParams.pipelineTreeConfiguration.size() == 1)
4552             continue;
4553 
4554         group->addChild(new PipelineLibraryTestCase(group->getTestContext(), testName.c_str(), testParams));
4555     }
4556 
4557     // repeat first case (one that creates montolithic pipeline) to test VK_KHR_maintenance5;
4558     // VkShaderModule deprecation (tested with delayedShaderCreate) was added to VK_KHR_maintenance5
4559     if (optimize == false)
4560     {
4561         const TestParams testParams{
4562             pipelineTreeConfiguration[0], //  PipelineTreeConfiguration pipelineTreeConfiguration;
4563             false,                        //  bool optimize;
4564             true,                         //  bool delayedShaderCreate;
4565             true                          //  bool useMaintenance5;
4566         };
4567 
4568         group->addChild(new PipelineLibraryTestCase(group->getTestContext(), "maintenance5", testParams));
4569     }
4570 }
4571 
4572 } // namespace
4573 
createPipelineLibraryTests(tcu::TestContext & testCtx)4574 tcu::TestCaseGroup *createPipelineLibraryTests(tcu::TestContext &testCtx)
4575 {
4576     de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "graphics_library"));
4577 
4578     // Tests graphics pipeline libraries linkage without optimization
4579     addTestGroup(group.get(), "fast", addPipelineLibraryConfigurationsTests, false);
4580     // Tests graphics pipeline libraries linkage with optimization
4581     addTestGroup(group.get(), "optimize", addPipelineLibraryConfigurationsTests, true);
4582 
4583     de::MovePtr<tcu::TestCaseGroup> miscTests(new tcu::TestCaseGroup(testCtx, "misc"));
4584 
4585     de::MovePtr<tcu::TestCaseGroup> independentLayoutSetsTests(
4586         new tcu::TestCaseGroup(testCtx, "independent_pipeline_layout_sets"));
4587     independentLayoutSetsTests->addChild(new PipelineLibraryMiscTestCase(
4588         testCtx, "fast_linked", {MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_FAST_LINKED, 0u, 0u}));
4589     independentLayoutSetsTests->addChild(new PipelineLibraryMiscTestCase(
4590         testCtx, "link_opt_union_handle",
4591         {MiscTestMode::INDEPENDENT_PIPELINE_LAYOUT_SETS_WITH_LINK_TIME_OPTIMIZATION_UNION_HANDLE, 0u, 0u}));
4592     miscTests->addChild(independentLayoutSetsTests.release());
4593 
4594     de::MovePtr<tcu::TestCaseGroup> bindNullDescriptorCombinationsTests(
4595         new tcu::TestCaseGroup(testCtx, "bind_null_descriptor_set"));
4596     const std::vector<const char *> bindNullDescriptorCombinations{
4597         // note: there will be as many descriptor sets layouts in pipeline layout as there are chcaracters in the case name;
4598         // '0' represents unused descriptor set layout, '1' represents used one;
4599         // location of first '1' represents index of layout used in vertex shader;
4600         // if present second '1' represents index of layout used in fragment shader
4601         "1",   "11", "01", "10", "101", "1010",
4602         "1001" // descriptor sets layouts for first pipeline part will be (&layoutA, NULL, NULL, NULL),
4603         //                                     for second pipeline part (NULL, NULL, NULL, &layoutB)
4604     };
4605     for (const char *name : bindNullDescriptorCombinations)
4606     {
4607         uint32_t layoutsCount = static_cast<uint32_t>(strlen(name));
4608         uint32_t layoutsBits  = 0u;
4609 
4610         // construct uint32_t with bits sets based on case name
4611         for (uint32_t i = 0; i < layoutsCount; ++i)
4612             layoutsBits |= (name[i] == '1') * (1 << (8 * sizeof(layoutsBits) - i - 1));
4613 
4614         bindNullDescriptorCombinationsTests->addChild(new PipelineLibraryMiscTestCase(
4615             testCtx, name, {MiscTestMode::BIND_NULL_DESCRIPTOR_SET, layoutsCount, layoutsBits}));
4616     }
4617     miscTests->addChild(bindNullDescriptorCombinationsTests.release());
4618 
4619     {
4620         de::MovePtr<tcu::TestCaseGroup> otherTests(new tcu::TestCaseGroup(testCtx, "other"));
4621         otherTests->addChild(
4622             new PipelineLibraryMiscTestCase(testCtx, "compare_link_times", {MiscTestMode::COMPARE_LINK_TIMES, 0u, 0u}));
4623         otherTests->addChild(
4624             new PipelineLibraryMiscTestCase(testCtx, "null_descriptor_set_in_monolithic_pipeline",
4625                                             {MiscTestMode::BIND_NULL_DESCRIPTOR_SET_IN_MONOLITHIC_PIPELINE, 0u, 0u}));
4626         otherTests->addChild(new PipelineLibraryMiscTestCase(testCtx, "null_rendering_create_info",
4627                                                              {MiscTestMode::NULL_RENDERING_CREATE_INFO, 0u, 0u}));
4628         otherTests->addChild(new PipelineLibraryMiscTestCase(testCtx, "common_frag_pipeline_library",
4629                                                              {MiscTestMode::COMMON_FRAG_LIBRARY, 0u, 0u}));
4630 
4631         otherTests->addChild(
4632             new PipelineLibraryMiscTestCase(testCtx, "view_index_from_device_index_in_all_stages",
4633                                             {MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_ALL_STAGES, 0u, 0u}));
4634         otherTests->addChild(
4635             new PipelineLibraryMiscTestCase(testCtx, "view_index_from_device_index_in_pre_rasterization",
4636                                             {MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_PRE_RASTERIZATION, 0u, 0u}));
4637         otherTests->addChild(
4638             new PipelineLibraryMiscTestCase(testCtx, "view_index_from_device_index_in_fragment",
4639                                             {MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_FRAGMENT, 0u, 0u}));
4640         otherTests->addChild(
4641             new PipelineLibraryMiscTestCase(testCtx, "view_index_from_device_index_in_mesh_stages",
4642                                             {MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_STAGES, 0u, 0u}));
4643         otherTests->addChild(new PipelineLibraryMiscTestCase(
4644             testCtx, "view_index_from_device_index_in_mesh_pre_rasterization",
4645             {MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_PRE_RASTERIZATION, 0u, 0u}));
4646         otherTests->addChild(
4647             new PipelineLibraryMiscTestCase(testCtx, "view_index_from_device_index_in_mesh_fragment",
4648                                             {MiscTestMode::VIEW_INDEX_FROM_DEVICE_INDEX_IN_MESH_FRAGMENT, 0u, 0u}));
4649 
4650         otherTests->addChild(new PipelineLibraryMiscTestCase(testCtx, "unusual_multisample_state",
4651                                                              {MiscTestMode::UNUSUAL_MULTISAMPLE_STATE, 0u, 0u}));
4652 
4653         miscTests->addChild(otherTests.release());
4654     }
4655 
4656     {
4657         de::MovePtr<tcu::TestCaseGroup> nonGraphicsTests(new tcu::TestCaseGroup(testCtx, "non_graphics"));
4658         nonGraphicsTests->addChild(new PipelineLibraryMiscTestCase(
4659             testCtx, "shader_module_info_comp", {MiscTestMode::SHADER_MODULE_CREATE_INFO_COMP, 0u, 0u}));
4660         nonGraphicsTests->addChild(new PipelineLibraryMiscTestCase(
4661             testCtx, "shader_module_info_rt", {MiscTestMode::SHADER_MODULE_CREATE_INFO_RT, 0u, 0u}));
4662         nonGraphicsTests->addChild(new PipelineLibraryMiscTestCase(
4663             testCtx, "shader_module_info_rt_lib", {MiscTestMode::SHADER_MODULE_CREATE_INFO_RT_LIB, 0u, 0u}));
4664         miscTests->addChild(nonGraphicsTests.release());
4665     }
4666 
4667     group->addChild(miscTests.release());
4668 
4669     return group.release();
4670 }
4671 
4672 } // namespace pipeline
4673 
4674 } // namespace vkt
4675