Home | History | Annotate | Download | only in robustness
      1 /*------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2016 The Khronos Group Inc.
      6  * Copyright (c) 2016 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 Robust Vertex Buffer Access Tests
     23  *//*--------------------------------------------------------------------*/
     24 
     25 #include "vktRobustnessVertexAccessTests.hpp"
     26 #include "vktRobustnessUtil.hpp"
     27 #include "vktTestCaseUtil.hpp"
     28 #include "vkBuilderUtil.hpp"
     29 #include "vkImageUtil.hpp"
     30 #include "vkMemUtil.hpp"
     31 #include "vkPrograms.hpp"
     32 #include "vkQueryUtil.hpp"
     33 #include "vkRef.hpp"
     34 #include "vkRefUtil.hpp"
     35 #include "vkTypeUtil.hpp"
     36 #include "tcuTestLog.hpp"
     37 #include "deMath.h"
     38 #include "deUniquePtr.hpp"
     39 #include <vector>
     40 
     41 namespace vkt
     42 {
     43 namespace robustness
     44 {
     45 
     46 using namespace vk;
     47 
     48 typedef std::vector<VkVertexInputBindingDescription>	BindingList;
     49 typedef std::vector<VkVertexInputAttributeDescription>	AttributeList;
     50 
     51 class VertexAccessTest : public vkt::TestCase
     52 {
     53 public:
     54 						VertexAccessTest	(tcu::TestContext&		testContext,
     55 											 const std::string&		name,
     56 											 const std::string&		description,
     57 											 VkFormat				inputFormat,
     58 											 deUint32				numVertexValues,
     59 											 deUint32				numInstanceValues,
     60 											 deUint32				numVertices,
     61 											 deUint32				numInstances);
     62 
     63 	virtual				~VertexAccessTest	(void) {}
     64 
     65 	void				initPrograms		(SourceCollections& programCollection) const;
     66 	TestInstance*		createInstance		(Context& context) const = 0;
     67 
     68 protected:
     69 	const VkFormat		m_inputFormat;
     70 	const deUint32		m_numVertexValues;
     71 	const deUint32		m_numInstanceValues;
     72 	const deUint32		m_numVertices;
     73 	const deUint32		m_numInstances;
     74 
     75 };
     76 
     77 class DrawAccessTest : public VertexAccessTest
     78 {
     79 public:
     80 						DrawAccessTest		(tcu::TestContext&		testContext,
     81 											 const std::string&		name,
     82 											 const std::string&		description,
     83 											 VkFormat				inputFormat,
     84 											 deUint32				numVertexValues,
     85 											 deUint32				numInstanceValues,
     86 											 deUint32				numVertices,
     87 											 deUint32				numInstances);
     88 
     89 	virtual				~DrawAccessTest		(void) {}
     90 	TestInstance*		createInstance		(Context& context) const;
     91 
     92 protected:
     93 };
     94 
     95 class DrawIndexedAccessTest : public VertexAccessTest
     96 {
     97 public:
     98 	enum IndexConfig
     99 	{
    100 		INDEX_CONFIG_LAST_INDEX_OUT_OF_BOUNDS,
    101 		INDEX_CONFIG_INDICES_OUT_OF_BOUNDS,
    102 		INDEX_CONFIG_TRIANGLE_OUT_OF_BOUNDS,
    103 
    104 		INDEX_CONFIG_COUNT
    105 	};
    106 
    107 	const static std::vector<deUint32> s_indexConfigs[INDEX_CONFIG_COUNT];
    108 
    109 						DrawIndexedAccessTest		(tcu::TestContext&		testContext,
    110 													 const std::string&		name,
    111 													 const std::string&		description,
    112 													 VkFormat				inputFormat,
    113 													 IndexConfig			indexConfig);
    114 
    115 	virtual				~DrawIndexedAccessTest		(void) {}
    116 	TestInstance*		createInstance				(Context& context) const;
    117 
    118 protected:
    119 	const IndexConfig	m_indexConfig;
    120 };
    121 
    122 class VertexAccessInstance : public vkt::TestInstance
    123 {
    124 public:
    125 										VertexAccessInstance					(Context&						context,
    126 																				 Move<VkDevice>					device,
    127 																				 VkFormat						inputFormat,
    128 																				 deUint32						numVertexValues,
    129 																				 deUint32						numInstanceValues,
    130 																				 deUint32						numVertices,
    131 																				 deUint32						numInstances,
    132 																				 const std::vector<deUint32>&	indices);
    133 
    134 	virtual								~VertexAccessInstance					(void) {}
    135 	virtual tcu::TestStatus				iterate									(void);
    136 	virtual bool						verifyResult							(void);
    137 
    138 private:
    139 	bool								isValueWithinVertexBufferOrZero			(void* vertexBuffer, VkDeviceSize vertexBufferSize, const void* value, deUint32 valueIndexa);
    140 
    141 protected:
    142 	static bool							isExpectedValueFromVertexBuffer			(const void* vertexBuffer, deUint32 vertexIndex, VkFormat vertexFormat, const void* value);
    143 	static VkDeviceSize					getBufferSizeInBytes					(deUint32 numScalars, VkFormat format);
    144 
    145 	virtual void						initVertexIds							(deUint32 *indicesPtr, size_t indexCount) = 0;
    146 	virtual deUint32					getIndex								(deUint32 vertexNum) const = 0;
    147 
    148 	Move<VkDevice>						m_device;
    149 
    150 	const VkFormat						m_inputFormat;
    151 	const deUint32						m_numVertexValues;
    152 	const deUint32						m_numInstanceValues;
    153 	const deUint32						m_numVertices;
    154 	const deUint32						m_numInstances;
    155 	AttributeList						m_vertexInputAttributes;
    156 	BindingList							m_vertexInputBindings;
    157 
    158 	Move<VkBuffer>						m_vertexRateBuffer;
    159 	VkDeviceSize						m_vertexRateBufferSize;
    160 	de::MovePtr<Allocation>				m_vertexRateBufferAlloc;
    161 	VkDeviceSize						m_vertexRateBufferAllocSize;
    162 
    163 	Move<VkBuffer>						m_instanceRateBuffer;
    164 	VkDeviceSize						m_instanceRateBufferSize;
    165 	de::MovePtr<Allocation>				m_instanceRateBufferAlloc;
    166 	VkDeviceSize						m_instanceRateBufferAllocSize;
    167 
    168 	Move<VkBuffer>						m_vertexNumBuffer;
    169 	VkDeviceSize						m_vertexNumBufferSize;
    170 	de::MovePtr<Allocation>				m_vertexNumBufferAlloc;
    171 
    172 	Move<VkBuffer>						m_indexBuffer;
    173 	VkDeviceSize						m_indexBufferSize;
    174 	de::MovePtr<Allocation>				m_indexBufferAlloc;
    175 
    176 	Move<VkBuffer>						m_outBuffer; // SSBO
    177 	VkDeviceSize						m_outBufferSize;
    178 	de::MovePtr<Allocation>				m_outBufferAlloc;
    179 
    180 	Move<VkDescriptorPool>				m_descriptorPool;
    181 	Move<VkDescriptorSetLayout>			m_descriptorSetLayout;
    182 	Move<VkDescriptorSet>				m_descriptorSet;
    183 
    184 	Move<VkFence>						m_fence;
    185 	VkQueue								m_queue;
    186 
    187 	de::MovePtr<GraphicsEnvironment>	m_graphicsTestEnvironment;
    188 };
    189 
    190 class DrawAccessInstance : public VertexAccessInstance
    191 {
    192 public:
    193 						DrawAccessInstance	(Context&				context,
    194 											 Move<VkDevice>			device,
    195 											 VkFormat				inputFormat,
    196 											 deUint32				numVertexValues,
    197 											 deUint32				numInstanceValues,
    198 											 deUint32				numVertices,
    199 											 deUint32				numInstances);
    200 
    201 	virtual				~DrawAccessInstance	(void) {}
    202 
    203 protected:
    204 	virtual void		initVertexIds		(deUint32 *indicesPtr, size_t indexCount);
    205 	virtual deUint32	getIndex			(deUint32 vertexNum) const;
    206 };
    207 
    208 class DrawIndexedAccessInstance : public VertexAccessInstance
    209 {
    210 public:
    211 										DrawIndexedAccessInstance	(Context&						context,
    212 																	 Move<VkDevice>					device,
    213 																	 VkFormat						inputFormat,
    214 																	 deUint32						numVertexValues,
    215 																	 deUint32						numInstanceValues,
    216 																	 deUint32						numVertices,
    217 																	 deUint32						numInstances,
    218 																	 const std::vector<deUint32>&	indices);
    219 
    220 	virtual								~DrawIndexedAccessInstance	(void) {}
    221 
    222 protected:
    223 	virtual void						initVertexIds				(deUint32 *indicesPtr, size_t indexCount);
    224 	virtual deUint32					getIndex					(deUint32 vertexNum) const;
    225 
    226 	const std::vector<deUint32>			m_indices;
    227 };
    228 
    229 // VertexAccessTest
    230 
    231 VertexAccessTest::VertexAccessTest (tcu::TestContext&		testContext,
    232 									const std::string&		name,
    233 									const std::string&		description,
    234 									VkFormat				inputFormat,
    235 									deUint32				numVertexValues,
    236 									deUint32				numInstanceValues,
    237 									deUint32				numVertices,
    238 									deUint32				numInstances)
    239 
    240 	: vkt::TestCase				(testContext, name, description)
    241 	, m_inputFormat				(inputFormat)
    242 	, m_numVertexValues			(numVertexValues)
    243 	, m_numInstanceValues		(numInstanceValues)
    244 	, m_numVertices				(numVertices)
    245 	, m_numInstances			(numInstances)
    246 {
    247 }
    248 
    249 void VertexAccessTest::initPrograms (SourceCollections& programCollection) const
    250 {
    251 	std::ostringstream		attributeDeclaration;
    252 	std::ostringstream		attributeUse;
    253 
    254 	std::ostringstream		vertexShaderSource;
    255 	std::ostringstream		fragmentShaderSource;
    256 
    257 	std::ostringstream		attributeTypeStr;
    258 	const int				numChannels				= getNumUsedChannels(mapVkFormat(m_inputFormat).order);
    259 	const deUint32			numScalarsPerVertex		= numChannels * 3; // Use 3 identical attributes
    260 	deUint32				numValues				= 0;
    261 
    262 	if (numChannels == 1)
    263 	{
    264 		if (isUintFormat(m_inputFormat))
    265 			attributeTypeStr << "uint";
    266 		else if (isIntFormat(m_inputFormat))
    267 			attributeTypeStr << "int";
    268 		else
    269 			attributeTypeStr << "float";
    270 	}
    271 	else
    272 	{
    273 		if (isUintFormat(m_inputFormat))
    274 			attributeTypeStr << "uvec";
    275 		else if (isIntFormat(m_inputFormat))
    276 			attributeTypeStr << "ivec";
    277 		else
    278 			attributeTypeStr << "vec";
    279 
    280 		attributeTypeStr << numChannels;
    281 	}
    282 
    283 	for (int attrNdx = 0; attrNdx < 3; attrNdx++)
    284 	{
    285 		attributeDeclaration << "layout(location = " << attrNdx << ") in " << attributeTypeStr.str() << " attr" << attrNdx << ";\n";
    286 
    287 		for (int chanNdx = 0; chanNdx < numChannels; chanNdx++)
    288 		{
    289 			attributeUse << "\toutData[(gl_InstanceIndex * " << numScalarsPerVertex * m_numVertices
    290 						 << ") + (vertexNum * " << numScalarsPerVertex << " + " << numValues++ << ")] = attr" << attrNdx;
    291 
    292 			if (numChannels == 1)
    293 				attributeUse << ";\n";
    294 			else
    295 				attributeUse << "[" << chanNdx << "];\n";
    296 		}
    297 	}
    298 
    299 	attributeDeclaration << "layout(location = 3) in int vertexNum;\n";
    300 
    301 	attributeUse << "\n";
    302 
    303 	const char *outType = "";
    304 	if (isUintFormat(m_inputFormat))
    305 		outType = "uint";
    306 	else if (isIntFormat(m_inputFormat))
    307 		outType = "int";
    308 	else
    309 		outType = "float";
    310 
    311 	vertexShaderSource <<
    312 		"#version 310 es\n"
    313 		"precision highp float;\n"
    314 		<< attributeDeclaration.str() <<
    315 		"layout(set = 0, binding = 0, std430) buffer outBuffer\n"
    316 		"{\n"
    317 		"\t" << outType << " outData[" << (m_numVertices * numValues) * m_numInstances << "];\n"
    318 		"};\n\n"
    319 		"void main (void)\n"
    320 		"{\n"
    321 		<< attributeUse.str() <<
    322 		"\tgl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
    323 		"}\n";
    324 
    325 	programCollection.glslSources.add("vertex") << glu::VertexSource(vertexShaderSource.str());
    326 
    327 	fragmentShaderSource <<
    328 		"#version 310 es\n"
    329 		"precision highp float;\n"
    330 		"layout(location = 0) out vec4 fragColor;\n"
    331 		"void main (void)\n"
    332 		"{\n"
    333 		"\tfragColor = vec4(1.0);\n"
    334 		"}\n";
    335 
    336 	programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentShaderSource.str());
    337 }
    338 
    339 // DrawAccessTest
    340 
    341 DrawAccessTest::DrawAccessTest (tcu::TestContext&		testContext,
    342 								const std::string&		name,
    343 								const std::string&		description,
    344 								VkFormat				inputFormat,
    345 								deUint32				numVertexValues,
    346 								deUint32				numInstanceValues,
    347 								deUint32				numVertices,
    348 								deUint32				numInstances)
    349 
    350 	: VertexAccessTest		(testContext, name, description, inputFormat, numVertexValues, numInstanceValues, numVertices, numInstances)
    351 {
    352 }
    353 
    354 TestInstance* DrawAccessTest::createInstance (Context& context) const
    355 {
    356 	Move<VkDevice> device = createRobustBufferAccessDevice(context);
    357 
    358 	return new DrawAccessInstance(context,
    359 								  device,
    360 								  m_inputFormat,
    361 								  m_numVertexValues,
    362 								  m_numInstanceValues,
    363 								  m_numVertices,
    364 								  m_numInstances);
    365 }
    366 
    367 // DrawIndexedAccessTest
    368 
    369 const deUint32 lastIndexOutOfBounds[] =
    370 {
    371 	0, 1, 2, 3, 4, 100,		// Indices of 100 and above are out of bounds
    372 };
    373 const deUint32 indicesOutOfBounds[] =
    374 {
    375 	0, 100, 2, 101, 3, 102,	// Indices of 100 and above are out of bounds
    376 };
    377 const deUint32 triangleOutOfBounds[] =
    378 {
    379 	100, 101, 102, 3, 4, 5,	// Indices of 100 and above are out of bounds
    380 };
    381 
    382 const std::vector<deUint32> DrawIndexedAccessTest::s_indexConfigs[INDEX_CONFIG_COUNT] =
    383 {
    384 	std::vector<deUint32>(lastIndexOutOfBounds, lastIndexOutOfBounds + DE_LENGTH_OF_ARRAY(lastIndexOutOfBounds)),
    385 	std::vector<deUint32>(indicesOutOfBounds, indicesOutOfBounds + DE_LENGTH_OF_ARRAY(indicesOutOfBounds)),
    386 	std::vector<deUint32>(triangleOutOfBounds, triangleOutOfBounds + DE_LENGTH_OF_ARRAY(triangleOutOfBounds)),
    387 };
    388 
    389 DrawIndexedAccessTest::DrawIndexedAccessTest (tcu::TestContext&		testContext,
    390 											  const std::string&	name,
    391 											  const std::string&	description,
    392 											  VkFormat				inputFormat,
    393 											  IndexConfig			indexConfig)
    394 
    395 	: VertexAccessTest	(testContext,
    396 						 name,
    397 						 description,
    398 						 inputFormat,
    399 						 getNumUsedChannels(mapVkFormat(inputFormat).order) * (deUint32)s_indexConfigs[indexConfig].size() * 2,	// numVertexValues
    400 						 getNumUsedChannels(mapVkFormat(inputFormat).order),													// numInstanceValues
    401 						 (deUint32)s_indexConfigs[indexConfig].size(),															// numVertices
    402 						 1)																										// numInstances
    403 	, m_indexConfig		(indexConfig)
    404 {
    405 }
    406 
    407 TestInstance* DrawIndexedAccessTest::createInstance (Context& context) const
    408 {
    409 	Move<VkDevice> device = createRobustBufferAccessDevice(context);
    410 
    411 	return new DrawIndexedAccessInstance(context,
    412 										 device,
    413 										 m_inputFormat,
    414 										 m_numVertexValues,
    415 										 m_numInstanceValues,
    416 										 m_numVertices,
    417 										 m_numInstances,
    418 										 s_indexConfigs[m_indexConfig]);
    419 }
    420 
    421 // VertexAccessInstance
    422 
    423 VertexAccessInstance::VertexAccessInstance (Context&						context,
    424 											Move<VkDevice>					device,
    425 											VkFormat						inputFormat,
    426 											deUint32						numVertexValues,
    427 											deUint32						numInstanceValues,
    428 											deUint32						numVertices,
    429 											deUint32						numInstances,
    430 											const std::vector<deUint32>&	indices)
    431 
    432 	: vkt::TestInstance			(context)
    433 	, m_device					(device)
    434 	, m_inputFormat				(inputFormat)
    435 	, m_numVertexValues			(numVertexValues)
    436 	, m_numInstanceValues		(numInstanceValues)
    437 	, m_numVertices				(numVertices)
    438 	, m_numInstances			(numInstances)
    439 {
    440 	const DeviceInterface&		vk						= context.getDeviceInterface();
    441 	const deUint32				queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
    442 	SimpleAllocator				memAlloc				(vk, *m_device, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
    443 	const deUint32				formatSizeInBytes		= tcu::getPixelSize(mapVkFormat(m_inputFormat));
    444 
    445 	// Check storage support
    446 	if (!context.getDeviceFeatures().vertexPipelineStoresAndAtomics)
    447 	{
    448 		TCU_THROW(NotSupportedError, "Stores not supported in vertex stage");
    449 	}
    450 
    451 	const VkVertexInputAttributeDescription attributes[] =
    452 	{
    453 		// input rate: vertex
    454 		{
    455 			0u,								// deUint32 location;
    456 			0u,								// deUint32 binding;
    457 			m_inputFormat,					// VkFormat format;
    458 			0u,								// deUint32 offset;
    459 		},
    460 		{
    461 			1u,								// deUint32 location;
    462 			0u,								// deUint32 binding;
    463 			m_inputFormat,					// VkFormat format;
    464 			formatSizeInBytes,				// deUint32 offset;
    465 		},
    466 
    467 		// input rate: instance
    468 		{
    469 			2u,								// deUint32 location;
    470 			1u,								// deUint32 binding;
    471 			m_inputFormat,					// VkFormat format;
    472 			0u,								// deUint32 offset;
    473 		},
    474 
    475 		// Attribute for vertex number
    476 		{
    477 			3u,								// deUint32 location;
    478 			2u,								// deUint32 binding;
    479 			VK_FORMAT_R32_SINT,				// VkFormat format;
    480 			0,								// deUint32 offset;
    481 		},
    482 	};
    483 
    484 	const VkVertexInputBindingDescription bindings[] =
    485 	{
    486 		{
    487 			0u,								// deUint32				binding;
    488 			formatSizeInBytes * 2,			// deUint32				stride;
    489 			VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputRate	inputRate;
    490 		},
    491 		{
    492 			1u,								// deUint32				binding;
    493 			formatSizeInBytes,				// deUint32				stride;
    494 			VK_VERTEX_INPUT_RATE_INSTANCE	// VkVertexInputRate	inputRate;
    495 		},
    496 		{
    497 			2u,								// deUint32				binding;
    498 			sizeof(deInt32),				// deUint32				stride;
    499 			VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputRate	inputRate;
    500 		},
    501 	};
    502 
    503 	m_vertexInputBindings	= std::vector<VkVertexInputBindingDescription>(bindings, bindings + DE_LENGTH_OF_ARRAY(bindings));
    504 	m_vertexInputAttributes	= std::vector<VkVertexInputAttributeDescription>(attributes, attributes + DE_LENGTH_OF_ARRAY(attributes));
    505 
    506 	// Create vertex buffer for vertex input rate
    507 	{
    508 		VkMemoryRequirements bufferMemoryReqs;
    509 
    510 		m_vertexRateBufferSize = getBufferSizeInBytes(m_numVertexValues, m_inputFormat); // All formats used in this test suite are 32-bit based.
    511 
    512 		const VkBufferCreateInfo	vertexRateBufferParams	=
    513 		{
    514 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
    515 			DE_NULL,									// const void*			pNext;
    516 			0u,											// VkBufferCreateFlags	flags;
    517 			m_vertexRateBufferSize,						// VkDeviceSize			size;
    518 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
    519 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
    520 			1u,											// deUint32				queueFamilyIndexCount;
    521 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
    522 		};
    523 
    524 		m_vertexRateBuffer			= createBuffer(vk, *m_device, &vertexRateBufferParams);
    525 		bufferMemoryReqs			= getBufferMemoryRequirements(vk, *m_device, *m_vertexRateBuffer);
    526 		m_vertexRateBufferAllocSize	= bufferMemoryReqs.size;
    527 		m_vertexRateBufferAlloc		= memAlloc.allocate(bufferMemoryReqs, MemoryRequirement::HostVisible);
    528 
    529 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_vertexRateBuffer, m_vertexRateBufferAlloc->getMemory(), m_vertexRateBufferAlloc->getOffset()));
    530 		populateBufferWithTestValues(m_vertexRateBufferAlloc->getHostPtr(), (deUint32)m_vertexRateBufferAllocSize, m_inputFormat);
    531 		flushMappedMemoryRange(vk, *m_device, m_vertexRateBufferAlloc->getMemory(), m_vertexRateBufferAlloc->getOffset(), VK_WHOLE_SIZE);
    532 	}
    533 
    534 	// Create vertex buffer for instance input rate
    535 	{
    536 		VkMemoryRequirements bufferMemoryReqs;
    537 
    538 		m_instanceRateBufferSize = getBufferSizeInBytes(m_numInstanceValues, m_inputFormat); // All formats used in this test suite are 32-bit based.
    539 
    540 		const VkBufferCreateInfo	instanceRateBufferParams	=
    541 		{
    542 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
    543 			DE_NULL,									// const void*			pNext;
    544 			0u,											// VkBufferCreateFlags	flags;
    545 			m_instanceRateBufferSize,					// VkDeviceSize			size;
    546 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
    547 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
    548 			1u,											// deUint32				queueFamilyIndexCount;
    549 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
    550 		};
    551 
    552 		m_instanceRateBuffer			= createBuffer(vk, *m_device, &instanceRateBufferParams);
    553 		bufferMemoryReqs				= getBufferMemoryRequirements(vk, *m_device, *m_instanceRateBuffer);
    554 		m_instanceRateBufferAllocSize	= bufferMemoryReqs.size;
    555 		m_instanceRateBufferAlloc		= memAlloc.allocate(bufferMemoryReqs, MemoryRequirement::HostVisible);
    556 
    557 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_instanceRateBuffer, m_instanceRateBufferAlloc->getMemory(), m_instanceRateBufferAlloc->getOffset()));
    558 		populateBufferWithTestValues(m_instanceRateBufferAlloc->getHostPtr(), (deUint32)m_instanceRateBufferAllocSize, m_inputFormat);
    559 		flushMappedMemoryRange(vk, *m_device, m_instanceRateBufferAlloc->getMemory(), m_instanceRateBufferAlloc->getOffset(), VK_WHOLE_SIZE);
    560 	}
    561 
    562 	// Create vertex buffer that stores the vertex number (from 0 to m_numVertices - 1)
    563 	{
    564 		m_vertexNumBufferSize = 128 * sizeof(deInt32); // Allocate enough device memory for all indices (0 to 127).
    565 
    566 		const VkBufferCreateInfo	vertexNumBufferParams	=
    567 		{
    568 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
    569 			DE_NULL,									// const void*			pNext;
    570 			0u,											// VkBufferCreateFlags	flags;
    571 			m_vertexNumBufferSize,						// VkDeviceSize			size;
    572 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
    573 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
    574 			1u,											// deUint32				queueFamilyIndexCount;
    575 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
    576 		};
    577 
    578 		m_vertexNumBuffer		= createBuffer(vk, *m_device, &vertexNumBufferParams);
    579 		m_vertexNumBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_vertexNumBuffer), MemoryRequirement::HostVisible);
    580 
    581 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_vertexNumBuffer, m_vertexNumBufferAlloc->getMemory(), m_vertexNumBufferAlloc->getOffset()));
    582 	}
    583 
    584 	// Create index buffer if required
    585 	if (!indices.empty())
    586 	{
    587 		m_indexBufferSize = sizeof(deUint32) * indices.size();
    588 
    589 		const VkBufferCreateInfo	indexBufferParams	=
    590 		{
    591 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
    592 			DE_NULL,									// const void*			pNext;
    593 			0u,											// VkBufferCreateFlags	flags;
    594 			m_indexBufferSize,							// VkDeviceSize			size;
    595 			VK_BUFFER_USAGE_INDEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
    596 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
    597 			1u,											// deUint32				queueFamilyIndexCount;
    598 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
    599 		};
    600 
    601 		m_indexBuffer		= createBuffer(vk, *m_device, &indexBufferParams);
    602 		m_indexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_indexBuffer), MemoryRequirement::HostVisible);
    603 
    604 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_indexBuffer, m_indexBufferAlloc->getMemory(), m_indexBufferAlloc->getOffset()));
    605 		deMemcpy(m_indexBufferAlloc->getHostPtr(), indices.data(), (size_t)m_indexBufferSize);
    606 		flushMappedMemoryRange(vk, *m_device, m_indexBufferAlloc->getMemory(), m_indexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
    607 	}
    608 
    609 	// Create result ssbo
    610 	{
    611 		const int	numChannels	= getNumUsedChannels(mapVkFormat(m_inputFormat).order);
    612 
    613 		m_outBufferSize = getBufferSizeInBytes(m_numVertices * m_numInstances * numChannels * 3, VK_FORMAT_R32_UINT);
    614 
    615 		const VkBufferCreateInfo	outBufferParams		=
    616 		{
    617 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
    618 			DE_NULL,									// const void*			pNext;
    619 			0u,											// VkBufferCreateFlags	flags;
    620 			m_outBufferSize,							// VkDeviceSize			size;
    621 			VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,			// VkBufferUsageFlags	usage;
    622 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
    623 			1u,											// deUint32				queueFamilyIndexCount;
    624 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
    625 		};
    626 
    627 		m_outBuffer			= createBuffer(vk, *m_device, &outBufferParams);
    628 		m_outBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_outBuffer), MemoryRequirement::HostVisible);
    629 
    630 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
    631 		deMemset(m_outBufferAlloc->getHostPtr(), 0xFF, (size_t)m_outBufferSize);
    632 		flushMappedMemoryRange(vk, *m_device, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset(), VK_WHOLE_SIZE);
    633 	}
    634 
    635 	// Create descriptor set data
    636 	{
    637 		DescriptorPoolBuilder descriptorPoolBuilder;
    638 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u);
    639 		m_descriptorPool = descriptorPoolBuilder.build(vk, *m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
    640 
    641 		DescriptorSetLayoutBuilder setLayoutBuilder;
    642 		setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT);
    643 		m_descriptorSetLayout = setLayoutBuilder.build(vk, *m_device);
    644 
    645 		const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
    646 		{
    647 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
    648 			DE_NULL,											// const void*					pNext;
    649 			*m_descriptorPool,									// VkDescriptorPool				desciptorPool;
    650 			1u,													// deUint32						setLayoutCount;
    651 			&m_descriptorSetLayout.get()						// const VkDescriptorSetLayout*	pSetLayouts;
    652 		};
    653 
    654 		m_descriptorSet = allocateDescriptorSet(vk, *m_device, &descriptorSetAllocateInfo);
    655 
    656 		const VkDescriptorBufferInfo outBufferDescriptorInfo	= makeDescriptorBufferInfo(*m_outBuffer, 0ull, VK_WHOLE_SIZE);
    657 
    658 		DescriptorSetUpdateBuilder setUpdateBuilder;
    659 		setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outBufferDescriptorInfo);
    660 		setUpdateBuilder.update(vk, *m_device);
    661 	}
    662 
    663 	// Create fence
    664 	{
    665 		const VkFenceCreateInfo fenceParams =
    666 		{
    667 			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
    668 			DE_NULL,								// const void*			pNext;
    669 			0u										// VkFenceCreateFlags	flags;
    670 		};
    671 
    672 		m_fence = createFence(vk, *m_device, &fenceParams);
    673 	}
    674 
    675 	// Get queue
    676 	vk.getDeviceQueue(*m_device, queueFamilyIndex, 0, &m_queue);
    677 
    678 	// Setup graphics test environment
    679 	{
    680 		GraphicsEnvironment::DrawConfig drawConfig;
    681 
    682 		drawConfig.vertexBuffers.push_back(*m_vertexRateBuffer);
    683 		drawConfig.vertexBuffers.push_back(*m_instanceRateBuffer);
    684 		drawConfig.vertexBuffers.push_back(*m_vertexNumBuffer);
    685 
    686 		drawConfig.vertexCount		= m_numVertices;
    687 		drawConfig.instanceCount	= m_numInstances;
    688 		drawConfig.indexBuffer		= *m_indexBuffer;
    689 		drawConfig.indexCount		= (deUint32)(m_indexBufferSize / sizeof(deUint32));
    690 
    691 		m_graphicsTestEnvironment	= de::MovePtr<GraphicsEnvironment>(new GraphicsEnvironment(m_context,
    692 																							   *m_device,
    693 																							   *m_descriptorSetLayout,
    694 																							   *m_descriptorSet,
    695 																							   GraphicsEnvironment::VertexBindings(bindings, bindings + DE_LENGTH_OF_ARRAY(bindings)),
    696 																							   GraphicsEnvironment::VertexAttributes(attributes, attributes + DE_LENGTH_OF_ARRAY(attributes)),
    697 																							   drawConfig));
    698 	}
    699 }
    700 
    701 tcu::TestStatus VertexAccessInstance::iterate (void)
    702 {
    703 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
    704 	const vk::VkCommandBuffer	cmdBuffer	= m_graphicsTestEnvironment->getCommandBuffer();
    705 
    706 	// Initialize vertex ids
    707 	{
    708 		deUint32 *bufferPtr = reinterpret_cast<deUint32*>(m_vertexNumBufferAlloc->getHostPtr());
    709 		deMemset(bufferPtr, 0, (size_t)m_vertexNumBufferSize);
    710 
    711 		initVertexIds(bufferPtr, (size_t)(m_vertexNumBufferSize / sizeof(deUint32)));
    712 
    713 		flushMappedMemoryRange(vk, *m_device, m_vertexNumBufferAlloc->getMemory(), m_vertexNumBufferAlloc->getOffset(), VK_WHOLE_SIZE);
    714 	}
    715 
    716 	// Submit command buffer
    717 	{
    718 		const VkSubmitInfo	submitInfo	=
    719 		{
    720 			VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
    721 			DE_NULL,						// const void*					pNext;
    722 			0u,								// deUint32						waitSemaphoreCount;
    723 			DE_NULL,						// const VkSemaphore*			pWaitSemaphores;
    724 			DE_NULL,						// const VkPIpelineStageFlags*	pWaitDstStageMask;
    725 			1u,								// deUint32						commandBufferCount;
    726 			&cmdBuffer,						// const VkCommandBuffer*		pCommandBuffers;
    727 			0u,								// deUint32						signalSemaphoreCount;
    728 			DE_NULL							// const VkSemaphore*			pSignalSemaphores;
    729 		};
    730 
    731 		VK_CHECK(vk.resetFences(*m_device, 1, &m_fence.get()));
    732 		VK_CHECK(vk.queueSubmit(m_queue, 1, &submitInfo, *m_fence));
    733 		VK_CHECK(vk.waitForFences(*m_device, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
    734 	}
    735 
    736 	// Prepare result buffer for read
    737 	{
    738 		const VkMappedMemoryRange	outBufferRange	=
    739 		{
    740 			VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	//  VkStructureType	sType;
    741 			DE_NULL,								//  const void*		pNext;
    742 			m_outBufferAlloc->getMemory(),			//  VkDeviceMemory	mem;
    743 			0ull,									//  VkDeviceSize	offset;
    744 			m_outBufferSize,						//  VkDeviceSize	size;
    745 		};
    746 
    747 		VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange));
    748 	}
    749 
    750 	if (verifyResult())
    751 		return tcu::TestStatus::pass("All values OK");
    752 	else
    753 		return tcu::TestStatus::fail("Invalid value(s) found");
    754 }
    755 
    756 bool VertexAccessInstance::verifyResult (void)
    757 {
    758 	std::ostringstream			logMsg;
    759 	const DeviceInterface&		vk						= m_context.getDeviceInterface();
    760 	tcu::TestLog&				log						= m_context.getTestContext().getLog();
    761 	const deUint32				numChannels				= getNumUsedChannels(mapVkFormat(m_inputFormat).order);
    762 	const deUint32				numScalarsPerVertex		= numChannels * 3; // Use 3 identical attributes
    763 	void*						outDataPtr				= m_outBufferAlloc->getHostPtr();
    764 	const deUint32				outValueSize			= sizeof(deUint32);
    765 	bool						allOk					= true;
    766 
    767 	const VkMappedMemoryRange	outBufferRange			=
    768 	{
    769 		VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	// VkStructureType	sType;
    770 		DE_NULL,								// const void*		pNext;
    771 		m_outBufferAlloc->getMemory(),			// VkDeviceMemory	mem;
    772 		m_outBufferAlloc->getOffset(),			// VkDeviceSize		offset;
    773 		m_outBufferSize,						// VkDeviceSize		size;
    774 	};
    775 
    776 	VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange));
    777 
    778 	for (deUint32 valueNdx = 0; valueNdx < m_outBufferSize / outValueSize; valueNdx++)
    779 	{
    780 		deUint32			numInBufferValues;
    781 		void*				inBufferPtr;
    782 		VkDeviceSize		inBufferAllocSize;
    783 		deUint32			inBufferValueIndex;
    784 		bool				isOutOfBoundsAccess		= false;
    785 		const deUint32		attributeIndex			= (valueNdx / numChannels) % 3;
    786 		const deUint32*		outValuePtr				= (deUint32*)outDataPtr + valueNdx;
    787 
    788 		if (attributeIndex == 2)
    789 		{
    790 			// Instance rate
    791 			const deUint32	elementIndex	= valueNdx / (numScalarsPerVertex * m_numVertices); // instance id
    792 
    793 			numInBufferValues	= m_numInstanceValues;
    794 			inBufferPtr			= m_instanceRateBufferAlloc->getHostPtr();
    795 			inBufferAllocSize	= m_instanceRateBufferAllocSize;
    796 			inBufferValueIndex	= (elementIndex * numChannels) + (valueNdx % numScalarsPerVertex) - (2 * numChannels);
    797 		}
    798 		else
    799 		{
    800 			// Vertex rate
    801 			const deUint32	vertexNdx		= valueNdx / numScalarsPerVertex;
    802 			const deUint32	instanceNdx		= vertexNdx / m_numVertices;
    803 			const deUint32	elementIndex	= valueNdx / numScalarsPerVertex; // vertex id
    804 
    805 			numInBufferValues	= m_numVertexValues;
    806 			inBufferPtr			= m_vertexRateBufferAlloc->getHostPtr();
    807 			inBufferAllocSize	= m_vertexRateBufferAllocSize;
    808 			inBufferValueIndex	= (getIndex(elementIndex) * (numChannels * 2)) + (valueNdx % numScalarsPerVertex) - instanceNdx * (m_numVertices * numChannels * 2);
    809 
    810 			// Binding 0 contains two attributes, so bounds checking for attribute 0 must also consider attribute 1 to determine if the binding is out of bounds.
    811 			if ((attributeIndex == 0) && (numInBufferValues >= numChannels))
    812 				numInBufferValues -= numChannels;
    813 		}
    814 
    815 		isOutOfBoundsAccess	= (inBufferValueIndex >= numInBufferValues);
    816 
    817 		const deInt32		distanceToOutOfBounds	= (deInt32)outValueSize * ((deInt32)numInBufferValues - (deInt32)inBufferValueIndex);
    818 
    819 		if (!isOutOfBoundsAccess && (distanceToOutOfBounds < 16))
    820 			isOutOfBoundsAccess = (((inBufferValueIndex / numChannels) + 1) * numChannels > numInBufferValues);
    821 
    822 		// Log value information
    823 		{
    824 			// Vertex separator
    825 			if (valueNdx && valueNdx % numScalarsPerVertex == 0)
    826 				logMsg << "\n";
    827 
    828 			logMsg << "\n" << valueNdx << ": Value ";
    829 
    830 			// Result index and value
    831 			if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
    832 				logValue(logMsg, outValuePtr, VK_FORMAT_R32_SFLOAT, 4);
    833 			else
    834 				logValue(logMsg, outValuePtr, m_inputFormat, 4);
    835 
    836 			// Attribute name
    837 			logMsg << "\tfrom attr" << attributeIndex;
    838 			if (numChannels > 1)
    839 				logMsg << "[" << valueNdx % numChannels << "]";
    840 
    841 			// Input rate
    842 			if (attributeIndex == 2)
    843 				logMsg << "\tinstance rate";
    844 			else
    845 				logMsg << "\tvertex rate";
    846 		}
    847 
    848 		if (isOutOfBoundsAccess)
    849 		{
    850 			const bool isValidValue = isValueWithinVertexBufferOrZero(inBufferPtr, inBufferAllocSize, outValuePtr, inBufferValueIndex);
    851 
    852 			logMsg << "\t(out of bounds)";
    853 
    854 			if (!isValidValue)
    855 			{
    856 				// Check if we are satisfying the [0, 0, 0, x] pattern, where x may be either 0 or 1,
    857 				// or the maximum representable positive integer value (if the format is integer-based).
    858 
    859 				const bool	canMatchVec4Pattern	= ((valueNdx % numChannels == 3) || m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32);
    860 				bool		matchesVec4Pattern	= false;
    861 
    862 				if (canMatchVec4Pattern)
    863 				{
    864 					if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
    865 						matchesVec4Pattern	=  verifyOutOfBoundsVec4(outValuePtr, m_inputFormat);
    866 					else
    867 						matchesVec4Pattern	=  verifyOutOfBoundsVec4(outValuePtr - 3, m_inputFormat);
    868 				}
    869 
    870 				if (!canMatchVec4Pattern || !matchesVec4Pattern)
    871 				{
    872 					logMsg << ", Failed: expected a value within the buffer range or 0";
    873 
    874 					if (canMatchVec4Pattern)
    875 						logMsg << ", or the [0, 0, 0, x] pattern";
    876 
    877 					allOk = false;
    878 				}
    879 			}
    880 		}
    881 		else if (!isExpectedValueFromVertexBuffer(inBufferPtr, inBufferValueIndex, m_inputFormat, outValuePtr))
    882 		{
    883 			logMsg << ", Failed: unexpected value";
    884 			allOk = false;
    885 		}
    886 	}
    887 	log << tcu::TestLog::Message << logMsg.str() << tcu::TestLog::EndMessage;
    888 
    889 	return allOk;
    890 }
    891 
    892 bool VertexAccessInstance::isValueWithinVertexBufferOrZero(void* vertexBuffer, VkDeviceSize vertexBufferSize, const void* value, deUint32 valueIndex)
    893 {
    894 	if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
    895 	{
    896 		const float		normValue		= *reinterpret_cast<const float*>(value);
    897 		const deUint32	scalarIndex		= valueIndex % 4;
    898 		const bool		isAlpha			= (scalarIndex == 3);
    899 		deUint32		encodedValue;
    900 
    901 		if (isAlpha)
    902 			encodedValue = deMin32(deUint32(normValue * 0x3u), 0x3u);
    903 		else
    904 			encodedValue = deMin32(deUint32(normValue * 0x3FFu), 0x3FFu);
    905 
    906 		if (encodedValue == 0)
    907 			return true;
    908 
    909 		for (deUint32 i = 0; i < vertexBufferSize / 4; i++)
    910 		{
    911 			const deUint32	packedValue		= reinterpret_cast<deUint32*>(vertexBuffer)[i];
    912 			deUint32		unpackedValue;
    913 
    914 			if (scalarIndex < 3)
    915 				unpackedValue = (packedValue >> (10 * scalarIndex)) & 0x3FFu;
    916 			else
    917 				unpackedValue = (packedValue >> 30) & 0x3u;
    918 
    919 			if (unpackedValue == encodedValue)
    920 				return true;
    921 		}
    922 
    923 		return false;
    924 	}
    925 	else
    926 	{
    927 		return isValueWithinBufferOrZero(vertexBuffer, vertexBufferSize, value, sizeof(deUint32));
    928 	}
    929 }
    930 
    931 bool VertexAccessInstance::isExpectedValueFromVertexBuffer (const void* vertexBuffer, deUint32 vertexIndex, VkFormat vertexFormat, const void* value)
    932 {
    933 	if (isUintFormat(vertexFormat))
    934 	{
    935 		const deUint32* bufferPtr = reinterpret_cast<const deUint32*>(vertexBuffer);
    936 
    937 		return bufferPtr[vertexIndex] == *reinterpret_cast<const deUint32 *>(value);
    938 	}
    939 	else if (isIntFormat(vertexFormat))
    940 	{
    941 		const deInt32* bufferPtr = reinterpret_cast<const deInt32*>(vertexBuffer);
    942 
    943 		return bufferPtr[vertexIndex] == *reinterpret_cast<const deInt32 *>(value);
    944 	}
    945 	else if (isFloatFormat(vertexFormat))
    946 	{
    947 		const float* bufferPtr = reinterpret_cast<const float*>(vertexBuffer);
    948 
    949 		return areEqual(bufferPtr[vertexIndex], *reinterpret_cast<const float *>(value));
    950 	}
    951 	else if (vertexFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
    952 	{
    953 		const deUint32*	bufferPtr		= reinterpret_cast<const deUint32*>(vertexBuffer);
    954 		const deUint32	packedValue		= bufferPtr[vertexIndex / 4];
    955 		const deUint32	scalarIndex		= vertexIndex % 4;
    956 		float			normValue;
    957 
    958 		if (scalarIndex < 3)
    959 			normValue = float((packedValue >> (10 * scalarIndex)) & 0x3FFu) / 0x3FFu;
    960 		else
    961 			normValue = float(packedValue >> 30) / 0x3u;
    962 
    963 		return areEqual(normValue, *reinterpret_cast<const float *>(value));
    964 	}
    965 
    966 	DE_ASSERT(false);
    967 	return false;
    968 }
    969 
    970 VkDeviceSize VertexAccessInstance::getBufferSizeInBytes (deUint32 numScalars, VkFormat format)
    971 {
    972 	if (isUintFormat(format) || isIntFormat(format) || isFloatFormat(format))
    973 	{
    974 		return numScalars * 4;
    975 	}
    976 	else if (format == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
    977 	{
    978 		DE_ASSERT(numScalars % 4 == 0);
    979 		return numScalars;
    980 	}
    981 
    982 	DE_ASSERT(false);
    983 	return 0;
    984 }
    985 
    986 // DrawAccessInstance
    987 
    988 DrawAccessInstance::DrawAccessInstance (Context&				context,
    989 										Move<VkDevice>			device,
    990 										VkFormat				inputFormat,
    991 										deUint32				numVertexValues,
    992 										deUint32				numInstanceValues,
    993 										deUint32				numVertices,
    994 										deUint32				numInstances)
    995 	: VertexAccessInstance (context,
    996 							device,
    997 							inputFormat,
    998 							numVertexValues,
    999 							numInstanceValues,
   1000 							numVertices,
   1001 							numInstances,
   1002 							std::vector<deUint32>()) // No index buffer
   1003 {
   1004 }
   1005 
   1006 void DrawAccessInstance::initVertexIds (deUint32 *indicesPtr, size_t indexCount)
   1007 {
   1008 	for (deUint32 i = 0; i < indexCount; i++)
   1009 		indicesPtr[i] = i;
   1010 }
   1011 
   1012 deUint32 DrawAccessInstance::getIndex (deUint32 vertexNum) const
   1013 {
   1014 	return vertexNum;
   1015 }
   1016 
   1017 // DrawIndexedAccessInstance
   1018 
   1019 DrawIndexedAccessInstance::DrawIndexedAccessInstance (Context&						context,
   1020 													  Move<VkDevice>				device,
   1021 													  VkFormat						inputFormat,
   1022 													  deUint32						numVertexValues,
   1023 													  deUint32						numInstanceValues,
   1024 													  deUint32						numVertices,
   1025 													  deUint32						numInstances,
   1026 													  const std::vector<deUint32>&	indices)
   1027 	: VertexAccessInstance	(context,
   1028 							 device,
   1029 							 inputFormat,
   1030 							 numVertexValues,
   1031 							 numInstanceValues,
   1032 							 numVertices,
   1033 							 numInstances,
   1034 							 indices)
   1035 	, m_indices				(indices)
   1036 {
   1037 }
   1038 
   1039 void DrawIndexedAccessInstance::initVertexIds (deUint32 *indicesPtr, size_t indexCount)
   1040 {
   1041 	DE_UNREF(indexCount);
   1042 
   1043 	for (deUint32 i = 0; i < m_indices.size(); i++)
   1044 	{
   1045 		DE_ASSERT(m_indices[i] < indexCount);
   1046 
   1047 		indicesPtr[m_indices[i]] = i;
   1048 	}
   1049 }
   1050 
   1051 deUint32 DrawIndexedAccessInstance::getIndex (deUint32 vertexNum) const
   1052 {
   1053 	DE_ASSERT(vertexNum < (deUint32)m_indices.size());
   1054 
   1055 	return m_indices[vertexNum];
   1056 }
   1057 
   1058 // Test node creation functions
   1059 
   1060 static tcu::TestCaseGroup* createDrawTests (tcu::TestContext& testCtx, VkFormat format)
   1061 {
   1062 	struct TestConfig
   1063 	{
   1064 		std::string		name;
   1065 		std::string		description;
   1066 		VkFormat		inputFormat;
   1067 		deUint32		numVertexValues;
   1068 		deUint32		numInstanceValues;
   1069 		deUint32		numVertices;
   1070 		deUint32		numInstances;
   1071 	};
   1072 
   1073 	const deUint32 numChannels = getNumUsedChannels(mapVkFormat(format).order);
   1074 
   1075 	const TestConfig testConfigs[] =
   1076 	{
   1077 		// name						description											format	numVertexValues			numInstanceValues	numVertices		numInstances
   1078 		{ "vertex_out_of_bounds",	"Create data for 6 vertices, draw 9 vertices",		format,	numChannels * 2 * 6,	numChannels,		9,				1	 },
   1079 		{ "vertex_incomplete",		"Create data for half a vertex, draw 3 vertices",	format,	numChannels,			numChannels,		3,				1	 },
   1080 		{ "instance_out_of_bounds", "Create data for 1 instance, draw 3 instances",		format,	numChannels * 2 * 9,	numChannels,		3,				3	 },
   1081 	};
   1082 
   1083 	de::MovePtr<tcu::TestCaseGroup>	drawTests (new tcu::TestCaseGroup(testCtx, "draw", ""));
   1084 
   1085 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(testConfigs); i++)
   1086 	{
   1087 		const TestConfig &config = testConfigs[i];
   1088 
   1089 		drawTests->addChild(new DrawAccessTest(testCtx, config.name, config.description, config.inputFormat,
   1090 											   config.numVertexValues, config.numInstanceValues,
   1091 											   config.numVertices, config.numInstances));
   1092 	}
   1093 
   1094 	return drawTests.release();
   1095 }
   1096 
   1097 static tcu::TestCaseGroup* createDrawIndexedTests (tcu::TestContext& testCtx, VkFormat format)
   1098 {
   1099 	struct TestConfig
   1100 	{
   1101 		std::string							name;
   1102 		std::string							description;
   1103 		VkFormat							inputFormat;
   1104 		DrawIndexedAccessTest::IndexConfig	indexConfig;
   1105 	};
   1106 
   1107 	const TestConfig testConfigs[] =
   1108 	{
   1109 		// name							description								format		indexConfig
   1110 		{ "last_index_out_of_bounds",	"Only last index is out of bounds",		format,		DrawIndexedAccessTest::INDEX_CONFIG_LAST_INDEX_OUT_OF_BOUNDS },
   1111 		{ "indices_out_of_bounds",		"Random indices out of bounds",			format,		DrawIndexedAccessTest::INDEX_CONFIG_INDICES_OUT_OF_BOUNDS },
   1112 		{ "triangle_out_of_bounds",		"First triangle is out of bounds",		format,		DrawIndexedAccessTest::INDEX_CONFIG_TRIANGLE_OUT_OF_BOUNDS },
   1113 	};
   1114 
   1115 	de::MovePtr<tcu::TestCaseGroup>	drawTests (new tcu::TestCaseGroup(testCtx, "draw_indexed", ""));
   1116 
   1117 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(testConfigs); i++)
   1118 	{
   1119 		const TestConfig &config = testConfigs[i];
   1120 
   1121 		drawTests->addChild(new DrawIndexedAccessTest(testCtx, config.name, config.description, config.inputFormat, config.indexConfig));
   1122 	}
   1123 
   1124 	return drawTests.release();
   1125 }
   1126 
   1127 static void addVertexFormatTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup)
   1128 {
   1129 	const VkFormat vertexFormats[] =
   1130 	{
   1131 		VK_FORMAT_R32_UINT,
   1132 		VK_FORMAT_R32_SINT,
   1133 		VK_FORMAT_R32_SFLOAT,
   1134 		VK_FORMAT_R32G32_UINT,
   1135 		VK_FORMAT_R32G32_SINT,
   1136 		VK_FORMAT_R32G32_SFLOAT,
   1137 		VK_FORMAT_R32G32B32_UINT,
   1138 		VK_FORMAT_R32G32B32_SINT,
   1139 		VK_FORMAT_R32G32B32_SFLOAT,
   1140 		VK_FORMAT_R32G32B32A32_UINT,
   1141 		VK_FORMAT_R32G32B32A32_SINT,
   1142 		VK_FORMAT_R32G32B32A32_SFLOAT,
   1143 
   1144 		VK_FORMAT_A2B10G10R10_UNORM_PACK32
   1145 	};
   1146 
   1147 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(vertexFormats); i++)
   1148 	{
   1149 		const std::string				formatName	= getFormatName(vertexFormats[i]);
   1150 		de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx, de::toLower(formatName.substr(10)).c_str(), ""));
   1151 
   1152 		formatGroup->addChild(createDrawTests(testCtx, vertexFormats[i]));
   1153 		formatGroup->addChild(createDrawIndexedTests(testCtx, vertexFormats[i]));
   1154 
   1155 		parentGroup->addChild(formatGroup.release());
   1156 	}
   1157 }
   1158 
   1159 tcu::TestCaseGroup* createVertexAccessTests (tcu::TestContext& testCtx)
   1160 {
   1161 	de::MovePtr<tcu::TestCaseGroup> vertexAccessTests	(new tcu::TestCaseGroup(testCtx, "vertex_access", ""));
   1162 
   1163 	addVertexFormatTests(testCtx, vertexAccessTests.get());
   1164 
   1165 	return vertexAccessTests.release();
   1166 }
   1167 
   1168 } // robustness
   1169 } // vkt
   1170