Home | History | Annotate | Download | only in pipeline
      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);
     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);
     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);
    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 
    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 
    220 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 
    230 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 
    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 
    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 
    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 
    286 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 
    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 
    640 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 
    898 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 
    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 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
   1359 
   1360 	// Create command buffer
   1361 	{
   1362 		const VkCommandBufferBeginInfo cmdBufferBeginInfo =
   1363 		{
   1364 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
   1365 			DE_NULL,										// const void*						pNext;
   1366 			0u,												// VkCommandBufferUsageFlags		flags;
   1367 			(const VkCommandBufferInheritanceInfo*)DE_NULL,
   1368 		};
   1369 
   1370 		const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
   1371 
   1372 		const VkRenderPassBeginInfo renderPassBeginInfo =
   1373 		{
   1374 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
   1375 			DE_NULL,												// const void*			pNext;
   1376 			*m_renderPass,											// VkRenderPass			renderPass;
   1377 			*m_framebuffer,											// VkFramebuffer		framebuffer;
   1378 			{ { 0, 0 } , { m_renderSize.x(), m_renderSize.y() } },	// VkRect2D				renderArea;
   1379 			1u,														// deUint32				clearValueCount;
   1380 			&attachmentClearValue									// const VkClearValue*	pClearValues;
   1381 		};
   1382 
   1383 		const VkImageMemoryBarrier attachmentLayoutBarrier =
   1384 		{
   1385 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
   1386 			DE_NULL,										// const void*				pNext;
   1387 			0u,												// VkAccessFlags			srcAccessMask;
   1388 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
   1389 			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
   1390 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			newLayout;
   1391 			VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
   1392 			VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
   1393 			*m_colorImage,									// VkImage					image;
   1394 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
   1395 		};
   1396 
   1397 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
   1398 
   1399 		VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
   1400 
   1401 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
   1402 			0u, DE_NULL, 0u, DE_NULL, 1u, &attachmentLayoutBarrier);
   1403 
   1404 		vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
   1405 
   1406 		const VkDeviceSize vertexBufferOffset = 0;
   1407 
   1408 		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
   1409 		vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
   1410 		vk.cmdBindIndexBuffer(*m_cmdBuffer, *m_indexBuffer, 0, m_indexType);
   1411 		vk.cmdDrawIndexed(*m_cmdBuffer, (deUint32)m_indices.size(), 1, 0, 0, 0);
   1412 
   1413 		vk.cmdEndRenderPass(*m_cmdBuffer);
   1414 		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
   1415 	}
   1416 
   1417 	// Create fence
   1418 	m_fence = createFence(vk, vkDevice);
   1419 }
   1420 
   1421 InputAssemblyInstance::~InputAssemblyInstance (void)
   1422 {
   1423 }
   1424 
   1425 tcu::TestStatus InputAssemblyInstance::iterate (void)
   1426 {
   1427 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
   1428 	const VkDevice				vkDevice	= m_context.getDevice();
   1429 	const VkQueue				queue		= m_context.getUniversalQueue();
   1430 	const VkSubmitInfo			submitInfo	=
   1431 	{
   1432 		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
   1433 		DE_NULL,						// const void*				pNext;
   1434 		0u,								// deUint32					waitSemaphoreCount;
   1435 		DE_NULL,						// const VkSemaphore*		pWaitSemaphores;
   1436 		(const VkPipelineStageFlags*)DE_NULL,
   1437 		1u,								// deUint32					commandBufferCount;
   1438 		&m_cmdBuffer.get(),				// const VkCommandBuffer*	pCommandBuffers;
   1439 		0u,								// deUint32					signalSemaphoreCount;
   1440 		DE_NULL							// const VkSemaphore*		pSignalSemaphores;
   1441 	};
   1442 
   1443 	VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
   1444 	VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
   1445 	VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
   1446 
   1447 	return verifyImage();
   1448 }
   1449 
   1450 tcu::TestStatus InputAssemblyInstance::verifyImage (void)
   1451 {
   1452 	const tcu::TextureFormat	tcuColorFormat		= mapVkFormat(m_colorFormat);
   1453 	const tcu::TextureFormat	tcuStencilFormat	= tcu::TextureFormat();
   1454 	const ColorVertexShader		vertexShader;
   1455 	const ColorFragmentShader	fragmentShader		(tcuColorFormat, tcuStencilFormat);
   1456 	const rr::Program			program				(&vertexShader, &fragmentShader);
   1457 	ReferenceRenderer			refRenderer			(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program);
   1458 	bool						compareOk			= false;
   1459 
   1460 	// Render reference image
   1461 	{
   1462 		const rr::PrimitiveType		topology	= mapVkPrimitiveTopology(m_primitiveTopology);
   1463 		rr::RenderState				renderState	(refRenderer.getViewportState());
   1464 
   1465 		if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
   1466 			renderState.point.pointSize = 3.0f;
   1467 
   1468 		if (m_primitiveRestartEnable)
   1469 		{
   1470 			std::vector<deUint32> indicesRange;
   1471 
   1472 			for (size_t indexNdx = 0; indexNdx < m_indices.size(); indexNdx++)
   1473 			{
   1474 				const bool isRestart = InputAssemblyTest::isRestartIndex(m_indexType, m_indices[indexNdx]);
   1475 
   1476 				if (!isRestart)
   1477 					indicesRange.push_back(m_indices[indexNdx]);
   1478 
   1479 				if (isRestart || indexNdx == (m_indices.size() - 1))
   1480 				{
   1481 					// Draw the range of indices found so far
   1482 
   1483 					std::vector<Vertex4RGBA> nonIndexedVertices;
   1484 					for (size_t i = 0; i < indicesRange.size(); i++)
   1485 						nonIndexedVertices.push_back(m_vertices[indicesRange[i]]);
   1486 
   1487 					refRenderer.draw(renderState, topology, nonIndexedVertices);
   1488 					indicesRange.clear();
   1489 				}
   1490 			}
   1491 		}
   1492 		else
   1493 		{
   1494 			std::vector<Vertex4RGBA> nonIndexedVertices;
   1495 			for (size_t i = 0; i < m_indices.size(); i++)
   1496 				nonIndexedVertices.push_back(m_vertices[m_indices[i]]);
   1497 
   1498 			refRenderer.draw(renderState, topology, nonIndexedVertices);
   1499 		}
   1500 	}
   1501 
   1502 	// Compare result with reference image
   1503 	{
   1504 		const DeviceInterface&				vk					= m_context.getDeviceInterface();
   1505 		const VkDevice						vkDevice			= m_context.getDevice();
   1506 		const VkQueue						queue				= m_context.getUniversalQueue();
   1507 		const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
   1508 		SimpleAllocator						allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
   1509 		de::UniquePtr<tcu::TextureLevel>	result				(readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
   1510 
   1511 		compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
   1512 															  "IntImageCompare",
   1513 															  "Image comparison",
   1514 															  refRenderer.getAccess(),
   1515 															  result->getAccess(),
   1516 															  tcu::UVec4(2, 2, 2, 2),
   1517 															  tcu::IVec3(1, 1, 0),
   1518 															  true,
   1519 															  tcu::COMPARE_LOG_RESULT);
   1520 	}
   1521 
   1522 	if (compareOk)
   1523 		return tcu::TestStatus::pass("Result image matches reference");
   1524 	else
   1525 		return tcu::TestStatus::fail("Image mismatch");
   1526 }
   1527 
   1528 void InputAssemblyInstance::uploadIndexBufferData16	(deUint16* destPtr, const std::vector<deUint32>& indexBufferData)
   1529 {
   1530 	for (size_t i = 0; i < indexBufferData.size(); i++)
   1531 	{
   1532 		DE_ASSERT(indexBufferData[i] <= 0xFFFF);
   1533 		destPtr[i] = (deUint16)indexBufferData[i];
   1534 	}
   1535 }
   1536 
   1537 
   1538 // Utilities for test names
   1539 
   1540 std::string getPrimitiveTopologyCaseName (VkPrimitiveTopology topology)
   1541 {
   1542 	const std::string  fullName = getPrimitiveTopologyName(topology);
   1543 
   1544 	DE_ASSERT(de::beginsWith(fullName, "VK_PRIMITIVE_TOPOLOGY_"));
   1545 
   1546 	return de::toLower(fullName.substr(22));
   1547 }
   1548 
   1549 de::MovePtr<tcu::TestCaseGroup> createPrimitiveTopologyTests (tcu::TestContext& testCtx)
   1550 {
   1551 	de::MovePtr<tcu::TestCaseGroup> primitiveTopologyTests (new tcu::TestCaseGroup(testCtx, "primitive_topology", ""));
   1552 
   1553 	for (int topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(InputAssemblyTest::s_primitiveTopologies); topologyNdx++)
   1554 	{
   1555 		const VkPrimitiveTopology topology = InputAssemblyTest::s_primitiveTopologies[topologyNdx];
   1556 
   1557 		primitiveTopologyTests->addChild(new PrimitiveTopologyTest(testCtx,
   1558 																   getPrimitiveTopologyCaseName(topology),
   1559 																   "",
   1560 																   topology));
   1561 	}
   1562 
   1563 	return primitiveTopologyTests;
   1564 }
   1565 
   1566 de::MovePtr<tcu::TestCaseGroup> createPrimitiveRestartTests (tcu::TestContext& testCtx)
   1567 {
   1568 	const VkPrimitiveTopology primitiveRestartTopologies[] =
   1569 	{
   1570 		VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
   1571 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
   1572 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
   1573 		VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
   1574 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
   1575 	};
   1576 
   1577 	de::MovePtr<tcu::TestCaseGroup> primitiveRestartTests (new tcu::TestCaseGroup(testCtx, "primitive_restart", "Restarts indices of "));
   1578 
   1579 	de::MovePtr<tcu::TestCaseGroup> indexUint16Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint16", ""));
   1580 	de::MovePtr<tcu::TestCaseGroup> indexUint32Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint32", ""));
   1581 
   1582 	for (int topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(primitiveRestartTopologies); topologyNdx++)
   1583 	{
   1584 		const VkPrimitiveTopology topology = primitiveRestartTopologies[topologyNdx];
   1585 
   1586 		indexUint16Tests->addChild(new PrimitiveRestartTest(testCtx,
   1587 															getPrimitiveTopologyCaseName(topology),
   1588 															"",
   1589 															topology,
   1590 															VK_INDEX_TYPE_UINT16));
   1591 
   1592 		indexUint32Tests->addChild(new PrimitiveRestartTest(testCtx,
   1593 															getPrimitiveTopologyCaseName(topology),
   1594 															"",
   1595 															topology,
   1596 															VK_INDEX_TYPE_UINT32));
   1597 	}
   1598 
   1599 	primitiveRestartTests->addChild(indexUint16Tests.release());
   1600 	primitiveRestartTests->addChild(indexUint32Tests.release());
   1601 
   1602 	return primitiveRestartTests;
   1603 }
   1604 
   1605 } // anonymous
   1606 
   1607 tcu::TestCaseGroup* createInputAssemblyTests (tcu::TestContext& testCtx)
   1608 {
   1609 	de::MovePtr<tcu::TestCaseGroup>		inputAssemblyTests (new tcu::TestCaseGroup(testCtx, "input_assembly", "Input assembly tests"));
   1610 
   1611 	inputAssemblyTests->addChild(createPrimitiveTopologyTests(testCtx).release());
   1612 	inputAssemblyTests->addChild(createPrimitiveRestartTests(testCtx).release());
   1613 
   1614 	return inputAssemblyTests.release();
   1615 }
   1616 
   1617 } // pipeline
   1618 } // vkt
   1619