1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2018 The Khronos Group Inc.
6 * Copyright (c) 2018 Danylo Piliaiev <[email protected]>
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 Test for conditional rendering of vkCmdDispatch* functions
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktConditionalDispatchTests.hpp"
26 #include "vktConditionalRenderingTestUtil.hpp"
27
28 #include "tcuTestLog.hpp"
29 #include "tcuResource.hpp"
30
31 #include "vkDefs.hpp"
32 #include "vkCmdUtil.hpp"
33 #include "vkBuilderUtil.hpp"
34 #include "vkObjUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkBufferWithMemory.hpp"
37
38 namespace vkt
39 {
40 namespace conditional
41 {
42 namespace
43 {
44
45 enum DispatchCommandType
46 {
47 DISPATCH_COMMAND_TYPE_DISPATCH = 0,
48 DISPATCH_COMMAND_TYPE_DISPATCH_INDIRECT,
49 DISPATCH_COMMAND_TYPE_DISPATCH_BASE,
50 DISPATCH_COMMAND_TYPE_DISPATCH_LAST
51 };
52
getDispatchCommandTypeName(DispatchCommandType command)53 const char *getDispatchCommandTypeName(DispatchCommandType command)
54 {
55 switch (command)
56 {
57 case DISPATCH_COMMAND_TYPE_DISPATCH:
58 return "dispatch";
59 case DISPATCH_COMMAND_TYPE_DISPATCH_INDIRECT:
60 return "dispatch_indirect";
61 case DISPATCH_COMMAND_TYPE_DISPATCH_BASE:
62 return "dispatch_base";
63 default:
64 DE_ASSERT(false);
65 }
66 return "";
67 }
68
69 struct ConditionalTestSpec
70 {
71 DispatchCommandType command;
72 int numCalls;
73 ConditionalData conditionalData;
74 };
75
76 class ConditionalDispatchTest : public vkt::TestCase
77 {
78 public:
79 ConditionalDispatchTest(tcu::TestContext &testCtx, const std::string &name, const ConditionalTestSpec &testSpec);
80
81 void initPrograms(vk::SourceCollections &sourceCollections) const;
82 void checkSupport(Context &context) const;
83 TestInstance *createInstance(Context &context) const;
84
85 private:
86 const ConditionalTestSpec m_testSpec;
87 };
88
89 class ConditionalDispatchTestInstance : public TestInstance
90 {
91 public:
92 ConditionalDispatchTestInstance(Context &context, ConditionalTestSpec testSpec);
93
94 virtual tcu::TestStatus iterate(void);
95 void recordDispatch(const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer,
96 vk::BufferWithMemory &indirectBuffer);
97
98 protected:
99 const DispatchCommandType m_command;
100 const int m_numCalls;
101 const ConditionalData m_conditionalData;
102 };
103
ConditionalDispatchTest(tcu::TestContext & testCtx,const std::string & name,const ConditionalTestSpec & testSpec)104 ConditionalDispatchTest::ConditionalDispatchTest(tcu::TestContext &testCtx, const std::string &name,
105 const ConditionalTestSpec &testSpec)
106 : TestCase(testCtx, name)
107 , m_testSpec(testSpec)
108 {
109 }
110
initPrograms(vk::SourceCollections & sourceCollections) const111 void ConditionalDispatchTest::initPrograms(vk::SourceCollections &sourceCollections) const
112 {
113 std::ostringstream src;
114 src << "#version 310 es\n"
115 << "layout(local_size_x = 1u, local_size_y = 1u, local_size_z = 1u) in;\n"
116 << "layout(set = 0, binding = 0, std140) buffer Out\n"
117 << "{\n"
118 << " coherent uint count;\n"
119 << "};\n"
120 << "void main(void)\n"
121 << "{\n"
122 << " atomicAdd(count, 1u);\n"
123 << "}\n";
124
125 sourceCollections.glslSources.add("comp") << glu::ComputeSource(src.str());
126 }
127
checkSupport(Context & context) const128 void ConditionalDispatchTest::checkSupport(Context &context) const
129 {
130 checkConditionalRenderingCapabilities(context, m_testSpec.conditionalData);
131
132 if (m_testSpec.command == DISPATCH_COMMAND_TYPE_DISPATCH_BASE)
133 context.requireDeviceFunctionality("VK_KHR_device_group");
134 }
135
createInstance(Context & context) const136 TestInstance *ConditionalDispatchTest::createInstance(Context &context) const
137 {
138 return new ConditionalDispatchTestInstance(context, m_testSpec);
139 }
140
ConditionalDispatchTestInstance(Context & context,ConditionalTestSpec testSpec)141 ConditionalDispatchTestInstance::ConditionalDispatchTestInstance(Context &context, ConditionalTestSpec testSpec)
142 : TestInstance(context)
143 , m_command(testSpec.command)
144 , m_numCalls(testSpec.numCalls)
145 , m_conditionalData(testSpec.conditionalData)
146 {
147 }
148
recordDispatch(const vk::DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,vk::BufferWithMemory & indirectBuffer)149 void ConditionalDispatchTestInstance::recordDispatch(const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer,
150 vk::BufferWithMemory &indirectBuffer)
151 {
152 for (int i = 0; i < m_numCalls; i++)
153 {
154 switch (m_command)
155 {
156 case DISPATCH_COMMAND_TYPE_DISPATCH:
157 {
158 vk.cmdDispatch(cmdBuffer, 1, 1, 1);
159 break;
160 }
161 case DISPATCH_COMMAND_TYPE_DISPATCH_INDIRECT:
162 {
163 vk.cmdDispatchIndirect(cmdBuffer, *indirectBuffer, 0);
164 break;
165 }
166 case DISPATCH_COMMAND_TYPE_DISPATCH_BASE:
167 {
168 vk.cmdDispatchBase(cmdBuffer, 0, 0, 0, 1, 1, 1);
169 break;
170 }
171 default:
172 DE_ASSERT(false);
173 }
174 }
175 }
176
iterate(void)177 tcu::TestStatus ConditionalDispatchTestInstance::iterate(void)
178 {
179 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
180 const vk::VkDevice device = m_context.getDevice();
181 const vk::VkQueue queue = m_context.getUniversalQueue();
182 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
183 vk::Allocator &allocator = m_context.getDefaultAllocator();
184
185 // Create a buffer and host-visible memory for it
186
187 const vk::VkDeviceSize bufferSizeBytes = sizeof(uint32_t);
188 const vk::BufferWithMemory outputBuffer(
189 vk, device, allocator, vk::makeBufferCreateInfo(bufferSizeBytes, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
190 vk::MemoryRequirement::HostVisible);
191
192 {
193 const vk::Allocation &alloc = outputBuffer.getAllocation();
194 uint8_t *outputBufferPtr = reinterpret_cast<uint8_t *>(alloc.getHostPtr());
195 *(uint32_t *)(outputBufferPtr) = 0;
196 vk::flushAlloc(vk, device, alloc);
197 }
198
199 // Create descriptor set
200
201 const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(
202 vk::DescriptorSetLayoutBuilder()
203 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
204 .build(vk, device));
205
206 const vk::Unique<vk::VkDescriptorPool> descriptorPool(
207 vk::DescriptorPoolBuilder()
208 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
209 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
210
211 const vk::Unique<vk::VkDescriptorSet> descriptorSet(
212 makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
213
214 const vk::VkDescriptorBufferInfo descriptorInfo =
215 vk::makeDescriptorBufferInfo(*outputBuffer, 0ull, bufferSizeBytes);
216 vk::DescriptorSetUpdateBuilder()
217 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
218 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
219 .update(vk, device);
220
221 // Setup pipeline
222
223 const vk::Unique<vk::VkShaderModule> shaderModule(
224 createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0u));
225 const vk::Unique<vk::VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
226 const vk::Unique<vk::VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
227
228 const vk::Unique<vk::VkCommandPool> cmdPool(makeCommandPool(vk, device, queueFamilyIndex));
229 const vk::Unique<vk::VkCommandBuffer> cmdBuffer(
230 vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
231 const vk::Unique<vk::VkCommandBuffer> secondaryCmdBuffer(
232 vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
233 const vk::Unique<vk::VkCommandBuffer> nestedCmdBuffer(
234 vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
235
236 // Create indirect buffer
237 const vk::VkDispatchIndirectCommand dispatchCommands[] = {{1u, 1u, 1u}};
238
239 vk::BufferWithMemory indirectBuffer(
240 vk, device, allocator,
241 vk::makeBufferCreateInfo(sizeof(dispatchCommands),
242 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
243 vk::MemoryRequirement::HostVisible);
244
245 uint8_t *indirectBufferPtr = reinterpret_cast<uint8_t *>(indirectBuffer.getAllocation().getHostPtr());
246 deMemcpy(indirectBufferPtr, &dispatchCommands[0], sizeof(dispatchCommands));
247
248 vk::flushAlloc(vk, device, indirectBuffer.getAllocation());
249
250 // Start recording commands
251
252 beginCommandBuffer(vk, *cmdBuffer);
253
254 vk::VkCommandBuffer targetCmdBuffer = *cmdBuffer;
255
256 const bool useSecondaryCmdBuffer =
257 m_conditionalData.conditionInherited || m_conditionalData.conditionInSecondaryCommandBuffer;
258
259 if (useSecondaryCmdBuffer)
260 {
261 const vk::VkCommandBufferInheritanceConditionalRenderingInfoEXT conditionalRenderingInheritanceInfo = {
262 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT, DE_NULL,
263 m_conditionalData.conditionInherited ? VK_TRUE : VK_FALSE // conditionalRenderingEnable
264 };
265
266 const vk::VkCommandBufferInheritanceInfo inheritanceInfo = {
267 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
268 &conditionalRenderingInheritanceInfo,
269 0u, // renderPass
270 0u, // subpass
271 0u, // framebuffer
272 VK_FALSE, // occlusionQueryEnable
273 (vk::VkQueryControlFlags)0u, // queryFlags
274 (vk::VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
275 };
276
277 const vk::VkCommandBufferBeginInfo commandBufferBeginInfo = {
278 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, DE_NULL, vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
279 &inheritanceInfo};
280
281 if (m_conditionalData.secondaryCommandBufferNested)
282 {
283 VK_CHECK(vk.beginCommandBuffer(*nestedCmdBuffer, &commandBufferBeginInfo));
284 }
285
286 VK_CHECK(vk.beginCommandBuffer(*secondaryCmdBuffer, &commandBufferBeginInfo));
287
288 targetCmdBuffer = *secondaryCmdBuffer;
289 }
290
291 vk.cmdBindPipeline(targetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
292 vk.cmdBindDescriptorSets(targetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u,
293 &descriptorSet.get(), 0u, DE_NULL);
294
295 de::SharedPtr<Draw::Buffer> conditionalBuffer = createConditionalRenderingBuffer(m_context, m_conditionalData);
296
297 if (m_conditionalData.conditionInSecondaryCommandBuffer)
298 {
299 beginConditionalRendering(vk, *secondaryCmdBuffer, *conditionalBuffer, m_conditionalData);
300 recordDispatch(vk, *secondaryCmdBuffer, indirectBuffer);
301 vk.cmdEndConditionalRenderingEXT(*secondaryCmdBuffer);
302 vk.endCommandBuffer(*secondaryCmdBuffer);
303 if (m_conditionalData.secondaryCommandBufferNested)
304 {
305 vk.cmdExecuteCommands(*nestedCmdBuffer, 1, &secondaryCmdBuffer.get());
306 vk.endCommandBuffer(*nestedCmdBuffer);
307 }
308 }
309 else if (m_conditionalData.conditionInherited)
310 {
311 recordDispatch(vk, *secondaryCmdBuffer, indirectBuffer);
312 vk.endCommandBuffer(*secondaryCmdBuffer);
313 if (m_conditionalData.secondaryCommandBufferNested)
314 {
315 vk.cmdExecuteCommands(*nestedCmdBuffer, 1, &secondaryCmdBuffer.get());
316 vk.endCommandBuffer(*nestedCmdBuffer);
317 }
318 }
319
320 if (m_conditionalData.conditionInPrimaryCommandBuffer)
321 {
322 beginConditionalRendering(vk, *cmdBuffer, *conditionalBuffer, m_conditionalData);
323
324 if (m_conditionalData.conditionInherited)
325 {
326 if (m_conditionalData.secondaryCommandBufferNested)
327 {
328 vk.cmdExecuteCommands(*cmdBuffer, 1, &nestedCmdBuffer.get());
329 }
330 else
331 {
332 vk.cmdExecuteCommands(*cmdBuffer, 1, &secondaryCmdBuffer.get());
333 }
334 }
335 else
336 {
337 recordDispatch(vk, *cmdBuffer, indirectBuffer);
338 }
339
340 vk.cmdEndConditionalRenderingEXT(*cmdBuffer);
341 }
342 else if (useSecondaryCmdBuffer)
343 {
344 if (m_conditionalData.secondaryCommandBufferNested)
345 {
346 vk.cmdExecuteCommands(*cmdBuffer, 1, &nestedCmdBuffer.get());
347 }
348 else
349 {
350 vk.cmdExecuteCommands(*cmdBuffer, 1, &secondaryCmdBuffer.get());
351 }
352 }
353
354 const vk::VkBufferMemoryBarrier outputBufferMemoryBarrier = {vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
355 DE_NULL,
356 vk::VK_ACCESS_SHADER_WRITE_BIT,
357 vk::VK_ACCESS_HOST_READ_BIT,
358 VK_QUEUE_FAMILY_IGNORED,
359 VK_QUEUE_FAMILY_IGNORED,
360 outputBuffer.get(),
361 0u,
362 VK_WHOLE_SIZE};
363
364 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u,
365 DE_NULL, 1u, &outputBufferMemoryBarrier, 0u, DE_NULL);
366
367 endCommandBuffer(vk, *cmdBuffer);
368
369 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
370
371 // Check result
372
373 qpTestResult res = QP_TEST_RESULT_PASS;
374
375 const vk::Allocation &outputBufferAllocation = outputBuffer.getAllocation();
376 invalidateAlloc(vk, device, outputBufferAllocation);
377
378 const uint32_t *bufferPtr = static_cast<uint32_t *>(outputBufferAllocation.getHostPtr());
379
380 const uint32_t expectedResult = m_conditionalData.expectCommandExecution ? m_numCalls : 0u;
381 if (bufferPtr[0] != expectedResult)
382 {
383 res = QP_TEST_RESULT_FAIL;
384 }
385
386 return tcu::TestStatus(res, qpGetTestResultName(res));
387 }
388
389 } // namespace
390
ConditionalDispatchTests(tcu::TestContext & testCtx)391 ConditionalDispatchTests::ConditionalDispatchTests(tcu::TestContext &testCtx) : TestCaseGroup(testCtx, "dispatch")
392 {
393 /* Left blank on purpose */
394 }
395
~ConditionalDispatchTests(void)396 ConditionalDispatchTests::~ConditionalDispatchTests(void)
397 {
398 }
399
init(void)400 void ConditionalDispatchTests::init(void)
401 {
402 for (int conditionNdx = 0; conditionNdx < DE_LENGTH_OF_ARRAY(conditional::s_testsData); conditionNdx++)
403 {
404 const ConditionalData &conditionData = conditional::s_testsData[conditionNdx];
405
406 if (conditionData.clearInRenderPass)
407 continue;
408
409 de::MovePtr<tcu::TestCaseGroup> conditionalDrawRootGroup(
410 new tcu::TestCaseGroup(m_testCtx, de::toString(conditionData).c_str()));
411
412 for (uint32_t commandTypeIdx = 0; commandTypeIdx < DISPATCH_COMMAND_TYPE_DISPATCH_LAST; ++commandTypeIdx)
413 {
414 const DispatchCommandType command = DispatchCommandType(commandTypeIdx);
415
416 ConditionalTestSpec testSpec;
417 testSpec.command = command;
418 testSpec.numCalls = 3;
419 testSpec.conditionalData = conditionData;
420
421 conditionalDrawRootGroup->addChild(
422 new ConditionalDispatchTest(m_testCtx, getDispatchCommandTypeName(command), testSpec));
423 }
424
425 addChild(conditionalDrawRootGroup.release());
426 }
427
428 enum class ConditionLocation
429 {
430 PRIMARY_FLAT = 0,
431 PRIMARY_WITH_SECONDARY,
432 SECONDARY_NORMAL,
433 SECONDARY_INHERITED,
434 };
435
436 // Tests verifying the condition is interpreted as a 32-bit value.
437 {
438 de::MovePtr<tcu::TestCaseGroup> conditionSizeGroup(new tcu::TestCaseGroup(m_testCtx, "condition_size"));
439
440 struct ValuePaddingExecution
441 {
442 uint32_t value;
443 bool padding;
444 bool execution;
445 const char *name;
446 };
447
448 const ValuePaddingExecution kConditionValueResults[] = {
449 {0x00000001u, false, true, "first_byte"}, {0x00000100u, false, true, "second_byte"},
450 {0x00010000u, false, true, "third_byte"}, {0x01000000u, false, true, "fourth_byte"},
451 {0u, true, false, "padded_zero"},
452 };
453
454 struct ConditionLocationSubcase
455 {
456 ConditionLocation location;
457 const char *name;
458 };
459
460 const ConditionLocationSubcase kConditionLocationSubcase[] = {
461 {ConditionLocation::PRIMARY_FLAT, "primary"},
462 {ConditionLocation::PRIMARY_WITH_SECONDARY, "inherited"},
463 {ConditionLocation::SECONDARY_NORMAL, "secondary"},
464 {ConditionLocation::SECONDARY_INHERITED, "secondary_inherited"},
465 };
466
467 for (int subcaseNdx = 0; subcaseNdx < DE_LENGTH_OF_ARRAY(kConditionLocationSubcase); ++subcaseNdx)
468 {
469 const auto &subcase = kConditionLocationSubcase[subcaseNdx];
470
471 de::MovePtr<tcu::TestCaseGroup> subcaseGroup(new tcu::TestCaseGroup(m_testCtx, subcase.name));
472
473 ConditionalData conditionalData = {};
474 conditionalData.conditionInverted = false;
475
476 switch (subcase.location)
477 {
478 case ConditionLocation::PRIMARY_FLAT:
479 conditionalData.conditionInPrimaryCommandBuffer = true;
480 conditionalData.conditionInSecondaryCommandBuffer = false;
481 conditionalData.conditionInherited = false;
482 break;
483
484 case ConditionLocation::PRIMARY_WITH_SECONDARY:
485 conditionalData.conditionInPrimaryCommandBuffer = true;
486 conditionalData.conditionInSecondaryCommandBuffer = false;
487 conditionalData.conditionInherited = true;
488 break;
489
490 case ConditionLocation::SECONDARY_NORMAL:
491 conditionalData.conditionInPrimaryCommandBuffer = false;
492 conditionalData.conditionInSecondaryCommandBuffer = true;
493 conditionalData.conditionInherited = false;
494 break;
495
496 case ConditionLocation::SECONDARY_INHERITED:
497 conditionalData.conditionInPrimaryCommandBuffer = false;
498 conditionalData.conditionInSecondaryCommandBuffer = true;
499 conditionalData.conditionInherited = true;
500 break;
501
502 default:
503 DE_ASSERT(false);
504 break;
505 }
506
507 for (int valueNdx = 0; valueNdx < DE_LENGTH_OF_ARRAY(kConditionValueResults); ++valueNdx)
508 {
509 const auto &valueResults = kConditionValueResults[valueNdx];
510
511 conditionalData.conditionValue = valueResults.value;
512 conditionalData.padConditionValue = valueResults.padding;
513 conditionalData.expectCommandExecution = valueResults.execution;
514
515 ConditionalTestSpec spec;
516 spec.command = DISPATCH_COMMAND_TYPE_DISPATCH;
517 spec.numCalls = 1;
518 spec.conditionalData = conditionalData;
519
520 subcaseGroup->addChild(new ConditionalDispatchTest(m_testCtx, valueResults.name, spec));
521 }
522
523 conditionSizeGroup->addChild(subcaseGroup.release());
524 }
525
526 addChild(conditionSizeGroup.release());
527 }
528
529 // Tests checking the buffer allocation offset is applied correctly when reading the condition.
530 {
531 de::MovePtr<tcu::TestCaseGroup> allocOffsetGroup(new tcu::TestCaseGroup(m_testCtx, "alloc_offset"));
532
533 const struct
534 {
535 ConditionLocation location;
536 const char *name;
537 } kLocationCases[] = {
538 {ConditionLocation::PRIMARY_FLAT, "primary"},
539 {ConditionLocation::PRIMARY_WITH_SECONDARY, "inherited"},
540 {ConditionLocation::SECONDARY_NORMAL, "secondary"},
541 {ConditionLocation::SECONDARY_INHERITED, "secondary_inherited"},
542 };
543
544 const struct
545 {
546 bool active;
547 const char *name;
548 } kActiveCases[] = {
549 {false, "zero"},
550 {true, "nonzero"},
551 };
552
553 const struct
554 {
555 ConditionalBufferMemory memoryType;
556 const char *name;
557 } kMemoryTypeCases[] = {
558 {LOCAL, "device_local"},
559 {HOST, "host_visible"},
560 };
561
562 for (const auto &locationCase : kLocationCases)
563 {
564 de::MovePtr<tcu::TestCaseGroup> locationSubGroup(new tcu::TestCaseGroup(m_testCtx, locationCase.name));
565
566 for (const auto &activeCase : kActiveCases)
567 {
568 de::MovePtr<tcu::TestCaseGroup> activeSubGroup(new tcu::TestCaseGroup(m_testCtx, activeCase.name));
569
570 for (const auto &memoryTypeCase : kMemoryTypeCases)
571 {
572 ConditionalData conditionalData = {
573 false, // bool conditionInPrimaryCommandBuffer;
574 false, // bool conditionInSecondaryCommandBuffer;
575 false, // bool conditionInverted;
576 false, // bool conditionInherited;
577 0u, // uint32_t conditionValue;
578 false, // bool padConditionValue;
579 true, // bool allocationOffset;
580 false, // bool clearInRenderPass;
581 false, // bool expectCommandExecution;
582 false, // bool secondaryCommandBufferNested;
583 memoryTypeCase.memoryType, // ConditionalBufferMemory memoryType;
584 };
585
586 switch (locationCase.location)
587 {
588 case ConditionLocation::PRIMARY_FLAT:
589 conditionalData.conditionInPrimaryCommandBuffer = true;
590 conditionalData.conditionInSecondaryCommandBuffer = false;
591 conditionalData.conditionInherited = false;
592 break;
593
594 case ConditionLocation::PRIMARY_WITH_SECONDARY:
595 conditionalData.conditionInPrimaryCommandBuffer = true;
596 conditionalData.conditionInSecondaryCommandBuffer = false;
597 conditionalData.conditionInherited = true;
598 break;
599
600 case ConditionLocation::SECONDARY_NORMAL:
601 conditionalData.conditionInPrimaryCommandBuffer = false;
602 conditionalData.conditionInSecondaryCommandBuffer = true;
603 conditionalData.conditionInherited = false;
604 break;
605
606 case ConditionLocation::SECONDARY_INHERITED:
607 conditionalData.conditionInPrimaryCommandBuffer = false;
608 conditionalData.conditionInSecondaryCommandBuffer = true;
609 conditionalData.conditionInherited = true;
610 break;
611
612 default:
613 DE_ASSERT(false);
614 break;
615 }
616
617 conditionalData.conditionValue = (activeCase.active ? 1u : 0u);
618 conditionalData.expectCommandExecution = activeCase.active;
619
620 const ConditionalTestSpec spec = {
621 DISPATCH_COMMAND_TYPE_DISPATCH, // DispatchCommandType command;
622 1, // int numCalls;
623 conditionalData, // ConditionalData conditionalData;
624 };
625
626 activeSubGroup->addChild(new ConditionalDispatchTest(m_testCtx, memoryTypeCase.name, spec));
627 }
628
629 locationSubGroup->addChild(activeSubGroup.release());
630 }
631
632 allocOffsetGroup->addChild(locationSubGroup.release());
633 }
634
635 addChild(allocOffsetGroup.release());
636 }
637 }
638
639 } // namespace conditional
640 } // namespace vkt
641