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 	if (numChannels == 1)
263 	{
264 		if (isUintFormat(m_inputFormat))
265 			attributeTypeStr << "uint";
266 		else if (isIntFormat(m_inputFormat))
267 			attributeTypeStr << "int";
268 		else
269 			attributeTypeStr << "float";
270 	}
271 	else
272 	{
273 		if (isUintFormat(m_inputFormat))
274 			attributeTypeStr << "uvec";
275 		else if (isIntFormat(m_inputFormat))
276 			attributeTypeStr << "ivec";
277 		else
278 			attributeTypeStr << "vec";
279 
280 		attributeTypeStr << numChannels;
281 	}
282 
283 	for (int attrNdx = 0; attrNdx < 3; attrNdx++)
284 	{
285 		attributeDeclaration << "layout(location = " << attrNdx << ") in " << attributeTypeStr.str() << " attr" << attrNdx << ";\n";
286 
287 		for (int chanNdx = 0; chanNdx < numChannels; chanNdx++)
288 		{
289 			attributeUse << "\toutData[(gl_InstanceIndex * " << numScalarsPerVertex * m_numVertices
290 						 << ") + (vertexNum * " << numScalarsPerVertex << " + " << numValues++ << ")] = attr" << attrNdx;
291 
292 			if (numChannels == 1)
293 				attributeUse << ";\n";
294 			else
295 				attributeUse << "[" << chanNdx << "];\n";
296 		}
297 	}
298 
299 	attributeDeclaration << "layout(location = 3) in int vertexNum;\n";
300 
301 	attributeUse << "\n";
302 
303 	const char *outType = "";
304 	if (isUintFormat(m_inputFormat))
305 		outType = "uint";
306 	else if (isIntFormat(m_inputFormat))
307 		outType = "int";
308 	else
309 		outType = "float";
310 
311 	vertexShaderSource <<
312 		"#version 310 es\n"
313 		"precision highp float;\n"
314 		<< attributeDeclaration.str() <<
315 		"layout(set = 0, binding = 0, std430) buffer outBuffer\n"
316 		"{\n"
317 		"\t" << outType << " outData[" << (m_numVertices * numValues) * m_numInstances << "];\n"
318 		"};\n\n"
319 		"void main (void)\n"
320 		"{\n"
321 		<< attributeUse.str() <<
322 		"\tgl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
323 		"}\n";
324 
325 	programCollection.glslSources.add("vertex") << glu::VertexSource(vertexShaderSource.str());
326 
327 	fragmentShaderSource <<
328 		"#version 310 es\n"
329 		"precision highp float;\n"
330 		"layout(location = 0) out vec4 fragColor;\n"
331 		"void main (void)\n"
332 		"{\n"
333 		"\tfragColor = vec4(1.0);\n"
334 		"}\n";
335 
336 	programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentShaderSource.str());
337 }
338 
339 // DrawAccessTest
340 
DrawAccessTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkFormat inputFormat,deUint32 numVertexValues,deUint32 numInstanceValues,deUint32 numVertices,deUint32 numInstances)341 DrawAccessTest::DrawAccessTest (tcu::TestContext&		testContext,
342 								const std::string&		name,
343 								const std::string&		description,
344 								VkFormat				inputFormat,
345 								deUint32				numVertexValues,
346 								deUint32				numInstanceValues,
347 								deUint32				numVertices,
348 								deUint32				numInstances)
349 
350 	: VertexAccessTest		(testContext, name, description, inputFormat, numVertexValues, numInstanceValues, numVertices, numInstances)
351 {
352 }
353 
createInstance(Context & context) const354 TestInstance* DrawAccessTest::createInstance (Context& context) const
355 {
356 	Move<VkDevice> device = createRobustBufferAccessDevice(context);
357 
358 	return new DrawAccessInstance(context,
359 								  device,
360 								  m_inputFormat,
361 								  m_numVertexValues,
362 								  m_numInstanceValues,
363 								  m_numVertices,
364 								  m_numInstances);
365 }
366 
367 // DrawIndexedAccessTest
368 
369 const deUint32 lastIndexOutOfBounds[] =
370 {
371 	0, 1, 2, 3, 4, 100,		// Indices of 100 and above are out of bounds
372 };
373 const deUint32 indicesOutOfBounds[] =
374 {
375 	0, 100, 2, 101, 3, 102,	// Indices of 100 and above are out of bounds
376 };
377 const deUint32 triangleOutOfBounds[] =
378 {
379 	100, 101, 102, 3, 4, 5,	// Indices of 100 and above are out of bounds
380 };
381 
382 const std::vector<deUint32> DrawIndexedAccessTest::s_indexConfigs[INDEX_CONFIG_COUNT] =
383 {
384 	std::vector<deUint32>(lastIndexOutOfBounds, lastIndexOutOfBounds + DE_LENGTH_OF_ARRAY(lastIndexOutOfBounds)),
385 	std::vector<deUint32>(indicesOutOfBounds, indicesOutOfBounds + DE_LENGTH_OF_ARRAY(indicesOutOfBounds)),
386 	std::vector<deUint32>(triangleOutOfBounds, triangleOutOfBounds + DE_LENGTH_OF_ARRAY(triangleOutOfBounds)),
387 };
388 
DrawIndexedAccessTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkFormat inputFormat,IndexConfig indexConfig)389 DrawIndexedAccessTest::DrawIndexedAccessTest (tcu::TestContext&		testContext,
390 											  const std::string&	name,
391 											  const std::string&	description,
392 											  VkFormat				inputFormat,
393 											  IndexConfig			indexConfig)
394 
395 	: VertexAccessTest	(testContext,
396 						 name,
397 						 description,
398 						 inputFormat,
399 						 getNumUsedChannels(mapVkFormat(inputFormat).order) * (deUint32)s_indexConfigs[indexConfig].size() * 2,	// numVertexValues
400 						 getNumUsedChannels(mapVkFormat(inputFormat).order),													// numInstanceValues
401 						 (deUint32)s_indexConfigs[indexConfig].size(),															// numVertices
402 						 1)																										// numInstances
403 	, m_indexConfig		(indexConfig)
404 {
405 }
406 
createInstance(Context & context) const407 TestInstance* DrawIndexedAccessTest::createInstance (Context& context) const
408 {
409 	Move<VkDevice> device = createRobustBufferAccessDevice(context);
410 
411 	return new DrawIndexedAccessInstance(context,
412 										 device,
413 										 m_inputFormat,
414 										 m_numVertexValues,
415 										 m_numInstanceValues,
416 										 m_numVertices,
417 										 m_numInstances,
418 										 s_indexConfigs[m_indexConfig]);
419 }
420 
421 // VertexAccessInstance
422 
VertexAccessInstance(Context & context,Move<VkDevice> device,VkFormat inputFormat,deUint32 numVertexValues,deUint32 numInstanceValues,deUint32 numVertices,deUint32 numInstances,const std::vector<deUint32> & indices)423 VertexAccessInstance::VertexAccessInstance (Context&						context,
424 											Move<VkDevice>					device,
425 											VkFormat						inputFormat,
426 											deUint32						numVertexValues,
427 											deUint32						numInstanceValues,
428 											deUint32						numVertices,
429 											deUint32						numInstances,
430 											const std::vector<deUint32>&	indices)
431 
432 	: vkt::TestInstance			(context)
433 	, m_device					(device)
434 	, m_inputFormat				(inputFormat)
435 	, m_numVertexValues			(numVertexValues)
436 	, m_numInstanceValues		(numInstanceValues)
437 	, m_numVertices				(numVertices)
438 	, m_numInstances			(numInstances)
439 {
440 	const DeviceInterface&		vk						= context.getDeviceInterface();
441 	const deUint32				queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
442 	SimpleAllocator				memAlloc				(vk, *m_device, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
443 	const deUint32				formatSizeInBytes		= tcu::getPixelSize(mapVkFormat(m_inputFormat));
444 
445 	// Check storage support
446 	if (!context.getDeviceFeatures().vertexPipelineStoresAndAtomics)
447 	{
448 		TCU_THROW(NotSupportedError, "Stores not supported in vertex stage");
449 	}
450 
451 	const VkVertexInputAttributeDescription attributes[] =
452 	{
453 		// input rate: vertex
454 		{
455 			0u,								// deUint32 location;
456 			0u,								// deUint32 binding;
457 			m_inputFormat,					// VkFormat format;
458 			0u,								// deUint32 offset;
459 		},
460 		{
461 			1u,								// deUint32 location;
462 			0u,								// deUint32 binding;
463 			m_inputFormat,					// VkFormat format;
464 			formatSizeInBytes,				// deUint32 offset;
465 		},
466 
467 		// input rate: instance
468 		{
469 			2u,								// deUint32 location;
470 			1u,								// deUint32 binding;
471 			m_inputFormat,					// VkFormat format;
472 			0u,								// deUint32 offset;
473 		},
474 
475 		// Attribute for vertex number
476 		{
477 			3u,								// deUint32 location;
478 			2u,								// deUint32 binding;
479 			VK_FORMAT_R32_SINT,				// VkFormat format;
480 			0,								// deUint32 offset;
481 		},
482 	};
483 
484 	const VkVertexInputBindingDescription bindings[] =
485 	{
486 		{
487 			0u,								// deUint32				binding;
488 			formatSizeInBytes * 2,			// deUint32				stride;
489 			VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputRate	inputRate;
490 		},
491 		{
492 			1u,								// deUint32				binding;
493 			formatSizeInBytes,				// deUint32				stride;
494 			VK_VERTEX_INPUT_RATE_INSTANCE	// VkVertexInputRate	inputRate;
495 		},
496 		{
497 			2u,								// deUint32				binding;
498 			sizeof(deInt32),				// deUint32				stride;
499 			VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputRate	inputRate;
500 		},
501 	};
502 
503 	m_vertexInputBindings	= std::vector<VkVertexInputBindingDescription>(bindings, bindings + DE_LENGTH_OF_ARRAY(bindings));
504 	m_vertexInputAttributes	= std::vector<VkVertexInputAttributeDescription>(attributes, attributes + DE_LENGTH_OF_ARRAY(attributes));
505 
506 	// Create vertex buffer for vertex input rate
507 	{
508 		VkMemoryRequirements bufferMemoryReqs;
509 
510 		m_vertexRateBufferSize = getBufferSizeInBytes(m_numVertexValues, m_inputFormat); // All formats used in this test suite are 32-bit based.
511 
512 		const VkBufferCreateInfo	vertexRateBufferParams	=
513 		{
514 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
515 			DE_NULL,									// const void*			pNext;
516 			0u,											// VkBufferCreateFlags	flags;
517 			m_vertexRateBufferSize,						// VkDeviceSize			size;
518 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
519 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
520 			1u,											// deUint32				queueFamilyIndexCount;
521 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
522 		};
523 
524 		m_vertexRateBuffer			= createBuffer(vk, *m_device, &vertexRateBufferParams);
525 		bufferMemoryReqs			= getBufferMemoryRequirements(vk, *m_device, *m_vertexRateBuffer);
526 		m_vertexRateBufferAllocSize	= bufferMemoryReqs.size;
527 		m_vertexRateBufferAlloc		= memAlloc.allocate(bufferMemoryReqs, MemoryRequirement::HostVisible);
528 
529 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_vertexRateBuffer, m_vertexRateBufferAlloc->getMemory(), m_vertexRateBufferAlloc->getOffset()));
530 		populateBufferWithTestValues(m_vertexRateBufferAlloc->getHostPtr(), (deUint32)m_vertexRateBufferAllocSize, m_inputFormat);
531 		flushMappedMemoryRange(vk, *m_device, m_vertexRateBufferAlloc->getMemory(), m_vertexRateBufferAlloc->getOffset(), VK_WHOLE_SIZE);
532 	}
533 
534 	// Create vertex buffer for instance input rate
535 	{
536 		VkMemoryRequirements bufferMemoryReqs;
537 
538 		m_instanceRateBufferSize = getBufferSizeInBytes(m_numInstanceValues, m_inputFormat); // All formats used in this test suite are 32-bit based.
539 
540 		const VkBufferCreateInfo	instanceRateBufferParams	=
541 		{
542 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
543 			DE_NULL,									// const void*			pNext;
544 			0u,											// VkBufferCreateFlags	flags;
545 			m_instanceRateBufferSize,					// VkDeviceSize			size;
546 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
547 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
548 			1u,											// deUint32				queueFamilyIndexCount;
549 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
550 		};
551 
552 		m_instanceRateBuffer			= createBuffer(vk, *m_device, &instanceRateBufferParams);
553 		bufferMemoryReqs				= getBufferMemoryRequirements(vk, *m_device, *m_instanceRateBuffer);
554 		m_instanceRateBufferAllocSize	= bufferMemoryReqs.size;
555 		m_instanceRateBufferAlloc		= memAlloc.allocate(bufferMemoryReqs, MemoryRequirement::HostVisible);
556 
557 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_instanceRateBuffer, m_instanceRateBufferAlloc->getMemory(), m_instanceRateBufferAlloc->getOffset()));
558 		populateBufferWithTestValues(m_instanceRateBufferAlloc->getHostPtr(), (deUint32)m_instanceRateBufferAllocSize, m_inputFormat);
559 		flushMappedMemoryRange(vk, *m_device, m_instanceRateBufferAlloc->getMemory(), m_instanceRateBufferAlloc->getOffset(), VK_WHOLE_SIZE);
560 	}
561 
562 	// Create vertex buffer that stores the vertex number (from 0 to m_numVertices - 1)
563 	{
564 		m_vertexNumBufferSize = 128 * sizeof(deInt32); // Allocate enough device memory for all indices (0 to 127).
565 
566 		const VkBufferCreateInfo	vertexNumBufferParams	=
567 		{
568 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
569 			DE_NULL,									// const void*			pNext;
570 			0u,											// VkBufferCreateFlags	flags;
571 			m_vertexNumBufferSize,						// VkDeviceSize			size;
572 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
573 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
574 			1u,											// deUint32				queueFamilyIndexCount;
575 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
576 		};
577 
578 		m_vertexNumBuffer		= createBuffer(vk, *m_device, &vertexNumBufferParams);
579 		m_vertexNumBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_vertexNumBuffer), MemoryRequirement::HostVisible);
580 
581 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_vertexNumBuffer, m_vertexNumBufferAlloc->getMemory(), m_vertexNumBufferAlloc->getOffset()));
582 	}
583 
584 	// Create index buffer if required
585 	if (!indices.empty())
586 	{
587 		m_indexBufferSize = sizeof(deUint32) * indices.size();
588 
589 		const VkBufferCreateInfo	indexBufferParams	=
590 		{
591 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
592 			DE_NULL,									// const void*			pNext;
593 			0u,											// VkBufferCreateFlags	flags;
594 			m_indexBufferSize,							// VkDeviceSize			size;
595 			VK_BUFFER_USAGE_INDEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
596 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
597 			1u,											// deUint32				queueFamilyIndexCount;
598 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
599 		};
600 
601 		m_indexBuffer		= createBuffer(vk, *m_device, &indexBufferParams);
602 		m_indexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_indexBuffer), MemoryRequirement::HostVisible);
603 
604 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_indexBuffer, m_indexBufferAlloc->getMemory(), m_indexBufferAlloc->getOffset()));
605 		deMemcpy(m_indexBufferAlloc->getHostPtr(), indices.data(), (size_t)m_indexBufferSize);
606 		flushMappedMemoryRange(vk, *m_device, m_indexBufferAlloc->getMemory(), m_indexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
607 	}
608 
609 	// Create result ssbo
610 	{
611 		const int	numChannels	= getNumUsedChannels(mapVkFormat(m_inputFormat).order);
612 
613 		m_outBufferSize = getBufferSizeInBytes(m_numVertices * m_numInstances * numChannels * 3, VK_FORMAT_R32_UINT);
614 
615 		const VkBufferCreateInfo	outBufferParams		=
616 		{
617 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
618 			DE_NULL,									// const void*			pNext;
619 			0u,											// VkBufferCreateFlags	flags;
620 			m_outBufferSize,							// VkDeviceSize			size;
621 			VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,			// VkBufferUsageFlags	usage;
622 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
623 			1u,											// deUint32				queueFamilyIndexCount;
624 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
625 		};
626 
627 		m_outBuffer			= createBuffer(vk, *m_device, &outBufferParams);
628 		m_outBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_outBuffer), MemoryRequirement::HostVisible);
629 
630 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
631 		deMemset(m_outBufferAlloc->getHostPtr(), 0xFF, (size_t)m_outBufferSize);
632 		flushMappedMemoryRange(vk, *m_device, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset(), VK_WHOLE_SIZE);
633 	}
634 
635 	// Create descriptor set data
636 	{
637 		DescriptorPoolBuilder descriptorPoolBuilder;
638 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u);
639 		m_descriptorPool = descriptorPoolBuilder.build(vk, *m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
640 
641 		DescriptorSetLayoutBuilder setLayoutBuilder;
642 		setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT);
643 		m_descriptorSetLayout = setLayoutBuilder.build(vk, *m_device);
644 
645 		const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
646 		{
647 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
648 			DE_NULL,											// const void*					pNext;
649 			*m_descriptorPool,									// VkDescriptorPool				desciptorPool;
650 			1u,													// deUint32						setLayoutCount;
651 			&m_descriptorSetLayout.get()						// const VkDescriptorSetLayout*	pSetLayouts;
652 		};
653 
654 		m_descriptorSet = allocateDescriptorSet(vk, *m_device, &descriptorSetAllocateInfo);
655 
656 		const VkDescriptorBufferInfo outBufferDescriptorInfo	= makeDescriptorBufferInfo(*m_outBuffer, 0ull, VK_WHOLE_SIZE);
657 
658 		DescriptorSetUpdateBuilder setUpdateBuilder;
659 		setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outBufferDescriptorInfo);
660 		setUpdateBuilder.update(vk, *m_device);
661 	}
662 
663 	// Create fence
664 	{
665 		const VkFenceCreateInfo fenceParams =
666 		{
667 			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
668 			DE_NULL,								// const void*			pNext;
669 			0u										// VkFenceCreateFlags	flags;
670 		};
671 
672 		m_fence = createFence(vk, *m_device, &fenceParams);
673 	}
674 
675 	// Get queue
676 	vk.getDeviceQueue(*m_device, queueFamilyIndex, 0, &m_queue);
677 
678 	// Setup graphics test environment
679 	{
680 		GraphicsEnvironment::DrawConfig drawConfig;
681 
682 		drawConfig.vertexBuffers.push_back(*m_vertexRateBuffer);
683 		drawConfig.vertexBuffers.push_back(*m_instanceRateBuffer);
684 		drawConfig.vertexBuffers.push_back(*m_vertexNumBuffer);
685 
686 		drawConfig.vertexCount		= m_numVertices;
687 		drawConfig.instanceCount	= m_numInstances;
688 		drawConfig.indexBuffer		= *m_indexBuffer;
689 		drawConfig.indexCount		= (deUint32)(m_indexBufferSize / sizeof(deUint32));
690 
691 		m_graphicsTestEnvironment	= de::MovePtr<GraphicsEnvironment>(new GraphicsEnvironment(m_context,
692 																							   *m_device,
693 																							   *m_descriptorSetLayout,
694 																							   *m_descriptorSet,
695 																							   GraphicsEnvironment::VertexBindings(bindings, bindings + DE_LENGTH_OF_ARRAY(bindings)),
696 																							   GraphicsEnvironment::VertexAttributes(attributes, attributes + DE_LENGTH_OF_ARRAY(attributes)),
697 																							   drawConfig));
698 	}
699 }
700 
iterate(void)701 tcu::TestStatus VertexAccessInstance::iterate (void)
702 {
703 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
704 	const vk::VkCommandBuffer	cmdBuffer	= m_graphicsTestEnvironment->getCommandBuffer();
705 
706 	// Initialize vertex ids
707 	{
708 		deUint32 *bufferPtr = reinterpret_cast<deUint32*>(m_vertexNumBufferAlloc->getHostPtr());
709 		deMemset(bufferPtr, 0, (size_t)m_vertexNumBufferSize);
710 
711 		initVertexIds(bufferPtr, (size_t)(m_vertexNumBufferSize / sizeof(deUint32)));
712 
713 		flushMappedMemoryRange(vk, *m_device, m_vertexNumBufferAlloc->getMemory(), m_vertexNumBufferAlloc->getOffset(), VK_WHOLE_SIZE);
714 	}
715 
716 	// Submit command buffer
717 	{
718 		const VkSubmitInfo	submitInfo	=
719 		{
720 			VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
721 			DE_NULL,						// const void*					pNext;
722 			0u,								// deUint32						waitSemaphoreCount;
723 			DE_NULL,						// const VkSemaphore*			pWaitSemaphores;
724 			DE_NULL,						// const VkPIpelineStageFlags*	pWaitDstStageMask;
725 			1u,								// deUint32						commandBufferCount;
726 			&cmdBuffer,						// const VkCommandBuffer*		pCommandBuffers;
727 			0u,								// deUint32						signalSemaphoreCount;
728 			DE_NULL							// const VkSemaphore*			pSignalSemaphores;
729 		};
730 
731 		VK_CHECK(vk.resetFences(*m_device, 1, &m_fence.get()));
732 		VK_CHECK(vk.queueSubmit(m_queue, 1, &submitInfo, *m_fence));
733 		VK_CHECK(vk.waitForFences(*m_device, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
734 	}
735 
736 	// Prepare result buffer for read
737 	{
738 		const VkMappedMemoryRange	outBufferRange	=
739 		{
740 			VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	//  VkStructureType	sType;
741 			DE_NULL,								//  const void*		pNext;
742 			m_outBufferAlloc->getMemory(),			//  VkDeviceMemory	mem;
743 			0ull,									//  VkDeviceSize	offset;
744 			m_outBufferSize,						//  VkDeviceSize	size;
745 		};
746 
747 		VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange));
748 	}
749 
750 	if (verifyResult())
751 		return tcu::TestStatus::pass("All values OK");
752 	else
753 		return tcu::TestStatus::fail("Invalid value(s) found");
754 }
755 
verifyResult(void)756 bool VertexAccessInstance::verifyResult (void)
757 {
758 	std::ostringstream			logMsg;
759 	const DeviceInterface&		vk						= m_context.getDeviceInterface();
760 	tcu::TestLog&				log						= m_context.getTestContext().getLog();
761 	const deUint32				numChannels				= getNumUsedChannels(mapVkFormat(m_inputFormat).order);
762 	const deUint32				numScalarsPerVertex		= numChannels * 3; // Use 3 identical attributes
763 	void*						outDataPtr				= m_outBufferAlloc->getHostPtr();
764 	const deUint32				outValueSize			= sizeof(deUint32);
765 	bool						allOk					= true;
766 
767 	const VkMappedMemoryRange	outBufferRange			=
768 	{
769 		VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	// VkStructureType	sType;
770 		DE_NULL,								// const void*		pNext;
771 		m_outBufferAlloc->getMemory(),			// VkDeviceMemory	mem;
772 		m_outBufferAlloc->getOffset(),			// VkDeviceSize		offset;
773 		m_outBufferSize,						// VkDeviceSize		size;
774 	};
775 
776 	VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange));
777 
778 	for (deUint32 valueNdx = 0; valueNdx < m_outBufferSize / outValueSize; valueNdx++)
779 	{
780 		deUint32			numInBufferValues;
781 		void*				inBufferPtr;
782 		VkDeviceSize		inBufferAllocSize;
783 		deUint32			inBufferValueIndex;
784 		bool				isOutOfBoundsAccess		= false;
785 		const deUint32		attributeIndex			= (valueNdx / numChannels) % 3;
786 		const deUint32*		outValuePtr				= (deUint32*)outDataPtr + valueNdx;
787 
788 		if (attributeIndex == 2)
789 		{
790 			// Instance rate
791 			const deUint32	elementIndex	= valueNdx / (numScalarsPerVertex * m_numVertices); // instance id
792 
793 			numInBufferValues	= m_numInstanceValues;
794 			inBufferPtr			= m_instanceRateBufferAlloc->getHostPtr();
795 			inBufferAllocSize	= m_instanceRateBufferAllocSize;
796 			inBufferValueIndex	= (elementIndex * numChannels) + (valueNdx % numScalarsPerVertex) - (2 * numChannels);
797 		}
798 		else
799 		{
800 			// Vertex rate
801 			const deUint32	vertexNdx		= valueNdx / numScalarsPerVertex;
802 			const deUint32	instanceNdx		= vertexNdx / m_numVertices;
803 			const deUint32	elementIndex	= valueNdx / numScalarsPerVertex; // vertex id
804 
805 			numInBufferValues	= m_numVertexValues;
806 			inBufferPtr			= m_vertexRateBufferAlloc->getHostPtr();
807 			inBufferAllocSize	= m_vertexRateBufferAllocSize;
808 			inBufferValueIndex	= (getIndex(elementIndex) * (numChannels * 2)) + (valueNdx % numScalarsPerVertex) - instanceNdx * (m_numVertices * numChannels * 2);
809 
810 			// 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.
811 			if ((attributeIndex == 0) && (numInBufferValues >= numChannels))
812 				numInBufferValues -= numChannels;
813 		}
814 
815 		isOutOfBoundsAccess	= (inBufferValueIndex >= numInBufferValues);
816 
817 		const deInt32		distanceToOutOfBounds	= (deInt32)outValueSize * ((deInt32)numInBufferValues - (deInt32)inBufferValueIndex);
818 
819 		if (!isOutOfBoundsAccess && (distanceToOutOfBounds < 16))
820 			isOutOfBoundsAccess = (((inBufferValueIndex / numChannels) + 1) * numChannels > numInBufferValues);
821 
822 		// Log value information
823 		{
824 			// Vertex separator
825 			if (valueNdx && valueNdx % numScalarsPerVertex == 0)
826 				logMsg << "\n";
827 
828 			logMsg << "\n" << valueNdx << ": Value ";
829 
830 			// Result index and value
831 			if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
832 				logValue(logMsg, outValuePtr, VK_FORMAT_R32_SFLOAT, 4);
833 			else
834 				logValue(logMsg, outValuePtr, m_inputFormat, 4);
835 
836 			// Attribute name
837 			logMsg << "\tfrom attr" << attributeIndex;
838 			if (numChannels > 1)
839 				logMsg << "[" << valueNdx % numChannels << "]";
840 
841 			// Input rate
842 			if (attributeIndex == 2)
843 				logMsg << "\tinstance rate";
844 			else
845 				logMsg << "\tvertex rate";
846 		}
847 
848 		if (isOutOfBoundsAccess)
849 		{
850 			const bool isValidValue = isValueWithinVertexBufferOrZero(inBufferPtr, inBufferAllocSize, outValuePtr, inBufferValueIndex);
851 
852 			logMsg << "\t(out of bounds)";
853 
854 			if (!isValidValue)
855 			{
856 				// Check if we are satisfying the [0, 0, 0, x] pattern, where x may be either 0 or 1,
857 				// or the maximum representable positive integer value (if the format is integer-based).
858 
859 				const bool	canMatchVec4Pattern	= ((valueNdx % numChannels == 3) || m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32);
860 				bool		matchesVec4Pattern	= false;
861 
862 				if (canMatchVec4Pattern)
863 				{
864 					if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
865 						matchesVec4Pattern	=  verifyOutOfBoundsVec4(outValuePtr, m_inputFormat);
866 					else
867 						matchesVec4Pattern	=  verifyOutOfBoundsVec4(outValuePtr - 3, m_inputFormat);
868 				}
869 
870 				if (!canMatchVec4Pattern || !matchesVec4Pattern)
871 				{
872 					logMsg << ", Failed: expected a value within the buffer range or 0";
873 
874 					if (canMatchVec4Pattern)
875 						logMsg << ", or the [0, 0, 0, x] pattern";
876 
877 					allOk = false;
878 				}
879 			}
880 		}
881 		else if (!isExpectedValueFromVertexBuffer(inBufferPtr, inBufferValueIndex, m_inputFormat, outValuePtr))
882 		{
883 			logMsg << ", Failed: unexpected value";
884 			allOk = false;
885 		}
886 	}
887 	log << tcu::TestLog::Message << logMsg.str() << tcu::TestLog::EndMessage;
888 
889 	return allOk;
890 }
891 
isValueWithinVertexBufferOrZero(void * vertexBuffer,VkDeviceSize vertexBufferSize,const void * value,deUint32 valueIndex)892 bool VertexAccessInstance::isValueWithinVertexBufferOrZero(void* vertexBuffer, VkDeviceSize vertexBufferSize, const void* value, deUint32 valueIndex)
893 {
894 	if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
895 	{
896 		const float		normValue		= *reinterpret_cast<const float*>(value);
897 		const deUint32	scalarIndex		= valueIndex % 4;
898 		const bool		isAlpha			= (scalarIndex == 3);
899 		deUint32		encodedValue;
900 
901 		if (isAlpha)
902 			encodedValue = deMin32(deUint32(deFloatRound(normValue * 0x3u)), 0x3u);
903 		else
904 			encodedValue = deMin32(deUint32(deFloatRound(normValue * 0x3FFu)), 0x3FFu);
905 
906 		if (encodedValue == 0)
907 			return true;
908 
909 		for (deUint32 i = 0; i < vertexBufferSize / 4; i++)
910 		{
911 			const deUint32	packedValue		= reinterpret_cast<deUint32*>(vertexBuffer)[i];
912 			deUint32		unpackedValue;
913 
914 			if (scalarIndex < 3)
915 				unpackedValue = (packedValue >> (10 * scalarIndex)) & 0x3FFu;
916 			else
917 				unpackedValue = (packedValue >> 30) & 0x3u;
918 
919 			if (unpackedValue == encodedValue)
920 				return true;
921 		}
922 
923 		return false;
924 	}
925 	else
926 	{
927 		return isValueWithinBufferOrZero(vertexBuffer, vertexBufferSize, value, sizeof(deUint32));
928 	}
929 }
930 
isExpectedValueFromVertexBuffer(const void * vertexBuffer,deUint32 vertexIndex,VkFormat vertexFormat,const void * value)931 bool VertexAccessInstance::isExpectedValueFromVertexBuffer (const void* vertexBuffer, deUint32 vertexIndex, VkFormat vertexFormat, const void* value)
932 {
933 	if (isUintFormat(vertexFormat))
934 	{
935 		const deUint32* bufferPtr = reinterpret_cast<const deUint32*>(vertexBuffer);
936 
937 		return bufferPtr[vertexIndex] == *reinterpret_cast<const deUint32 *>(value);
938 	}
939 	else if (isIntFormat(vertexFormat))
940 	{
941 		const deInt32* bufferPtr = reinterpret_cast<const deInt32*>(vertexBuffer);
942 
943 		return bufferPtr[vertexIndex] == *reinterpret_cast<const deInt32 *>(value);
944 	}
945 	else if (isFloatFormat(vertexFormat))
946 	{
947 		const float* bufferPtr = reinterpret_cast<const float*>(vertexBuffer);
948 
949 		return areEqual(bufferPtr[vertexIndex], *reinterpret_cast<const float *>(value));
950 	}
951 	else if (vertexFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
952 	{
953 		const deUint32*	bufferPtr		= reinterpret_cast<const deUint32*>(vertexBuffer);
954 		const deUint32	packedValue		= bufferPtr[vertexIndex / 4];
955 		const deUint32	scalarIndex		= vertexIndex % 4;
956 		float			normValue;
957 
958 		if (scalarIndex < 3)
959 			normValue = float((packedValue >> (10 * scalarIndex)) & 0x3FFu) / 0x3FFu;
960 		else
961 			normValue = float(packedValue >> 30) / 0x3u;
962 
963 		return areEqual(normValue, *reinterpret_cast<const float *>(value));
964 	}
965 
966 	DE_ASSERT(false);
967 	return false;
968 }
969 
getBufferSizeInBytes(deUint32 numScalars,VkFormat format)970 VkDeviceSize VertexAccessInstance::getBufferSizeInBytes (deUint32 numScalars, VkFormat format)
971 {
972 	if (isUintFormat(format) || isIntFormat(format) || isFloatFormat(format))
973 	{
974 		return numScalars * 4;
975 	}
976 	else if (format == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
977 	{
978 		DE_ASSERT(numScalars % 4 == 0);
979 		return numScalars;
980 	}
981 
982 	DE_ASSERT(false);
983 	return 0;
984 }
985 
986 // DrawAccessInstance
987 
DrawAccessInstance(Context & context,Move<VkDevice> device,VkFormat inputFormat,deUint32 numVertexValues,deUint32 numInstanceValues,deUint32 numVertices,deUint32 numInstances)988 DrawAccessInstance::DrawAccessInstance (Context&				context,
989 										Move<VkDevice>			device,
990 										VkFormat				inputFormat,
991 										deUint32				numVertexValues,
992 										deUint32				numInstanceValues,
993 										deUint32				numVertices,
994 										deUint32				numInstances)
995 	: VertexAccessInstance (context,
996 							device,
997 							inputFormat,
998 							numVertexValues,
999 							numInstanceValues,
1000 							numVertices,
1001 							numInstances,
1002 							std::vector<deUint32>()) // No index buffer
1003 {
1004 }
1005 
initVertexIds(deUint32 * indicesPtr,size_t indexCount)1006 void DrawAccessInstance::initVertexIds (deUint32 *indicesPtr, size_t indexCount)
1007 {
1008 	for (deUint32 i = 0; i < indexCount; i++)
1009 		indicesPtr[i] = i;
1010 }
1011 
getIndex(deUint32 vertexNum) const1012 deUint32 DrawAccessInstance::getIndex (deUint32 vertexNum) const
1013 {
1014 	return vertexNum;
1015 }
1016 
1017 // DrawIndexedAccessInstance
1018 
DrawIndexedAccessInstance(Context & context,Move<VkDevice> device,VkFormat inputFormat,deUint32 numVertexValues,deUint32 numInstanceValues,deUint32 numVertices,deUint32 numInstances,const std::vector<deUint32> & indices)1019 DrawIndexedAccessInstance::DrawIndexedAccessInstance (Context&						context,
1020 													  Move<VkDevice>				device,
1021 													  VkFormat						inputFormat,
1022 													  deUint32						numVertexValues,
1023 													  deUint32						numInstanceValues,
1024 													  deUint32						numVertices,
1025 													  deUint32						numInstances,
1026 													  const std::vector<deUint32>&	indices)
1027 	: VertexAccessInstance	(context,
1028 							 device,
1029 							 inputFormat,
1030 							 numVertexValues,
1031 							 numInstanceValues,
1032 							 numVertices,
1033 							 numInstances,
1034 							 indices)
1035 	, m_indices				(indices)
1036 {
1037 }
1038 
initVertexIds(deUint32 * indicesPtr,size_t indexCount)1039 void DrawIndexedAccessInstance::initVertexIds (deUint32 *indicesPtr, size_t indexCount)
1040 {
1041 	DE_UNREF(indexCount);
1042 
1043 	for (deUint32 i = 0; i < m_indices.size(); i++)
1044 	{
1045 		DE_ASSERT(m_indices[i] < indexCount);
1046 
1047 		indicesPtr[m_indices[i]] = i;
1048 	}
1049 }
1050 
getIndex(deUint32 vertexNum) const1051 deUint32 DrawIndexedAccessInstance::getIndex (deUint32 vertexNum) const
1052 {
1053 	DE_ASSERT(vertexNum < (deUint32)m_indices.size());
1054 
1055 	return m_indices[vertexNum];
1056 }
1057 
1058 // Test node creation functions
1059 
createDrawTests(tcu::TestContext & testCtx,VkFormat format)1060 static tcu::TestCaseGroup* createDrawTests (tcu::TestContext& testCtx, VkFormat format)
1061 {
1062 	struct TestConfig
1063 	{
1064 		std::string		name;
1065 		std::string		description;
1066 		VkFormat		inputFormat;
1067 		deUint32		numVertexValues;
1068 		deUint32		numInstanceValues;
1069 		deUint32		numVertices;
1070 		deUint32		numInstances;
1071 	};
1072 
1073 	const deUint32 numChannels = getNumUsedChannels(mapVkFormat(format).order);
1074 
1075 	const TestConfig testConfigs[] =
1076 	{
1077 		// name						description											format	numVertexValues			numInstanceValues	numVertices		numInstances
1078 		{ "vertex_out_of_bounds",	"Create data for 6 vertices, draw 9 vertices",		format,	numChannels * 2 * 6,	numChannels,		9,				1	 },
1079 		{ "vertex_incomplete",		"Create data for half a vertex, draw 3 vertices",	format,	numChannels,			numChannels,		3,				1	 },
1080 		{ "instance_out_of_bounds", "Create data for 1 instance, draw 3 instances",		format,	numChannels * 2 * 9,	numChannels,		3,				3	 },
1081 	};
1082 
1083 	de::MovePtr<tcu::TestCaseGroup>	drawTests (new tcu::TestCaseGroup(testCtx, "draw", ""));
1084 
1085 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(testConfigs); i++)
1086 	{
1087 		const TestConfig &config = testConfigs[i];
1088 
1089 		drawTests->addChild(new DrawAccessTest(testCtx, config.name, config.description, config.inputFormat,
1090 											   config.numVertexValues, config.numInstanceValues,
1091 											   config.numVertices, config.numInstances));
1092 	}
1093 
1094 	return drawTests.release();
1095 }
1096 
createDrawIndexedTests(tcu::TestContext & testCtx,VkFormat format)1097 static tcu::TestCaseGroup* createDrawIndexedTests (tcu::TestContext& testCtx, VkFormat format)
1098 {
1099 	struct TestConfig
1100 	{
1101 		std::string							name;
1102 		std::string							description;
1103 		VkFormat							inputFormat;
1104 		DrawIndexedAccessTest::IndexConfig	indexConfig;
1105 	};
1106 
1107 	const TestConfig testConfigs[] =
1108 	{
1109 		// name							description								format		indexConfig
1110 		{ "last_index_out_of_bounds",	"Only last index is out of bounds",		format,		DrawIndexedAccessTest::INDEX_CONFIG_LAST_INDEX_OUT_OF_BOUNDS },
1111 		{ "indices_out_of_bounds",		"Random indices out of bounds",			format,		DrawIndexedAccessTest::INDEX_CONFIG_INDICES_OUT_OF_BOUNDS },
1112 		{ "triangle_out_of_bounds",		"First triangle is out of bounds",		format,		DrawIndexedAccessTest::INDEX_CONFIG_TRIANGLE_OUT_OF_BOUNDS },
1113 	};
1114 
1115 	de::MovePtr<tcu::TestCaseGroup>	drawTests (new tcu::TestCaseGroup(testCtx, "draw_indexed", ""));
1116 
1117 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(testConfigs); i++)
1118 	{
1119 		const TestConfig &config = testConfigs[i];
1120 
1121 		drawTests->addChild(new DrawIndexedAccessTest(testCtx, config.name, config.description, config.inputFormat, config.indexConfig));
1122 	}
1123 
1124 	return drawTests.release();
1125 }
1126 
addVertexFormatTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * parentGroup)1127 static void addVertexFormatTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup)
1128 {
1129 	const VkFormat vertexFormats[] =
1130 	{
1131 		VK_FORMAT_R32_UINT,
1132 		VK_FORMAT_R32_SINT,
1133 		VK_FORMAT_R32_SFLOAT,
1134 		VK_FORMAT_R32G32_UINT,
1135 		VK_FORMAT_R32G32_SINT,
1136 		VK_FORMAT_R32G32_SFLOAT,
1137 		VK_FORMAT_R32G32B32_UINT,
1138 		VK_FORMAT_R32G32B32_SINT,
1139 		VK_FORMAT_R32G32B32_SFLOAT,
1140 		VK_FORMAT_R32G32B32A32_UINT,
1141 		VK_FORMAT_R32G32B32A32_SINT,
1142 		VK_FORMAT_R32G32B32A32_SFLOAT,
1143 
1144 		VK_FORMAT_A2B10G10R10_UNORM_PACK32
1145 	};
1146 
1147 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(vertexFormats); i++)
1148 	{
1149 		const std::string				formatName	= getFormatName(vertexFormats[i]);
1150 		de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx, de::toLower(formatName.substr(10)).c_str(), ""));
1151 
1152 		formatGroup->addChild(createDrawTests(testCtx, vertexFormats[i]));
1153 		formatGroup->addChild(createDrawIndexedTests(testCtx, vertexFormats[i]));
1154 
1155 		parentGroup->addChild(formatGroup.release());
1156 	}
1157 }
1158 
createVertexAccessTests(tcu::TestContext & testCtx)1159 tcu::TestCaseGroup* createVertexAccessTests (tcu::TestContext& testCtx)
1160 {
1161 	de::MovePtr<tcu::TestCaseGroup> vertexAccessTests	(new tcu::TestCaseGroup(testCtx, "vertex_access", ""));
1162 
1163 	addVertexFormatTests(testCtx, vertexAccessTests.get());
1164 
1165 	return vertexAccessTests.release();
1166 }
1167 
1168 } // robustness
1169 } // vkt
1170