• 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 Instanced Draw Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktDrawInstancedTests.hpp"
26 
27 #include <climits>
28 
29 #include "deSharedPtr.hpp"
30 #include "rrRenderer.hpp"
31 #include "tcuImageCompare.hpp"
32 #include "tcuRGBA.hpp"
33 #include "tcuTextureUtil.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vktDrawBufferObjectUtil.hpp"
40 #include "vktDrawCreateInfoUtil.hpp"
41 #include "vktDrawImageObjectUtil.hpp"
42 #include "vktDrawTestCaseUtil.hpp"
43 
44 namespace vkt
45 {
46 namespace Draw
47 {
48 namespace
49 {
50 
51 static const int	QUAD_GRID_SIZE	= 8;
52 static const int	WIDTH			= 128;
53 static const int	HEIGHT			= 128;
54 
55 struct TestParams
56 {
57 	enum DrawFunction
58 	{
59 		FUNCTION_DRAW = 0,
60 		FUNCTION_DRAW_INDEXED,
61 		FUNCTION_DRAW_INDIRECT,
62 		FUNCTION_DRAW_INDEXED_INDIRECT,
63 
64 		FUNTION_LAST
65 	};
66 
67 	DrawFunction			function;
68 	vk::VkPrimitiveTopology	topology;
69 	const SharedGroupParams	groupParams;
70 
71 	deBool					testAttribDivisor;
72 	deUint32				attribDivisor;
73 
74 	deBool					testMultiview;
75 
76 	deBool					dynamicState;
77 };
78 
79 struct VertexPositionAndColor
80 {
VertexPositionAndColorvkt::Draw::__anon44c184b70111::VertexPositionAndColor81 				VertexPositionAndColor (tcu::Vec4 position_, tcu::Vec4 color_)
82 					: position	(position_)
83 					, color		(color_)
84 				{
85 				}
86 
87 	tcu::Vec4	position;
88 	tcu::Vec4	color;
89 };
90 
operator <<(std::ostream & str,TestParams const & v)91 std::ostream & operator<<(std::ostream & str, TestParams const & v)
92 {
93 	std::ostringstream string;
94 
95 	if (v.dynamicState)
96 		string << "dynamic_state_";
97 
98 	switch (v.function)
99 	{
100 		case TestParams::FUNCTION_DRAW:
101 			string << "draw";
102 			break;
103 		case TestParams::FUNCTION_DRAW_INDEXED:
104 			string << "draw_indexed";
105 			break;
106 		case TestParams::FUNCTION_DRAW_INDIRECT:
107 			string << "draw_indirect";
108 			break;
109 		case TestParams::FUNCTION_DRAW_INDEXED_INDIRECT:
110 			string << "draw_indexed_indirect";
111 			break;
112 		default:
113 			DE_ASSERT(false);
114 	}
115 
116 	string << "_" << de::toString(v.topology);
117 
118 	if (v.testAttribDivisor)
119 		string << "_attrib_divisor_" << v.attribDivisor;
120 
121 	if (v.testMultiview)
122 		string << "_multiview";
123 
124 	return str << string.str();
125 }
126 
mapVkPrimitiveTopology(vk::VkPrimitiveTopology primitiveTopology)127 rr::PrimitiveType mapVkPrimitiveTopology (vk::VkPrimitiveTopology primitiveTopology)
128 {
129 	switch (primitiveTopology)
130 	{
131 		case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:						return rr::PRIMITIVETYPE_POINTS;
132 		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:						return rr::PRIMITIVETYPE_LINES;
133 		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:						return rr::PRIMITIVETYPE_LINE_STRIP;
134 		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:					return rr::PRIMITIVETYPE_TRIANGLES;
135 		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:					return rr::PRIMITIVETYPE_TRIANGLE_FAN;
136 		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:					return rr::PRIMITIVETYPE_TRIANGLE_STRIP;
137 		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:		return rr::PRIMITIVETYPE_LINES_ADJACENCY;
138 		case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:		return rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY;
139 		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:	return rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY;
140 		case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:	return rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY;
141 		default:
142 			DE_ASSERT(false);
143 	}
144 	return rr::PRIMITIVETYPE_LAST;
145 }
146 
147 template<typename T>
createAndUploadBuffer(const std::vector<T> data,const vk::DeviceInterface & vk,const Context & context,vk::VkBufferUsageFlags usage)148 de::SharedPtr<Buffer> createAndUploadBuffer(const std::vector<T> data, const vk::DeviceInterface& vk, const Context& context, vk::VkBufferUsageFlags usage)
149 {
150 	const vk::VkDeviceSize dataSize = data.size() * sizeof(T);
151 	de::SharedPtr<Buffer> buffer = Buffer::createAndAlloc(vk, context.getDevice(),
152 														  BufferCreateInfo(dataSize, usage),
153 														  context.getDefaultAllocator(),
154 														  vk::MemoryRequirement::HostVisible);
155 
156 	deUint8* ptr = reinterpret_cast<deUint8*>(buffer->getBoundMemory().getHostPtr());
157 
158 	deMemcpy(ptr, &data[0], static_cast<size_t>(dataSize));
159 
160 	vk::flushAlloc(vk, context.getDevice(), buffer->getBoundMemory());
161 	return buffer;
162 }
163 
164 class TestVertShader : public rr::VertexShader
165 {
166 public:
TestVertShader(int numInstances,int firstInstance)167 	TestVertShader (int numInstances, int firstInstance)
168 		: rr::VertexShader	(3, 1)
169 		, m_numInstances	(numInstances)
170 		, m_firstInstance	(firstInstance)
171 	{
172 		m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
173 		m_inputs[1].type	= rr::GENERICVECTYPE_FLOAT;
174 		m_inputs[2].type	= rr::GENERICVECTYPE_FLOAT;
175 		m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
176 	}
177 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const178 	void shadeVertices (const rr::VertexAttrib* inputs,
179 						rr::VertexPacket* const* packets,
180 						const int numPackets) const
181 	{
182 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
183 		{
184 			const int		instanceNdx		= packets[packetNdx]->instanceNdx + m_firstInstance;
185 			const tcu::Vec4	position		= rr::readVertexAttribFloat(inputs[0], packets[packetNdx]->instanceNdx,	packets[packetNdx]->vertexNdx, m_firstInstance);
186 			const tcu::Vec4	color			= rr::readVertexAttribFloat(inputs[1], packets[packetNdx]->instanceNdx,	packets[packetNdx]->vertexNdx, m_firstInstance);
187 			const tcu::Vec4	color2			= rr::readVertexAttribFloat(inputs[2], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx, m_firstInstance);
188 			packets[packetNdx]->position	= position + tcu::Vec4((float)(packets[packetNdx]->instanceNdx * 2.0 / m_numInstances), 0.0, 0.0, 0.0);
189 			packets[packetNdx]->outputs[0]	= color + tcu::Vec4((float)instanceNdx / (float)m_numInstances, 0.0, 0.0, 1.0) + color2;
190 		}
191 	}
192 
193 private:
194 	const int m_numInstances;
195 	const int m_firstInstance;
196 };
197 
198 class TestFragShader : public rr::FragmentShader
199 {
200 public:
TestFragShader(void)201 	TestFragShader (void)
202 		: rr::FragmentShader(1, 1)
203 	{
204 		m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
205 		m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
206 	}
207 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const208 	void shadeFragments (rr::FragmentPacket* packets,
209 						 const int numPackets,
210 						 const rr::FragmentShadingContext& context) const
211 	{
212 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
213 		{
214 			rr::FragmentPacket& packet = packets[packetNdx];
215 			for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
216 			{
217 				const tcu::Vec4 color = rr::readVarying<float>(packet, context, 0, fragNdx);
218 				rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
219 			}
220 		}
221 	}
222 };
223 
224 class InstancedDrawInstance : public TestInstance
225 {
226 public:
227 												InstancedDrawInstance	(Context& context, TestParams params);
228 	virtual	tcu::TestStatus						iterate					(void);
229 
230 private:
231 	void										prepareVertexData		(int instanceCount, int firstInstance, int instanceDivisor);
232 	void										preRenderCommands		(const vk::VkClearValue& clearColor, deUint32 numLayers);
233 	void										draw					(vk::VkCommandBuffer cmdBuffer,
234 																		 vk::VkBuffer vertexBuffer, vk::VkBuffer instancedVertexBuffer,
235 																		 de::SharedPtr<Buffer> indexBuffer, de::SharedPtr<Buffer> indirectBuffer,
236 																		 deUint32 firstInstance, deUint32 instanceCount);
237 
238 #ifndef CTS_USES_VULKANSC
239 	void										beginSecondaryCmdBuffer	(vk::VkRenderingFlagsKHR renderingFlags = 0u);
240 #endif // CTS_USES_VULKANSC
241 
242 private:
243 
244 	const TestParams							m_params;
245 	const vk::DeviceInterface&					m_vk;
246 
247 	vk::VkFormat								m_colorAttachmentFormat;
248 
249 	vk::Move<vk::VkPipeline>					m_pipeline;
250 	vk::Move<vk::VkPipelineLayout>				m_pipelineLayout;
251 
252 	de::SharedPtr<Image>						m_colorTargetImage;
253 	vk::Move<vk::VkImageView>					m_colorTargetView;
254 
255 	PipelineCreateInfo::VertexInputState		m_vertexInputState;
256 
257 	vk::Move<vk::VkCommandPool>					m_cmdPool;
258 	vk::Move<vk::VkCommandBuffer>				m_cmdBuffer;
259 	vk::Move<vk::VkCommandBuffer>				m_secCmdBuffer;
260 
261 	vk::Move<vk::VkFramebuffer>					m_framebuffer;
262 	vk::Move<vk::VkRenderPass>					m_renderPass;
263 
264 	// Vertex data
265 	std::vector<VertexPositionAndColor>			m_data;
266 	std::vector<deUint32>						m_indexes;
267 	std::vector<tcu::Vec4>						m_instancedColor;
268 };
269 
270 class InstancedDrawCase : public TestCase
271 {
272 public:
InstancedDrawCase(tcu::TestContext & testCtx,const std::string & name,const std::string & desc,TestParams params)273 	InstancedDrawCase (tcu::TestContext&	testCtx,
274 					   const std::string&	name,
275 					   const std::string&	desc,
276 					   TestParams			params)
277 		: TestCase	(testCtx, name, desc)
278 		, m_params	(params)
279 	{
280 		m_vertexShader = "#version 430\n"
281 				"layout(location = 0) in vec4 in_position;\n"
282 				"layout(location = 1) in vec4 in_color;\n"
283 				"layout(location = 2) in vec4 in_color_2;\n"
284 				"layout(push_constant) uniform TestParams {\n"
285 				"	float firstInstance;\n"
286 				"	float instanceCount;\n"
287 				"} params;\n"
288 				"layout(location = 0) out vec4 out_color;\n"
289 				"out gl_PerVertex {\n"
290 				"    vec4  gl_Position;\n"
291 				"    float gl_PointSize;\n"
292 				"};\n"
293 				"void main() {\n"
294 				"    gl_PointSize = 1.0;\n"
295 				"    gl_Position  = in_position + vec4(float(gl_InstanceIndex - params.firstInstance) * 2.0 / params.instanceCount, 0.0, 0.0, 0.0);\n"
296 				"    out_color    = in_color + vec4(float(gl_InstanceIndex) / params.instanceCount, 0.0, 0.0, 1.0) + in_color_2;\n"
297 				"}\n";
298 
299 		m_fragmentShader = "#version 430\n"
300 				"layout(location = 0) in vec4 in_color;\n"
301 				"layout(location = 0) out vec4 out_color;\n"
302 				"void main()\n"
303 				"{\n"
304 				"    out_color = in_color;\n"
305 				"}\n";
306 	}
307 
checkSupport(Context & context) const308 	virtual void	checkSupport	(Context& context) const
309 	{
310 		if (m_params.dynamicState)
311 		{
312 			const auto physicalVertexInputDynamicState = context.getVertexInputDynamicStateFeaturesEXT();
313 			if (!physicalVertexInputDynamicState.vertexInputDynamicState)
314 				TCU_THROW(NotSupportedError, "Implementation does not support vertexInputDynamicState");
315 		}
316 		if (m_params.testAttribDivisor)
317 		{
318 			context.requireDeviceFunctionality("VK_EXT_vertex_attribute_divisor");
319 
320 			const vk::VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT& vertexAttributeDivisorFeatures = context.getVertexAttributeDivisorFeaturesEXT();
321 
322 			if (m_params.attribDivisor != 1 && !vertexAttributeDivisorFeatures.vertexAttributeInstanceRateDivisor)
323 				TCU_THROW(NotSupportedError, "Implementation does not support vertexAttributeInstanceRateDivisor");
324 
325 			if (m_params.attribDivisor == 0 && !vertexAttributeDivisorFeatures.vertexAttributeInstanceRateZeroDivisor)
326 				TCU_THROW(NotSupportedError, "Implementation does not support vertexAttributeInstanceRateDivisorZero");
327 
328 			if (m_params.testMultiview)
329 			{
330 				context.requireDeviceFunctionality("VK_KHR_multiview");
331 
332 				const vk::VkPhysicalDeviceMultiviewFeatures& multiviewFeatures = context.getMultiviewFeatures();
333 
334 				if (!multiviewFeatures.multiview)
335 					TCU_THROW(NotSupportedError, "Implementation does not support multiview feature");
336 			}
337 		}
338 
339 #ifndef CTS_USES_VULKANSC
340 		if (m_params.groupParams->useDynamicRendering)
341 			context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
342 
343 		if (m_params.topology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN &&
344 			context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
345 			!context.getPortabilitySubsetFeatures().triangleFans)
346 		{
347 			TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
348 		}
349 #endif // CTS_USES_VULKANSC
350 	}
351 
createInstance(Context & context) const352 	TestInstance*	createInstance	(Context& context) const
353 	{
354 		return new InstancedDrawInstance(context, m_params);
355 	}
356 
initPrograms(vk::SourceCollections & programCollection) const357 	virtual void	initPrograms	(vk::SourceCollections& programCollection) const
358 	{
359 		programCollection.glslSources.add("InstancedDrawVert") << glu::VertexSource(m_vertexShader);
360 		programCollection.glslSources.add("InstancedDrawFrag") << glu::FragmentSource(m_fragmentShader);
361 	}
362 
363 private:
364 	const TestParams	m_params;
365 	std::string			m_vertexShader;
366 	std::string			m_fragmentShader;
367 };
368 
InstancedDrawInstance(Context & context,TestParams params)369 InstancedDrawInstance::InstancedDrawInstance(Context &context, TestParams params)
370 	: TestInstance				(context)
371 	, m_params					(params)
372 	, m_vk						(context.getDeviceInterface())
373 	, m_colorAttachmentFormat	(vk::VK_FORMAT_R8G8B8A8_UNORM)
374 {
375 	const vk::VkDevice device				= m_context.getDevice();
376 	const deUint32 queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
377 
378 	const vk::VkPushConstantRange pushConstantRange = {
379 		vk::VK_SHADER_STAGE_VERTEX_BIT,				// VkShaderStageFlags    stageFlags;
380 		0u,											// uint32_t              offset;
381 		(deUint32)sizeof(float) * 2,				// uint32_t              size;
382 	};
383 
384 	const PipelineLayoutCreateInfo pipelineLayoutCreateInfo(0, DE_NULL, 1, &pushConstantRange);
385 	m_pipelineLayout						= vk::createPipelineLayout(m_vk, device, &pipelineLayoutCreateInfo);
386 
387 	deUint32 arrayLayers = m_params.testMultiview ? 2 : 1;
388 	const vk::VkExtent3D targetImageExtent	= { WIDTH, HEIGHT, 1 };
389 	const ImageCreateInfo targetImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, targetImageExtent, 1, arrayLayers, vk::VK_SAMPLE_COUNT_1_BIT,
390 		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);
391 
392 	m_colorTargetImage						= Image::createAndAlloc(m_vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
393 
394 	const enum vk::VkImageViewType imageViewType = m_params.testMultiview ? vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY : vk::VK_IMAGE_VIEW_TYPE_2D;
395 	ImageSubresourceRange subresourceRange = ImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT);
396 
397 	if (m_params.testMultiview)
398 		subresourceRange.layerCount = 2;
399 
400 	const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), imageViewType, m_colorAttachmentFormat, subresourceRange);
401 	m_colorTargetView						= vk::createImageView(m_vk, device, &colorTargetViewInfo);
402 
403 	if (!m_params.groupParams->useDynamicRendering)
404 	{
405 		RenderPassCreateInfo renderPassCreateInfo;
406 		renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat,
407 																 vk::VK_SAMPLE_COUNT_1_BIT,
408 																 vk::VK_ATTACHMENT_LOAD_OP_LOAD,
409 																 vk::VK_ATTACHMENT_STORE_OP_STORE,
410 																 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
411 																 vk::VK_ATTACHMENT_STORE_OP_STORE,
412 																 vk::VK_IMAGE_LAYOUT_GENERAL,
413 																 vk::VK_IMAGE_LAYOUT_GENERAL));
414 
415 		const vk::VkAttachmentReference colorAttachmentReference =
416 		{
417 			0,
418 			vk::VK_IMAGE_LAYOUT_GENERAL
419 		};
420 
421 		renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
422 														   0,
423 														   0,
424 														   DE_NULL,
425 														   1,
426 														   &colorAttachmentReference,
427 														   DE_NULL,
428 														   AttachmentReference(),
429 														   0,
430 														   DE_NULL));
431 
432 		vk::VkRenderPassMultiviewCreateInfo renderPassMultiviewCreateInfo;
433 		// Bit mask that specifies which view rendering is broadcast to
434 		// 0011 = Broadcast to first and second view (layer)
435 		const deUint32 viewMask = 0x3;
436 		// Bit mask that specifices correlation between views
437 		// An implementation may use this for optimizations (concurrent render)
438 		const deUint32 correlationMask = 0x3;
439 
440 		if (m_params.testMultiview)
441 		{
442 			DE_ASSERT(renderPassCreateInfo.subpassCount == 1);
443 
444 			renderPassMultiviewCreateInfo.sType = vk::VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO;
445 			renderPassMultiviewCreateInfo.pNext = DE_NULL;
446 			renderPassMultiviewCreateInfo.subpassCount = renderPassCreateInfo.subpassCount;
447 			renderPassMultiviewCreateInfo.pViewMasks = &viewMask;
448 			renderPassMultiviewCreateInfo.correlationMaskCount = 1u;
449 			renderPassMultiviewCreateInfo.pCorrelationMasks = &correlationMask;
450 			renderPassMultiviewCreateInfo.pViewOffsets = DE_NULL;
451 			renderPassMultiviewCreateInfo.dependencyCount = 0u;
452 
453 			renderPassCreateInfo.pNext = &renderPassMultiviewCreateInfo;
454 		}
455 
456 		m_renderPass = vk::createRenderPass(m_vk, device, &renderPassCreateInfo);
457 
458 		// create framebuffer
459 		std::vector<vk::VkImageView>	colorAttachments { *m_colorTargetView };
460 		const FramebufferCreateInfo		framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
461 		m_framebuffer = vk::createFramebuffer(m_vk, device, &framebufferCreateInfo);
462 	}
463 
464 	const vk::VkVertexInputBindingDescription vertexInputBindingDescription[2] =
465 	{
466 		{
467 			0u,
468 			(deUint32)sizeof(VertexPositionAndColor),
469 			vk::VK_VERTEX_INPUT_RATE_VERTEX,
470 		},
471 		{
472 			1u,
473 			(deUint32)sizeof(tcu::Vec4),
474 			vk::VK_VERTEX_INPUT_RATE_INSTANCE,
475 		},
476 	};
477 
478 	const vk::VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
479 	{
480 		{
481 			0u,
482 			0u,
483 			vk::VK_FORMAT_R32G32B32A32_SFLOAT,
484 			0u
485 		},
486 		{
487 			1u,
488 			0u,
489 			vk::VK_FORMAT_R32G32B32A32_SFLOAT,
490 			(deUint32)sizeof(tcu::Vec4),
491 		},
492 		{
493 			2u,
494 			1u,
495 			vk::VK_FORMAT_R32G32B32A32_SFLOAT,
496 			0,
497 		}
498 	};
499 
500 	m_vertexInputState = PipelineCreateInfo::VertexInputState(2,
501 															  vertexInputBindingDescription,
502 															  DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),
503 															  vertexInputAttributeDescriptions);
504 
505 	const vk::VkVertexInputBindingDivisorDescriptionEXT vertexInputBindingDivisorDescription =
506 	{
507 		1u,
508 		m_params.attribDivisor,
509 	};
510 
511 	if (m_params.testAttribDivisor)
512 		m_vertexInputState.addDivisors(1, &vertexInputBindingDivisorDescription);
513 
514 	const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex);
515 	m_cmdPool	= vk::createCommandPool(m_vk, device, &cmdPoolCreateInfo);
516 	m_cmdBuffer	= vk::allocateCommandBuffer(m_vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
517 	if (m_params.groupParams->useSecondaryCmdBuffer)
518 		m_secCmdBuffer = vk::allocateCommandBuffer(m_vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY);
519 
520 	const vk::Unique<vk::VkShaderModule> vs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("InstancedDrawVert"), 0));
521 	const vk::Unique<vk::VkShaderModule> fs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("InstancedDrawFrag"), 0));
522 
523 	const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
524 
525 	vk::VkViewport	viewport	= vk::makeViewport(WIDTH, HEIGHT);
526 	vk::VkRect2D	scissor		= vk::makeRect2D(WIDTH, HEIGHT);
527 
528 	PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
529 	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
530 	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
531 	pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(m_params.topology));
532 	pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
533 	pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport), std::vector<vk::VkRect2D>(1, scissor)));
534 	pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
535 	pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
536 	pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
537 
538 	if (m_params.dynamicState)
539 	{
540 		vk::VkDynamicState dynStates[] =
541 		{
542 			vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT
543 		};
544 
545 		vk::VkPipelineDynamicStateCreateInfo dynamicState
546 		{
547 			vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
548 			DE_NULL,
549 			0,
550 			1,
551 			dynStates
552 		};
553 		pipelineCreateInfo.addState(dynamicState);
554 	}
555 	else
556 	{
557 		pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(m_vertexInputState));
558 	}
559 
560 #ifndef CTS_USES_VULKANSC
561 	vk::VkPipelineRenderingCreateInfoKHR renderingFormatCreateInfo
562 	{
563 		vk::VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
564 		DE_NULL,
565 		0u,
566 		1u,
567 		&m_colorAttachmentFormat,
568 		vk::VK_FORMAT_UNDEFINED,
569 		vk::VK_FORMAT_UNDEFINED
570 	};
571 
572 	if (m_params.groupParams->useDynamicRendering)
573 	{
574 		pipelineCreateInfo.pNext = &renderingFormatCreateInfo;
575 
576 		if (m_params.testMultiview)
577 			renderingFormatCreateInfo.viewMask = 3u;
578 	}
579 #endif // CTS_USES_VULKANSC
580 
581 	m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
582 }
583 
iterate()584 tcu::TestStatus InstancedDrawInstance::iterate()
585 {
586 	const vk::VkQueue		queue					= m_context.getUniversalQueue();
587 	const vk::VkDevice		device					= m_context.getDevice();
588 	static const deUint32	instanceCounts[]		= { 0, 1, 2, 4, 20 };
589 	static const deUint32	firstInstanceIndices[]	= { 0, 1, 3, 4, 20 };
590 	const deUint32			numLayers				= m_params.testMultiview ? 2 : 1;
591 	const vk::VkRect2D		renderArea				= vk::makeRect2D(WIDTH, HEIGHT);
592 
593 	qpTestResult			res						= QP_TEST_RESULT_PASS;
594 
595 	const vk::VkClearValue clearColor = { { { 0.0f, 0.0f, 0.0f, 1.0f } } };
596 	int firstInstanceIndicesCount = DE_LENGTH_OF_ARRAY(firstInstanceIndices);
597 
598 	// Require 'drawIndirectFirstInstance' feature to run non-zero firstInstance indirect draw tests.
599 	if (m_params.function == TestParams::FUNCTION_DRAW_INDIRECT && !m_context.getDeviceFeatures().drawIndirectFirstInstance)
600 	{
601 		firstInstanceIndicesCount = 1;
602 	}
603 
604 	for (int instanceCountNdx = 0; instanceCountNdx < DE_LENGTH_OF_ARRAY(instanceCounts); instanceCountNdx++)
605 	{
606 		const deUint32 instanceCount = instanceCounts[instanceCountNdx];
607 		for (int firstInstanceIndexNdx = 0; firstInstanceIndexNdx < firstInstanceIndicesCount; firstInstanceIndexNdx++)
608 		{
609 			// Prepare vertex data for at least one instance
610 			const deUint32				prepareCount			= de::max(instanceCount, 1u);
611 			const deUint32				firstInstance			= firstInstanceIndices[firstInstanceIndexNdx];
612 
613 			prepareVertexData(prepareCount, firstInstance, m_params.testAttribDivisor ? m_params.attribDivisor : 1);
614 			const de::SharedPtr<Buffer>	vertexBuffer			= createAndUploadBuffer(m_data, m_vk, m_context, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
615 			const de::SharedPtr<Buffer>	instancedVertexBuffer	= createAndUploadBuffer(m_instancedColor, m_vk, m_context, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
616 
617 			de::SharedPtr<Buffer> indexBuffer;
618 			if (m_params.function == TestParams::FUNCTION_DRAW_INDEXED || m_params.function == TestParams::FUNCTION_DRAW_INDEXED_INDIRECT)
619 				indexBuffer = createAndUploadBuffer(m_indexes, m_vk, m_context, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
620 
621 			de::SharedPtr<Buffer> indirectBuffer;
622 			if (m_params.function == TestParams::FUNCTION_DRAW_INDIRECT)
623 			{
624 				std::vector<vk::VkDrawIndirectCommand> drawCommands;
625 				drawCommands.push_back({
626 					(deUint32)m_data.size(),	// uint32_t	vertexCount;
627 					instanceCount,				// uint32_t	instanceCount;
628 					0u,							// uint32_t	firstVertex;
629 					firstInstance				// uint32_t	firstInstance;
630 				});
631 				indirectBuffer = createAndUploadBuffer(drawCommands, m_vk, m_context, vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
632 			}
633 			if (m_params.function == TestParams::FUNCTION_DRAW_INDEXED_INDIRECT)
634 			{
635 				std::vector<vk::VkDrawIndexedIndirectCommand> drawCommands;
636 				drawCommands.push_back({
637 					(deUint32)m_indexes.size(),	// uint32_t	indexCount;
638 					instanceCount,				// uint32_t	instanceCount;
639 					0u,							// uint32_t	firstIndex;
640 					0,							// int32_t	vertexOffset;
641 					firstInstance				// uint32_t	firstInstance;
642 				});
643 				indirectBuffer = createAndUploadBuffer(drawCommands, m_vk, m_context, vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
644 			}
645 
646 #ifndef CTS_USES_VULKANSC
647 			const deUint32 layerCount	= (m_params.testMultiview) ? 2u : 1u;
648 			const deUint32 viewMask		= (m_params.testMultiview) ? 3u : 0u;
649 			if (m_params.groupParams->useSecondaryCmdBuffer)
650 			{
651 				// record secondary command buffer
652 				if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
653 				{
654 					beginSecondaryCmdBuffer(vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
655 					beginRendering(m_vk, *m_secCmdBuffer, *m_colorTargetView, renderArea, clearColor, vk::VK_IMAGE_LAYOUT_GENERAL,
656 								   vk::VK_ATTACHMENT_LOAD_OP_LOAD, 0u, layerCount, viewMask);
657 				}
658 				else
659 					beginSecondaryCmdBuffer();
660 
661 				draw(*m_secCmdBuffer, vertexBuffer->object(), instancedVertexBuffer->object(), indexBuffer, indirectBuffer, firstInstance, instanceCount);
662 
663 				if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
664 					endRendering(m_vk, *m_secCmdBuffer);
665 
666 				endCommandBuffer(m_vk, *m_secCmdBuffer);
667 
668 				// record primary command buffer
669 				beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
670 
671 				preRenderCommands(clearColor, numLayers);
672 
673 				if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
674 				{
675 					beginRendering(m_vk, *m_cmdBuffer, *m_colorTargetView, renderArea, clearColor, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_LOAD,
676 								   vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR, layerCount, viewMask);
677 				}
678 
679 				m_vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
680 
681 				if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
682 					endRendering(m_vk, *m_cmdBuffer);
683 
684 				endCommandBuffer(m_vk, *m_cmdBuffer);
685 			}
686 			else if (m_params.groupParams->useDynamicRendering)
687 			{
688 				beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
689 				preRenderCommands(clearColor, numLayers);
690 
691 				beginRendering(m_vk, *m_cmdBuffer, *m_colorTargetView, renderArea, clearColor, vk::VK_IMAGE_LAYOUT_GENERAL,
692 							   vk::VK_ATTACHMENT_LOAD_OP_LOAD, 0u, layerCount, viewMask);
693 				draw(*m_cmdBuffer, vertexBuffer->object(), instancedVertexBuffer->object(), indexBuffer, indirectBuffer, firstInstance, instanceCount);
694 				endRendering(m_vk, *m_cmdBuffer);
695 
696 				endCommandBuffer(m_vk, *m_cmdBuffer);
697 			}
698 #endif // CTS_USES_VULKANSC
699 
700 			if (!m_params.groupParams->useDynamicRendering)
701 			{
702 				beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
703 				preRenderCommands(clearColor, numLayers);
704 
705 				beginRenderPass(m_vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, renderArea);
706 				draw(*m_cmdBuffer, vertexBuffer->object(), instancedVertexBuffer->object(), indexBuffer, indirectBuffer, firstInstance, instanceCount);
707 				endRenderPass(m_vk, *m_cmdBuffer);
708 
709 				endCommandBuffer(m_vk, *m_cmdBuffer);
710 			}
711 
712 /*
713 
714 void InstancedDrawInstance::beginRender(vk::VkCommandBuffer cmdBuffer, const vk::VkClearValue& clearColor, vk::VkRenderingFlagsKHR renderingFlags)
715 {
716 
717 	if (m_params.groupParams->useDynamicRendering)
718 	else
719 */
720 
721 			submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
722 			m_context.resetCommandPoolForVKSC(device, *m_cmdPool);
723 
724 			// Reference rendering
725 			std::vector<tcu::Vec4>	vetrices;
726 			std::vector<tcu::Vec4>	colors;
727 
728 			for (std::vector<VertexPositionAndColor>::const_iterator it = m_data.begin(); it != m_data.end(); ++it)
729 			{
730 				vetrices.push_back(it->position);
731 				colors.push_back(it->color);
732 			}
733 
734 			tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
735 
736 			tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
737 
738 			const TestVertShader					vertShader(instanceCount, firstInstance);
739 			const TestFragShader					fragShader;
740 			const rr::Program						program			(&vertShader, &fragShader);
741 			const rr::MultisamplePixelBufferAccess	colorBuffer		= rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(refImage.getAccess());
742 			const rr::RenderTarget					renderTarget	(colorBuffer);
743 			const rr::RenderState					renderState		((rr::ViewportState(colorBuffer)), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
744 			const rr::Renderer						renderer;
745 
746 			const rr::VertexAttrib	vertexAttribs[] =
747 			{
748 				rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &vetrices[0]),
749 				rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &colors[0]),
750 				// The reference renderer treats a divisor of 0 as meaning per-vertex.  Use INT_MAX instead; it should work just as well.
751 				rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), m_params.testAttribDivisor ? (m_params.attribDivisor == 0 ? INT_MAX : m_params.attribDivisor) : 1, &m_instancedColor[0])
752 			};
753 
754 			if (m_params.function == TestParams::FUNCTION_DRAW || m_params.function == TestParams::FUNCTION_DRAW_INDIRECT)
755 			{
756 				const rr::PrimitiveList	primitives = rr::PrimitiveList(mapVkPrimitiveTopology(m_params.topology), (int)vetrices.size(), 0);
757 				const rr::DrawCommand	command(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), &vertexAttribs[0],
758 												primitives);
759 				renderer.drawInstanced(command, instanceCount);
760 			}
761 			else
762 			{
763 				const rr::DrawIndices indicies(m_indexes.data());
764 
765 				const rr::PrimitiveList	primitives = rr::PrimitiveList(mapVkPrimitiveTopology(m_params.topology), (int)m_indexes.size(), indicies);
766 				const rr::DrawCommand	command(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), &vertexAttribs[0],
767 												primitives);
768 				renderer.drawInstanced(command, instanceCount);
769 			}
770 
771 			const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
772 			for (deUint32 i = 0; i < numLayers; i++)
773 			{
774 				const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
775 					vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT, 0, i);
776 
777 				tcu::TestLog &log		= m_context.getTestContext().getLog();
778 
779 				std::ostringstream resultDesc;
780 				resultDesc << "Image layer " << i << " comparison result. Instance count: " << instanceCount << " first instance index: " << firstInstance;
781 
782 				if (m_params.topology == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
783 				{
784 					const bool ok = tcu::intThresholdPositionDeviationCompare(
785 						log, "Result", resultDesc.str().c_str(), refImage.getAccess(), renderedFrame,
786 						tcu::UVec4(4u),					// color threshold
787 						tcu::IVec3(1, 1, 0),			// position deviation tolerance
788 						true,							// don't check the pixels at the boundary
789 						tcu::COMPARE_LOG_RESULT);
790 
791 					if (!ok)
792 						res = QP_TEST_RESULT_FAIL;
793 				}
794 				else
795 				{
796 					if (!tcu::fuzzyCompare(log, "Result", resultDesc.str().c_str(), refImage.getAccess(), renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT))
797 						res = QP_TEST_RESULT_FAIL;
798 				}
799 			}
800 		}
801 	}
802 	return tcu::TestStatus(res, qpGetTestResultName(res));
803 }
804 
prepareVertexData(int instanceCount,int firstInstance,int instanceDivisor)805 void InstancedDrawInstance::prepareVertexData(int instanceCount, int firstInstance, int instanceDivisor)
806 {
807 	m_data.clear();
808 	m_indexes.clear();
809 	m_instancedColor.clear();
810 
811 	if (m_params.function == TestParams::FUNCTION_DRAW || m_params.function == TestParams::FUNCTION_DRAW_INDIRECT)
812 	{
813 		for (int y = 0; y < QUAD_GRID_SIZE; y++)
814 		{
815 			for (int x = 0; x < QUAD_GRID_SIZE; x++)
816 			{
817 				const float fx0 = -1.0f + (float)(x+0) / (float)QUAD_GRID_SIZE * 2.0f / (float)instanceCount;
818 				const float fx1 = -1.0f + (float)(x+1) / (float)QUAD_GRID_SIZE * 2.0f / (float)instanceCount;
819 				const float fy0 = -1.0f + (float)(y+0) / (float)QUAD_GRID_SIZE * 2.0f;
820 				const float fy1 = -1.0f + (float)(y+1) / (float)QUAD_GRID_SIZE * 2.0f;
821 
822 				// Vertices of a quad's lower-left triangle: (fx0, fy0), (fx1, fy0) and (fx0, fy1)
823 				m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx0, fy0, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
824 				m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx1, fy0, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
825 				m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx0, fy1, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
826 
827 				// Vertices of a quad's upper-right triangle: (fx1, fy1), (fx0, fy1) and (fx1, fy0)
828 				m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx1, fy1, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
829 				m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx0, fy1, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
830 				m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx1, fy0, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
831 			}
832 		}
833 	}
834 	else
835 	{
836 		for (int y = 0; y < QUAD_GRID_SIZE + 1; y++)
837 		{
838 			for (int x = 0; x < QUAD_GRID_SIZE + 1; x++)
839 			{
840 				const float fx = -1.0f + (float)x / (float)QUAD_GRID_SIZE * 2.0f / (float)instanceCount;
841 				const float fy = -1.0f + (float)y / (float)QUAD_GRID_SIZE * 2.0f;
842 
843 				m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx, fy, 1.0f, 1.0f),
844 														(y % 2 ? tcu::RGBA::blue().toVec() : tcu::RGBA::green().toVec())));
845 			}
846 		}
847 
848 		for (int y = 0; y < QUAD_GRID_SIZE; y++)
849 		{
850 			for (int x = 0; x < QUAD_GRID_SIZE; x++)
851 			{
852 				const int ndx00 = y*(QUAD_GRID_SIZE + 1) + x;
853 				const int ndx10 = y*(QUAD_GRID_SIZE + 1) + x + 1;
854 				const int ndx01 = (y + 1)*(QUAD_GRID_SIZE + 1) + x;
855 				const int ndx11 = (y + 1)*(QUAD_GRID_SIZE + 1) + x + 1;
856 
857 				// Lower-left triangle of a quad.
858 				m_indexes.push_back((deUint16)ndx00);
859 				m_indexes.push_back((deUint16)ndx10);
860 				m_indexes.push_back((deUint16)ndx01);
861 
862 				// Upper-right triangle of a quad.
863 				m_indexes.push_back((deUint16)ndx11);
864 				m_indexes.push_back((deUint16)ndx01);
865 				m_indexes.push_back((deUint16)ndx10);
866 			}
867 		}
868 	}
869 
870 	const int colorCount = instanceDivisor == 0 ? 1 : (instanceCount + firstInstance + instanceDivisor - 1) / instanceDivisor;
871 	for (int i = 0; i < instanceCount + firstInstance; i++)
872 	{
873 		m_instancedColor.push_back(tcu::Vec4(0.0, (float)(1.0 - i * 1.0 / colorCount) / 2, 0.0, 1.0));
874 	}
875 }
876 
preRenderCommands(const vk::VkClearValue & clearColor,deUint32 numLayers)877 void InstancedDrawInstance::preRenderCommands(const vk::VkClearValue& clearColor, deUint32 numLayers)
878 {
879 	const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, numLayers);
880 
881 	if (m_params.testMultiview)
882 	{
883 		vk::VkImageMemoryBarrier barrier
884 		{
885 			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
886 			DE_NULL,											// const void*				pNext;
887 			0u,													// VkAccessFlags			srcAccessMask;
888 			vk::VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			dstAccessMask;
889 			vk::VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
890 			vk::VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout			newLayout;
891 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t					srcQueueFamilyIndex;
892 			VK_QUEUE_FAMILY_IGNORED,							// uint32_t					dstQueueFamilyIndex;
893 			m_colorTargetImage->object(),						// VkImage					image;
894 			subresourceRange									// VkImageSubresourceRange	subresourceRange;
895 		};
896 
897 		m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL,
898 								0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
899 	}
900 	else
901 	{
902 		initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
903 									  vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
904 	}
905 
906 	m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(),
907 							vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &subresourceRange);
908 
909 	const vk::VkMemoryBarrier memBarrier
910 	{
911 		vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,
912 		DE_NULL,
913 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,
914 		vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
915 	};
916 
917 	m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
918 							vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
919 							0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
920 }
921 
draw(vk::VkCommandBuffer cmdBuffer,vk::VkBuffer vertexBuffer,vk::VkBuffer instancedVertexBuffer,de::SharedPtr<Buffer> indexBuffer,de::SharedPtr<Buffer> indirectBuffer,deUint32 firstInstance,deUint32 instanceCount)922 void InstancedDrawInstance::draw(vk::VkCommandBuffer cmdBuffer,
923 								 vk::VkBuffer vertexBuffer, vk::VkBuffer instancedVertexBuffer,
924 								 de::SharedPtr<Buffer> indexBuffer, de::SharedPtr<Buffer> indirectBuffer,
925 								 deUint32 firstInstance, deUint32 instanceCount)
926 {
927 	if (m_params.function == TestParams::FUNCTION_DRAW_INDEXED || m_params.function == TestParams::FUNCTION_DRAW_INDEXED_INDIRECT)
928 		m_vk.cmdBindIndexBuffer(cmdBuffer, indexBuffer->object(), 0, vk::VK_INDEX_TYPE_UINT32);
929 
930 	const vk::VkBuffer		vertexBuffers[]			{ vertexBuffer,		instancedVertexBuffer	};
931 	const vk::VkDeviceSize	vertexBufferOffsets[]	{ 0,				0 };
932 
933 	m_vk.cmdBindVertexBuffers(cmdBuffer, 0, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers, vertexBufferOffsets);
934 
935 	const float pushConstants[] = { (float)firstInstance, (float)instanceCount };
936 	m_vk.cmdPushConstants(cmdBuffer, *m_pipelineLayout, vk::VK_SHADER_STAGE_VERTEX_BIT, 0u, (deUint32)sizeof(pushConstants), pushConstants);
937 	m_vk.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
938 
939 	if (m_params.dynamicState)
940 	{
941 		vk::VkVertexInputBindingDescription2EXT vertexBindingDescription[2]
942 		{
943 			{
944 				vk::VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT,
945 				0,
946 				0u,
947 				(deUint32)sizeof(VertexPositionAndColor),
948 				vk::VK_VERTEX_INPUT_RATE_VERTEX,
949 				1
950 			},
951 			{
952 				vk::VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT,
953 				0,
954 				1u,
955 				(deUint32)sizeof(tcu::Vec4),
956 				vk::VK_VERTEX_INPUT_RATE_INSTANCE,
957 				m_params.attribDivisor
958 			},
959 
960 		};
961 		vk::VkVertexInputAttributeDescription2EXT vertexAttributeDescription[3]
962 		{
963 			{
964 				vk::VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT,
965 				0,
966 				0u,
967 				0u,
968 				vk::VK_FORMAT_R32G32B32A32_SFLOAT,
969 				0u
970 			},
971 			{
972 				vk::VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT,
973 				0,
974 				1u,
975 				0u,
976 				vk::VK_FORMAT_R32G32B32A32_SFLOAT,
977 				(deUint32)sizeof(tcu::Vec4),
978 			},
979 			{
980 				vk::VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT,
981 				0,
982 				2u,
983 				1u,
984 				vk::VK_FORMAT_R32G32B32A32_SFLOAT,
985 				0,
986 			}
987 		};
988 
989 		m_vk.cmdSetVertexInputEXT(cmdBuffer, 2, vertexBindingDescription, 3, vertexAttributeDescription);
990 	}
991 
992 	switch (m_params.function)
993 	{
994 	case TestParams::FUNCTION_DRAW:
995 		m_vk.cmdDraw(cmdBuffer, (deUint32)m_data.size(), instanceCount, 0u, firstInstance);
996 		break;
997 
998 	case TestParams::FUNCTION_DRAW_INDEXED:
999 		m_vk.cmdDrawIndexed(cmdBuffer, (deUint32)m_indexes.size(), instanceCount, 0u, 0u, firstInstance);
1000 		break;
1001 
1002 	case TestParams::FUNCTION_DRAW_INDIRECT:
1003 		m_vk.cmdDrawIndirect(cmdBuffer, indirectBuffer->object(), 0, 1u, 0u);
1004 		break;
1005 
1006 	case TestParams::FUNCTION_DRAW_INDEXED_INDIRECT:
1007 		m_vk.cmdDrawIndexedIndirect(cmdBuffer, indirectBuffer->object(), 0, 1u, 0u);
1008 		break;
1009 
1010 	default:
1011 		DE_ASSERT(false);
1012 	}
1013 }
1014 
1015 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(vk::VkRenderingFlagsKHR renderingFlags)1016 void InstancedDrawInstance::beginSecondaryCmdBuffer(vk::VkRenderingFlagsKHR renderingFlags)
1017 {
1018 	const vk::VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
1019 	{
1020 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,	// VkStructureType					sType;
1021 		DE_NULL,																// const void*						pNext;
1022 		renderingFlags,															// VkRenderingFlagsKHR				flags;
1023 		(m_params.testMultiview) ? 3u : 0u,										// uint32_t							viewMask;
1024 		1u,																		// uint32_t							colorAttachmentCount;
1025 		&m_colorAttachmentFormat,												// const VkFormat*					pColorAttachmentFormats;
1026 		vk::VK_FORMAT_UNDEFINED,												// VkFormat							depthAttachmentFormat;
1027 		vk::VK_FORMAT_UNDEFINED,												// VkFormat							stencilAttachmentFormat;
1028 		vk::VK_SAMPLE_COUNT_1_BIT,												// VkSampleCountFlagBits			rasterizationSamples;
1029 	};
1030 
1031 	const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo
1032 	{
1033 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,					// VkStructureType					sType;
1034 		&inheritanceRenderingInfo,												// const void*						pNext;
1035 		DE_NULL,																// VkRenderPass						renderPass;
1036 		0u,																		// deUint32							subpass;
1037 		DE_NULL,																// VkFramebuffer					framebuffer;
1038 		VK_FALSE,																// VkBool32							occlusionQueryEnable;
1039 		(vk::VkQueryControlFlags)0u,											// VkQueryControlFlags				queryFlags;
1040 		(vk::VkQueryPipelineStatisticFlags)0u									// VkQueryPipelineStatisticFlags	pipelineStatistics;
1041 	};
1042 
1043 	vk::VkCommandBufferUsageFlags usageFlags = vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
1044 	if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1045 		usageFlags |= vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
1046 
1047 	const vk::VkCommandBufferBeginInfo commandBufBeginParams
1048 	{
1049 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,						// VkStructureType					sType;
1050 		DE_NULL,																// const void*						pNext;
1051 		usageFlags,																// VkCommandBufferUsageFlags		flags;
1052 		&bufferInheritanceInfo
1053 	};
1054 
1055 	VK_CHECK(m_vk.beginCommandBuffer(*m_secCmdBuffer, &commandBufBeginParams));
1056 }
1057 #endif // CTS_USES_VULKANSC
1058 
1059 } // anonymus
1060 
InstancedTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1061 InstancedTests::InstancedTests(tcu::TestContext& testCtx, const SharedGroupParams groupParams)
1062 	: TestCaseGroup		(testCtx, "instanced", "Instanced drawing tests")
1063 	, m_groupParams		(groupParams)
1064 {
1065 	static const vk::VkPrimitiveTopology	topologies[]			=
1066 	{
1067 		vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
1068 		vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
1069 		vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
1070 		vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
1071 		vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
1072 		vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
1073 	};
1074 	static const TestParams::DrawFunction	functions[]				=
1075 	{
1076 		TestParams::FUNCTION_DRAW,
1077 		TestParams::FUNCTION_DRAW_INDEXED,
1078 		TestParams::FUNCTION_DRAW_INDIRECT,
1079 		TestParams::FUNCTION_DRAW_INDEXED_INDIRECT,
1080 	};
1081 
1082 	static const deBool multiviews[] = { DE_FALSE, DE_TRUE };
1083 
1084 	static const deUint32 divisors[] = { 0, 1, 2, 4, 20 };
1085 	for (int dynState = 0; dynState < 2; dynState++)
1086 	{
1087 		for (int topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(topologies); topologyNdx++)
1088 		{
1089 			// reduce number of tests for dynamic rendering cases where secondary command buffer is used
1090 			if (groupParams->useSecondaryCmdBuffer && (topologyNdx % 2u))
1091 				continue;
1092 
1093 			for (int functionNdx = 0; functionNdx < DE_LENGTH_OF_ARRAY(functions); functionNdx++)
1094 			{
1095 				for (int testAttribDivisor = 0; testAttribDivisor < 2; testAttribDivisor++)
1096 				{
1097 					for (int divisorNdx = 0; divisorNdx < DE_LENGTH_OF_ARRAY(divisors); divisorNdx++)
1098 					{
1099 						// reduce number of tests for dynamic rendering cases where secondary command buffer is used
1100 						if (groupParams->useSecondaryCmdBuffer && (divisorNdx % 2u))
1101 							continue;
1102 
1103 						for (int multiviewNdx = 0; multiviewNdx < DE_LENGTH_OF_ARRAY(multiviews); multiviewNdx++)
1104 						{
1105 							// If we don't have VK_EXT_vertex_attribute_divisor, we only get a divisor or 1.
1106 							if (!testAttribDivisor && divisors[divisorNdx] != 1)
1107 								continue;
1108 
1109 							TestParams param
1110 							{
1111 								functions[functionNdx],						// DrawFunction				function;
1112 								topologies[topologyNdx],					// vk::VkPrimitiveTopology	topology;
1113 								groupParams,								// const SharedGroupParams	groupParams;
1114 								testAttribDivisor ? DE_TRUE : DE_FALSE,		// deBool					testAttribDivisor;
1115 								divisors[divisorNdx],						// deUint32					attribDivisor;
1116 								multiviews[multiviewNdx],					// deBool					testMultiview;
1117 								dynState == 0 ? false : true				// deBool					dynamicState;
1118 							};
1119 
1120 							// Add multiview tests only when vertex attribute divisor is enabled.
1121 							if (param.testMultiview && !testAttribDivisor)
1122 								continue;
1123 
1124 							std::string testName = de::toString(param);
1125 
1126 							addChild(new InstancedDrawCase(m_testCtx, de::toLower(testName), "Instanced drawing test", param));
1127 						}
1128 					}
1129 				}
1130 			}
1131 		}
1132 	}
1133 }
1134 
~InstancedTests()1135 InstancedTests::~InstancedTests() {}
1136 
1137 } // DrawTests
1138 } // vkt
1139