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