• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 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 Robust Vertex Buffer Access Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktRobustnessVertexAccessTests.hpp"
26 #include "vktRobustnessUtil.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vkBuilderUtil.hpp"
29 #include "vkImageUtil.hpp"
30 #include "vkMemUtil.hpp"
31 #include "vkPrograms.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkRef.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "tcuTestLog.hpp"
37 #include "deMath.h"
38 #include "deUniquePtr.hpp"
39 #include <vector>
40 
41 namespace vkt
42 {
43 namespace robustness
44 {
45 
46 using namespace vk;
47 
48 typedef std::vector<VkVertexInputBindingDescription>	BindingList;
49 typedef std::vector<VkVertexInputAttributeDescription>	AttributeList;
50 
51 class VertexAccessTest : public vkt::TestCase
52 {
53 public:
54 						VertexAccessTest	(tcu::TestContext&		testContext,
55 											 const std::string&		name,
56 											 const std::string&		description,
57 											 VkFormat				inputFormat,
58 											 deUint32				numVertexValues,
59 											 deUint32				numInstanceValues,
60 											 deUint32				numVertices,
61 											 deUint32				numInstances);
62 
~VertexAccessTest(void)63 	virtual				~VertexAccessTest	(void) {}
64 
65 	void				initPrograms		(SourceCollections& programCollection) const;
66 	TestInstance*		createInstance		(Context& context) const = 0;
67 
68 protected:
69 	const VkFormat		m_inputFormat;
70 	const deUint32		m_numVertexValues;
71 	const deUint32		m_numInstanceValues;
72 	const deUint32		m_numVertices;
73 	const deUint32		m_numInstances;
74 
75 };
76 
77 class DrawAccessTest : public VertexAccessTest
78 {
79 public:
80 						DrawAccessTest		(tcu::TestContext&		testContext,
81 											 const std::string&		name,
82 											 const std::string&		description,
83 											 VkFormat				inputFormat,
84 											 deUint32				numVertexValues,
85 											 deUint32				numInstanceValues,
86 											 deUint32				numVertices,
87 											 deUint32				numInstances);
88 
~DrawAccessTest(void)89 	virtual				~DrawAccessTest		(void) {}
90 	TestInstance*		createInstance		(Context& context) const;
91 
92 protected:
93 };
94 
95 class DrawIndexedAccessTest : public VertexAccessTest
96 {
97 public:
98 	enum IndexConfig
99 	{
100 		INDEX_CONFIG_LAST_INDEX_OUT_OF_BOUNDS,
101 		INDEX_CONFIG_INDICES_OUT_OF_BOUNDS,
102 		INDEX_CONFIG_TRIANGLE_OUT_OF_BOUNDS,
103 
104 		INDEX_CONFIG_COUNT
105 	};
106 
107 	const static std::vector<deUint32> s_indexConfigs[INDEX_CONFIG_COUNT];
108 
109 						DrawIndexedAccessTest		(tcu::TestContext&		testContext,
110 													 const std::string&		name,
111 													 const std::string&		description,
112 													 VkFormat				inputFormat,
113 													 IndexConfig			indexConfig);
114 
~DrawIndexedAccessTest(void)115 	virtual				~DrawIndexedAccessTest		(void) {}
116 	TestInstance*		createInstance				(Context& context) const;
117 
118 protected:
119 	const IndexConfig	m_indexConfig;
120 };
121 
122 class VertexAccessInstance : public vkt::TestInstance
123 {
124 public:
125 										VertexAccessInstance					(Context&						context,
126 																				 Move<VkDevice>					device,
127 																				 VkFormat						inputFormat,
128 																				 deUint32						numVertexValues,
129 																				 deUint32						numInstanceValues,
130 																				 deUint32						numVertices,
131 																				 deUint32						numInstances,
132 																				 const std::vector<deUint32>&	indices);
133 
~VertexAccessInstance(void)134 	virtual								~VertexAccessInstance					(void) {}
135 	virtual tcu::TestStatus				iterate									(void);
136 	virtual bool						verifyResult							(void);
137 
138 private:
139 	bool								isValueWithinVertexBufferOrZero			(void* vertexBuffer, VkDeviceSize vertexBufferSize, const void* value, deUint32 valueIndexa);
140 
141 protected:
142 	static bool							isExpectedValueFromVertexBuffer			(const void* vertexBuffer, deUint32 vertexIndex, VkFormat vertexFormat, const void* value);
143 	static VkDeviceSize					getBufferSizeInBytes					(deUint32 numScalars, VkFormat format);
144 
145 	virtual void						initVertexIds							(deUint32 *indicesPtr, size_t indexCount) = 0;
146 	virtual deUint32					getIndex								(deUint32 vertexNum) const = 0;
147 
148 	Move<VkDevice>						m_device;
149 
150 	const VkFormat						m_inputFormat;
151 	const deUint32						m_numVertexValues;
152 	const deUint32						m_numInstanceValues;
153 	const deUint32						m_numVertices;
154 	const deUint32						m_numInstances;
155 	AttributeList						m_vertexInputAttributes;
156 	BindingList							m_vertexInputBindings;
157 
158 	Move<VkBuffer>						m_vertexRateBuffer;
159 	VkDeviceSize						m_vertexRateBufferSize;
160 	de::MovePtr<Allocation>				m_vertexRateBufferAlloc;
161 	VkDeviceSize						m_vertexRateBufferAllocSize;
162 
163 	Move<VkBuffer>						m_instanceRateBuffer;
164 	VkDeviceSize						m_instanceRateBufferSize;
165 	de::MovePtr<Allocation>				m_instanceRateBufferAlloc;
166 	VkDeviceSize						m_instanceRateBufferAllocSize;
167 
168 	Move<VkBuffer>						m_vertexNumBuffer;
169 	VkDeviceSize						m_vertexNumBufferSize;
170 	de::MovePtr<Allocation>				m_vertexNumBufferAlloc;
171 
172 	Move<VkBuffer>						m_indexBuffer;
173 	VkDeviceSize						m_indexBufferSize;
174 	de::MovePtr<Allocation>				m_indexBufferAlloc;
175 
176 	Move<VkBuffer>						m_outBuffer; // SSBO
177 	VkDeviceSize						m_outBufferSize;
178 	de::MovePtr<Allocation>				m_outBufferAlloc;
179 
180 	Move<VkDescriptorPool>				m_descriptorPool;
181 	Move<VkDescriptorSetLayout>			m_descriptorSetLayout;
182 	Move<VkDescriptorSet>				m_descriptorSet;
183 
184 	Move<VkFence>						m_fence;
185 	VkQueue								m_queue;
186 
187 	de::MovePtr<GraphicsEnvironment>	m_graphicsTestEnvironment;
188 };
189 
190 class DrawAccessInstance : public VertexAccessInstance
191 {
192 public:
193 						DrawAccessInstance	(Context&				context,
194 											 Move<VkDevice>			device,
195 											 VkFormat				inputFormat,
196 											 deUint32				numVertexValues,
197 											 deUint32				numInstanceValues,
198 											 deUint32				numVertices,
199 											 deUint32				numInstances);
200 
~DrawAccessInstance(void)201 	virtual				~DrawAccessInstance	(void) {}
202 
203 protected:
204 	virtual void		initVertexIds		(deUint32 *indicesPtr, size_t indexCount);
205 	virtual deUint32	getIndex			(deUint32 vertexNum) const;
206 };
207 
208 class DrawIndexedAccessInstance : public VertexAccessInstance
209 {
210 public:
211 										DrawIndexedAccessInstance	(Context&						context,
212 																	 Move<VkDevice>					device,
213 																	 VkFormat						inputFormat,
214 																	 deUint32						numVertexValues,
215 																	 deUint32						numInstanceValues,
216 																	 deUint32						numVertices,
217 																	 deUint32						numInstances,
218 																	 const std::vector<deUint32>&	indices);
219 
~DrawIndexedAccessInstance(void)220 	virtual								~DrawIndexedAccessInstance	(void) {}
221 
222 protected:
223 	virtual void						initVertexIds				(deUint32 *indicesPtr, size_t indexCount);
224 	virtual deUint32					getIndex					(deUint32 vertexNum) const;
225 
226 	const std::vector<deUint32>			m_indices;
227 };
228 
229 // VertexAccessTest
230 
VertexAccessTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkFormat inputFormat,deUint32 numVertexValues,deUint32 numInstanceValues,deUint32 numVertices,deUint32 numInstances)231 VertexAccessTest::VertexAccessTest (tcu::TestContext&		testContext,
232 									const std::string&		name,
233 									const std::string&		description,
234 									VkFormat				inputFormat,
235 									deUint32				numVertexValues,
236 									deUint32				numInstanceValues,
237 									deUint32				numVertices,
238 									deUint32				numInstances)
239 
240 	: vkt::TestCase				(testContext, name, description)
241 	, m_inputFormat				(inputFormat)
242 	, m_numVertexValues			(numVertexValues)
243 	, m_numInstanceValues		(numInstanceValues)
244 	, m_numVertices				(numVertices)
245 	, m_numInstances			(numInstances)
246 {
247 }
248 
initPrograms(SourceCollections & programCollection) const249 void VertexAccessTest::initPrograms (SourceCollections& programCollection) const
250 {
251 	std::ostringstream		attributeDeclaration;
252 	std::ostringstream		attributeUse;
253 
254 	std::ostringstream		vertexShaderSource;
255 	std::ostringstream		fragmentShaderSource;
256 
257 	std::ostringstream		attributeTypeStr;
258 	const int				numChannels				= getNumUsedChannels(mapVkFormat(m_inputFormat).order);
259 	const deUint32			numScalarsPerVertex		= numChannels * 3; // Use 3 identical attributes
260 	deUint32				numValues				= 0;
261 
262 	const bool				isR64					= (m_inputFormat == VK_FORMAT_R64_UINT || m_inputFormat == VK_FORMAT_R64_SINT);
263 
264 	if (numChannels == 1)
265 	{
266 		if (isUintFormat(m_inputFormat))
267 			attributeTypeStr << "uint";
268 		else if (isIntFormat(m_inputFormat))
269 			attributeTypeStr << "int";
270 		else
271 			attributeTypeStr << "float";
272 
273 		attributeTypeStr << (isR64 ? "64_t" : " ");
274 	}
275 	else
276 	{
277 		if (isUintFormat(m_inputFormat))
278 			attributeTypeStr << "uvec";
279 		else if (isIntFormat(m_inputFormat))
280 			attributeTypeStr << "ivec";
281 		else
282 			attributeTypeStr << "vec";
283 
284 		attributeTypeStr << numChannels;
285 	}
286 
287 	for (int attrNdx = 0; attrNdx < 3; attrNdx++)
288 	{
289 		attributeDeclaration << "layout(location = " << attrNdx << ") in " << attributeTypeStr.str() << " attr" << attrNdx << ";\n";
290 
291 		for (int chanNdx = 0; chanNdx < numChannels; chanNdx++)
292 		{
293 			attributeUse << "\toutData[(gl_InstanceIndex * " << numScalarsPerVertex * m_numVertices
294 						 << ") + (vertexNum * " << numScalarsPerVertex << " + " << numValues++ << ")] = attr" << attrNdx;
295 
296 			if (numChannels == 1)
297 				attributeUse << ";\n";
298 			else
299 				attributeUse << "[" << chanNdx << "];\n";
300 		}
301 	}
302 
303 	attributeDeclaration << "layout(location = 3) in int vertexNum;\n";
304 
305 	attributeUse << "\n";
306 
307 	std::string outType = "";
308 	if (isUintFormat(m_inputFormat))
309 		outType = "uint";
310 	else if (isIntFormat(m_inputFormat))
311 		outType = "int";
312 	else
313 		outType = "float";
314 
315 	outType += isR64 ? "64_t" : "";
316 
317 	std::string extensions	= "";
318 	std::string version		= "#version 310 es\n";
319 	if (isR64)
320 	{
321 		extensions	= "#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require\n";
322 		version		= "#version 440\n";
323 	}
324 
325 	vertexShaderSource <<
326 		version <<
327 		"precision highp float;\n"
328 		<< extensions
329 		<< attributeDeclaration.str() <<
330 		"layout(set = 0, binding = 0, std430) buffer outBuffer\n"
331 		"{\n"
332 		"\t" << outType << " outData[" << (m_numVertices * numValues) * m_numInstances << "];\n"
333 		"};\n\n"
334 		"void main (void)\n"
335 		"{\n"
336 		<< attributeUse.str() <<
337 		"\tgl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
338 		"}\n";
339 
340 	programCollection.glslSources.add("vertex") << glu::VertexSource(vertexShaderSource.str());
341 
342 	fragmentShaderSource <<
343 		"#version 310 es\n"
344 		"precision highp float;\n"
345 		"layout(location = 0) out vec4 fragColor;\n"
346 		"void main (void)\n"
347 		"{\n"
348 		"\tfragColor = vec4(1.0);\n"
349 		"}\n";
350 
351 	programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentShaderSource.str());
352 }
353 
354 // DrawAccessTest
355 
DrawAccessTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkFormat inputFormat,deUint32 numVertexValues,deUint32 numInstanceValues,deUint32 numVertices,deUint32 numInstances)356 DrawAccessTest::DrawAccessTest (tcu::TestContext&		testContext,
357 								const std::string&		name,
358 								const std::string&		description,
359 								VkFormat				inputFormat,
360 								deUint32				numVertexValues,
361 								deUint32				numInstanceValues,
362 								deUint32				numVertices,
363 								deUint32				numInstances)
364 
365 	: VertexAccessTest		(testContext, name, description, inputFormat, numVertexValues, numInstanceValues, numVertices, numInstances)
366 {
367 }
368 
createInstance(Context & context) const369 TestInstance* DrawAccessTest::createInstance (Context& context) const
370 {
371 	Move<VkDevice> device = createRobustBufferAccessDevice(context);
372 
373 	return new DrawAccessInstance(context,
374 								  device,
375 								  m_inputFormat,
376 								  m_numVertexValues,
377 								  m_numInstanceValues,
378 								  m_numVertices,
379 								  m_numInstances);
380 }
381 
382 // DrawIndexedAccessTest
383 
384 const deUint32 lastIndexOutOfBounds[] =
385 {
386 	0, 1, 2, 3, 4, 100,		// Indices of 100 and above are out of bounds
387 };
388 const deUint32 indicesOutOfBounds[] =
389 {
390 	0, 100, 2, 101, 3, 102,	// Indices of 100 and above are out of bounds
391 };
392 const deUint32 triangleOutOfBounds[] =
393 {
394 	100, 101, 102, 3, 4, 5,	// Indices of 100 and above are out of bounds
395 };
396 
397 const std::vector<deUint32> DrawIndexedAccessTest::s_indexConfigs[INDEX_CONFIG_COUNT] =
398 {
399 	std::vector<deUint32>(lastIndexOutOfBounds, lastIndexOutOfBounds + DE_LENGTH_OF_ARRAY(lastIndexOutOfBounds)),
400 	std::vector<deUint32>(indicesOutOfBounds, indicesOutOfBounds + DE_LENGTH_OF_ARRAY(indicesOutOfBounds)),
401 	std::vector<deUint32>(triangleOutOfBounds, triangleOutOfBounds + DE_LENGTH_OF_ARRAY(triangleOutOfBounds)),
402 };
403 
DrawIndexedAccessTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkFormat inputFormat,IndexConfig indexConfig)404 DrawIndexedAccessTest::DrawIndexedAccessTest (tcu::TestContext&		testContext,
405 											  const std::string&	name,
406 											  const std::string&	description,
407 											  VkFormat				inputFormat,
408 											  IndexConfig			indexConfig)
409 
410 	: VertexAccessTest	(testContext,
411 						 name,
412 						 description,
413 						 inputFormat,
414 						 getNumUsedChannels(mapVkFormat(inputFormat).order) * (deUint32)s_indexConfigs[indexConfig].size() * 2,	// numVertexValues
415 						 getNumUsedChannels(mapVkFormat(inputFormat).order),													// numInstanceValues
416 						 (deUint32)s_indexConfigs[indexConfig].size(),															// numVertices
417 						 1)																										// numInstances
418 	, m_indexConfig		(indexConfig)
419 {
420 }
421 
createInstance(Context & context) const422 TestInstance* DrawIndexedAccessTest::createInstance (Context& context) const
423 {
424 	Move<VkDevice> device = createRobustBufferAccessDevice(context);
425 
426 	return new DrawIndexedAccessInstance(context,
427 										 device,
428 										 m_inputFormat,
429 										 m_numVertexValues,
430 										 m_numInstanceValues,
431 										 m_numVertices,
432 										 m_numInstances,
433 										 s_indexConfigs[m_indexConfig]);
434 }
435 
436 // VertexAccessInstance
437 
VertexAccessInstance(Context & context,Move<VkDevice> device,VkFormat inputFormat,deUint32 numVertexValues,deUint32 numInstanceValues,deUint32 numVertices,deUint32 numInstances,const std::vector<deUint32> & indices)438 VertexAccessInstance::VertexAccessInstance (Context&						context,
439 											Move<VkDevice>					device,
440 											VkFormat						inputFormat,
441 											deUint32						numVertexValues,
442 											deUint32						numInstanceValues,
443 											deUint32						numVertices,
444 											deUint32						numInstances,
445 											const std::vector<deUint32>&	indices)
446 
447 	: vkt::TestInstance			(context)
448 	, m_device					(device)
449 	, m_inputFormat				(inputFormat)
450 	, m_numVertexValues			(numVertexValues)
451 	, m_numInstanceValues		(numInstanceValues)
452 	, m_numVertices				(numVertices)
453 	, m_numInstances			(numInstances)
454 {
455 	const DeviceInterface&		vk						= context.getDeviceInterface();
456 	const deUint32				queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
457 	SimpleAllocator				memAlloc				(vk, *m_device, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
458 	const deUint32				formatSizeInBytes		= tcu::getPixelSize(mapVkFormat(m_inputFormat));
459 
460 	// Check storage support
461 	if (!context.getDeviceFeatures().vertexPipelineStoresAndAtomics)
462 	{
463 		TCU_THROW(NotSupportedError, "Stores not supported in vertex stage");
464 	}
465 
466 	if (m_inputFormat == VK_FORMAT_R64_UINT || m_inputFormat == VK_FORMAT_R64_SINT)
467 	{
468 		const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), m_inputFormat);
469 		context.requireDeviceFunctionality("VK_EXT_shader_image_atomic_int64");
470 
471 		if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) != VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)
472 			TCU_THROW(NotSupportedError, "VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT not supported");
473 	}
474 
475 
476 	const VkVertexInputAttributeDescription attributes[] =
477 	{
478 		// input rate: vertex
479 		{
480 			0u,								// deUint32 location;
481 			0u,								// deUint32 binding;
482 			m_inputFormat,					// VkFormat format;
483 			0u,								// deUint32 offset;
484 		},
485 		{
486 			1u,								// deUint32 location;
487 			0u,								// deUint32 binding;
488 			m_inputFormat,					// VkFormat format;
489 			formatSizeInBytes,				// deUint32 offset;
490 		},
491 
492 		// input rate: instance
493 		{
494 			2u,								// deUint32 location;
495 			1u,								// deUint32 binding;
496 			m_inputFormat,					// VkFormat format;
497 			0u,								// deUint32 offset;
498 		},
499 
500 		// Attribute for vertex number
501 		{
502 			3u,								// deUint32 location;
503 			2u,								// deUint32 binding;
504 			VK_FORMAT_R32_SINT,				// VkFormat format;
505 			0,								// deUint32 offset;
506 		},
507 	};
508 
509 	const VkVertexInputBindingDescription bindings[] =
510 	{
511 		{
512 			0u,								// deUint32				binding;
513 			formatSizeInBytes * 2,			// deUint32				stride;
514 			VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputRate	inputRate;
515 		},
516 		{
517 			1u,								// deUint32				binding;
518 			formatSizeInBytes,				// deUint32				stride;
519 			VK_VERTEX_INPUT_RATE_INSTANCE	// VkVertexInputRate	inputRate;
520 		},
521 		{
522 			2u,								// deUint32				binding;
523 			sizeof(deInt32),				// deUint32				stride;
524 			VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputRate	inputRate;
525 		},
526 	};
527 
528 	m_vertexInputBindings	= std::vector<VkVertexInputBindingDescription>(bindings, bindings + DE_LENGTH_OF_ARRAY(bindings));
529 	m_vertexInputAttributes	= std::vector<VkVertexInputAttributeDescription>(attributes, attributes + DE_LENGTH_OF_ARRAY(attributes));
530 
531 	// Create vertex buffer for vertex input rate
532 	{
533 		VkMemoryRequirements bufferMemoryReqs;
534 
535 		m_vertexRateBufferSize = getBufferSizeInBytes(m_numVertexValues, m_inputFormat); // All formats used in this test suite are 32-bit based.
536 
537 		const VkBufferCreateInfo	vertexRateBufferParams	=
538 		{
539 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
540 			DE_NULL,									// const void*			pNext;
541 			0u,											// VkBufferCreateFlags	flags;
542 			m_vertexRateBufferSize,						// VkDeviceSize			size;
543 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
544 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
545 			1u,											// deUint32				queueFamilyIndexCount;
546 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
547 		};
548 
549 		m_vertexRateBuffer			= createBuffer(vk, *m_device, &vertexRateBufferParams);
550 		bufferMemoryReqs			= getBufferMemoryRequirements(vk, *m_device, *m_vertexRateBuffer);
551 		m_vertexRateBufferAllocSize	= bufferMemoryReqs.size;
552 		m_vertexRateBufferAlloc		= memAlloc.allocate(bufferMemoryReqs, MemoryRequirement::HostVisible);
553 
554 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_vertexRateBuffer, m_vertexRateBufferAlloc->getMemory(), m_vertexRateBufferAlloc->getOffset()));
555 		populateBufferWithTestValues(m_vertexRateBufferAlloc->getHostPtr(), (deUint32)m_vertexRateBufferAllocSize, m_inputFormat);
556 		flushMappedMemoryRange(vk, *m_device, m_vertexRateBufferAlloc->getMemory(), m_vertexRateBufferAlloc->getOffset(), VK_WHOLE_SIZE);
557 	}
558 
559 	// Create vertex buffer for instance input rate
560 	{
561 		VkMemoryRequirements bufferMemoryReqs;
562 
563 		m_instanceRateBufferSize = getBufferSizeInBytes(m_numInstanceValues, m_inputFormat); // All formats used in this test suite are 32-bit based.
564 
565 		const VkBufferCreateInfo	instanceRateBufferParams	=
566 		{
567 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
568 			DE_NULL,									// const void*			pNext;
569 			0u,											// VkBufferCreateFlags	flags;
570 			m_instanceRateBufferSize,					// VkDeviceSize			size;
571 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
572 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
573 			1u,											// deUint32				queueFamilyIndexCount;
574 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
575 		};
576 
577 		m_instanceRateBuffer			= createBuffer(vk, *m_device, &instanceRateBufferParams);
578 		bufferMemoryReqs				= getBufferMemoryRequirements(vk, *m_device, *m_instanceRateBuffer);
579 		m_instanceRateBufferAllocSize	= bufferMemoryReqs.size;
580 		m_instanceRateBufferAlloc		= memAlloc.allocate(bufferMemoryReqs, MemoryRequirement::HostVisible);
581 
582 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_instanceRateBuffer, m_instanceRateBufferAlloc->getMemory(), m_instanceRateBufferAlloc->getOffset()));
583 		populateBufferWithTestValues(m_instanceRateBufferAlloc->getHostPtr(), (deUint32)m_instanceRateBufferAllocSize, m_inputFormat);
584 		flushMappedMemoryRange(vk, *m_device, m_instanceRateBufferAlloc->getMemory(), m_instanceRateBufferAlloc->getOffset(), VK_WHOLE_SIZE);
585 	}
586 
587 	// Create vertex buffer that stores the vertex number (from 0 to m_numVertices - 1)
588 	{
589 		m_vertexNumBufferSize = 128 * sizeof(deInt32); // Allocate enough device memory for all indices (0 to 127).
590 
591 		const VkBufferCreateInfo	vertexNumBufferParams	=
592 		{
593 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
594 			DE_NULL,									// const void*			pNext;
595 			0u,											// VkBufferCreateFlags	flags;
596 			m_vertexNumBufferSize,						// VkDeviceSize			size;
597 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
598 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
599 			1u,											// deUint32				queueFamilyIndexCount;
600 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
601 		};
602 
603 		m_vertexNumBuffer		= createBuffer(vk, *m_device, &vertexNumBufferParams);
604 		m_vertexNumBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_vertexNumBuffer), MemoryRequirement::HostVisible);
605 
606 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_vertexNumBuffer, m_vertexNumBufferAlloc->getMemory(), m_vertexNumBufferAlloc->getOffset()));
607 	}
608 
609 	// Create index buffer if required
610 	if (!indices.empty())
611 	{
612 		m_indexBufferSize = sizeof(deUint32) * indices.size();
613 
614 		const VkBufferCreateInfo	indexBufferParams	=
615 		{
616 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
617 			DE_NULL,									// const void*			pNext;
618 			0u,											// VkBufferCreateFlags	flags;
619 			m_indexBufferSize,							// VkDeviceSize			size;
620 			VK_BUFFER_USAGE_INDEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
621 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
622 			1u,											// deUint32				queueFamilyIndexCount;
623 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
624 		};
625 
626 		m_indexBuffer		= createBuffer(vk, *m_device, &indexBufferParams);
627 		m_indexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_indexBuffer), MemoryRequirement::HostVisible);
628 
629 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_indexBuffer, m_indexBufferAlloc->getMemory(), m_indexBufferAlloc->getOffset()));
630 		deMemcpy(m_indexBufferAlloc->getHostPtr(), indices.data(), (size_t)m_indexBufferSize);
631 		flushMappedMemoryRange(vk, *m_device, m_indexBufferAlloc->getMemory(), m_indexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
632 	}
633 
634 	// Create result ssbo
635 	{
636 		const int	numChannels	= getNumUsedChannels(mapVkFormat(m_inputFormat).order);
637 
638 		m_outBufferSize = getBufferSizeInBytes(m_numVertices * m_numInstances * numChannels * 3, VK_FORMAT_R32_UINT);
639 
640 		const VkBufferCreateInfo	outBufferParams		=
641 		{
642 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
643 			DE_NULL,									// const void*			pNext;
644 			0u,											// VkBufferCreateFlags	flags;
645 			m_outBufferSize,							// VkDeviceSize			size;
646 			VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,			// VkBufferUsageFlags	usage;
647 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
648 			1u,											// deUint32				queueFamilyIndexCount;
649 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
650 		};
651 
652 		m_outBuffer			= createBuffer(vk, *m_device, &outBufferParams);
653 		m_outBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_outBuffer), MemoryRequirement::HostVisible);
654 
655 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
656 		deMemset(m_outBufferAlloc->getHostPtr(), 0xFF, (size_t)m_outBufferSize);
657 		flushMappedMemoryRange(vk, *m_device, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset(), VK_WHOLE_SIZE);
658 	}
659 
660 	// Create descriptor set data
661 	{
662 		DescriptorPoolBuilder descriptorPoolBuilder;
663 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u);
664 		m_descriptorPool = descriptorPoolBuilder.build(vk, *m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
665 
666 		DescriptorSetLayoutBuilder setLayoutBuilder;
667 		setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT);
668 		m_descriptorSetLayout = setLayoutBuilder.build(vk, *m_device);
669 
670 		const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
671 		{
672 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
673 			DE_NULL,											// const void*					pNext;
674 			*m_descriptorPool,									// VkDescriptorPool				desciptorPool;
675 			1u,													// deUint32						setLayoutCount;
676 			&m_descriptorSetLayout.get()						// const VkDescriptorSetLayout*	pSetLayouts;
677 		};
678 
679 		m_descriptorSet = allocateDescriptorSet(vk, *m_device, &descriptorSetAllocateInfo);
680 
681 		const VkDescriptorBufferInfo outBufferDescriptorInfo	= makeDescriptorBufferInfo(*m_outBuffer, 0ull, VK_WHOLE_SIZE);
682 
683 		DescriptorSetUpdateBuilder setUpdateBuilder;
684 		setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outBufferDescriptorInfo);
685 		setUpdateBuilder.update(vk, *m_device);
686 	}
687 
688 	// Create fence
689 	{
690 		const VkFenceCreateInfo fenceParams =
691 		{
692 			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
693 			DE_NULL,								// const void*			pNext;
694 			0u										// VkFenceCreateFlags	flags;
695 		};
696 
697 		m_fence = createFence(vk, *m_device, &fenceParams);
698 	}
699 
700 	// Get queue
701 	vk.getDeviceQueue(*m_device, queueFamilyIndex, 0, &m_queue);
702 
703 	// Setup graphics test environment
704 	{
705 		GraphicsEnvironment::DrawConfig drawConfig;
706 
707 		drawConfig.vertexBuffers.push_back(*m_vertexRateBuffer);
708 		drawConfig.vertexBuffers.push_back(*m_instanceRateBuffer);
709 		drawConfig.vertexBuffers.push_back(*m_vertexNumBuffer);
710 
711 		drawConfig.vertexCount		= m_numVertices;
712 		drawConfig.instanceCount	= m_numInstances;
713 		drawConfig.indexBuffer		= *m_indexBuffer;
714 		drawConfig.indexCount		= (deUint32)(m_indexBufferSize / sizeof(deUint32));
715 
716 		m_graphicsTestEnvironment	= de::MovePtr<GraphicsEnvironment>(new GraphicsEnvironment(m_context,
717 																							   *m_device,
718 																							   *m_descriptorSetLayout,
719 																							   *m_descriptorSet,
720 																							   GraphicsEnvironment::VertexBindings(bindings, bindings + DE_LENGTH_OF_ARRAY(bindings)),
721 																							   GraphicsEnvironment::VertexAttributes(attributes, attributes + DE_LENGTH_OF_ARRAY(attributes)),
722 																							   drawConfig));
723 	}
724 }
725 
iterate(void)726 tcu::TestStatus VertexAccessInstance::iterate (void)
727 {
728 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
729 	const vk::VkCommandBuffer	cmdBuffer	= m_graphicsTestEnvironment->getCommandBuffer();
730 
731 	// Initialize vertex ids
732 	{
733 		deUint32 *bufferPtr = reinterpret_cast<deUint32*>(m_vertexNumBufferAlloc->getHostPtr());
734 		deMemset(bufferPtr, 0, (size_t)m_vertexNumBufferSize);
735 
736 		initVertexIds(bufferPtr, (size_t)(m_vertexNumBufferSize / sizeof(deUint32)));
737 
738 		flushMappedMemoryRange(vk, *m_device, m_vertexNumBufferAlloc->getMemory(), m_vertexNumBufferAlloc->getOffset(), VK_WHOLE_SIZE);
739 	}
740 
741 	// Submit command buffer
742 	{
743 		const VkSubmitInfo	submitInfo	=
744 		{
745 			VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
746 			DE_NULL,						// const void*					pNext;
747 			0u,								// deUint32						waitSemaphoreCount;
748 			DE_NULL,						// const VkSemaphore*			pWaitSemaphores;
749 			DE_NULL,						// const VkPIpelineStageFlags*	pWaitDstStageMask;
750 			1u,								// deUint32						commandBufferCount;
751 			&cmdBuffer,						// const VkCommandBuffer*		pCommandBuffers;
752 			0u,								// deUint32						signalSemaphoreCount;
753 			DE_NULL							// const VkSemaphore*			pSignalSemaphores;
754 		};
755 
756 		VK_CHECK(vk.resetFences(*m_device, 1, &m_fence.get()));
757 		VK_CHECK(vk.queueSubmit(m_queue, 1, &submitInfo, *m_fence));
758 		VK_CHECK(vk.waitForFences(*m_device, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
759 	}
760 
761 	// Prepare result buffer for read
762 	{
763 		const VkMappedMemoryRange	outBufferRange	=
764 		{
765 			VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	//  VkStructureType	sType;
766 			DE_NULL,								//  const void*		pNext;
767 			m_outBufferAlloc->getMemory(),			//  VkDeviceMemory	mem;
768 			0ull,									//  VkDeviceSize	offset;
769 			m_outBufferSize,						//  VkDeviceSize	size;
770 		};
771 
772 		VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange));
773 	}
774 
775 	if (verifyResult())
776 		return tcu::TestStatus::pass("All values OK");
777 	else
778 		return tcu::TestStatus::fail("Invalid value(s) found");
779 }
780 
verifyResult(void)781 bool VertexAccessInstance::verifyResult (void)
782 {
783 	std::ostringstream			logMsg;
784 	const DeviceInterface&		vk						= m_context.getDeviceInterface();
785 	tcu::TestLog&				log						= m_context.getTestContext().getLog();
786 	const deUint32				numChannels				= getNumUsedChannels(mapVkFormat(m_inputFormat).order);
787 	const deUint32				numScalarsPerVertex		= numChannels * 3; // Use 3 identical attributes
788 	void*						outDataPtr				= m_outBufferAlloc->getHostPtr();
789 	const deUint32				outValueSize			= static_cast<deUint32>((m_inputFormat == VK_FORMAT_R64_UINT || m_inputFormat == VK_FORMAT_R64_SINT)
790 										? sizeof(deUint64) : sizeof(deUint32));
791 	bool						allOk					= true;
792 
793 	const VkMappedMemoryRange	outBufferRange			=
794 	{
795 		VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	// VkStructureType	sType;
796 		DE_NULL,								// const void*		pNext;
797 		m_outBufferAlloc->getMemory(),			// VkDeviceMemory	mem;
798 		m_outBufferAlloc->getOffset(),			// VkDeviceSize		offset;
799 		m_outBufferSize,						// VkDeviceSize		size;
800 	};
801 
802 	VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange));
803 
804 	for (deUint32 valueNdx = 0; valueNdx < m_outBufferSize / outValueSize; valueNdx++)
805 	{
806 		deUint32			numInBufferValues;
807 		void*				inBufferPtr;
808 		VkDeviceSize		inBufferAllocSize;
809 		deUint32			inBufferValueIndex;
810 		bool				isOutOfBoundsAccess		= false;
811 		const deUint32		attributeIndex			= (valueNdx / numChannels) % 3;
812 		deUint32*			ptr32					= (deUint32*)outDataPtr;
813 		deUint64*			ptr64					= (deUint64*)outDataPtr;
814 		const void*			outValuePtr				= ((m_inputFormat == VK_FORMAT_R64_UINT || m_inputFormat == VK_FORMAT_R64_SINT) ?
815 														(void*)(ptr64 + valueNdx) :
816 														(void*)(ptr32 + valueNdx));
817 
818 		if (attributeIndex == 2)
819 		{
820 			// Instance rate
821 			const deUint32	elementIndex	= valueNdx / (numScalarsPerVertex * m_numVertices); // instance id
822 
823 			numInBufferValues	= m_numInstanceValues;
824 			inBufferPtr			= m_instanceRateBufferAlloc->getHostPtr();
825 			inBufferAllocSize	= m_instanceRateBufferAllocSize;
826 			inBufferValueIndex	= (elementIndex * numChannels) + (valueNdx % numScalarsPerVertex) - (2 * numChannels);
827 		}
828 		else
829 		{
830 			// Vertex rate
831 			const deUint32	vertexNdx		= valueNdx / numScalarsPerVertex;
832 			const deUint32	instanceNdx		= vertexNdx / m_numVertices;
833 			const deUint32	elementIndex	= valueNdx / numScalarsPerVertex; // vertex id
834 
835 			numInBufferValues	= m_numVertexValues;
836 			inBufferPtr			= m_vertexRateBufferAlloc->getHostPtr();
837 			inBufferAllocSize	= m_vertexRateBufferAllocSize;
838 			inBufferValueIndex	= (getIndex(elementIndex) * (numChannels * 2)) + (valueNdx % numScalarsPerVertex) - instanceNdx * (m_numVertices * numChannels * 2);
839 
840 			// Binding 0 contains two attributes, so bounds checking for attribute 0 must also consider attribute 1 to determine if the binding is out of bounds.
841 			if ((attributeIndex == 0) && (numInBufferValues >= numChannels))
842 				numInBufferValues -= numChannels;
843 		}
844 
845 		isOutOfBoundsAccess	= (inBufferValueIndex >= numInBufferValues);
846 
847 		const deInt32		distanceToOutOfBounds	= (deInt32)outValueSize * ((deInt32)numInBufferValues - (deInt32)inBufferValueIndex);
848 
849 		if (!isOutOfBoundsAccess && (distanceToOutOfBounds < 16))
850 			isOutOfBoundsAccess = (((inBufferValueIndex / numChannels) + 1) * numChannels > numInBufferValues);
851 
852 		// Log value information
853 		{
854 			// Vertex separator
855 			if (valueNdx && valueNdx % numScalarsPerVertex == 0)
856 				logMsg << "\n";
857 
858 			logMsg << "\n" << valueNdx << ": Value ";
859 
860 			// Result index and value
861 			if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
862 				logValue(logMsg, outValuePtr, VK_FORMAT_R32_SFLOAT, 4);
863 			else
864 				logValue(logMsg, outValuePtr, m_inputFormat, 4);
865 
866 			// Attribute name
867 			logMsg << "\tfrom attr" << attributeIndex;
868 			if (numChannels > 1)
869 				logMsg << "[" << valueNdx % numChannels << "]";
870 
871 			// Input rate
872 			if (attributeIndex == 2)
873 				logMsg << "\tinstance rate";
874 			else
875 				logMsg << "\tvertex rate";
876 		}
877 
878 		if (isOutOfBoundsAccess)
879 		{
880 			const bool isValidValue = isValueWithinVertexBufferOrZero(inBufferPtr, inBufferAllocSize, outValuePtr, inBufferValueIndex);
881 
882 			logMsg << "\t(out of bounds)";
883 
884 			if (!isValidValue)
885 			{
886 				// Check if we are satisfying the [0, 0, 0, x] pattern, where x may be either 0 or 1,
887 				// or the maximum representable positive integer value (if the format is integer-based).
888 
889 				const bool	canMatchVec4Pattern	= ((valueNdx % numChannels == 3) || m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32);
890 				bool		matchesVec4Pattern	= false;
891 
892 				if (canMatchVec4Pattern)
893 				{
894 					if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
895 						matchesVec4Pattern	=  verifyOutOfBoundsVec4(outValuePtr, m_inputFormat);
896 					else
897 						matchesVec4Pattern	=  verifyOutOfBoundsVec4(((deUint32*)outValuePtr) - 3, m_inputFormat);
898 				}
899 
900 				if (!canMatchVec4Pattern || !matchesVec4Pattern)
901 				{
902 					logMsg << ", Failed: expected a value within the buffer range or 0";
903 
904 					if (canMatchVec4Pattern)
905 						logMsg << ", or the [0, 0, 0, x] pattern";
906 
907 					allOk = false;
908 				}
909 			}
910 		}
911 		else if (!isExpectedValueFromVertexBuffer(inBufferPtr, inBufferValueIndex, m_inputFormat, outValuePtr))
912 		{
913 			logMsg << ", Failed: unexpected value";
914 			allOk = false;
915 		}
916 	}
917 	log << tcu::TestLog::Message << logMsg.str() << tcu::TestLog::EndMessage;
918 
919 	return allOk;
920 }
921 
isValueWithinVertexBufferOrZero(void * vertexBuffer,VkDeviceSize vertexBufferSize,const void * value,deUint32 valueIndex)922 bool VertexAccessInstance::isValueWithinVertexBufferOrZero(void* vertexBuffer, VkDeviceSize vertexBufferSize, const void* value, deUint32 valueIndex)
923 {
924 	if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
925 	{
926 		const float		normValue		= *reinterpret_cast<const float*>(value);
927 		const deUint32	scalarIndex		= valueIndex % 4;
928 		const bool		isAlpha			= (scalarIndex == 3);
929 		deUint32		encodedValue;
930 
931 		if (isAlpha)
932 			encodedValue = deMin32(deUint32(deFloatRound(normValue * 0x3u)), 0x3u);
933 		else
934 			encodedValue = deMin32(deUint32(deFloatRound(normValue * 0x3FFu)), 0x3FFu);
935 
936 		if (encodedValue == 0)
937 			return true;
938 
939 		for (deUint32 i = 0; i < vertexBufferSize / 4; i++)
940 		{
941 			const deUint32	packedValue		= reinterpret_cast<deUint32*>(vertexBuffer)[i];
942 			deUint32		unpackedValue;
943 
944 			if (scalarIndex < 3)
945 				unpackedValue = (packedValue >> (10 * scalarIndex)) & 0x3FFu;
946 			else
947 				unpackedValue = (packedValue >> 30) & 0x3u;
948 
949 			if (unpackedValue == encodedValue)
950 				return true;
951 		}
952 
953 		return false;
954 	}
955 	else
956 	{
957 		return isValueWithinBufferOrZero(vertexBuffer, vertexBufferSize, value, sizeof(deUint32));
958 	}
959 }
960 
isExpectedValueFromVertexBuffer(const void * vertexBuffer,deUint32 vertexIndex,VkFormat vertexFormat,const void * value)961 bool VertexAccessInstance::isExpectedValueFromVertexBuffer (const void* vertexBuffer, deUint32 vertexIndex, VkFormat vertexFormat, const void* value)
962 {
963 	if (isUintFormat(vertexFormat))
964 	{
965 		if (vertexFormat == VK_FORMAT_R64_UINT || vertexFormat == VK_FORMAT_R64_SINT)
966 		{
967 			const deUint64* bufferPtr = reinterpret_cast<const deUint64*>(vertexBuffer);
968 			return bufferPtr[vertexIndex] == *reinterpret_cast<const deUint64 *>(value);
969 		}
970 		else
971 		{
972 			const deUint32* bufferPtr = reinterpret_cast<const deUint32*>(vertexBuffer);
973 			return bufferPtr[vertexIndex] == *reinterpret_cast<const deUint32 *>(value);
974 		}
975 	}
976 	else if (isIntFormat(vertexFormat))
977 	{
978 		if (vertexFormat == VK_FORMAT_R64_UINT || vertexFormat == VK_FORMAT_R64_SINT)
979 		{
980 			const deInt64* bufferPtr = reinterpret_cast<const deInt64*>(vertexBuffer);
981 			return bufferPtr[vertexIndex] == *reinterpret_cast<const deInt64 *>(value);
982 		}
983 		else
984 		{
985 			const deInt32* bufferPtr = reinterpret_cast<const deInt32*>(vertexBuffer);
986 			return bufferPtr[vertexIndex] == *reinterpret_cast<const deInt32 *>(value);
987 		}
988 	}
989 	else if (isFloatFormat(vertexFormat))
990 	{
991 		const float* bufferPtr = reinterpret_cast<const float*>(vertexBuffer);
992 
993 		return areEqual(bufferPtr[vertexIndex], *reinterpret_cast<const float *>(value));
994 	}
995 	else if (vertexFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
996 	{
997 		const deUint32*	bufferPtr		= reinterpret_cast<const deUint32*>(vertexBuffer);
998 		const deUint32	packedValue		= bufferPtr[vertexIndex / 4];
999 		const deUint32	scalarIndex		= vertexIndex % 4;
1000 		float			normValue;
1001 
1002 		if (scalarIndex < 3)
1003 			normValue = float((packedValue >> (10 * scalarIndex)) & 0x3FFu) / 0x3FFu;
1004 		else
1005 			normValue = float(packedValue >> 30) / 0x3u;
1006 
1007 		return areEqual(normValue, *reinterpret_cast<const float *>(value));
1008 	}
1009 
1010 	DE_ASSERT(false);
1011 	return false;
1012 }
1013 
getBufferSizeInBytes(deUint32 numScalars,VkFormat format)1014 VkDeviceSize VertexAccessInstance::getBufferSizeInBytes (deUint32 numScalars, VkFormat format)
1015 {
1016 	if (isUintFormat(format) || isIntFormat(format) || isFloatFormat(format))
1017 	{
1018 		return numScalars * ((format == VK_FORMAT_R64_UINT || format == VK_FORMAT_R64_SINT) ? 8 : 4);
1019 	}
1020 	else if (format == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
1021 	{
1022 		DE_ASSERT(numScalars % 4 == 0);
1023 		return numScalars;
1024 	}
1025 
1026 	DE_ASSERT(false);
1027 	return 0;
1028 }
1029 
1030 // DrawAccessInstance
1031 
DrawAccessInstance(Context & context,Move<VkDevice> device,VkFormat inputFormat,deUint32 numVertexValues,deUint32 numInstanceValues,deUint32 numVertices,deUint32 numInstances)1032 DrawAccessInstance::DrawAccessInstance (Context&				context,
1033 										Move<VkDevice>			device,
1034 										VkFormat				inputFormat,
1035 										deUint32				numVertexValues,
1036 										deUint32				numInstanceValues,
1037 										deUint32				numVertices,
1038 										deUint32				numInstances)
1039 	: VertexAccessInstance (context,
1040 							device,
1041 							inputFormat,
1042 							numVertexValues,
1043 							numInstanceValues,
1044 							numVertices,
1045 							numInstances,
1046 							std::vector<deUint32>()) // No index buffer
1047 {
1048 }
1049 
initVertexIds(deUint32 * indicesPtr,size_t indexCount)1050 void DrawAccessInstance::initVertexIds (deUint32 *indicesPtr, size_t indexCount)
1051 {
1052 	for (deUint32 i = 0; i < indexCount; i++)
1053 		indicesPtr[i] = i;
1054 }
1055 
getIndex(deUint32 vertexNum) const1056 deUint32 DrawAccessInstance::getIndex (deUint32 vertexNum) const
1057 {
1058 	return vertexNum;
1059 }
1060 
1061 // DrawIndexedAccessInstance
1062 
DrawIndexedAccessInstance(Context & context,Move<VkDevice> device,VkFormat inputFormat,deUint32 numVertexValues,deUint32 numInstanceValues,deUint32 numVertices,deUint32 numInstances,const std::vector<deUint32> & indices)1063 DrawIndexedAccessInstance::DrawIndexedAccessInstance (Context&						context,
1064 													  Move<VkDevice>				device,
1065 													  VkFormat						inputFormat,
1066 													  deUint32						numVertexValues,
1067 													  deUint32						numInstanceValues,
1068 													  deUint32						numVertices,
1069 													  deUint32						numInstances,
1070 													  const std::vector<deUint32>&	indices)
1071 	: VertexAccessInstance	(context,
1072 							 device,
1073 							 inputFormat,
1074 							 numVertexValues,
1075 							 numInstanceValues,
1076 							 numVertices,
1077 							 numInstances,
1078 							 indices)
1079 	, m_indices				(indices)
1080 {
1081 }
1082 
initVertexIds(deUint32 * indicesPtr,size_t indexCount)1083 void DrawIndexedAccessInstance::initVertexIds (deUint32 *indicesPtr, size_t indexCount)
1084 {
1085 	DE_UNREF(indexCount);
1086 
1087 	for (deUint32 i = 0; i < m_indices.size(); i++)
1088 	{
1089 		DE_ASSERT(m_indices[i] < indexCount);
1090 
1091 		indicesPtr[m_indices[i]] = i;
1092 	}
1093 }
1094 
getIndex(deUint32 vertexNum) const1095 deUint32 DrawIndexedAccessInstance::getIndex (deUint32 vertexNum) const
1096 {
1097 	DE_ASSERT(vertexNum < (deUint32)m_indices.size());
1098 
1099 	return m_indices[vertexNum];
1100 }
1101 
1102 // Test node creation functions
1103 
createDrawTests(tcu::TestContext & testCtx,VkFormat format)1104 static tcu::TestCaseGroup* createDrawTests (tcu::TestContext& testCtx, VkFormat format)
1105 {
1106 	struct TestConfig
1107 	{
1108 		std::string		name;
1109 		std::string		description;
1110 		VkFormat		inputFormat;
1111 		deUint32		numVertexValues;
1112 		deUint32		numInstanceValues;
1113 		deUint32		numVertices;
1114 		deUint32		numInstances;
1115 	};
1116 
1117 	const deUint32 numChannels = getNumUsedChannels(mapVkFormat(format).order);
1118 
1119 	const TestConfig testConfigs[] =
1120 	{
1121 		// name						description											format	numVertexValues			numInstanceValues	numVertices		numInstances
1122 		{ "vertex_out_of_bounds",	"Create data for 6 vertices, draw 9 vertices",		format,	numChannels * 2 * 6,	numChannels,		9,				1	 },
1123 		{ "vertex_incomplete",		"Create data for half a vertex, draw 3 vertices",	format,	numChannels,			numChannels,		3,				1	 },
1124 		{ "instance_out_of_bounds", "Create data for 1 instance, draw 3 instances",		format,	numChannels * 2 * 9,	numChannels,		3,				3	 },
1125 	};
1126 
1127 	de::MovePtr<tcu::TestCaseGroup>	drawTests (new tcu::TestCaseGroup(testCtx, "draw", ""));
1128 
1129 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(testConfigs); i++)
1130 	{
1131 		const TestConfig &config = testConfigs[i];
1132 
1133 		drawTests->addChild(new DrawAccessTest(testCtx, config.name, config.description, config.inputFormat,
1134 											   config.numVertexValues, config.numInstanceValues,
1135 											   config.numVertices, config.numInstances));
1136 	}
1137 
1138 	return drawTests.release();
1139 }
1140 
createDrawIndexedTests(tcu::TestContext & testCtx,VkFormat format)1141 static tcu::TestCaseGroup* createDrawIndexedTests (tcu::TestContext& testCtx, VkFormat format)
1142 {
1143 	struct TestConfig
1144 	{
1145 		std::string							name;
1146 		std::string							description;
1147 		VkFormat							inputFormat;
1148 		DrawIndexedAccessTest::IndexConfig	indexConfig;
1149 	};
1150 
1151 	const TestConfig testConfigs[] =
1152 	{
1153 		// name							description								format		indexConfig
1154 		{ "last_index_out_of_bounds",	"Only last index is out of bounds",		format,		DrawIndexedAccessTest::INDEX_CONFIG_LAST_INDEX_OUT_OF_BOUNDS },
1155 		{ "indices_out_of_bounds",		"Random indices out of bounds",			format,		DrawIndexedAccessTest::INDEX_CONFIG_INDICES_OUT_OF_BOUNDS },
1156 		{ "triangle_out_of_bounds",		"First triangle is out of bounds",		format,		DrawIndexedAccessTest::INDEX_CONFIG_TRIANGLE_OUT_OF_BOUNDS },
1157 	};
1158 
1159 	de::MovePtr<tcu::TestCaseGroup>	drawTests (new tcu::TestCaseGroup(testCtx, "draw_indexed", ""));
1160 
1161 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(testConfigs); i++)
1162 	{
1163 		const TestConfig &config = testConfigs[i];
1164 
1165 		drawTests->addChild(new DrawIndexedAccessTest(testCtx, config.name, config.description, config.inputFormat, config.indexConfig));
1166 	}
1167 
1168 	return drawTests.release();
1169 }
1170 
addVertexFormatTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * parentGroup)1171 static void addVertexFormatTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup)
1172 {
1173 	const VkFormat vertexFormats[] =
1174 	{
1175 		VK_FORMAT_R32_UINT,
1176 		VK_FORMAT_R32_SINT,
1177 		VK_FORMAT_R32_SFLOAT,
1178 		VK_FORMAT_R32G32_UINT,
1179 		VK_FORMAT_R32G32_SINT,
1180 		VK_FORMAT_R32G32_SFLOAT,
1181 		VK_FORMAT_R32G32B32_UINT,
1182 		VK_FORMAT_R32G32B32_SINT,
1183 		VK_FORMAT_R32G32B32_SFLOAT,
1184 		VK_FORMAT_R32G32B32A32_UINT,
1185 		VK_FORMAT_R32G32B32A32_SINT,
1186 		VK_FORMAT_R32G32B32A32_SFLOAT,
1187 		VK_FORMAT_R64_UINT,
1188 		VK_FORMAT_R64_SINT,
1189 
1190 		VK_FORMAT_A2B10G10R10_UNORM_PACK32
1191 	};
1192 
1193 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(vertexFormats); i++)
1194 	{
1195 		const std::string				formatName	= getFormatName(vertexFormats[i]);
1196 		de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx, de::toLower(formatName.substr(10)).c_str(), ""));
1197 
1198 		formatGroup->addChild(createDrawTests(testCtx, vertexFormats[i]));
1199 		formatGroup->addChild(createDrawIndexedTests(testCtx, vertexFormats[i]));
1200 
1201 		parentGroup->addChild(formatGroup.release());
1202 	}
1203 }
1204 
createVertexAccessTests(tcu::TestContext & testCtx)1205 tcu::TestCaseGroup* createVertexAccessTests (tcu::TestContext& testCtx)
1206 {
1207 	de::MovePtr<tcu::TestCaseGroup> vertexAccessTests	(new tcu::TestCaseGroup(testCtx, "vertex_access", ""));
1208 
1209 	addVertexFormatTests(testCtx, vertexAccessTests.get());
1210 
1211 	return vertexAccessTests.release();
1212 }
1213 
1214 } // robustness
1215 } // vkt
1216