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