• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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