1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Imagination Technologies Ltd.
7  * Copyright (c) 2023 LunarG, Inc.
8  * Copyright (c) 2023 Nintendo
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Input Assembly Tests
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktPipelineInputAssemblyTests.hpp"
28 #include "vktPipelineClearUtil.hpp"
29 #include "vktPipelineImageUtil.hpp"
30 #include "vktPipelineVertexUtil.hpp"
31 #include "vktPipelineReferenceRenderer.hpp"
32 #include "vktAmberTestCase.hpp"
33 #include "vktTestCase.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkRef.hpp"
39 #include "vkRefUtil.hpp"
40 #include "vkTypeUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43 #include "tcuImageCompare.hpp"
44 #include "deMath.h"
45 #include "deMemory.h"
46 #include "deRandom.hpp"
47 #include "deStringUtil.hpp"
48 #include "deUniquePtr.hpp"
49 
50 #include <algorithm>
51 #include <sstream>
52 #include <vector>
53 
54 namespace vkt
55 {
56 namespace pipeline
57 {
58 
59 using namespace vk;
60 
61 enum class RestartType
62 {
63 	NORMAL,
64 	NONE,
65 	ALL,
66 };
67 
68 namespace
69 {
70 
71 class InputAssemblyTest : public vkt::TestCase
72 {
73 public:
74 	const static VkPrimitiveTopology	s_primitiveTopologies[];
75 	const static deUint32				s_restartIndex32;
76 	const static deUint16				s_restartIndex16;
77 	const static deUint8				s_restartIndex8;
78 
79 										InputAssemblyTest		(tcu::TestContext&					testContext,
80 																 const std::string&					name,
81 																 const PipelineConstructionType		pipelineConstructionType,
82 																 VkPrimitiveTopology				primitiveTopology,
83 																 int								primitiveCount,
84 																 bool								testPrimitiveRestart,
85 																 VkIndexType						indexType);
~InputAssemblyTest(void)86 	virtual								~InputAssemblyTest		(void) {}
87 	virtual void						initPrograms			(SourceCollections& sourceCollections) const;
88 	virtual void						checkSupport			(Context& context) const;
89 	virtual TestInstance*				createInstance			(Context& context) const;
90 	static bool							isRestartIndex			(VkIndexType indexType, deUint32 indexValue);
91 #ifndef CTS_USES_VULKANSC
92 	static deUint32						getRestartIndex			(VkIndexType indexType);
93 #endif // CTS_USES_VULKANSC
94 
95 protected:
96 	virtual void						createBufferData		(VkPrimitiveTopology		topology,
97 																 int						primitiveCount,
98 																 VkIndexType				indexType,
99 																 std::vector<deUint32>&		indexData,
100 																 std::vector<Vertex4RGBA>&	vertexData) const = 0;
101 	VkPrimitiveTopology					m_primitiveTopology;
102 	const int							m_primitiveCount;
103 
104 private:
105 	const PipelineConstructionType		m_pipelineConstructionType;
106 	bool								m_testPrimitiveRestart;
107 	VkIndexType							m_indexType;
108 };
109 
110 class PrimitiveTopologyTest : public InputAssemblyTest
111 {
112 public:
113 										PrimitiveTopologyTest	(tcu::TestContext&			testContext,
114 																 const std::string&			name,
115 																 PipelineConstructionType	pipelineConstructionType,
116 																 VkPrimitiveTopology		primitiveTopology,
117 																 VkIndexType				indexType);
~PrimitiveTopologyTest(void)118 	virtual								~PrimitiveTopologyTest	(void) {}
119 
120 protected:
121 	virtual void						createBufferData		(VkPrimitiveTopology		topology,
122 																 int						primitiveCount,
123 																 VkIndexType				indexType,
124 																 std::vector<deUint32>&		indexData,
125 																 std::vector<Vertex4RGBA>&	vertexData) const;
126 
127 private:
128 };
129 
130 #ifndef CTS_USES_VULKANSC
131 class PrimitiveRestartTest : public InputAssemblyTest
132 {
133 public:
134 										PrimitiveRestartTest	(tcu::TestContext&					testContext,
135 																 const std::string&					name,
136 																 const PipelineConstructionType		pipelineConstructionType,
137 																 VkPrimitiveTopology				primitiveTopology,
138 																 VkIndexType						indexType,
139 																 RestartType						restartType);
~PrimitiveRestartTest(void)140 	virtual								~PrimitiveRestartTest	(void) {}
141 	virtual void						checkSupport			(Context& context) const;
142 
143 protected:
144 	virtual void						createBufferData		(VkPrimitiveTopology		topology,
145 																 int						primitiveCount,
146 																 VkIndexType				indexType,
147 																 std::vector<deUint32>&		indexData,
148 																 std::vector<Vertex4RGBA>&	vertexData) const;
149 
150 private:
151 	bool								isRestartPrimitive		(int primitiveIndex) const;
152 	void								createListPrimitives	(int						primitiveCount,
153 																 float						originX,
154 																 float						originY,
155 																 float						primitiveSizeX,
156 																 float						primitiveSizeY,
157 																 int						verticesPerPrimitive,
158 																 VkIndexType				indexType,
159 																 std::vector<deUint32>&		indexData,
160 																 std::vector<Vertex4RGBA>&	vertexData,
161 																 std::vector<deUint32>		adjacencies) const;
162 
163 	std::vector<deUint32>				m_restartPrimitives;
164 	RestartType							m_restartType;
165 };
166 #endif // CTS_USES_VULKANSC
167 
168 
169 class InputAssemblyInstance : public vkt::TestInstance
170 {
171 public:
172 										InputAssemblyInstance	(Context&							context,
173 																 const PipelineConstructionType		pipelineConstructionType,
174 																 const VkPrimitiveTopology			primitiveTopology,
175 																 bool								testPrimitiveRestart,
176 																 VkIndexType						indexType,
177 																 const std::vector<deUint32>&		indexBufferData,
178 																 const std::vector<Vertex4RGBA>&	vertexBufferData);
179 	virtual								~InputAssemblyInstance	(void);
180 	virtual tcu::TestStatus				iterate					(void);
181 
182 private:
183 	tcu::TestStatus						verifyImage				(void);
184 	void								uploadIndexBufferData16	(deUint16* destPtr, const std::vector<deUint32>& indexBufferData);
185 	void								uploadIndexBufferData8	(deUint8* destPtr, const std::vector<deUint32>& indexBufferData);
186 
187 	VkPrimitiveTopology					m_primitiveTopology;
188 	bool								m_primitiveRestartEnable;
189 	VkIndexType							m_indexType;
190 
191 	Move<VkBuffer>						m_vertexBuffer;
192 	std::vector<Vertex4RGBA>			m_vertices;
193 	de::MovePtr<Allocation>				m_vertexBufferAlloc;
194 
195 	Move<VkBuffer>						m_indexBuffer;
196 	std::vector<deUint32>				m_indices;
197 	de::MovePtr<Allocation>				m_indexBufferAlloc;
198 
199 	const tcu::UVec2					m_renderSize;
200 
201 	const VkFormat						m_colorFormat;
202 	VkImageCreateInfo					m_colorImageCreateInfo;
203 	Move<VkImage>						m_colorImage;
204 	de::MovePtr<Allocation>				m_colorImageAlloc;
205 	Move<VkImageView>					m_colorAttachmentView;
206 	RenderPassWrapper					m_renderPass;
207 	Move<VkFramebuffer>					m_framebuffer;
208 
209 	ShaderWrapper						m_vertexShaderModule;
210 	ShaderWrapper						m_fragmentShaderModule;
211 	ShaderWrapper						m_tcsShaderModule;
212 	ShaderWrapper						m_tesShaderModule;
213 
214 	PipelineLayoutWrapper				m_pipelineLayout;
215 	GraphicsPipelineWrapper				m_graphicsPipeline;
216 
217 	Move<VkCommandPool>					m_cmdPool;
218 	Move<VkCommandBuffer>				m_cmdBuffer;
219 };
220 
221 
222 // InputAssemblyTest
223 
224 const VkPrimitiveTopology InputAssemblyTest::s_primitiveTopologies[] =
225 {
226 	VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
227 	VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
228 	VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
229 	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
230 	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
231 	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
232 	VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
233 	VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
234 	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
235 	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
236 };
237 
238 const deUint32 InputAssemblyTest::s_restartIndex32	= ~((deUint32)0u);
239 const deUint16 InputAssemblyTest::s_restartIndex16	= ~((deUint16)0u);
240 const deUint8 InputAssemblyTest::s_restartIndex8	= ~((deUint8)0u);
241 
InputAssemblyTest(tcu::TestContext& testContext, const std::string& name, const PipelineConstructionType pipelineConstructionType, VkPrimitiveTopology primitiveTopology, int primitiveCount, bool testPrimitiveRestart, VkIndexType indexType)242 InputAssemblyTest::InputAssemblyTest (tcu::TestContext&					testContext,
243 									  const std::string&				name,
244 									  const PipelineConstructionType	pipelineConstructionType,
245 									  VkPrimitiveTopology				primitiveTopology,
246 									  int								primitiveCount,
247 									  bool								testPrimitiveRestart,
248 									  VkIndexType						indexType)
249 	: vkt::TestCase				(testContext, name)
250 	, m_primitiveTopology		(primitiveTopology)
251 	, m_primitiveCount(primitiveCount)
252 	, m_pipelineConstructionType(pipelineConstructionType)
253 	, m_testPrimitiveRestart	(testPrimitiveRestart)
254 	, m_indexType				(indexType)
255 {
256 }
257 
checkSupport(Context& context) const258 void InputAssemblyTest::checkSupport (Context& context) const
259 {
260 	if (m_indexType == VK_INDEX_TYPE_UINT8_EXT)
261 		context.requireDeviceFunctionality("VK_EXT_index_type_uint8");
262 
263 	switch (m_primitiveTopology)
264 	{
265 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
266 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
267 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
268 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
269 			context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
270 			break;
271 
272 		case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
273 			context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
274 			break;
275 
276 		default:
277 			break;
278 	}
279 
280 	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
281 
282 #ifndef CTS_USES_VULKANSC
283 	if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN &&
284 		context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
285 		!context.getPortabilitySubsetFeatures().triangleFans)
286 	{
287 		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
288 	}
289 #endif // CTS_USES_VULKANSC
290 }
291 
createInstance(Context& context) const292 TestInstance* InputAssemblyTest::createInstance (Context& context) const
293 {
294 	std::vector<deUint32>		indexBufferData;
295 	std::vector<Vertex4RGBA>	vertexBufferData;
296 
297 	createBufferData(m_primitiveTopology, m_primitiveCount, m_indexType, indexBufferData, vertexBufferData);
298 
299 	return new InputAssemblyInstance(context, m_pipelineConstructionType, m_primitiveTopology, m_testPrimitiveRestart, m_indexType, indexBufferData, vertexBufferData);
300 }
301 
initPrograms(SourceCollections& sourceCollections) const302 void InputAssemblyTest::initPrograms (SourceCollections& sourceCollections) const
303 {
304 	std::ostringstream vertexSource;
305 
306 	vertexSource <<
307 		"#version 310 es\n"
308 		"layout(location = 0) in vec4 position;\n"
309 		"layout(location = 1) in vec4 color;\n"
310 		"layout(location = 0) out highp vec4 vtxColor;\n"
311 		"void main (void)\n"
312 		"{\n"
313 		"	gl_Position = position;\n"
314 		<< (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST ? "	gl_PointSize = 3.0;\n"
315 																	: "" )
316 		<< "	vtxColor = color;\n"
317 		"}\n";
318 
319 	sourceCollections.glslSources.add("color_vert") << glu::VertexSource(vertexSource.str());
320 
321 	sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(
322 		"#version 310 es\n"
323 		"layout(location = 0) in highp vec4 vtxColor;\n"
324 		"layout(location = 0) out highp vec4 fragColor;\n"
325 		"void main (void)\n"
326 		"{\n"
327 		"	fragColor = vtxColor;\n"
328 		"}\n");
329 
330 	sourceCollections.glslSources.add("color_tcs") << glu::TessellationControlSource(
331 		"#version 310 es\n"
332 		"#extension GL_EXT_tessellation_shader : require\n"
333 		"layout(vertices = 3) out;\n"
334 		"layout(location = 0) in highp vec4 vtxColorIn[];\n"
335 		"layout(location = 0) out highp vec4 vtxColorOut[];\n"
336 		"#define ID gl_InvocationID\n"
337 		"void main (void)\n"
338 		"{\n"
339 		"	vtxColorOut[ID] = vtxColorIn[ID];\n"
340 		"	gl_out[ID].gl_Position = gl_in[ID].gl_Position;\n"
341 		"	if (ID == 0)\n"
342 		"	{\n"
343 		"		gl_TessLevelInner[0] = 5.0;\n"
344 		"		gl_TessLevelOuter[0] = 4.0;\n"
345 		"		gl_TessLevelOuter[1] = 5.0;\n"
346 		"		gl_TessLevelOuter[2] = 6.0;\n"
347 		"	}\n"
348 		"}\n");
349 
350 	sourceCollections.glslSources.add("color_tes") << glu::TessellationEvaluationSource(
351 		"#version 310 es\n"
352 		"#extension GL_EXT_tessellation_shader : require\n"
353 		"layout(triangles) in;\n"
354 		"layout(location = 0) in vec4 vtxColorIn[];\n"
355 		"layout(location = 0) out vec4 vtxColorOut;\n"
356 		"void main (void)\n"
357 		"{\n"
358 		"	vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;\n"
359 		"	vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;\n"
360 		"	vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;\n"
361 		"	gl_Position = p0 + p1 + p2;\n"
362 		"	vec4 q0 = gl_TessCoord.x * vtxColorIn[0];\n"
363 		"	vec4 q1 = gl_TessCoord.y * vtxColorIn[1];\n"
364 		"	vec4 q2 = gl_TessCoord.z * vtxColorIn[2];\n"
365 		"	vtxColorOut = q0 + q1 + q2;\n"
366 		"}\n");
367 }
368 
isRestartIndex(VkIndexType indexType, deUint32 indexValue)369 bool InputAssemblyTest::isRestartIndex (VkIndexType indexType, deUint32 indexValue)
370 {
371 	if (indexType == VK_INDEX_TYPE_UINT16)
372 		return indexValue == s_restartIndex16;
373 	else if (indexType == VK_INDEX_TYPE_UINT8_EXT)
374 		return indexValue == s_restartIndex8;
375 	else
376 		return indexValue == s_restartIndex32;
377 }
378 
379 #ifndef CTS_USES_VULKANSC
getRestartIndex(VkIndexType indexType)380 deUint32 InputAssemblyTest::getRestartIndex (VkIndexType indexType)
381 {
382 	if (indexType == VK_INDEX_TYPE_UINT16)
383 		return InputAssemblyTest::s_restartIndex16;
384 	else if (indexType == VK_INDEX_TYPE_UINT8_EXT)
385 		return InputAssemblyTest::s_restartIndex8;
386 	else
387 		return InputAssemblyTest::s_restartIndex32;
388 }
389 #endif // CTS_USES_VULKANSC
390 
391 // PrimitiveTopologyTest
392 
PrimitiveTopologyTest(tcu::TestContext& testContext, const std::string& name, PipelineConstructionType pipelineConstructionType, VkPrimitiveTopology primitiveTopology, VkIndexType indexType)393 PrimitiveTopologyTest::PrimitiveTopologyTest (tcu::TestContext&			testContext,
394 											  const std::string&		name,
395 											  PipelineConstructionType	pipelineConstructionType,
396 											  VkPrimitiveTopology		primitiveTopology,
397 											  VkIndexType				indexType)
398 	: InputAssemblyTest	(testContext, name, pipelineConstructionType, primitiveTopology, 10, false, indexType)
399 {
400 }
401 
createBufferData(VkPrimitiveTopology topology, int primitiveCount, VkIndexType indexType, std::vector<deUint32>& indexData, std::vector<Vertex4RGBA>& vertexData) const402 void PrimitiveTopologyTest::createBufferData (VkPrimitiveTopology topology, int primitiveCount, VkIndexType indexType, std::vector<deUint32>& indexData, std::vector<Vertex4RGBA>& vertexData) const
403 {
404 	DE_ASSERT(primitiveCount > 0);
405 	DE_UNREF(indexType);
406 
407 	const tcu::Vec4				red						(1.0f, 0.0f, 0.0f, 1.0f);
408 	const tcu::Vec4				green					(0.0f, 1.0f, 0.0f, 1.0f);
409 	const float					border					= 0.2f;
410 	const float					originX					= -1.0f + border;
411 	const float					originY					= -1.0f + border;
412 	const Vertex4RGBA			defaultVertex			= { tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), green };
413 	float						primitiveSizeY			= (2.0f - 2.0f * border);
414 	float						primitiveSizeX;
415 	std::vector<deUint32>		indices;
416 	std::vector<Vertex4RGBA>	vertices;
417 
418 
419 	// Calculate primitive size
420 	switch (topology)
421 	{
422 		case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
423 			primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2 - 1);
424 			break;
425 
426 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
427 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
428 			primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount - 1);
429 			break;
430 
431 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
432 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
433 			primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2);
434 			break;
435 
436 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
437 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
438 			primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount + primitiveCount / 2 + primitiveCount % 2 - 1);
439 			break;
440 
441 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
442 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
443 			primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2);
444 			break;
445 
446 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
447 			primitiveSizeX = 1.0f - border;
448 			primitiveSizeY = 1.0f - border;
449 			break;
450 
451 		default:
452 			primitiveSizeX = 0.0f; // Garbage
453 			DE_ASSERT(false);
454 	}
455 
456 	switch (topology)
457 	{
458 		case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
459 			for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
460 			{
461 				const Vertex4RGBA vertex =
462 				{
463 					tcu::Vec4(originX + float(primitiveNdx / 2) * primitiveSizeX, originY + float(primitiveNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
464 					red
465 				};
466 
467 				vertices.push_back(vertex);
468 				indices.push_back(primitiveNdx);
469 			}
470 			break;
471 
472 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
473 			for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
474 			{
475 				for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++)
476 				{
477 					const Vertex4RGBA vertex =
478 					{
479 						tcu::Vec4(originX + float((primitiveNdx * 2 + vertexNdx) / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
480 						red
481 					};
482 
483 					vertices.push_back(vertex);
484 					indices.push_back((primitiveNdx * 2 + vertexNdx));
485 				}
486 			}
487 			break;
488 
489 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
490 			for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
491 			{
492 				if (primitiveNdx == 0)
493 				{
494 					Vertex4RGBA vertex =
495 					{
496 						tcu::Vec4(originX, originY, 0.0f, 1.0f),
497 						red
498 					};
499 
500 					vertices.push_back(vertex);
501 					indices.push_back(0);
502 
503 					vertex.position = tcu::Vec4(originX, originY + primitiveSizeY, 0.0f, 1.0f);
504 					vertices.push_back(vertex);
505 					indices.push_back(1);
506 				}
507 				else
508 				{
509 					const Vertex4RGBA vertex =
510 					{
511 						tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f),
512 						red
513 					};
514 
515 					vertices.push_back(vertex);
516 					indices.push_back(primitiveNdx + 1);
517 				}
518 			}
519 			break;
520 
521 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
522 			for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
523 			{
524 				for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++)
525 				{
526 					const Vertex4RGBA vertex =
527 					{
528 						tcu::Vec4(originX + float((primitiveNdx * 3 + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx * 3 + vertexNdx)% 2) * primitiveSizeY, 0.0f, 1.0f),
529 						red
530 					};
531 
532 					vertices.push_back(vertex);
533 					indices.push_back(primitiveNdx * 3 + vertexNdx);
534 				}
535 			}
536 			break;
537 
538 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
539 			for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
540 			{
541 				if (primitiveNdx == 0)
542 				{
543 					for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++)
544 					{
545 						const Vertex4RGBA vertex =
546 						{
547 							tcu::Vec4(originX + float(vertexNdx / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
548 							red
549 						};
550 
551 						vertices.push_back(vertex);
552 						indices.push_back(vertexNdx);
553 					}
554 				}
555 				else
556 				{
557 					const Vertex4RGBA vertex =
558 					{
559 						tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f),
560 						red
561 					};
562 
563 					vertices.push_back(vertex);
564 					indices.push_back(primitiveNdx + 2);
565 				}
566 			}
567 			break;
568 
569 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
570 		{
571 			const float stepAngle = de::min(DE_PI * 0.5f, (2 * DE_PI) / float(primitiveCount));
572 
573 			for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
574 			{
575 				if (primitiveNdx == 0)
576 				{
577 					Vertex4RGBA vertex =
578 					{
579 						tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
580 						red
581 					};
582 
583 					vertices.push_back(vertex);
584 					indices.push_back(0);
585 
586 					vertex.position = tcu::Vec4(primitiveSizeX, 0.0f, 0.0f, 1.0f);
587 					vertices.push_back(vertex);
588 					indices.push_back(1);
589 
590 					vertex.position = tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle), primitiveSizeY * deFloatSin(stepAngle), 0.0f, 1.0f);
591 					vertices.push_back(vertex);
592 					indices.push_back(2);
593 				}
594 				else
595 				{
596 					const Vertex4RGBA vertex =
597 					{
598 						tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle * float(primitiveNdx + 1)), primitiveSizeY * deFloatSin(stepAngle * float(primitiveNdx + 1)), 0.0f, 1.0f),
599 						red
600 					};
601 
602 					vertices.push_back(vertex);
603 					indices.push_back(primitiveNdx + 2);
604 				}
605 			}
606 			break;
607 		}
608 
609 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
610 			vertices.push_back(defaultVertex);
611 
612 			for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
613 			{
614 				indices.push_back(0);
615 
616 				for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++)
617 				{
618 					const Vertex4RGBA vertex =
619 					{
620 						tcu::Vec4(originX + float((primitiveNdx * 2 + vertexNdx) / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
621 						red
622 					};
623 
624 					vertices.push_back(vertex);
625 					indices.push_back(primitiveNdx * 2 + vertexNdx + 1);
626 				}
627 
628 				indices.push_back(0);
629 			}
630 			break;
631 
632 
633 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
634 			vertices.push_back(defaultVertex);
635 			indices.push_back(0);
636 
637 			for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
638 			{
639 				if (primitiveNdx == 0)
640 				{
641 					Vertex4RGBA vertex =
642 					{
643 						tcu::Vec4(originX, originY, 0.0f, 1.0f),
644 						red
645 					};
646 
647 					vertices.push_back(vertex);
648 					indices.push_back(1);
649 
650 					vertex.position = tcu::Vec4(originX, originY + primitiveSizeY, 0.0f, 1.0f);
651 					vertices.push_back(vertex);
652 					indices.push_back(2);
653 				}
654 				else
655 				{
656 					const Vertex4RGBA vertex =
657 					{
658 						tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f),
659 						red
660 					};
661 
662 					vertices.push_back(vertex);
663 					indices.push_back(primitiveNdx + 2);
664 				}
665 			}
666 
667 			indices.push_back(0);
668 			break;
669 
670 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
671 			vertices.push_back(defaultVertex);
672 
673 			for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
674 			{
675 				for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++)
676 				{
677 					const Vertex4RGBA vertex =
678 					{
679 						tcu::Vec4(originX + float((primitiveNdx * 3 + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx * 3 + vertexNdx)% 2) * primitiveSizeY, 0.0f, 1.0f),
680 						red
681 					};
682 
683 					vertices.push_back(vertex);
684 					indices.push_back(primitiveNdx * 3 + vertexNdx + 1);
685 					indices.push_back(0);
686 				}
687 			}
688 			break;
689 
690 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
691 			vertices.push_back(defaultVertex);
692 
693 			for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
694 			{
695 				if (primitiveNdx == 0)
696 				{
697 					for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++)
698 					{
699 						const Vertex4RGBA vertex =
700 						{
701 							tcu::Vec4(originX + float(vertexNdx / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
702 							red
703 						};
704 
705 						vertices.push_back(vertex);
706 						indices.push_back(vertexNdx + 1);
707 						indices.push_back(0);
708 					}
709 				}
710 				else
711 				{
712 					const Vertex4RGBA vertex =
713 					{
714 						tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f),
715 						red
716 					};
717 
718 					vertices.push_back(vertex);
719 					indices.push_back(primitiveNdx + 2 + 1);
720 					indices.push_back(0);
721 				}
722 			}
723 			break;
724 
725 		default:
726 			DE_ASSERT(false);
727 			break;
728 	}
729 
730 	vertexData	= vertices;
731 	indexData	= indices;
732 }
733 
734 #ifndef CTS_USES_VULKANSC
735 // PrimitiveRestartTest
736 
PrimitiveRestartTest(tcu::TestContext& testContext, const std::string& name, PipelineConstructionType pipelineConstructionType, VkPrimitiveTopology primitiveTopology, VkIndexType indexType, RestartType restartType)737 PrimitiveRestartTest::PrimitiveRestartTest (tcu::TestContext&			testContext,
738 											const std::string&			name,
739 											PipelineConstructionType	pipelineConstructionType,
740 											VkPrimitiveTopology			primitiveTopology,
741 											VkIndexType					indexType,
742 											RestartType					restartType)
743 
744 	: InputAssemblyTest	(testContext, name, pipelineConstructionType, primitiveTopology, 10, true, indexType)
745 	, m_restartType(restartType)
746 {
747 	deUint32 restartPrimitives[] = { 1, 5 };
748 
749 	if (restartType == RestartType::NORMAL)
750 	{
751 		m_restartPrimitives = std::vector<deUint32>(restartPrimitives, restartPrimitives + sizeof(restartPrimitives) / sizeof(deUint32));
752 	}
753 	else if (restartType == RestartType::NONE)
754 	{
755 		m_restartPrimitives = std::vector<deUint32>{};
756 	}
757 	else
758 	{
759 		deUint32 count = 1;
760 		switch (primitiveTopology)
761 		{
762 			case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
763 			case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
764 			case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
765 			case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
766 				count = 2;
767 				break;
768 			case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
769 			case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
770 			case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
771 			case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
772 			case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
773 				count = 3;
774 				break;
775 			default:
776 				break;
777 		}
778 		for (deUint32 i = 0; i < (deUint32)m_primitiveCount; ++i)
779 		{
780 			if (i % count == count - 1)
781 			{
782 				m_restartPrimitives.push_back(i);
783 			}
784 		}
785 	}
786 }
787 
checkSupport(Context& context) const788 void PrimitiveRestartTest::checkSupport (Context& context) const
789 {
790 	switch (m_primitiveTopology)
791 	{
792 		case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
793 		case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
794 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
795 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
796 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
797 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
798 		{
799 			context.requireDeviceFunctionality("VK_EXT_primitive_topology_list_restart");
800 
801 			const auto& features = context.getPrimitiveTopologyListRestartFeaturesEXT();
802 			if (!features.primitiveTopologyListRestart)
803 				TCU_THROW(NotSupportedError, "Primitive topology list restart feature not supported");
804 			if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && !features.primitiveTopologyPatchListRestart)
805 				TCU_THROW(NotSupportedError, "Primitive topology patch list restart feature not supported");
806 		}
807 		break;
808 
809 		default:
810 		break;
811 	}
812 
813 	InputAssemblyTest::checkSupport(context);
814 }
815 
createBufferData(VkPrimitiveTopology topology, int primitiveCount, VkIndexType indexType, std::vector<deUint32>& indexData, std::vector<Vertex4RGBA>& vertexData) const816 void PrimitiveRestartTest::createBufferData (VkPrimitiveTopology topology, int primitiveCount, VkIndexType indexType, std::vector<deUint32>& indexData, std::vector<Vertex4RGBA>& vertexData) const
817 {
818 	DE_ASSERT(primitiveCount > 0);
819 	DE_UNREF(indexType);
820 
821 	const tcu::Vec4				red						(1.0f, 0.0f, 0.0f, 1.0f);
822 	const tcu::Vec4				green					(0.0f, 1.0f, 0.0f, 1.0f);
823 	const float					border					= 0.2f;
824 	const float					originX					= -1.0f + border;
825 	const float					originY					= -1.0f + border;
826 	const Vertex4RGBA			defaultVertex			= { tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), green };
827 	float						primitiveSizeY			= (2.0f - 2.0f * border);
828 	float						primitiveSizeX;
829 	bool						primitiveStart			= true;
830 	std::vector<deUint32>		indices;
831 	std::vector<Vertex4RGBA>	vertices;
832 
833 	// Calculate primitive size
834 	switch (topology)
835 	{
836 		case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
837 			primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2 - 1);
838 			break;
839 
840 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
841 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
842 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
843 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
844 			primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2);
845 			break;
846 
847 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
848 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
849 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
850 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
851 		case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
852 			primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2);
853 			break;
854 
855 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
856 			primitiveSizeX = 1.0f - border;
857 			primitiveSizeY = 1.0f - border;
858 			break;
859 
860 		default:
861 			primitiveSizeX = 0.0f; // Garbage
862 			DE_ASSERT(false);
863 	}
864 
865 	switch (topology)
866 	{
867 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
868 			for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
869 			{
870 				if (isRestartPrimitive(primitiveNdx))
871 				{
872 					indices.push_back(InputAssemblyTest::getRestartIndex(indexType));
873 					primitiveStart = true;
874 				}
875 				else
876 				{
877 					if (primitiveStart && m_restartType != RestartType::ALL)
878 					{
879 						const Vertex4RGBA vertex =
880 						{
881 							tcu::Vec4(originX + float(primitiveNdx / 2) * primitiveSizeX, originY + float(primitiveNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
882 							red
883 						};
884 
885 						vertices.push_back(vertex);
886 						indices.push_back((deUint32)vertices.size() - 1);
887 
888 						primitiveStart = false;
889 					}
890 
891 					const Vertex4RGBA vertex =
892 					{
893 						tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f),
894 						red
895 					};
896 
897 					vertices.push_back(vertex);
898 					indices.push_back((deUint32)vertices.size() - 1);
899 				}
900 			}
901 			break;
902 
903 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
904 		{
905 			for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
906 			{
907 				if (isRestartPrimitive(primitiveNdx))
908 				{
909 					indices.push_back(InputAssemblyTest::getRestartIndex(indexType));
910 					primitiveStart = true;
911 				}
912 				else
913 				{
914 					if (primitiveStart && m_restartType != RestartType::ALL)
915 					{
916 						for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++)
917 						{
918 							const Vertex4RGBA vertex =
919 							{
920 								tcu::Vec4(originX + float((primitiveNdx + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx + vertexNdx) % 2) * primitiveSizeY, 0.0f, 1.0f),
921 								red
922 							};
923 
924 							vertices.push_back(vertex);
925 							indices.push_back((deUint32)vertices.size() - 1);
926 						}
927 
928 						primitiveStart = false;
929 					}
930 					const Vertex4RGBA vertex =
931 					{
932 						tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f),
933 						red
934 					};
935 
936 					vertices.push_back(vertex);
937 					indices.push_back((deUint32)vertices.size() - 1);
938 				}
939 			}
940 			break;
941 		}
942 
943 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
944 		{
945 			const float stepAngle = de::min(DE_PI * 0.5f, (2 * DE_PI) / float(primitiveCount));
946 
947 			for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
948 			{
949 				if (isRestartPrimitive(primitiveNdx))
950 				{
951 					indices.push_back(InputAssemblyTest::getRestartIndex(indexType));
952 					primitiveStart = true;
953 				}
954 				else
955 				{
956 					if (primitiveStart && m_restartType != RestartType::ALL)
957 					{
958 						Vertex4RGBA vertex =
959 						{
960 							tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
961 							red
962 						};
963 
964 						vertices.push_back(vertex);
965 						indices.push_back((deUint32)vertices.size() - 1);
966 
967 						vertex.position = tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle * float(primitiveNdx)), primitiveSizeY * deFloatSin(stepAngle * float(primitiveNdx)), 0.0f, 1.0f);
968 						vertices.push_back(vertex);
969 						indices.push_back((deUint32)vertices.size() - 1);
970 
971 						primitiveStart = false;
972 					}
973 
974 					const Vertex4RGBA vertex =
975 					{
976 						tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle * float(primitiveNdx + 1)), primitiveSizeY * deFloatSin(stepAngle * float(primitiveNdx + 1)), 0.0f, 1.0f),
977 						red
978 					};
979 
980 					vertices.push_back(vertex);
981 					indices.push_back((deUint32)vertices.size() - 1);
982 				}
983 			}
984 			break;
985 		}
986 
987 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
988 			vertices.push_back(defaultVertex);
989 
990 			for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
991 			{
992 				if (isRestartPrimitive(primitiveNdx))
993 				{
994 					indices.push_back(0);
995 					indices.push_back(InputAssemblyTest::getRestartIndex(indexType));
996 					primitiveStart = true;
997 				}
998 				else
999 				{
1000 					if (primitiveStart && m_restartType != RestartType::ALL)
1001 					{
1002 						indices.push_back(0);
1003 
1004 						const Vertex4RGBA vertex =
1005 						{
1006 							tcu::Vec4(originX + float(primitiveNdx / 2) * primitiveSizeX, originY + float(primitiveNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
1007 							red
1008 						};
1009 
1010 						vertices.push_back(vertex);
1011 						indices.push_back((deUint32)vertices.size() - 1);
1012 
1013 						primitiveStart = false;
1014 					}
1015 
1016 					const Vertex4RGBA vertex =
1017 					{
1018 						tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f),
1019 						red
1020 					};
1021 
1022 					vertices.push_back(vertex);
1023 					indices.push_back((deUint32)vertices.size() - 1);
1024 				}
1025 			}
1026 
1027 			indices.push_back(0);
1028 			break;
1029 
1030 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
1031 			vertices.push_back(defaultVertex);
1032 
1033 			for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
1034 			{
1035 				if (isRestartPrimitive(primitiveNdx))
1036 				{
1037 					indices.push_back(InputAssemblyTest::getRestartIndex(indexType));
1038 					primitiveStart = true;
1039 				}
1040 				else
1041 				{
1042 					if (primitiveStart && m_restartType != RestartType::ALL)
1043 					{
1044 						for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++)
1045 						{
1046 							const Vertex4RGBA vertex =
1047 							{
1048 								tcu::Vec4(originX + float((primitiveNdx + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx + vertexNdx) % 2) * primitiveSizeY, 0.0f, 1.0f),
1049 								red
1050 							};
1051 
1052 							vertices.push_back(vertex);
1053 							indices.push_back((deUint32)vertices.size() - 1);
1054 							indices.push_back(0);
1055 						}
1056 
1057 						primitiveStart = false;
1058 					}
1059 
1060 					const Vertex4RGBA vertex =
1061 					{
1062 						tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f),
1063 						red
1064 					};
1065 
1066 					vertices.push_back(vertex);
1067 					indices.push_back((deUint32)vertices.size() - 1);
1068 					indices.push_back(0);
1069 				}
1070 			}
1071 			break;
1072 
1073 		case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
1074 			createListPrimitives(primitiveCount, originX, originY, primitiveSizeX, primitiveSizeY,
1075 								 1, indexType, indices, vertices, std::vector<deUint32>());
1076 			break;
1077 
1078 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
1079 			createListPrimitives(primitiveCount, originX, originY, primitiveSizeX, primitiveSizeY,
1080 								 2, indexType, indices, vertices, std::vector<deUint32>());
1081 			break;
1082 
1083 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
1084 		{
1085 			std::vector<deUint32> adjacencies = { 0, 3 };
1086 
1087 			createListPrimitives(primitiveCount, originX, originY, primitiveSizeX, primitiveSizeY,
1088 								 4, indexType, indices, vertices, adjacencies);
1089 		}
1090 		break;
1091 
1092 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
1093 		case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
1094 			createListPrimitives(primitiveCount, originX, originY, primitiveSizeX, primitiveSizeY,
1095 						3, indexType, indices, vertices, std::vector<deUint32>());
1096 			break;
1097 
1098 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
1099 		{
1100 			std::vector<deUint32> adjacencies = { 1, 3, 5 };
1101 
1102 			createListPrimitives(primitiveCount, originX, originY, primitiveSizeX, primitiveSizeY,
1103 								 6, indexType, indices, vertices, adjacencies);
1104 		}
1105 		break;
1106 
1107 		default:
1108 			DE_ASSERT(false);
1109 			break;
1110 	}
1111 
1112 	vertexData	= vertices;
1113 	indexData	= indices;
1114 }
1115 
createListPrimitives(int primitiveCount, float originX, float originY, float primitiveSizeX, float primitiveSizeY, int verticesPerPrimitive, VkIndexType indexType, std::vector<deUint32>& indexData, std::vector<Vertex4RGBA>& vertexData, std::vector<deUint32> adjacencies) const1116 void PrimitiveRestartTest::createListPrimitives (int						primitiveCount,
1117 												 float						originX,
1118 												 float						originY,
1119 												 float						primitiveSizeX,
1120 												 float						primitiveSizeY,
1121 												 int						verticesPerPrimitive,
1122 												 VkIndexType				indexType,
1123 												 std::vector<deUint32>&		indexData,
1124 												 std::vector<Vertex4RGBA>&	vertexData,
1125 												 std::vector<deUint32>		adjacencies) const
1126 {
1127 	const tcu::Vec4	red		(1.0f, 0.0f, 0.0f, 1.0f);
1128 	const tcu::Vec4	green	(0.0f, 1.0f, 0.0f, 1.0f);
1129 	// Tells which vertex of a primitive is used as a restart index.
1130 	// This is decreased each time a restart primitive is used.
1131 	int restartVertexIndex = verticesPerPrimitive - 1;
1132 
1133 	for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
1134 	{
1135 		deUint32 nonAdjacentVertexNdx = 0;
1136 
1137 		for (int vertexNdx = 0; vertexNdx < verticesPerPrimitive; vertexNdx++)
1138 		{
1139 			if (isRestartPrimitive(primitiveNdx) && vertexNdx == restartVertexIndex)
1140 			{
1141 				indexData.push_back(InputAssemblyTest::getRestartIndex(indexType));
1142 
1143 				restartVertexIndex--;
1144 				if (restartVertexIndex < 0) restartVertexIndex = verticesPerPrimitive - 1;
1145 
1146 				break;
1147 			}
1148 
1149 			if (std::find(adjacencies.begin(), adjacencies.end(), vertexNdx) != adjacencies.end())
1150 			{
1151 				// This is an adjacency vertex index. Add a green vertex that should never end up to the framebuffer.
1152 				const Vertex4RGBA vertex =
1153 				{
1154 					tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
1155 					green
1156 				};
1157 				vertexData.push_back(vertex);
1158 				indexData.push_back((deUint32) vertexData.size() - 1);
1159 				continue;
1160 			}
1161 
1162 			const Vertex4RGBA vertex =
1163 			{
1164 				tcu::Vec4(originX + float((primitiveNdx + nonAdjacentVertexNdx) / 2) * primitiveSizeX,
1165 						  originY + float((primitiveNdx + nonAdjacentVertexNdx) % 2) * primitiveSizeY, 0.0f, 1.0f),
1166 						  red
1167 			};
1168 
1169 			vertexData.push_back(vertex);
1170 			indexData.push_back((deUint32) vertexData.size() - 1);
1171 			nonAdjacentVertexNdx++;
1172 		}
1173 	}
1174 }
1175 
isRestartPrimitive(int primitiveIndex) const1176 bool PrimitiveRestartTest::isRestartPrimitive (int primitiveIndex) const
1177 {
1178 	return std::find(m_restartPrimitives.begin(), m_restartPrimitives.end(), primitiveIndex) != m_restartPrimitives.end();
1179 }
1180 #endif // CTS_USES_VULKANSC
1181 
1182 // InputAssemblyInstance
1183 
InputAssemblyInstance(Context& context, PipelineConstructionType pipelineConstructionType, VkPrimitiveTopology primitiveTopology, bool testPrimitiveRestart, VkIndexType indexType, const std::vector<deUint32>& indexBufferData, const std::vector<Vertex4RGBA>& vertexBufferData)1184 InputAssemblyInstance::InputAssemblyInstance (Context&							context,
1185 											  PipelineConstructionType			pipelineConstructionType,
1186 											  VkPrimitiveTopology				primitiveTopology,
1187 											  bool								testPrimitiveRestart,
1188 											  VkIndexType						indexType,
1189 											  const std::vector<deUint32>&		indexBufferData,
1190 											  const std::vector<Vertex4RGBA>&	vertexBufferData)
1191 
1192 	: vkt::TestInstance			(context)
1193 	, m_primitiveTopology		(primitiveTopology)
1194 	, m_primitiveRestartEnable	(testPrimitiveRestart)
1195 	, m_indexType				(indexType)
1196 	, m_vertices				(vertexBufferData)
1197 	, m_indices					(indexBufferData)
1198 	, m_renderSize				((primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN) ? tcu::UVec2(32, 32) : tcu::UVec2(64, 16))
1199 	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
1200 	, m_graphicsPipeline		(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType)
1201 {
1202 	const DeviceInterface&			vk						= context.getDeviceInterface();
1203 	const VkDevice					vkDevice				= context.getDevice();
1204 	const deUint32					queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
1205 	SimpleAllocator					memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
1206 	const VkComponentMapping		componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
1207 	const bool						patchList				= m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
1208 
1209 	// Create color image
1210 	{
1211 		const VkImageCreateInfo colorImageParams =
1212 		{
1213 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
1214 			DE_NULL,																	// const void*				pNext;
1215 			0u,																			// VkImageCreateFlags		flags;
1216 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
1217 			m_colorFormat,																// VkFormat					format;
1218 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
1219 			1u,																			// deUint32					mipLevels;
1220 			1u,																			// deUint32					arrayLayers;
1221 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
1222 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
1223 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
1224 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
1225 			1u,																			// deUint32					queueFamilyIndexCount;
1226 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
1227 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
1228 		};
1229 
1230 		m_colorImageCreateInfo	= colorImageParams;
1231 		m_colorImage			= createImage(vk, vkDevice, &m_colorImageCreateInfo);
1232 
1233 		// Allocate and bind color image memory
1234 		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
1235 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
1236 	}
1237 
1238 	// Create color attachment view
1239 	{
1240 		const VkImageViewCreateInfo colorAttachmentViewParams =
1241 		{
1242 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
1243 			DE_NULL,											// const void*				pNext;
1244 			0u,													// VkImageViewCreateFlags	flags;
1245 			*m_colorImage,										// VkImage					image;
1246 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
1247 			m_colorFormat,										// VkFormat					format;
1248 			componentMappingRGBA,								// VkComponentMapping		components;
1249 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },		// VkImageSubresourceRange	subresourceRange;
1250 		};
1251 
1252 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
1253 	}
1254 
1255 	// Create render pass
1256 	m_renderPass = RenderPassWrapper(pipelineConstructionType, vk, vkDevice, m_colorFormat);
1257 
1258 	// Create framebuffer
1259 	{
1260 		const VkFramebufferCreateInfo framebufferParams =
1261 		{
1262 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
1263 			DE_NULL,											// const void*				pNext;
1264 			0u,													// VkFramebufferCreateFlags	flags;
1265 			*m_renderPass,										// VkRenderPass				renderPass;
1266 			1u,													// deUint32					attachmentCount;
1267 			&m_colorAttachmentView.get(),						// const VkImageView*		pAttachments;
1268 			(deUint32)m_renderSize.x(),							// deUint32					width;
1269 			(deUint32)m_renderSize.y(),							// deUint32					height;
1270 			1u													// deUint32					layers;
1271 		};
1272 
1273 		m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, *m_colorImage);
1274 	}
1275 
1276 	// Create pipeline layout
1277 	{
1278 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1279 		{
1280 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
1281 			DE_NULL,											// const void*						pNext;
1282 			0u,													// VkPipelineLayoutCreateFlags		flags;
1283 			0u,													// deUint32							setLayoutCount;
1284 			DE_NULL,											// const VkDescriptorSetLayout*		pSetLayouts;
1285 			0u,													// deUint32							pushConstantRangeCount;
1286 			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
1287 		};
1288 
1289 		m_pipelineLayout = PipelineLayoutWrapper(pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
1290 	}
1291 
1292 	m_vertexShaderModule	= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
1293 	m_fragmentShaderModule	= ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
1294 
1295 	if (patchList)
1296 	{
1297 		m_tcsShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_tcs"), 0);
1298 		m_tesShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_tes"), 0);
1299 	}
1300 
1301 	// Create pipeline
1302 	{
1303 		const VkVertexInputBindingDescription vertexInputBindingDescription =
1304 		{
1305 			0u,								// deUint32					binding;
1306 			sizeof(Vertex4RGBA),			// deUint32					stride;
1307 			VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputRate		inputRate;
1308 		};
1309 
1310 		const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
1311 		{
1312 			{
1313 				0u,									// deUint32	location;
1314 				0u,									// deUint32	binding;
1315 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
1316 				0u									// deUint32	offset;
1317 			},
1318 			{
1319 				1u,									// deUint32	location;
1320 				0u,									// deUint32	binding;
1321 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
1322 				DE_OFFSET_OF(Vertex4RGBA, color),	// deUint32	offset;
1323 			}
1324 		};
1325 
1326 		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
1327 		{
1328 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType								sType;
1329 			DE_NULL,														// const void*									pNext;
1330 			0u,																// VkPipelineVertexInputStateCreateFlags		flags;
1331 			1u,																// deUint32										vertexBindingDescriptionCount;
1332 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
1333 			2u,																// deUint32										vertexAttributeDescriptionCount;
1334 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*		pVertexAttributeDescriptions;
1335 		};
1336 
1337 		const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
1338 		{
1339 			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
1340 			DE_NULL,														// const void*								pNext;
1341 			0u,																// VkPipelineInputAssemblyStateCreateFlags	flags;
1342 			m_primitiveTopology,											// VkPrimitiveTopology						topology;
1343 			m_primitiveRestartEnable										// VkBool32									primitiveRestartEnable;
1344 		};
1345 
1346 		const std::vector<VkViewport>	viewport	{ makeViewport(m_renderSize) };
1347 		const std::vector<VkRect2D>		scissor		{ makeRect2D(m_renderSize) };
1348 
1349 		const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1350 		{
1351 			false,															// VkBool32					blendEnable;
1352 			VK_BLEND_FACTOR_ONE,											// VkBlendFactor			srcColorBlendFactor;
1353 			VK_BLEND_FACTOR_ZERO,											// VkBlendFactor			dstColorBlendFactor;
1354 			VK_BLEND_OP_ADD,												// VkBlendOp				colorBlendOp;
1355 			VK_BLEND_FACTOR_ONE,											// VkBlendFactor			srcAlphaBlendFactor;
1356 			VK_BLEND_FACTOR_ZERO,											// VkBlendFactor			dstAlphaBlendFactor;
1357 			VK_BLEND_OP_ADD,												// VkBlendOp				alphaBlendOp;
1358 			VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |			// VkColorComponentFlags	colorWriteMask;
1359 				VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
1360 		};
1361 
1362 		const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
1363 		{
1364 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
1365 			DE_NULL,													// const void*									pNext;
1366 			0u,															// VkPipelineColorBlendStateCreateFlags			flags;
1367 			false,														// VkBool32										logicOpEnable;
1368 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
1369 			1u,															// deUint32										attachmentCount;
1370 			&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
1371 			{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4];
1372 		};
1373 
1374 		VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
1375 		{
1376 			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
1377 			DE_NULL,													// const void*								pNext;
1378 			0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
1379 			false,														// VkBool32									depthTestEnable;
1380 			false,														// VkBool32									depthWriteEnable;
1381 			VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
1382 			false,														// VkBool32									depthBoundsTestEnable;
1383 			false,														// VkBool32									stencilTestEnable;
1384 			// VkStencilOpState	front;
1385 			{
1386 				VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
1387 				VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
1388 				VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
1389 				VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
1390 				0u,						// deUint32		compareMask;
1391 				0u,						// deUint32		writeMask;
1392 				0u,						// deUint32		reference;
1393 			},
1394 			// VkStencilOpState	back;
1395 			{
1396 				VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
1397 				VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
1398 				VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
1399 				VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
1400 				0u,						// deUint32		compareMask;
1401 				0u,						// deUint32		writeMask;
1402 				0u,						// deUint32		reference;
1403 			},
1404 			0.0f,														// float			minDepthBounds;
1405 			1.0f														// float			maxDepthBounds;
1406 		};
1407 
1408 		m_graphicsPipeline.setDefaultRasterizationState()
1409 						  .setDefaultMultisampleState()
1410 						  .setupVertexInputState(&vertexInputStateParams, &inputAssemblyStateParams)
1411 						  .setupPreRasterizationShaderState(viewport,
1412 											scissor,
1413 											m_pipelineLayout,
1414 											*m_renderPass,
1415 											0u,
1416 											m_vertexShaderModule,
1417 											DE_NULL,
1418 											m_tcsShaderModule,
1419 											m_tesShaderModule)
1420 						  .setupFragmentShaderState(m_pipelineLayout,
1421 											*m_renderPass,
1422 											0u,
1423 											m_fragmentShaderModule,
1424 											&depthStencilStateParams)
1425 						  .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateParams)
1426 						  .setMonolithicPipelineLayout(m_pipelineLayout)
1427 						  .buildPipeline();
1428 	}
1429 
1430 	// Create vertex and index buffer
1431 	{
1432 		const VkBufferCreateInfo indexBufferParams =
1433 		{
1434 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1435 			DE_NULL,									// const void*			pNext;
1436 			0u,											// VkBufferCreateFlags	flags;
1437 			m_indices.size() * sizeof(deUint32),		// VkDeviceSize			size;
1438 			VK_BUFFER_USAGE_INDEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
1439 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1440 			1u,											// deUint32				queueFamilyIndexCount;
1441 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
1442 		};
1443 
1444 		const VkBufferCreateInfo vertexBufferParams =
1445 		{
1446 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1447 			DE_NULL,									// const void*			pNext;
1448 			0u,											// VkBufferCreateFlags	flags;
1449 			m_vertices.size() * sizeof(Vertex4RGBA),	// VkDeviceSize			size;
1450 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
1451 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1452 			1u,											// deUint32				queueFamilyIndexCount;
1453 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
1454 		};
1455 
1456 		m_indexBuffer		= createBuffer(vk, vkDevice, &indexBufferParams);
1457 		m_indexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_indexBuffer), MemoryRequirement::HostVisible);
1458 
1459 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_indexBuffer, m_indexBufferAlloc->getMemory(), m_indexBufferAlloc->getOffset()));
1460 
1461 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
1462 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
1463 
1464 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
1465 
1466 		// Load vertices into index buffer
1467 		if (m_indexType == VK_INDEX_TYPE_UINT32)
1468 		{
1469 			deMemcpy(m_indexBufferAlloc->getHostPtr(), m_indices.data(), m_indices.size() * sizeof(deUint32));
1470 		}
1471 		else if (m_indexType == VK_INDEX_TYPE_UINT8_EXT)
1472 		{
1473 			uploadIndexBufferData8((deUint8*)m_indexBufferAlloc->getHostPtr(), m_indices);
1474 		}
1475 		else // m_indexType == VK_INDEX_TYPE_UINT16
1476 		{
1477 			uploadIndexBufferData16((deUint16*)m_indexBufferAlloc->getHostPtr(), m_indices);
1478 		}
1479 
1480 		// Load vertices into vertex buffer
1481 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
1482 
1483 		flushAlloc(vk, vkDevice, *m_indexBufferAlloc);
1484 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
1485 	}
1486 
1487 	// Create command pool
1488 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1489 
1490 	// Create command buffer
1491 	{
1492 		const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
1493 
1494 		const VkImageMemoryBarrier attachmentLayoutBarrier =
1495 		{
1496 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
1497 			DE_NULL,										// const void*				pNext;
1498 			0u,												// VkAccessFlags			srcAccessMask;
1499 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
1500 			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
1501 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			newLayout;
1502 			VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
1503 			VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
1504 			*m_colorImage,									// VkImage					image;
1505 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
1506 		};
1507 
1508 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1509 
1510 		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1511 
1512 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0,
1513 			0u, DE_NULL, 0u, DE_NULL, 1u, &attachmentLayoutBarrier);
1514 
1515 		m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
1516 
1517 		const VkDeviceSize vertexBufferOffset = 0;
1518 
1519 		m_graphicsPipeline.bind(*m_cmdBuffer);
1520 		vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1521 		vk.cmdBindIndexBuffer(*m_cmdBuffer, *m_indexBuffer, 0, m_indexType);
1522 		vk.cmdDrawIndexed(*m_cmdBuffer, (deUint32)m_indices.size(), 1, 0, 0, 0);
1523 
1524 		m_renderPass.end(vk, *m_cmdBuffer);
1525 		endCommandBuffer(vk, *m_cmdBuffer);
1526 	}
1527 }
1528 
~InputAssemblyInstance(void)1529 InputAssemblyInstance::~InputAssemblyInstance (void)
1530 {
1531 }
1532 
iterate(void)1533 tcu::TestStatus InputAssemblyInstance::iterate (void)
1534 {
1535 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
1536 	const VkDevice				vkDevice	= m_context.getDevice();
1537 	const VkQueue				queue		= m_context.getUniversalQueue();
1538 
1539 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1540 
1541 	return verifyImage();
1542 }
1543 
verifyImage(void)1544 tcu::TestStatus InputAssemblyInstance::verifyImage (void)
1545 {
1546 	const tcu::TextureFormat	tcuColorFormat		= mapVkFormat(m_colorFormat);
1547 	const tcu::TextureFormat	tcuStencilFormat	= tcu::TextureFormat();
1548 	const ColorVertexShader		vertexShader;
1549 	const ColorFragmentShader	fragmentShader		(tcuColorFormat, tcuStencilFormat);
1550 	const rr::Program			program				(&vertexShader, &fragmentShader);
1551 	ReferenceRenderer			refRenderer			(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program);
1552 	bool						compareOk			= false;
1553 
1554 	// Render reference image
1555 	{
1556 		// The reference for tessellated patches are drawn using ordinary triangles.
1557 		const rr::PrimitiveType		topology	= m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST ? rr::PrimitiveType::PRIMITIVETYPE_TRIANGLES : mapVkPrimitiveTopology(m_primitiveTopology);
1558 		rr::RenderState				renderState	(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits);
1559 
1560 		if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
1561 			renderState.point.pointSize = 3.0f;
1562 
1563 		if (m_primitiveRestartEnable)
1564 		{
1565 			std::vector<deUint32> indicesRange;
1566 
1567 			for (size_t indexNdx = 0; indexNdx < m_indices.size(); indexNdx++)
1568 			{
1569 				const bool isRestart = InputAssemblyTest::isRestartIndex(m_indexType, m_indices[indexNdx]);
1570 
1571 				if (!isRestart)
1572 					indicesRange.push_back(m_indices[indexNdx]);
1573 
1574 				if (isRestart || indexNdx == (m_indices.size() - 1))
1575 				{
1576 					// Draw the range of indices found so far
1577 
1578 					std::vector<Vertex4RGBA> nonIndexedVertices;
1579 					for (size_t i = 0; i < indicesRange.size(); i++)
1580 						nonIndexedVertices.push_back(m_vertices[indicesRange[i]]);
1581 
1582 					refRenderer.draw(renderState, topology, nonIndexedVertices);
1583 					indicesRange.clear();
1584 				}
1585 			}
1586 		}
1587 		else
1588 		{
1589 			std::vector<Vertex4RGBA> nonIndexedVertices;
1590 			for (size_t i = 0; i < m_indices.size(); i++)
1591 				nonIndexedVertices.push_back(m_vertices[m_indices[i]]);
1592 
1593 			refRenderer.draw(renderState, topology, nonIndexedVertices);
1594 		}
1595 	}
1596 
1597 	// Compare result with reference image
1598 	{
1599 		const DeviceInterface&				vk					= m_context.getDeviceInterface();
1600 		const VkDevice						vkDevice			= m_context.getDevice();
1601 		const VkQueue						queue				= m_context.getUniversalQueue();
1602 		const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1603 		SimpleAllocator						allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1604 		de::UniquePtr<tcu::TextureLevel>	result				(readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
1605 
1606 		compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
1607 															  "IntImageCompare",
1608 															  "Image comparison",
1609 															  refRenderer.getAccess(),
1610 															  result->getAccess(),
1611 															  tcu::UVec4(2, 2, 2, 2),
1612 															  tcu::IVec3(1, 1, 0),
1613 															  true,
1614 															  tcu::COMPARE_LOG_RESULT);
1615 	}
1616 
1617 	if (compareOk)
1618 		return tcu::TestStatus::pass("Result image matches reference");
1619 	else
1620 		return tcu::TestStatus::fail("Image mismatch");
1621 }
1622 
uploadIndexBufferData16(deUint16* destPtr, const std::vector<deUint32>& indexBufferData)1623 void InputAssemblyInstance::uploadIndexBufferData16	(deUint16* destPtr, const std::vector<deUint32>& indexBufferData)
1624 {
1625 	for (size_t i = 0; i < indexBufferData.size(); i++)
1626 	{
1627 		DE_ASSERT(indexBufferData[i] <= 0xFFFF);
1628 		destPtr[i] = (deUint16)indexBufferData[i];
1629 	}
1630 }
1631 
uploadIndexBufferData8(deUint8* destPtr, const std::vector<deUint32>& indexBufferData)1632 void InputAssemblyInstance::uploadIndexBufferData8	(deUint8* destPtr, const std::vector<deUint32>& indexBufferData)
1633 {
1634 	for (size_t i = 0; i < indexBufferData.size(); i++)
1635 	{
1636 		DE_ASSERT(indexBufferData[i] <= 0xFF);
1637 		destPtr[i] = (deUint8)indexBufferData[i];
1638 	}
1639 }
1640 
1641 
1642 // Utilities for test names
1643 
getPrimitiveTopologyCaseName(VkPrimitiveTopology topology)1644 std::string getPrimitiveTopologyCaseName (VkPrimitiveTopology topology)
1645 {
1646 	const std::string  fullName = getPrimitiveTopologyName(topology);
1647 
1648 	DE_ASSERT(de::beginsWith(fullName, "VK_PRIMITIVE_TOPOLOGY_"));
1649 
1650 	return de::toLower(fullName.substr(22));
1651 }
1652 
createPrimitiveTopologyTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)1653 de::MovePtr<tcu::TestCaseGroup> createPrimitiveTopologyTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
1654 {
1655 	de::MovePtr<tcu::TestCaseGroup> primitiveTopologyTests (new tcu::TestCaseGroup(testCtx, "primitive_topology"));
1656 
1657 	de::MovePtr<tcu::TestCaseGroup> indexUint16Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint16"));
1658 	de::MovePtr<tcu::TestCaseGroup> indexUint32Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint32"));
1659 	de::MovePtr<tcu::TestCaseGroup> indexUint8Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint8"));
1660 
1661 	for (int topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(InputAssemblyTest::s_primitiveTopologies); topologyNdx++)
1662 	{
1663 		const VkPrimitiveTopology topology = InputAssemblyTest::s_primitiveTopologies[topologyNdx];
1664 
1665 		indexUint16Tests->addChild(new PrimitiveTopologyTest(testCtx,
1666 															 getPrimitiveTopologyCaseName(topology),
1667 															 pipelineConstructionType,
1668 															 topology,
1669 															 VK_INDEX_TYPE_UINT16));
1670 
1671 		indexUint32Tests->addChild(new PrimitiveTopologyTest(testCtx,
1672 															 getPrimitiveTopologyCaseName(topology),
1673 															 pipelineConstructionType,
1674 															 topology,
1675 															 VK_INDEX_TYPE_UINT32));
1676 
1677 		indexUint8Tests->addChild(new PrimitiveTopologyTest(testCtx,
1678 															 getPrimitiveTopologyCaseName(topology),
1679 															 pipelineConstructionType,
1680 															 topology,
1681 															 VK_INDEX_TYPE_UINT8_EXT));
1682 	}
1683 
1684 	primitiveTopologyTests->addChild(indexUint16Tests.release());
1685 	primitiveTopologyTests->addChild(indexUint32Tests.release());
1686 	primitiveTopologyTests->addChild(indexUint8Tests.release());
1687 
1688 	return primitiveTopologyTests;
1689 }
1690 
1691 #ifndef CTS_USES_VULKANSC
createPrimitiveRestartTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)1692 de::MovePtr<tcu::TestCaseGroup> createPrimitiveRestartTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
1693 {
1694 	const VkPrimitiveTopology primitiveRestartTopologies[] =
1695 	{
1696 		VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
1697 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
1698 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
1699 		VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
1700 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
1701 
1702 		// Supported with VK_EXT_primitive_topology_list_restart
1703 		VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
1704 		VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
1705 		VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
1706 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
1707 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
1708 		VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
1709 	};
1710 
1711 	de::MovePtr<tcu::TestCaseGroup> primitiveRestartTests (new tcu::TestCaseGroup(testCtx, "primitive_restart"));
1712 
1713 	de::MovePtr<tcu::TestCaseGroup> indexUint16Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint16"));
1714 	de::MovePtr<tcu::TestCaseGroup> indexUint32Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint32"));
1715 	de::MovePtr<tcu::TestCaseGroup> indexUint8Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint8"));
1716 
1717 	constexpr struct RestartTest
1718 	{
1719 		RestartType	type;
1720 		const char* name;
1721 	} restartTypes[] =
1722 	{
1723 		{ RestartType::NORMAL,	"",					},
1724 		{ RestartType::NONE,	"no_restart_",		},
1725 		{ RestartType::ALL,		"restart_all_"		},
1726 	};
1727 
1728 	for (int topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(primitiveRestartTopologies); topologyNdx++)
1729 	{
1730 		const VkPrimitiveTopology topology = primitiveRestartTopologies[topologyNdx];
1731 
1732 		for (int useRestartNdx = 0; useRestartNdx < DE_LENGTH_OF_ARRAY(restartTypes); useRestartNdx++)
1733 		{
1734 			if (topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && restartTypes[useRestartNdx].type == RestartType::ALL) {
1735 				continue;
1736 			}
1737 			indexUint16Tests->addChild(new PrimitiveRestartTest(testCtx,
1738 																restartTypes[useRestartNdx].name + getPrimitiveTopologyCaseName(topology),
1739 																pipelineConstructionType,
1740 																topology,
1741 																VK_INDEX_TYPE_UINT16,
1742 																restartTypes[useRestartNdx].type));
1743 
1744 			indexUint32Tests->addChild(new PrimitiveRestartTest(testCtx,
1745 																restartTypes[useRestartNdx].name + getPrimitiveTopologyCaseName(topology),
1746 																pipelineConstructionType,
1747 																topology,
1748 																VK_INDEX_TYPE_UINT32,
1749 																restartTypes[useRestartNdx].type));
1750 
1751 			indexUint8Tests->addChild(new PrimitiveRestartTest(testCtx,
1752 																restartTypes[useRestartNdx].name + getPrimitiveTopologyCaseName(topology),
1753 																pipelineConstructionType,
1754 																topology,
1755 																VK_INDEX_TYPE_UINT8_EXT,
1756 																restartTypes[useRestartNdx].type));
1757 		}
1758 	}
1759 
1760 	// Tests that have primitive restart disabled, but have indices with restart index value.
1761 	if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1762 	{
1763 		struct
1764 		{
1765 			std::string	name;
1766 			std::vector<std::string> requirements;
1767 		} tests[] =
1768 		{
1769 			{ "line_list", { "VK_EXT_primitive_topology_list_restart" } },
1770 			{ "line_list_with_adjacency", { "Features.geometryShader", "VK_EXT_primitive_topology_list_restart" } },
1771 			{ "line_strip", {} },
1772 			{ "line_strip_with_adjacency", {"Features.geometryShader"} },
1773 			{ "patch_list", { "VK_EXT_primitive_topology_list_restart", "Features.tessellationShader" } },
1774 			{ "point_list", { "VK_EXT_primitive_topology_list_restart" } },
1775 			{ "triangle_fan", {} },
1776 			{ "triangle_list", { "VK_EXT_primitive_topology_list_restart" } },
1777 			{ "triangle_list_with_adjacency", { "Features.geometryShader", "VK_EXT_primitive_topology_list_restart" } },
1778 			{ "triangle_strip", {} },
1779 			{ "triangle_strip_with_adjacency", {"Features.geometryShader"} }
1780 		};
1781 
1782 		const std::string dataDir = "pipeline/input_assembly/primitive_restart";
1783 
1784 		for (auto& test : tests)
1785 		{
1786 			std::string testName = "restart_disabled_" + test.name;
1787 			indexUint16Tests->addChild(cts_amber::createAmberTestCase(testCtx, testName.c_str(),  dataDir.c_str(), testName + "_uint16.amber", test.requirements));
1788 			test.requirements.push_back("VK_EXT_index_type_uint8");
1789 			indexUint8Tests->addChild(cts_amber::createAmberTestCase(testCtx, testName.c_str(), dataDir.c_str(), testName + "_uint8.amber", test.requirements));
1790 		}
1791 	}
1792 
1793 	primitiveRestartTests->addChild(indexUint16Tests.release());
1794 	primitiveRestartTests->addChild(indexUint32Tests.release());
1795 	primitiveRestartTests->addChild(indexUint8Tests.release());
1796 
1797 	return primitiveRestartTests;
1798 }
1799 #endif // CTS_USES_VULKANSC
1800 
1801 } // anonymous
1802 
createInputAssemblyTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)1803 tcu::TestCaseGroup* createInputAssemblyTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
1804 {
1805 	de::MovePtr<tcu::TestCaseGroup>		inputAssemblyTests (new tcu::TestCaseGroup(testCtx, "input_assembly"));
1806 
1807 	inputAssemblyTests->addChild(createPrimitiveTopologyTests(testCtx, pipelineConstructionType).release());
1808 #ifndef CTS_USES_VULKANSC
1809 	inputAssemblyTests->addChild(createPrimitiveRestartTests(testCtx, pipelineConstructionType).release());
1810 #endif // CTS_USES_VULKANSC
1811 
1812 	return inputAssemblyTests.release();
1813 }
1814 
1815 } // pipeline
1816 } // vkt
1817