• 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 vkCmdDraw* functions
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktConditionalDrawTests.hpp"
26 #include "vktConditionalRenderingTestUtil.hpp"
27 
28 #include "vktTestCaseUtil.hpp"
29 #include "vktDrawTestCaseUtil.hpp"
30 
31 #include "vktDrawBaseClass.hpp"
32 
33 #include "tcuTestLog.hpp"
34 #include "tcuResource.hpp"
35 #include "tcuImageCompare.hpp"
36 #include "tcuTextureUtil.hpp"
37 #include "tcuRGBA.hpp"
38 
39 #include "vkDefs.hpp"
40 #include "vkCmdUtil.hpp"
41 
42 namespace vkt
43 {
44 namespace conditional
45 {
46 namespace
47 {
48 
49 enum DrawCommandType
50 {
51 	DRAW_COMMAND_TYPE_DRAW = 0,
52 	DRAW_COMMAND_TYPE_DRAW_INDEXED,
53 	DRAW_COMMAND_TYPE_DRAW_INDIRECT,
54 	DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT,
55 	DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT,
56 	DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT,
57 
58 	DRAW_COMMAND_TYPE_DRAW_LAST
59 };
60 
getDrawCommandTypeName(DrawCommandType command)61 const char* getDrawCommandTypeName (DrawCommandType command)
62 {
63 	switch (command)
64 	{
65 		case DRAW_COMMAND_TYPE_DRAW:					    return "draw";
66 		case DRAW_COMMAND_TYPE_DRAW_INDEXED:			    return "draw_indexed";
67 		case DRAW_COMMAND_TYPE_DRAW_INDIRECT:			    return "draw_indirect";
68 		case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:	    return "draw_indexed_indirect";
69 		case DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT:			return "draw_indirect_count";
70 		case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT:	return "draw_indexed_indirect_count";
71 		default:					                        DE_ASSERT(false);
72 	}
73 	return "";
74 }
75 
76 struct ConditionalTestSpec : public Draw::TestSpecBase
77 {
78 	DrawCommandType		command;
79 	deUint32			drawCalls;
80 	ConditionalData		conditionalData;
81 };
82 
83 class ConditionalDraw : public Draw::DrawTestsBaseClass
84 {
85 public:
86 	typedef		ConditionalTestSpec	TestSpec;
87 
88 								ConditionalDraw				(Context &context, ConditionalTestSpec testSpec);
89 
90 	virtual		tcu::TestStatus iterate						(void);
91 				void			createAndBindIndexBuffer	(vk::VkCommandBuffer cmdBuffer);
92 				void			createIndirectBuffer		(void);
93 				void			createIndexedIndirectBuffer	(void);
94 				void			createIndirectCountBuffer	(void);
95 				void			recordDraw					(vk::VkCommandBuffer cmdBuffer);
96 
97 protected:
98 	const DrawCommandType		    m_command;
99 	const deUint32					m_drawCalls;
100 
101 	const ConditionalData			m_conditionalData;
102 	de::SharedPtr<Draw::Buffer>		m_conditionalBuffer;
103 
104 	vk::Move<vk::VkCommandBuffer>	m_secondaryCmdBuffer;
105 
106 	std::vector<deUint32>		    m_indexes;
107 	de::SharedPtr<Draw::Buffer>		m_indexBuffer;
108 
109 	de::SharedPtr<Draw::Buffer>		m_indirectBuffer;
110 	de::SharedPtr<Draw::Buffer>		m_indirectCountBuffer;
111 };
112 
ConditionalDraw(Context & context,ConditionalTestSpec testSpec)113 ConditionalDraw::ConditionalDraw (Context &context, ConditionalTestSpec testSpec)
114 	: Draw::DrawTestsBaseClass(context, testSpec.shaders[glu::SHADERTYPE_VERTEX], testSpec.shaders[glu::SHADERTYPE_FRAGMENT], false, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
115 	, m_command(testSpec.command)
116 	, m_drawCalls(testSpec.drawCalls)
117 	, m_conditionalData(testSpec.conditionalData)
118 {
119 	checkConditionalRenderingCapabilities(context, m_conditionalData);
120 
121 	const float minX = -0.3f;
122 	const float maxX = 0.3f;
123 	const float drawStep = 0.6f / static_cast<float>(m_drawCalls);
124 
125 	for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
126 	{
127 		const float minY = minX + static_cast<float>(drawIdx) * drawStep;
128 		const float maxY = minY + drawStep;
129 
130 		m_data.push_back(Draw::VertexElementData(tcu::Vec4(	minX,	maxY,	0.5f,	1.0f), tcu::RGBA::blue().toVec(), 0));
131 		m_data.push_back(Draw::VertexElementData(tcu::Vec4(	minX,	minY,	0.5f,	1.0f), tcu::RGBA::blue().toVec(), 0));
132 		m_data.push_back(Draw::VertexElementData(tcu::Vec4(	maxX,	maxY,	0.5f,	1.0f), tcu::RGBA::blue().toVec(), 0));
133 
134 		m_data.push_back(Draw::VertexElementData(tcu::Vec4(	minX,	minY,	0.5f,	1.0f), tcu::RGBA::blue().toVec(), 0));
135 		m_data.push_back(Draw::VertexElementData(tcu::Vec4(	maxX,	maxY,	0.5f,	1.0f), tcu::RGBA::blue().toVec(), 0));
136 		m_data.push_back(Draw::VertexElementData(tcu::Vec4(	maxX,	minY,	0.5f,	1.0f), tcu::RGBA::blue().toVec(), 0));
137 	}
138 
139 	m_data.push_back(Draw::VertexElementData(tcu::Vec4(	-1.0f,	1.0f,	0.0f,	1.0f), tcu::RGBA::red().toVec(), 0));
140 	m_data.push_back(Draw::VertexElementData(tcu::Vec4(	-1.0f,	-1.0f,	0.0f,	1.0f), tcu::RGBA::red().toVec(), 0));
141 	m_data.push_back(Draw::VertexElementData(tcu::Vec4(	1.0f,	1.0f,	0.0f,	1.0f), tcu::RGBA::red().toVec(), 0));
142 
143 	m_data.push_back(Draw::VertexElementData(tcu::Vec4(	-1.0f,	-1.0f,	0.0f,	1.0f), tcu::RGBA::red().toVec(), 0));
144 	m_data.push_back(Draw::VertexElementData(tcu::Vec4(	1.0f,	1.0f,	0.0f,	1.0f), tcu::RGBA::red().toVec(), 0));
145 	m_data.push_back(Draw::VertexElementData(tcu::Vec4(	1.0f,	-1.0f,	0.0f,	1.0f), tcu::RGBA::red().toVec(), 0));
146 
147 	for (deUint32 index = 0; index < m_data.size(); index++)
148 	{
149 		m_indexes.push_back(index);
150 	}
151 
152 	initialize();
153 
154 	m_secondaryCmdBuffer = vk::allocateCommandBuffer(m_vk, m_context.getDevice(), *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY);
155 }
156 
createAndBindIndexBuffer(vk::VkCommandBuffer cmdBuffer)157 void ConditionalDraw::createAndBindIndexBuffer (vk::VkCommandBuffer cmdBuffer)
158 {
159 	const vk::VkDeviceSize indexDataSize = m_indexes.size() * sizeof(deUint32);
160 	m_indexBuffer = Draw::Buffer::createAndAlloc(m_vk, m_context.getDevice(),
161 											Draw::BufferCreateInfo(indexDataSize,
162 															vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT),
163 											m_context.getDefaultAllocator(),
164 											vk::MemoryRequirement::HostVisible);
165 
166 	deUint8* indexBufferPtr = reinterpret_cast<deUint8*>(m_indexBuffer->getBoundMemory().getHostPtr());
167 	deMemcpy(indexBufferPtr, &m_indexes[0], static_cast<size_t>(indexDataSize));
168 
169 	vk::flushAlloc(m_vk, m_context.getDevice(), m_indexBuffer->getBoundMemory());
170 
171 	const vk::VkBuffer indexBuffer = m_indexBuffer->object();
172 	m_vk.cmdBindIndexBuffer(cmdBuffer, indexBuffer, 0, vk::VK_INDEX_TYPE_UINT32);
173 }
174 
createIndirectBuffer(void)175 void ConditionalDraw::createIndirectBuffer (void)
176 {
177 	const vk::VkDrawIndirectCommand badDrawCommand =
178 	{
179 		6u,					// vertexCount
180 		1u,					// instanceCount
181 		m_drawCalls * 6u,	// firstVertex
182 		0u					// firstInstance
183 	};
184 
185 	std::vector<vk::VkDrawIndirectCommand> drawCommands;
186 	for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
187 	{
188 		const vk::VkDrawIndirectCommand goodDrawCommand =
189 		{
190 			6u,				// vertexCount
191 			1u,				// instanceCount
192 			6u * drawIdx,	// firstVertex
193 			0u				// firstInstance
194 		};
195 
196 		drawCommands.push_back(goodDrawCommand);
197 		// *Bad* commands should not be rendered by vkCmdDrawIndirectCountKHR
198 		drawCommands.push_back(badDrawCommand);
199 		drawCommands.push_back(badDrawCommand);
200 	}
201 
202 	const vk::VkDeviceSize drawCommandsSize = drawCommands.size() * sizeof(vk::VkDrawIndirectCommand);
203 
204 	m_indirectBuffer = Draw::Buffer::createAndAlloc(m_vk,
205 													m_context.getDevice(),
206 													Draw::BufferCreateInfo(drawCommandsSize,
207 																	vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
208 													m_context.getDefaultAllocator(),
209 													vk::MemoryRequirement::HostVisible);
210 
211 	deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
212 	deMemcpy(ptr, &drawCommands[0], static_cast<size_t>(drawCommandsSize));
213 
214 	vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
215 }
216 
createIndexedIndirectBuffer(void)217 void ConditionalDraw::createIndexedIndirectBuffer (void)
218 {
219 	const vk::VkDrawIndexedIndirectCommand badDrawCommand =
220 	{
221 		6u,					// indexCount
222 		1u,					// instanceCount
223 		m_drawCalls * 6u,	// firstIndex
224 		0u,					// vertexOffset
225 		0u,					// firstInstance
226 	};
227 
228 	std::vector<vk::VkDrawIndexedIndirectCommand> drawCommands;
229 	for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
230 	{
231 		const vk::VkDrawIndexedIndirectCommand goodDrawCommand =
232 		{
233 			6u,				// indexCount
234 			1u,				// instanceCount
235 			6u * drawIdx,	// firstIndex
236 			0u,				// vertexOffset
237 			0u,				// firstInstance
238 		};
239 
240 		drawCommands.push_back(goodDrawCommand);
241 		// *Bad* commands should not be rendered by vkCmdDrawIndexedIndirectCountKHR
242 		drawCommands.push_back(badDrawCommand);
243 		drawCommands.push_back(badDrawCommand);
244 	}
245 
246 	const vk::VkDeviceSize drawCommandsSize = drawCommands.size() * sizeof(vk::VkDrawIndexedIndirectCommand);
247 
248 	m_indirectBuffer = Draw::Buffer::createAndAlloc(m_vk,
249 													m_context.getDevice(),
250 													Draw::BufferCreateInfo(drawCommandsSize,
251 																	vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
252 													m_context.getDefaultAllocator(),
253 													vk::MemoryRequirement::HostVisible);
254 
255 	deUint8* ptr = reinterpret_cast<deUint8*>(m_indirectBuffer->getBoundMemory().getHostPtr());
256 	deMemcpy(ptr, &drawCommands[0], static_cast<size_t>(drawCommandsSize));
257 
258 	vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectBuffer->getBoundMemory());
259 }
260 
createIndirectCountBuffer(void)261 void ConditionalDraw::createIndirectCountBuffer (void)
262 {
263 	m_indirectCountBuffer = Draw::Buffer::createAndAlloc(m_vk,
264 														m_context.getDevice(),
265 														Draw::BufferCreateInfo(sizeof(deUint32),
266 																			vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT),
267 														m_context.getDefaultAllocator(),
268 														vk::MemoryRequirement::HostVisible);
269 
270 	deUint8* countBufferPtr = reinterpret_cast<deUint8*>(m_indirectCountBuffer->getBoundMemory().getHostPtr());
271 	*(deUint32*)(countBufferPtr) = 1;
272 
273 	vk::flushAlloc(m_vk, m_context.getDevice(), m_indirectCountBuffer->getBoundMemory());
274 }
275 
recordDraw(vk::VkCommandBuffer cmdBuffer)276 void ConditionalDraw::recordDraw(vk::VkCommandBuffer cmdBuffer)
277 {
278 	for (deUint32 drawIdx = 0; drawIdx < m_drawCalls; drawIdx++)
279 	{
280 		/* Indirect buffer has next layout:
281 		 * goodCommand badCommand badCommand goodCommand badCommand badCommand ...
282 		 */
283 		const vk::VkDeviceSize indirectOffset = sizeof(vk::VkDrawIndirectCommand) * drawIdx * 3;
284 		const vk::VkDeviceSize indexedIndirectOffset = sizeof(vk::VkDrawIndexedIndirectCommand) * drawIdx * 3;
285 		switch (m_command)
286 		{
287 			case DRAW_COMMAND_TYPE_DRAW:
288 			{
289 				m_vk.cmdDraw(cmdBuffer, 6, 1, 6 * drawIdx, 0);
290 				break;
291 			}
292 			case DRAW_COMMAND_TYPE_DRAW_INDEXED:
293 			{
294 				m_vk.cmdDrawIndexed(cmdBuffer, 6, 1, 6 * drawIdx, 0, 0);
295 				break;
296 			}
297 			case DRAW_COMMAND_TYPE_DRAW_INDIRECT:
298 			{
299 				m_vk.cmdDrawIndirect(cmdBuffer, m_indirectBuffer->object(), indirectOffset, 1, 0);
300 				break;
301 			}
302 			case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:
303 			{
304 				m_vk.cmdDrawIndexedIndirect(cmdBuffer, m_indirectBuffer->object(), indexedIndirectOffset, 1, 0);
305 				break;
306 			}
307 			case DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT:
308 			{
309 				m_vk.cmdDrawIndirectCount(	cmdBuffer,
310 											m_indirectBuffer->object(), indirectOffset,
311 											m_indirectCountBuffer->object(), 0, 3,
312 											sizeof(vk::VkDrawIndirectCommand));
313 				break;
314 			}
315 			case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT:
316 			{
317 				m_vk.cmdDrawIndexedIndirectCount(cmdBuffer,
318 												 m_indirectBuffer->object(), indexedIndirectOffset,
319 												 m_indirectCountBuffer->object(), 0, 3,
320 												 sizeof(vk::VkDrawIndexedIndirectCommand));
321 				break;
322 			}
323 			default: DE_ASSERT(false);
324 		}
325 	}
326 }
327 
iterate(void)328 tcu::TestStatus ConditionalDraw::iterate (void)
329 {
330 	tcu::TestLog&		log		= m_context.getTestContext().getLog();
331 	const vk::VkQueue	queue	= m_context.getUniversalQueue();
332 	const vk::VkDevice	device	= m_context.getDevice();
333 
334 	const bool useSecondaryCmdBuffer = m_conditionalData.conditionInherited || m_conditionalData.conditionInSecondaryCommandBuffer;
335 	beginRender(useSecondaryCmdBuffer ? vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : vk::VK_SUBPASS_CONTENTS_INLINE);
336 
337 	vk::VkCommandBuffer targetCmdBuffer = *m_cmdBuffer;
338 
339 	if (useSecondaryCmdBuffer)
340 	{
341 		const vk::VkCommandBufferInheritanceConditionalRenderingInfoEXT conditionalRenderingInheritanceInfo =
342 		{
343 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT,
344 			DE_NULL,
345 			m_conditionalData.conditionInherited ? VK_TRUE : VK_FALSE	// conditionalRenderingEnable
346 		};
347 
348 		const vk::VkCommandBufferInheritanceInfo inheritanceInfo =
349 		{
350 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
351 			&conditionalRenderingInheritanceInfo,
352 			*m_renderPass,										        // renderPass
353 			0u,															// subpass
354 			*m_framebuffer,										        // framebuffer
355 			VK_FALSE,													// occlusionQueryEnable
356 			(vk::VkQueryControlFlags)0u,								// queryFlags
357 			(vk::VkQueryPipelineStatisticFlags)0u,						// pipelineStatistics
358 		};
359 
360 		const vk::VkCommandBufferBeginInfo commandBufferBeginInfo =
361 		{
362 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
363 			DE_NULL,
364 			vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,
365 			&inheritanceInfo
366 		};
367 
368 		m_vk.beginCommandBuffer(*m_secondaryCmdBuffer, &commandBufferBeginInfo);
369 
370 		targetCmdBuffer = *m_secondaryCmdBuffer;
371 	}
372 
373 	const vk::VkDeviceSize vertexBufferOffset = 0;
374 	const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
375 
376 	m_vk.cmdBindVertexBuffers(targetCmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
377 
378 	switch(m_command)
379 	{
380 		case DRAW_COMMAND_TYPE_DRAW:
381 		{
382 			break;
383 		}
384 		case DRAW_COMMAND_TYPE_DRAW_INDEXED:
385 		{
386 			createAndBindIndexBuffer(targetCmdBuffer);
387 			break;
388 		}
389 		case DRAW_COMMAND_TYPE_DRAW_INDIRECT:
390 		{
391 			createIndirectBuffer();
392 			break;
393 		}
394 		case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:
395 		{
396 			createAndBindIndexBuffer(targetCmdBuffer);
397 			createIndexedIndirectBuffer();
398 			break;
399 		}
400 		case DRAW_COMMAND_TYPE_DRAW_INDIRECT_COUNT:
401 		{
402 			createIndirectBuffer();
403 			createIndirectCountBuffer();
404 			break;
405 		}
406 		case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT_COUNT:
407 		{
408 			createAndBindIndexBuffer(targetCmdBuffer);
409 			createIndexedIndirectBuffer();
410 			createIndirectCountBuffer();
411 			break;
412 		}
413 		default: DE_ASSERT(false);
414 	}
415 
416 	m_vk.cmdBindPipeline(targetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
417 
418 	m_conditionalBuffer = createConditionalRenderingBuffer(m_context, m_conditionalData);
419 
420 	if (m_conditionalData.conditionInSecondaryCommandBuffer)
421 	{
422 		beginConditionalRendering(m_vk, *m_secondaryCmdBuffer, *m_conditionalBuffer, m_conditionalData);
423 		recordDraw(*m_secondaryCmdBuffer);
424 		m_vk.cmdEndConditionalRenderingEXT(*m_secondaryCmdBuffer);
425 		m_vk.endCommandBuffer(*m_secondaryCmdBuffer);
426 	}
427 	else if (m_conditionalData.conditionInherited)
428 	{
429 		recordDraw(*m_secondaryCmdBuffer);
430 		m_vk.endCommandBuffer(*m_secondaryCmdBuffer);
431 	}
432 
433 	if (m_conditionalData.conditionInPrimaryCommandBuffer)
434 	{
435 		beginConditionalRendering(m_vk, *m_cmdBuffer, *m_conditionalBuffer, m_conditionalData);
436 
437 		if (m_conditionalData.conditionInherited)
438 		{
439 			m_vk.cmdExecuteCommands(*m_cmdBuffer, 1, &m_secondaryCmdBuffer.get());
440 		}
441 		else
442 		{
443 			recordDraw(*m_cmdBuffer);
444 		}
445 
446 		m_vk.cmdEndConditionalRenderingEXT(*m_cmdBuffer);
447 	}
448 	else if (useSecondaryCmdBuffer)
449 	{
450 		m_vk.cmdExecuteCommands(*m_cmdBuffer, 1, &m_secondaryCmdBuffer.get());
451 	}
452 
453 	endRender();
454 	endCommandBuffer(m_vk, *m_cmdBuffer);
455 
456 	submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
457 
458 	// Validation
459 	tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
460 								  referenceFrame.allocLevel(0);
461 
462 	const deInt32 frameWidth	= referenceFrame.getWidth();
463 	const deInt32 frameHeight	= referenceFrame.getHeight();
464 
465 	const tcu::Vec4 clearColor = tcu::RGBA::black().toVec();
466 	const tcu::Vec4 drawColor  = tcu::RGBA::blue().toVec();
467 
468 	tcu::clear(referenceFrame.getLevel(0), clearColor);
469 
470 	const tcu::Vec4 referenceColor = m_conditionalData.expectCommandExecution ?
471 										drawColor : clearColor;
472 
473 	Draw::ReferenceImageCoordinates refCoords;
474 
475 	for (int y = 0; y < frameHeight; y++)
476 	{
477 		const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
478 
479 		for (int x = 0; x < frameWidth; x++)
480 		{
481 			const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
482 
483 			if ((yCoord >= refCoords.bottom &&
484 				 yCoord <= refCoords.top	&&
485 				 xCoord >= refCoords.left	&&
486 				 xCoord <= refCoords.right))
487 				referenceFrame.getLevel(0).setPixel(referenceColor, x, y);
488 		}
489 	}
490 
491 	const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
492 	const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
493 		vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
494 
495 	qpTestResult res = QP_TEST_RESULT_PASS;
496 
497 	if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
498 		referenceFrame.getLevel(0), renderedFrame, 0.05f,
499 		tcu::COMPARE_LOG_RESULT))
500 	{
501 		res = QP_TEST_RESULT_FAIL;
502 	}
503 
504 	return tcu::TestStatus(res, qpGetTestResultName(res));
505 }
506 
507 }	// anonymous
508 
ConditionalDrawTests(tcu::TestContext & testCtx)509 ConditionalDrawTests::ConditionalDrawTests (tcu::TestContext &testCtx)
510 	: TestCaseGroup	(testCtx, "draw", "Conditional Rendering Of Draw Commands")
511 {
512 	/* Left blank on purpose */
513 }
514 
~ConditionalDrawTests(void)515 ConditionalDrawTests::~ConditionalDrawTests (void) {}
516 
init(void)517 void ConditionalDrawTests::init (void)
518 {
519 	for (int conditionNdx = 0; conditionNdx < DE_LENGTH_OF_ARRAY(conditional::s_testsData); conditionNdx++)
520 	{
521 		const ConditionalData& conditionData = conditional::s_testsData[conditionNdx];
522 
523 		tcu::TestCaseGroup* conditionalDrawRootGroup = new tcu::TestCaseGroup(m_testCtx, de::toString(conditionData).c_str(), "Conditionaly execute draw calls");
524 
525 		for (deUint32 commandTypeIdx = 0; commandTypeIdx < DRAW_COMMAND_TYPE_DRAW_LAST; ++commandTypeIdx)
526 		{
527 			const DrawCommandType	command	= DrawCommandType(commandTypeIdx);
528 
529 			ConditionalTestSpec testSpec;
530 			testSpec.command = command;
531 			testSpec.drawCalls = 4;
532 			testSpec.conditionalData = conditionData;
533 			testSpec.shaders[glu::SHADERTYPE_VERTEX] = "vulkan/dynamic_state/VertexFetch.vert";
534 			testSpec.shaders[glu::SHADERTYPE_FRAGMENT] = "vulkan/dynamic_state/VertexFetch.frag";
535 
536 			conditionalDrawRootGroup->addChild(new Draw::InstanceFactory<ConditionalDraw>(m_testCtx, getDrawCommandTypeName(command), "", testSpec));
537 		}
538 
539 		addChild(conditionalDrawRootGroup);
540 	}
541 }
542 
543 }	// conditional
544 }	// vkt
545