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