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 
48 namespace vkt
49 {
50 namespace pipeline
51 {
52 
53 using namespace vk;
54 
55 namespace
56 {
57 
58 class InputAssemblyTest : public vkt::TestCase
59 {
60 public:
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);
~InputAssemblyTest(void)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 
78 protected:
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 
85 private:
86 	VkPrimitiveTopology					m_primitiveTopology;
87 	const int							m_primitiveCount;
88 	bool								m_testPrimitiveRestart;
89 	VkIndexType							m_indexType;
90 };
91 
92 class PrimitiveTopologyTest : public InputAssemblyTest
93 {
94 public:
95 										PrimitiveTopologyTest	(tcu::TestContext&		testContext,
96 																 const std::string&		name,
97 																 const std::string&		description,
98 																 VkPrimitiveTopology	primitiveTopology);
~PrimitiveTopologyTest(void)99 	virtual								~PrimitiveTopologyTest	(void) {}
100 
101 protected:
102 	virtual void						createBufferData		(VkPrimitiveTopology		topology,
103 																 int						primitiveCount,
104 																 VkIndexType				indexType,
105 																 std::vector<deUint32>&		indexData,
106 																 std::vector<Vertex4RGBA>&	vertexData) const;
107 
108 private:
109 };
110 
111 class PrimitiveRestartTest : public InputAssemblyTest
112 {
113 public:
114 										PrimitiveRestartTest	(tcu::TestContext&		testContext,
115 																 const std::string&		name,
116 																 const std::string&		description,
117 																 VkPrimitiveTopology	primitiveTopology,
118 																 VkIndexType			indexType);
~PrimitiveRestartTest(void)119 	virtual								~PrimitiveRestartTest	(void) {}
120 
121 protected:
122 	virtual void						createBufferData		(VkPrimitiveTopology		topology,
123 																 int						primitiveCount,
124 																 VkIndexType				indexType,
125 																 std::vector<deUint32>&		indexData,
126 																 std::vector<Vertex4RGBA>&	vertexData) const;
127 
128 private:
129 	bool								isRestartPrimitive		(int primitiveIndex) const;
130 
131 	std::vector<deUint32>				m_restartPrimitives;
132 };
133 
134 class InputAssemblyInstance : public vkt::TestInstance
135 {
136 public:
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 
146 private:
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 
187 const 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 
201 const deUint32 InputAssemblyTest::s_restartIndex32	= ~((deUint32)0u);
202 const deUint16 InputAssemblyTest::s_restartIndex16	= ~((deUint16)0u);
203 
InputAssemblyTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkPrimitiveTopology primitiveTopology,int primitiveCount,bool testPrimitiveRestart,VkIndexType indexType)204 InputAssemblyTest::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 
createInstance(Context & context) const220 TestInstance* 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 
initPrograms(SourceCollections & sourceCollections) const230 void 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 
isRestartIndex(VkIndexType indexType,deUint32 indexValue)259 bool 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 
getRestartIndex(VkIndexType indexType)267 deUint32 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 
PrimitiveTopologyTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkPrimitiveTopology primitiveTopology)278 PrimitiveTopologyTest::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 
createBufferData(VkPrimitiveTopology topology,int primitiveCount,VkIndexType indexType,std::vector<deUint32> & indexData,std::vector<Vertex4RGBA> & vertexData) const286 void 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 
PrimitiveRestartTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkPrimitiveTopology primitiveTopology,VkIndexType indexType)621 PrimitiveRestartTest::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 
createBufferData(VkPrimitiveTopology topology,int primitiveCount,VkIndexType indexType,std::vector<deUint32> & indexData,std::vector<Vertex4RGBA> & vertexData) const640 void 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 
isRestartPrimitive(int primitiveIndex) const898 bool 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 
InputAssemblyInstance(Context & context,VkPrimitiveTopology primitiveTopology,bool testPrimitiveRestart,VkIndexType indexType,const std::vector<deUint32> & indexBufferData,const std::vector<Vertex4RGBA> & vertexBufferData)906 InputAssemblyInstance::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 
~InputAssemblyInstance(void)1449 InputAssemblyInstance::~InputAssemblyInstance (void)
1450 {
1451 }
1452 
iterate(void)1453 tcu::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 
verifyImage(void)1478 tcu::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 
uploadIndexBufferData16(deUint16 * destPtr,const std::vector<deUint32> & indexBufferData)1556 void 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 
getPrimitiveTopologyCaseName(VkPrimitiveTopology topology)1568 std::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 
createPrimitiveTopologyTests(tcu::TestContext & testCtx)1577 de::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 
createPrimitiveRestartTests(tcu::TestContext & testCtx)1594 de::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 
createInputAssemblyTests(tcu::TestContext & testCtx)1635 tcu::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