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