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