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