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