• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 The Khronos Group Inc.
6  * Copyright (c) 2022 Google Inc.
7  * Copyright (c) 2023 LunarG, Inc.
8  * Copyright (c) 2023 Nintendo
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *		http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \brief Robustness1 vertex access out of range tests
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktRobustness1VertexAccessTests.hpp"
27 #include "deDefs.h"
28 #include "deMemory.h"
29 #include "gluShaderProgram.hpp"
30 #include "gluShaderUtil.hpp"
31 #include "image/vktImageLoadStoreUtil.hpp"
32 #include "pipeline/vktPipelineSpecConstantUtil.hpp"
33 #include "qpTestLog.h"
34 #include "tcuTestCase.hpp"
35 #include "tcuTestContext.hpp"
36 #include "tcuTexture.hpp"
37 #include "tcuTextureUtil.hpp"
38 #include "tcuVectorType.hpp"
39 #include "tcuVectorUtil.hpp"
40 #include "vkBarrierUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkDefs.hpp"
43 #include "vkObjUtil.hpp"
44 #include "vkShaderProgram.hpp"
45 #include "vktRobustnessUtil.hpp"
46 #include "vktTestCase.hpp"
47 #include "vktTestCaseUtil.hpp"
48 #include "vkBuilderUtil.hpp"
49 #include "vkImageUtil.hpp"
50 #include "vkMemUtil.hpp"
51 #include "vkPrograms.hpp"
52 #include "vkQueryUtil.hpp"
53 #include "vkRef.hpp"
54 #include "vkRefUtil.hpp"
55 #include "vkTypeUtil.hpp"
56 #include "tcuTestLog.hpp"
57 #include "deMath.h"
58 #include "deUniquePtr.hpp"
59 #include "vkRefUtil.hpp"
60 #include <algorithm>
61 #include <cstdint>
62 #include <cstdio>
63 #include <iterator>
64 #include <sstream>
65 #include <tuple>
66 #include <vector>
67 #include <array>
68 #include <functional>
69 #include <cmath>
70 #include <limits>
71 #include "pipeline/vktPipelineImageUtil.hpp"
72 
73 namespace vkt
74 {
75 namespace robustness
76 {
77 namespace
78 {
79 
80 using namespace vk;
81 using namespace de;
82 using namespace tcu;
83 
84 using std::function;
85 using std::ostringstream;
86 using std::string;
87 using std::vector;
88 using std::numeric_limits;
89 using std::setprecision;
90 using std::fixed;
91 
92 typedef function<deUint32(Vec4, Vec4)>				AllocateVertexFn;
93 typedef function<void(deUint32)>					WriteIndexFn;
94 struct ValidityInfo
95 {
96 	bool	color0;
97 	bool	color1;
98 };
99 
100 deUint32 GetVerticesCountForTriangles(deUint32 tilesX, deUint32 tilesY);
__anon6766c1080202(deUint32) 101 void GenerateTriangles(deUint32 tilesX, deUint32 tilesY, vector<Vec4> colors, const vector<deUint32>& invalidIndices, AllocateVertexFn allocateVertex, WriteIndexFn writeIndex = [](deUint32) { });
102 
103 typedef vector<VkVertexInputBindingDescription>		VertexBindings;
104 typedef vector<VkVertexInputAttributeDescription>	VertexAttributes;
105 struct AttributeData
106 {
107 	const void*		data;
108 	deUint32		size;
109 };
110 
111 struct InputInfo
112 {
113 	VertexBindings			vertexBindings;
114 	VertexAttributes		vertexAttributes;
115 	vector<AttributeData>	data;
116 	deUint32				vertexCount;
117 	vector<deUint32>		indices;
118 };
119 typedef function<TestStatus(const ConstPixelBufferAccess &)>	ValidationFn;
120 
121 
122 static const auto		expectedColor		= Vec4(0.25f, 0.0f, 0.75f, 1.0f);		// Expected color input
123 static const auto		unusedColor			= Vec4(0.75f, 0.0f, 0.25f, 1.0f);		// Unused color attributes
124 static const auto		outOfRangeColor		= Vec4(0.2f , 0.2f, 0.2f , 1.0f);		// Padding, out of range accesses - never accepted as output
125 static const auto		validColors			= vector<Vec4>							// Colors accepted as valid in verification shader
126 {
127 	expectedColor, unusedColor
128 };
129 static const auto		invalidColors		= vector<Vec4>							// Colors accepted as oob access in verification shader
130 {
131 	expectedColor, unusedColor, Vec4(0.0f), Vec4(0.0f, 0.0f, 0.0f, 1.0f)
132 };
133 
134 static TestStatus		robustness1TestFn(TestContext&				testCtx,
135 										  Context&					context,
136 										  const VkDevice			device,
137 										  DeviceDriverPtr			deviceDriver,
138 										  const vector<InputInfo>&	inputs,
139 										  const IVec2&				renderSize);
140 
141 template<typename T>
142 class PaddedAlloc
143 {
144 	deUint32	m_count, m_paddingCount;
145 	vector<T>	m_data;
146 public:
147 					PaddedAlloc		(deUint32 count, deUint32 paddingCount, const T& paddingValue);
148 					PaddedAlloc		(const PaddedAlloc<T>&) = delete;
149 
paddedSize() const150 	deUint32		paddedSize() const { return static_cast<deUint32>(m_data.size()); }
paddedStart() const151 	deUint32		paddedStart() const { return m_paddingCount; }
paddedData() const152 	const T*		paddedData() const { return m_data.data(); }
153 
size() const154 	deUint32		size() const { return m_count; }
data() const155 	const T*		data() const { return m_data.data() + m_paddingCount; }
156 
operator [](const deUint32 index)157 	T&				operator[](const deUint32 index) { return m_data[m_paddingCount + index]; }
operator [](const deUint32 index) const158 	const T&		operator[](const deUint32 index) const { return m_data[m_paddingCount + index]; }
159 
160 	PaddedAlloc&	operator=		(PaddedAlloc&) = delete;
161 };
162 
163 template <typename T>
PaddedAlloc(deUint32 count,deUint32 paddingCount,const T & paddingValue)164 PaddedAlloc<T>::PaddedAlloc (deUint32 count, deUint32 paddingCount, const T& paddingValue)
165 		: m_count			(count)
166 		, m_paddingCount	(paddingCount)
167 {
168 	DE_ASSERT((count + 2 * paddingCount) * sizeof(T) <= numeric_limits<deUint32>::max());
169 	m_data.resize(count + 2 * paddingCount);
170 	const auto	end			= m_data.size() - 1;
171 	for(deUint32 i = 0; i < paddingCount; ++i)
172 	{
173 		m_data[i]			= paddingValue;
174 		m_data[end - i]		= paddingValue;
175 	}
176 }
177 
178 typedef function<TestStatus (TestContext&,Context&, const VkDevice device, DeviceDriverPtr deviceDriver)>	TestFn;
179 struct Robustness1TestInfo
180 {
181 	string	name;
182 	TestFn	testFn;
183 };
184 static const auto		renderTargetSize	= IVec2(12, 12);
185 static const auto		robustness1Tests	= vector<Robustness1TestInfo>
186 {
187 	/* Layout of generated vertices vs location invalid vertices always at middle,
188 	   (3x3 tiles = 4x4 vertices):
189 			 0	 1	 2	 3	->	  0	  1	  2	  3
190 			 4 * 5 * 6	 7	->	  4	  7	  8	 11
191 			 8 * 9 *10	11	->	 12	 13	 14	 15
192 			12	13	14	15	->	* 5 * 6 * 9 *10
193 	*/
194 	{
195 		"out_of_bounds_stride_0",														// string			name
196 		[](TestContext& testContext, Context& context, const VkDevice device, DeviceDriverPtr deviceDriver)
__anon6766c1080302(TestContext& testContext, Context& context, const VkDevice device, DeviceDriverPtr deviceDriver) 197 		{
198 			struct Color
199 			{
200 				Vec4 unused;
201 				Vec4 color;
202 			};
203 			const deUint32			totalCount	= GetVerticesCountForTriangles(3, 3);
204 			PaddedAlloc<Vec4>		positions	(totalCount, 8, outOfRangeColor);
205 			PaddedAlloc<Color>		colors		(totalCount, 8, { outOfRangeColor, outOfRangeColor });
206 			PaddedAlloc<Vec4>		color0		(1, 4, outOfRangeColor);
207 			color0[0]							= expectedColor;
208 			vector<deUint32>		indices;
209 			deUint32				writeIndex	= 0;
210 			GenerateTriangles(
211 				3u,
212 				3u,
213 				{ unusedColor },
214 				{ 5, 6, 9, 10 },
215 				[&positions, &colors, &writeIndex](Vec4 position, Vec4 color)
216 				{
217 					positions[writeIndex]	= position;
218 					colors[writeIndex]		= { color, color };
219 					return writeIndex++;
220 				},
221 				[&indices](deUint32 index) { indices.push_back(index); });
222 			auto bindings	=
223 			{
224 				makeVertexInputBindingDescription(0u, sizeof(positions[0]), VK_VERTEX_INPUT_RATE_VERTEX),
225 				makeVertexInputBindingDescription(1u, 0u, VK_VERTEX_INPUT_RATE_VERTEX),
226 				makeVertexInputBindingDescription(2u, sizeof(colors[0]), VK_VERTEX_INPUT_RATE_VERTEX)
227 			};
228 			auto attributes	=
229 			{
230 				makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u),
231 				makeVertexInputAttributeDescription(1u, 1u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u),
232 				makeVertexInputAttributeDescription(2u, 2u, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Color, color))
233 			};
234 			return robustness1TestFn(
235 				testContext, context, device, deviceDriver,
236 				{
237 					{
238 						bindings,
239 						attributes,
240 						{
241 							{ positions.data()	, positions.size() * static_cast<deUint32>(sizeof(positions[0]))													},
242 							{ color0.data()		, color0.size()	* static_cast<deUint32>(sizeof(color0[0]))															},
243 							{ colors.data()		, (colors.size() - 3) * static_cast<deUint32>(sizeof(colors[0])) - static_cast<deUint32>(sizeof(Color::color) / 2)	}
244 						},
245 						static_cast<deUint32>(positions.size()),
246 						indices
247 					}
248 				},
249 				renderTargetSize);
250 		}
251 	},
252 	{
253 		"out_of_bounds_stride_16_single_buffer",										// string			name
254 		[](TestContext& testContext, Context& context, const VkDevice device, DeviceDriverPtr deviceDriver)
__anon6766c1080602(TestContext& testContext, Context& context, const VkDevice device, DeviceDriverPtr deviceDriver) 255 		{
256 			struct Vertex
257 			{
258 				Vec4 position;
259 				Vec4 unused1;
260 				Vec4 color1;
261 				Vec4 color2;
262 			};
263 			const deUint32			totalCount	= GetVerticesCountForTriangles(3, 3);
264 			PaddedAlloc<Vertex>		vertices	(totalCount, 8, { outOfRangeColor, outOfRangeColor, outOfRangeColor, outOfRangeColor });
265 			deUint32				writeIndex	= 0;
266 			vector<deUint32>		indices;
267 			GenerateTriangles(
268 				3u,
269 				3u,
270 				{ expectedColor },
271 				{ 5, 6, 9, 10 },
272 				[&vertices, &writeIndex](Vec4 position, Vec4 color)
273 				{
274 					vertices[writeIndex]	= { position, unusedColor, color, color };
275 					return writeIndex++;
276 				},
277 				[&indices](deUint32 index) { indices.push_back(index); });
278 			auto	bindings	=
279 			{
280 				makeVertexInputBindingDescription(0u, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX),
281 				makeVertexInputBindingDescription(1u, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX)
282 			};
283 			auto	attributes	=
284 			{
285 				makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Vertex, position)),
286 				makeVertexInputAttributeDescription(1u, 1u, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Vertex, color1)),
287 				makeVertexInputAttributeDescription(2u, 1u, VK_FORMAT_R32G32B32A32_SFLOAT, offsetof(Vertex, color2))
288 			};
289 			return robustness1TestFn(
290 				testContext, context, device, deviceDriver,
291 				{
292 					{
293 						bindings,
294 						attributes,
295 						{
296 							{ vertices.data(),	static_cast<deUint32>(vertices.size() * sizeof(vertices[0]))								},
297 							{ vertices.data(),	static_cast<deUint32>((vertices.size() - 3) * sizeof(vertices[0]) - sizeof(Vertex::color2))	}
298 						},
299 						static_cast<deUint32>(vertices.size()),
300 						indices,
301 					}
302 				},
303 				renderTargetSize);
304 		}
305 	},
306 	{
307 		"out_of_bounds_stride_30_middle_of_buffer",										// string			name
308 		[](TestContext& testContext, Context& context, const VkDevice device, DeviceDriverPtr deviceDriver)
__anon6766c1080902(TestContext& testContext, Context& context, const VkDevice device, DeviceDriverPtr deviceDriver) 309 		{
310 			const vector<deUint32>	invalidIndices	= { 5, 6, 9, 10 };
311 			const deUint32			invalidCount	= static_cast<deUint32>(invalidIndices.size());
312 			const deUint32			totalCount		= GetVerticesCountForTriangles(3, 3);
313 			struct Vertex
314 			{
315 				Vec4	position;
316 				Vec4	color1;
317 				Vec4	unused1;
318 				Vec4	color2;
319 				Vec4	unused2;
320 			};
321 			PaddedAlloc<Vertex>		vertices		(totalCount, 8, { outOfRangeColor, outOfRangeColor, outOfRangeColor, outOfRangeColor, outOfRangeColor });
322 			deUint32				writeIndex		= 0;
323 			vector<deUint32>		indices;
324 			GenerateTriangles(
325 				3u,
326 				3u,
327 				{ expectedColor },
328 				invalidIndices,
329 				[&vertices, &writeIndex](Vec4 position, Vec4 color)
330 				{
331 					vertices[writeIndex] = { position, color, unusedColor, unusedColor, unusedColor };
332 					return writeIndex++;
333 				},
334 				[&indices](deUint32 index) { indices.push_back(index); });
335 			const auto elementSize	= static_cast<deUint32>(sizeof(Vertex));
336 			auto	bindings		=
337 			{
338 				makeVertexInputBindingDescription(0u, elementSize, VK_VERTEX_INPUT_RATE_VERTEX),
339 				makeVertexInputBindingDescription(1u, elementSize, VK_VERTEX_INPUT_RATE_VERTEX),
340 			};
341 			auto	attributes		=
342 			{
343 				makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, vertices.paddedStart() * elementSize + static_cast<deUint32>(offsetof(Vertex, position))),
344 				makeVertexInputAttributeDescription(1u, 1u, VK_FORMAT_R32G32B32A32_SFLOAT, vertices.paddedStart() * elementSize + static_cast<deUint32>(offsetof(Vertex, color1))),
345 				makeVertexInputAttributeDescription(2u, 1u, VK_FORMAT_R32G32B32A32_SFLOAT, vertices.paddedStart() * elementSize + static_cast<deUint32>(offsetof(Vertex, color2))),
346 			};
347 			return robustness1TestFn(
348 				testContext, context, device, deviceDriver,
349 				{
350 					{
351 						bindings,
352 						attributes,
353 						{
354 							{ vertices.paddedData()	, vertices.paddedSize() * elementSize					},
355 							{ vertices.paddedData()	, (vertices.paddedSize() - invalidCount) * elementSize	},
356 						},
357 						static_cast<deUint32>(vertices.size()),
358 						indices
359 					}
360 				},
361 				renderTargetSize);
362 		}
363 	},
364 	{
365 		"out_of_bounds_stride_8_middle_of_buffer_separate",								// string			name
366 		[](TestContext& testContext, Context& context, const VkDevice device, DeviceDriverPtr deviceDriver)
__anon6766c1080c02(TestContext& testContext, Context& context, const VkDevice device, DeviceDriverPtr deviceDriver) 367 		{
368 			/* NOTE: Out of range entries ('padding') need to be initialized with unusedColor as the spec
369 			   allows out of range to return any value from within the bound memory range. */
370 			const vector<deUint32>	invalidIndices	= { 5, 6, 9, 10 };
371 			const deUint32			invalidCount	= static_cast<deUint32>(invalidIndices.size());
372 			const deUint32			totalCount		= GetVerticesCountForTriangles(3, 3);
373 			PaddedAlloc<Vec4>		vertices		(totalCount, 8, unusedColor);
374 			PaddedAlloc<Vec4>		colors			(2 * totalCount - invalidCount, 8, unusedColor);
375 			deUint32				writeIndex		= 0;
376 			vector<deUint32>		indices;
377 			GenerateTriangles(
378 				3u,
379 				3u,
380 				{ expectedColor },
381 				invalidIndices,
382 				[&vertices, &colors, &writeIndex, totalCount](Vec4 position, Vec4 color)
383 				{
384 					vertices[writeIndex]					= position;
385 					colors[writeIndex]						= color;
386 					if (totalCount + writeIndex < colors.size())
387 					{
388 						colors[totalCount + writeIndex]		= color;
389 					}
390 					return writeIndex++;
391 				},
392 				[&indices](deUint32 index) { indices.push_back(index); });
393 			const auto elementSize	= static_cast<deUint32>(sizeof(Vec4));
394 			auto	bindings		=
395 			{
396 				makeVertexInputBindingDescription(0u, elementSize, VK_VERTEX_INPUT_RATE_VERTEX),
397 				makeVertexInputBindingDescription(1u, elementSize, VK_VERTEX_INPUT_RATE_VERTEX)
398 			};
399 			auto	attributes		=
400 			{
401 				makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, vertices.paddedStart() * elementSize),
402 				makeVertexInputAttributeDescription(1u, 1u, VK_FORMAT_R32G32B32A32_SFLOAT, colors.paddedStart() * elementSize),
403 				makeVertexInputAttributeDescription(2u, 1u, VK_FORMAT_R32G32B32A32_SFLOAT, (colors.paddedStart() + totalCount) * elementSize)
404 			};
405 			return robustness1TestFn(
406 				testContext, context, device, deviceDriver,
407 				{
408 					{
409 						bindings,
410 						attributes,
411 						{
412 							{ vertices.paddedData()	, vertices.paddedSize() * elementSize	},
413 							{ colors.paddedData()	, colors.paddedSize() * elementSize		}
414 						},
415 						static_cast<deUint32>(vertices.size()),
416 						indices
417 					}
418 				},
419 				renderTargetSize);
420 		}
421 	}
422 };
423 
GetVerticesCountForTriangles(deUint32 tilesX,deUint32 tilesY)424 deUint32 GetVerticesCountForTriangles(deUint32 tilesX, deUint32 tilesY)
425 {
426 	return (tilesX + 1) * (tilesY + 1);
427 }
428 
429 // Generate triangles with invalid vertices placed at end of buffer. NOTE: Assumes invalidIndices to be in ascending order!
GenerateTriangles(deUint32 tilesX,deUint32 tilesY,vector<Vec4> colors,const vector<deUint32> & invalidIndices,AllocateVertexFn allocateVertex,WriteIndexFn writeIndex)430 void GenerateTriangles (deUint32 tilesX, deUint32 tilesY, vector<Vec4> colors, const vector<deUint32>& invalidIndices, AllocateVertexFn allocateVertex, WriteIndexFn writeIndex)
431 {
432 	const auto			tilesStride			= (tilesX + 1);
433 	const auto			total				= tilesStride * (tilesY + 1);
434 	const auto			lastValidIndex		= total - 1 - static_cast<deUint32>(invalidIndices.size());
435 	const Vec2			step				(1.0f / static_cast<float>(tilesX), 1.0f / static_cast<float>(tilesY));
436 
437 	vector<deUint32>	indexMappings		(total);
438 	deUint32			nextInvalid			= 0;
439 	deUint32			writeOffset			= 0;
440 	deUint32			nextInvalidValue	= nextInvalid < invalidIndices.size() ? invalidIndices[nextInvalid] : total;
441 	for(deUint32 i = 0; i < total; ++i)
442 	{
443 		if (i < nextInvalidValue)
444 		{
445 			indexMappings[writeOffset++] = i;
446 		}
447 		else
448 		{
449 			++nextInvalid;
450 			nextInvalidValue = nextInvalid < invalidIndices.size() ? invalidIndices[nextInvalid] : total;
451 		}
452 	}
453 	for(deUint32 i = 0; i < static_cast<deUint32>(invalidIndices.size()); ++i)
454 	{
455 		indexMappings[writeOffset++] = invalidIndices[i];
456 	}
457 	deUint32			count				= 0;
458 	const auto			vertexFn			= [lastValidIndex, &step, allocateVertex, &count](deUint32 x, deUint32 y, Vec4 color)
459 	{
460 		const auto result = allocateVertex(
461 			Vec4(
462 				2.0f * static_cast<float>(x) * step.x() - 1.0f,
463 				2.0f * static_cast<float>(y) * step.y() - 1.0f,
464 				(count <= lastValidIndex) ? 1.0f : 0.0f,
465 				1.0f
466 			), color);
467 		++count;
468 		return result;
469 	};
470 	vector<deUint32> indices(total);
471 	for(deUint32 index = 0; index < total; ++index)
472 	{
473 		const auto	mapped	= indexMappings[index];
474 		const auto	x		= mapped % tilesStride;
475 		const auto	y		= mapped / tilesStride;
476 		const auto	color	= colors[(x + y) % colors.size()];
477 		indices[y * tilesStride + x] = vertexFn(x, y, color);
478 	}
479 	for(deUint32 y = 0; y < tilesY; ++y)
480 	{
481 		for(deUint32 x = 0; x < tilesX; ++x)
482 		{
483 			writeIndex(indices[(y	 ) * tilesStride + x	]);
484 			writeIndex(indices[(y + 1) * tilesStride + x	]);
485 			writeIndex(indices[(y	 ) * tilesStride + x + 1]);
486 			writeIndex(indices[(y	 ) * tilesStride + x + 1]);
487 			writeIndex(indices[(y + 1) * tilesStride + x + 1]);
488 			writeIndex(indices[(y + 1) * tilesStride + x	]);
489 		}
490 	}
491 }
492 
makeImageCreateInfo(const tcu::IVec2 & size,const VkFormat format,const VkImageUsageFlags usage)493 VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
494 {
495 	const VkImageCreateInfo imageInfo =
496 	{
497 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType          sType;
498 		DE_NULL,									// const void*              pNext;
499 		(VkImageCreateFlags)0,						// VkImageCreateFlags       flags;
500 		VK_IMAGE_TYPE_2D,							// VkImageType              imageType;
501 		format,										// VkFormat                 format;
502 		makeExtent3D(size.x(), size.y(), 1),		// VkExtent3D               extent;
503 		1u,											// uint32_t                 mipLevels;
504 		1u,											// uint32_t                 arrayLayers;
505 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits    samples;
506 		VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling            tiling;
507 		usage,										// VkImageUsageFlags        usage;
508 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode            sharingMode;
509 		0u,											// uint32_t                 queueFamilyIndexCount;
510 		DE_NULL,									// const uint32_t*          pQueueFamilyIndices;
511 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout            initialLayout;
512 	};
513 	return imageInfo;
514 }
515 
robustness1TestFn(TestContext & testCtx,Context & context,const VkDevice device,DeviceDriverPtr deviceDriver,const vector<InputInfo> & inputs,const IVec2 & renderSize)516 static TestStatus robustness1TestFn (TestContext& testCtx, Context& context, const VkDevice device, DeviceDriverPtr	deviceDriver, const vector<InputInfo>& inputs, const IVec2& renderSize)
517 {
518 	const auto					colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
519 	const DeviceInterface&		vk					= *deviceDriver;
520 	auto						allocator			= SimpleAllocator(vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
521 
522 	const auto					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
523 	VkQueue						queue;
524 	vk.getDeviceQueue(device, queueFamilyIndex, 0, &queue);
525 
526 	vector<Move<VkImage>>		colorImages;
527 	vector<MovePtr<Allocation>>	colorImageAllocs;
528 	vector<Move<VkImageView>>	colorViews;
529 	vector<VkImageView>			attachmentViews;
530 	VkImageCreateInfo			imageCreateInfos[]	=
531 	{
532 		makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT),
533 	};
534 	for(const auto& params : imageCreateInfos)
535 	{
536 		auto			image					= createImage(vk, device, &params);
537 		auto			imageAlloc				= allocator.allocate(getImageMemoryRequirements(vk, device, *image), MemoryRequirement::Any);
538 		VK_CHECK(vk.bindImageMemory(device, *image, imageAlloc->getMemory(), imageAlloc->getOffset()));
539 		const auto		createInfo				= VkImageViewCreateInfo
540 		{
541 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,											// VkStructureType			sType;
542 			DE_NULL,																			// const void*				pNext;
543 			0u,																					// VkImageViewCreateFlags	flags;
544 			*image,																				// VkImage					image;
545 			VK_IMAGE_VIEW_TYPE_2D,																// VkImageViewType			viewType;
546 			colorFormat,																		// VkFormat					format;
547 			{ VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
548 			  VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY },					// VkComponentMapping		components;
549 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }										// VkImageSubresourceRange	subresourceRange;
550 		};
551 		auto			imageView				= createImageView(vk, device, &createInfo);
552 		attachmentViews.push_back(*imageView);
553 		colorImageAllocs.emplace_back(imageAlloc);
554 		colorViews.emplace_back(imageView);
555 		colorImages.emplace_back(image);
556 	}
557 
558 	const auto		colorAttachmentDescs		= vector<VkAttachmentDescription>
559 	{
560 		{
561 			(VkAttachmentDescriptionFlags)0,												// VkAttachmentDescriptionFlags		flags
562 			colorFormat,																	// VkFormat							format
563 			VK_SAMPLE_COUNT_1_BIT,															// VkSampleCountFlagBits			samples
564 			VK_ATTACHMENT_LOAD_OP_CLEAR,													// VkAttachmentLoadOp				loadOp
565 			VK_ATTACHMENT_STORE_OP_STORE,													// VkAttachmentStoreOp				storeOp
566 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,												// VkAttachmentLoadOp				stencilLoadOp
567 			VK_ATTACHMENT_STORE_OP_DONT_CARE,												// VkAttachmentStoreOp				stencilStoreOp
568 			VK_IMAGE_LAYOUT_UNDEFINED,														// VkImageLayout					initialLayout
569 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL										// VkImageLayout					finalLayout
570 		},
571 	};
572 	const auto		attachmentRefs				= vector<vector<VkAttachmentReference>>
573 	{
574 		{ { 0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } },								// pass 0 color
575 	};
576 	const auto		subpassDescs				= vector<VkSubpassDescription>
577 	{
578 		{
579 			static_cast<VkSubpassDescriptionFlags>(0),										// VkSubpassDescriptionFlags		flags;
580 			VK_PIPELINE_BIND_POINT_GRAPHICS,												// VkPipelineBindPoint				pipelineBindPoint;
581 			0u,																				// uint32_t							inputAttachmentCount;
582 			DE_NULL,																		// const VkAttachmentReference*		pInputAttachments;
583 			static_cast<deUint32>(attachmentRefs[0].size()),								// uint32_t							colorAttachmentCount;
584 			attachmentRefs[0].data(),														// const VkAttachmentReference*		pColorAttachments;
585 			DE_NULL,																		// const VkAttachmentReference*		pResolveAttachments;
586 			DE_NULL,																		// const VkAttachmentReference*		pDepthStencilAttachment;
587 			0u,																				// uint32_t							preserveAttachmentCount;
588 			DE_NULL																			// const uint32_t*					pPreserveAttachments;
589 		}
590 	};
591 	const auto		subpassDeps					= vector<VkSubpassDependency>
592 	{
593 		{
594 			VK_SUBPASS_EXTERNAL,															// uint32_t					srcSubpass;
595 			0u,																				// uint32_t					dstSubpass;
596 			VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,												// VkPipelineStageFlags		srcStageMask;
597 			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,									// VkPipelineStageFlags		dstStageMask;
598 			0u,																				// VkAccessFlags			srcAccessMask;
599 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,											// VkAccessFlags			dstAccessMask;
600 			VK_DEPENDENCY_BY_REGION_BIT														// VkDependencyFlags		dependencyFlags;
601 		},
602 		{
603 			0u,																				// uint32_t					srcSubpass;
604 			VK_SUBPASS_EXTERNAL,															// uint32_t					dstSubpass;
605 			VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,									// VkPipelineStageFlags		srcStageMask;
606 			VK_PIPELINE_STAGE_TRANSFER_BIT,													// VkPipelineStageFlags		dstStageMask;
607 			VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,											// VkAccessFlags			srcAccessMask;
608 			VK_ACCESS_TRANSFER_READ_BIT,													// VkAccessFlags			dstAccessMask;
609 			VK_DEPENDENCY_BY_REGION_BIT														// VkDependencyFlags		dependencyFlags;
610 		}
611 	};
612 	const auto		renderPassInfo				= VkRenderPassCreateInfo
613 	{
614 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,											// VkStructureType					sType
615 		DE_NULL,																			// const void*						pNext
616 		static_cast<VkRenderPassCreateFlags>(0),											// VkRenderPassCreateFlags			flags
617 		static_cast<deUint32>(colorAttachmentDescs.size()),									// deUint32							attachmentCount
618 		colorAttachmentDescs.data(),														// const VkAttachmentDescription*	pAttachments
619 		static_cast<deUint32>(subpassDescs.size()),											// deUint32							subpassCount
620 		subpassDescs.data(),																// const VkSubpassDescription*		pSubpasses
621 		static_cast<deUint32>(subpassDeps.size()),											// deUint32							dependencyCount
622 		subpassDeps.data()																	// const VkSubpassDependency*		pDependencies
623 	};
624 	const Unique<VkRenderPass>		pass		(createRenderPass(vk, device, &renderPassInfo, DE_NULL));
625 
626 	vector<Move<VkBuffer>>			vertexBuffers;
627 	vector<MovePtr<Allocation>>		vertexBufferAllocs;
628 	vector<vector<VkBuffer>>		vertexBufferPtrs;
629 	vector<vector<VkDeviceSize>>	vertexBufferOffsets;
630 	vector<Move<VkBuffer>>			indexBuffers;
631 	vector<MovePtr<Allocation>>		indexBufferAllocs;
632 	vector<Move<VkPipelineLayout>>	pipelineLayouts;
633 	vector<Move<VkPipeline>>		pipelines;
634 
635 	const auto								descriptorPool			= DescriptorPoolBuilder()
636 		.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, static_cast<deUint32>(inputs.size() * 4u))
637 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
638 	vector<Move<VkDescriptorSetLayout>>		descriptorSetLayouts;
639 	vector<Move<VkDescriptorSet>>			descriptorSets;
640 	vector<vector<VkDescriptorSet>>			descriptorSetPtrs;
641 	vector<Move<VkShaderModule>>			shaderModules;
642 	const vector<VkViewport>				viewports				= { makeViewport(renderSize) };
643 	const vector<VkRect2D>					scissors				= { makeRect2D(renderSize) };
644 	const vector<string>					vertexNames				= { "vertex-test" };
645 	const vector<string>					fragmentNames			= { "fragment-test" };
646 	for(vector<InputInfo>::size_type i = 0; i < inputs.size(); ++i)
647 	{
648 		const auto&						input						= inputs[i];
649 		vector<VkDescriptorSet>			inputDescriptorSets;
650 		vector<VkDescriptorSetLayout>	setLayouts;
651 		DescriptorSetLayoutBuilder		builder;
652 		for(size_t j = 0; j < input.vertexBindings.size(); ++j)
653 		{
654 			builder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_ALL);
655 		}
656 		auto							descriptorSetLayout			= builder.build(vk, device);
657 		setLayouts.push_back(*descriptorSetLayout);
658 		VkDescriptorSetAllocateInfo		descriptorSetAllocateInfo	=
659 		{
660 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,										// VkStructureType				sType;
661 			DE_NULL,																			// const void*					pNext;
662 			*descriptorPool,																	// VkDescriptorPool				descriptorPool;
663 			1u,																					// deUint32						setLayoutCount;
664 			&*descriptorSetLayout																// const VkDescriptorSetLayout*	pSetLayouts;
665 		};
666 		auto							descriptorSet				= allocateDescriptorSet(vk, device, &descriptorSetAllocateInfo);
667 		inputDescriptorSets.push_back(*descriptorSet);
668 
669 		VkPipelineLayoutCreateInfo			pipelineLayoutCreateInfo	=
670 		{
671 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,										// VkStructureType				sType;
672 			DE_NULL,																			// const void*					pNext;
673 			0u,																					// VkPipelineLayoutCreateFlags	flags;
674 			static_cast<deUint32>(setLayouts.size()),											// deUint32						setLayoutCount;
675 			setLayouts.data(),																	// const VkDescriptorSetLayout*	pSetLayouts;
676 			0u,																					// deUint32						pushConstantRangeCount;
677 			DE_NULL																				// const VkPushConstantRange*	pPushConstantRanges;
678 		};
679 		auto								pipelineLayout				= createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
680 
681 		descriptorSetPtrs.push_back(inputDescriptorSets);
682 		descriptorSetLayouts.emplace_back(descriptorSetLayout);
683 		descriptorSets.emplace_back(descriptorSet);
684 
685 		vector<VkBuffer>	inputVertexBufferPtrs;
686 		for(const auto& data : input.data)
687 		{
688 			const auto	createInfo			= makeBufferCreateInfo(data.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
689 			auto		buffer				= createBuffer(vk, device, &createInfo);
690 			auto		bufferAlloc			= allocator.allocate(getBufferMemoryRequirements(vk, device, *buffer), MemoryRequirement::HostVisible);
691 			VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
692 			deMemcpy(bufferAlloc->getHostPtr(), data.data, data.size);
693 			flushMappedMemoryRange(vk, device, bufferAlloc->getMemory(), bufferAlloc->getOffset(), VK_WHOLE_SIZE);
694 			inputVertexBufferPtrs.push_back(*buffer);
695 			vertexBufferAllocs.emplace_back(bufferAlloc);
696 			vertexBuffers.emplace_back(buffer);
697 		}
698 		vertexBufferOffsets.push_back(vector<VkDeviceSize>(inputVertexBufferPtrs.size(), 0ull));
699 		vertexBufferPtrs.push_back(inputVertexBufferPtrs);
700 
701 		if (input.indices.size() > 0u)
702 		{
703 			const auto	indexDataSize		= input.indices.size() * sizeof(input.indices[0]);
704 			const auto	createInfo			= makeBufferCreateInfo(indexDataSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
705 			auto		indexBuffer			= createBuffer(vk, device, &createInfo);
706 			auto		indexBufferAlloc	= allocator.allocate(getBufferMemoryRequirements(vk, device, *indexBuffer), MemoryRequirement::HostVisible);
707 			VK_CHECK(vk.bindBufferMemory(device, *indexBuffer, indexBufferAlloc->getMemory(), indexBufferAlloc->getOffset()));
708 			deMemcpy(indexBufferAlloc->getHostPtr(), input.indices.data(), indexDataSize);
709 			flushMappedMemoryRange(vk, device, indexBufferAlloc->getMemory(), indexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
710 			indexBufferAllocs.emplace_back(indexBufferAlloc);
711 			indexBuffers.emplace_back(indexBuffer);
712 		}
713 		const auto&		bindings					= input.vertexBindings;
714 		const auto&		attributes					= input.vertexAttributes;
715 		const auto		vertexInputCreateInfo		= VkPipelineVertexInputStateCreateInfo
716 		{
717 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,						// VkStructureType							sType;
718 			DE_NULL,																		// const void*								pNext;
719 			0u,																				// VkPipelineVertexInputStateCreateFlags	flags;
720 			static_cast<deUint32>(bindings.size()),											// deUint32									vertexBindingDescriptionCount;
721 			bindings.data(),																// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
722 			static_cast<deUint32>(attributes.size()),										// deUint32									vertexAttributeDescriptionCount;
723 			attributes.data()																// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
724 		};
725 		auto			vertexShaderModule			= createShaderModule(vk, device, context.getBinaryCollection().get(vertexNames[i % vertexNames.size()]), 0u);
726 		auto			fragmentShaderModule		= createShaderModule(vk, device, context.getBinaryCollection().get(fragmentNames[i % fragmentNames.size()]), 0u);
727 		auto			graphicsPipeline			= makeGraphicsPipeline(
728 			vk,																				// const DeviceInterface&							vk,
729 			device,																			// const VkDevice									device,
730 			*pipelineLayout,																// const VkPipelineLayout							pipelineLayout,
731 			*vertexShaderModule,															// const VkShaderModule								vertexShaderModule,
732 			DE_NULL,																		// const VkShaderModule								tessellationControlShaderModule,
733 			DE_NULL,																		// const VkShaderModule								tessellationEvalShaderModule,
734 			DE_NULL,																		// const VkShaderModule								geometryShaderModule,
735 			*fragmentShaderModule,															// const VkShaderModule								fragmentShaderModule,
736 			*pass,																			// const VkRenderPass								renderPass,
737 			viewports,																		// const std::vector<VkViewport>&					viewports,
738 			scissors,																		// const std::vector<VkRect2D>&						scissors,
739 			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,											// const VkPrimitiveTopology						topology,
740 			static_cast<deUint32>(i),														// const deUint32									subpass,
741 			0u,																				// const deUint32									patchControlPoints,
742 			&vertexInputCreateInfo);														// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo,
743 
744 		pipelineLayouts.emplace_back(pipelineLayout);
745 		pipelines.emplace_back(graphicsPipeline);
746 		shaderModules.emplace_back(vertexShaderModule);
747 		shaderModules.emplace_back(fragmentShaderModule);
748 	}
749 
750 	const auto						framebufferCreateInfo	= VkFramebufferCreateInfo
751 	{
752 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,											// VkStructureType			sType;
753 		DE_NULL,																			// const void*				pNext;
754 		0u,																					// VkFramebufferCreateFlags	flags;
755 		*pass,																				// VkRenderPass				renderPass;
756 		static_cast<deUint32>(attachmentViews.size()),										// deUint32					attachmentCount;
757 		attachmentViews.data(),																// const VkImageView*		pAttachments;
758 		(deUint32)renderSize.x(),															// deUint32					width;
759 		(deUint32)renderSize.y(),															// deUint32					height;
760 		1u																					// deUint32					layers;
761 	};
762 	const Unique<VkFramebuffer>		framebuffer				(createFramebuffer(vk, device, &framebufferCreateInfo));
763 
764 	const Unique<VkCommandPool>		commandPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex));
765 	const Unique<VkCommandBuffer>	commandBuffer			(allocateCommandBuffer(vk, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
766 	beginCommandBuffer(vk, *commandBuffer, 0u);
767 	beginRenderPass(vk, *commandBuffer, *pass, *framebuffer, makeRect2D(renderSize), Vec4(0.0f));
768 	deUint32						nextIndex				= 0;
769 	for(vector<InputInfo>::size_type i = 0; i < inputs.size(); ++i)
770 	{
771 		const auto&					input					= inputs[i];
772 		vk.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelines[i]);
773 		vk.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayouts[i], 0, static_cast<deUint32>(descriptorSetPtrs[i].size()), descriptorSetPtrs[i].data(), 0, DE_NULL);
774 		vk.cmdBindVertexBuffers(*commandBuffer, 0, (deUint32)vertexBufferPtrs[i].size(), vertexBufferPtrs[i].data(), vertexBufferOffsets[i].data());
775 		if (!input.indices.empty())
776 		{
777 			vk.cmdBindIndexBuffer(*commandBuffer, *indexBuffers[nextIndex], 0u, VK_INDEX_TYPE_UINT32);
778 			vk.cmdDrawIndexed(*commandBuffer, static_cast<deUint32>(input.indices.size()), 1u, 0, 0, 0u);
779 			++nextIndex;
780 		}
781 		else
782 		{
783 			vk.cmdDraw(*commandBuffer, input.vertexCount, 1u, 0, 0);
784 		}
785 		if (i + 1 < inputs.size())
786 		{
787 			vk.cmdNextSubpass(*commandBuffer, VK_SUBPASS_CONTENTS_INLINE);
788 		}
789 	}
790 	endRenderPass(vk, *commandBuffer);
791 
792 	endCommandBuffer(vk, *commandBuffer);
793 	submitCommandsAndWait(vk, device, queue, *commandBuffer);
794 
795 	const auto		texture0		= pipeline::readColorAttachment(vk, device, queue, queueFamilyIndex, allocator, *colorImages[0], colorFormat, UVec2(renderSize.x(), renderSize.y()));
796 
797 	const auto		tex1Access		= texture0->getAccess();
798 	for(deInt32 y = 0; y < tex1Access.getHeight(); ++y)
799 	{
800 		for(deInt32 x = 0; x < tex1Access.getWidth(); ++x)
801 		{
802 			if (tex1Access.getPixel(x, y) != Vec4(0.0f, 1.0f, 0.0f, 1.0f))
803 			{
804 				testCtx.getLog()
805 					<< TestLog::ImageSet("Result Images", "")
806 					<< TestLog::Image("Texture 0 (source)", "", texture0->getAccess())
807 					<< TestLog::EndImageSet;
808 
809 				return TestStatus::fail("Image comparison failed.");
810 			}
811 		}
812 	}
813 	return TestStatus::pass("OK");
814 }
815 } // namespace
816 
817 // Robustness1AccessInstance
818 
819 template<typename T>
820 class Robustness1AccessInstance : public vkt::TestInstance
821 {
822 public:
823 								Robustness1AccessInstance	(TestContext&							testCtx,
824 															 Context&								context,
825 															 T										device,
826 															 DeviceDriverPtr						deviceDriver,
827 															 const Robustness1TestInfo&				testInfo);
~Robustness1AccessInstance()828 	virtual						~Robustness1AccessInstance	() {}
829 	virtual TestStatus			iterate() override;
830 
831 private:
832 	TestContext&												m_testCtx;
833 	T															m_device;
834 #ifndef CTS_USES_VULKANSC
835 	de::MovePtr<vk::DeviceDriver>								m_deviceDriver;
836 #else
837 	de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter>	m_deviceDriver;
838 #endif // CTS_USES_VULKANSC
839 	const Robustness1TestInfo&									m_testInfo;
840 };
841 
842 template<typename T>
Robustness1AccessInstance(TestContext & testCtx,Context & context,T device,DeviceDriverPtr deviceDriver,const Robustness1TestInfo & testInfo)843 Robustness1AccessInstance<T>::Robustness1AccessInstance (TestContext&							testCtx,
844 														 Context&								context,
845 														 T										device,
846 														 DeviceDriverPtr						deviceDriver,
847 														 const Robustness1TestInfo&				testInfo)
848 	: vkt::TestInstance				(context)
849 	, m_testCtx						(testCtx)
850 	, m_device						(device)
851 	, m_deviceDriver				(deviceDriver)
852 	, m_testInfo					(testInfo)
853 {
854 }
855 
856 template<typename T>
iterate()857 TestStatus Robustness1AccessInstance<T>::iterate ()
858 {
859 	return m_testInfo.testFn(m_testCtx, m_context, *m_device, m_deviceDriver);
860 }
861 
862 // Robustness1AccessTest
863 
864 class Robustness1AccessTest : public vkt::TestCase
865 {
866 public:
867 							Robustness1AccessTest	(TestContext& testContext, const Robustness1TestInfo &testInfo);
~Robustness1AccessTest()868 	virtual					~Robustness1AccessTest	() {}
869 
870 	virtual TestInstance*	createInstance			(Context& context) const override;
871 
872 protected:
873 	virtual void			initPrograms			(SourceCollections& programCollection) const override;
874 
875 private:
876 	Robustness1TestInfo		m_testInfo;
877 };
878 
Robustness1AccessTest(TestContext & testContext,const Robustness1TestInfo & testInfo)879 Robustness1AccessTest::Robustness1AccessTest (TestContext &testContext, const Robustness1TestInfo& testInfo)
880 	: vkt::TestCase(testContext, testInfo.name),
881 	  m_testInfo(testInfo)
882 {
883 }
884 
createInstance(Context & context) const885 TestInstance *Robustness1AccessTest::createInstance (Context &context) const
886 {
887 	Move<VkDevice>	device = createRobustBufferAccessDevice(context);
888 #ifndef CTS_USES_VULKANSC
889 	DeviceDriverPtr	deviceDriver = DeviceDriverPtr (new DeviceDriver(context.getPlatformInterface(), context.getInstance(), *device, context.getUsedApiVersion()));
890 #else
891 	DeviceDriverPtr	deviceDriver = DeviceDriverPtr (new DeviceDriverSC(context.getPlatformInterface(), context.getInstance(), *device, context.getTestContext().getCommandLine(), context.getResourceInterface(), context.getDeviceVulkanSC10Properties(), context.getDeviceProperties(), context.getUsedApiVersion()), vk::DeinitDeviceDeleter( context.getResourceInterface().get(), *device ));
892 #endif // CTS_USES_VULKANSC
893 
894 	return new Robustness1AccessInstance<Move<VkDevice>>(m_testCtx, context, device, deviceDriver, m_testInfo);
895 }
896 
initPrograms(SourceCollections & programCollection) const897 void Robustness1AccessTest::initPrograms (SourceCollections& programCollection) const
898 {
899 	ostringstream vertexTestSource;
900 	vertexTestSource
901 		<< "#version 310 es\n"
902 		<< "precision highp float;\n"
903 		<< "layout(location = 0) in vec4 in_position;\n"
904 		<< "layout(location = 1) in vec4 in_color0;\n"
905 		<< "layout(location = 2) in vec4 in_color1;\n"
906 		<< "layout(location = 0) out vec4 out_color;\n"
907 		<< "bool is_valid(vec4 color)\n"
908 		<< "{\n"
909 		<< "  return\n";
910 	const auto compare_color = [](ostringstream& out, const string& variable, const Vec4& color)
911 	{
912 		out << setprecision(5) << fixed
913 			<< "	("
914 			<< variable << ".r - " << color.x() << " < 0.00001 && "
915 			<< variable << ".g - " << color.y() << " < 0.00001 && "
916 			<< variable << ".b - " << color.z() << " < 0.00001 && "
917 			<< variable << ".a - " << color.w() << " < 0.00001"
918 			<< ")";
919 	};
920 	for(vector<Vec4>::size_type i = 0; i < validColors.size(); ++i)
921 	{
922 		compare_color(vertexTestSource, "color", validColors[i]);
923 		vertexTestSource << ((i < validColors.size() - 1) ? " ||\n" : ";\n");
924 	}
925 	vertexTestSource
926 		<< "}\n"
927 		<< "bool is_invalid(vec4 color)\n"
928 		<< "{\n"
929 		<< "  return\n";
930 	for(vector<Vec4>::size_type i = 0; i < invalidColors.size(); ++i)
931 	{
932 		compare_color(vertexTestSource, "color", invalidColors[i]);
933 		vertexTestSource << ((i < invalidColors.size() - 1) ? " ||\n" : ";\n");
934 	}
935 	vertexTestSource
936 		<< "}\n"
937 		<< "bool validate(bool should_be_valid, vec4 color0, vec4 color1)\n"
938 		<< "{\n"
939 		<< "  return (should_be_valid && is_valid(color0) && is_valid(color1)) || (is_invalid(color0) && is_invalid(color1));\n"
940 		<< "}\n"
941 		<< "void main()\n"
942 		<< "{\n"
943 		<< "  out_color = validate(in_position.z >= 1.0, in_color0, in_color1) ? vec4(0,1,0,1) : in_color0;"
944 		<< "  gl_Position = vec4(in_position.xy, 0.0, 1.0);\n"
945 		<< "}\n";
946 	programCollection.glslSources.add("vertex-test") << glu::VertexSource(vertexTestSource.str());
947 	programCollection.glslSources.add("fragment-test") << glu::FragmentSource(
948 		"#version 310 es\n"
949 		"precision highp float;\n"
950 		"layout(location = 0) in vec4 in_color;\n"
951 		"layout(location = 0) out vec4 out_color;\n"
952 		"void main() {\n"
953 		"  out_color = in_color;\n"
954 		"}\n");
955 }
956 
createRobustness1VertexAccessTests(TestContext & testCtx)957 TestCaseGroup* createRobustness1VertexAccessTests (TestContext& testCtx)
958 {
959 	MovePtr<TestCaseGroup> robustness1AccessTests	(new TestCaseGroup(testCtx, "robustness1_vertex_access"));
960 	for(const auto& info : robustness1Tests)
961 	{
962 		robustness1AccessTests->addChild(new Robustness1AccessTest(testCtx, info));
963 	}
964 
965 	return robustness1AccessTests.release();
966 }
967 
968 } // robustness
969 } // vkt
970