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