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