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