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