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