1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2021 The Khronos Group Inc.
6 * Copyright (c) 2021 Valve Corporation.
7 * Copyright (c) 2023 LunarG, Inc.
8 * Copyright (c) 2023 Nintendo
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file
24 * \brief Pipeline Bind Point Tests
25 *//*--------------------------------------------------------------------*/
26 #include "vktPipelineBindPointTests.hpp"
27 #include "vktPipelineImageUtil.hpp"
28
29 #include "vkObjUtil.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkTypeUtil.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkBarrierUtil.hpp"
35 #include "vkBufferWithMemory.hpp"
36 #include "vkImageWithMemory.hpp"
37 #include "vkRayTracingUtil.hpp"
38
39 #include "tcuVector.hpp"
40
41 #include <algorithm>
42 #include <string>
43 #include <sstream>
44 #include <type_traits>
45 #include <utility>
46
47 namespace vkt
48 {
49 namespace pipeline
50 {
51
52 namespace
53 {
54
55 using namespace vk;
56
57 // These operations will be tried in different orders.
58 // To avoid combinatory explosions, we'll only use two pipeline types per test, which means 2 pipeline bind operations and 2 related set bind operations.
59 // The following types will be mixed: (graphics, compute), (graphics, ray tracing) and (compute, ray tracing).
60 enum class SetupOp
61 {
62 BIND_GRAPHICS_PIPELINE = 0,
63 BIND_COMPUTE_PIPELINE = 1,
64 BIND_RAYTRACING_PIPELINE = 2,
65 BIND_GRAPHICS_SET = 3,
66 BIND_COMPUTE_SET = 4,
67 BIND_RAYTRACING_SET = 5,
68 OP_COUNT = 6,
69 };
70
71 // How to bind each set.
72 enum class SetUpdateType
73 {
74 WRITE = 0,
75 PUSH = 1,
76 PUSH_WITH_TEMPLATE = 2,
77 TYPE_COUNT = 3,
78 };
79
80 // Types of operations to dispatch. They will be tried in different orders and are related to the setup sequence.
81 enum class DispatchOp
82 {
83 DRAW = 0,
84 COMPUTE = 1,
85 TRACE_RAYS = 2,
86 OP_COUNT = 3,
87 };
88
89 constexpr auto kTestBindPoints = 2; // Two bind points per test.
90 constexpr auto kSetupSequenceSize = kTestBindPoints * 2; // For each bind point: bind pipeline and bind set.
91 constexpr auto kDispatchSequenceSize = kTestBindPoints; // Dispatch two types of work, matching the bind points being used.
92
93 using SetupSequence = tcu::Vector<SetupOp, kSetupSequenceSize>;
94 using DispatchSequence = tcu::Vector<DispatchOp, kDispatchSequenceSize>;
95
96 // Test parameters.
97 struct TestParams
98 {
99 PipelineConstructionType pipelineConstructionType;
100 SetUpdateType graphicsSetUpdateType;
101 SetUpdateType computeSetUpdateType;
102 SetUpdateType rayTracingSetUpdateType;
103 SetupSequence setupSequence;
104 DispatchSequence dispatchSequence;
105
106 protected:
hasSetupOpvkt::pipeline::__anonca0205ca0111::TestParams107 bool hasSetupOp (SetupOp op) const
108 {
109 for (int i = 0; i < decltype(setupSequence)::SIZE; ++i)
110 {
111 if (setupSequence[i] == op)
112 return true;
113 }
114 return false;
115 }
116
hasAnyOfvkt::pipeline::__anonca0205ca0111::TestParams117 bool hasAnyOf (const std::vector<SetupOp>& opVec) const
118 {
119 for (const auto& op : opVec)
120 {
121 if (hasSetupOp(op))
122 return true;
123 }
124 return false;
125 }
126
127 public:
hasGraphicsvkt::pipeline::__anonca0205ca0111::TestParams128 bool hasGraphics (void) const
129 {
130 const std::vector<SetupOp> setupOps {SetupOp::BIND_GRAPHICS_PIPELINE, SetupOp::BIND_GRAPHICS_SET};
131 return hasAnyOf(setupOps);
132 }
133
hasComputevkt::pipeline::__anonca0205ca0111::TestParams134 bool hasCompute (void) const
135 {
136 const std::vector<SetupOp> setupOps {SetupOp::BIND_COMPUTE_PIPELINE, SetupOp::BIND_COMPUTE_SET};
137 return hasAnyOf(setupOps);
138 }
139
hasRayTracingvkt::pipeline::__anonca0205ca0111::TestParams140 bool hasRayTracing (void) const
141 {
142 const std::vector<SetupOp> setupOps {SetupOp::BIND_RAYTRACING_PIPELINE, SetupOp::BIND_RAYTRACING_SET};
143 return hasAnyOf(setupOps);
144 }
145
146 };
147
148 // Expected output values in each buffer.
149 constexpr deUint32 kExpectedBufferValueGraphics = 1u;
150 constexpr deUint32 kExpectedBufferValueCompute = 2u;
151 constexpr deUint32 kExpectedBufferValueRayTracing = 3u;
152
153 class BindPointTest : public vkt::TestCase
154 {
155 public:
156 BindPointTest (tcu::TestContext& testCtx, const std::string& name, const TestParams& params);
~BindPointTest(void)157 virtual ~BindPointTest (void) {}
158
159 virtual void checkSupport (Context& context) const;
160 virtual void initPrograms (vk::SourceCollections& programCollection) const;
161 virtual TestInstance* createInstance (Context& context) const;
162
163 protected:
164 TestParams m_params;
165 };
166
167 class BindPointInstance : public vkt::TestInstance
168 {
169 public:
170 BindPointInstance (Context& context, const TestParams& params);
~BindPointInstance(void)171 virtual ~BindPointInstance (void) {}
172
173 virtual tcu::TestStatus iterate (void);
174
175 protected:
176 TestParams m_params;
177 };
178
BindPointTest(tcu::TestContext & testCtx,const std::string & name,const TestParams & params)179 BindPointTest::BindPointTest (tcu::TestContext& testCtx, const std::string& name, const TestParams& params)
180 : vkt::TestCase (testCtx, name)
181 , m_params (params)
182 {}
183
checkSupport(Context & context) const184 void BindPointTest::checkSupport (Context& context) const
185 {
186 if ((m_params.hasGraphics() && m_params.graphicsSetUpdateType != SetUpdateType::WRITE) ||
187 (m_params.hasCompute() && m_params.computeSetUpdateType != SetUpdateType::WRITE) ||
188 (m_params.hasRayTracing() && m_params.rayTracingSetUpdateType != SetUpdateType::WRITE))
189 {
190 context.requireDeviceFunctionality("VK_KHR_push_descriptor");
191
192 if ((m_params.hasGraphics() && m_params.graphicsSetUpdateType == SetUpdateType::PUSH_WITH_TEMPLATE) ||
193 (m_params.hasCompute() && m_params.computeSetUpdateType == SetUpdateType::PUSH_WITH_TEMPLATE) ||
194 (m_params.hasRayTracing() && m_params.rayTracingSetUpdateType == SetUpdateType::PUSH_WITH_TEMPLATE))
195 {
196 context.requireDeviceFunctionality("VK_KHR_descriptor_update_template");
197 }
198 }
199
200 if (m_params.hasRayTracing())
201 context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
202
203 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
204 }
205
initPrograms(vk::SourceCollections & programCollection) const206 void BindPointTest::initPrograms (vk::SourceCollections& programCollection) const
207 {
208 // The flags array will only have 1 element.
209 const std::string descriptorDecl = "layout(set=0, binding=0, std430) buffer BufferBlock { uint flag[]; } outBuffer;\n";
210
211 if (m_params.hasGraphics())
212 {
213 std::ostringstream vert;
214 vert
215 << "#version 450\n"
216 << "\n"
217 << "void main()\n"
218 << "{\n"
219 // Full-screen clockwise triangle strip with 4 vertices.
220 << " const float x = (-1.0+2.0*((gl_VertexIndex & 2)>>1));\n"
221 << " const float y = ( 1.0-2.0* (gl_VertexIndex % 2));\n"
222 << " gl_Position = vec4(x, y, 0.0, 1.0);\n"
223 << "}\n"
224 ;
225
226 // Note: the color attachment will be a 1x1 image, so gl_FragCoord.xy is (0.5, 0.5).
227 std::ostringstream frag;
228 frag
229 << "#version 450\n"
230 << descriptorDecl
231 << "layout(location=0) out vec4 outColor;\n"
232 << "\n"
233 << "void main()\n"
234 << "{\n"
235 << " const uint xCoord = uint(trunc(gl_FragCoord.x));\n"
236 << " const uint yCoord = uint(trunc(gl_FragCoord.y));\n"
237 << " outBuffer.flag[xCoord + yCoord] = " << kExpectedBufferValueGraphics << "u;\n"
238 << " outColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
239 << "}\n"
240 ;
241
242 programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
243 programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
244 }
245
246 if (m_params.hasCompute())
247 {
248 // Note: we will only dispatch 1 group.
249 std::ostringstream comp;
250 comp
251 << "#version 450\n"
252 << descriptorDecl
253 << "layout(local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
254 << "\n"
255 << "void main()\n"
256 << "{\n"
257 << " const uint index = gl_GlobalInvocationID.x + gl_GlobalInvocationID.y + gl_GlobalInvocationID.z;\n"
258 << " outBuffer.flag[index] = " << kExpectedBufferValueCompute << "u;\n"
259 << "}\n"
260 ;
261
262 programCollection.glslSources.add("comp") << glu::ComputeSource(comp.str());
263 }
264
265 if (m_params.hasRayTracing())
266 {
267 // We will only call the ray gen shader once.
268 std::ostringstream rgen;
269 rgen
270 << "#version 460\n"
271 << "#extension GL_EXT_ray_tracing : require\n"
272 << descriptorDecl
273 << "\n"
274 << "void main()\n"
275 << "{\n"
276 << " const uint index = gl_LaunchIDEXT.x + gl_LaunchIDEXT.y + gl_LaunchIDEXT.z;\n"
277 << " outBuffer.flag[index] = " << kExpectedBufferValueRayTracing << "u;\n"
278 << "}\n"
279 ;
280
281 const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
282 programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(rgen.str())) << buildOptions;
283 }
284 }
285
createInstance(Context & context) const286 vkt::TestInstance* BindPointTest::createInstance (Context& context) const
287 {
288 return new BindPointInstance(context, m_params);
289 }
290
BindPointInstance(Context & context,const TestParams & params)291 BindPointInstance::BindPointInstance (Context& context, const TestParams& params)
292 : vkt::TestInstance (context)
293 , m_params (params)
294 {}
295
makeSetLayout(const DeviceInterface & vkd,VkDevice device,VkShaderStageFlags stages,bool push)296 Move<VkDescriptorSetLayout> makeSetLayout(const DeviceInterface& vkd, VkDevice device, VkShaderStageFlags stages, bool push)
297 {
298 VkDescriptorSetLayoutCreateFlags createFlags = 0u;
299 if (push)
300 createFlags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
301
302 DescriptorSetLayoutBuilder builder;
303 builder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stages);
304 return builder.build(vkd, device, createFlags);
305 }
306
zeroOutAndFlush(const DeviceInterface & vkd,VkDevice device,BufferWithMemory & buffer,VkDeviceSize bufferSize)307 void zeroOutAndFlush (const DeviceInterface& vkd, VkDevice device, BufferWithMemory& buffer, VkDeviceSize bufferSize)
308 {
309 auto& alloc = buffer.getAllocation();
310 void* hostPtr = alloc.getHostPtr();
311
312 deMemset(hostPtr, 0, static_cast<size_t>(bufferSize));
313 flushAlloc(vkd, device, alloc);
314 }
315
makePoolAndSet(const DeviceInterface & vkd,VkDevice device,VkDescriptorSetLayout layout,Move<VkDescriptorPool> & pool,Move<VkDescriptorSet> & set)316 void makePoolAndSet (const DeviceInterface& vkd, VkDevice device, VkDescriptorSetLayout layout, Move<VkDescriptorPool>& pool, Move<VkDescriptorSet>& set)
317 {
318 DescriptorPoolBuilder poolBuilder;
319 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
320 pool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
321 set = makeDescriptorSet(vkd, device, pool.get(), layout);
322 }
323
writeSetUpdate(const DeviceInterface & vkd,VkDevice device,VkBuffer buffer,VkDeviceSize offset,VkDeviceSize size,VkDescriptorSet set)324 void writeSetUpdate (const DeviceInterface& vkd, VkDevice device, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size, VkDescriptorSet set)
325 {
326 DescriptorSetUpdateBuilder updateBuilder;
327 const auto bufferInfo = makeDescriptorBufferInfo(buffer, offset, size);
328 updateBuilder.writeSingle(set, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo);
329 updateBuilder.update(vkd, device);
330 }
331
makeUpdateTemplate(const DeviceInterface & vkd,VkDevice device,VkDescriptorSetLayout setLayout,VkPipelineBindPoint bindPoint,VkPipelineLayout pipelineLayout)332 Move<VkDescriptorUpdateTemplate> makeUpdateTemplate (const DeviceInterface& vkd, VkDevice device, VkDescriptorSetLayout setLayout, VkPipelineBindPoint bindPoint, VkPipelineLayout pipelineLayout)
333 {
334 const auto templateEntry = makeDescriptorUpdateTemplateEntry(0u, 0u, 1u, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, static_cast<deUintptr>(0), static_cast<deUintptr>(sizeof(VkDescriptorBufferInfo)));
335 const VkDescriptorUpdateTemplateCreateInfo templateCreateInfo =
336 {
337 VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO, // VkStructureType sType;
338 nullptr, // const void* pNext;
339 0u, // VkDescriptorUpdateTemplateCreateFlags flags;
340 1u, // deUint32 descriptorUpdateEntryCount;
341 &templateEntry, // const VkDescriptorUpdateTemplateEntry* pDescriptorUpdateEntries;
342 VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR, // VkDescriptorUpdateTemplateType templateType;
343 setLayout, // VkDescriptorSetLayout descriptorSetLayout;
344 bindPoint, // VkPipelineBindPoint pipelineBindPoint;
345 pipelineLayout, // VkPipelineLayout pipelineLayout;
346 0u, // deUint32 set;
347 };
348 return createDescriptorUpdateTemplate(vkd, device, &templateCreateInfo);
349 }
350
pushBufferDescriptor(const DeviceInterface & vkd,VkCommandBuffer cmdBuffer,VkPipelineBindPoint bindPoint,VkPipelineLayout layout,VkBuffer buffer,VkDeviceSize offset,VkDeviceSize size)351 void pushBufferDescriptor(const DeviceInterface& vkd, VkCommandBuffer cmdBuffer, VkPipelineBindPoint bindPoint, VkPipelineLayout layout, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size)
352 {
353 const auto bufferInfo = makeDescriptorBufferInfo(buffer, offset, size);
354 const VkWriteDescriptorSet write =
355 {
356 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
357 nullptr, // const void* pNext;
358 DE_NULL, // VkDescriptorSet dstSet;
359 0u, // deUint32 dstBinding;
360 0u, // deUint32 dstArrayElement;
361 1u, // deUint32 descriptorCount;
362 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // VkDescriptorType descriptorType;
363 nullptr, // const VkDescriptorImageInfo* pImageInfo;
364 &bufferInfo, // const VkDescriptorBufferInfo* pBufferInfo;
365 nullptr, // const VkBufferView* pTexelBufferView;
366 };
367 vkd.cmdPushDescriptorSetKHR(cmdBuffer, bindPoint, layout, 0u, 1u, &write);
368 }
369
verifyBufferContents(const DeviceInterface & vkd,VkDevice device,const BufferWithMemory & buffer,const std::string & bufferName,deUint32 expected)370 void verifyBufferContents (const DeviceInterface& vkd, VkDevice device, const BufferWithMemory& buffer, const std::string& bufferName, deUint32 expected)
371 {
372 auto& bufferAlloc = buffer.getAllocation();
373 const auto dataPtr = reinterpret_cast<deUint32*>(bufferAlloc.getHostPtr());
374 deUint32 data;
375
376 invalidateAlloc(vkd, device, bufferAlloc);
377 deMemcpy(&data, dataPtr, sizeof(data));
378
379 if (data != expected)
380 {
381 std::ostringstream msg;
382 msg << "Invalid value found in " << bufferName << " buffer: expected " << expected << " and found " << data;
383 TCU_FAIL(msg.str());
384 }
385 }
386
makeBufferBarrier(VkBuffer buffer,VkDeviceSize offset,VkDeviceSize size)387 VkBufferMemoryBarrier makeBufferBarrier (VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size)
388 {
389 return makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, buffer, offset, size);
390 }
391
recordBufferBarrier(const DeviceInterface & vkd,VkCommandBuffer cmdBuffer,VkPipelineStageFlagBits stage,const VkBufferMemoryBarrier & barrier)392 void recordBufferBarrier (const DeviceInterface& vkd, VkCommandBuffer cmdBuffer, VkPipelineStageFlagBits stage, const VkBufferMemoryBarrier& barrier)
393 {
394 vkd.cmdPipelineBarrier(cmdBuffer, stage, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 1u, &barrier, 0u, nullptr);
395 }
396
iterate(void)397 tcu::TestStatus BindPointInstance::iterate (void)
398 {
399 const auto& vki = m_context.getInstanceInterface();
400 const auto physDev = m_context.getPhysicalDevice();
401 const auto& vkd = m_context.getDeviceInterface();
402 const auto device = m_context.getDevice();
403 const auto qIndex = m_context.getUniversalQueueFamilyIndex();
404 const auto queue = m_context.getUniversalQueue();
405 auto& alloc = m_context.getDefaultAllocator();
406
407 const auto imageFormat = VK_FORMAT_R8G8B8A8_UNORM;
408 const auto imageExtent = makeExtent3D(1u, 1u, 1u);
409 const auto imageType = VK_IMAGE_TYPE_2D;
410 const auto imageViewType = VK_IMAGE_VIEW_TYPE_2D;
411 const auto imageUsage = static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
412
413 const std::vector<VkViewport> viewports { makeViewport(imageExtent) };
414 const std::vector<VkRect2D> scissors { makeRect2D(imageExtent) };
415
416 const auto hasGraphics = m_params.hasGraphics();
417 const auto hasCompute = m_params.hasCompute();
418 const auto hasRayTracing = m_params.hasRayTracing();
419
420 // Storage buffers.
421 const auto bufferSize = static_cast<VkDeviceSize>(sizeof(deUint32));
422 const auto bufferCreateInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
423
424 using BufferWithMemoryPtr = de::MovePtr<BufferWithMemory>;
425 using ImageWithMemoryPtr = de::MovePtr<ImageWithMemory>;
426
427 BufferWithMemoryPtr graphicsBuffer;
428 BufferWithMemoryPtr computeBuffer;
429 BufferWithMemoryPtr rayTracingBuffer;
430
431 if (hasGraphics) graphicsBuffer = BufferWithMemoryPtr(new BufferWithMemory(vkd, device, alloc, bufferCreateInfo, MemoryRequirement::HostVisible));
432 if (hasCompute) computeBuffer = BufferWithMemoryPtr(new BufferWithMemory(vkd, device, alloc, bufferCreateInfo, MemoryRequirement::HostVisible));
433 if (hasRayTracing) rayTracingBuffer = BufferWithMemoryPtr(new BufferWithMemory(vkd, device, alloc, bufferCreateInfo, MemoryRequirement::HostVisible));
434
435 if (hasGraphics) zeroOutAndFlush(vkd, device, *graphicsBuffer, bufferSize);
436 if (hasCompute) zeroOutAndFlush(vkd, device, *computeBuffer, bufferSize);
437 if (hasRayTracing) zeroOutAndFlush(vkd, device, *rayTracingBuffer, bufferSize);
438
439 ImageWithMemoryPtr colorAttachment;
440 Move<VkImageView> colorAttachmentView;
441
442 if (hasGraphics)
443 {
444 // Color attachment.
445 const VkImageCreateInfo imageCreateInfo =
446 {
447 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
448 nullptr, // const void* pNext;
449 0u, // VkImageCreateFlags flags;
450 imageType, // VkImageType imageType;
451 imageFormat, // VkFormat format;
452 imageExtent, // VkExtent3D extent;
453 1u, // deUint32 mipLevels;
454 1u, // deUint32 arrayLayers;
455 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
456 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
457 imageUsage, // VkImageUsageFlags usage;
458 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
459 1u, // deUint32 queueFamilyIndexCount;
460 &qIndex, // const deUint32* pQueueFamilyIndices;
461 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
462 };
463
464 const auto subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
465 colorAttachment = ImageWithMemoryPtr(new ImageWithMemory(vkd, device, alloc, imageCreateInfo, MemoryRequirement::Any));
466 colorAttachmentView = makeImageView(vkd, device, colorAttachment->get(), imageViewType, imageFormat, subresourceRange);
467 }
468
469 // Command buffer and pool.
470 const auto cmdPool = makeCommandPool(vkd, device, qIndex);
471 const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
472 const auto cmdBuffer = cmdBufferPtr.get();
473
474 // Set and pipeline layouts.
475 Move<VkDescriptorSetLayout> graphicsSetLayout;
476 Move<VkDescriptorSetLayout> computeSetLayout;
477 Move<VkDescriptorSetLayout> rayTracingSetLayout;
478
479 if (hasGraphics) graphicsSetLayout = makeSetLayout(vkd, device, VK_SHADER_STAGE_FRAGMENT_BIT, (m_params.graphicsSetUpdateType != SetUpdateType::WRITE));
480 if (hasCompute) computeSetLayout = makeSetLayout(vkd, device, VK_SHADER_STAGE_COMPUTE_BIT, (m_params.computeSetUpdateType != SetUpdateType::WRITE));
481 if (hasRayTracing) rayTracingSetLayout = makeSetLayout(vkd, device, VK_SHADER_STAGE_RAYGEN_BIT_KHR, (m_params.rayTracingSetUpdateType != SetUpdateType::WRITE));
482
483 PipelineLayoutWrapper graphicsPipelineLayout;
484 PipelineLayoutWrapper computePipelineLayout;
485 PipelineLayoutWrapper rayTracingPipelineLayout;
486
487 if (hasGraphics) graphicsPipelineLayout = PipelineLayoutWrapper(m_params.pipelineConstructionType, vkd, device, graphicsSetLayout.get());
488 if (hasCompute) computePipelineLayout = PipelineLayoutWrapper(m_params.pipelineConstructionType, vkd, device, computeSetLayout.get());
489 if (hasRayTracing) rayTracingPipelineLayout = PipelineLayoutWrapper(m_params.pipelineConstructionType, vkd, device, rayTracingSetLayout.get());
490
491 // Shader modules.
492 ShaderWrapper vertShader;
493 ShaderWrapper fragShader;
494 ShaderWrapper compShader;
495 ShaderWrapper rgenShader;
496
497 if (hasGraphics) vertShader = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
498 if (hasGraphics) fragShader = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
499 if (hasCompute) compShader = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("comp"), 0u);
500 if (hasRayTracing) rgenShader = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("rgen"), 0u);
501
502 RenderPassWrapper renderPass;
503 GraphicsPipelineWrapper graphicsPipeline(vki, vkd, physDev, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType);
504
505 if (hasGraphics)
506 {
507 // Render pass and framebuffer.
508 renderPass = RenderPassWrapper(m_params.pipelineConstructionType, vkd, device, imageFormat);
509 renderPass.createFramebuffer(vkd, device, **colorAttachment, colorAttachmentView.get(), imageExtent.width, imageExtent.height);
510
511 // Graphics pipeline.
512 const VkPipelineVertexInputStateCreateInfo vertexInputState =
513 {
514 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
515 nullptr, // const void* pNext
516 0u, // VkPipelineVertexInputStateCreateFlags flags
517 0u, // deUint32 vertexBindingDescriptionCount
518 nullptr, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
519 0u, // deUint32 vertexAttributeDescriptionCount
520 nullptr, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
521 };
522
523 graphicsPipeline.setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
524 .setDefaultRasterizationState()
525 .setDefaultMultisampleState()
526 .setDefaultDepthStencilState()
527 .setDefaultColorBlendState()
528 .setupVertexInputState(&vertexInputState)
529 .setupPreRasterizationShaderState(
530 viewports,
531 scissors,
532 graphicsPipelineLayout,
533 *renderPass,
534 0u,
535 vertShader)
536 .setupFragmentShaderState(graphicsPipelineLayout, *renderPass, 0u, fragShader)
537 .setupFragmentOutputState(*renderPass, 0u)
538 .setMonolithicPipelineLayout(graphicsPipelineLayout)
539 .buildPipeline();
540 }
541
542 // Compute pipeline.
543 Move<VkPipeline> computePipeline;
544
545 if (hasCompute)
546 {
547 const VkPipelineShaderStageCreateInfo computeShaderStageInfo =
548 {
549 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
550 nullptr, // const void* pNext;
551 0u, // VkPipelineShaderStageCreateFlags flags;
552 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
553 compShader.getModule(), // VkShaderModule module;
554 "main", // const char* pName;
555 nullptr, // const VkSpecializationInfo* pSpecializationInfo;
556 };
557
558 const VkComputePipelineCreateInfo computePipelineCreateInfo =
559 {
560 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
561 nullptr, // const void* pNext;
562 0u, // VkPipelineCreateFlags flags;
563 computeShaderStageInfo, // VkPipelineShaderStageCreateInfo stage;
564 computePipelineLayout.get(), // VkPipelineLayout layout;
565 DE_NULL, // VkPipeline basePipelineHandle;
566 0u, // deInt32 basePipelineIndex;
567 };
568
569 computePipeline = createComputePipeline(vkd, device, DE_NULL, &computePipelineCreateInfo);
570 }
571
572 // Ray tracing pipeline and shader binding tables.
573 using RayTracingPipelineHelperPtr = de::MovePtr<RayTracingPipeline>;
574
575 RayTracingPipelineHelperPtr rayTracingPipelineHelper;
576 Move<VkPipeline> rayTracingPipeline;
577 BufferWithMemoryPtr raygenSBT;
578
579 VkStridedDeviceAddressRegionKHR raygenSBTRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
580 VkStridedDeviceAddressRegionKHR missSBTRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
581 VkStridedDeviceAddressRegionKHR hitSBTRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
582 VkStridedDeviceAddressRegionKHR callableSBTRegion = makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
583
584 if (hasRayTracing)
585 {
586 const auto rtProperties = makeRayTracingProperties(vki, physDev);
587 const auto shaderGroupHandleSize = rtProperties->getShaderGroupHandleSize();
588 const auto shaderGroupBaseAlignment = rtProperties->getShaderGroupBaseAlignment();
589 rayTracingPipelineHelper = RayTracingPipelineHelperPtr(new RayTracingPipeline());
590
591 rayTracingPipelineHelper->addShader(VK_SHADER_STAGE_RAYGEN_BIT_KHR, rgenShader.getModule(), 0);
592 rayTracingPipeline = rayTracingPipelineHelper->createPipeline(vkd, device, rayTracingPipelineLayout.get());
593
594 raygenSBT = rayTracingPipelineHelper->createShaderBindingTable(vkd, device, rayTracingPipeline.get(), alloc, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
595 raygenSBTRegion = makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenSBT->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize);
596 }
597
598 // Descriptor pools and sets if needed.
599 Move<VkDescriptorPool> graphicsDescriptorPool;
600 Move<VkDescriptorPool> computeDescriptorPool;
601 Move<VkDescriptorPool> rayTracingDescriptorPool;
602 Move<VkDescriptorSet> graphicsDescritorSet;
603 Move<VkDescriptorSet> computeDescriptorSet;
604 Move<VkDescriptorSet> rayTracingDescriptorSet;
605
606 if (m_params.graphicsSetUpdateType == SetUpdateType::WRITE)
607 {
608 makePoolAndSet(vkd, device, graphicsSetLayout.get(), graphicsDescriptorPool, graphicsDescritorSet);
609 writeSetUpdate(vkd, device, graphicsBuffer->get(), 0ull, bufferSize, graphicsDescritorSet.get());
610 }
611
612 if (m_params.computeSetUpdateType == SetUpdateType::WRITE)
613 {
614 makePoolAndSet(vkd, device, computeSetLayout.get(), computeDescriptorPool, computeDescriptorSet);
615 writeSetUpdate(vkd, device, computeBuffer->get(), 0ull, bufferSize, computeDescriptorSet.get());
616 }
617
618 if (m_params.rayTracingSetUpdateType == SetUpdateType::WRITE)
619 {
620 makePoolAndSet(vkd, device, rayTracingSetLayout.get(), rayTracingDescriptorPool, rayTracingDescriptorSet);
621 writeSetUpdate(vkd, device, rayTracingBuffer->get(), 0ull, bufferSize, rayTracingDescriptorSet.get());
622 }
623
624 // Templates if needed.
625 Move<VkDescriptorUpdateTemplate> graphicsUpdateTemplate;
626 Move<VkDescriptorUpdateTemplate> computeUpdateTemplate;
627 Move<VkDescriptorUpdateTemplate> rayTracingUpdateTemplate;
628
629 if (m_params.graphicsSetUpdateType == SetUpdateType::PUSH_WITH_TEMPLATE)
630 graphicsUpdateTemplate = makeUpdateTemplate(vkd, device, graphicsSetLayout.get(), VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineLayout.get());
631
632 if (m_params.computeSetUpdateType == SetUpdateType::PUSH_WITH_TEMPLATE)
633 computeUpdateTemplate = makeUpdateTemplate(vkd, device, computeSetLayout.get(), VK_PIPELINE_BIND_POINT_COMPUTE, computePipelineLayout.get());
634
635 if (m_params.rayTracingSetUpdateType == SetUpdateType::PUSH_WITH_TEMPLATE)
636 rayTracingUpdateTemplate = makeUpdateTemplate(vkd, device, rayTracingSetLayout.get(), VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, rayTracingPipelineLayout.get());
637
638 beginCommandBuffer(vkd, cmdBuffer);
639
640 // Helper flags to check the test has been specified properly.
641 bool boundGraphicsPipeline = false;
642 bool boundGraphicsSet = false;
643 bool boundComputePipeline = false;
644 bool boundComputeSet = false;
645 bool boundRayTracingPipeline = false;
646 bool boundRayTracingSet = false;
647
648 // Setup operations in desired order.
649 for (int i = 0; i < decltype(m_params.setupSequence)::SIZE; ++i)
650 {
651 const auto& setupOp = m_params.setupSequence[i];
652 switch (setupOp)
653 {
654 case SetupOp::BIND_GRAPHICS_PIPELINE:
655 graphicsPipeline.bind(cmdBuffer);
656 boundGraphicsPipeline = true;
657 break;
658
659 case SetupOp::BIND_COMPUTE_PIPELINE:
660 vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline.get());
661 boundComputePipeline = true;
662 break;
663
664 case SetupOp::BIND_RAYTRACING_PIPELINE:
665 vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, rayTracingPipeline.get());
666 boundRayTracingPipeline = true;
667 break;
668
669 case SetupOp::BIND_GRAPHICS_SET:
670 if (m_params.graphicsSetUpdateType == SetUpdateType::WRITE)
671 vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineLayout.get(), 0u, 1u, &graphicsDescritorSet.get(), 0u, nullptr);
672 else if (m_params.graphicsSetUpdateType == SetUpdateType::PUSH)
673 pushBufferDescriptor(vkd, cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineLayout.get(), graphicsBuffer->get(), 0ull, bufferSize);
674 else if (m_params.graphicsSetUpdateType == SetUpdateType::PUSH_WITH_TEMPLATE)
675 {
676 const auto bufferInfo = makeDescriptorBufferInfo(graphicsBuffer->get(), 0ull, bufferSize);
677 vkd.cmdPushDescriptorSetWithTemplateKHR(cmdBuffer, graphicsUpdateTemplate.get(), graphicsPipelineLayout.get(), 0u, &bufferInfo);
678 }
679 else
680 DE_ASSERT(false);
681 boundGraphicsSet = true;
682 break;
683
684 case SetupOp::BIND_COMPUTE_SET:
685 if (m_params.computeSetUpdateType == SetUpdateType::WRITE)
686 vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipelineLayout.get(), 0u, 1u, &computeDescriptorSet.get(), 0u, nullptr);
687 else if (m_params.computeSetUpdateType == SetUpdateType::PUSH)
688 pushBufferDescriptor(vkd, cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipelineLayout.get(), computeBuffer->get(), 0ull, bufferSize);
689 else if (m_params.computeSetUpdateType == SetUpdateType::PUSH_WITH_TEMPLATE)
690 {
691 const auto bufferInfo = makeDescriptorBufferInfo(computeBuffer->get(), 0ull, bufferSize);
692 vkd.cmdPushDescriptorSetWithTemplateKHR(cmdBuffer, computeUpdateTemplate.get(), computePipelineLayout.get(), 0u, &bufferInfo);
693 }
694 else
695 DE_ASSERT(false);
696 boundComputeSet = true;
697 break;
698
699 case SetupOp::BIND_RAYTRACING_SET:
700 if (m_params.rayTracingSetUpdateType == SetUpdateType::WRITE)
701 vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, rayTracingPipelineLayout.get(), 0u, 1u, &rayTracingDescriptorSet.get(), 0u, nullptr);
702 else if (m_params.rayTracingSetUpdateType == SetUpdateType::PUSH)
703 pushBufferDescriptor(vkd, cmdBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, rayTracingPipelineLayout.get(), rayTracingBuffer->get(), 0ull, bufferSize);
704 else if (m_params.rayTracingSetUpdateType == SetUpdateType::PUSH_WITH_TEMPLATE)
705 {
706 const auto bufferInfo = makeDescriptorBufferInfo(rayTracingBuffer->get(), 0ull, bufferSize);
707 vkd.cmdPushDescriptorSetWithTemplateKHR(cmdBuffer, rayTracingUpdateTemplate.get(), rayTracingPipelineLayout.get(), 0u, &bufferInfo);
708 }
709 else
710 DE_ASSERT(false);
711 boundRayTracingSet = true;
712 break;
713
714 default:
715 DE_ASSERT(false);
716 break;
717 }
718 }
719
720 // Avoid warning in release builds.
721 DE_UNREF(boundGraphicsPipeline);
722 DE_UNREF(boundGraphicsSet);
723 DE_UNREF(boundComputePipeline);
724 DE_UNREF(boundComputeSet);
725 DE_UNREF(boundRayTracingPipeline);
726 DE_UNREF(boundRayTracingSet);
727
728 // Dispatch operations in desired order.
729 for (int i = 0; i < decltype(m_params.dispatchSequence)::SIZE; ++i)
730 {
731 const auto& dispatchOp = m_params.dispatchSequence[i];
732 switch (dispatchOp)
733 {
734 case DispatchOp::DRAW:
735 DE_ASSERT(boundGraphicsPipeline && boundGraphicsSet);
736 renderPass.begin(vkd, cmdBuffer, scissors[0], tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
737 vkd.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
738 renderPass.end(vkd, cmdBuffer);
739 break;
740
741 case DispatchOp::COMPUTE:
742 DE_ASSERT(boundComputePipeline && boundComputeSet);
743 vkd.cmdDispatch(cmdBuffer, 1u, 1u, 1u);
744 break;
745
746 case DispatchOp::TRACE_RAYS:
747 DE_ASSERT(boundRayTracingPipeline && boundRayTracingSet);
748 cmdTraceRays(vkd, cmdBuffer, &raygenSBTRegion, &missSBTRegion, &hitSBTRegion, &callableSBTRegion, 1u, 1u, 1u);
749 break;
750
751 default:
752 DE_ASSERT(false);
753 break;
754 }
755 }
756
757 if (hasGraphics)
758 {
759 const auto graphicsBufferBarrier = makeBufferBarrier(graphicsBuffer->get(), 0ull, bufferSize);
760 recordBufferBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, graphicsBufferBarrier);
761 }
762 if (hasCompute)
763 {
764 const auto computeBufferBarrier = makeBufferBarrier(computeBuffer->get(), 0ull, bufferSize);
765 recordBufferBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, computeBufferBarrier);
766 }
767 if (hasRayTracing)
768 {
769 const auto rayTracingBufferBarrier = makeBufferBarrier(rayTracingBuffer->get(), 0ull, bufferSize);
770 recordBufferBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, rayTracingBufferBarrier);
771 }
772
773 endCommandBuffer(vkd, cmdBuffer);
774 submitCommandsAndWait(vkd, device, queue, cmdBuffer);
775
776 // Verify storage buffers.
777 if (hasGraphics) verifyBufferContents(vkd, device, *graphicsBuffer, "graphics", kExpectedBufferValueGraphics);
778 if (hasCompute) verifyBufferContents(vkd, device, *computeBuffer, "compute", kExpectedBufferValueCompute);
779 if (hasRayTracing) verifyBufferContents(vkd, device, *rayTracingBuffer, "raytracing", kExpectedBufferValueRayTracing);
780
781 // Verify color attachment.
782 if (hasGraphics)
783 {
784 const auto textureLevel = readColorAttachment(vkd, device, queue, qIndex, alloc, colorAttachment->get(), imageFormat, tcu::UVec2(imageExtent.width, imageExtent.height));
785 const auto pixelBuffer = textureLevel->getAccess();
786 const auto iWidth = static_cast<int>(imageExtent.width);
787 const auto iHeight = static_cast<int>(imageExtent.height);
788 const tcu::Vec4 expectedColor (0.0f, 1.0f, 0.0f, 1.0f);
789
790 for (int y = 0; y < iHeight; ++y)
791 for (int x = 0; x < iWidth; ++x)
792 {
793 const auto value = pixelBuffer.getPixel(x, y);
794 if (value != expectedColor)
795 {
796 std::ostringstream msg;
797 msg << "Unexpected color found in attachment: expected " << expectedColor << " but found " << value;
798 TCU_FAIL(msg.str());
799 }
800 }
801 }
802
803 return tcu::TestStatus::pass("Pass");
804 }
805
806 // Auxiliar string conversion functions.
807
toString(SetUpdateType updateType)808 std::string toString(SetUpdateType updateType)
809 {
810 switch (updateType)
811 {
812 case SetUpdateType::WRITE: return "write";
813 case SetUpdateType::PUSH: return "push";
814 case SetUpdateType::PUSH_WITH_TEMPLATE: return "template_push";
815 default: DE_ASSERT(false); break;
816 }
817
818 return "";
819 }
820
toString(const SetupSequence & setupSequence)821 std::string toString(const SetupSequence& setupSequence)
822 {
823 std::ostringstream out;
824
825 out << "setup";
826 for (int i = 0; i < std::remove_reference<decltype(setupSequence)>::type::SIZE; ++i)
827 {
828 out << "_";
829 switch (setupSequence[i])
830 {
831 case SetupOp::BIND_GRAPHICS_PIPELINE: out << "gp"; break;
832 case SetupOp::BIND_COMPUTE_PIPELINE: out << "cp"; break;
833 case SetupOp::BIND_RAYTRACING_PIPELINE: out << "rp"; break;
834 case SetupOp::BIND_GRAPHICS_SET: out << "gs"; break;
835 case SetupOp::BIND_COMPUTE_SET: out << "cs"; break;
836 case SetupOp::BIND_RAYTRACING_SET: out << "rs"; break;
837 default: DE_ASSERT(false); break;
838 }
839 }
840
841 return out.str();
842 }
843
toString(const DispatchSequence & dispatchSequence)844 std::string toString(const DispatchSequence& dispatchSequence)
845 {
846 std::ostringstream out;
847
848 out << "cmd";
849 for (int i = 0; i < std::remove_reference<decltype(dispatchSequence)>::type::SIZE; ++i)
850 {
851 out << "_";
852 switch (dispatchSequence[i])
853 {
854 case DispatchOp::COMPUTE: out << "dispatch"; break;
855 case DispatchOp::DRAW: out << "draw"; break;
856 case DispatchOp::TRACE_RAYS: out << "tracerays"; break;
857 default: DE_ASSERT(false); break;
858 }
859 }
860
861 return out.str();
862 }
863
toString(VkPipelineBindPoint point)864 std::string toString(VkPipelineBindPoint point)
865 {
866 if (point == VK_PIPELINE_BIND_POINT_GRAPHICS) return "graphics";
867 if (point == VK_PIPELINE_BIND_POINT_COMPUTE) return "compute";
868 if (point == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR) return "raytracing";
869
870 DE_ASSERT(false);
871 return "";
872 }
873
874 } // anonymous
875
createBindPointTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)876 tcu::TestCaseGroup* createBindPointTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
877 {
878 using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
879 using BindPointPair = tcu::Vector<VkPipelineBindPoint, kTestBindPoints>;
880
881 GroupPtr bindPointGroup(new tcu::TestCaseGroup(testCtx, "bind_point"));
882
883 // Bind point combinations to test.
884 const BindPointPair testPairs[] =
885 {
886 BindPointPair(VK_PIPELINE_BIND_POINT_GRAPHICS, VK_PIPELINE_BIND_POINT_COMPUTE),
887 BindPointPair(VK_PIPELINE_BIND_POINT_GRAPHICS, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR),
888 BindPointPair(VK_PIPELINE_BIND_POINT_COMPUTE, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR),
889 };
890
891 for (int testPairIdx = 0; testPairIdx < DE_LENGTH_OF_ARRAY(testPairs); ++testPairIdx)
892 {
893 const auto& testPair = testPairs[testPairIdx];
894
895 // dont repeat tests if there is no graphics pipeline
896 if (pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
897 {
898 bool skipTests = true;
899 for (int elemIdx = 0; elemIdx < std::remove_reference<decltype(testPair)>::type::SIZE; ++elemIdx)
900 {
901 if (testPair[elemIdx] == VK_PIPELINE_BIND_POINT_GRAPHICS)
902 {
903 skipTests = false;
904 break;
905 }
906 }
907
908 if (skipTests)
909 continue;
910 }
911
912 // Default values. Two of them will be overwritten later.
913 TestParams params;
914 params.pipelineConstructionType = pipelineConstructionType;
915 params.graphicsSetUpdateType = SetUpdateType::TYPE_COUNT;
916 params.computeSetUpdateType = SetUpdateType::TYPE_COUNT;
917 params.rayTracingSetUpdateType = SetUpdateType::TYPE_COUNT;
918
919 // What to test based on the test pair.
920 // Note: updateTypePtrs will tell us which of the set update type members above we need to vary (graphics, compute, ray tracing).
921 SetUpdateType* updateTypePtrs [kTestBindPoints] = { nullptr, nullptr };
922 SetupOp pipelineBinds [kTestBindPoints] = { SetupOp::OP_COUNT, SetupOp::OP_COUNT };
923 SetupOp setBinds [kTestBindPoints] = { SetupOp::OP_COUNT, SetupOp::OP_COUNT };
924 DispatchOp dispatches [kTestBindPoints] = { DispatchOp::OP_COUNT, DispatchOp::OP_COUNT };
925
926 for (int elemIdx = 0; elemIdx < std::remove_reference<decltype(testPair)>::type::SIZE; ++elemIdx)
927 {
928 if (testPair[elemIdx] == VK_PIPELINE_BIND_POINT_GRAPHICS)
929 {
930 updateTypePtrs[elemIdx] = ¶ms.graphicsSetUpdateType; // Test different graphics set update types.
931 pipelineBinds[elemIdx] = SetupOp::BIND_GRAPHICS_PIPELINE;
932 setBinds[elemIdx] = SetupOp::BIND_GRAPHICS_SET;
933 dispatches[elemIdx] = DispatchOp::DRAW;
934 }
935 else if (testPair[elemIdx] == VK_PIPELINE_BIND_POINT_COMPUTE)
936 {
937 updateTypePtrs[elemIdx] = ¶ms.computeSetUpdateType; // Test different compute set update types.
938 pipelineBinds[elemIdx] = SetupOp::BIND_COMPUTE_PIPELINE;
939 setBinds[elemIdx] = SetupOp::BIND_COMPUTE_SET;
940 dispatches[elemIdx] = DispatchOp::COMPUTE;
941 }
942 else if (testPair[elemIdx] == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR)
943 {
944 updateTypePtrs[elemIdx] = ¶ms.rayTracingSetUpdateType; // Test different ray tracing set update types.
945 pipelineBinds[elemIdx] = SetupOp::BIND_RAYTRACING_PIPELINE;
946 setBinds[elemIdx] = SetupOp::BIND_RAYTRACING_SET;
947 dispatches[elemIdx] = DispatchOp::TRACE_RAYS;
948 }
949 }
950
951 const std::string pairName = toString(testPair[0]) + "_" + toString(testPair[1]);
952 GroupPtr pairGroup (new tcu::TestCaseGroup(testCtx, pairName.c_str()));
953
954 // Combine two update types.
955 for (int firstUpdateTypeIdx = 0; firstUpdateTypeIdx < static_cast<int>(SetUpdateType::TYPE_COUNT); ++firstUpdateTypeIdx)
956 for (int secondUpdateTypeIdx = 0; secondUpdateTypeIdx < static_cast<int>(SetUpdateType::TYPE_COUNT); ++ secondUpdateTypeIdx)
957 {
958 const auto firstUpdateType = static_cast<SetUpdateType>(firstUpdateTypeIdx);
959 const auto secondUpdateType = static_cast<SetUpdateType>(secondUpdateTypeIdx);
960 const std::string updateGroupName = toString(firstUpdateType) + "_" + toString(secondUpdateType);
961 GroupPtr updateGroup (new tcu::TestCaseGroup(testCtx, updateGroupName.c_str()));
962
963 // Change update types of the relevant sets.
964 *updateTypePtrs[0] = firstUpdateType;
965 *updateTypePtrs[1] = secondUpdateType;
966
967 // Prepare initial permutation of test parameters.
968 params.setupSequence[0] = pipelineBinds[0];
969 params.setupSequence[1] = pipelineBinds[1];
970 params.setupSequence[2] = setBinds[0];
971 params.setupSequence[3] = setBinds[1];
972
973 // Permutate setup sequence and dispatch sequence.
974 const auto ssBegin = params.setupSequence.m_data;
975 const auto ssEnd = ssBegin + decltype(params.setupSequence)::SIZE;
976 do
977 {
978 const auto setupGroupName = toString(params.setupSequence);
979 GroupPtr setupGroup (new tcu::TestCaseGroup(testCtx, setupGroupName.c_str()));
980
981 // Reset dispatch sequence permutation.
982 params.dispatchSequence = dispatches;
983
984 const auto dsBegin = params.dispatchSequence.m_data;
985 const auto dsEnd = dsBegin + decltype(params.dispatchSequence)::SIZE;
986 do
987 {
988 const auto testName = toString(params.dispatchSequence);
989 setupGroup->addChild(new BindPointTest(testCtx, testName, params));
990 } while (std::next_permutation(dsBegin, dsEnd));
991
992 updateGroup->addChild(setupGroup.release());
993
994 } while (std::next_permutation(ssBegin, ssEnd));
995
996 pairGroup->addChild(updateGroup.release());
997 }
998
999 bindPointGroup->addChild(pairGroup.release());
1000 }
1001
1002
1003 return bindPointGroup.release();
1004 }
1005
1006 } // pipeline
1007 } // vkt
1008