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