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