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 Vertex Input Tests
     23  *//*--------------------------------------------------------------------*/
     24 
     25 #include "vktPipelineVertexInputTests.hpp"
     26 #include "vktTestGroupUtil.hpp"
     27 #include "vktPipelineClearUtil.hpp"
     28 #include "vktPipelineImageUtil.hpp"
     29 #include "vktPipelineVertexUtil.hpp"
     30 #include "vktPipelineReferenceRenderer.hpp"
     31 #include "vktTestCase.hpp"
     32 #include "vktTestCaseUtil.hpp"
     33 #include "vkImageUtil.hpp"
     34 #include "vkMemUtil.hpp"
     35 #include "vkPrograms.hpp"
     36 #include "vkQueryUtil.hpp"
     37 #include "vkRef.hpp"
     38 #include "vkRefUtil.hpp"
     39 #include "vkTypeUtil.hpp"
     40 #include "vkCmdUtil.hpp"
     41 #include "vkObjUtil.hpp"
     42 #include "tcuFloat.hpp"
     43 #include "tcuImageCompare.hpp"
     44 #include "deFloat16.h"
     45 #include "deMemory.h"
     46 #include "deRandom.hpp"
     47 #include "deStringUtil.hpp"
     48 #include "deUniquePtr.hpp"
     49 
     50 #include <sstream>
     51 #include <vector>
     52 
     53 namespace vkt
     54 {
     55 namespace pipeline
     56 {
     57 
     58 using namespace vk;
     59 
     60 namespace
     61 {
     62 
     63 bool isSupportedVertexFormat (Context& context, VkFormat format)
     64 {
     65 	if (isVertexFormatDouble(format) && !context.getDeviceFeatures().shaderFloat64)
     66 		return false;
     67 
     68 	VkFormatProperties  formatProps;
     69 	deMemset(&formatProps, 0, sizeof(VkFormatProperties));
     70 	context.getInstanceInterface().getPhysicalDeviceFormatProperties(context.getPhysicalDevice(), format, &formatProps);
     71 
     72 	return (formatProps.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) != 0u;
     73 }
     74 
     75 float getRepresentableDifferenceUnorm (VkFormat format)
     76 {
     77 	DE_ASSERT(isVertexFormatUnorm(format) || isVertexFormatSRGB(format));
     78 
     79 	return 1.0f / float((1 << (getVertexFormatComponentSize(format) * 8)) - 1);
     80 }
     81 
     82 float getRepresentableDifferenceUnormPacked(VkFormat format, deUint32 componentNdx)
     83 {
     84 	DE_ASSERT((isVertexFormatUnorm(format) || isVertexFormatSRGB(format)) && isVertexFormatPacked(format));
     85 
     86 	return 1.0f / float((1 << (getPackedVertexFormatComponentWidth(format, componentNdx))) - 1);
     87 }
     88 
     89 float getRepresentableDifferenceSnorm (VkFormat format)
     90 {
     91 	DE_ASSERT(isVertexFormatSnorm(format));
     92 
     93 	return 1.0f / float((1 << (getVertexFormatComponentSize(format) * 8 - 1)) - 1);
     94 }
     95 
     96 float getRepresentableDifferenceSnormPacked(VkFormat format, deUint32 componentNdx)
     97 {
     98 	DE_ASSERT(isVertexFormatSnorm(format) && isVertexFormatPacked(format));
     99 
    100 	return 1.0f / float((1 << (getPackedVertexFormatComponentWidth(format, componentNdx) - 1)) - 1);
    101 }
    102 
    103 deUint32 getNextMultipleOffset (deUint32 divisor, deUint32 value)
    104 {
    105 	if (value % divisor == 0)
    106 		return 0;
    107 	else
    108 		return divisor - (value % divisor);
    109 }
    110 
    111 class VertexInputTest : public vkt::TestCase
    112 {
    113 public:
    114 	enum GlslType
    115 	{
    116 		GLSL_TYPE_INT,
    117 		GLSL_TYPE_IVEC2,
    118 		GLSL_TYPE_IVEC3,
    119 		GLSL_TYPE_IVEC4,
    120 
    121 		GLSL_TYPE_UINT,
    122 		GLSL_TYPE_UVEC2,
    123 		GLSL_TYPE_UVEC3,
    124 		GLSL_TYPE_UVEC4,
    125 
    126 		GLSL_TYPE_FLOAT,
    127 		GLSL_TYPE_VEC2,
    128 		GLSL_TYPE_VEC3,
    129 		GLSL_TYPE_VEC4,
    130 		GLSL_TYPE_MAT2,
    131 		GLSL_TYPE_MAT3,
    132 		GLSL_TYPE_MAT4,
    133 
    134 		GLSL_TYPE_DOUBLE,
    135 		GLSL_TYPE_DVEC2,
    136 		GLSL_TYPE_DVEC3,
    137 		GLSL_TYPE_DVEC4,
    138 		GLSL_TYPE_DMAT2,
    139 		GLSL_TYPE_DMAT3,
    140 		GLSL_TYPE_DMAT4,
    141 
    142 		GLSL_TYPE_COUNT
    143 	};
    144 
    145 	enum GlslBasicType
    146 	{
    147 		GLSL_BASIC_TYPE_INT,
    148 		GLSL_BASIC_TYPE_UINT,
    149 		GLSL_BASIC_TYPE_FLOAT,
    150 		GLSL_BASIC_TYPE_DOUBLE
    151 	};
    152 
    153 	enum BindingMapping
    154 	{
    155 		BINDING_MAPPING_ONE_TO_ONE,		//!< Vertex input bindings will not contain data for more than one attribute.
    156 		BINDING_MAPPING_ONE_TO_MANY		//!< Vertex input bindings can contain data for more than one attribute.
    157 	};
    158 
    159 	enum AttributeLayout
    160 	{
    161 		ATTRIBUTE_LAYOUT_INTERLEAVED,	//!< Attribute data is bundled together as if in a structure: [pos 0][color 0][pos 1][color 1]...
    162 		ATTRIBUTE_LAYOUT_SEQUENTIAL		//!< Data for each attribute is laid out separately: [pos 0][pos 1]...[color 0][color 1]...
    163 										//   Sequential only makes a difference if ONE_TO_MANY mapping is used (more than one attribute in a binding).
    164 	};
    165 
    166 	enum LayoutSkip
    167 	{
    168 		LAYOUT_SKIP_ENABLED,	//!< Skip one location slot after each attribute
    169 		LAYOUT_SKIP_DISABLED	//!< Consume locations sequentially
    170 	};
    171 
    172 	enum LayoutOrder
    173 	{
    174 		LAYOUT_ORDER_IN_ORDER,		//!< Assign locations in order
    175 		LAYOUT_ORDER_OUT_OF_ORDER	//!< Assign locations out of order
    176 	};
    177 
    178 	struct AttributeInfo
    179 	{
    180 		GlslType				glslType;
    181 		VkFormat				vkType;
    182 		VkVertexInputRate		inputRate;
    183 	};
    184 
    185 	struct GlslTypeDescription
    186 	{
    187 		const char*		name;
    188 		int				vertexInputComponentCount;
    189 		int				vertexInputCount;
    190 		GlslBasicType	basicType;
    191 	};
    192 
    193 	static const GlslTypeDescription		s_glslTypeDescriptions[GLSL_TYPE_COUNT];
    194 
    195 											VertexInputTest				(tcu::TestContext&					testContext,
    196 																		 const std::string&					name,
    197 																		 const std::string&					description,
    198 																		 const std::vector<AttributeInfo>&	attributeInfos,
    199 																		 BindingMapping						bindingMapping,
    200 																		 AttributeLayout					attributeLayout,
    201 																		 LayoutSkip							layoutSkip = LAYOUT_SKIP_DISABLED,
    202 																		 LayoutOrder						layoutOrder = LAYOUT_ORDER_IN_ORDER);
    203 
    204 	virtual									~VertexInputTest			(void) {}
    205 	virtual void							initPrograms				(SourceCollections& programCollection) const;
    206 	virtual TestInstance*					createInstance				(Context& context) const;
    207 	static bool								isCompatibleType			(VkFormat format, GlslType glslType);
    208 
    209 private:
    210 	AttributeInfo							getAttributeInfo			(size_t attributeNdx) const;
    211 	size_t									getNumAttributes			(void) const;
    212 	std::string								getGlslInputDeclarations	(void) const;
    213 	std::string								getGlslVertexCheck			(void) const;
    214 	std::string								getGlslAttributeConditions	(const AttributeInfo& attributeInfo, const std::string attributeIndex) const;
    215 	static tcu::Vec4						getFormatThreshold			(VkFormat format);
    216 
    217 	const std::vector<AttributeInfo>		m_attributeInfos;
    218 	const BindingMapping					m_bindingMapping;
    219 	const AttributeLayout					m_attributeLayout;
    220 	const LayoutSkip						m_layoutSkip;
    221 	mutable std::vector<deUint32>			m_locations;
    222 	const bool								m_queryMaxAttributes;
    223 	bool									m_usesDoubleType;
    224 	mutable size_t							m_maxAttributes;
    225 };
    226 
    227 class VertexInputInstance : public vkt::TestInstance
    228 {
    229 public:
    230 	struct VertexInputAttributeDescription
    231 	{
    232 		VertexInputTest::GlslType			glslType;
    233 		int									vertexInputIndex;
    234 		VkVertexInputAttributeDescription	vkDescription;
    235 	};
    236 
    237 	typedef	std::vector<VertexInputAttributeDescription>	AttributeDescriptionList;
    238 
    239 											VertexInputInstance			(Context&												context,
    240 																		 const AttributeDescriptionList&						attributeDescriptions,
    241 																		 const std::vector<VkVertexInputBindingDescription>&	bindingDescriptions,
    242 																		 const std::vector<VkDeviceSize>&						bindingOffsets);
    243 
    244 	virtual									~VertexInputInstance		(void);
    245 	virtual tcu::TestStatus					iterate						(void);
    246 
    247 
    248 	static void								writeVertexInputData		(deUint8* destPtr, const VkVertexInputBindingDescription& bindingDescription, const VkDeviceSize bindingOffset, const AttributeDescriptionList& attributes);
    249 	static void								writeVertexInputValue		(deUint8* destPtr, const VertexInputAttributeDescription& attributes, int indexId);
    250 
    251 private:
    252 	tcu::TestStatus							verifyImage					(void);
    253 
    254 private:
    255 	std::vector<VkBuffer>					m_vertexBuffers;
    256 	std::vector<Allocation*>				m_vertexBufferAllocs;
    257 
    258 	const tcu::UVec2						m_renderSize;
    259 	const VkFormat							m_colorFormat;
    260 
    261 	Move<VkImage>							m_colorImage;
    262 	de::MovePtr<Allocation>					m_colorImageAlloc;
    263 	Move<VkImage>							m_depthImage;
    264 	Move<VkImageView>						m_colorAttachmentView;
    265 	Move<VkRenderPass>						m_renderPass;
    266 	Move<VkFramebuffer>						m_framebuffer;
    267 
    268 	Move<VkShaderModule>					m_vertexShaderModule;
    269 	Move<VkShaderModule>					m_fragmentShaderModule;
    270 
    271 	Move<VkPipelineLayout>					m_pipelineLayout;
    272 	Move<VkPipeline>						m_graphicsPipeline;
    273 
    274 	Move<VkCommandPool>						m_cmdPool;
    275 	Move<VkCommandBuffer>					m_cmdBuffer;
    276 };
    277 
    278 const VertexInputTest::GlslTypeDescription VertexInputTest::s_glslTypeDescriptions[GLSL_TYPE_COUNT] =
    279 {
    280 	{ "int",	1, 1, GLSL_BASIC_TYPE_INT },
    281 	{ "ivec2",	2, 1, GLSL_BASIC_TYPE_INT },
    282 	{ "ivec3",	3, 1, GLSL_BASIC_TYPE_INT },
    283 	{ "ivec4",	4, 1, GLSL_BASIC_TYPE_INT },
    284 
    285 	{ "uint",	1, 1, GLSL_BASIC_TYPE_UINT },
    286 	{ "uvec2",	2, 1, GLSL_BASIC_TYPE_UINT },
    287 	{ "uvec3",	3, 1, GLSL_BASIC_TYPE_UINT },
    288 	{ "uvec4",	4, 1, GLSL_BASIC_TYPE_UINT },
    289 
    290 	{ "float",	1, 1, GLSL_BASIC_TYPE_FLOAT },
    291 	{ "vec2",	2, 1, GLSL_BASIC_TYPE_FLOAT },
    292 	{ "vec3",	3, 1, GLSL_BASIC_TYPE_FLOAT },
    293 	{ "vec4",	4, 1, GLSL_BASIC_TYPE_FLOAT },
    294 	{ "mat2",	2, 2, GLSL_BASIC_TYPE_FLOAT },
    295 	{ "mat3",	3, 3, GLSL_BASIC_TYPE_FLOAT },
    296 	{ "mat4",	4, 4, GLSL_BASIC_TYPE_FLOAT },
    297 
    298 	{ "double",	1, 1, GLSL_BASIC_TYPE_DOUBLE },
    299 	{ "dvec2",	2, 1, GLSL_BASIC_TYPE_DOUBLE },
    300 	{ "dvec3",	3, 1, GLSL_BASIC_TYPE_DOUBLE },
    301 	{ "dvec4",	4, 1, GLSL_BASIC_TYPE_DOUBLE },
    302 	{ "dmat2",	2, 2, GLSL_BASIC_TYPE_DOUBLE },
    303 	{ "dmat3",	3, 3, GLSL_BASIC_TYPE_DOUBLE },
    304 	{ "dmat4",	4, 4, GLSL_BASIC_TYPE_DOUBLE }
    305 };
    306 
    307 deUint32 getAttributeBinding (const VertexInputTest::BindingMapping bindingMapping, const VkVertexInputRate firstInputRate, const VkVertexInputRate inputRate, const deUint32 attributeNdx)
    308 {
    309 	if (bindingMapping == VertexInputTest::BINDING_MAPPING_ONE_TO_ONE)
    310 	{
    311 		// Each attribute uses a unique binding
    312 		return attributeNdx;
    313 	}
    314 	else // bindingMapping == BINDING_MAPPING_ONE_TO_MANY
    315 	{
    316 		// Alternate between two bindings
    317 		return deUint32(firstInputRate + inputRate) % 2u;
    318 	}
    319 }
    320 
    321 //! Number of locations used up by an attribute.
    322 deUint32 getConsumedLocations (const VertexInputTest::AttributeInfo& attributeInfo)
    323 {
    324 	// double formats with more than 2 components will take 2 locations
    325 	const VertexInputTest::GlslType type = attributeInfo.glslType;
    326 	if ((type == VertexInputTest::GLSL_TYPE_DMAT2 || type == VertexInputTest::GLSL_TYPE_DMAT3 || type == VertexInputTest::GLSL_TYPE_DMAT4) &&
    327 		(attributeInfo.vkType == VK_FORMAT_R64G64B64_SFLOAT || attributeInfo.vkType == VK_FORMAT_R64G64B64A64_SFLOAT))
    328 	{
    329 		return 2u;
    330 	}
    331 	else
    332 		return 1u;
    333 }
    334 
    335 VertexInputTest::VertexInputTest (tcu::TestContext&						testContext,
    336 								  const std::string&					name,
    337 								  const std::string&					description,
    338 								  const std::vector<AttributeInfo>&		attributeInfos,
    339 								  BindingMapping						bindingMapping,
    340 								  AttributeLayout						attributeLayout,
    341 								  LayoutSkip							layoutSkip,
    342 								  LayoutOrder							layoutOrder)
    343 
    344 	: vkt::TestCase			(testContext, name, description)
    345 	, m_attributeInfos		(attributeInfos)
    346 	, m_bindingMapping		(bindingMapping)
    347 	, m_attributeLayout		(attributeLayout)
    348 	, m_layoutSkip			(layoutSkip)
    349 	, m_queryMaxAttributes	(attributeInfos.size() == 0)
    350 	, m_maxAttributes		(16)
    351 {
    352 	DE_ASSERT(m_attributeLayout == ATTRIBUTE_LAYOUT_INTERLEAVED || m_bindingMapping == BINDING_MAPPING_ONE_TO_MANY);
    353 
    354 	m_usesDoubleType = false;
    355 
    356 	for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++)
    357 	{
    358 		if (s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].basicType == GLSL_BASIC_TYPE_DOUBLE)
    359 		{
    360 			m_usesDoubleType = true;
    361 			break;
    362 		}
    363 	}
    364 
    365 	// Determine number of location slots required for each attribute
    366 	deUint32				attributeLocation		= 0;
    367 	std::vector<deUint32>	locationSlotsNeeded;
    368 	const size_t			numAttributes			= getNumAttributes();
    369 
    370 	for (size_t attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx)
    371 	{
    372 		const AttributeInfo&		attributeInfo			= getAttributeInfo(attributeNdx);
    373 		const GlslTypeDescription&	glslTypeDescription		= s_glslTypeDescriptions[attributeInfo.glslType];
    374 		const deUint32				prevAttributeLocation	= attributeLocation;
    375 
    376 		attributeLocation += glslTypeDescription.vertexInputCount * getConsumedLocations(attributeInfo);
    377 
    378 		if (m_layoutSkip == LAYOUT_SKIP_ENABLED)
    379 			attributeLocation++;
    380 
    381 		locationSlotsNeeded.push_back(attributeLocation - prevAttributeLocation);
    382 	}
    383 
    384 	if (layoutOrder == LAYOUT_ORDER_IN_ORDER)
    385 	{
    386 		deUint32 loc = 0;
    387 
    388 		// Assign locations in order
    389 		for (size_t attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx)
    390 		{
    391 			m_locations.push_back(loc);
    392 			loc += locationSlotsNeeded[attributeNdx];
    393 		}
    394 	}
    395 	else
    396 	{
    397 		// Assign locations out of order
    398 		std::vector<deUint32>	indices;
    399 		std::vector<deUint32>	slots;
    400 		deUint32				slot	= 0;
    401 
    402 		// Mix the location slots: first all even and then all odd attributes.
    403 		for (deUint32 attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx)
    404 			if (attributeNdx % 2 == 0)
    405 				indices.push_back(attributeNdx);
    406 		for (deUint32 attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx)
    407 			if (attributeNdx % 2 != 0)
    408 				indices.push_back(attributeNdx);
    409 
    410 		for (size_t i = 0; i < indices.size(); i++)
    411 		{
    412 			slots.push_back(slot);
    413 			slot += locationSlotsNeeded[indices[i]];
    414 		}
    415 
    416 		for (size_t attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx)
    417 		{
    418 			deUint32 slotIdx = 0;
    419 			for (deUint32 i = 0; i < (deUint32)indices.size(); i++)
    420 				if (attributeNdx == indices[i])
    421 					slotIdx = i;
    422 			m_locations.push_back(slots[slotIdx]);
    423 		}
    424 	}
    425 }
    426 
    427 VertexInputTest::AttributeInfo VertexInputTest::getAttributeInfo (size_t attributeNdx) const
    428 {
    429 	if (m_queryMaxAttributes)
    430 	{
    431 		AttributeInfo attributeInfo =
    432 		{
    433 			GLSL_TYPE_VEC4,
    434 			VK_FORMAT_R8G8B8A8_SNORM,
    435 			(attributeNdx % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE
    436 		};
    437 
    438 		return attributeInfo;
    439 	}
    440 	else
    441 	{
    442 		return m_attributeInfos.at(attributeNdx);
    443 	}
    444 }
    445 
    446 size_t VertexInputTest::getNumAttributes (void) const
    447 {
    448 	if (m_queryMaxAttributes)
    449 		return m_maxAttributes;
    450 	else
    451 		return m_attributeInfos.size();
    452 }
    453 
    454 TestInstance* VertexInputTest::createInstance (Context& context) const
    455 {
    456 	typedef VertexInputInstance::VertexInputAttributeDescription VertexInputAttributeDescription;
    457 
    458 	// Check upfront for maximum number of vertex input attributes
    459 	{
    460 		const InstanceInterface&		vki				= context.getInstanceInterface();
    461 		const VkPhysicalDevice			physDevice		= context.getPhysicalDevice();
    462 		const VkPhysicalDeviceLimits	limits			= getPhysicalDeviceProperties(vki, physDevice).limits;
    463 
    464 		const deUint32					maxAttributes	= limits.maxVertexInputAttributes;
    465 
    466 		if (m_attributeInfos.size() > maxAttributes)
    467 		{
    468 			const std::string notSupportedStr = "Unsupported number of vertex input attributes, maxVertexInputAttributes: " + de::toString(maxAttributes);
    469 			TCU_THROW(NotSupportedError, notSupportedStr.c_str());
    470 		}
    471 
    472 		// Use VkPhysicalDeviceLimits::maxVertexInputAttributes
    473 		if (m_queryMaxAttributes)
    474 		{
    475 			m_maxAttributes = maxAttributes;
    476 			m_locations.clear();
    477 			for (deUint32 i = 0; i < maxAttributes; i++)
    478 				m_locations.push_back(i);
    479 		}
    480 	}
    481 
    482 	// Create enough binding descriptions with random offsets
    483 	std::vector<VkVertexInputBindingDescription>	bindingDescriptions;
    484 	std::vector<VkDeviceSize>						bindingOffsets;
    485 	const size_t									numAttributes		= getNumAttributes();
    486 	const size_t									numBindings			= (m_bindingMapping == BINDING_MAPPING_ONE_TO_ONE) ? numAttributes : ((numAttributes > 1) ? 2 : 1);
    487 	const VkVertexInputRate							firstInputrate		= getAttributeInfo(0).inputRate;
    488 
    489 	for (size_t bindingNdx = 0; bindingNdx < numBindings; ++bindingNdx)
    490 	{
    491 		// Bindings alternate between STEP_RATE_VERTEX and STEP_RATE_INSTANCE
    492 		const VkVertexInputRate						inputRate			= ((firstInputrate + bindingNdx) % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
    493 
    494 		// Stride will be updated when creating the attribute descriptions
    495 		const VkVertexInputBindingDescription		bindingDescription	=
    496 		{
    497 			static_cast<deUint32>(bindingNdx),		// deUint32				binding;
    498 			0u,										// deUint32				stride;
    499 			inputRate								// VkVertexInputRate	inputRate;
    500 		};
    501 
    502 		bindingDescriptions.push_back(bindingDescription);
    503 		bindingOffsets.push_back(4 * bindingNdx);
    504 	}
    505 
    506 	std::vector<VertexInputAttributeDescription>	attributeDescriptions;
    507 	std::vector<deUint32>							attributeOffsets		(bindingDescriptions.size(), 0);
    508 	std::vector<deUint32>							attributeMaxSizes		(bindingDescriptions.size(), 0);	// max component or vector size, depending on which layout we are using
    509 
    510 	// To place the attributes sequentially we need to know the largest attribute and use its size in stride and offset calculations.
    511 	if (m_attributeLayout == ATTRIBUTE_LAYOUT_SEQUENTIAL)
    512 		for (size_t attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx)
    513 		{
    514 			const AttributeInfo&	attributeInfo			= getAttributeInfo(attributeNdx);
    515 			const deUint32			attributeBinding		= getAttributeBinding(m_bindingMapping, firstInputrate, attributeInfo.inputRate, static_cast<deUint32>(attributeNdx));
    516 			const deUint32			inputSize				= getVertexFormatSize(attributeInfo.vkType);
    517 
    518 			attributeMaxSizes[attributeBinding]				= de::max(attributeMaxSizes[attributeBinding], inputSize);
    519 		}
    520 
    521 	// Create attribute descriptions, assign them to bindings and update stride.
    522 	for (size_t attributeNdx = 0; attributeNdx < numAttributes; ++attributeNdx)
    523 	{
    524 		const AttributeInfo&		attributeInfo			= getAttributeInfo(attributeNdx);
    525 		const GlslTypeDescription&	glslTypeDescription		= s_glslTypeDescriptions[attributeInfo.glslType];
    526 		const deUint32				inputSize				= getVertexFormatSize(attributeInfo.vkType);
    527 		const deUint32				attributeBinding		= getAttributeBinding(m_bindingMapping, firstInputrate, attributeInfo.inputRate, static_cast<deUint32>(attributeNdx));
    528 		const deUint32				vertexCount				= (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) ? (4 * 2) : 2;
    529 
    530 		VertexInputAttributeDescription attributeDescription =
    531 		{
    532 			attributeInfo.glslType,							// GlslType		glslType;
    533 			0,												// int			vertexInputIndex;
    534 			{
    535 				0u,											// uint32_t    location;
    536 				attributeBinding,							// uint32_t    binding;
    537 				attributeInfo.vkType,						// VkFormat    format;
    538 				0u,											// uint32_t    offset;
    539 			},
    540 		};
    541 
    542 		// Matrix types add each column as a separate attribute.
    543 		for (int descNdx = 0; descNdx < glslTypeDescription.vertexInputCount; ++descNdx)
    544 		{
    545 			attributeDescription.vertexInputIndex		= descNdx;
    546 			attributeDescription.vkDescription.location	= m_locations[attributeNdx] + getConsumedLocations(attributeInfo) * descNdx;
    547 
    548 			if (m_attributeLayout == ATTRIBUTE_LAYOUT_INTERLEAVED)
    549 			{
    550 				const deUint32	offsetToComponentAlignment		 = getNextMultipleOffset(getVertexFormatSize(attributeInfo.vkType),
    551 																						 (deUint32)bindingOffsets[attributeBinding] + attributeOffsets[attributeBinding]);
    552 
    553 				attributeOffsets[attributeBinding]				+= offsetToComponentAlignment;
    554 
    555 				attributeDescription.vkDescription.offset		 = attributeOffsets[attributeBinding];
    556 				attributeDescriptions.push_back(attributeDescription);
    557 
    558 				bindingDescriptions[attributeBinding].stride	+= offsetToComponentAlignment + inputSize;
    559 				attributeOffsets[attributeBinding]				+= inputSize;
    560 				attributeMaxSizes[attributeBinding]				 = de::max(attributeMaxSizes[attributeBinding], getVertexFormatSize(attributeInfo.vkType));
    561 			}
    562 			else // m_attributeLayout == ATTRIBUTE_LAYOUT_SEQUENTIAL
    563 			{
    564 				attributeDescription.vkDescription.offset		 = attributeOffsets[attributeBinding];
    565 				attributeDescriptions.push_back(attributeDescription);
    566 
    567 				attributeOffsets[attributeBinding]				+= vertexCount * attributeMaxSizes[attributeBinding];
    568 			}
    569 		}
    570 
    571 		if (m_attributeLayout == ATTRIBUTE_LAYOUT_SEQUENTIAL)
    572 			bindingDescriptions[attributeBinding].stride = attributeMaxSizes[attributeBinding];
    573 	}
    574 
    575 	// Make sure the stride results in aligned access
    576 	for (size_t bindingNdx = 0; bindingNdx < bindingDescriptions.size(); ++bindingNdx)
    577 	{
    578 		if (attributeMaxSizes[bindingNdx] > 0)
    579 			bindingDescriptions[bindingNdx].stride += getNextMultipleOffset(attributeMaxSizes[bindingNdx], bindingDescriptions[bindingNdx].stride);
    580 	}
    581 
    582 	// Check upfront for maximum number of vertex input bindings
    583 	{
    584 		const InstanceInterface&		vki				= context.getInstanceInterface();
    585 		const VkPhysicalDevice			physDevice		= context.getPhysicalDevice();
    586 		const VkPhysicalDeviceLimits	limits			= getPhysicalDeviceProperties(vki, physDevice).limits;
    587 
    588 		const deUint32					maxBindings		= limits.maxVertexInputBindings;
    589 
    590 		if (bindingDescriptions.size() > maxBindings)
    591 		{
    592 			const std::string notSupportedStr = "Unsupported number of vertex input bindings, maxVertexInputBindings: " + de::toString(maxBindings);
    593 			TCU_THROW(NotSupportedError, notSupportedStr.c_str());
    594 		}
    595 	}
    596 
    597 	return new VertexInputInstance(context, attributeDescriptions, bindingDescriptions, bindingOffsets);
    598 }
    599 
    600 void VertexInputTest::initPrograms (SourceCollections& programCollection) const
    601 {
    602 	std::ostringstream vertexSrc;
    603 
    604 	vertexSrc << "#version 440\n"
    605 			  << "layout(constant_id = 0) const int numAttributes = " << m_maxAttributes << ";\n"
    606 			  << getGlslInputDeclarations()
    607 			  << "layout(location = 0) out highp vec4 vtxColor;\n"
    608 			  << "out gl_PerVertex {\n"
    609 			  << "  vec4 gl_Position;\n"
    610 			  << "};\n";
    611 
    612 	// NOTE: double abs(double x) undefined in glslang ??
    613 	if (m_usesDoubleType)
    614 		vertexSrc << "double abs (double x) { if (x < 0.0LF) return -x; else return x; }\n";
    615 
    616 	vertexSrc << "void main (void)\n"
    617 			  << "{\n"
    618 			  << getGlslVertexCheck()
    619 			  << "}\n";
    620 
    621 	programCollection.glslSources.add("attribute_test_vert") << glu::VertexSource(vertexSrc.str());
    622 
    623 	programCollection.glslSources.add("attribute_test_frag") << glu::FragmentSource(
    624 		"#version 440\n"
    625 		"layout(location = 0) in highp vec4 vtxColor;\n"
    626 		"layout(location = 0) out highp vec4 fragColor;\n"
    627 		"void main (void)\n"
    628 		"{\n"
    629 		"	fragColor = vtxColor;\n"
    630 		"}\n");
    631 }
    632 
    633 std::string VertexInputTest::getGlslInputDeclarations (void) const
    634 {
    635 	std::ostringstream	glslInputs;
    636 
    637 	if (m_queryMaxAttributes)
    638 	{
    639 		const GlslTypeDescription& glslTypeDesc = s_glslTypeDescriptions[GLSL_TYPE_VEC4];
    640 		glslInputs << "layout(location = 0) in " << glslTypeDesc.name << " attr[numAttributes];\n";
    641 	}
    642 	else
    643 	{
    644 		for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++)
    645 		{
    646 			const GlslTypeDescription& glslTypeDesc = s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType];
    647 
    648 			glslInputs << "layout(location = " << m_locations[attributeNdx] << ") in " << glslTypeDesc.name << " attr" << attributeNdx << ";\n";
    649 		}
    650 	}
    651 
    652 	return glslInputs.str();
    653 }
    654 
    655 std::string VertexInputTest::getGlslVertexCheck (void) const
    656 {
    657 	std::ostringstream	glslCode;
    658 	int					totalInputComponentCount	= 0;
    659 
    660 	glslCode << "	int okCount = 0;\n";
    661 
    662 	if (m_queryMaxAttributes)
    663 	{
    664 		const AttributeInfo attributeInfo = getAttributeInfo(0);
    665 
    666 		glslCode << "	for (int checkNdx = 0; checkNdx < numAttributes; checkNdx++)\n"
    667 				 <<	"	{\n"
    668 				 << "		uint index = (checkNdx % 2 == 0) ? gl_VertexIndex : gl_InstanceIndex;\n";
    669 
    670 		glslCode << getGlslAttributeConditions(attributeInfo, "checkNdx")
    671 				 << "	}\n";
    672 
    673 			const int vertexInputCount	= VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputCount;
    674 			totalInputComponentCount	+= vertexInputCount * VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputComponentCount;
    675 
    676 		glslCode <<
    677 			"	if (okCount == " << totalInputComponentCount << " * numAttributes)\n"
    678 			"	{\n"
    679 			"		if (gl_InstanceIndex == 0)\n"
    680 			"			vtxColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
    681 			"		else\n"
    682 			"			vtxColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
    683 			"	}\n"
    684 			"	else\n"
    685 			"	{\n"
    686 			"		vtxColor = vec4(okCount / float(" << totalInputComponentCount << " * numAttributes), 0.0f, 0.0f, 1.0);\n" <<
    687 			"	}\n\n"
    688 			"	if (gl_InstanceIndex == 0)\n"
    689 			"	{\n"
    690 			"		if (gl_VertexIndex == 0) gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
    691 			"		else if (gl_VertexIndex == 1) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
    692 			"		else if (gl_VertexIndex == 2) gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
    693 			"		else if (gl_VertexIndex == 3) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n"
    694 			"		else gl_Position = vec4(0.0);\n"
    695 			"	}\n"
    696 			"	else\n"
    697 			"	{\n"
    698 			"		if (gl_VertexIndex == 0) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
    699 			"		else if (gl_VertexIndex == 1) gl_Position = vec4(1.0, -1.0, 0.0, 1.0);\n"
    700 			"		else if (gl_VertexIndex == 2) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n"
    701 			"		else if (gl_VertexIndex == 3) gl_Position = vec4(1.0, 1.0, 0.0, 1.0);\n"
    702 			"		else gl_Position = vec4(0.0);\n"
    703 			"	}\n";
    704 	}
    705 	else
    706 	{
    707 		for (size_t attributeNdx = 0; attributeNdx < m_attributeInfos.size(); attributeNdx++)
    708 		{
    709 			glslCode << getGlslAttributeConditions(m_attributeInfos[attributeNdx], de::toString(attributeNdx));
    710 
    711 			const int vertexInputCount	= VertexInputTest::s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].vertexInputCount;
    712 			totalInputComponentCount	+= vertexInputCount * VertexInputTest::s_glslTypeDescriptions[m_attributeInfos[attributeNdx].glslType].vertexInputComponentCount;
    713 		}
    714 
    715 		glslCode <<
    716 			"	if (okCount == " << totalInputComponentCount << ")\n"
    717 			"	{\n"
    718 			"		if (gl_InstanceIndex == 0)\n"
    719 			"			vtxColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
    720 			"		else\n"
    721 			"			vtxColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
    722 			"	}\n"
    723 			"	else\n"
    724 			"	{\n"
    725 			"		vtxColor = vec4(okCount / float(" << totalInputComponentCount << "), 0.0f, 0.0f, 1.0);\n" <<
    726 			"	}\n\n"
    727 			"	if (gl_InstanceIndex == 0)\n"
    728 			"	{\n"
    729 			"		if (gl_VertexIndex == 0) gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
    730 			"		else if (gl_VertexIndex == 1) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
    731 			"		else if (gl_VertexIndex == 2) gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
    732 			"		else if (gl_VertexIndex == 3) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n"
    733 			"		else gl_Position = vec4(0.0);\n"
    734 			"	}\n"
    735 			"	else\n"
    736 			"	{\n"
    737 			"		if (gl_VertexIndex == 0) gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
    738 			"		else if (gl_VertexIndex == 1) gl_Position = vec4(1.0, -1.0, 0.0, 1.0);\n"
    739 			"		else if (gl_VertexIndex == 2) gl_Position = vec4(0.0, 1.0, 0.0, 1.0);\n"
    740 			"		else if (gl_VertexIndex == 3) gl_Position = vec4(1.0, 1.0, 0.0, 1.0);\n"
    741 			"		else gl_Position = vec4(0.0);\n"
    742 			"	}\n";
    743 	}
    744 	return glslCode.str();
    745 }
    746 
    747 std::string VertexInputTest::getGlslAttributeConditions (const AttributeInfo& attributeInfo, const std::string attributeIndex) const
    748 {
    749 	std::ostringstream	glslCode;
    750 	std::ostringstream	attributeVar;
    751 	const int			componentCount		= VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputComponentCount;
    752 	const int			vertexInputCount	= VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].vertexInputCount;
    753 	const deUint32		totalComponentCount	= componentCount * vertexInputCount;
    754 	const tcu::Vec4		threshold			= getFormatThreshold(attributeInfo.vkType);
    755 	const std::string	indexStr			= m_queryMaxAttributes ? "[" + attributeIndex + "]" : attributeIndex;
    756 	const std::string	indentStr			= m_queryMaxAttributes ? "\t\t" : "\t";
    757 	deUint32			componentIndex		= 0;
    758 	deUint32			orderNdx;
    759 	std::string			indexId;
    760 
    761 	const deUint32		BGROrder[]			= { 2, 1, 0, 3 };
    762 	const deUint32		ABGROrder[]			= { 3, 2, 1, 0 };
    763 	const deUint32		ARGBOrder[]			= { 1, 2, 3, 0 };
    764 
    765 	if (m_queryMaxAttributes)
    766 		indexId	= "index";
    767 	else
    768 		indexId	= (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) ? "gl_VertexIndex" : "gl_InstanceIndex";
    769 
    770 	attributeVar << "attr" << indexStr;
    771 
    772 	glslCode << std::fixed;
    773 
    774 	for (int columnNdx = 0; columnNdx< vertexInputCount; columnNdx++)
    775 	{
    776 		for (int rowNdx = 0; rowNdx < componentCount; rowNdx++)
    777 		{
    778 			if (isVertexFormatComponentOrderABGR(attributeInfo.vkType))
    779 				orderNdx = ABGROrder[rowNdx];
    780 			else if (isVertexFormatComponentOrderARGB(attributeInfo.vkType))
    781 				orderNdx = ARGBOrder[rowNdx];
    782 			else
    783 				orderNdx = BGROrder[rowNdx];
    784 
    785 			std::string accessStr;
    786 			{
    787 				// Build string representing the access to the attribute component
    788 				std::ostringstream accessStream;
    789 				accessStream << attributeVar.str();
    790 
    791 				if (vertexInputCount == 1)
    792 				{
    793 					if (componentCount > 1)
    794 						accessStream << "[" << rowNdx << "]";
    795 				}
    796 				else
    797 				{
    798 					accessStream << "[" << columnNdx << "][" << rowNdx << "]";
    799 				}
    800 
    801 				accessStr = accessStream.str();
    802 			}
    803 
    804 			if (isVertexFormatSint(attributeInfo.vkType))
    805 			{
    806 				if (isVertexFormatPacked(attributeInfo.vkType))
    807 				{
    808 					const deInt32 maxIntValue = (1 << (getPackedVertexFormatComponentWidth(attributeInfo.vkType, orderNdx) - 1)) - 1;
    809 					const deInt32 minIntValue = -maxIntValue;
    810 
    811 					glslCode << indentStr << "if (" << accessStr << " == clamp(-(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "), " << minIntValue << ", " << maxIntValue << "))\n";
    812 				}
    813 				else
    814 					glslCode << indentStr << "if (" << accessStr << " == -(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "))\n";
    815 			}
    816 			else if (isVertexFormatUint(attributeInfo.vkType))
    817 			{
    818 				if (isVertexFormatPacked(attributeInfo.vkType))
    819 				{
    820 					const deUint32 maxUintValue = (1 << getPackedVertexFormatComponentWidth(attributeInfo.vkType, orderNdx)) - 1;
    821 
    822 					glslCode << indentStr << "if (" << accessStr << " == clamp(uint(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "), 0, " << maxUintValue << "))\n";
    823 				}
    824 				else
    825 					glslCode << indentStr << "if (" << accessStr << " == uint(" << totalComponentCount << " * " << indexId << " + " << componentIndex << "))\n";
    826 			}
    827 			else if (isVertexFormatSfloat(attributeInfo.vkType))
    828 			{
    829 				if (VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].basicType == VertexInputTest::GLSL_BASIC_TYPE_DOUBLE)
    830 				{
    831 					glslCode << indentStr << "if (abs(" << accessStr << " + double(0.01 * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < double(" << threshold[rowNdx] << "))\n";
    832 				}
    833 				else
    834 				{
    835 					glslCode << indentStr << "if (abs(" << accessStr << " + (0.01 * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n";
    836 				}
    837 			}
    838 			else if (isVertexFormatSscaled(attributeInfo.vkType))
    839 			{
    840 				if (isVertexFormatPacked(attributeInfo.vkType))
    841 				{
    842 					const float maxScaledValue = float((1 << (getPackedVertexFormatComponentWidth(attributeInfo.vkType, orderNdx) - 1)) - 1);
    843 					const float minScaledValue = -maxScaledValue - 1.0f;
    844 
    845 					glslCode << indentStr << "if (abs(" << accessStr << " + clamp(" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0, " << minScaledValue << ", " << maxScaledValue << ")) < " << threshold[orderNdx] << ")\n";
    846 				}
    847 				else
    848 					glslCode << indentStr << "if (abs(" << accessStr << " + (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)) < " << threshold[rowNdx] << ")\n";
    849 			}
    850 			else if (isVertexFormatUscaled(attributeInfo.vkType))
    851 			{
    852 				if (isVertexFormatPacked(attributeInfo.vkType))
    853 				{
    854 					const float maxScaledValue = float((1 << getPackedVertexFormatComponentWidth(attributeInfo.vkType, orderNdx)) - 1);
    855 
    856 					glslCode << indentStr << "if (abs(" << accessStr << " - clamp(" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0, 0, " << maxScaledValue << ")) < " << threshold[orderNdx] << ")\n";
    857 				}
    858 				else
    859 					glslCode << indentStr << "if (abs(" << accessStr << " - (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)) < " << threshold[rowNdx] << ")\n";
    860 			}
    861 			else if (isVertexFormatSnorm(attributeInfo.vkType))
    862 			{
    863 				const float representableDiff = isVertexFormatPacked(attributeInfo.vkType) ? getRepresentableDifferenceSnormPacked(attributeInfo.vkType, orderNdx) : getRepresentableDifferenceSnorm(attributeInfo.vkType);
    864 
    865 				if(isVertexFormatPacked(attributeInfo.vkType))
    866 					glslCode << indentStr << "if (abs(" << accessStr << " - clamp((-1.0 + " << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)), -1.0, 1.0)) < " << threshold[orderNdx] << ")\n";
    867 				else
    868 					glslCode << indentStr << "if (abs(" << accessStr << " - (-1.0 + " << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n";
    869 			}
    870 			else if (isVertexFormatUnorm(attributeInfo.vkType) || isVertexFormatSRGB(attributeInfo.vkType))
    871 			{
    872 				const float representableDiff = isVertexFormatPacked(attributeInfo.vkType) ? getRepresentableDifferenceUnormPacked(attributeInfo.vkType, orderNdx) : getRepresentableDifferenceUnorm(attributeInfo.vkType);
    873 
    874 				if (isVertexFormatPacked(attributeInfo.vkType))
    875 					glslCode << indentStr << "if (abs(" << accessStr << " - " << "clamp((" << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0)), 0.0, 1.0)) < " << threshold[orderNdx] << ")\n";
    876 				else
    877 					glslCode << indentStr << "if (abs(" << accessStr << " - " << "(" << representableDiff << " * (" << totalComponentCount << ".0 * float(" << indexId << ") + " << componentIndex << ".0))) < " << threshold[rowNdx] << ")\n";
    878 			}
    879 			else
    880 			{
    881 				DE_ASSERT(false);
    882 			}
    883 
    884 			glslCode << indentStr << "\tokCount++;\n\n";
    885 
    886 			componentIndex++;
    887 		}
    888 	}
    889 	return glslCode.str();
    890 }
    891 
    892 tcu::Vec4 VertexInputTest::getFormatThreshold (VkFormat format)
    893 {
    894 	using tcu::Vec4;
    895 
    896 	switch (format)
    897 	{
    898 		case VK_FORMAT_R32_SFLOAT:
    899 		case VK_FORMAT_R32G32_SFLOAT:
    900 		case VK_FORMAT_R32G32B32_SFLOAT:
    901 		case VK_FORMAT_R32G32B32A32_SFLOAT:
    902 		case VK_FORMAT_R64_SFLOAT:
    903 		case VK_FORMAT_R64G64_SFLOAT:
    904 		case VK_FORMAT_R64G64B64_SFLOAT:
    905 		case VK_FORMAT_R64G64B64A64_SFLOAT:
    906 			return Vec4(0.00001f);
    907 
    908 		default:
    909 			break;
    910 	}
    911 
    912 	if (isVertexFormatSnorm(format))
    913 	{
    914 		return (isVertexFormatPacked(format) ? Vec4(1.5f * getRepresentableDifferenceSnormPacked(format, 0),
    915 													1.5f * getRepresentableDifferenceSnormPacked(format, 1),
    916 													1.5f * getRepresentableDifferenceSnormPacked(format, 2),
    917 													1.5f * getRepresentableDifferenceSnormPacked(format, 3))
    918 													: Vec4(1.5f * getRepresentableDifferenceSnorm(format)));
    919 	}
    920 	else if (isVertexFormatUnorm(format))
    921 	{
    922 		return (isVertexFormatPacked(format) ? Vec4(1.5f * getRepresentableDifferenceUnormPacked(format, 0),
    923 													1.5f * getRepresentableDifferenceUnormPacked(format, 1),
    924 													1.5f * getRepresentableDifferenceUnormPacked(format, 2),
    925 													1.5f * getRepresentableDifferenceUnormPacked(format, 3))
    926 													: Vec4(1.5f * getRepresentableDifferenceUnorm(format)));
    927 	}
    928 
    929 	return Vec4(0.001f);
    930 }
    931 
    932 VertexInputInstance::VertexInputInstance (Context&												context,
    933 										  const AttributeDescriptionList&						attributeDescriptions,
    934 										  const std::vector<VkVertexInputBindingDescription>&	bindingDescriptions,
    935 										  const std::vector<VkDeviceSize>&						bindingOffsets)
    936 	: vkt::TestInstance			(context)
    937 	, m_renderSize				(16, 16)
    938 	, m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
    939 {
    940 	DE_ASSERT(bindingDescriptions.size() == bindingOffsets.size());
    941 
    942 	const DeviceInterface&		vk						= context.getDeviceInterface();
    943 	const VkDevice				vkDevice				= context.getDevice();
    944 	const deUint32				queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
    945 	SimpleAllocator				memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
    946 	const VkComponentMapping	componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
    947 
    948 	// Check upfront for unsupported features
    949 	for (size_t attributeNdx = 0; attributeNdx < attributeDescriptions.size(); attributeNdx++)
    950 	{
    951 		const VkVertexInputAttributeDescription& attributeDescription = attributeDescriptions[attributeNdx].vkDescription;
    952 		if (!isSupportedVertexFormat(context, attributeDescription.format))
    953 		{
    954 			throw tcu::NotSupportedError(std::string("Unsupported format for vertex input: ") + getFormatName(attributeDescription.format));
    955 		}
    956 	}
    957 
    958 	// Create color image
    959 	{
    960 		const VkImageCreateInfo colorImageParams =
    961 		{
    962 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
    963 			DE_NULL,																	// const void*				pNext;
    964 			0u,																			// VkImageCreateFlags		flags;
    965 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
    966 			m_colorFormat,																// VkFormat					format;
    967 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
    968 			1u,																			// deUint32					mipLevels;
    969 			1u,																			// deUint32					arrayLayers;
    970 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
    971 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
    972 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
    973 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
    974 			1u,																			// deUint32					queueFamilyIndexCount;
    975 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
    976 			VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout			initialLayout;
    977 		};
    978 
    979 		m_colorImage			= createImage(vk, vkDevice, &colorImageParams);
    980 
    981 		// Allocate and bind color image memory
    982 		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
    983 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
    984 	}
    985 
    986 	// Create color attachment view
    987 	{
    988 		const VkImageViewCreateInfo colorAttachmentViewParams =
    989 		{
    990 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
    991 			DE_NULL,										// const void*				pNext;
    992 			0u,												// VkImageViewCreateFlags	flags;
    993 			*m_colorImage,									// VkImage					image;
    994 			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType			viewType;
    995 			m_colorFormat,									// VkFormat					format;
    996 			componentMappingRGBA,							// VkComponentMapping		components;
    997 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },  // VkImageSubresourceRange	subresourceRange;
    998 		};
    999 
   1000 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
   1001 	}
   1002 
   1003 	// Create render pass
   1004 	m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat);
   1005 
   1006 	// Create framebuffer
   1007 	{
   1008 		const VkFramebufferCreateInfo framebufferParams =
   1009 		{
   1010 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
   1011 			DE_NULL,											// const void*				pNext;
   1012 			0u,													// VkFramebufferCreateFlags	flags;
   1013 			*m_renderPass,										// VkRenderPass				renderPass;
   1014 			1u,													// deUint32					attachmentCount;
   1015 			&m_colorAttachmentView.get(),						// const VkImageView*		pAttachments;
   1016 			(deUint32)m_renderSize.x(),							// deUint32					width;
   1017 			(deUint32)m_renderSize.y(),							// deUint32					height;
   1018 			1u													// deUint32					layers;
   1019 		};
   1020 
   1021 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
   1022 	}
   1023 
   1024 	// Create pipeline layout
   1025 	{
   1026 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
   1027 		{
   1028 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
   1029 			DE_NULL,											// const void*						pNext;
   1030 			0u,													// VkPipelineLayoutCreateFlags		flags;
   1031 			0u,													// deUint32							setLayoutCount;
   1032 			DE_NULL,											// const VkDescriptorSetLayout*		pSetLayouts;
   1033 			0u,													// deUint32							pushConstantRangeCount;
   1034 			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
   1035 		};
   1036 
   1037 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
   1038 	}
   1039 
   1040 	m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("attribute_test_vert"), 0);
   1041 	m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("attribute_test_frag"), 0);
   1042 
   1043 	// Create specialization constant
   1044 	deUint32 specializationData = static_cast<deUint32>(attributeDescriptions.size());
   1045 
   1046 	const VkSpecializationMapEntry specializationMapEntry =
   1047 	{
   1048 		0,														// uint32_t							constantID
   1049 		0,														// uint32_t							offset
   1050 		sizeof(specializationData),								// uint32_t							size
   1051 	};
   1052 
   1053 	const VkSpecializationInfo specializationInfo =
   1054 	{
   1055 		1,														// uint32_t							mapEntryCount
   1056 		&specializationMapEntry,								// const void*						pMapEntries
   1057 		sizeof(specializationData),								// size_t							dataSize
   1058 		&specializationData										// const void*						pData
   1059 	};
   1060 
   1061 	// Create pipeline
   1062 	{
   1063 		const VkPipelineShaderStageCreateInfo shaderStageParams[2] =
   1064 		{
   1065 			{
   1066 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
   1067 				DE_NULL,													// const void*							pNext;
   1068 				0u,															// VkPipelineShaderStageCreateFlags		flags;
   1069 				VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBits				stage;
   1070 				*m_vertexShaderModule,										// VkShaderModule						module;
   1071 				"main",														// const char*							pName;
   1072 				&specializationInfo											// const VkSpecializationInfo*			pSpecializationInfo;
   1073 			},
   1074 			{
   1075 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
   1076 				DE_NULL,													// const void*							pNext;
   1077 				0u,															// VkPipelineShaderStageCreateFlags		flags;
   1078 				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBits				stage;
   1079 				*m_fragmentShaderModule,									// VkShaderModule						module;
   1080 				"main",														// const char*							pName;
   1081 				DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
   1082 			}
   1083 		};
   1084 
   1085 		// Create vertex attribute array and check if their VK formats are supported
   1086 		std::vector<VkVertexInputAttributeDescription> vkAttributeDescriptions;
   1087 		for (size_t attributeNdx = 0; attributeNdx < attributeDescriptions.size(); attributeNdx++)
   1088 		{
   1089 			const VkVertexInputAttributeDescription& attributeDescription = attributeDescriptions[attributeNdx].vkDescription;
   1090 			vkAttributeDescriptions.push_back(attributeDescription);
   1091 		}
   1092 
   1093 		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams	=
   1094 		{
   1095 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
   1096 			DE_NULL,														// const void*								pNext;
   1097 			0u,																// VkPipelineVertexInputStateCreateFlags	flags;
   1098 			(deUint32)bindingDescriptions.size(),							// deUint32									vertexBindingDescriptionCount;
   1099 			bindingDescriptions.data(),										// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
   1100 			(deUint32)vkAttributeDescriptions.size(),						// deUint32									vertexAttributeDescriptionCount;
   1101 			vkAttributeDescriptions.data()									// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
   1102 		};
   1103 
   1104 		const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
   1105 		{
   1106 			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
   1107 			DE_NULL,														// const void*								pNext;
   1108 			0u,																// VkPipelineInputAssemblyStateCreateFlags	flags;
   1109 			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,							// VkPrimitiveTopology						topology;
   1110 			false															// VkBool32									primitiveRestartEnable;
   1111 		};
   1112 
   1113 		const VkViewport	viewport	= makeViewport(m_renderSize);
   1114 		const VkRect2D		scissor		= makeRect2D(m_renderSize);
   1115 
   1116 		const VkPipelineViewportStateCreateInfo viewportStateParams =
   1117 		{
   1118 			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType						sType;
   1119 			DE_NULL,														// const void*							pNext;
   1120 			0u,																// VkPipelineViewportStateCreateFlags	flags;
   1121 			1u,																// deUint32								viewportCount;
   1122 			&viewport,														// const VkViewport*					pViewports;
   1123 			1u,																// deUint32								scissorCount;
   1124 			&scissor														// const VkRect2D*						pScissors;
   1125 		};
   1126 
   1127 		const VkPipelineRasterizationStateCreateInfo rasterStateParams =
   1128 		{
   1129 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
   1130 			DE_NULL,														// const void*								pNext;
   1131 			0u,																// VkPipelineRasterizationStateCreateFlags	flags;
   1132 			false,															// VkBool32									depthClampEnable;
   1133 			false,															// VkBool32									rasterizerDiscardEnable;
   1134 			VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
   1135 			VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
   1136 			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
   1137 			VK_FALSE,														// VkBool32									depthBiasEnable;
   1138 			0.0f,															// float									depthBiasConstantFactor;
   1139 			0.0f,															// float									depthBiasClamp;
   1140 			0.0f,															// float									depthBiasSlopeFactor;
   1141 			1.0f,															// float									lineWidth;
   1142 		};
   1143 
   1144 		const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
   1145 		{
   1146 			false,																		// VkBool32					blendEnable;
   1147 			VK_BLEND_FACTOR_ONE,														// VkBlendFactor			srcColorBlendFactor;
   1148 			VK_BLEND_FACTOR_ZERO,														// VkBlendFactor			dstColorBlendFactor;
   1149 			VK_BLEND_OP_ADD,															// VkBlendOp				colorBlendOp;
   1150 			VK_BLEND_FACTOR_ONE,														// VkBlendFactor			srcAlphaBlendFactor;
   1151 			VK_BLEND_FACTOR_ZERO,														// VkBlendFactor			dstAlphaBlendFactor;
   1152 			VK_BLEND_OP_ADD,															// VkBlendOp				alphaBlendOp;
   1153 			VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |						// VkColorComponentFlags	colorWriteMask;
   1154 				VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
   1155 		};
   1156 
   1157 		const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
   1158 		{
   1159 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
   1160 			DE_NULL,													// const void*									pNext;
   1161 			0u,															// VkPipelineColorBlendStateCreateFlags			flags;
   1162 			false,														// VkBool32										logicOpEnable;
   1163 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
   1164 			1u,															// deUint32										attachmentCount;
   1165 			&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
   1166 			{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
   1167 		};
   1168 
   1169 		const VkPipelineMultisampleStateCreateInfo	multisampleStateParams	=
   1170 		{
   1171 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
   1172 			DE_NULL,													// const void*								pNext;
   1173 			0u,															// VkPipelineMultisampleStateCreateFlags	flags;
   1174 			VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
   1175 			false,														// VkBool32									sampleShadingEnable;
   1176 			0.0f,														// float									minSampleShading;
   1177 			DE_NULL,													// const VkSampleMask*						pSampleMask;
   1178 			false,														// VkBool32									alphaToCoverageEnable;
   1179 			false														// VkBool32									alphaToOneEnable;
   1180 		};
   1181 
   1182 		VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
   1183 		{
   1184 			VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
   1185 			DE_NULL,													// const void*								pNext;
   1186 			0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
   1187 			false,														// VkBool32									depthTestEnable;
   1188 			false,														// VkBool32									depthWriteEnable;
   1189 			VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
   1190 			false,														// VkBool32									depthBoundsTestEnable;
   1191 			false,														// VkBool32									stencilTestEnable;
   1192 			// VkStencilOpState	front;
   1193 			{
   1194 				VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
   1195 				VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
   1196 				VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
   1197 				VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
   1198 				0u,						// deUint32		compareMask;
   1199 				0u,						// deUint32		writeMask;
   1200 				0u,						// deUint32		reference;
   1201 			},
   1202 			// VkStencilOpState	back;
   1203 			{
   1204 				VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
   1205 				VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
   1206 				VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
   1207 				VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
   1208 				0u,						// deUint32		compareMask;
   1209 				0u,						// deUint32		writeMask;
   1210 				0u,						// deUint32		reference;
   1211 			},
   1212 			0.0f,														// float			minDepthBounds;
   1213 			1.0f,														// float			maxDepthBounds;
   1214 		};
   1215 
   1216 		const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
   1217 		{
   1218 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
   1219 			DE_NULL,											// const void*										pNext;
   1220 			0u,													// VkPipelineCreateFlags							flags;
   1221 			2u,													// deUint32											stageCount;
   1222 			shaderStageParams,									// const VkPipelineShaderStageCreateInfo*			pStages;
   1223 			&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
   1224 			&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
   1225 			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
   1226 			&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
   1227 			&rasterStateParams,									// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
   1228 			&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
   1229 			&depthStencilStateParams,							// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
   1230 			&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
   1231 			(const VkPipelineDynamicStateCreateInfo*)DE_NULL,	// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
   1232 			*m_pipelineLayout,									// VkPipelineLayout									layout;
   1233 			*m_renderPass,										// VkRenderPass										renderPass;
   1234 			0u,													// deUint32											subpass;
   1235 			0u,													// VkPipeline										basePipelineHandle;
   1236 			0u													// deInt32											basePipelineIndex;
   1237 		};
   1238 
   1239 		m_graphicsPipeline	= createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
   1240 	}
   1241 
   1242 	// Create vertex buffer
   1243 	{
   1244 		// calculate buffer size
   1245 		// 32 is maximal attribute size (4*sizeof(double)),
   1246 		// 8 maximal vertex count used in writeVertexInputData
   1247 		VkDeviceSize bufferSize = 32 * 8 * attributeDescriptions.size();
   1248 
   1249 		const VkBufferCreateInfo vertexBufferParams =
   1250 		{
   1251 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
   1252 			DE_NULL,									// const void*			pNext;
   1253 			0u,											// VkBufferCreateFlags	flags;
   1254 			bufferSize,									// VkDeviceSize			size;
   1255 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
   1256 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
   1257 			1u,											// deUint32				queueFamilyIndexCount;
   1258 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
   1259 		};
   1260 
   1261 		// Upload data for each vertex input binding
   1262 		for (deUint32 bindingNdx = 0; bindingNdx < bindingDescriptions.size(); bindingNdx++)
   1263 		{
   1264 			Move<VkBuffer>			vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
   1265 			de::MovePtr<Allocation>	vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
   1266 
   1267 			VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset()));
   1268 
   1269 			writeVertexInputData((deUint8*)vertexBufferAlloc->getHostPtr(), bindingDescriptions[bindingNdx], bindingOffsets[bindingNdx], attributeDescriptions);
   1270 			flushAlloc(vk, vkDevice, *vertexBufferAlloc);
   1271 
   1272 			m_vertexBuffers.push_back(vertexBuffer.disown());
   1273 			m_vertexBufferAllocs.push_back(vertexBufferAlloc.release());
   1274 		}
   1275 	}
   1276 
   1277 	// Create command pool
   1278 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
   1279 
   1280 	// Create command buffer
   1281 	{
   1282 		const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
   1283 
   1284 		const VkImageMemoryBarrier attachmentLayoutBarrier =
   1285 		{
   1286 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
   1287 			DE_NULL,										// const void*				pNext;
   1288 			0u,												// VkAccessFlags			srcAccessMask;
   1289 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
   1290 			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
   1291 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			newLayout;
   1292 			VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
   1293 			VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
   1294 			*m_colorImage,									// VkImage					image;
   1295 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange	subresourceRange;
   1296 		};
   1297 
   1298 		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
   1299 
   1300 		beginCommandBuffer(vk, *m_cmdBuffer, 0u);
   1301 
   1302 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0,
   1303 			0u, DE_NULL, 0u, DE_NULL, 1u, &attachmentLayoutBarrier);
   1304 
   1305 		beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
   1306 
   1307 		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
   1308 
   1309 		std::vector<VkBuffer> vertexBuffers;
   1310 		for (size_t bufferNdx = 0; bufferNdx < m_vertexBuffers.size(); bufferNdx++)
   1311 			vertexBuffers.push_back(m_vertexBuffers[bufferNdx]);
   1312 
   1313 		if (vertexBuffers.size() <= 1)
   1314 		{
   1315 			// One vertex buffer
   1316 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, (deUint32)vertexBuffers.size(), vertexBuffers.data(), bindingOffsets.data());
   1317 		}
   1318 		else
   1319 		{
   1320 			// Smoke-test vkCmdBindVertexBuffers(..., startBinding, ... )
   1321 
   1322 			const deUint32 firstHalfLength = (deUint32)vertexBuffers.size() / 2;
   1323 			const deUint32 secondHalfLength = firstHalfLength + (deUint32)(vertexBuffers.size() % 2);
   1324 
   1325 			// Bind first half of vertex buffers
   1326 			vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, firstHalfLength, vertexBuffers.data(), bindingOffsets.data());
   1327 
   1328 			// Bind second half of vertex buffers
   1329 			vk.cmdBindVertexBuffers(*m_cmdBuffer, firstHalfLength, secondHalfLength,
   1330 									vertexBuffers.data() + firstHalfLength,
   1331 									bindingOffsets.data() + firstHalfLength);
   1332 		}
   1333 
   1334 		vk.cmdDraw(*m_cmdBuffer, 4, 2, 0, 0);
   1335 
   1336 		endRenderPass(vk, *m_cmdBuffer);
   1337 		endCommandBuffer(vk, *m_cmdBuffer);
   1338 	}
   1339 }
   1340 
   1341 VertexInputInstance::~VertexInputInstance (void)
   1342 {
   1343 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
   1344 	const VkDevice				vkDevice	= m_context.getDevice();
   1345 
   1346 	for (size_t bufferNdx = 0; bufferNdx < m_vertexBuffers.size(); bufferNdx++)
   1347 		vk.destroyBuffer(vkDevice, m_vertexBuffers[bufferNdx], DE_NULL);
   1348 
   1349 	for (size_t allocNdx = 0; allocNdx < m_vertexBufferAllocs.size(); allocNdx++)
   1350 		delete m_vertexBufferAllocs[allocNdx];
   1351 }
   1352 
   1353 void VertexInputInstance::writeVertexInputData(deUint8* destPtr, const VkVertexInputBindingDescription& bindingDescription, const VkDeviceSize bindingOffset, const AttributeDescriptionList& attributes)
   1354 {
   1355 	const deUint32 vertexCount = (bindingDescription.inputRate == VK_VERTEX_INPUT_RATE_VERTEX) ? (4 * 2) : 2;
   1356 
   1357 	deUint8* destOffsetPtr = ((deUint8 *)destPtr) + bindingOffset;
   1358 	for (deUint32 vertexNdx = 0; vertexNdx < vertexCount; vertexNdx++)
   1359 	{
   1360 		for (size_t attributeNdx = 0; attributeNdx < attributes.size(); attributeNdx++)
   1361 		{
   1362 			const VertexInputAttributeDescription& attribDesc = attributes[attributeNdx];
   1363 
   1364 			// Only write vertex input data to bindings referenced by attribute descriptions
   1365 			if (attribDesc.vkDescription.binding == bindingDescription.binding)
   1366 			{
   1367 				writeVertexInputValue(destOffsetPtr + attribDesc.vkDescription.offset, attribDesc, vertexNdx);
   1368 			}
   1369 		}
   1370 		destOffsetPtr += bindingDescription.stride;
   1371 	}
   1372 }
   1373 
   1374 void writeVertexInputValueSint (deUint8* destPtr, VkFormat format, int componentNdx, deInt32 value)
   1375 {
   1376 	const deUint32	componentSize	= getVertexFormatComponentSize(format);
   1377 	deUint8*		destFormatPtr	= ((deUint8*)destPtr) + componentSize * componentNdx;
   1378 
   1379 	switch (componentSize)
   1380 	{
   1381 		case 1:
   1382 			*((deInt8*)destFormatPtr) = (deInt8)value;
   1383 			break;
   1384 
   1385 		case 2:
   1386 			*((deInt16*)destFormatPtr) = (deInt16)value;
   1387 			break;
   1388 
   1389 		case 4:
   1390 			*((deInt32*)destFormatPtr) = (deInt32)value;
   1391 			break;
   1392 
   1393 		default:
   1394 			DE_ASSERT(false);
   1395 	}
   1396 }
   1397 
   1398 void writeVertexInputValueIntPacked(deUint8* destPtr, deUint32& packedFormat, deUint32& componentOffset, VkFormat format, deUint32 componentNdx, deUint32 value)
   1399 {
   1400 	const deUint32	componentWidth	= getPackedVertexFormatComponentWidth(format, componentNdx);
   1401 	const deUint32	componentCount	= getVertexFormatComponentCount(format);
   1402 	const deUint32	usedBits		= ~(deUint32)0 >> ((getVertexFormatSize(format) * 8) - componentWidth);
   1403 
   1404 	componentOffset -= componentWidth;
   1405 	packedFormat |= (((deUint32)value & usedBits) << componentOffset);
   1406 
   1407 	if (componentNdx == componentCount - 1)
   1408 		*((deUint32*)destPtr) = (deUint32)packedFormat;
   1409 }
   1410 
   1411 void writeVertexInputValueUint (deUint8* destPtr, VkFormat format, int componentNdx, deUint32 value)
   1412 {
   1413 	const deUint32	componentSize	= getVertexFormatComponentSize(format);
   1414 	deUint8*		destFormatPtr	= ((deUint8*)destPtr) + componentSize * componentNdx;
   1415 
   1416 	switch (componentSize)
   1417 	{
   1418 		case 1:
   1419 			*((deUint8 *)destFormatPtr) = (deUint8)value;
   1420 			break;
   1421 
   1422 		case 2:
   1423 			*((deUint16 *)destFormatPtr) = (deUint16)value;
   1424 			break;
   1425 
   1426 		case 4:
   1427 			*((deUint32 *)destFormatPtr) = (deUint32)value;
   1428 			break;
   1429 
   1430 		default:
   1431 			DE_ASSERT(false);
   1432 	}
   1433 }
   1434 
   1435 void writeVertexInputValueSfloat (deUint8* destPtr, VkFormat format, int componentNdx, float value)
   1436 {
   1437 	const deUint32	componentSize	= getVertexFormatComponentSize(format);
   1438 	deUint8*		destFormatPtr	= ((deUint8*)destPtr) + componentSize * componentNdx;
   1439 
   1440 	switch (componentSize)
   1441 	{
   1442 		case 2:
   1443 		{
   1444 			deFloat16 f16 = deFloat32To16(value);
   1445 			deMemcpy(destFormatPtr, &f16, sizeof(f16));
   1446 			break;
   1447 		}
   1448 
   1449 		case 4:
   1450 			deMemcpy(destFormatPtr, &value, sizeof(value));
   1451 			break;
   1452 
   1453 		default:
   1454 			DE_ASSERT(false);
   1455 	}
   1456 }
   1457 
   1458 void VertexInputInstance::writeVertexInputValue (deUint8* destPtr, const VertexInputAttributeDescription& attribute, int indexId)
   1459 {
   1460 	const int		vertexInputCount	= VertexInputTest::s_glslTypeDescriptions[attribute.glslType].vertexInputCount;
   1461 	const int		componentCount		= VertexInputTest::s_glslTypeDescriptions[attribute.glslType].vertexInputComponentCount;
   1462 	const deUint32	totalComponentCount	= componentCount * vertexInputCount;
   1463 	const deUint32	vertexInputIndex	= indexId * totalComponentCount + attribute.vertexInputIndex * componentCount;
   1464 	const bool		hasBGROrder			= isVertexFormatComponentOrderBGR(attribute.vkDescription.format);
   1465 	const bool		hasABGROrder		= isVertexFormatComponentOrderABGR(attribute.vkDescription.format);
   1466 	const bool		hasARGBOrder		= isVertexFormatComponentOrderARGB(attribute.vkDescription.format);
   1467 	deUint32		componentOffset		= getVertexFormatSize(attribute.vkDescription.format) * 8;
   1468 	deUint32		packedFormat32		= 0;
   1469 	deUint32		swizzledNdx;
   1470 
   1471 	const deUint32	BGRSwizzle[]		= { 2, 1, 0, 3 };
   1472 	const deUint32	ABGRSwizzle[]		= { 3, 2, 1, 0 };
   1473 	const deUint32	ARGBSwizzle[]		= { 3, 0, 1, 2 };
   1474 
   1475 	for (int componentNdx = 0; componentNdx < componentCount; componentNdx++)
   1476 	{
   1477 		if (hasABGROrder)
   1478 			swizzledNdx = ABGRSwizzle[componentNdx];
   1479 		else if (hasARGBOrder)
   1480 			swizzledNdx = ARGBSwizzle[componentNdx];
   1481 		else if (hasBGROrder)
   1482 			swizzledNdx = BGRSwizzle[componentNdx];
   1483 		else
   1484 			swizzledNdx = componentNdx;
   1485 
   1486 		const deInt32	maxIntValue		= isVertexFormatPacked(attribute.vkDescription.format) ? (1 << (getPackedVertexFormatComponentWidth(attribute.vkDescription.format, componentNdx) - 1)) - 1 : (1 << (getVertexFormatComponentSize(attribute.vkDescription.format) * 8 - 1)) - 1;
   1487 		const deUint32	maxUintValue	= isVertexFormatPacked(attribute.vkDescription.format) ? ((1 << getPackedVertexFormatComponentWidth(attribute.vkDescription.format, componentNdx)) - 1) : (1 << (getVertexFormatComponentSize(attribute.vkDescription.format) * 8 )) - 1;
   1488 		const deInt32	minIntValue		= -maxIntValue;
   1489 		const deUint32	minUintValue	= 0;
   1490 
   1491 		switch (attribute.glslType)
   1492 		{
   1493 			case VertexInputTest::GLSL_TYPE_INT:
   1494 			case VertexInputTest::GLSL_TYPE_IVEC2:
   1495 			case VertexInputTest::GLSL_TYPE_IVEC3:
   1496 			case VertexInputTest::GLSL_TYPE_IVEC4:
   1497 			{
   1498 				if (isVertexFormatPacked(attribute.vkDescription.format))
   1499 					writeVertexInputValueIntPacked(destPtr, packedFormat32, componentOffset, attribute.vkDescription.format, componentNdx, deClamp32(-(deInt32)(vertexInputIndex + swizzledNdx), minIntValue, maxIntValue));
   1500 				else
   1501 					writeVertexInputValueSint(destPtr, attribute.vkDescription.format, componentNdx, -(deInt32)(vertexInputIndex + swizzledNdx));
   1502 
   1503 				break;
   1504 			}
   1505 			case VertexInputTest::GLSL_TYPE_UINT:
   1506 			case VertexInputTest::GLSL_TYPE_UVEC2:
   1507 			case VertexInputTest::GLSL_TYPE_UVEC3:
   1508 			case VertexInputTest::GLSL_TYPE_UVEC4:
   1509 			{
   1510 				if (isVertexFormatPacked(attribute.vkDescription.format))
   1511 					writeVertexInputValueIntPacked(destPtr, packedFormat32, componentOffset, attribute.vkDescription.format, componentNdx, deClamp32(vertexInputIndex + swizzledNdx, minUintValue, maxUintValue));
   1512 				else
   1513 					writeVertexInputValueUint(destPtr, attribute.vkDescription.format, componentNdx, vertexInputIndex + swizzledNdx);
   1514 
   1515 				break;
   1516 			}
   1517 			case VertexInputTest::GLSL_TYPE_FLOAT:
   1518 			case VertexInputTest::GLSL_TYPE_VEC2:
   1519 			case VertexInputTest::GLSL_TYPE_VEC3:
   1520 			case VertexInputTest::GLSL_TYPE_VEC4:
   1521 			case VertexInputTest::GLSL_TYPE_MAT2:
   1522 			case VertexInputTest::GLSL_TYPE_MAT3:
   1523 			case VertexInputTest::GLSL_TYPE_MAT4:
   1524 			{
   1525 				if (isVertexFormatSfloat(attribute.vkDescription.format))
   1526 				{
   1527 					writeVertexInputValueSfloat(destPtr, attribute.vkDescription.format, componentNdx, -(0.01f * (float)(vertexInputIndex + swizzledNdx)));
   1528 				}
   1529 				else if (isVertexFormatSscaled(attribute.vkDescription.format))
   1530 				{
   1531 					if (isVertexFormatPacked(attribute.vkDescription.format))
   1532 						writeVertexInputValueIntPacked(destPtr, packedFormat32, componentOffset, attribute.vkDescription.format, componentNdx, deClamp32(-(deInt32)(vertexInputIndex + swizzledNdx), minIntValue, maxIntValue));
   1533 					else
   1534 						writeVertexInputValueSint(destPtr, attribute.vkDescription.format, componentNdx, -(deInt32)(vertexInputIndex + swizzledNdx));
   1535 				}
   1536 				else if (isVertexFormatUscaled(attribute.vkDescription.format) || isVertexFormatUnorm(attribute.vkDescription.format) || isVertexFormatSRGB(attribute.vkDescription.format))
   1537 				{
   1538 					if (isVertexFormatPacked(attribute.vkDescription.format))
   1539 						writeVertexInputValueIntPacked(destPtr, packedFormat32, componentOffset, attribute.vkDescription.format, componentNdx, deClamp32(vertexInputIndex + swizzledNdx, minUintValue, maxUintValue));
   1540 					else
   1541 						writeVertexInputValueUint(destPtr, attribute.vkDescription.format, componentNdx, vertexInputIndex + swizzledNdx);
   1542 				}
   1543 				else if (isVertexFormatSnorm(attribute.vkDescription.format))
   1544 				{
   1545 					if (isVertexFormatPacked(attribute.vkDescription.format))
   1546 						writeVertexInputValueIntPacked(destPtr, packedFormat32, componentOffset, attribute.vkDescription.format, componentNdx, deClamp32(minIntValue + (vertexInputIndex + swizzledNdx), minIntValue, maxIntValue));
   1547 					else
   1548 						writeVertexInputValueSint(destPtr, attribute.vkDescription.format, componentNdx, minIntValue + (vertexInputIndex + swizzledNdx));
   1549 				}
   1550 				else
   1551 					DE_ASSERT(false);
   1552 				break;
   1553 			}
   1554 			case VertexInputTest::GLSL_TYPE_DOUBLE:
   1555 			case VertexInputTest::GLSL_TYPE_DVEC2:
   1556 			case VertexInputTest::GLSL_TYPE_DVEC3:
   1557 			case VertexInputTest::GLSL_TYPE_DVEC4:
   1558 			case VertexInputTest::GLSL_TYPE_DMAT2:
   1559 			case VertexInputTest::GLSL_TYPE_DMAT3:
   1560 			case VertexInputTest::GLSL_TYPE_DMAT4:
   1561 				*(reinterpret_cast<double *>(destPtr) + componentNdx) = -0.01 * (vertexInputIndex + swizzledNdx);
   1562 
   1563 				break;
   1564 
   1565 			default:
   1566 				DE_ASSERT(false);
   1567 		}
   1568 	}
   1569 }
   1570 
   1571 tcu::TestStatus VertexInputInstance::iterate (void)
   1572 {
   1573 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
   1574 	const VkDevice				vkDevice	= m_context.getDevice();
   1575 	const VkQueue				queue		= m_context.getUniversalQueue();
   1576 
   1577 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
   1578 
   1579 	return verifyImage();
   1580 }
   1581 
   1582 bool VertexInputTest::isCompatibleType (VkFormat format, GlslType glslType)
   1583 {
   1584 	const GlslTypeDescription glslTypeDesc = s_glslTypeDescriptions[glslType];
   1585 
   1586 	if ((deUint32)s_glslTypeDescriptions[glslType].vertexInputComponentCount == getVertexFormatComponentCount(format))
   1587 	{
   1588 		switch (glslTypeDesc.basicType)
   1589 		{
   1590 			case GLSL_BASIC_TYPE_INT:
   1591 				return isVertexFormatSint(format);
   1592 
   1593 			case GLSL_BASIC_TYPE_UINT:
   1594 				return isVertexFormatUint(format);
   1595 
   1596 			case GLSL_BASIC_TYPE_FLOAT:
   1597 				return (isVertexFormatPacked(format) ? (getVertexFormatSize(format) <= 4) : getVertexFormatComponentSize(format) <= 4) && (isVertexFormatSfloat(format) ||
   1598 					isVertexFormatSnorm(format) || isVertexFormatUnorm(format) || isVertexFormatSscaled(format) || isVertexFormatUscaled(format) || isVertexFormatSRGB(format));
   1599 
   1600 			case GLSL_BASIC_TYPE_DOUBLE:
   1601 				return isVertexFormatSfloat(format) && getVertexFormatComponentSize(format) == 8;
   1602 
   1603 			default:
   1604 				DE_ASSERT(false);
   1605 				return false;
   1606 		}
   1607 	}
   1608 	else
   1609 		return false;
   1610 }
   1611 
   1612 tcu::TestStatus VertexInputInstance::verifyImage (void)
   1613 {
   1614 	bool							compareOk			= false;
   1615 	const tcu::TextureFormat		tcuColorFormat		= mapVkFormat(m_colorFormat);
   1616 	tcu::TextureLevel				reference			(tcuColorFormat, m_renderSize.x(), m_renderSize.y());
   1617 	const tcu::PixelBufferAccess	refRedSubregion		(tcu::getSubregion(reference.getAccess(),
   1618 																		   deRoundFloatToInt32((float)m_renderSize.x() * 0.0f),
   1619 																		   deRoundFloatToInt32((float)m_renderSize.y() * 0.0f),
   1620 																		   deRoundFloatToInt32((float)m_renderSize.x() * 0.5f),
   1621 																		   deRoundFloatToInt32((float)m_renderSize.y() * 1.0f)));
   1622 	const tcu::PixelBufferAccess	refBlueSubregion	(tcu::getSubregion(reference.getAccess(),
   1623 																		   deRoundFloatToInt32((float)m_renderSize.x() * 0.5f),
   1624 																		   deRoundFloatToInt32((float)m_renderSize.y() * 0.0f),
   1625 																		   deRoundFloatToInt32((float)m_renderSize.x() * 0.5f),
   1626 																		   deRoundFloatToInt32((float)m_renderSize.y() * 1.0f)));
   1627 
   1628 	// Create reference image
   1629 	tcu::clear(reference.getAccess(), defaultClearColor(tcuColorFormat));
   1630 	tcu::clear(refRedSubregion, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
   1631 	tcu::clear(refBlueSubregion, tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
   1632 
   1633 	// Compare result with reference image
   1634 	{
   1635 		const DeviceInterface&			vk					= m_context.getDeviceInterface();
   1636 		const VkDevice					vkDevice			= m_context.getDevice();
   1637 		const VkQueue					queue				= m_context.getUniversalQueue();
   1638 		const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
   1639 		SimpleAllocator					allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
   1640 		de::MovePtr<tcu::TextureLevel>	result				= readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
   1641 
   1642 		compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
   1643 															  "IntImageCompare",
   1644 															  "Image comparison",
   1645 															  reference.getAccess(),
   1646 															  result->getAccess(),
   1647 															  tcu::UVec4(2, 2, 2, 2),
   1648 															  tcu::IVec3(1, 1, 0),
   1649 															  true,
   1650 															  tcu::COMPARE_LOG_RESULT);
   1651 	}
   1652 
   1653 	if (compareOk)
   1654 		return tcu::TestStatus::pass("Result image matches reference");
   1655 	else
   1656 		return tcu::TestStatus::fail("Image mismatch");
   1657 }
   1658 
   1659 std::string getAttributeInfoCaseName (const VertexInputTest::AttributeInfo& attributeInfo)
   1660 {
   1661 	std::ostringstream	caseName;
   1662 	const std::string	formatName	= getFormatName(attributeInfo.vkType);
   1663 
   1664 	caseName << "as_" << de::toLower(formatName.substr(10)) << "_rate_";
   1665 
   1666 	if (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX)
   1667 		caseName <<  "vertex";
   1668 	else
   1669 		caseName <<  "instance";
   1670 
   1671 	return caseName.str();
   1672 }
   1673 
   1674 std::string getAttributeInfoDescription (const VertexInputTest::AttributeInfo& attributeInfo)
   1675 {
   1676 	std::ostringstream caseDesc;
   1677 
   1678 	caseDesc << std::string(VertexInputTest::s_glslTypeDescriptions[attributeInfo.glslType].name) << " from type " << getFormatName(attributeInfo.vkType) <<  " with ";
   1679 
   1680 	if (attributeInfo.inputRate == VK_VERTEX_INPUT_RATE_VERTEX)
   1681 		caseDesc <<  "vertex input rate ";
   1682 	else
   1683 		caseDesc <<  "instance input rate ";
   1684 
   1685 	return caseDesc.str();
   1686 }
   1687 
   1688 std::string getAttributeInfosDescription (const std::vector<VertexInputTest::AttributeInfo>& attributeInfos)
   1689 {
   1690 	std::ostringstream caseDesc;
   1691 
   1692 	caseDesc << "Uses vertex attributes:\n";
   1693 
   1694 	for (size_t attributeNdx = 0; attributeNdx < attributeInfos.size(); attributeNdx++)
   1695 		caseDesc << "\t- " << getAttributeInfoDescription (attributeInfos[attributeNdx]) << "\n";
   1696 
   1697 	return caseDesc.str();
   1698 }
   1699 
   1700 struct CompatibleFormats
   1701 {
   1702 	VertexInputTest::GlslType	glslType;
   1703 	std::vector<VkFormat>		compatibleVkFormats;
   1704 };
   1705 
   1706 void createSingleAttributeCases (tcu::TestCaseGroup* singleAttributeTests, VertexInputTest::GlslType glslType)
   1707 {
   1708 	const VkFormat vertexFormats[] =
   1709 	{
   1710 		// Required, unpacked
   1711 		VK_FORMAT_R8_UNORM,
   1712 		VK_FORMAT_R8_SNORM,
   1713 		VK_FORMAT_R8_UINT,
   1714 		VK_FORMAT_R8_SINT,
   1715 		VK_FORMAT_R8G8_UNORM,
   1716 		VK_FORMAT_R8G8_SNORM,
   1717 		VK_FORMAT_R8G8_UINT,
   1718 		VK_FORMAT_R8G8_SINT,
   1719 		VK_FORMAT_R8G8B8A8_UNORM,
   1720 		VK_FORMAT_R8G8B8A8_SNORM,
   1721 		VK_FORMAT_R8G8B8A8_UINT,
   1722 		VK_FORMAT_R8G8B8A8_SINT,
   1723 		VK_FORMAT_B8G8R8A8_UNORM,
   1724 		VK_FORMAT_R16_UNORM,
   1725 		VK_FORMAT_R16_SNORM,
   1726 		VK_FORMAT_R16_UINT,
   1727 		VK_FORMAT_R16_SINT,
   1728 		VK_FORMAT_R16_SFLOAT,
   1729 		VK_FORMAT_R16G16_UNORM,
   1730 		VK_FORMAT_R16G16_SNORM,
   1731 		VK_FORMAT_R16G16_UINT,
   1732 		VK_FORMAT_R16G16_SINT,
   1733 		VK_FORMAT_R16G16_SFLOAT,
   1734 		VK_FORMAT_R16G16B16A16_UNORM,
   1735 		VK_FORMAT_R16G16B16A16_SNORM,
   1736 		VK_FORMAT_R16G16B16A16_UINT,
   1737 		VK_FORMAT_R16G16B16A16_SINT,
   1738 		VK_FORMAT_R16G16B16A16_SFLOAT,
   1739 		VK_FORMAT_R32_UINT,
   1740 		VK_FORMAT_R32_SINT,
   1741 		VK_FORMAT_R32_SFLOAT,
   1742 		VK_FORMAT_R32G32_UINT,
   1743 		VK_FORMAT_R32G32_SINT,
   1744 		VK_FORMAT_R32G32_SFLOAT,
   1745 		VK_FORMAT_R32G32B32_UINT,
   1746 		VK_FORMAT_R32G32B32_SINT,
   1747 		VK_FORMAT_R32G32B32_SFLOAT,
   1748 		VK_FORMAT_R32G32B32A32_UINT,
   1749 		VK_FORMAT_R32G32B32A32_SINT,
   1750 		VK_FORMAT_R32G32B32A32_SFLOAT,
   1751 
   1752 		// Scaled formats
   1753 		VK_FORMAT_R8G8_USCALED,
   1754 		VK_FORMAT_R8G8_SSCALED,
   1755 		VK_FORMAT_R16_USCALED,
   1756 		VK_FORMAT_R16_SSCALED,
   1757 		VK_FORMAT_R8G8B8_USCALED,
   1758 		VK_FORMAT_R8G8B8_SSCALED,
   1759 		VK_FORMAT_B8G8R8_USCALED,
   1760 		VK_FORMAT_B8G8R8_SSCALED,
   1761 		VK_FORMAT_R8G8B8A8_USCALED,
   1762 		VK_FORMAT_R8G8B8A8_SSCALED,
   1763 		VK_FORMAT_B8G8R8A8_USCALED,
   1764 		VK_FORMAT_B8G8R8A8_SSCALED,
   1765 		VK_FORMAT_R16G16_USCALED,
   1766 		VK_FORMAT_R16G16_SSCALED,
   1767 		VK_FORMAT_R16G16B16_USCALED,
   1768 		VK_FORMAT_R16G16B16_SSCALED,
   1769 		VK_FORMAT_R16G16B16A16_USCALED,
   1770 		VK_FORMAT_R16G16B16A16_SSCALED,
   1771 
   1772 		// SRGB formats
   1773 		VK_FORMAT_R8_SRGB,
   1774 		VK_FORMAT_R8G8_SRGB,
   1775 		VK_FORMAT_R8G8B8_SRGB,
   1776 		VK_FORMAT_B8G8R8_SRGB,
   1777 		VK_FORMAT_R8G8B8A8_SRGB,
   1778 		VK_FORMAT_B8G8R8A8_SRGB,
   1779 
   1780 		// Double formats
   1781 		VK_FORMAT_R64_SFLOAT,
   1782 		VK_FORMAT_R64G64_SFLOAT,
   1783 		VK_FORMAT_R64G64B64_SFLOAT,
   1784 		VK_FORMAT_R64G64B64A64_SFLOAT,
   1785 
   1786 		// Packed formats
   1787 		VK_FORMAT_A2R10G10B10_USCALED_PACK32,
   1788 		VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
   1789 		VK_FORMAT_A2R10G10B10_UINT_PACK32,
   1790 		VK_FORMAT_A2R10G10B10_SINT_PACK32,
   1791 		VK_FORMAT_A8B8G8R8_UNORM_PACK32,
   1792 		VK_FORMAT_A8B8G8R8_SNORM_PACK32,
   1793 		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
   1794 		VK_FORMAT_A2R10G10B10_SNORM_PACK32,
   1795 		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
   1796 		VK_FORMAT_A2B10G10R10_SNORM_PACK32
   1797 	};
   1798 
   1799 	for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); formatNdx++)
   1800 	{
   1801 		if (VertexInputTest::isCompatibleType(vertexFormats[formatNdx], glslType))
   1802 		{
   1803 			// Create test case for RATE_VERTEX
   1804 			VertexInputTest::AttributeInfo attributeInfo;
   1805 			attributeInfo.vkType = vertexFormats[formatNdx];
   1806 			attributeInfo.glslType = glslType;
   1807 			attributeInfo.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
   1808 
   1809 			singleAttributeTests->addChild(new VertexInputTest(singleAttributeTests->getTestContext(),
   1810 															   getAttributeInfoCaseName(attributeInfo),
   1811 															   getAttributeInfoDescription(attributeInfo),
   1812 															   std::vector<VertexInputTest::AttributeInfo>(1, attributeInfo),
   1813 															   VertexInputTest::BINDING_MAPPING_ONE_TO_ONE,
   1814 															   VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED));
   1815 
   1816 			// Create test case for RATE_INSTANCE
   1817 			attributeInfo.inputRate	= VK_VERTEX_INPUT_RATE_INSTANCE;
   1818 
   1819 			singleAttributeTests->addChild(new VertexInputTest(singleAttributeTests->getTestContext(),
   1820 															   getAttributeInfoCaseName(attributeInfo),
   1821 															   getAttributeInfoDescription(attributeInfo),
   1822 															   std::vector<VertexInputTest::AttributeInfo>(1, attributeInfo),
   1823 															   VertexInputTest::BINDING_MAPPING_ONE_TO_ONE,
   1824 															   VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED));
   1825 		}
   1826 	}
   1827 }
   1828 
   1829 void createSingleAttributeTests (tcu::TestCaseGroup* singleAttributeTests)
   1830 {
   1831 	for (int glslTypeNdx = 0; glslTypeNdx < VertexInputTest::GLSL_TYPE_COUNT; glslTypeNdx++)
   1832 	{
   1833 		VertexInputTest::GlslType glslType = (VertexInputTest::GlslType)glslTypeNdx;
   1834 		addTestGroup(singleAttributeTests, VertexInputTest::s_glslTypeDescriptions[glslType].name, "", createSingleAttributeCases, glslType);
   1835 	}
   1836 }
   1837 
   1838 // Create all unique GlslType combinations recursively
   1839 void createMultipleAttributeCases (deUint32 depth, deUint32 firstNdx, CompatibleFormats* compatibleFormats, de::Random& randomFunc, tcu::TestCaseGroup& testGroup, VertexInputTest::BindingMapping bindingMapping, VertexInputTest::AttributeLayout attributeLayout, VertexInputTest::LayoutSkip layoutSkip, VertexInputTest::LayoutOrder layoutOrder, const std::vector<VertexInputTest::AttributeInfo>& attributeInfos = std::vector<VertexInputTest::AttributeInfo>(0))
   1840 {
   1841 	tcu::TestContext& testCtx = testGroup.getTestContext();
   1842 
   1843 	// Exclude double values, which are not included in vertexFormats
   1844 	for (deUint32 currentNdx = firstNdx; currentNdx < VertexInputTest::GLSL_TYPE_DOUBLE - depth; currentNdx++)
   1845 	{
   1846 		std::vector <VertexInputTest::AttributeInfo> newAttributeInfos = attributeInfos;
   1847 
   1848 		{
   1849 			VertexInputTest::AttributeInfo attributeInfo;
   1850 			attributeInfo.glslType	= (VertexInputTest::GlslType)currentNdx;
   1851 			attributeInfo.inputRate	= (depth % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
   1852 			attributeInfo.vkType	= VK_FORMAT_UNDEFINED;
   1853 
   1854 			newAttributeInfos.push_back(attributeInfo);
   1855 		}
   1856 
   1857 		// Add test case
   1858 		if (depth == 0)
   1859 		{
   1860 			// Select a random compatible format for each attribute
   1861 			for (size_t i = 0; i < newAttributeInfos.size(); i++)
   1862 			{
   1863 				const std::vector<VkFormat>& formats = compatibleFormats[newAttributeInfos[i].glslType].compatibleVkFormats;
   1864 				newAttributeInfos[i].vkType = formats[randomFunc.getUint32() % formats.size()];
   1865 			}
   1866 
   1867 			const std::string caseName = VertexInputTest::s_glslTypeDescriptions[currentNdx].name;
   1868 			const std::string caseDesc = getAttributeInfosDescription(newAttributeInfos);
   1869 
   1870 			testGroup.addChild(new VertexInputTest(testCtx, caseName, caseDesc, newAttributeInfos, bindingMapping, attributeLayout, layoutSkip, layoutOrder));
   1871 		}
   1872 		// Add test group
   1873 		else
   1874 		{
   1875 			const std::string				name			= VertexInputTest::s_glslTypeDescriptions[currentNdx].name;
   1876 			de::MovePtr<tcu::TestCaseGroup>	newTestGroup	(new tcu::TestCaseGroup(testCtx, name.c_str(), ""));
   1877 
   1878 			createMultipleAttributeCases(depth - 1u, currentNdx + 1u, compatibleFormats, randomFunc, *newTestGroup, bindingMapping, attributeLayout, layoutSkip, layoutOrder, newAttributeInfos);
   1879 			testGroup.addChild(newTestGroup.release());
   1880 		}
   1881 	}
   1882 }
   1883 
   1884 void createMultipleAttributeTests (tcu::TestCaseGroup* multipleAttributeTests)
   1885 {
   1886 	// Required vertex formats, unpacked
   1887 	const VkFormat vertexFormats[] =
   1888 	{
   1889 		VK_FORMAT_R8_UNORM,
   1890 		VK_FORMAT_R8_SNORM,
   1891 		VK_FORMAT_R8_UINT,
   1892 		VK_FORMAT_R8_SINT,
   1893 		VK_FORMAT_R8G8_UNORM,
   1894 		VK_FORMAT_R8G8_SNORM,
   1895 		VK_FORMAT_R8G8_UINT,
   1896 		VK_FORMAT_R8G8_SINT,
   1897 		VK_FORMAT_R8G8B8A8_UNORM,
   1898 		VK_FORMAT_R8G8B8A8_SNORM,
   1899 		VK_FORMAT_R8G8B8A8_UINT,
   1900 		VK_FORMAT_R8G8B8A8_SINT,
   1901 		VK_FORMAT_B8G8R8A8_UNORM,
   1902 		VK_FORMAT_R16_UNORM,
   1903 		VK_FORMAT_R16_SNORM,
   1904 		VK_FORMAT_R16_UINT,
   1905 		VK_FORMAT_R16_SINT,
   1906 		VK_FORMAT_R16_SFLOAT,
   1907 		VK_FORMAT_R16G16_UNORM,
   1908 		VK_FORMAT_R16G16_SNORM,
   1909 		VK_FORMAT_R16G16_UINT,
   1910 		VK_FORMAT_R16G16_SINT,
   1911 		VK_FORMAT_R16G16_SFLOAT,
   1912 		VK_FORMAT_R16G16B16A16_UNORM,
   1913 		VK_FORMAT_R16G16B16A16_SNORM,
   1914 		VK_FORMAT_R16G16B16A16_UINT,
   1915 		VK_FORMAT_R16G16B16A16_SINT,
   1916 		VK_FORMAT_R16G16B16A16_SFLOAT,
   1917 		VK_FORMAT_R32_UINT,
   1918 		VK_FORMAT_R32_SINT,
   1919 		VK_FORMAT_R32_SFLOAT,
   1920 		VK_FORMAT_R32G32_UINT,
   1921 		VK_FORMAT_R32G32_SINT,
   1922 		VK_FORMAT_R32G32_SFLOAT,
   1923 		VK_FORMAT_R32G32B32_UINT,
   1924 		VK_FORMAT_R32G32B32_SINT,
   1925 		VK_FORMAT_R32G32B32_SFLOAT,
   1926 		VK_FORMAT_R32G32B32A32_UINT,
   1927 		VK_FORMAT_R32G32B32A32_SINT,
   1928 		VK_FORMAT_R32G32B32A32_SFLOAT
   1929 	};
   1930 
   1931 	const VertexInputTest::LayoutSkip layoutSkips[] =
   1932 	{
   1933 		VertexInputTest::LAYOUT_SKIP_DISABLED,
   1934 		VertexInputTest::LAYOUT_SKIP_ENABLED
   1935 	};
   1936 
   1937 	const VertexInputTest::LayoutOrder layoutOrders[] =
   1938 	{
   1939 		VertexInputTest::LAYOUT_ORDER_IN_ORDER,
   1940 		VertexInputTest::LAYOUT_ORDER_OUT_OF_ORDER
   1941 	};
   1942 
   1943 	// Find compatible VK formats for each GLSL vertex type
   1944 	CompatibleFormats compatibleFormats[VertexInputTest::GLSL_TYPE_COUNT];
   1945 	{
   1946 		for (int glslTypeNdx = 0; glslTypeNdx < VertexInputTest::GLSL_TYPE_COUNT; glslTypeNdx++)
   1947 		{
   1948 			for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); formatNdx++)
   1949 			{
   1950 				if (VertexInputTest::isCompatibleType(vertexFormats[formatNdx], (VertexInputTest::GlslType)glslTypeNdx))
   1951 					compatibleFormats[glslTypeNdx].compatibleVkFormats.push_back(vertexFormats[formatNdx]);
   1952 			}
   1953 		}
   1954 	}
   1955 
   1956 	de::Random                      randomFunc(102030);
   1957 	tcu::TestContext&				testCtx = multipleAttributeTests->getTestContext();
   1958 
   1959 	for (deUint32 layoutSkipNdx = 0; layoutSkipNdx < DE_LENGTH_OF_ARRAY(layoutSkips); layoutSkipNdx++)
   1960 	for (deUint32 layoutOrderNdx = 0; layoutOrderNdx < DE_LENGTH_OF_ARRAY(layoutOrders); layoutOrderNdx++)
   1961 	{
   1962 		const VertexInputTest::LayoutSkip	layoutSkip	= layoutSkips[layoutSkipNdx];
   1963 		const VertexInputTest::LayoutOrder	layoutOrder	= layoutOrders[layoutOrderNdx];
   1964 		de::MovePtr<tcu::TestCaseGroup> oneToOneAttributeTests(new tcu::TestCaseGroup(testCtx, "attributes", ""));
   1965 		de::MovePtr<tcu::TestCaseGroup> oneToManyAttributeTests(new tcu::TestCaseGroup(testCtx, "attributes", ""));
   1966 		de::MovePtr<tcu::TestCaseGroup> oneToManySequentialAttributeTests(new tcu::TestCaseGroup(testCtx, "attributes_sequential", ""));
   1967 
   1968 		if (layoutSkip == VertexInputTest::LAYOUT_SKIP_ENABLED && layoutOrder == VertexInputTest::LAYOUT_ORDER_OUT_OF_ORDER)
   1969 			continue;
   1970 
   1971 		createMultipleAttributeCases(2u, 0u, compatibleFormats, randomFunc, *oneToOneAttributeTests,			VertexInputTest::BINDING_MAPPING_ONE_TO_ONE,	VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED, layoutSkip, layoutOrder);
   1972 		createMultipleAttributeCases(2u, 0u, compatibleFormats, randomFunc, *oneToManyAttributeTests,			VertexInputTest::BINDING_MAPPING_ONE_TO_MANY,	VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED, layoutSkip, layoutOrder);
   1973 		createMultipleAttributeCases(2u, 0u, compatibleFormats, randomFunc, *oneToManySequentialAttributeTests,	VertexInputTest::BINDING_MAPPING_ONE_TO_MANY,	VertexInputTest::ATTRIBUTE_LAYOUT_SEQUENTIAL, layoutSkip, layoutOrder);
   1974 
   1975 		if (layoutSkip == VertexInputTest::LAYOUT_SKIP_ENABLED)
   1976 		{
   1977 			de::MovePtr<tcu::TestCaseGroup> layoutSkipTests(new tcu::TestCaseGroup(testCtx, "layout_skip", "Skip one layout after each attribute"));
   1978 
   1979 			de::MovePtr<tcu::TestCaseGroup> bindingOneToOneTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_one", "Each attribute uses a unique binding"));
   1980 			bindingOneToOneTests->addChild(oneToOneAttributeTests.release());
   1981 			layoutSkipTests->addChild(bindingOneToOneTests.release());
   1982 
   1983 			de::MovePtr<tcu::TestCaseGroup> bindingOneToManyTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_many", "Attributes share the same binding"));
   1984 			bindingOneToManyTests->addChild(oneToManyAttributeTests.release());
   1985 			bindingOneToManyTests->addChild(oneToManySequentialAttributeTests.release());
   1986 			layoutSkipTests->addChild(bindingOneToManyTests.release());
   1987 			multipleAttributeTests->addChild(layoutSkipTests.release());
   1988 		}
   1989 		else if (layoutOrder == VertexInputTest::LAYOUT_ORDER_OUT_OF_ORDER)
   1990 		{
   1991 			de::MovePtr<tcu::TestCaseGroup> layoutOutOfOrderTests(new tcu::TestCaseGroup(testCtx, "out_of_order", "Layout slots out of order"));
   1992 
   1993 			de::MovePtr<tcu::TestCaseGroup> bindingOneToOneTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_one", "Each attribute uses a unique binding"));
   1994 			bindingOneToOneTests->addChild(oneToOneAttributeTests.release());
   1995 			layoutOutOfOrderTests->addChild(bindingOneToOneTests.release());
   1996 
   1997 			de::MovePtr<tcu::TestCaseGroup> bindingOneToManyTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_many", "Attributes share the same binding"));
   1998 			bindingOneToManyTests->addChild(oneToManyAttributeTests.release());
   1999 			bindingOneToManyTests->addChild(oneToManySequentialAttributeTests.release());
   2000 			layoutOutOfOrderTests->addChild(bindingOneToManyTests.release());
   2001 			multipleAttributeTests->addChild(layoutOutOfOrderTests.release());
   2002 		}
   2003 		else
   2004 		{
   2005 			de::MovePtr<tcu::TestCaseGroup> bindingOneToOneTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_one", "Each attribute uses a unique binding"));
   2006 			bindingOneToOneTests->addChild(oneToOneAttributeTests.release());
   2007 			multipleAttributeTests->addChild(bindingOneToOneTests.release());
   2008 
   2009 			de::MovePtr<tcu::TestCaseGroup> bindingOneToManyTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_many", "Attributes share the same binding"));
   2010 			bindingOneToManyTests->addChild(oneToManyAttributeTests.release());
   2011 			bindingOneToManyTests->addChild(oneToManySequentialAttributeTests.release());
   2012 			multipleAttributeTests->addChild(bindingOneToManyTests.release());
   2013 		}
   2014 	}
   2015 }
   2016 
   2017 void createMaxAttributeTests (tcu::TestCaseGroup* maxAttributeTests)
   2018 {
   2019 	// Required vertex formats, unpacked
   2020 	const VkFormat					vertexFormats[]		=
   2021 	{
   2022 		VK_FORMAT_R8_UNORM,
   2023 		VK_FORMAT_R8_SNORM,
   2024 		VK_FORMAT_R8_UINT,
   2025 		VK_FORMAT_R8_SINT,
   2026 		VK_FORMAT_R8G8_UNORM,
   2027 		VK_FORMAT_R8G8_SNORM,
   2028 		VK_FORMAT_R8G8_UINT,
   2029 		VK_FORMAT_R8G8_SINT,
   2030 		VK_FORMAT_R8G8B8A8_UNORM,
   2031 		VK_FORMAT_R8G8B8A8_SNORM,
   2032 		VK_FORMAT_R8G8B8A8_UINT,
   2033 		VK_FORMAT_R8G8B8A8_SINT,
   2034 		VK_FORMAT_B8G8R8A8_UNORM,
   2035 		VK_FORMAT_R16_UNORM,
   2036 		VK_FORMAT_R16_SNORM,
   2037 		VK_FORMAT_R16_UINT,
   2038 		VK_FORMAT_R16_SINT,
   2039 		VK_FORMAT_R16_SFLOAT,
   2040 		VK_FORMAT_R16G16_UNORM,
   2041 		VK_FORMAT_R16G16_SNORM,
   2042 		VK_FORMAT_R16G16_UINT,
   2043 		VK_FORMAT_R16G16_SINT,
   2044 		VK_FORMAT_R16G16_SFLOAT,
   2045 		VK_FORMAT_R16G16B16A16_UNORM,
   2046 		VK_FORMAT_R16G16B16A16_SNORM,
   2047 		VK_FORMAT_R16G16B16A16_UINT,
   2048 		VK_FORMAT_R16G16B16A16_SINT,
   2049 		VK_FORMAT_R16G16B16A16_SFLOAT,
   2050 		VK_FORMAT_R32_UINT,
   2051 		VK_FORMAT_R32_SINT,
   2052 		VK_FORMAT_R32_SFLOAT,
   2053 		VK_FORMAT_R32G32_UINT,
   2054 		VK_FORMAT_R32G32_SINT,
   2055 		VK_FORMAT_R32G32_SFLOAT,
   2056 		VK_FORMAT_R32G32B32_UINT,
   2057 		VK_FORMAT_R32G32B32_SINT,
   2058 		VK_FORMAT_R32G32B32_SFLOAT,
   2059 		VK_FORMAT_R32G32B32A32_UINT,
   2060 		VK_FORMAT_R32G32B32A32_SINT,
   2061 		VK_FORMAT_R32G32B32A32_SFLOAT
   2062 	};
   2063 
   2064 	// VkPhysicalDeviceLimits::maxVertexInputAttributes is used when attributeCount is 0
   2065 	const deUint32					attributeCount[]	= { 16, 32, 64, 128, 0 };
   2066 	tcu::TestContext&				testCtx				(maxAttributeTests->getTestContext());
   2067 	de::Random						randomFunc			(132030);
   2068 
   2069 	// Find compatible VK formats for each GLSL vertex type
   2070 	CompatibleFormats compatibleFormats[VertexInputTest::GLSL_TYPE_COUNT];
   2071 	{
   2072 		for (int glslTypeNdx = 0; glslTypeNdx < VertexInputTest::GLSL_TYPE_COUNT; glslTypeNdx++)
   2073 		{
   2074 			for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(vertexFormats); formatNdx++)
   2075 			{
   2076 				if (VertexInputTest::isCompatibleType(vertexFormats[formatNdx], (VertexInputTest::GlslType)glslTypeNdx))
   2077 					compatibleFormats[glslTypeNdx].compatibleVkFormats.push_back(vertexFormats[formatNdx]);
   2078 			}
   2079 		}
   2080 	}
   2081 
   2082 	for (deUint32 attributeCountNdx = 0; attributeCountNdx < DE_LENGTH_OF_ARRAY(attributeCount); attributeCountNdx++)
   2083 	{
   2084 		const std::string							groupName = (attributeCount[attributeCountNdx] == 0 ? "query_max" : de::toString(attributeCount[attributeCountNdx])) + "_attributes";
   2085 		const std::string							groupDesc = de::toString(attributeCount[attributeCountNdx]) + " vertex input attributes";
   2086 
   2087 		de::MovePtr<tcu::TestCaseGroup>				numAttributeTests(new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDesc.c_str()));
   2088 		de::MovePtr<tcu::TestCaseGroup>				bindingOneToOneTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_one", "Each attribute uses a unique binding"));
   2089 		de::MovePtr<tcu::TestCaseGroup>				bindingOneToManyTests(new tcu::TestCaseGroup(testCtx, "binding_one_to_many", "Attributes share the same binding"));
   2090 
   2091 		std::vector<VertexInputTest::AttributeInfo>	attributeInfos(attributeCount[attributeCountNdx]);
   2092 
   2093 		for (deUint32 attributeNdx = 0; attributeNdx < attributeCount[attributeCountNdx]; attributeNdx++)
   2094 		{
   2095 			// Use random glslTypes, each consuming one attribute location
   2096 			const VertexInputTest::GlslType	glslType	= (VertexInputTest::GlslType)(randomFunc.getUint32() % VertexInputTest::GLSL_TYPE_MAT2);
   2097 			const std::vector<VkFormat>&	formats		= compatibleFormats[glslType].compatibleVkFormats;
   2098 			const VkFormat					format		= formats[randomFunc.getUint32() % formats.size()];
   2099 
   2100 			attributeInfos[attributeNdx].glslType		= glslType;
   2101 			attributeInfos[attributeNdx].inputRate		= ((attributeCountNdx + attributeNdx) % 2 == 0) ? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE;
   2102 			attributeInfos[attributeNdx].vkType			= format;
   2103 		}
   2104 
   2105 		bindingOneToOneTests->addChild(new VertexInputTest(testCtx, "interleaved", "Interleaved attribute layout", attributeInfos, VertexInputTest::BINDING_MAPPING_ONE_TO_ONE, VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED));
   2106 		bindingOneToManyTests->addChild(new VertexInputTest(testCtx, "interleaved", "Interleaved attribute layout", attributeInfos, VertexInputTest::BINDING_MAPPING_ONE_TO_MANY, VertexInputTest::ATTRIBUTE_LAYOUT_INTERLEAVED));
   2107 		bindingOneToManyTests->addChild(new VertexInputTest(testCtx, "sequential", "Sequential attribute layout", attributeInfos, VertexInputTest::BINDING_MAPPING_ONE_TO_MANY, VertexInputTest::ATTRIBUTE_LAYOUT_SEQUENTIAL));
   2108 
   2109 		numAttributeTests->addChild(bindingOneToOneTests.release());
   2110 		numAttributeTests->addChild(bindingOneToManyTests.release());
   2111 		maxAttributeTests->addChild(numAttributeTests.release());
   2112 	}
   2113 }
   2114 
   2115 } // anonymous
   2116 
   2117 void createVertexInputTests (tcu::TestCaseGroup* vertexInputTests)
   2118 {
   2119 	addTestGroup(vertexInputTests, "single_attribute", "Uses one attribute", createSingleAttributeTests);
   2120 	addTestGroup(vertexInputTests, "multiple_attributes", "Uses more than one attribute", createMultipleAttributeTests);
   2121 	addTestGroup(vertexInputTests, "max_attributes", "Implementations can use as many vertex input attributes as they advertise", createMaxAttributeTests);
   2122 }
   2123 
   2124 } // pipeline
   2125 } // vkt
   2126