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