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