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