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