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