• 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 buffer access tests for uniform/storage buffers and
23  *        uniform/storage texel buffers.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktRobustnessBufferAccessTests.hpp"
27 #include "vktRobustnessUtil.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vkBuilderUtil.hpp"
30 #include "vkImageUtil.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 
38 #include <limits>
39 #include <sstream>
40 
41 namespace vkt
42 {
43 namespace robustness
44 {
45 
46 using namespace vk;
47 
48 enum ShaderType
49 {
50 	SHADER_TYPE_MATRIX_COPY,
51 	SHADER_TYPE_VECTOR_COPY,
52 	SHADER_TYPE_SCALAR_COPY,
53 	SHADER_TYPE_TEXEL_COPY,
54 
55 	SHADER_TYPE_COUNT
56 };
57 
58 enum BufferAccessType
59 {
60 	BUFFER_ACCESS_TYPE_READ,
61 	BUFFER_ACCESS_TYPE_READ_FROM_STORAGE,
62 	BUFFER_ACCESS_TYPE_WRITE,
63 };
64 
min(VkDeviceSize a,VkDeviceSize b)65 static VkDeviceSize min (VkDeviceSize a, VkDeviceSize b)
66 {
67 	return (a < b) ? a : b;
68 }
69 
70 class RobustBufferAccessTest : public vkt::TestCase
71 {
72 public:
73 	static const deUint32		s_testArraySize;
74 	static const deUint32		s_numberOfBytesAccessed;
75 
76 								RobustBufferAccessTest		(tcu::TestContext&		testContext,
77 															 const std::string&		name,
78 															 const std::string&		description,
79 															 VkShaderStageFlags		shaderStage,
80 															 ShaderType				shaderType,
81 															 VkFormat				bufferFormat);
82 
~RobustBufferAccessTest(void)83 	virtual						~RobustBufferAccessTest		(void) {}
84 
85 	virtual void				checkSupport				(Context& context) const;
86 
87 private:
88 	static void					genBufferShaderAccess		(ShaderType				shaderType,
89 															 VkFormat				bufferFormat,
90 															 bool					readFromStorage,
91 															 std::ostringstream&	bufferDefinition,
92 															 std::ostringstream&	bufferUse);
93 
94 	static void					genTexelBufferShaderAccess	(VkFormat				bufferFormat,
95 															 std::ostringstream&	bufferDefinition,
96 															 std::ostringstream&	bufferUse,
97 															 bool					readFromStorage);
98 
99 protected:
100 	static void					initBufferAccessPrograms	(SourceCollections&		programCollection,
101 															 VkShaderStageFlags		shaderStage,
102 															 ShaderType				shaderType,
103 															 VkFormat				bufferFormat,
104 															 bool					readFromStorage);
105 
106 	const VkShaderStageFlags	m_shaderStage;
107 	const ShaderType			m_shaderType;
108 	const VkFormat				m_bufferFormat;
109 };
110 
111 class RobustBufferReadTest : public RobustBufferAccessTest
112 {
113 public:
114 								RobustBufferReadTest		(tcu::TestContext&		testContext,
115 															 const std::string&		name,
116 															 const std::string&		description,
117 															 VkShaderStageFlags		shaderStage,
118 															 ShaderType				shaderType,
119 															 VkFormat				bufferFormat,
120 															 VkDeviceSize			readAccessRange,
121 															 bool					readFromStorage,
122 															 bool					accessOutOfBackingMemory);
123 
~RobustBufferReadTest(void)124 	virtual						~RobustBufferReadTest		(void) {}
125 
126 	virtual void				initPrograms				(SourceCollections& programCollection) const;
127 	virtual TestInstance*		createInstance				(Context& context) const;
128 
129 private:
130 	const bool					m_readFromStorage;
131 	const VkDeviceSize			m_readAccessRange;
132 	const bool					m_accessOutOfBackingMemory;
133 };
134 
135 class RobustBufferWriteTest : public RobustBufferAccessTest
136 {
137 public:
138 								RobustBufferWriteTest		(tcu::TestContext&		testContext,
139 															 const std::string&		name,
140 															 const std::string&		description,
141 															 VkShaderStageFlags		shaderStage,
142 															 ShaderType				shaderType,
143 															 VkFormat				bufferFormat,
144 															 VkDeviceSize			writeAccessRange,
145 															 bool					accessOutOfBackingMemory);
146 
~RobustBufferWriteTest(void)147 	virtual						~RobustBufferWriteTest		(void) {}
148 
149 	virtual void				initPrograms				(SourceCollections& programCollection) const;
150 	virtual TestInstance*		createInstance				(Context& context) const;
151 
152 private:
153 	const VkDeviceSize			m_writeAccessRange;
154 	const bool					m_accessOutOfBackingMemory;
155 };
156 
157 class BufferAccessInstance : public vkt::TestInstance
158 {
159 public:
160 									BufferAccessInstance			(Context&			context,
161 																	 Move<VkDevice>		device,
162 																	 ShaderType			shaderType,
163 																	 VkShaderStageFlags	shaderStage,
164 																	 VkFormat			bufferFormat,
165 																	 BufferAccessType	bufferAccessType,
166 																	 VkDeviceSize		inBufferAccessRange,
167 																	 VkDeviceSize		outBufferAccessRange,
168 																	 bool				accessOutOfBackingMemory);
169 
~BufferAccessInstance(void)170 	virtual							~BufferAccessInstance			(void) {}
171 
172 	virtual tcu::TestStatus			iterate							(void);
173 
174 	virtual bool					verifyResult					(void);
175 
176 private:
177 	bool							isExpectedValueFromInBuffer		(VkDeviceSize offsetInBytes, const void* valuePtr, VkDeviceSize valueSize);
178 	bool							isOutBufferValueUnchanged		(VkDeviceSize offsetInBytes, VkDeviceSize valueSize);
179 
180 protected:
181 	Move<VkDevice>					m_device;
182 	de::MovePtr<TestEnvironment>	m_testEnvironment;
183 
184 	const ShaderType				m_shaderType;
185 	const VkShaderStageFlags		m_shaderStage;
186 
187 	const VkFormat					m_bufferFormat;
188 	const BufferAccessType			m_bufferAccessType;
189 
190 	const VkDeviceSize				m_inBufferAccessRange;
191 	Move<VkBuffer>					m_inBuffer;
192 	de::MovePtr<Allocation>			m_inBufferAlloc;
193 	VkDeviceSize					m_inBufferAllocSize;
194 	VkDeviceSize					m_inBufferMaxAccessRange;
195 
196 	const VkDeviceSize				m_outBufferAccessRange;
197 	Move<VkBuffer>					m_outBuffer;
198 	de::MovePtr<Allocation>			m_outBufferAlloc;
199 	VkDeviceSize					m_outBufferAllocSize;
200 	VkDeviceSize					m_outBufferMaxAccessRange;
201 
202 	Move<VkBuffer>					m_indicesBuffer;
203 	de::MovePtr<Allocation>			m_indicesBufferAlloc;
204 
205 	Move<VkDescriptorPool>			m_descriptorPool;
206 	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
207 	Move<VkDescriptorSet>			m_descriptorSet;
208 
209 	Move<VkFence>					m_fence;
210 	VkQueue							m_queue;
211 
212 	// Used when m_shaderStage == VK_SHADER_STAGE_VERTEX_BIT
213 	Move<VkBuffer>					m_vertexBuffer;
214 	de::MovePtr<Allocation>			m_vertexBufferAlloc;
215 
216 	// Used when m_shaderType == SHADER_TYPE_TEXEL_COPY
217 	Move<VkBufferView>				m_inTexelBufferView;
218 	Move<VkBufferView>				m_outTexelBufferView;
219 
220 	const bool						m_accessOutOfBackingMemory;
221 };
222 
223 class BufferReadInstance: public BufferAccessInstance
224 {
225 public:
226 									BufferReadInstance			(Context&				context,
227 																 Move<VkDevice>			device,
228 																 ShaderType				shaderType,
229 																 VkShaderStageFlags		shaderStage,
230 																 VkFormat				bufferFormat,
231 																 bool					readFromStorage,
232 																 VkDeviceSize			inBufferAccessRange,
233 																 bool					accessOutOfBackingMemory);
234 
~BufferReadInstance(void)235 	virtual							~BufferReadInstance			(void) {}
236 
237 private:
238 };
239 
240 class BufferWriteInstance: public BufferAccessInstance
241 {
242 public:
243 									BufferWriteInstance			(Context&				context,
244 																 Move<VkDevice>			device,
245 																 ShaderType				shaderType,
246 																 VkShaderStageFlags		shaderStage,
247 																 VkFormat				bufferFormat,
248 																 VkDeviceSize			writeBufferAccessRange,
249 																 bool					accessOutOfBackingMemory);
250 
~BufferWriteInstance(void)251 	virtual							~BufferWriteInstance		(void) {}
252 };
253 
254 // RobustBufferAccessTest
255 
256 const deUint32 RobustBufferAccessTest::s_testArraySize = 1024;
257 const deUint32 RobustBufferAccessTest::s_numberOfBytesAccessed	= (deUint32)(16 * sizeof(float)); // size of mat4
258 
RobustBufferAccessTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkShaderStageFlags shaderStage,ShaderType shaderType,VkFormat bufferFormat)259 RobustBufferAccessTest::RobustBufferAccessTest (tcu::TestContext&		testContext,
260 												const std::string&		name,
261 												const std::string&		description,
262 												VkShaderStageFlags		shaderStage,
263 												ShaderType				shaderType,
264 												VkFormat				bufferFormat)
265 	: vkt::TestCase		(testContext, name, description)
266 	, m_shaderStage		(shaderStage)
267 	, m_shaderType		(shaderType)
268 	, m_bufferFormat	(bufferFormat)
269 {
270 	DE_ASSERT(m_shaderStage == VK_SHADER_STAGE_VERTEX_BIT || m_shaderStage == VK_SHADER_STAGE_FRAGMENT_BIT || m_shaderStage == VK_SHADER_STAGE_COMPUTE_BIT);
271 }
272 
checkSupport(Context & context) const273 void RobustBufferAccessTest::checkSupport(Context& context) const
274 {
275 	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getDeviceFeatures().robustBufferAccess)
276 		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: robustBufferAccess not supported by this implementation");
277 }
278 
genBufferShaderAccess(ShaderType shaderType,VkFormat bufferFormat,bool readFromStorage,std::ostringstream & bufferDefinition,std::ostringstream & bufferUse)279 void RobustBufferAccessTest::genBufferShaderAccess (ShaderType			shaderType,
280 												    VkFormat			bufferFormat,
281 												    bool				readFromStorage,
282 												    std::ostringstream&	bufferDefinition,
283 												    std::ostringstream&	bufferUse)
284 {
285 	if (isFloatFormat(bufferFormat))
286 	{
287 		bufferDefinition <<
288 			"layout(binding = 0, " << (readFromStorage ? "std430" : "std140") << ") " << (readFromStorage ? "buffer" : "uniform") << " InBuffer\n"
289 			"{\n"
290 			"	mat4 inMatrix[" << s_testArraySize << "];\n"
291 			"};\n\n";
292 
293 		bufferDefinition <<
294 			"layout(binding = 1, std430) buffer OutBuffer\n"
295 			"{\n"
296 			"	mat4 outMatrix[" << s_testArraySize << "];\n"
297 			"};\n\n";
298 
299 		bufferDefinition <<
300 			"layout(binding = 2, std140) uniform Indices\n"
301 			"{\n"
302 			"	int inIndex;\n"
303 			"	int outIndex;\n"
304 			"};\n\n";
305 
306 		switch (shaderType)
307 		{
308 			case SHADER_TYPE_MATRIX_COPY:
309 				bufferUse <<
310 					"	mat4 tmp = inMatrix[inIndex];\n"
311 					"	outMatrix[outIndex] = tmp;\n";
312 				break;
313 
314 			case SHADER_TYPE_VECTOR_COPY:
315 				bufferUse <<
316 					"	outMatrix[outIndex][0] = inMatrix[inIndex][0];\n"
317 					"	outMatrix[outIndex][1] = inMatrix[inIndex][1];\n"
318 					"	outMatrix[outIndex][2] = inMatrix[inIndex][2];\n"
319 					"	outMatrix[outIndex][3] = inMatrix[inIndex][3];\n";
320 				break;
321 
322 			case SHADER_TYPE_SCALAR_COPY:
323 				bufferUse <<
324 					"	outMatrix[outIndex][0][0] = inMatrix[inIndex][0][0];\n"
325 					"	outMatrix[outIndex][0][1] = inMatrix[inIndex][0][1];\n"
326 					"	outMatrix[outIndex][0][2] = inMatrix[inIndex][0][2];\n"
327 					"	outMatrix[outIndex][0][3] = inMatrix[inIndex][0][3];\n"
328 
329 					"	outMatrix[outIndex][1][0] = inMatrix[inIndex][1][0];\n"
330 					"	outMatrix[outIndex][1][1] = inMatrix[inIndex][1][1];\n"
331 					"	outMatrix[outIndex][1][2] = inMatrix[inIndex][1][2];\n"
332 					"	outMatrix[outIndex][1][3] = inMatrix[inIndex][1][3];\n"
333 
334 					"	outMatrix[outIndex][2][0] = inMatrix[inIndex][2][0];\n"
335 					"	outMatrix[outIndex][2][1] = inMatrix[inIndex][2][1];\n"
336 					"	outMatrix[outIndex][2][2] = inMatrix[inIndex][2][2];\n"
337 					"	outMatrix[outIndex][2][3] = inMatrix[inIndex][2][3];\n"
338 
339 					"	outMatrix[outIndex][3][0] = inMatrix[inIndex][3][0];\n"
340 					"	outMatrix[outIndex][3][1] = inMatrix[inIndex][3][1];\n"
341 					"	outMatrix[outIndex][3][2] = inMatrix[inIndex][3][2];\n"
342 					"	outMatrix[outIndex][3][3] = inMatrix[inIndex][3][3];\n";
343 				break;
344 
345 			default:
346 				DE_ASSERT(false);
347 		}
348 	}
349 	else
350 	{
351 		std::string typePrefixStr;
352 
353 		if (isUintFormat(bufferFormat))
354 		{
355 			typePrefixStr = "u";
356 		}
357 		else if (isIntFormat(bufferFormat))
358 		{
359 			typePrefixStr =  "i";
360 		}
361 		else
362 		{
363 			DE_ASSERT(false);
364 		}
365 
366 		typePrefixStr += (bufferFormat == vk::VK_FORMAT_R64_UINT || bufferFormat == vk::VK_FORMAT_R64_SINT) ?
367 						 "64" : "";
368 
369 		bufferDefinition <<
370 			"layout(binding = 0, " << (readFromStorage ? "std430" : "std140") << ") " << (readFromStorage ? "buffer readonly" : "uniform") << " InBuffer\n"
371 			"{\n"
372 			"	" << typePrefixStr << "vec4 inVecs[" << s_testArraySize << "][4];\n"
373 			"};\n\n";
374 
375 		bufferDefinition <<
376 			"layout(binding = 1, std430) buffer OutBuffer\n"
377 			"{\n"
378 			"	" << typePrefixStr << "vec4 outVecs[" << s_testArraySize << "][4];\n"
379 			"};\n\n";
380 
381 		bufferDefinition <<
382 			"layout(binding = 2, std140) uniform Indices\n"
383 			"{\n"
384 			"	int inIndex;\n"
385 			"	int outIndex;\n"
386 			"};\n\n";
387 
388 		switch (shaderType)
389 		{
390 			case SHADER_TYPE_MATRIX_COPY:
391 				// Shader type not supported for integer types.
392 				DE_ASSERT(false);
393 				break;
394 
395 			case SHADER_TYPE_VECTOR_COPY:
396 				bufferUse <<
397 					"	outVecs[outIndex][0] = inVecs[inIndex][0];\n"
398 					"	outVecs[outIndex][1] = inVecs[inIndex][1];\n"
399 					"	outVecs[outIndex][2] = inVecs[inIndex][2];\n"
400 					"	outVecs[outIndex][3] = inVecs[inIndex][3];\n";
401 				break;
402 
403 			case SHADER_TYPE_SCALAR_COPY:
404 				bufferUse <<
405 					"	outVecs[outIndex][0][0] = inVecs[inIndex][0][0];\n"
406 					"	outVecs[outIndex][0][1] = inVecs[inIndex][0][1];\n"
407 					"	outVecs[outIndex][0][2] = inVecs[inIndex][0][2];\n"
408 					"	outVecs[outIndex][0][3] = inVecs[inIndex][0][3];\n"
409 
410 					"	outVecs[outIndex][1][0] = inVecs[inIndex][1][0];\n"
411 					"	outVecs[outIndex][1][1] = inVecs[inIndex][1][1];\n"
412 					"	outVecs[outIndex][1][2] = inVecs[inIndex][1][2];\n"
413 					"	outVecs[outIndex][1][3] = inVecs[inIndex][1][3];\n"
414 
415 					"	outVecs[outIndex][2][0] = inVecs[inIndex][2][0];\n"
416 					"	outVecs[outIndex][2][1] = inVecs[inIndex][2][1];\n"
417 					"	outVecs[outIndex][2][2] = inVecs[inIndex][2][2];\n"
418 					"	outVecs[outIndex][2][3] = inVecs[inIndex][2][3];\n"
419 
420 					"	outVecs[outIndex][3][0] = inVecs[inIndex][3][0];\n"
421 					"	outVecs[outIndex][3][1] = inVecs[inIndex][3][1];\n"
422 					"	outVecs[outIndex][3][2] = inVecs[inIndex][3][2];\n"
423 					"	outVecs[outIndex][3][3] = inVecs[inIndex][3][3];\n";
424 				break;
425 
426 			default:
427 				DE_ASSERT(false);
428 		}
429 	}
430 }
431 
genTexelBufferShaderAccess(VkFormat bufferFormat,std::ostringstream & bufferDefinition,std::ostringstream & bufferUse,bool readFromStorage)432 void RobustBufferAccessTest::genTexelBufferShaderAccess (VkFormat				bufferFormat,
433 														 std::ostringstream&	bufferDefinition,
434 														 std::ostringstream&	bufferUse,
435 														 bool					readFromStorage)
436 {
437 	const char*		layoutTypeStr;
438 	const char*		inTexelBufferTypeStr;
439 	const char*		outTexelBufferTypeStr;
440 	const deUint32	texelSize				= mapVkFormat(bufferFormat).getPixelSize();
441 
442 	if (isFloatFormat(bufferFormat))
443 	{
444 		layoutTypeStr			= "rgba32f";
445 		inTexelBufferTypeStr	= readFromStorage ? "imageBuffer" : "textureBuffer";
446 		outTexelBufferTypeStr	= "imageBuffer";
447 	}
448 	else if (isUintFormat(bufferFormat))
449 	{
450 		layoutTypeStr			= "rgba32ui";
451 		inTexelBufferTypeStr	= readFromStorage ? "uimageBuffer" : "utextureBuffer";
452 		outTexelBufferTypeStr	= "uimageBuffer";
453 	}
454 	else if (isIntFormat(bufferFormat))
455 	{
456 		layoutTypeStr			= "rgba32i";
457 		inTexelBufferTypeStr	= readFromStorage ? "iimageBuffer" : "itextureBuffer";
458 		outTexelBufferTypeStr	= "iimageBuffer";
459 	}
460 	else if (bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
461 	{
462 		layoutTypeStr			= "rgb10_a2";
463 		inTexelBufferTypeStr	= readFromStorage ? "imageBuffer" : "textureBuffer"; outTexelBufferTypeStr	= "imageBuffer";
464 	}
465 	else
466 	{
467 		TCU_THROW(NotSupportedError, (std::string("Unsupported format: ") + getFormatName(bufferFormat)).c_str());
468 	}
469 
470 	bufferDefinition << "layout(set = 0, binding = 0" << ((readFromStorage) ? (std::string(", ") + layoutTypeStr) : "") << ") uniform highp "
471 					 << ((readFromStorage) ? "readonly " : "") << inTexelBufferTypeStr << " inImage;\n";
472 
473 	bufferDefinition << "layout(set = 0, binding = 1, " << layoutTypeStr << ") uniform highp writeonly " << outTexelBufferTypeStr << " outImage;\n";
474 
475 	bufferDefinition <<
476 		"layout(binding = 2, std140) uniform Offsets\n"
477 		"{\n"
478 		"	int inOffset;\n"
479 		"	int outOffset;\n"
480 		"};\n\n";
481 
482 	bufferUse << "	for (int i = 0; i < " << (s_numberOfBytesAccessed / texelSize) << "; i++)\n"
483 			  << "	{\n"
484 			  << "		imageStore(outImage, outOffset + i, " << (readFromStorage ? "imageLoad" : "texelFetch") << "(inImage, inOffset + i));\n"
485 			  << "	}\n";
486 }
487 
initBufferAccessPrograms(SourceCollections & programCollection,VkShaderStageFlags shaderStage,ShaderType shaderType,VkFormat bufferFormat,bool readFromStorage)488 void RobustBufferAccessTest::initBufferAccessPrograms (SourceCollections&	programCollection,
489 													   VkShaderStageFlags	shaderStage,
490 													   ShaderType			shaderType,
491 													   VkFormat				bufferFormat,
492 													   bool					readFromStorage)
493 {
494 	std::ostringstream	bufferDefinition;
495 	std::ostringstream	bufferUse;
496 	std::string			extensions;
497 
498 	if (bufferFormat == vk::VK_FORMAT_R64_UINT || bufferFormat == vk::VK_FORMAT_R64_SINT)
499 	{
500 		extensions = "#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require\n";
501 	}
502 
503 	if (shaderType != SHADER_TYPE_TEXEL_COPY)
504 	{
505 		genBufferShaderAccess(shaderType, bufferFormat, readFromStorage, bufferDefinition, bufferUse);
506 	}
507 
508 	if (shaderStage == VK_SHADER_STAGE_COMPUTE_BIT)
509 	{
510 		std::ostringstream computeShaderSource;
511 
512 		if (shaderType == SHADER_TYPE_TEXEL_COPY)
513 			genTexelBufferShaderAccess(bufferFormat, bufferDefinition, bufferUse, readFromStorage);
514 
515 		computeShaderSource <<
516 			"#version 440\n"
517 			"#extension GL_EXT_texture_buffer : require\n"
518 			<< extensions <<
519 			"precision highp float;\n"
520 			"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
521 			<< bufferDefinition.str() <<
522 			"void main (void)\n"
523 			"{\n"
524 			<< bufferUse.str() <<
525 			"}\n";
526 
527 		programCollection.glslSources.add("compute") << glu::ComputeSource(computeShaderSource.str());
528 	}
529 	else
530 	{
531 		std::ostringstream vertexShaderSource;
532 		std::ostringstream fragmentShaderSource;
533 
534 		if (shaderStage == VK_SHADER_STAGE_VERTEX_BIT)
535 		{
536 			if (shaderType == SHADER_TYPE_TEXEL_COPY)
537 				genTexelBufferShaderAccess(bufferFormat, bufferDefinition, bufferUse, readFromStorage);
538 
539 			vertexShaderSource <<
540 				"#version 440\n"
541 				"#extension GL_EXT_texture_buffer : require\n"
542 				<< extensions <<
543 				"precision highp float;\n"
544 				"layout(location = 0) in vec4 position;\n\n"
545 				<< bufferDefinition.str() << "\n"
546 				"out gl_PerVertex {\n"
547 				"	vec4 gl_Position;\n"
548 				"};\n\n"
549 				"void main (void)\n"
550 				"{\n"
551 				<< bufferUse.str() <<
552 				"	gl_Position = position;\n"
553 				"}\n";
554 		}
555 		else
556 		{
557 			vertexShaderSource <<
558 				"#version 440\n"
559 				"precision highp float;\n"
560 				"layout(location = 0) in vec4 position;\n\n"
561 				"out gl_PerVertex {\n"
562 				"	vec4 gl_Position;\n"
563 				"};\n\n"
564 				"void main (void)\n"
565 				"{\n"
566 				"	gl_Position = position;\n"
567 				"}\n";
568 		}
569 
570 		programCollection.glslSources.add("vertex") << glu::VertexSource(vertexShaderSource.str());
571 
572 		if (shaderStage == VK_SHADER_STAGE_FRAGMENT_BIT)
573 		{
574 			if (shaderType == SHADER_TYPE_TEXEL_COPY)
575 				genTexelBufferShaderAccess(bufferFormat, bufferDefinition, bufferUse, readFromStorage);
576 
577 			fragmentShaderSource <<
578 				"#version 440\n"
579 				"#extension GL_EXT_texture_buffer : require\n"
580 				<< extensions <<
581 				"precision highp float;\n"
582 				"layout(location = 0) out vec4 fragColor;\n"
583 				<< bufferDefinition.str() <<
584 				"void main (void)\n"
585 				"{\n"
586 				<< bufferUse.str() <<
587 				"	fragColor = vec4(1.0);\n"
588 				"}\n";
589 		}
590 		else
591 		{
592 			fragmentShaderSource <<
593 				"#version 440\n"
594 				"precision highp float;\n"
595 				"layout(location = 0) out vec4 fragColor;\n\n"
596 				"void main (void)\n"
597 				"{\n"
598 				"	fragColor = vec4(1.0);\n"
599 				"}\n";
600 		}
601 
602 		programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentShaderSource.str());
603 	}
604 }
605 
606 // RobustBufferReadTest
607 
RobustBufferReadTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkShaderStageFlags shaderStage,ShaderType shaderType,VkFormat bufferFormat,VkDeviceSize readAccessRange,bool readFromStorage,bool accessOutOfBackingMemory)608 RobustBufferReadTest::RobustBufferReadTest (tcu::TestContext&	testContext,
609 											const std::string&	name,
610 											const std::string&	description,
611 											VkShaderStageFlags	shaderStage,
612 											ShaderType			shaderType,
613 											VkFormat			bufferFormat,
614 											VkDeviceSize		readAccessRange,
615 											bool				readFromStorage,
616 											bool				accessOutOfBackingMemory)
617 	: RobustBufferAccessTest		(testContext, name, description, shaderStage, shaderType, bufferFormat)
618 	, m_readFromStorage				(readFromStorage)
619 	, m_readAccessRange				(readAccessRange)
620 	, m_accessOutOfBackingMemory	(accessOutOfBackingMemory)
621 {
622 }
623 
initPrograms(SourceCollections & programCollection) const624 void RobustBufferReadTest::initPrograms (SourceCollections& programCollection) const
625 {
626 	initBufferAccessPrograms(programCollection, m_shaderStage, m_shaderType, m_bufferFormat, m_readFromStorage);
627 }
628 
createInstance(Context & context) const629 TestInstance* RobustBufferReadTest::createInstance (Context& context) const
630 {
631 	Move<VkDevice>	device			= createRobustBufferAccessDevice(context);
632 
633 	return new BufferReadInstance(context, device, m_shaderType, m_shaderStage, m_bufferFormat, m_readFromStorage, m_readAccessRange, m_accessOutOfBackingMemory);
634 }
635 
636 // RobustBufferWriteTest
637 
RobustBufferWriteTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkShaderStageFlags shaderStage,ShaderType shaderType,VkFormat bufferFormat,VkDeviceSize writeAccessRange,bool accessOutOfBackingMemory)638 RobustBufferWriteTest::RobustBufferWriteTest (tcu::TestContext&		testContext,
639 											  const std::string&	name,
640 											  const std::string&	description,
641 											  VkShaderStageFlags	shaderStage,
642 											  ShaderType			shaderType,
643 											  VkFormat				bufferFormat,
644 											  VkDeviceSize			writeAccessRange,
645 											  bool					accessOutOfBackingMemory)
646 
647 	: RobustBufferAccessTest		(testContext, name, description, shaderStage, shaderType, bufferFormat)
648 	, m_writeAccessRange			(writeAccessRange)
649 	, m_accessOutOfBackingMemory	(accessOutOfBackingMemory)
650 {
651 }
652 
initPrograms(SourceCollections & programCollection) const653 void RobustBufferWriteTest::initPrograms (SourceCollections& programCollection) const
654 {
655 	initBufferAccessPrograms(programCollection, m_shaderStage, m_shaderType, m_bufferFormat, false /* readFromStorage */);
656 }
657 
createInstance(Context & context) const658 TestInstance* RobustBufferWriteTest::createInstance (Context& context) const
659 {
660 	Move<VkDevice>	device			= createRobustBufferAccessDevice(context);
661 
662 	return new BufferWriteInstance(context, device, m_shaderType, m_shaderStage, m_bufferFormat, m_writeAccessRange, m_accessOutOfBackingMemory);
663 }
664 
665 // BufferAccessInstance
666 
BufferAccessInstance(Context & context,Move<VkDevice> device,ShaderType shaderType,VkShaderStageFlags shaderStage,VkFormat bufferFormat,BufferAccessType bufferAccessType,VkDeviceSize inBufferAccessRange,VkDeviceSize outBufferAccessRange,bool accessOutOfBackingMemory)667 BufferAccessInstance::BufferAccessInstance (Context&			context,
668 											Move<VkDevice>		device,
669 											ShaderType			shaderType,
670 											VkShaderStageFlags	shaderStage,
671 											VkFormat			bufferFormat,
672 											BufferAccessType	bufferAccessType,
673 											VkDeviceSize		inBufferAccessRange,
674 											VkDeviceSize		outBufferAccessRange,
675 											bool				accessOutOfBackingMemory)
676 	: vkt::TestInstance				(context)
677 	, m_device						(device)
678 	, m_shaderType					(shaderType)
679 	, m_shaderStage					(shaderStage)
680 	, m_bufferFormat				(bufferFormat)
681 	, m_bufferAccessType			(bufferAccessType)
682 	, m_inBufferAccessRange			(inBufferAccessRange)
683 	, m_outBufferAccessRange		(outBufferAccessRange)
684 	, m_accessOutOfBackingMemory	(accessOutOfBackingMemory)
685 {
686 	const DeviceInterface&		vk						= context.getDeviceInterface();
687 	const deUint32				queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
688 	const bool					isTexelAccess			= !!(m_shaderType == SHADER_TYPE_TEXEL_COPY);
689 	const bool					readFromStorage			= !!(m_bufferAccessType == BUFFER_ACCESS_TYPE_READ_FROM_STORAGE);
690 	SimpleAllocator				memAlloc				(vk, *m_device, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
691 	tcu::TestLog&				log						= m_context.getTestContext().getLog();
692 
693 	DE_ASSERT(RobustBufferAccessTest::s_numberOfBytesAccessed % sizeof(deUint32) == 0);
694 	DE_ASSERT(inBufferAccessRange <= RobustBufferAccessTest::s_numberOfBytesAccessed);
695 	DE_ASSERT(outBufferAccessRange <= RobustBufferAccessTest::s_numberOfBytesAccessed);
696 
697 	if (m_bufferFormat == VK_FORMAT_R64_UINT || m_bufferFormat == VK_FORMAT_R64_SINT)
698 	{
699 		context.requireDeviceFunctionality("VK_EXT_shader_image_atomic_int64");
700 	}
701 
702 	// Check storage support
703 	if (shaderStage == VK_SHADER_STAGE_VERTEX_BIT)
704 	{
705 		if (!context.getDeviceFeatures().vertexPipelineStoresAndAtomics)
706 		{
707 			TCU_THROW(NotSupportedError, "Stores not supported in vertex stage");
708 		}
709 	}
710 	else if (shaderStage == VK_SHADER_STAGE_FRAGMENT_BIT)
711 	{
712 		if (!context.getDeviceFeatures().fragmentStoresAndAtomics)
713 		{
714 			TCU_THROW(NotSupportedError, "Stores not supported in fragment stage");
715 		}
716 	}
717 
718 	// Check format support
719 	{
720 		VkFormatFeatureFlags		requiredFormatFeatures	= 0;
721 		const VkFormatProperties	formatProperties		= getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), m_bufferFormat);
722 
723 		if (isTexelAccess)
724 		{
725 			requiredFormatFeatures	= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;
726 		}
727 
728 		if ((formatProperties.bufferFeatures & requiredFormatFeatures) != requiredFormatFeatures)
729 		{
730 			TCU_THROW(NotSupportedError, (std::string("Format cannot be used in uniform and storage") + (isTexelAccess ? " texel" : "") + " buffers: "
731 										  + getFormatName(m_bufferFormat)).c_str());
732 		}
733 	}
734 
735 	// Create buffer to read data from
736 	{
737 		VkBufferUsageFlags		inBufferUsageFlags;
738 		VkMemoryRequirements	inBufferMemoryReqs;
739 
740 		if (isTexelAccess)
741 		{
742 			inBufferUsageFlags = readFromStorage ? VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
743 		}
744 		else
745 		{
746 			inBufferUsageFlags = readFromStorage ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
747 		}
748 
749 		const VkBufferCreateInfo	inBufferParams =
750 		{
751 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
752 			DE_NULL,									// const void*			pNext;
753 			0u,											// VkBufferCreateFlags	flags;
754 			m_inBufferAccessRange,						// VkDeviceSize			size;
755 			inBufferUsageFlags,							// VkBufferUsageFlags	usage;
756 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
757 			VK_QUEUE_FAMILY_IGNORED,					// deUint32				queueFamilyIndexCount;
758 			DE_NULL										// const deUint32*		pQueueFamilyIndices;
759 		};
760 
761 		m_inBuffer				= createBuffer(vk, *m_device, &inBufferParams);
762 
763 		inBufferMemoryReqs		= getBufferMemoryRequirements(vk, *m_device, *m_inBuffer);
764 		m_inBufferAllocSize		= inBufferMemoryReqs.size;
765 		m_inBufferAlloc			= memAlloc.allocate(inBufferMemoryReqs, MemoryRequirement::HostVisible);
766 
767 		// Size of the most restrictive bound
768 		m_inBufferMaxAccessRange = min(m_inBufferAllocSize, min(inBufferParams.size, m_inBufferAccessRange));
769 
770 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_inBuffer, m_inBufferAlloc->getMemory(), m_inBufferAlloc->getOffset()));
771 		populateBufferWithTestValues(m_inBufferAlloc->getHostPtr(), m_inBufferAllocSize, m_bufferFormat);
772 		flushMappedMemoryRange(vk, *m_device, m_inBufferAlloc->getMemory(), m_inBufferAlloc->getOffset(), VK_WHOLE_SIZE);
773 
774 		log << tcu::TestLog::Message << "inBufferAllocSize = " << m_inBufferAllocSize << tcu::TestLog::EndMessage;
775 		log << tcu::TestLog::Message << "inBufferMaxAccessRange = " << m_inBufferMaxAccessRange << tcu::TestLog::EndMessage;
776 	}
777 
778 	// Create buffer to write data into
779 	{
780 		VkMemoryRequirements		outBufferMemoryReqs;
781 		const VkBufferUsageFlags	outBufferUsageFlags	= (m_shaderType == SHADER_TYPE_TEXEL_COPY) ? VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT
782 																								   : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
783 
784 		const VkBufferCreateInfo	outBufferParams		=
785 		{
786 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
787 			DE_NULL,									// const void*			pNext;
788 			0u,											// VkBufferCreateFlags	flags;
789 			m_outBufferAccessRange,						// VkDeviceSize			size;
790 			outBufferUsageFlags,						// VkBufferUsageFlags	usage;
791 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
792 			VK_QUEUE_FAMILY_IGNORED,					// deUint32				queueFamilyIndexCount;
793 			DE_NULL										// const deUint32*		pQueueFamilyIndices;
794 		};
795 
796 		m_outBuffer					= createBuffer(vk, *m_device, &outBufferParams);
797 
798 		outBufferMemoryReqs			= getBufferMemoryRequirements(vk, *m_device, *m_outBuffer);
799 		m_outBufferAllocSize		= outBufferMemoryReqs.size;
800 		m_outBufferAlloc			= memAlloc.allocate(outBufferMemoryReqs, MemoryRequirement::HostVisible);
801 
802 		// If we are requesting access out of the memory that backs the buffer, make sure the test is able to do so.
803 		if (m_accessOutOfBackingMemory)
804 		{
805 			if (m_outBufferAllocSize >= ((RobustBufferAccessTest::s_testArraySize + 1) * RobustBufferAccessTest::s_numberOfBytesAccessed))
806 			{
807 				TCU_THROW(NotSupportedError, "Cannot access beyond the end of the memory that backs the buffer");
808 			}
809 		}
810 
811 		// Size of the most restrictive bound
812 		m_outBufferMaxAccessRange = min(m_outBufferAllocSize, min(outBufferParams.size, m_outBufferAccessRange));
813 
814 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
815 		deMemset(m_outBufferAlloc->getHostPtr(), 0xFF, (size_t)m_outBufferAllocSize);
816 		flushMappedMemoryRange(vk, *m_device, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset(), VK_WHOLE_SIZE);
817 
818 		log << tcu::TestLog::Message << "outBufferAllocSize = " << m_outBufferAllocSize << tcu::TestLog::EndMessage;
819 		log << tcu::TestLog::Message << "outBufferMaxAccessRange = " << m_outBufferMaxAccessRange << tcu::TestLog::EndMessage;
820 	}
821 
822 	// Create buffer for indices/offsets
823 	{
824 		struct IndicesBuffer
825 		{
826 			deInt32 inIndex;
827 			deInt32 outIndex;
828 		};
829 
830 		IndicesBuffer indices = { 0, 0 };
831 
832 		const VkBufferCreateInfo	indicesBufferParams			=
833 		{
834 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
835 			DE_NULL,									// const void*			pNext;
836 			0u,											// VkBufferCreateFlags	flags;
837 			sizeof(IndicesBuffer),						// VkDeviceSize			size;
838 			VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,			// VkBufferUsageFlags	usage;
839 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
840 			VK_QUEUE_FAMILY_IGNORED,					// deUint32				queueFamilyIndexCount;
841 			DE_NULL,									// const deUint32*		pQueueFamilyIndices;
842 		};
843 
844 		m_indicesBuffer				= createBuffer(vk, *m_device, &indicesBufferParams);
845 		m_indicesBufferAlloc		= memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_indicesBuffer), MemoryRequirement::HostVisible);
846 
847 		VK_CHECK(vk.bindBufferMemory(*m_device, *m_indicesBuffer, m_indicesBufferAlloc->getMemory(), m_indicesBufferAlloc->getOffset()));
848 
849 		if (m_accessOutOfBackingMemory)
850 		{
851 			if (m_bufferAccessType == BUFFER_ACCESS_TYPE_WRITE)
852 			{
853 				indices.outIndex = RobustBufferAccessTest::s_testArraySize - 1;
854 			}
855 			else
856 			{
857 				indices.inIndex = RobustBufferAccessTest::s_testArraySize - 1;
858 			}
859 		}
860 
861 		deMemcpy(m_indicesBufferAlloc->getHostPtr(), &indices, sizeof(IndicesBuffer));
862 
863 		flushMappedMemoryRange(vk, *m_device, m_indicesBufferAlloc->getMemory(), m_indicesBufferAlloc->getOffset(), VK_WHOLE_SIZE);
864 
865 		log << tcu::TestLog::Message << "inIndex = " << indices.inIndex << tcu::TestLog::EndMessage;
866 		log << tcu::TestLog::Message << "outIndex = " << indices.outIndex << tcu::TestLog::EndMessage;
867 	}
868 
869 	// Create descriptor data
870 	{
871 		VkDescriptorType	inBufferDescriptorType;
872 		VkDescriptorType	outBufferDescriptorType;
873 
874 		if (isTexelAccess)
875 		{
876 			inBufferDescriptorType	= readFromStorage ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
877 			outBufferDescriptorType	= VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
878 		}
879 		else
880 		{
881 			inBufferDescriptorType	= readFromStorage ? VK_DESCRIPTOR_TYPE_STORAGE_BUFFER : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
882 			outBufferDescriptorType	= VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
883 		}
884 
885 		DescriptorPoolBuilder descriptorPoolBuilder;
886 		descriptorPoolBuilder.addType(inBufferDescriptorType, 1u);
887 		descriptorPoolBuilder.addType(outBufferDescriptorType, 1u);
888 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u);
889 		m_descriptorPool = descriptorPoolBuilder.build(vk, *m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
890 
891 		DescriptorSetLayoutBuilder setLayoutBuilder;
892 		setLayoutBuilder.addSingleBinding(inBufferDescriptorType, VK_SHADER_STAGE_ALL);
893 		setLayoutBuilder.addSingleBinding(outBufferDescriptorType, VK_SHADER_STAGE_ALL);
894 		setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_ALL);
895 		m_descriptorSetLayout = setLayoutBuilder.build(vk, *m_device);
896 
897 		const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
898 		{
899 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
900 			DE_NULL,											// const void*					pNext;
901 			*m_descriptorPool,									// VkDescriptorPool				descriptorPool;
902 			1u,													// deUint32						setLayoutCount;
903 			&m_descriptorSetLayout.get()						// const VkDescriptorSetLayout*	pSetLayouts;
904 		};
905 
906 		m_descriptorSet = allocateDescriptorSet(vk, *m_device, &descriptorSetAllocateInfo);
907 
908 		DescriptorSetUpdateBuilder setUpdateBuilder;
909 
910 		if (isTexelAccess)
911 		{
912 			const VkBufferViewCreateInfo inBufferViewCreateInfo =
913 			{
914 				VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,		// VkStructureType			sType;
915 				DE_NULL,										// const void*				pNext;
916 				0u,												// VkBufferViewCreateFlags	flags;
917 				*m_inBuffer,									// VkBuffer					buffer;
918 				m_bufferFormat,									// VkFormat					format;
919 				0ull,											// VkDeviceSize				offset;
920 				m_inBufferAccessRange							// VkDeviceSize				range;
921 			};
922 			m_inTexelBufferView	= createBufferView(vk, *m_device, &inBufferViewCreateInfo, DE_NULL);
923 
924 			const VkBufferViewCreateInfo outBufferViewCreateInfo =
925 			{
926 				VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,		// VkStructureType			sType;
927 				DE_NULL,										// const void*				pNext;
928 				0u,												// VkBufferViewCreateFlags	flags;
929 				*m_outBuffer,									// VkBuffer					buffer;
930 				m_bufferFormat,									// VkFormat					format;
931 				0ull,											// VkDeviceSize				offset;
932 				m_outBufferAccessRange,							// VkDeviceSize				range;
933 			};
934 			m_outTexelBufferView	= createBufferView(vk, *m_device, &outBufferViewCreateInfo, DE_NULL);
935 
936 			setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), inBufferDescriptorType, &m_inTexelBufferView.get());
937 			setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1), outBufferDescriptorType, &m_outTexelBufferView.get());
938 		}
939 		else
940 		{
941 			const VkDescriptorBufferInfo inBufferDescriptorInfo		= makeDescriptorBufferInfo(*m_inBuffer, 0ull, m_inBufferAccessRange);
942 			const VkDescriptorBufferInfo outBufferDescriptorInfo	= makeDescriptorBufferInfo(*m_outBuffer, 0ull, m_outBufferAccessRange);
943 
944 			setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), inBufferDescriptorType, &inBufferDescriptorInfo);
945 			setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1), outBufferDescriptorType, &outBufferDescriptorInfo);
946 		}
947 
948 		const VkDescriptorBufferInfo indicesBufferDescriptorInfo	= makeDescriptorBufferInfo(*m_indicesBuffer, 0ull, 8ull);
949 		setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &indicesBufferDescriptorInfo);
950 
951 		setUpdateBuilder.update(vk, *m_device);
952 	}
953 
954 	// Create fence
955 	{
956 		const VkFenceCreateInfo fenceParams =
957 		{
958 			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
959 			DE_NULL,								// const void*			pNext;
960 			0u										// VkFenceCreateFlags	flags;
961 		};
962 
963 		m_fence = createFence(vk, *m_device, &fenceParams);
964 	}
965 
966 	// Get queue
967 	vk.getDeviceQueue(*m_device, queueFamilyIndex, 0, &m_queue);
968 
969 	if (m_shaderStage == VK_SHADER_STAGE_COMPUTE_BIT)
970 	{
971 		m_testEnvironment = de::MovePtr<TestEnvironment>(new ComputeEnvironment(m_context, *m_device, *m_descriptorSetLayout, *m_descriptorSet));
972 	}
973 	else
974 	{
975 		using tcu::Vec4;
976 
977 		const VkVertexInputBindingDescription vertexInputBindingDescription =
978 		{
979 			0u,								// deUint32					binding;
980 			sizeof(tcu::Vec4),				// deUint32					strideInBytes;
981 			VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputStepRate	inputRate;
982 		};
983 
984 		const VkVertexInputAttributeDescription vertexInputAttributeDescription =
985 		{
986 			0u,								// deUint32	location;
987 			0u,								// deUint32	binding;
988 			VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
989 			0u								// deUint32	offset;
990 		};
991 
992 		const Vec4 vertices[] =
993 		{
994 			Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
995 			Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
996 			Vec4(1.0f, -1.0f, 0.0f, 1.0f),
997 		};
998 
999 		// Create vertex buffer
1000 		{
1001 			const VkDeviceSize			vertexBufferSize	= (VkDeviceSize)(4u * sizeof(tcu::Vec4));
1002 			const VkBufferCreateInfo	vertexBufferParams	=
1003 			{
1004 				VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1005 				DE_NULL,									// const void*			pNext;
1006 				0u,											// VkBufferCreateFlags	flags;
1007 				vertexBufferSize,							// VkDeviceSize			size;
1008 				VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
1009 				VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1010 				VK_QUEUE_FAMILY_IGNORED,					// deUint32				queueFamilyIndexCount;
1011 				DE_NULL										// const deUint32*		pQueueFamilyIndices;
1012 			};
1013 
1014 			DE_ASSERT(vertexBufferSize > 0);
1015 
1016 			m_vertexBuffer		= createBuffer(vk, *m_device, &vertexBufferParams);
1017 			m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_vertexBuffer), MemoryRequirement::HostVisible);
1018 
1019 			VK_CHECK(vk.bindBufferMemory(*m_device, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
1020 
1021 			// Load vertices into vertex buffer
1022 			deMemcpy(m_vertexBufferAlloc->getHostPtr(), vertices, sizeof(tcu::Vec4) * DE_LENGTH_OF_ARRAY(vertices));
1023 			flushMappedMemoryRange(vk, *m_device, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1024 		}
1025 
1026 		const GraphicsEnvironment::DrawConfig drawWithOneVertexBuffer =
1027 		{
1028 			std::vector<VkBuffer>(1, *m_vertexBuffer),	// std::vector<VkBuffer>	vertexBuffers;
1029 			DE_LENGTH_OF_ARRAY(vertices),				// deUint32					vertexCount;
1030 			1,											// deUint32					instanceCount;
1031 			DE_NULL,									// VkBuffer					indexBuffer;
1032 			0u,											// deUint32					indexCount;
1033 		};
1034 
1035 		m_testEnvironment = de::MovePtr<TestEnvironment>(new GraphicsEnvironment(m_context,
1036 																				 *m_device,
1037 																				 *m_descriptorSetLayout,
1038 																				 *m_descriptorSet,
1039 																				 GraphicsEnvironment::VertexBindings(1, vertexInputBindingDescription),
1040 																				 GraphicsEnvironment::VertexAttributes(1, vertexInputAttributeDescription),
1041 																				 drawWithOneVertexBuffer));
1042 	}
1043 }
1044 
1045 // Verifies if the buffer has the value initialized by BufferAccessInstance::populateReadBuffer at a given offset.
isExpectedValueFromInBuffer(VkDeviceSize offsetInBytes,const void * valuePtr,VkDeviceSize valueSize)1046 bool BufferAccessInstance::isExpectedValueFromInBuffer (VkDeviceSize offsetInBytes, const void* valuePtr, VkDeviceSize valueSize)
1047 {
1048 	DE_ASSERT(offsetInBytes % 4 == 0);
1049 	DE_ASSERT(offsetInBytes < m_inBufferAllocSize);
1050 
1051 	const deUint32 valueIndex = deUint32(offsetInBytes / 4) + 2;
1052 
1053 	if (isUintFormat(m_bufferFormat))
1054 	{
1055 		return !deMemCmp(valuePtr, &valueIndex, (size_t)valueSize);
1056 	}
1057 	else if (isIntFormat(m_bufferFormat))
1058 	{
1059 		const deInt32 value = -deInt32(valueIndex);
1060 		return !deMemCmp(valuePtr, &value, (size_t)valueSize);
1061 	}
1062 	else if (isFloatFormat(m_bufferFormat))
1063 	{
1064 		const float value = float(valueIndex);
1065 		return !deMemCmp(valuePtr, &value, (size_t)valueSize);
1066 	}
1067 	else if (m_bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
1068 	{
1069 		const deUint32	r		= ((valueIndex + 0) & ((2u << 10) - 1u));
1070 		const deUint32	g		= ((valueIndex + 1) & ((2u << 10) - 1u));
1071 		const deUint32	b		= ((valueIndex + 2) & ((2u << 10) - 1u));
1072 		const deUint32	a		= ((valueIndex + 0) & ((2u << 2) - 1u));
1073 		const deUint32	abgr	= (a << 30) | (b << 20) | (g << 10) | r;
1074 
1075 		return !deMemCmp(valuePtr, &abgr, (size_t)valueSize);
1076 	}
1077 	else
1078 	{
1079 		DE_ASSERT(false);
1080 		return false;
1081 	}
1082 }
1083 
isOutBufferValueUnchanged(VkDeviceSize offsetInBytes,VkDeviceSize valueSize)1084 bool BufferAccessInstance::isOutBufferValueUnchanged (VkDeviceSize offsetInBytes, VkDeviceSize valueSize)
1085 {
1086 	const deUint8 *const	outValuePtr		= (deUint8*)m_outBufferAlloc->getHostPtr() + offsetInBytes;
1087 	const deUint32			defaultValue	= 0xFFFFFFFFu;
1088 
1089 	return !deMemCmp(outValuePtr, &defaultValue, (size_t)valueSize);
1090 }
1091 
iterate(void)1092 tcu::TestStatus BufferAccessInstance::iterate (void)
1093 {
1094 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
1095 	const vk::VkCommandBuffer	cmdBuffer	= m_testEnvironment->getCommandBuffer();
1096 
1097 	// Submit command buffer
1098 	{
1099 		const VkSubmitInfo	submitInfo	=
1100 		{
1101 			VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
1102 			DE_NULL,						// const void*					pNext;
1103 			0u,								// deUint32						waitSemaphoreCount;
1104 			DE_NULL,						// const VkSemaphore*			pWaitSemaphores;
1105 			DE_NULL,						// const VkPIpelineStageFlags*	pWaitDstStageMask;
1106 			1u,								// deUint32						commandBufferCount;
1107 			&cmdBuffer,						// const VkCommandBuffer*		pCommandBuffers;
1108 			0u,								// deUint32						signalSemaphoreCount;
1109 			DE_NULL							// const VkSemaphore*			pSignalSemaphores;
1110 		};
1111 
1112 		VK_CHECK(vk.resetFences(*m_device, 1, &m_fence.get()));
1113 		VK_CHECK(vk.queueSubmit(m_queue, 1, &submitInfo, *m_fence));
1114 		VK_CHECK(vk.waitForFences(*m_device, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
1115 	}
1116 
1117 	// Prepare result buffer for read
1118 	{
1119 		const VkMappedMemoryRange	outBufferRange	=
1120 		{
1121 			VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	//  VkStructureType	sType;
1122 			DE_NULL,								//  const void*		pNext;
1123 			m_outBufferAlloc->getMemory(),			//  VkDeviceMemory	mem;
1124 			0ull,									//  VkDeviceSize	offset;
1125 			m_outBufferAllocSize,					//  VkDeviceSize	size;
1126 		};
1127 
1128 		VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange));
1129 	}
1130 
1131 	if (verifyResult())
1132 		return tcu::TestStatus::pass("All values OK");
1133 	else
1134 		return tcu::TestStatus::fail("Invalid value(s) found");
1135 }
1136 
verifyResult(void)1137 bool BufferAccessInstance::verifyResult (void)
1138 {
1139 	std::ostringstream	logMsg;
1140 	tcu::TestLog&		log					= m_context.getTestContext().getLog();
1141 	const bool			isReadAccess		= !!(m_bufferAccessType == BUFFER_ACCESS_TYPE_READ || m_bufferAccessType == BUFFER_ACCESS_TYPE_READ_FROM_STORAGE);
1142 	const void*			inDataPtr			= m_inBufferAlloc->getHostPtr();
1143 	const void*			outDataPtr			= m_outBufferAlloc->getHostPtr();
1144 	bool				allOk				= true;
1145 	deUint32			valueNdx			= 0;
1146 	const VkDeviceSize	maxAccessRange		= isReadAccess ? m_inBufferMaxAccessRange : m_outBufferMaxAccessRange;
1147 
1148 	for (VkDeviceSize offsetInBytes = 0; offsetInBytes < m_outBufferAllocSize; offsetInBytes += 4)
1149 	{
1150 		deUint8*			outValuePtr		= (deUint8*)outDataPtr + offsetInBytes;
1151 		const size_t		outValueSize	= (size_t)min(4, (m_outBufferAllocSize - offsetInBytes));
1152 
1153 		if (offsetInBytes >= RobustBufferAccessTest::s_numberOfBytesAccessed)
1154 		{
1155 			// The shader will only write 16 values into the result buffer. The rest of the values
1156 			// should remain unchanged or may be modified if we are writing out of bounds.
1157 			if (!isOutBufferValueUnchanged(offsetInBytes, outValueSize)
1158 				&& (isReadAccess || !isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, 4)))
1159 			{
1160 				logMsg << "\nValue " << valueNdx++ << " has been modified with an unknown value: " << *((deUint32 *)outValuePtr);
1161 				allOk = false;
1162 			}
1163 		}
1164 		else
1165 		{
1166 			const deInt32	distanceToOutOfBounds	= (deInt32)maxAccessRange - (deInt32)offsetInBytes;
1167 			bool			isOutOfBoundsAccess		= false;
1168 
1169 			logMsg << "\n" << valueNdx++ << ": ";
1170 
1171 			logValue(logMsg, outValuePtr, m_bufferFormat, outValueSize);
1172 
1173 			if (m_accessOutOfBackingMemory)
1174 			{
1175 				isOutOfBoundsAccess = true;
1176 			}
1177 			else
1178 			{
1179 				// Check if the shader operation accessed an operand located less than 16 bytes away
1180 				// from the out of bounds address.
1181 
1182 				deUint32 operandSize = 0;
1183 
1184 				switch (m_shaderType)
1185 				{
1186 					case SHADER_TYPE_SCALAR_COPY:
1187 						operandSize		= 4; // Size of scalar
1188 						break;
1189 
1190 					case SHADER_TYPE_VECTOR_COPY:
1191 						operandSize		= 4 * ((m_bufferFormat == vk::VK_FORMAT_R64_UINT || m_bufferFormat == vk::VK_FORMAT_R64_SINT) ? 8 : 4);// Size of vec4
1192 						break;
1193 
1194 					case SHADER_TYPE_MATRIX_COPY:
1195 						operandSize		= 4 * 16; // Size of mat4
1196 						break;
1197 
1198 					case SHADER_TYPE_TEXEL_COPY:
1199 						operandSize		= mapVkFormat(m_bufferFormat).getPixelSize();
1200 						break;
1201 
1202 					default:
1203 						DE_ASSERT(false);
1204 				}
1205 
1206 				isOutOfBoundsAccess = (maxAccessRange < 16)
1207 									|| (((offsetInBytes / operandSize + 1) * operandSize) > (maxAccessRange - 16));
1208 			}
1209 
1210 			if (isOutOfBoundsAccess)
1211 			{
1212 				logMsg << " (out of bounds " << (isReadAccess ? "read": "write") << ")";
1213 
1214 				const bool	isValuePartiallyOutOfBounds = ((distanceToOutOfBounds > 0) && ((deUint32)distanceToOutOfBounds < 4));
1215 				bool		isValidValue				= false;
1216 
1217 				if (isValuePartiallyOutOfBounds && !m_accessOutOfBackingMemory)
1218 				{
1219 					// The value is partially out of bounds
1220 
1221 					bool	isOutOfBoundsPartOk = true;
1222 					bool	isWithinBoundsPartOk = true;
1223 
1224 					if (isReadAccess)
1225 					{
1226 						isWithinBoundsPartOk	= isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, distanceToOutOfBounds);
1227 						isOutOfBoundsPartOk		= isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, (deUint8*)outValuePtr + distanceToOutOfBounds , outValueSize - distanceToOutOfBounds);
1228 					}
1229 					else
1230 					{
1231 						isWithinBoundsPartOk	= isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, distanceToOutOfBounds)
1232 												  || isOutBufferValueUnchanged(offsetInBytes, distanceToOutOfBounds);
1233 
1234 						isOutOfBoundsPartOk		= isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, (deUint8*)outValuePtr + distanceToOutOfBounds, outValueSize - distanceToOutOfBounds)
1235 												  || isOutBufferValueUnchanged(offsetInBytes + distanceToOutOfBounds, outValueSize - distanceToOutOfBounds);
1236 					}
1237 
1238 					logMsg << ", first " << distanceToOutOfBounds << " byte(s) " << (isWithinBoundsPartOk ? "OK": "wrong");
1239 					logMsg << ", last " << outValueSize - distanceToOutOfBounds << " byte(s) " << (isOutOfBoundsPartOk ? "OK": "wrong");
1240 
1241 					isValidValue	= isWithinBoundsPartOk && isOutOfBoundsPartOk;
1242 				}
1243 				else
1244 				{
1245 					if (isReadAccess)
1246 					{
1247 						isValidValue	= isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, outValueSize);
1248 					}
1249 					else
1250 					{
1251 						isValidValue	= isOutBufferValueUnchanged(offsetInBytes, outValueSize);
1252 
1253 						if (!isValidValue)
1254 						{
1255 							// Out of bounds writes may modify values withing the memory ranges bound to the buffer
1256 							isValidValue	= isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, outValueSize);
1257 
1258 							if (isValidValue)
1259 								logMsg << ", OK, written within the memory range bound to the buffer";
1260 						}
1261 					}
1262 				}
1263 
1264 				if (!isValidValue)
1265 				{
1266 					// Check if we are satisfying the [0, 0, 0, x] pattern, where x may be either 0 or 1,
1267 					// or the maximum representable positive integer value (if the format is integer-based).
1268 
1269 					const bool	canMatchVec4Pattern	= (isReadAccess
1270 													&& !isValuePartiallyOutOfBounds
1271 													&& (m_shaderType == SHADER_TYPE_VECTOR_COPY || m_shaderType == SHADER_TYPE_TEXEL_COPY)
1272 													&& ((offsetInBytes / 4 + 1) % 4 == 0 || m_bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32));
1273 					bool		matchesVec4Pattern	= false;
1274 
1275 					if (canMatchVec4Pattern)
1276 					{
1277 						if (m_bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
1278 							matchesVec4Pattern	= verifyOutOfBoundsVec4(outValuePtr, m_bufferFormat);
1279 						else
1280 							matchesVec4Pattern	= verifyOutOfBoundsVec4(reinterpret_cast<deUint32*>(outValuePtr) - 3, m_bufferFormat);
1281 					}
1282 
1283 					if (!canMatchVec4Pattern || !matchesVec4Pattern)
1284 					{
1285 						logMsg << ". Failed: ";
1286 
1287 						if (isReadAccess)
1288 						{
1289 							logMsg << "expected value within the buffer range or 0";
1290 
1291 							if (canMatchVec4Pattern)
1292 								logMsg << ", or the [0, 0, 0, x] pattern";
1293 						}
1294 						else
1295 						{
1296 							logMsg << "written out of the range";
1297 						}
1298 
1299 						allOk = false;
1300 					}
1301 				}
1302 			}
1303 			else // We are within bounds
1304 			{
1305 				if (isReadAccess)
1306 				{
1307 					if (!isExpectedValueFromInBuffer(offsetInBytes, outValuePtr, 4))
1308 					{
1309 						logMsg << ", Failed: unexpected value";
1310 						allOk = false;
1311 					}
1312 				}
1313 				else
1314 				{
1315 					// Out of bounds writes may change values within the bounds.
1316 					if (!isValueWithinBufferOrZero(inDataPtr, m_inBufferAccessRange, outValuePtr, 4))
1317 					{
1318 						logMsg << ", Failed: unexpected value";
1319 						allOk = false;
1320 					}
1321 				}
1322 			}
1323 		}
1324 	}
1325 
1326 	log << tcu::TestLog::Message << logMsg.str() << tcu::TestLog::EndMessage;
1327 
1328 	return allOk;
1329 }
1330 
1331 // BufferReadInstance
1332 
BufferReadInstance(Context & context,Move<VkDevice> device,ShaderType shaderType,VkShaderStageFlags shaderStage,VkFormat bufferFormat,bool readFromStorage,VkDeviceSize inBufferAccessRange,bool accessOutOfBackingMemory)1333 BufferReadInstance::BufferReadInstance (Context&			context,
1334 										Move<VkDevice>		device,
1335 										ShaderType			shaderType,
1336 										VkShaderStageFlags	shaderStage,
1337 										VkFormat			bufferFormat,
1338 										bool				readFromStorage,
1339 										VkDeviceSize		inBufferAccessRange,
1340 										bool				accessOutOfBackingMemory)
1341 
1342 	: BufferAccessInstance	(context, device, shaderType, shaderStage, bufferFormat,
1343 							 readFromStorage ? BUFFER_ACCESS_TYPE_READ_FROM_STORAGE : BUFFER_ACCESS_TYPE_READ,
1344 							 inBufferAccessRange,
1345 							 RobustBufferAccessTest::s_numberOfBytesAccessed,	// outBufferAccessRange
1346 							 accessOutOfBackingMemory)
1347 {
1348 }
1349 
1350 // BufferWriteInstance
1351 
BufferWriteInstance(Context & context,Move<VkDevice> device,ShaderType shaderType,VkShaderStageFlags shaderStage,VkFormat bufferFormat,VkDeviceSize writeBufferAccessRange,bool accessOutOfBackingMemory)1352 BufferWriteInstance::BufferWriteInstance (Context&				context,
1353 										  Move<VkDevice>		device,
1354 										  ShaderType			shaderType,
1355 										  VkShaderStageFlags	shaderStage,
1356 										  VkFormat				bufferFormat,
1357 										  VkDeviceSize			writeBufferAccessRange,
1358 										  bool					accessOutOfBackingMemory)
1359 
1360 	: BufferAccessInstance	(context, device, shaderType, shaderStage, bufferFormat,
1361 							 BUFFER_ACCESS_TYPE_WRITE,
1362 							 RobustBufferAccessTest::s_numberOfBytesAccessed,	// inBufferAccessRange
1363 							 writeBufferAccessRange,
1364 							 accessOutOfBackingMemory)
1365 {
1366 }
1367 
1368 // Test node creation functions
1369 
getShaderStageName(VkShaderStageFlagBits shaderStage)1370 static const char* getShaderStageName (VkShaderStageFlagBits shaderStage)
1371 {
1372 	switch (shaderStage)
1373 	{
1374 		case VK_SHADER_STAGE_VERTEX_BIT:					return "vertex";
1375 		case VK_SHADER_STAGE_FRAGMENT_BIT:					return "fragment";
1376 		case VK_SHADER_STAGE_COMPUTE_BIT:					return "compute";
1377 		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:		return "tess_control";
1378 		case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:	return "tess_eval";
1379 		case VK_SHADER_STAGE_GEOMETRY_BIT:					return "geometry";
1380 
1381 		default:
1382 			DE_ASSERT(false);
1383 	}
1384 
1385 	return DE_NULL;
1386 }
1387 
addBufferAccessTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * parentNode)1388 static void addBufferAccessTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* parentNode)
1389 {
1390 	struct BufferRangeConfig
1391 	{
1392 		const char*		name;
1393 		VkDeviceSize	range;
1394 	};
1395 
1396 	const VkShaderStageFlagBits bufferAccessStages[] =
1397 	{
1398 		VK_SHADER_STAGE_VERTEX_BIT,
1399 		VK_SHADER_STAGE_FRAGMENT_BIT,
1400 		VK_SHADER_STAGE_COMPUTE_BIT,
1401 	};
1402 
1403 	const VkFormat bufferFormats[] =
1404 	{
1405 		VK_FORMAT_R32_SINT,
1406 		VK_FORMAT_R32_UINT,
1407 		VK_FORMAT_R64_SINT,
1408 		VK_FORMAT_R64_UINT,
1409 		VK_FORMAT_R32_SFLOAT
1410 	};
1411 
1412 	const VkFormat texelBufferFormats[] =
1413 	{
1414 		VK_FORMAT_R32G32B32A32_SINT,
1415 		VK_FORMAT_R32G32B32A32_UINT,
1416 		VK_FORMAT_R32G32B32A32_SFLOAT,
1417 
1418 		VK_FORMAT_A2B10G10R10_UNORM_PACK32
1419 	};
1420 
1421 	const BufferRangeConfig bufferRangeConfigs[] =
1422 	{
1423 		{ "range_1_byte",		1ull },
1424 		{ "range_3_bytes",		3ull },
1425 		{ "range_4_bytes",		4ull },		// size of float
1426 		{ "range_32_bytes",		32ull },	// size of half mat4
1427 	};
1428 
1429 	const BufferRangeConfig texelBufferRangeConfigs[] =
1430 	{
1431 		{ "range_1_texel",		1u },
1432 		{ "range_3_texels",		3u },
1433 	};
1434 
1435 	const char* shaderTypeNames[SHADER_TYPE_COUNT] =
1436 	{
1437 		"mat4_copy",
1438 		"vec4_copy",
1439 		"scalar_copy",
1440 		"texel_copy",
1441 	};
1442 
1443 	for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(bufferAccessStages); stageNdx++)
1444 	{
1445 		const VkShaderStageFlagBits			stage			= bufferAccessStages[stageNdx];
1446 		de::MovePtr<tcu::TestCaseGroup>		stageTests		(new tcu::TestCaseGroup(testCtx, getShaderStageName(stage), ""));
1447 
1448 		for (int shaderTypeNdx = 0; shaderTypeNdx < SHADER_TYPE_COUNT; shaderTypeNdx++)
1449 		{
1450 			const VkFormat*					formats;
1451 			size_t							formatsLength;
1452 			const BufferRangeConfig*		ranges;
1453 			size_t							rangesLength;
1454 			deUint32						rangeMultiplier;
1455 			de::MovePtr<tcu::TestCaseGroup> shaderTypeTests	(new tcu::TestCaseGroup(testCtx, shaderTypeNames[shaderTypeNdx], ""));
1456 
1457 			if ((ShaderType)shaderTypeNdx == SHADER_TYPE_TEXEL_COPY)
1458 			{
1459 				formats			= texelBufferFormats;
1460 				formatsLength	= DE_LENGTH_OF_ARRAY(texelBufferFormats);
1461 
1462 				ranges			= texelBufferRangeConfigs;
1463 				rangesLength	= DE_LENGTH_OF_ARRAY(texelBufferRangeConfigs);
1464 			}
1465 			else
1466 			{
1467 				formats			= bufferFormats;
1468 				formatsLength	= DE_LENGTH_OF_ARRAY(bufferFormats);
1469 
1470 				ranges			= bufferRangeConfigs;
1471 				rangesLength	= DE_LENGTH_OF_ARRAY(bufferRangeConfigs);
1472 			}
1473 
1474 			for (size_t formatNdx = 0; formatNdx < formatsLength; formatNdx++)
1475 			{
1476 				const VkFormat	bufferFormat	= formats[formatNdx];
1477 
1478 				rangeMultiplier = ((ShaderType)shaderTypeNdx == SHADER_TYPE_TEXEL_COPY) ? mapVkFormat(bufferFormat).getPixelSize() : 1;
1479 
1480 				if (!isFloatFormat(bufferFormat) && ((ShaderType)shaderTypeNdx) == SHADER_TYPE_MATRIX_COPY)
1481 				{
1482 					// Use SHADER_TYPE_MATRIX_COPY with floating-point formats only
1483 					break;
1484 				}
1485 
1486 				const std::string				formatName		= getFormatName(bufferFormat);
1487 				de::MovePtr<tcu::TestCaseGroup>	formatTests		(new tcu::TestCaseGroup(testCtx, de::toLower(formatName.substr(10)).c_str(), ""));
1488 
1489 				de::MovePtr<tcu::TestCaseGroup> uboReadTests		(new tcu::TestCaseGroup(testCtx, "oob_uniform_read", ""));
1490 				de::MovePtr<tcu::TestCaseGroup> ssboReadTests		(new tcu::TestCaseGroup(testCtx, "oob_storage_read", ""));
1491 				de::MovePtr<tcu::TestCaseGroup> ssboWriteTests		(new tcu::TestCaseGroup(testCtx, "oob_storage_write", ""));
1492 
1493 				for (size_t rangeNdx = 0; rangeNdx < rangesLength; rangeNdx++)
1494 				{
1495 					const BufferRangeConfig&	rangeConfig			= ranges[rangeNdx];
1496 					const VkDeviceSize			rangeInBytes		= rangeConfig.range * rangeMultiplier;
1497 
1498 					uboReadTests->addChild(new RobustBufferReadTest(testCtx, rangeConfig.name, "", stage, (ShaderType)shaderTypeNdx, bufferFormat, rangeInBytes, false, false));
1499 					ssboReadTests->addChild(new RobustBufferReadTest(testCtx, rangeConfig.name, "", stage, (ShaderType)shaderTypeNdx, bufferFormat, rangeInBytes, true, false));
1500 					ssboWriteTests->addChild(new RobustBufferWriteTest(testCtx, rangeConfig.name, "", stage, (ShaderType)shaderTypeNdx, bufferFormat, rangeInBytes, false));
1501 
1502 				}
1503 
1504 				formatTests->addChild(uboReadTests.release());
1505 				formatTests->addChild(ssboReadTests.release());
1506 				formatTests->addChild(ssboWriteTests.release());
1507 
1508 				shaderTypeTests->addChild(formatTests.release());
1509 			}
1510 
1511 			// Read/write out of the memory that backs the buffer
1512 			{
1513 				de::MovePtr<tcu::TestCaseGroup>	outOfAllocTests		(new tcu::TestCaseGroup(testCtx, "out_of_alloc", ""));
1514 
1515 				const VkFormat format = (((ShaderType)shaderTypeNdx == SHADER_TYPE_TEXEL_COPY ) ? VK_FORMAT_R32G32B32A32_SFLOAT : VK_FORMAT_R32_SFLOAT);
1516 
1517 				outOfAllocTests->addChild(new RobustBufferReadTest(testCtx, "oob_uniform_read", "", stage, (ShaderType)shaderTypeNdx, format, 16, false, true));
1518 				outOfAllocTests->addChild(new RobustBufferReadTest(testCtx, "oob_storage_read", "", stage, (ShaderType)shaderTypeNdx, format, 16, true, true));
1519 				outOfAllocTests->addChild(new RobustBufferWriteTest(testCtx, "oob_storage_write", "", stage, (ShaderType)shaderTypeNdx, format, 16, true));
1520 
1521 				shaderTypeTests->addChild(outOfAllocTests.release());
1522 			}
1523 
1524 			stageTests->addChild(shaderTypeTests.release());
1525 		}
1526 		parentNode->addChild(stageTests.release());
1527 	}
1528 }
1529 
createBufferAccessTests(tcu::TestContext & testCtx)1530 tcu::TestCaseGroup* createBufferAccessTests (tcu::TestContext& testCtx)
1531 {
1532 	de::MovePtr<tcu::TestCaseGroup> bufferAccessTests	(new tcu::TestCaseGroup(testCtx, "buffer_access", ""));
1533 
1534 	addBufferAccessTests(testCtx, bufferAccessTests.get());
1535 
1536 	return bufferAccessTests.release();
1537 }
1538 
1539 } // robustness
1540 } // vkt
1541