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