• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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 Simple Draw Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktBasicDrawTests.hpp"
26 
27 #include "vktDrawBaseClass.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vktTestGroupUtil.hpp"
32 
33 #include "deDefs.h"
34 #include "deRandom.hpp"
35 #include "deString.h"
36 
37 #include "tcuTestCase.hpp"
38 #include "tcuRGBA.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "tcuVectorUtil.hpp"
42 
43 #include "rrRenderer.hpp"
44 
45 #include <string>
46 #include <sstream>
47 
48 namespace vkt
49 {
50 namespace Draw
51 {
52 namespace
53 {
54 static const deUint32 SEED			= 0xc2a39fu;
55 static const deUint32 INDEX_LIMIT	= 10000;
56 // To avoid too big and mostly empty structures
57 static const deUint32 OFFSET_LIMIT	= 1000;
58 // Number of primitives to draw
59 static const deUint32 PRIMITIVE_COUNT[] = {1, 3, 17, 45};
60 
61 enum DrawCommandType
62 {
63 	DRAW_COMMAND_TYPE_DRAW,
64 	DRAW_COMMAND_TYPE_DRAW_INDEXED,
65 	DRAW_COMMAND_TYPE_DRAW_INDIRECT,
66 	DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT,
67 
68 	DRAW_COMMAND_TYPE_DRAW_LAST
69 };
70 
getDrawCommandTypeName(DrawCommandType command)71 const char* getDrawCommandTypeName (DrawCommandType command)
72 {
73 	switch (command)
74 	{
75 		case DRAW_COMMAND_TYPE_DRAW:					return "draw";
76 		case DRAW_COMMAND_TYPE_DRAW_INDEXED:			return "draw_indexed";
77 		case DRAW_COMMAND_TYPE_DRAW_INDIRECT:			return "draw_indirect";
78 		case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:	return "draw_indexed_indirect";
79 		default:					DE_ASSERT(false);
80 	}
81 	return "";
82 }
83 
mapVkPrimitiveTopology(vk::VkPrimitiveTopology primitiveTopology)84 rr::PrimitiveType mapVkPrimitiveTopology (vk::VkPrimitiveTopology primitiveTopology)
85 {
86 	switch (primitiveTopology)
87 	{
88 		case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:						return rr::PRIMITIVETYPE_POINTS;
89 		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:						return rr::PRIMITIVETYPE_LINES;
90 		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:						return rr::PRIMITIVETYPE_LINE_STRIP;
91 		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:					return rr::PRIMITIVETYPE_TRIANGLES;
92 		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:					return rr::PRIMITIVETYPE_TRIANGLE_FAN;
93 		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:					return rr::PRIMITIVETYPE_TRIANGLE_STRIP;
94 		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:		return rr::PRIMITIVETYPE_LINES_ADJACENCY;
95 		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:		return rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY;
96 		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:	return rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY;
97 		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:	return rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY;
98 		default:
99 			DE_ASSERT(false);
100 	}
101 	return rr::PRIMITIVETYPE_LAST;
102 }
103 
104 struct DrawParamsBase
105 {
106 	std::vector<PositionColorVertex>	vertices;
107 	vk::VkPrimitiveTopology				topology;
108 	GroupParams							groupParams;	// we can't use SharedGroupParams here
109 
DrawParamsBasevkt::Draw::__anona9f947520111::DrawParamsBase110 	DrawParamsBase ()
111 	{}
112 
DrawParamsBasevkt::Draw::__anona9f947520111::DrawParamsBase113 	DrawParamsBase (const vk::VkPrimitiveTopology top, const SharedGroupParams gParams)
114 		: topology		(top)
115 		, groupParams
116 		{
117 			gParams->useDynamicRendering,
118 			gParams->useSecondaryCmdBuffer,
119 			gParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass
120 		}
121 	{}
122 };
123 
124 struct IndexedParamsBase
125 {
126 	std::vector<deUint32>	indexes;
127 	const vk::VkIndexType	indexType;
128 
IndexedParamsBasevkt::Draw::__anona9f947520111::IndexedParamsBase129 	IndexedParamsBase (const vk::VkIndexType indexT)
130 		: indexType	(indexT)
131 	{}
132 };
133 
134 // Structs to store draw parameters
135 struct DrawParams : DrawParamsBase
136 {
137 	// vkCmdDraw parameters is like a single VkDrawIndirectCommand
138 	vk::VkDrawIndirectCommand	params;
139 
DrawParamsvkt::Draw::__anona9f947520111::DrawParams140 	DrawParams (const vk::VkPrimitiveTopology top, const SharedGroupParams gParams, const deUint32 vertexC, const deUint32 instanceC, const deUint32 firstV, const deUint32 firstI)
141 		: DrawParamsBase	(top, gParams)
142 	{
143 		params.vertexCount		= vertexC;
144 		params.instanceCount	= instanceC;
145 		params.firstVertex		= firstV;
146 		params.firstInstance	= firstI;
147 	}
148 };
149 
150 struct DrawIndexedParams : DrawParamsBase, IndexedParamsBase
151 {
152 	// vkCmdDrawIndexed parameters is like a single VkDrawIndexedIndirectCommand
153 	vk::VkDrawIndexedIndirectCommand	params;
154 
DrawIndexedParamsvkt::Draw::__anona9f947520111::DrawIndexedParams155 	DrawIndexedParams (const vk::VkPrimitiveTopology top, const SharedGroupParams gParams, const vk::VkIndexType indexT, const deUint32 indexC, const deUint32 instanceC, const deUint32 firstIdx, const deInt32 vertexO, const deUint32 firstIns)
156 		: DrawParamsBase	(top, gParams)
157 		, IndexedParamsBase	(indexT)
158 	{
159 		params.indexCount		= indexC;
160 		params.instanceCount	= instanceC;
161 		params.firstIndex		= firstIdx;
162 		params.vertexOffset		= vertexO;
163 		params.firstInstance	= firstIns;
164 	}
165 };
166 
167 struct DrawIndirectParams : DrawParamsBase
168 {
169 	std::vector<vk::VkDrawIndirectCommand>	commands;
170 
DrawIndirectParamsvkt::Draw::__anona9f947520111::DrawIndirectParams171 	DrawIndirectParams (const vk::VkPrimitiveTopology top, const SharedGroupParams gParams)
172 		: DrawParamsBase	(top, gParams)
173 	{}
174 
addCommandvkt::Draw::__anona9f947520111::DrawIndirectParams175 	void addCommand (const deUint32 vertexC, const deUint32 instanceC, const deUint32 firstV, const deUint32 firstI)
176 	{
177 		vk::VkDrawIndirectCommand	cmd;
178 		cmd.vertexCount				= vertexC;
179 		cmd.instanceCount			= instanceC;
180 		cmd.firstVertex				= firstV;
181 		cmd.firstInstance			= firstI;
182 
183 		commands.push_back(cmd);
184 	}
185 };
186 
187 struct DrawIndexedIndirectParams : DrawParamsBase, IndexedParamsBase
188 {
189 	std::vector<vk::VkDrawIndexedIndirectCommand>	commands;
190 
DrawIndexedIndirectParamsvkt::Draw::__anona9f947520111::DrawIndexedIndirectParams191 	DrawIndexedIndirectParams (const vk::VkPrimitiveTopology top, const SharedGroupParams gParams, const vk::VkIndexType indexT)
192 		: DrawParamsBase	(top, gParams)
193 		, IndexedParamsBase	(indexT)
194 	{}
195 
addCommandvkt::Draw::__anona9f947520111::DrawIndexedIndirectParams196 	void addCommand (const deUint32 indexC, const deUint32 instanceC, const deUint32 firstIdx, const deInt32 vertexO, const deUint32 firstIns)
197 	{
198 		vk::VkDrawIndexedIndirectCommand	cmd;
199 		cmd.indexCount						= indexC;
200 		cmd.instanceCount					= instanceC;
201 		cmd.firstIndex						= firstIdx;
202 		cmd.vertexOffset					= vertexO;
203 		cmd.firstInstance					= firstIns;
204 
205 		commands.push_back(cmd);
206 	}
207 };
208 
209 // Reference renderer shaders
210 class PassthruVertShader : public rr::VertexShader
211 {
212 public:
PassthruVertShader(void)213 	PassthruVertShader (void)
214 	: rr::VertexShader (2, 1)
215 	{
216 		m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
217 		m_inputs[1].type	= rr::GENERICVECTYPE_FLOAT;
218 		m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
219 	}
220 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const221 	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
222 	{
223 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
224 		{
225 			packets[packetNdx]->position = rr::readVertexAttribFloat(inputs[0],
226 																	 packets[packetNdx]->instanceNdx,
227 																	 packets[packetNdx]->vertexNdx);
228 
229 			tcu::Vec4 color = rr::readVertexAttribFloat(inputs[1],
230 														packets[packetNdx]->instanceNdx,
231 														packets[packetNdx]->vertexNdx);
232 
233 			packets[packetNdx]->outputs[0] = color;
234 		}
235 	}
236 };
237 
238 class PassthruFragShader : public rr::FragmentShader
239 {
240 public:
PassthruFragShader(void)241 	PassthruFragShader (void)
242 		: rr::FragmentShader(1, 1)
243 	{
244 		m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
245 		m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
246 	}
247 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const248 	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
249 	{
250 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
251 		{
252 			rr::FragmentPacket& packet = packets[packetNdx];
253 			for (deUint32 fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
254 			{
255 				tcu::Vec4 color = rr::readVarying<float>(packet, context, 0, fragNdx);
256 				rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
257 			}
258 		}
259 	}
260 };
261 
imageCompare(tcu::TestLog & log,const tcu::ConstPixelBufferAccess & reference,const tcu::ConstPixelBufferAccess & result,const vk::VkPrimitiveTopology topology)262 inline bool imageCompare (tcu::TestLog& log, const tcu::ConstPixelBufferAccess& reference, const tcu::ConstPixelBufferAccess& result, const vk::VkPrimitiveTopology topology)
263 {
264 	if (topology == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
265 	{
266 		return tcu::intThresholdPositionDeviationCompare(
267 			log, "Result", "Image comparison result", reference, result,
268 			tcu::UVec4(4u),					// color threshold
269 			tcu::IVec3(1, 1, 0),			// position deviation tolerance
270 			true,							// don't check the pixels at the boundary
271 			tcu::COMPARE_LOG_RESULT);
272 	}
273 	else
274 		return tcu::fuzzyCompare(log, "Result", "Image comparison result", reference, result, 0.053f, tcu::COMPARE_LOG_RESULT);
275 }
276 
277 class DrawTestInstanceBase : public TestInstance
278 {
279 public:
280 									DrawTestInstanceBase	(Context& context);
281 	virtual							~DrawTestInstanceBase	(void) = 0;
282 	void							initialize				(const DrawParamsBase& data);
283 	void							initPipeline			(const vk::VkDevice device);
284 	void							preRenderBarriers		(void);
285 	void							beginRenderPass			(vk::VkCommandBuffer cmdBuffer);
286 	void							endRenderPass			(vk::VkCommandBuffer cmdBuffer);
287 
288 #ifndef CTS_USES_VULKANSC
289 	void							beginSecondaryCmdBuffer	(const vk::DeviceInterface& vk, vk::VkRenderingFlagsKHR renderingFlags = 0u);
290 	void							beginDynamicRender		(vk::VkCommandBuffer cmdBuffer, vk::VkRenderingFlagsKHR renderingFlags = 0u);
291 	void							endDynamicRender		(vk::VkCommandBuffer cmdBuffer);
292 #endif // CTS_USES_VULKANSC
293 
294 	// Specialize this function for each type
295 	virtual tcu::TestStatus			iterate					(void) = 0;
296 protected:
297 	// Specialize this function for each type
298 	virtual void					generateDrawData		(void) = 0;
299 	void							generateRefImage		(const tcu::PixelBufferAccess& access, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
300 
301 	DrawParamsBase											m_data;
302 	const vk::DeviceInterface&								m_vk;
303 	vk::Move<vk::VkPipeline>								m_pipeline;
304 	vk::Move<vk::VkPipelineLayout>							m_pipelineLayout;
305 	vk::VkFormat											m_colorAttachmentFormat;
306 	de::SharedPtr<Image>									m_colorTargetImage;
307 	vk::Move<vk::VkImageView>								m_colorTargetView;
308 	vk::Move<vk::VkRenderPass>								m_renderPass;
309 	vk::Move<vk::VkFramebuffer>								m_framebuffer;
310 	PipelineCreateInfo::VertexInputState					m_vertexInputState;
311 	de::SharedPtr<Buffer>									m_vertexBuffer;
312 	vk::Move<vk::VkCommandPool>								m_cmdPool;
313 	vk::Move<vk::VkCommandBuffer>							m_cmdBuffer;
314 	vk::Move<vk::VkCommandBuffer>							m_secCmdBuffer;
315 
316 	enum
317 	{
318 		WIDTH = 256,
319 		HEIGHT = 256
320 	};
321 };
322 
DrawTestInstanceBase(Context & context)323 DrawTestInstanceBase::DrawTestInstanceBase (Context& context)
324 	: vkt::TestInstance			(context)
325 	, m_vk						(context.getDeviceInterface())
326 	, m_colorAttachmentFormat	(vk::VK_FORMAT_R8G8B8A8_UNORM)
327 {
328 }
329 
~DrawTestInstanceBase(void)330 DrawTestInstanceBase::~DrawTestInstanceBase (void)
331 {
332 }
333 
initialize(const DrawParamsBase & data)334 void DrawTestInstanceBase::initialize (const DrawParamsBase& data)
335 {
336 	m_data = data;
337 
338 	const vk::VkDevice	device				= m_context.getDevice();
339 	const deUint32		queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
340 
341 	const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
342 	m_pipelineLayout						= vk::createPipelineLayout(m_vk, device, &pipelineLayoutCreateInfo);
343 
344 	const vk::VkExtent3D targetImageExtent	= { WIDTH, HEIGHT, 1 };
345 	const ImageCreateInfo targetImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, targetImageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
346 		vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
347 
348 	m_colorTargetImage						= Image::createAndAlloc(m_vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
349 
350 	const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
351 	m_colorTargetView						= vk::createImageView(m_vk, device, &colorTargetViewInfo);
352 
353 	// create render pass only when we are not using dynamic rendering
354 	if (!m_data.groupParams.useDynamicRendering)
355 	{
356 		RenderPassCreateInfo renderPassCreateInfo;
357 		renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat,
358 																 vk::VK_SAMPLE_COUNT_1_BIT,
359 																 vk::VK_ATTACHMENT_LOAD_OP_LOAD,
360 																 vk::VK_ATTACHMENT_STORE_OP_STORE,
361 																 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
362 																 vk::VK_ATTACHMENT_STORE_OP_STORE,
363 																 vk::VK_IMAGE_LAYOUT_GENERAL,
364 																 vk::VK_IMAGE_LAYOUT_GENERAL));
365 
366 		const vk::VkAttachmentReference colorAttachmentReference
367 		{
368 			0,
369 			vk::VK_IMAGE_LAYOUT_GENERAL
370 		};
371 
372 		renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
373 														   0,
374 														   0,
375 														   DE_NULL,
376 														   1,
377 														   &colorAttachmentReference,
378 														   DE_NULL,
379 														   AttachmentReference(),
380 														   0,
381 														   DE_NULL));
382 
383 		m_renderPass = vk::createRenderPass(m_vk, device, &renderPassCreateInfo);
384 
385 		// create framebuffer
386 		std::vector<vk::VkImageView>	colorAttachments		{ *m_colorTargetView };
387 		const FramebufferCreateInfo		framebufferCreateInfo	(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
388 		m_framebuffer = vk::createFramebuffer(m_vk, device, &framebufferCreateInfo);
389 	}
390 
391 	const vk::VkVertexInputBindingDescription vertexInputBindingDescription =
392 	{
393 		0,
394 		(deUint32)sizeof(tcu::Vec4) * 2,
395 		vk::VK_VERTEX_INPUT_RATE_VERTEX,
396 	};
397 
398 	const vk::VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
399 	{
400 		{
401 			0u,
402 			0u,
403 			vk::VK_FORMAT_R32G32B32A32_SFLOAT,
404 			0u
405 		},
406 		{
407 			1u,
408 			0u,
409 			vk::VK_FORMAT_R32G32B32A32_SFLOAT,
410 			(deUint32)(sizeof(float)* 4),
411 		}
412 	};
413 
414 	m_vertexInputState = PipelineCreateInfo::VertexInputState(1,
415 															  &vertexInputBindingDescription,
416 															  2,
417 															  vertexInputAttributeDescriptions);
418 
419 	const vk::VkDeviceSize dataSize = m_data.vertices.size() * sizeof(PositionColorVertex);
420 	m_vertexBuffer = Buffer::createAndAlloc(m_vk, device, BufferCreateInfo(dataSize,
421 		vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
422 
423 	deUint8* ptr = reinterpret_cast<deUint8*>(m_vertexBuffer->getBoundMemory().getHostPtr());
424 	deMemcpy(ptr, &(m_data.vertices[0]), static_cast<size_t>(dataSize));
425 
426 	vk::flushAlloc(m_vk, device, m_vertexBuffer->getBoundMemory());
427 
428 	const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex);
429 	m_cmdPool	= vk::createCommandPool(m_vk, device, &cmdPoolCreateInfo);
430 	m_cmdBuffer	= vk::allocateCommandBuffer(m_vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
431 
432 	if (m_data.groupParams.useSecondaryCmdBuffer)
433 		m_secCmdBuffer = vk::allocateCommandBuffer(m_vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY);
434 
435 	initPipeline(device);
436 }
437 
initPipeline(const vk::VkDevice device)438 void DrawTestInstanceBase::initPipeline (const vk::VkDevice device)
439 {
440 	const vk::Unique<vk::VkShaderModule>	vs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("vert"), 0));
441 	const vk::Unique<vk::VkShaderModule>	fs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("frag"), 0));
442 
443 	const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
444 
445 	vk::VkViewport viewport	= vk::makeViewport(WIDTH, HEIGHT);
446 	vk::VkRect2D scissor	= vk::makeRect2D(WIDTH, HEIGHT);
447 
448 	// when dynamic_rendering is tested then renderPass won't be created and VK_NULL_HANDLE will be used here
449 	PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
450 	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
451 	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
452 	pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(m_vertexInputState));
453 	pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(m_data.topology));
454 	pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
455 	pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport), std::vector<vk::VkRect2D>(1, scissor)));
456 	pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
457 	pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
458 	pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
459 
460 #ifndef CTS_USES_VULKANSC
461 	vk::VkPipelineRenderingCreateInfoKHR renderingCreateInfo
462 	{
463 		vk::VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
464 		DE_NULL,
465 		0u,
466 		1u,
467 		&m_colorAttachmentFormat,
468 		vk::VK_FORMAT_UNDEFINED,
469 		vk::VK_FORMAT_UNDEFINED
470 	};
471 
472 	if (m_data.groupParams.useDynamicRendering)
473 		pipelineCreateInfo.pNext = &renderingCreateInfo;
474 #endif // CTS_USES_VULKANSC
475 
476 	m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
477 }
478 
preRenderBarriers(void)479 void DrawTestInstanceBase::preRenderBarriers (void)
480 {
481 	const vk::VkClearValue clearColor { { { 0.0f, 0.0f, 0.0f, 1.0f } } };
482 
483 	initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
484 								  vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
485 
486 	const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT);
487 	m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(),
488 		vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &subresourceRange);
489 
490 	const vk::VkMemoryBarrier memBarrier
491 	{
492 		vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,
493 		DE_NULL,
494 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,
495 		vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
496 	};
497 
498 	m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
499 		vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
500 		0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
501 }
502 
beginRenderPass(vk::VkCommandBuffer cmdBuffer)503 void DrawTestInstanceBase::beginRenderPass (vk::VkCommandBuffer cmdBuffer)
504 {
505 	const vk::VkClearValue	clearColor	{ { { 0.0f, 0.0f, 0.0f, 1.0f } } };
506 	const vk::VkRect2D		renderArea	= vk::makeRect2D(WIDTH, HEIGHT);
507 
508 	vk::beginRenderPass(m_vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, 1u, &clearColor);
509 }
510 
endRenderPass(vk::VkCommandBuffer cmdBuffer)511 void DrawTestInstanceBase::endRenderPass (vk::VkCommandBuffer cmdBuffer)
512 {
513 	vk::endRenderPass(m_vk, cmdBuffer);
514 }
515 
516 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(const vk::DeviceInterface & vk,vk::VkRenderingFlagsKHR renderingFlags)517 void DrawTestInstanceBase::beginSecondaryCmdBuffer(const vk::DeviceInterface& vk, vk::VkRenderingFlagsKHR renderingFlags)
518 {
519 	const vk::VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
520 	{
521 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,	// VkStructureType					sType;
522 		DE_NULL,																// const void*						pNext;
523 		renderingFlags,															// VkRenderingFlagsKHR				flags;
524 		0u,																		// uint32_t							viewMask;
525 		1u,																		// uint32_t							colorAttachmentCount;
526 		&m_colorAttachmentFormat,												// const VkFormat*					pColorAttachmentFormats;
527 		vk::VK_FORMAT_UNDEFINED,												// VkFormat							depthAttachmentFormat;
528 		vk::VK_FORMAT_UNDEFINED,												// VkFormat							stencilAttachmentFormat;
529 		vk::VK_SAMPLE_COUNT_1_BIT,												// VkSampleCountFlagBits			rasterizationSamples;
530 	};
531 
532 	const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo
533 	{
534 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,					// VkStructureType					sType;
535 		&inheritanceRenderingInfo,												// const void*						pNext;
536 		DE_NULL,																// VkRenderPass						renderPass;
537 		0u,																		// deUint32							subpass;
538 		DE_NULL,																// VkFramebuffer					framebuffer;
539 		VK_FALSE,																// VkBool32							occlusionQueryEnable;
540 		(vk::VkQueryControlFlags)0u,											// VkQueryControlFlags				queryFlags;
541 		(vk::VkQueryPipelineStatisticFlags)0u									// VkQueryPipelineStatisticFlags	pipelineStatistics;
542 	};
543 
544 	vk::VkCommandBufferUsageFlags usageFlags = vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
545 	if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
546 		usageFlags |= vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
547 
548 	const vk::VkCommandBufferBeginInfo commandBufBeginParams
549 	{
550 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,						// VkStructureType					sType;
551 		DE_NULL,																// const void*						pNext;
552 		usageFlags,																// VkCommandBufferUsageFlags		flags;
553 		&bufferInheritanceInfo
554 	};
555 
556 	VK_CHECK(vk.beginCommandBuffer(*m_secCmdBuffer, &commandBufBeginParams));
557 }
558 
beginDynamicRender(vk::VkCommandBuffer cmdBuffer,vk::VkRenderingFlagsKHR renderingFlags)559 void DrawTestInstanceBase::beginDynamicRender(vk::VkCommandBuffer cmdBuffer, vk::VkRenderingFlagsKHR renderingFlags)
560 {
561 	const vk::VkClearValue	clearColor{ { { 0.0f, 0.0f, 0.0f, 1.0f } } };
562 	const vk::VkRect2D		renderArea = vk::makeRect2D(WIDTH, HEIGHT);
563 
564 	vk::beginRendering(m_vk, cmdBuffer, *m_colorTargetView, renderArea, clearColor, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_LOAD, renderingFlags);
565 }
566 
endDynamicRender(vk::VkCommandBuffer cmdBuffer)567 void DrawTestInstanceBase::endDynamicRender(vk::VkCommandBuffer cmdBuffer)
568 {
569 	vk::endRendering(m_vk, cmdBuffer);
570 }
571 #endif // CTS_USES_VULKANSC
572 
generateRefImage(const tcu::PixelBufferAccess & access,const std::vector<tcu::Vec4> & vertices,const std::vector<tcu::Vec4> & colors) const573 void DrawTestInstanceBase::generateRefImage (const tcu::PixelBufferAccess& access, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
574 {
575 	const PassthruVertShader				vertShader;
576 	const PassthruFragShader				fragShader;
577 	const rr::Program						program			(&vertShader, &fragShader);
578 	const rr::MultisamplePixelBufferAccess	colorBuffer		= rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(access);
579 	const rr::RenderTarget					renderTarget	(colorBuffer);
580 	const rr::RenderState					renderState		((rr::ViewportState(colorBuffer)), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
581 	const rr::Renderer						renderer;
582 
583 	const rr::VertexAttrib	vertexAttribs[] =
584 	{
585 		rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &vertices[0]),
586 		rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &colors[0])
587 	};
588 
589 	renderer.draw(rr::DrawCommand(renderState,
590 								  renderTarget,
591 								  program,
592 								  DE_LENGTH_OF_ARRAY(vertexAttribs),
593 								  &vertexAttribs[0],
594 								  rr::PrimitiveList(mapVkPrimitiveTopology(m_data.topology), (deUint32)vertices.size(), 0)));
595 }
596 
597 template<typename T>
598 class DrawTestInstance : public DrawTestInstanceBase
599 {
600 public:
601 							DrawTestInstance		(Context& context, const T& data);
602 	virtual					~DrawTestInstance		(void);
603 	virtual void			generateDrawData		(void);
604 	virtual void			draw					(vk::VkCommandBuffer cmdBuffer, vk::VkBuffer indirectBuffer = DE_NULL, vk::VkDeviceSize indirectOffset = 0ul);
605 	virtual tcu::TestStatus	iterate					(void);
606 private:
607 	T						m_data;
608 };
609 
610 template<typename T>
DrawTestInstance(Context & context,const T & data)611 DrawTestInstance<T>::DrawTestInstance (Context& context, const T& data)
612 	: DrawTestInstanceBase	(context)
613 	, m_data(data)
614 {
615 	generateDrawData();
616 	initialize(m_data);
617 }
618 
619 template<typename T>
~DrawTestInstance(void)620 DrawTestInstance<T>::~DrawTestInstance (void)
621 {
622 }
623 
624 template<typename T>
generateDrawData(void)625 void DrawTestInstance<T>::generateDrawData (void)
626 {
627 	DE_FATAL("Using the general case of this function is forbidden!");
628 }
629 
630 template<typename T>
draw(vk::VkCommandBuffer,vk::VkBuffer,vk::VkDeviceSize)631 void DrawTestInstance<T>::draw(vk::VkCommandBuffer, vk::VkBuffer, vk::VkDeviceSize)
632 {
633 	DE_FATAL("Using the general case of this function is forbidden!");
634 }
635 
636 template<typename T>
iterate(void)637 tcu::TestStatus DrawTestInstance<T>::iterate (void)
638 {
639 	DE_FATAL("Using the general case of this function is forbidden!");
640 	return tcu::TestStatus::fail("");
641 }
642 
643 template<typename T>
644 class DrawTestCase : public TestCase
645 {
646 	public:
647 									DrawTestCase		(tcu::TestContext& context, const char* name, const char* desc, const T data);
648 									~DrawTestCase		(void);
649 	virtual	void					initPrograms		(vk::SourceCollections& programCollection) const;
650 	virtual void					initShaderSources	(void);
651 	virtual void					checkSupport		(Context& context) const;
652 	virtual TestInstance*			createInstance		(Context& context) const;
653 
654 private:
655 	T													m_data;
656 	std::string											m_vertShaderSource;
657 	std::string											m_fragShaderSource;
658 };
659 
660 template<typename T>
DrawTestCase(tcu::TestContext & context,const char * name,const char * desc,const T data)661 DrawTestCase<T>::DrawTestCase (tcu::TestContext& context, const char* name, const char* desc, const T data)
662 	: vkt::TestCase	(context, name, desc)
663 	, m_data		(data)
664 {
665 	initShaderSources();
666 }
667 
668 template<typename T>
~DrawTestCase(void)669 DrawTestCase<T>::~DrawTestCase	(void)
670 {
671 }
672 
673 template<typename T>
initPrograms(vk::SourceCollections & programCollection) const674 void DrawTestCase<T>::initPrograms (vk::SourceCollections& programCollection) const
675 {
676 	programCollection.glslSources.add("vert") << glu::VertexSource(m_vertShaderSource);
677 	programCollection.glslSources.add("frag") << glu::FragmentSource(m_fragShaderSource);
678 }
679 
680 template<typename T>
checkSupport(Context & context) const681 void DrawTestCase<T>::checkSupport (Context& context) const
682 {
683 	if (m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY ||
684 		m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY ||
685 		m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY ||
686 		m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY)
687 	{
688 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
689 	}
690 
691 #ifndef CTS_USES_VULKANSC
692 	if (m_data.groupParams.useDynamicRendering)
693 		context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
694 
695 	if (m_data.topology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN &&
696 		context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
697 		!context.getPortabilitySubsetFeatures().triangleFans)
698 	{
699 		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
700 	}
701 #endif // CTS_USES_VULKANSC
702 }
703 
704 template<typename T>
initShaderSources(void)705 void DrawTestCase<T>::initShaderSources (void)
706 {
707 	std::stringstream vertShader;
708 	vertShader	<< "#version 430\n"
709 				<< "layout(location = 0) in vec4 in_position;\n"
710 				<< "layout(location = 1) in vec4 in_color;\n"
711 				<< "layout(location = 0) out vec4 out_color;\n"
712 
713 				<< "out gl_PerVertex {\n"
714 				<< "    vec4  gl_Position;\n"
715 				<< "    float gl_PointSize;\n"
716 				<< "};\n"
717 				<< "void main() {\n"
718 				<< "    gl_PointSize = 1.0;\n"
719 				<< "    gl_Position  = in_position;\n"
720 				<< "    out_color    = in_color;\n"
721 				<< "}\n";
722 
723 	m_vertShaderSource = vertShader.str();
724 
725 	std::stringstream fragShader;
726 	fragShader	<< "#version 430\n"
727 				<< "layout(location = 0) in vec4 in_color;\n"
728 				<< "layout(location = 0) out vec4 out_color;\n"
729 				<< "void main()\n"
730 				<< "{\n"
731 				<< "    out_color = in_color;\n"
732 				<< "}\n";
733 
734 	m_fragShaderSource = fragShader.str();
735 }
736 
737 template<typename T>
createInstance(Context & context) const738 TestInstance* DrawTestCase<T>::createInstance (Context& context) const
739 {
740 	return new DrawTestInstance<T>(context, m_data);
741 }
742 
743 // Specialized cases
744 template<>
generateDrawData(void)745 void DrawTestInstance<DrawParams>::generateDrawData (void)
746 {
747 	de::Random		rnd			(SEED ^ m_data.params.firstVertex ^ m_data.params.vertexCount);
748 
749 	const deUint32	vectorSize	= m_data.params.firstVertex + m_data.params.vertexCount;
750 
751 	// Initialize the vector
752 	m_data.vertices = std::vector<PositionColorVertex>(vectorSize, PositionColorVertex(tcu::Vec4(0.0, 0.0, 0.0, 0.0), tcu::Vec4(0.0, 0.0, 0.0, 0.0)));
753 
754 	// Fill only the used indexes
755 	for (deUint32 vertexIdx = m_data.params.firstVertex; vertexIdx < vectorSize; ++vertexIdx)
756 	{
757 		const float f0 = rnd.getFloat(-1.0f, 1.0f);
758 		const float f1 = rnd.getFloat(-1.0f, 1.0f);
759 
760 		m_data.vertices[vertexIdx] = PositionColorVertex(
761 			tcu::Vec4(f0, f1, 1.0f, 1.0f),	// Coord
762 			tcu::randomVec4(rnd));			// Color
763 	}
764 }
765 
766 template<>
draw(vk::VkCommandBuffer cmdBuffer,vk::VkBuffer,vk::VkDeviceSize)767 void DrawTestInstance<DrawParams>::draw(vk::VkCommandBuffer cmdBuffer, vk::VkBuffer, vk::VkDeviceSize)
768 {
769 	m_vk.cmdDraw(cmdBuffer, m_data.params.vertexCount, m_data.params.instanceCount, m_data.params.firstVertex, m_data.params.firstInstance);
770 }
771 
772 template<>
iterate(void)773 tcu::TestStatus DrawTestInstance<DrawParams>::iterate (void)
774 {
775 	tcu::TestLog			&log				= m_context.getTestContext().getLog();
776 	const vk::VkQueue		queue				= m_context.getUniversalQueue();
777 	const vk::VkDevice		device				= m_context.getDevice();
778 	const vk::VkDeviceSize	vertexBufferOffset	= 0;
779 	const vk::VkBuffer		vertexBuffer		= m_vertexBuffer->object();
780 
781 #ifndef CTS_USES_VULKANSC
782 	if (m_data.groupParams.useSecondaryCmdBuffer)
783 	{
784 		// record secondary command buffer
785 		if (m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
786 		{
787 			beginSecondaryCmdBuffer(m_vk, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
788 			beginDynamicRender(*m_secCmdBuffer);
789 		}
790 		else
791 			beginSecondaryCmdBuffer(m_vk);
792 
793 		m_vk.cmdBindVertexBuffers(*m_secCmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
794 		m_vk.cmdBindPipeline(*m_secCmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
795 		draw(*m_secCmdBuffer);
796 
797 		if (m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
798 			endDynamicRender(*m_secCmdBuffer);
799 
800 		endCommandBuffer(m_vk, *m_secCmdBuffer);
801 
802 		// record primary command buffer
803 		beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
804 
805 		preRenderBarriers();
806 
807 		if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
808 			beginDynamicRender(*m_cmdBuffer, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
809 
810 		m_vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
811 
812 		if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
813 			endDynamicRender(*m_cmdBuffer);
814 
815 		endCommandBuffer(m_vk, *m_cmdBuffer);
816 	}
817 	else if(m_data.groupParams.useDynamicRendering)
818 	{
819 		beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
820 		preRenderBarriers();
821 		beginDynamicRender(*m_cmdBuffer);
822 
823 		m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
824 		m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
825 		draw(*m_cmdBuffer);
826 
827 		endDynamicRender(*m_cmdBuffer);
828 		endCommandBuffer(m_vk, *m_cmdBuffer);
829 	}
830 #endif // CTS_USES_VULKANSC
831 
832 	if (!m_data.groupParams.useDynamicRendering)
833 	{
834 		beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
835 		preRenderBarriers();
836 		beginRenderPass(*m_cmdBuffer);
837 
838 		m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
839 		m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
840 		draw(*m_cmdBuffer);
841 
842 		endRenderPass(*m_cmdBuffer);
843 		endCommandBuffer(m_vk, *m_cmdBuffer);
844 	}
845 
846 	submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
847 
848 	// Validation
849 	tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
850 	tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
851 
852 	std::vector<tcu::Vec4>	vertices;
853 	std::vector<tcu::Vec4>	colors;
854 
855 	for (std::vector<PositionColorVertex>::const_iterator vertex = m_data.vertices.begin() + m_data.params.firstVertex; vertex != m_data.vertices.end(); ++vertex)
856 	{
857 		vertices.push_back(vertex->position);
858 		colors.push_back(vertex->color);
859 	}
860 	generateRefImage(refImage.getAccess(), vertices, colors);
861 
862 	const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
863 	const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
864 		vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
865 
866 	qpTestResult res = QP_TEST_RESULT_PASS;
867 
868 	if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
869 		res = QP_TEST_RESULT_FAIL;
870 
871 	return tcu::TestStatus(res, qpGetTestResultName(res));
872 }
873 
874 template<>
generateDrawData(void)875 void DrawTestInstance<DrawIndexedParams>::generateDrawData (void)
876 {
877 	de::Random		rnd			(SEED ^ m_data.params.firstIndex ^ m_data.params.indexCount);
878 	const deUint32	indexSize	= m_data.params.firstIndex + m_data.params.indexCount;
879 
880 	// Initialize the vector with zeros
881 	m_data.indexes = std::vector<deUint32>(indexSize, 0);
882 
883 	deUint32		highestIndex	= 0;	// Store to highest index to calculate the vertices size
884 	// Fill the indexes from firstIndex
885 	for (deUint32 idx = 0; idx < m_data.params.indexCount; ++idx)
886 	{
887 		deUint32	vertexIdx	= rnd.getInt(m_data.params.vertexOffset, INDEX_LIMIT);
888 		highestIndex = (vertexIdx > highestIndex) ? vertexIdx : highestIndex;
889 
890 		m_data.indexes[m_data.params.firstIndex + idx]	= vertexIdx;
891 	}
892 
893 	// Fill up the vertex coordinates with zeros until the highestIndex including the vertexOffset
894 	m_data.vertices = std::vector<PositionColorVertex>(m_data.params.vertexOffset + highestIndex + 1, PositionColorVertex(tcu::Vec4(0.0, 0.0, 0.0, 0.0), tcu::Vec4(0.0, 0.0, 0.0, 0.0)));
895 
896 	// Generate random vertex only where you have index pointing at
897 	for (std::vector<deUint32>::const_iterator indexIt = m_data.indexes.begin() + m_data.params.firstIndex; indexIt != m_data.indexes.end(); ++indexIt)
898 	{
899 		// Get iterator to the vertex position  with the vertexOffset
900 		std::vector<PositionColorVertex>::iterator vertexIt = m_data.vertices.begin() + m_data.params.vertexOffset + *indexIt;
901 
902 		tcu::VecAccess<float, 4, 4>	positionAccess = vertexIt->position.xyzw();
903 		const float f0 = rnd.getFloat(-1.0f, 1.0f);
904 		const float f1 = rnd.getFloat(-1.0f, 1.0f);
905 		positionAccess = tcu::Vec4(f0, f1, 1.0f, 1.0f);
906 
907 		tcu::VecAccess<float, 4, 4>	colorAccess = vertexIt->color.xyzw();
908 		colorAccess = tcu::randomVec4(rnd);
909 	}
910 }
911 
912 template<>
draw(vk::VkCommandBuffer cmdBuffer,vk::VkBuffer,vk::VkDeviceSize)913 void DrawTestInstance<DrawIndexedParams>::draw(vk::VkCommandBuffer cmdBuffer, vk::VkBuffer, vk::VkDeviceSize)
914 {
915 	m_vk.cmdDrawIndexed(cmdBuffer, m_data.params.indexCount, m_data.params.instanceCount, m_data.params.firstIndex, m_data.params.vertexOffset, m_data.params.firstInstance);
916 }
917 
918 template<>
iterate(void)919 tcu::TestStatus DrawTestInstance<DrawIndexedParams>::iterate (void)
920 {
921 	tcu::TestLog				&log				= m_context.getTestContext().getLog();
922 	const vk::DeviceInterface&	vk					= m_context.getDeviceInterface();
923 	const vk::VkDevice			vkDevice			= m_context.getDevice();
924 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
925 	const vk::VkQueue			queue				= m_context.getUniversalQueue();
926 	vk::Allocator&				allocator			= m_context.getDefaultAllocator();
927 	const vk::VkDeviceSize		vertexBufferOffset	= 0;
928 	const vk::VkBuffer			vertexBuffer		= m_vertexBuffer->object();
929 	const deUint32				bufferSize			= (deUint32)(m_data.indexes.size() * sizeof(deUint32));
930 
931 	const vk::VkBufferCreateInfo	bufferCreateInfo =
932 	{
933 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
934 		DE_NULL,									// const void*			pNext;
935 		0u,											// VkBufferCreateFlags	flags;
936 		bufferSize,									// VkDeviceSize			size;
937 		vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,		// VkBufferUsageFlags	usage;
938 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
939 		1u,											// deUint32				queueFamilyIndexCount;
940 		&queueFamilyIndex,							// const deUint32*		pQueueFamilyIndices;
941 	};
942 
943 	vk::Move<vk::VkBuffer>			indexBuffer = createBuffer(vk, vkDevice, &bufferCreateInfo);
944 	de::MovePtr<vk::Allocation>		indexAlloc;
945 
946 	indexAlloc = allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indexBuffer), vk::MemoryRequirement::HostVisible);
947 	VK_CHECK(vk.bindBufferMemory(vkDevice, *indexBuffer, indexAlloc->getMemory(), indexAlloc->getOffset()));
948 
949 	deMemcpy(indexAlloc->getHostPtr(), &(m_data.indexes[0]), bufferSize);
950 
951 	vk::flushAlloc(m_vk, vkDevice, *indexAlloc);
952 
953 #ifndef CTS_USES_VULKANSC
954 	if (m_data.groupParams.useSecondaryCmdBuffer)
955 	{
956 		// record secondary command buffer
957 		if (m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
958 		{
959 			beginSecondaryCmdBuffer(m_vk, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
960 			beginDynamicRender(*m_secCmdBuffer);
961 		}
962 		else
963 			beginSecondaryCmdBuffer(m_vk);
964 
965 		m_vk.cmdBindPipeline(*m_secCmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
966 		m_vk.cmdBindVertexBuffers(*m_secCmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
967 		m_vk.cmdBindIndexBuffer(*m_secCmdBuffer, *indexBuffer, 0u, m_data.indexType);
968 		draw(*m_secCmdBuffer);
969 
970 		if (m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
971 			endDynamicRender(*m_secCmdBuffer);
972 
973 		endCommandBuffer(m_vk, *m_secCmdBuffer);
974 
975 		// record primary command buffer
976 		beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
977 
978 		preRenderBarriers();
979 
980 		if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
981 			beginDynamicRender(*m_cmdBuffer, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
982 
983 		m_vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
984 
985 		if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
986 			endDynamicRender(*m_cmdBuffer);
987 
988 		endCommandBuffer(m_vk, *m_cmdBuffer);
989 	}
990 	else if (m_data.groupParams.useDynamicRendering)
991 	{
992 		beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
993 		preRenderBarriers();
994 		beginDynamicRender(*m_cmdBuffer);
995 
996 		m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
997 		m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
998 		m_vk.cmdBindIndexBuffer(*m_cmdBuffer, *indexBuffer, 0u, m_data.indexType);
999 		draw(*m_cmdBuffer);
1000 
1001 		endDynamicRender(*m_cmdBuffer);
1002 		endCommandBuffer(m_vk, *m_cmdBuffer);
1003 	}
1004 #endif // CTS_USES_VULKANSC
1005 
1006 	if (!m_data.groupParams.useDynamicRendering)
1007 	{
1008 		beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
1009 		preRenderBarriers();
1010 		beginRenderPass(*m_cmdBuffer);
1011 
1012 		m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1013 		m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1014 		m_vk.cmdBindIndexBuffer(*m_cmdBuffer, *indexBuffer, 0u, m_data.indexType);
1015 		draw(*m_cmdBuffer);
1016 
1017 		endRenderPass(*m_cmdBuffer);
1018 		endCommandBuffer(m_vk, *m_cmdBuffer);
1019 	}
1020 
1021 	submitCommandsAndWait(m_vk, vkDevice, queue, m_cmdBuffer.get());
1022 
1023 	// Validation
1024 	tcu::TextureLevel	refImage	(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
1025 	tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1026 
1027 	std::vector<tcu::Vec4>	vertices;
1028 	std::vector<tcu::Vec4>	colors;
1029 
1030 	for (std::vector<deUint32>::const_iterator it = m_data.indexes.begin() + m_data.params.firstIndex; it != m_data.indexes.end(); ++it)
1031 	{
1032 		deUint32 idx = m_data.params.vertexOffset + *it;
1033 		vertices.push_back(m_data.vertices[idx].position);
1034 		colors.push_back(m_data.vertices[idx].color);
1035 	}
1036 	generateRefImage(refImage.getAccess(), vertices, colors);
1037 
1038 	const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
1039 	const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
1040 		vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
1041 
1042 	qpTestResult res = QP_TEST_RESULT_PASS;
1043 
1044 	if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
1045 		res = QP_TEST_RESULT_FAIL;
1046 
1047 	return tcu::TestStatus(res, qpGetTestResultName(res));
1048 }
1049 
1050 template<>
generateDrawData(void)1051 void DrawTestInstance<DrawIndirectParams>::generateDrawData (void)
1052 {
1053 	de::Random	rnd(SEED ^ m_data.commands[0].vertexCount ^ m_data.commands[0].firstVertex);
1054 
1055 	deUint32 lastIndex	= 0;
1056 
1057 	// Find the interval which will be used
1058 	for (std::vector<vk::VkDrawIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
1059 	{
1060 		const deUint32	index = it->firstVertex + it->vertexCount;
1061 		lastIndex	= (index > lastIndex) ? index : lastIndex;
1062 	}
1063 
1064 	// Initialize with zeros
1065 	m_data.vertices = std::vector<PositionColorVertex>(lastIndex, PositionColorVertex(tcu::Vec4(0.0, 0.0, 0.0, 0.0), tcu::Vec4(0.0, 0.0, 0.0, 0.0)));
1066 
1067 	// Generate random vertices only where necessary
1068 	for (std::vector<vk::VkDrawIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
1069 	{
1070 		std::vector<PositionColorVertex>::iterator vertexStart = m_data.vertices.begin() + it->firstVertex;
1071 
1072 		for (deUint32 idx = 0; idx < it->vertexCount; ++idx)
1073 		{
1074 			std::vector<PositionColorVertex>::iterator vertexIt = vertexStart + idx;
1075 
1076 			tcu::VecAccess<float, 4, 4> positionAccess = vertexIt->position.xyzw();
1077 			const float f0 = rnd.getFloat(-1.0f, 1.0f);
1078 			const float f1 = rnd.getFloat(-1.0f, 1.0f);
1079 			positionAccess = tcu::Vec4(f0, f1, 1.0f, 1.0f);
1080 
1081 			tcu::VecAccess<float, 4, 4> colorAccess = vertexIt->color.xyzw();
1082 			colorAccess = tcu::randomVec4(rnd);
1083 		}
1084 	}
1085 }
1086 
1087 template<>
draw(vk::VkCommandBuffer cmdBuffer,vk::VkBuffer indirectBuffer,vk::VkDeviceSize indirectOffset)1088 void DrawTestInstance<DrawIndirectParams>::draw(vk::VkCommandBuffer cmdBuffer, vk::VkBuffer indirectBuffer, vk::VkDeviceSize indirectOffset)
1089 {
1090 	const vk::VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
1091 
1092 	// If multiDrawIndirect not supported execute single calls
1093 	if (m_data.commands.size() > 1 && !(features.multiDrawIndirect))
1094 	{
1095 		for (deUint32 cmdIdx = 0; cmdIdx < m_data.commands.size(); ++cmdIdx)
1096 		{
1097 			const deUint32	offset = (deUint32)(indirectOffset + cmdIdx * sizeof(vk::VkDrawIndirectCommand));
1098 			m_vk.cmdDrawIndirect(cmdBuffer, indirectBuffer, offset, 1, sizeof(vk::VkDrawIndirectCommand));
1099 		}
1100 	}
1101 	else
1102 	{
1103 		m_vk.cmdDrawIndirect(cmdBuffer, indirectBuffer, indirectOffset, (deUint32)m_data.commands.size(), sizeof(vk::VkDrawIndirectCommand));
1104 	}
1105 }
1106 
1107 template<>
iterate(void)1108 tcu::TestStatus DrawTestInstance<DrawIndirectParams>::iterate (void)
1109 {
1110 	tcu::TestLog						&log				= m_context.getTestContext().getLog();
1111 	const vk::DeviceInterface&			vk					= m_context.getDeviceInterface();
1112 	const vk::VkDevice					vkDevice			= m_context.getDevice();
1113 	vk::Allocator&						allocator			= m_context.getDefaultAllocator();
1114 	const vk::VkQueue					queue				= m_context.getUniversalQueue();
1115 	const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1116 	const vk::VkDeviceSize				vertexBufferOffset	= 0;
1117 	const vk::VkBuffer					vertexBuffer		= m_vertexBuffer->object();
1118 	vk::Move<vk::VkBuffer>				indirectBuffer;
1119 	de::MovePtr<vk::Allocation>			indirectAlloc;
1120 
1121 	{
1122 		const vk::VkDeviceSize	indirectInfoSize	= m_data.commands.size() * sizeof(vk::VkDrawIndirectCommand);
1123 
1124 		const vk::VkBufferCreateInfo	indirectCreateInfo =
1125 		{
1126 			vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
1127 			DE_NULL,									// const void*			pNext;
1128 			0u,											// VkBufferCreateFlags	flags;
1129 			indirectInfoSize,							// VkDeviceSize			size;
1130 			vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT,	// VkBufferUsageFlags	usage;
1131 			vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
1132 			1u,											// deUint32				queueFamilyIndexCount;
1133 			&queueFamilyIndex,							// const deUint32*		pQueueFamilyIndices;
1134 		};
1135 
1136 		indirectBuffer	= createBuffer(vk, vkDevice, &indirectCreateInfo);
1137 		indirectAlloc	= allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indirectBuffer), vk::MemoryRequirement::HostVisible);
1138 		VK_CHECK(vk.bindBufferMemory(vkDevice, *indirectBuffer, indirectAlloc->getMemory(), indirectAlloc->getOffset()));
1139 
1140 		deMemcpy(indirectAlloc->getHostPtr(), &(m_data.commands[0]), (size_t)indirectInfoSize);
1141 
1142 		vk::flushAlloc(m_vk, vkDevice, *indirectAlloc);
1143 	}
1144 
1145 #ifndef CTS_USES_VULKANSC
1146 	if (m_data.groupParams.useSecondaryCmdBuffer)
1147 	{
1148 		// record secondary command buffer
1149 		if (m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1150 		{
1151 			beginSecondaryCmdBuffer(m_vk, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
1152 			beginDynamicRender(*m_secCmdBuffer);
1153 		}
1154 		else
1155 			beginSecondaryCmdBuffer(m_vk);
1156 
1157 		m_vk.cmdBindVertexBuffers(*m_secCmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1158 		m_vk.cmdBindPipeline(*m_secCmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1159 		draw(*m_secCmdBuffer, *indirectBuffer, indirectAlloc->getOffset());
1160 
1161 		if (m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1162 			endDynamicRender(*m_secCmdBuffer);
1163 
1164 		endCommandBuffer(m_vk, *m_secCmdBuffer);
1165 
1166 		// record primary command buffer
1167 		beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
1168 
1169 		preRenderBarriers();
1170 
1171 		if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1172 			beginDynamicRender(*m_cmdBuffer, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
1173 
1174 		m_vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
1175 
1176 		if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1177 			endDynamicRender(*m_cmdBuffer);
1178 
1179 		endCommandBuffer(m_vk, *m_cmdBuffer);
1180 	}
1181 	else if (m_data.groupParams.useDynamicRendering)
1182 	{
1183 		beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
1184 		preRenderBarriers();
1185 		beginDynamicRender(*m_cmdBuffer);
1186 
1187 		m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1188 		m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1189 		draw(*m_cmdBuffer, *indirectBuffer, indirectAlloc->getOffset());
1190 
1191 		endDynamicRender(*m_cmdBuffer);
1192 		endCommandBuffer(m_vk, *m_cmdBuffer);
1193 	}
1194 #endif // CTS_USES_VULKANSC
1195 
1196 	if (!m_data.groupParams.useDynamicRendering)
1197 	{
1198 		beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
1199 		preRenderBarriers();
1200 		beginRenderPass(*m_cmdBuffer);
1201 
1202 		m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1203 		m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1204 		draw(*m_cmdBuffer, *indirectBuffer, indirectAlloc->getOffset());
1205 
1206 		endRenderPass(*m_cmdBuffer);
1207 		endCommandBuffer(m_vk, *m_cmdBuffer);
1208 	}
1209 
1210 	submitCommandsAndWait(m_vk, vkDevice, queue, m_cmdBuffer.get());
1211 
1212 	// Validation
1213 	tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
1214 	tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1215 
1216 	for (std::vector<vk::VkDrawIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
1217 	{
1218 		std::vector<tcu::Vec4>	vertices;
1219 		std::vector<tcu::Vec4>	colors;
1220 
1221 		std::vector<PositionColorVertex>::const_iterator	firstIt	= m_data.vertices.begin() + it->firstVertex;
1222 		std::vector<PositionColorVertex>::const_iterator	lastIt	= firstIt + it->vertexCount;
1223 
1224 		for (std::vector<PositionColorVertex>::const_iterator vertex = firstIt; vertex != lastIt; ++vertex)
1225 		{
1226 			vertices.push_back(vertex->position);
1227 			colors.push_back(vertex->color);
1228 		}
1229 		generateRefImage(refImage.getAccess(), vertices, colors);
1230 	}
1231 
1232 	const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
1233 	const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
1234 		vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
1235 
1236 	qpTestResult res = QP_TEST_RESULT_PASS;
1237 
1238 	if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
1239 		res = QP_TEST_RESULT_FAIL;
1240 
1241 	return tcu::TestStatus(res, qpGetTestResultName(res));
1242 }
1243 
1244 template<>
generateDrawData(void)1245 void DrawTestInstance<DrawIndexedIndirectParams>::generateDrawData (void)
1246 {
1247 	de::Random		rnd			(SEED ^ m_data.commands[0].firstIndex ^ m_data.commands[0].indexCount);
1248 
1249 	deUint32		lastIndex	= 0;
1250 
1251 	// Get the maximum range of indexes
1252 	for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
1253 	{
1254 		const deUint32	index		= it->firstIndex + it->indexCount;
1255 						lastIndex	= (index > lastIndex) ? index : lastIndex;
1256 	}
1257 
1258 	// Initialize the vector with zeros
1259 	m_data.indexes = std::vector<deUint32>(lastIndex, 0);
1260 
1261 	deUint32	highestIndex	= 0;
1262 
1263 	// Generate random indexes for the ranges
1264 	for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator it = m_data.commands.begin(); it != m_data.commands.end(); ++it)
1265 	{
1266 		for (deUint32 idx = 0; idx < it->indexCount; ++idx)
1267 		{
1268 			const deUint32	vertexIdx	= rnd.getInt(it->vertexOffset, INDEX_LIMIT);
1269 			const deUint32	maxIndex	= vertexIdx + it->vertexOffset;
1270 
1271 			highestIndex = (maxIndex > highestIndex) ? maxIndex : highestIndex;
1272 			m_data.indexes[it->firstIndex + idx] = vertexIdx;
1273 		}
1274 	}
1275 
1276 	// Initialize the vertex vector
1277 	m_data.vertices = std::vector<PositionColorVertex>(highestIndex + 1, PositionColorVertex(tcu::Vec4(0.0, 0.0, 0.0, 0.0), tcu::Vec4(0.0, 0.0, 0.0, 0.0)));
1278 
1279 	// Generate random vertices in the used locations
1280 	for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator cmdIt = m_data.commands.begin(); cmdIt != m_data.commands.end(); ++cmdIt)
1281 	{
1282 		deUint32	firstIdx	= cmdIt->firstIndex;
1283 		deUint32	lastIdx		= firstIdx + cmdIt->indexCount;
1284 
1285 		for (deUint32 idx = firstIdx; idx < lastIdx; ++idx)
1286 		{
1287 			std::vector<PositionColorVertex>::iterator	vertexIt = m_data.vertices.begin() + cmdIt->vertexOffset + m_data.indexes[idx];
1288 
1289 			tcu::VecAccess<float, 4, 4> positionAccess = vertexIt->position.xyzw();
1290 			const float f0 = rnd.getFloat(-1.0f, 1.0f);
1291 			const float f1 = rnd.getFloat(-1.0f, 1.0f);
1292 			positionAccess = tcu::Vec4(f0, f1, 1.0f, 1.0f);
1293 
1294 			tcu::VecAccess<float, 4, 4> colorAccess = vertexIt->color.xyzw();
1295 			colorAccess = tcu::randomVec4(rnd);
1296 		}
1297 	}
1298 }
1299 
1300 template<>
draw(vk::VkCommandBuffer cmdBuffer,vk::VkBuffer indirectBuffer,vk::VkDeviceSize indirectOffset)1301 void DrawTestInstance<DrawIndexedIndirectParams>::draw(vk::VkCommandBuffer cmdBuffer, vk::VkBuffer indirectBuffer, vk::VkDeviceSize indirectOffset)
1302 {
1303 	const vk::VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
1304 
1305 	// If multiDrawIndirect not supported execute single calls
1306 	if (m_data.commands.size() > 1 && !(features.multiDrawIndirect))
1307 	{
1308 		for (deUint32 cmdIdx = 0; cmdIdx < m_data.commands.size(); ++cmdIdx)
1309 		{
1310 			const deUint32	offset = (deUint32)(indirectOffset + cmdIdx * sizeof(vk::VkDrawIndexedIndirectCommand));
1311 			m_vk.cmdDrawIndexedIndirect(cmdBuffer, indirectBuffer, offset, 1, sizeof(vk::VkDrawIndexedIndirectCommand));
1312 		}
1313 	}
1314 	else
1315 	{
1316 		m_vk.cmdDrawIndexedIndirect(cmdBuffer, indirectBuffer, indirectOffset, (deUint32)m_data.commands.size(), sizeof(vk::VkDrawIndexedIndirectCommand));
1317 	}
1318 }
1319 
1320 template<>
iterate(void)1321 tcu::TestStatus DrawTestInstance<DrawIndexedIndirectParams>::iterate (void)
1322 {
1323 	tcu::TestLog						&log				= m_context.getTestContext().getLog();
1324 	const vk::DeviceInterface&			vk					= m_context.getDeviceInterface();
1325 	const vk::VkDevice					vkDevice			= m_context.getDevice();
1326 	const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1327 	const vk::VkQueue					queue				= m_context.getUniversalQueue();
1328 	vk::Allocator&						allocator			= m_context.getDefaultAllocator();
1329 	const vk::VkDeviceSize				vertexBufferOffset	= 0;
1330 	const vk::VkBuffer					vertexBuffer		= m_vertexBuffer->object();
1331 	vk::Move<vk::VkBuffer>				indirectBuffer;
1332 	de::MovePtr<vk::Allocation>			indirectAlloc;
1333 
1334 	{
1335 		const vk::VkDeviceSize	indirectInfoSize	= m_data.commands.size() * sizeof(vk::VkDrawIndexedIndirectCommand);
1336 
1337 		const vk::VkBufferCreateInfo	indirectCreateInfo =
1338 		{
1339 			vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
1340 			DE_NULL,									// const void*			pNext;
1341 			0u,											// VkBufferCreateFlags	flags;
1342 			indirectInfoSize,							// VkDeviceSize			size;
1343 			vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT,	// VkBufferUsageFlags	usage;
1344 			vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
1345 			1u,											// deUint32				queueFamilyIndexCount;
1346 			&queueFamilyIndex,							// const deUint32*		pQueueFamilyIndices;
1347 		};
1348 
1349 		indirectBuffer	= createBuffer(vk, vkDevice, &indirectCreateInfo);
1350 		indirectAlloc	= allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indirectBuffer), vk::MemoryRequirement::HostVisible);
1351 		VK_CHECK(vk.bindBufferMemory(vkDevice, *indirectBuffer, indirectAlloc->getMemory(), indirectAlloc->getOffset()));
1352 
1353 		deMemcpy(indirectAlloc->getHostPtr(), &(m_data.commands[0]), (size_t)indirectInfoSize);
1354 
1355 		vk::flushAlloc(m_vk, vkDevice, *indirectAlloc);
1356 	}
1357 
1358 	const deUint32	bufferSize = (deUint32)(m_data.indexes.size() * sizeof(deUint32));
1359 
1360 	vk::Move<vk::VkBuffer>			indexBuffer;
1361 
1362 	const vk::VkBufferCreateInfo	bufferCreateInfo =
1363 	{
1364 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
1365 		DE_NULL,									// const void*			pNext;
1366 		0u,											// VkBufferCreateFlags	flags;
1367 		bufferSize,									// VkDeviceSize			size;
1368 		vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,		// VkBufferUsageFlags	usage;
1369 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
1370 		1u,											// deUint32				queueFamilyIndexCount;
1371 		&queueFamilyIndex,							// const deUint32*		pQueueFamilyIndices;
1372 	};
1373 
1374 	indexBuffer = createBuffer(vk, vkDevice, &bufferCreateInfo);
1375 
1376 	de::MovePtr<vk::Allocation>	indexAlloc;
1377 
1378 	indexAlloc = allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *indexBuffer), vk::MemoryRequirement::HostVisible);
1379 	VK_CHECK(vk.bindBufferMemory(vkDevice, *indexBuffer, indexAlloc->getMemory(), indexAlloc->getOffset()));
1380 
1381 	deMemcpy(indexAlloc->getHostPtr(), &(m_data.indexes[0]), bufferSize);
1382 
1383 	vk::flushAlloc(m_vk, vkDevice, *indexAlloc);
1384 
1385 #ifndef CTS_USES_VULKANSC
1386 	if (m_data.groupParams.useSecondaryCmdBuffer)
1387 	{
1388 		// record secondary command buffer
1389 		if (m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1390 		{
1391 			beginSecondaryCmdBuffer(m_vk, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
1392 			beginDynamicRender(*m_secCmdBuffer);
1393 		}
1394 		else
1395 			beginSecondaryCmdBuffer(m_vk);
1396 
1397 		m_vk.cmdBindPipeline(*m_secCmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1398 		m_vk.cmdBindVertexBuffers(*m_secCmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1399 		m_vk.cmdBindIndexBuffer(*m_secCmdBuffer, *indexBuffer, 0u, m_data.indexType);
1400 		draw(*m_secCmdBuffer, *indirectBuffer, indirectAlloc->getOffset());
1401 
1402 		if (m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1403 			endDynamicRender(*m_secCmdBuffer);
1404 
1405 		endCommandBuffer(m_vk, *m_secCmdBuffer);
1406 
1407 		// record primary command buffer
1408 		beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
1409 
1410 		preRenderBarriers();
1411 
1412 		if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1413 			beginDynamicRender(*m_cmdBuffer, vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
1414 
1415 		m_vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
1416 
1417 		if (!m_data.groupParams.secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1418 			endDynamicRender(*m_cmdBuffer);
1419 
1420 		endCommandBuffer(m_vk, *m_cmdBuffer);
1421 	}
1422 	else if (m_data.groupParams.useDynamicRendering)
1423 	{
1424 		beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
1425 		preRenderBarriers();
1426 		beginDynamicRender(*m_cmdBuffer);
1427 
1428 		m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1429 		m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1430 		m_vk.cmdBindIndexBuffer(*m_cmdBuffer, *indexBuffer, 0u, m_data.indexType);
1431 		draw(*m_cmdBuffer, *indirectBuffer, indirectAlloc->getOffset());
1432 
1433 		endDynamicRender(*m_cmdBuffer);
1434 		endCommandBuffer(m_vk, *m_cmdBuffer);
1435 	}
1436 #endif // CTS_USES_VULKANSC
1437 
1438 	if (!m_data.groupParams.useDynamicRendering)
1439 	{
1440 		beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
1441 		preRenderBarriers();
1442 		beginRenderPass(*m_cmdBuffer);
1443 
1444 		m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1445 		m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1446 		m_vk.cmdBindIndexBuffer(*m_cmdBuffer, *indexBuffer, 0u, m_data.indexType);
1447 		draw(*m_cmdBuffer, *indirectBuffer, indirectAlloc->getOffset());
1448 
1449 		endRenderPass(*m_cmdBuffer);
1450 		endCommandBuffer(m_vk, *m_cmdBuffer);
1451 	}
1452 
1453 	submitCommandsAndWait(m_vk, vkDevice, queue, m_cmdBuffer.get());
1454 
1455 	// Validation
1456 	tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
1457 	tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1458 
1459 	for (std::vector<vk::VkDrawIndexedIndirectCommand>::const_iterator cmd = m_data.commands.begin(); cmd != m_data.commands.end(); ++cmd)
1460 	{
1461 		std::vector<tcu::Vec4>	vertices;
1462 		std::vector<tcu::Vec4>	colors;
1463 
1464 		for (deUint32 idx = 0; idx < cmd->indexCount; ++idx)
1465 		{
1466 			const deUint32 vertexIndex = cmd->vertexOffset + m_data.indexes[cmd->firstIndex + idx];
1467 			vertices.push_back(m_data.vertices[vertexIndex].position);
1468 			colors.push_back(m_data.vertices[vertexIndex].color);
1469 		}
1470 		generateRefImage(refImage.getAccess(), vertices, colors);
1471 	}
1472 
1473 	const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
1474 	const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
1475 		vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
1476 
1477 	qpTestResult res = QP_TEST_RESULT_PASS;
1478 
1479 	if (!imageCompare(log, refImage.getAccess(), renderedFrame, m_data.topology))
1480 		res = QP_TEST_RESULT_FAIL;
1481 
1482 	return tcu::TestStatus(res, qpGetTestResultName(res));
1483 }
1484 
1485 typedef DrawTestCase<DrawParams>				DrawCase;
1486 typedef DrawTestCase<DrawIndexedParams>			IndexedCase;
1487 typedef DrawTestCase<DrawIndirectParams>		IndirectCase;
1488 typedef DrawTestCase<DrawIndexedIndirectParams>	IndexedIndirectCase;
1489 
1490 struct TestCaseParams
1491 {
1492 	const DrawCommandType			command;
1493 	const vk::VkPrimitiveTopology	topology;
1494 	const SharedGroupParams			groupParams;
1495 
TestCaseParamsvkt::Draw::__anona9f947520111::TestCaseParams1496 	TestCaseParams (const DrawCommandType cmd, const vk::VkPrimitiveTopology top, const SharedGroupParams gParams)
1497 		: command		(cmd)
1498 		, topology		(top)
1499 		, groupParams	(gParams)
1500 	{}
1501 };
1502 
1503 }	// anonymous
1504 
populateSubGroup(tcu::TestCaseGroup * testGroup,const TestCaseParams caseParams)1505 void populateSubGroup (tcu::TestCaseGroup* testGroup, const TestCaseParams caseParams)
1506 {
1507 	de::Random						rnd						(SEED ^ deStringHash(testGroup->getName()));
1508 	tcu::TestContext&				testCtx					= testGroup->getTestContext();
1509 	const DrawCommandType			command					= caseParams.command;
1510 	const vk::VkPrimitiveTopology	topology				= caseParams.topology;
1511 	const SharedGroupParams			groupParams				= caseParams.groupParams;
1512 	const deUint32					primitiveCountArrLength = DE_LENGTH_OF_ARRAY(PRIMITIVE_COUNT);
1513 
1514 	for (deUint32 primitiveCountIdx = 0; primitiveCountIdx < primitiveCountArrLength; ++primitiveCountIdx)
1515 	{
1516 		const deUint32 primitives = PRIMITIVE_COUNT[primitiveCountIdx];
1517 
1518 		// when testing VK_KHR_dynamic_rendering there is no need to duplicate tests for all primitive counts; use just 1 and 45
1519 		if (groupParams->useDynamicRendering && (primitiveCountIdx != 0) && (primitiveCountIdx != primitiveCountArrLength-1))
1520 			continue;
1521 
1522 		deUint32	multiplier	= 1;
1523 		deUint32	offset		= 0;
1524 		// Calculated by Vulkan 23.1
1525 		switch (topology)
1526 		{
1527 			case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:													break;
1528 			case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:						multiplier = 2;				break;
1529 			case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:													break;
1530 			case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:					multiplier = 3;				break;
1531 			case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:												break;
1532 			case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:									offset = 1;	break;
1533 			case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:		multiplier = 4;	offset = 1;	break;
1534 			case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:						offset = 1;	break;
1535 			case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:	multiplier = 6;				break;
1536 			case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:	multiplier = 2;				break;
1537 			default:														DE_FATAL("Unsupported topology.");
1538 		}
1539 
1540 		const deUint32	vertexCount		= multiplier * primitives + offset;
1541 		std::string		name			= de::toString(primitives);
1542 
1543 		switch (command)
1544 		{
1545 			case DRAW_COMMAND_TYPE_DRAW:
1546 			{
1547 				deUint32	firstPrimitive	= rnd.getInt(0, primitives);
1548 				deUint32	firstVertex		= multiplier * firstPrimitive;
1549 				testGroup->addChild(new DrawCase(testCtx, name.c_str(), "vkCmdDraw testcase.",
1550 					DrawParams(topology, groupParams, vertexCount, 1, firstVertex, 0))
1551 				);
1552 				break;
1553 			}
1554 			case DRAW_COMMAND_TYPE_DRAW_INDEXED:
1555 			{
1556 				deUint32	firstIndex			= rnd.getInt(0, OFFSET_LIMIT);
1557 				deUint32	vertexOffset		= rnd.getInt(0, OFFSET_LIMIT);
1558 				testGroup->addChild(new IndexedCase(testCtx, name.c_str(), "vkCmdDrawIndexed testcase.",
1559 					DrawIndexedParams(topology, groupParams, vk::VK_INDEX_TYPE_UINT32, vertexCount, 1, firstIndex, vertexOffset, 0))
1560 				);
1561 				break;
1562 			}
1563 			case DRAW_COMMAND_TYPE_DRAW_INDIRECT:
1564 			{
1565 				deUint32	firstVertex		= rnd.getInt(0, OFFSET_LIMIT);
1566 
1567 				DrawIndirectParams	params	= DrawIndirectParams(topology, groupParams);
1568 
1569 				params.addCommand(vertexCount, 1, 0, 0);
1570 				testGroup->addChild(new IndirectCase(testCtx, (name + "_single_command").c_str(), "vkCmdDrawIndirect testcase.", params));
1571 
1572 				params.addCommand(vertexCount, 1, firstVertex, 0);
1573 				testGroup->addChild(new IndirectCase(testCtx, (name + "_multi_command").c_str(), "vkCmdDrawIndirect testcase.", params));
1574 				break;
1575 			}
1576 			case DRAW_COMMAND_TYPE_DRAW_INDEXED_INDIRECT:
1577 			{
1578 				deUint32	firstIndex		= rnd.getInt(vertexCount, OFFSET_LIMIT);
1579 				deUint32	vertexOffset	= rnd.getInt(vertexCount, OFFSET_LIMIT);
1580 
1581 				DrawIndexedIndirectParams	params	= DrawIndexedIndirectParams(topology, groupParams, vk::VK_INDEX_TYPE_UINT32);
1582 				params.addCommand(vertexCount, 1, 0, 0, 0);
1583 				testGroup->addChild(new IndexedIndirectCase(testCtx, (name + "_single_command").c_str(), "vkCmdDrawIndexedIndirect testcase.", params));
1584 
1585 				params.addCommand(vertexCount, 1, firstIndex, vertexOffset, 0);
1586 				testGroup->addChild(new IndexedIndirectCase(testCtx, (name + "_multi_command").c_str(), "vkCmdDrawIndexedIndirect testcase.", params));
1587 				break;
1588 			}
1589 			default:
1590 				DE_FATAL("Unsupported draw command.");
1591 		}
1592 	}
1593 }
1594 
createDrawTests(tcu::TestCaseGroup * testGroup,const SharedGroupParams groupParams)1595 void createDrawTests(tcu::TestCaseGroup* testGroup, const SharedGroupParams groupParams)
1596 {
1597 	for (deUint32 drawTypeIndex = 0; drawTypeIndex < DRAW_COMMAND_TYPE_DRAW_LAST; ++drawTypeIndex)
1598 	{
1599 		const DrawCommandType			command			(static_cast<DrawCommandType>(drawTypeIndex));
1600 		de::MovePtr<tcu::TestCaseGroup>	topologyGroup	(new tcu::TestCaseGroup(testGroup->getTestContext(), getDrawCommandTypeName(command), "Group for testing a specific draw command."));
1601 
1602 		for (deUint32 topologyIdx = 0; topologyIdx != vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; ++topologyIdx)
1603 		{
1604 			const vk::VkPrimitiveTopology	topology	(static_cast<vk::VkPrimitiveTopology>(topologyIdx));
1605 			const std::string				groupName	(de::toLower(getPrimitiveTopologyName(topology)).substr(22));
1606 
1607 			// reduce number of tests for dynamic rendering cases where secondary command buffer is used
1608 			if (groupParams->useSecondaryCmdBuffer && (topologyIdx % 2u))
1609 				continue;
1610 
1611 			addTestGroup(topologyGroup.get(), groupName, "Testcases with a specific topology.", populateSubGroup, TestCaseParams(command, topology, groupParams));
1612 		}
1613 
1614 		testGroup->addChild(topologyGroup.release());
1615 	}
1616 }
1617 
createBasicDrawTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1618 tcu::TestCaseGroup*	createBasicDrawTests (tcu::TestContext& testCtx, const SharedGroupParams groupParams)
1619 {
1620 	return createTestGroup(testCtx, "basic_draw", "Basic drawing tests", createDrawTests, groupParams);
1621 }
1622 
1623 }	// DrawTests
1624 }	// vkt
1625