1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file  vktSparseResourcesTestsUtil.cpp
21 * \brief Sparse Resources Tests Utility Classes
22 *//*--------------------------------------------------------------------*/
23
24#include "vktSparseResourcesTestsUtil.hpp"
25#include "vkQueryUtil.hpp"
26#include "vkDeviceUtil.hpp"
27#include "vkTypeUtil.hpp"
28#include "tcuTextureUtil.hpp"
29#include "deStringUtil.hpp"
30
31#include <deMath.h>
32
33using namespace vk;
34
35namespace vkt
36{
37namespace sparse
38{
39
40bool formatIsR64 (const VkFormat& format)
41{
42	switch (format)
43	{
44	case VK_FORMAT_R64_SINT:
45	case VK_FORMAT_R64_UINT:
46		return true;
47	default:
48		return false;
49	}
50}
51
52std::vector<TestFormat> getTestFormats (const ImageType& imageType)
53{
54	std::vector<TestFormat> results =
55	{
56		{ VK_FORMAT_R64_SINT },				{ VK_FORMAT_R32_SINT },				{ VK_FORMAT_R16_SINT },				{ VK_FORMAT_R8_SINT },
57		{ VK_FORMAT_R64_UINT },				{ VK_FORMAT_R32_UINT },				{ VK_FORMAT_R16_UINT },				{ VK_FORMAT_R8_UINT },
58
59											{ VK_FORMAT_R16_UNORM },			{ VK_FORMAT_R8_UNORM },
60											{ VK_FORMAT_R16_SNORM },			{ VK_FORMAT_R8_SNORM },
61		{ VK_FORMAT_R32G32_SINT },			{ VK_FORMAT_R16G16_SINT },			{ VK_FORMAT_R8G8_SINT },
62		{ VK_FORMAT_R32G32_UINT },			{ VK_FORMAT_R16G16_UINT },			{ VK_FORMAT_R8G8_UINT },
63											{ VK_FORMAT_R16G16_UNORM },			{ VK_FORMAT_R8G8_UNORM },
64											{ VK_FORMAT_R16G16_SNORM },			{ VK_FORMAT_R8G8_SNORM },
65		{ VK_FORMAT_R32G32B32A32_SINT },	{ VK_FORMAT_R16G16B16A16_SINT },	{ VK_FORMAT_R8G8B8A8_SINT },
66		{ VK_FORMAT_R32G32B32A32_UINT },	{ VK_FORMAT_R16G16B16A16_UINT },	{ VK_FORMAT_R8G8B8A8_UINT },
67											{ VK_FORMAT_R16G16B16A16_UNORM },	{ VK_FORMAT_R8G8B8A8_UNORM },
68											{ VK_FORMAT_R16G16B16A16_SNORM },	{ VK_FORMAT_R8G8B8A8_SNORM }
69	};
70
71	if (imageType == IMAGE_TYPE_2D || imageType == IMAGE_TYPE_2D_ARRAY)
72	{
73		std::vector<TestFormat> ycbcrFormats =
74		{
75			{ VK_FORMAT_G8B8G8R8_422_UNORM },
76			{ VK_FORMAT_B8G8R8G8_422_UNORM },
77			{ VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM },
78			{ VK_FORMAT_G8_B8R8_2PLANE_420_UNORM },
79			{ VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM },
80			{ VK_FORMAT_G8_B8R8_2PLANE_422_UNORM },
81			{ VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM },
82			{ VK_FORMAT_R10X6_UNORM_PACK16 },
83			{ VK_FORMAT_R10X6G10X6_UNORM_2PACK16 },
84			{ VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 },
85			{ VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16 },
86			{ VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16 },
87			{ VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16 },
88			{ VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 },
89			{ VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16 },
90			{ VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16 },
91			{ VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16 },
92			{ VK_FORMAT_R12X4_UNORM_PACK16 },
93			{ VK_FORMAT_R12X4G12X4_UNORM_2PACK16 },
94			{ VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 },
95			{ VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16 },
96			{ VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16 },
97			{ VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16 },
98			{ VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16 },
99			{ VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16 },
100			{ VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16 },
101			{ VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16 },
102			{ VK_FORMAT_G16B16G16R16_422_UNORM },
103			{ VK_FORMAT_B16G16R16G16_422_UNORM },
104			{ VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM },
105			{ VK_FORMAT_G16_B16R16_2PLANE_420_UNORM },
106			{ VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM },
107			{ VK_FORMAT_G16_B16R16_2PLANE_422_UNORM },
108			{ VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM },
109			{ VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT },
110			{ VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT },
111			{ VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT },
112			{ VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT },
113		};
114		std::copy(begin(ycbcrFormats), end(ycbcrFormats), std::back_inserter(results));
115	}
116
117	return results;
118}
119
120tcu::UVec3 getShaderGridSize (const ImageType imageType, const tcu::UVec3& imageSize, const deUint32 mipLevel)
121{
122	const deUint32 mipLevelX = std::max(imageSize.x() >> mipLevel, 1u);
123	const deUint32 mipLevelY = std::max(imageSize.y() >> mipLevel, 1u);
124	const deUint32 mipLevelZ = std::max(imageSize.z() >> mipLevel, 1u);
125
126	switch (imageType)
127	{
128		case IMAGE_TYPE_1D:
129			return tcu::UVec3(mipLevelX, 1u, 1u);
130
131		case IMAGE_TYPE_BUFFER:
132			return tcu::UVec3(imageSize.x(), 1u, 1u);
133
134		case IMAGE_TYPE_1D_ARRAY:
135			return tcu::UVec3(mipLevelX, imageSize.z(), 1u);
136
137		case IMAGE_TYPE_2D:
138			return tcu::UVec3(mipLevelX, mipLevelY, 1u);
139
140		case IMAGE_TYPE_2D_ARRAY:
141			return tcu::UVec3(mipLevelX, mipLevelY, imageSize.z());
142
143		case IMAGE_TYPE_3D:
144			return tcu::UVec3(mipLevelX, mipLevelY, mipLevelZ);
145
146		case IMAGE_TYPE_CUBE:
147			return tcu::UVec3(mipLevelX, mipLevelY, 6u);
148
149		case IMAGE_TYPE_CUBE_ARRAY:
150			return tcu::UVec3(mipLevelX, mipLevelY, 6u * imageSize.z());
151
152		default:
153			DE_FATAL("Unknown image type");
154			return tcu::UVec3(1u, 1u, 1u);
155	}
156}
157
158tcu::UVec3 getLayerSize (const ImageType imageType, const tcu::UVec3& imageSize)
159{
160	switch (imageType)
161	{
162		case IMAGE_TYPE_1D:
163		case IMAGE_TYPE_1D_ARRAY:
164		case IMAGE_TYPE_BUFFER:
165			return tcu::UVec3(imageSize.x(), 1u, 1u);
166
167		case IMAGE_TYPE_2D:
168		case IMAGE_TYPE_2D_ARRAY:
169		case IMAGE_TYPE_CUBE:
170		case IMAGE_TYPE_CUBE_ARRAY:
171			return tcu::UVec3(imageSize.x(), imageSize.y(), 1u);
172
173		case IMAGE_TYPE_3D:
174			return tcu::UVec3(imageSize.x(), imageSize.y(), imageSize.z());
175
176		default:
177			DE_FATAL("Unknown image type");
178			return tcu::UVec3(1u, 1u, 1u);
179	}
180}
181
182deUint32 getNumLayers (const ImageType imageType, const tcu::UVec3& imageSize)
183{
184	switch (imageType)
185	{
186		case IMAGE_TYPE_1D:
187		case IMAGE_TYPE_2D:
188		case IMAGE_TYPE_3D:
189		case IMAGE_TYPE_BUFFER:
190			return 1u;
191
192		case IMAGE_TYPE_1D_ARRAY:
193		case IMAGE_TYPE_2D_ARRAY:
194			return imageSize.z();
195
196		case IMAGE_TYPE_CUBE:
197			return 6u;
198
199		case IMAGE_TYPE_CUBE_ARRAY:
200			return imageSize.z() * 6u;
201
202		default:
203			DE_FATAL("Unknown image type");
204			return 0u;
205	}
206}
207
208deUint32 getNumPixels (const ImageType imageType, const tcu::UVec3& imageSize)
209{
210	const tcu::UVec3 gridSize = getShaderGridSize(imageType, imageSize);
211
212	return gridSize.x() * gridSize.y() * gridSize.z();
213}
214
215deUint32 getDimensions (const ImageType imageType)
216{
217	switch (imageType)
218	{
219		case IMAGE_TYPE_1D:
220		case IMAGE_TYPE_BUFFER:
221			return 1u;
222
223		case IMAGE_TYPE_1D_ARRAY:
224		case IMAGE_TYPE_2D:
225			return 2u;
226
227		case IMAGE_TYPE_2D_ARRAY:
228		case IMAGE_TYPE_CUBE:
229		case IMAGE_TYPE_CUBE_ARRAY:
230		case IMAGE_TYPE_3D:
231			return 3u;
232
233		default:
234			DE_FATAL("Unknown image type");
235			return 0u;
236	}
237}
238
239deUint32 getLayerDimensions (const ImageType imageType)
240{
241	switch (imageType)
242	{
243		case IMAGE_TYPE_1D:
244		case IMAGE_TYPE_BUFFER:
245		case IMAGE_TYPE_1D_ARRAY:
246			return 1u;
247
248		case IMAGE_TYPE_2D:
249		case IMAGE_TYPE_2D_ARRAY:
250		case IMAGE_TYPE_CUBE:
251		case IMAGE_TYPE_CUBE_ARRAY:
252			return 2u;
253
254		case IMAGE_TYPE_3D:
255			return 3u;
256
257		default:
258			DE_FATAL("Unknown image type");
259			return 0u;
260	}
261}
262
263bool isImageSizeSupported (const InstanceInterface& instance, const VkPhysicalDevice physicalDevice, const ImageType imageType, const tcu::UVec3& imageSize)
264{
265	const VkPhysicalDeviceProperties deviceProperties = getPhysicalDeviceProperties(instance, physicalDevice);
266
267	switch (imageType)
268	{
269		case IMAGE_TYPE_1D:
270			return	imageSize.x() <= deviceProperties.limits.maxImageDimension1D;
271		case IMAGE_TYPE_1D_ARRAY:
272			return	imageSize.x() <= deviceProperties.limits.maxImageDimension1D &&
273					imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
274		case IMAGE_TYPE_2D:
275			return	imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
276					imageSize.y() <= deviceProperties.limits.maxImageDimension2D;
277		case IMAGE_TYPE_2D_ARRAY:
278			return	imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
279					imageSize.y() <= deviceProperties.limits.maxImageDimension2D &&
280					imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
281		case IMAGE_TYPE_CUBE:
282			return	imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
283					imageSize.y() <= deviceProperties.limits.maxImageDimensionCube;
284		case IMAGE_TYPE_CUBE_ARRAY:
285			return	imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
286					imageSize.y() <= deviceProperties.limits.maxImageDimensionCube &&
287					imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
288		case IMAGE_TYPE_3D:
289			return	imageSize.x() <= deviceProperties.limits.maxImageDimension3D &&
290					imageSize.y() <= deviceProperties.limits.maxImageDimension3D &&
291					imageSize.z() <= deviceProperties.limits.maxImageDimension3D;
292		case IMAGE_TYPE_BUFFER:
293			return true;
294		default:
295			DE_FATAL("Unknown image type");
296			return false;
297	}
298}
299
300VkBufferImageCopy makeBufferImageCopy (const VkExtent3D		extent,
301									   const deUint32		layerCount,
302									   const deUint32		mipmapLevel,
303									   const VkDeviceSize	bufferOffset)
304{
305	const VkBufferImageCopy copyParams =
306	{
307		bufferOffset,																		//	VkDeviceSize				bufferOffset;
308		0u,																					//	deUint32					bufferRowLength;
309		0u,																					//	deUint32					bufferImageHeight;
310		makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, mipmapLevel, 0u, layerCount),	//	VkImageSubresourceLayers	imageSubresource;
311		makeOffset3D(0, 0, 0),																//	VkOffset3D					imageOffset;
312		extent,																				//	VkExtent3D					imageExtent;
313	};
314	return copyParams;
315}
316
317void submitCommands (const DeviceInterface&			vk,
318					 const VkQueue					queue,
319					 const VkCommandBuffer			commandBuffer,
320					 const deUint32					waitSemaphoreCount,
321					 const VkSemaphore*				pWaitSemaphores,
322					 const VkPipelineStageFlags*	pWaitDstStageMask,
323					 const deUint32					signalSemaphoreCount,
324					 const VkSemaphore*				pSignalSemaphores)
325{
326	const VkSubmitInfo submitInfo =
327	{
328		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
329		DE_NULL,						// const void*					pNext;
330		waitSemaphoreCount,				// deUint32						waitSemaphoreCount;
331		pWaitSemaphores,				// const VkSemaphore*			pWaitSemaphores;
332		pWaitDstStageMask,				// const VkPipelineStageFlags*	pWaitDstStageMask;
333		1u,								// deUint32						commandBufferCount;
334		&commandBuffer,					// const VkCommandBuffer*		pCommandBuffers;
335		signalSemaphoreCount,			// deUint32						signalSemaphoreCount;
336		pSignalSemaphores,				// const VkSemaphore*			pSignalSemaphores;
337	};
338
339	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, DE_NULL));
340}
341
342void submitCommandsAndWait (const DeviceInterface&		vk,
343							const VkDevice				device,
344							const VkQueue				queue,
345							const VkCommandBuffer		commandBuffer,
346							const deUint32				waitSemaphoreCount,
347							const VkSemaphore*			pWaitSemaphores,
348							const VkPipelineStageFlags*	pWaitDstStageMask,
349							const deUint32				signalSemaphoreCount,
350							const VkSemaphore*			pSignalSemaphores,
351							const bool					useDeviceGroups,
352							const deUint32				physicalDeviceID)
353{
354	const VkFenceCreateInfo	fenceParams				=
355	{
356		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,				// VkStructureType		sType;
357		DE_NULL,											// const void*			pNext;
358		0u,													// VkFenceCreateFlags	flags;
359	};
360	const Unique<VkFence>	fence(createFence		(vk, device, &fenceParams));
361
362	const deUint32			deviceMask				= 1 << physicalDeviceID;
363	std::vector<deUint32>	deviceIndices			(waitSemaphoreCount, physicalDeviceID);
364	VkDeviceGroupSubmitInfo deviceGroupSubmitInfo	=
365	{
366		VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO,			//VkStructureType		sType
367		DE_NULL,											// const void*			pNext
368		waitSemaphoreCount,									// uint32_t				waitSemaphoreCount
369		deviceIndices.size() ? &deviceIndices[0] : DE_NULL,	// const uint32_t*		pWaitSemaphoreDeviceIndices
370		1u,													// uint32_t				commandBufferCount
371		&deviceMask,										// const uint32_t*		pCommandBufferDeviceMasks
372		0u,													// uint32_t				signalSemaphoreCount
373		DE_NULL,											// const uint32_t*		pSignalSemaphoreDeviceIndices
374	};
375	const VkSubmitInfo		submitInfo				=
376	{
377		VK_STRUCTURE_TYPE_SUBMIT_INFO,						// VkStructureType				sType;
378		useDeviceGroups ? &deviceGroupSubmitInfo : DE_NULL,	// const void*					pNext;
379		waitSemaphoreCount,									// deUint32						waitSemaphoreCount;
380		pWaitSemaphores,									// const VkSemaphore*			pWaitSemaphores;
381		pWaitDstStageMask,									// const VkPipelineStageFlags*	pWaitDstStageMask;
382		1u,													// deUint32						commandBufferCount;
383		&commandBuffer,										// const VkCommandBuffer*		pCommandBuffers;
384		signalSemaphoreCount,								// deUint32						signalSemaphoreCount;
385		pSignalSemaphores,									// const VkSemaphore*			pSignalSemaphores;
386	};
387
388	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
389	VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
390}
391
392VkImageType	mapImageType (const ImageType imageType)
393{
394	switch (imageType)
395	{
396		case IMAGE_TYPE_1D:
397		case IMAGE_TYPE_1D_ARRAY:
398		case IMAGE_TYPE_BUFFER:
399			return VK_IMAGE_TYPE_1D;
400
401		case IMAGE_TYPE_2D:
402		case IMAGE_TYPE_2D_ARRAY:
403		case IMAGE_TYPE_CUBE:
404		case IMAGE_TYPE_CUBE_ARRAY:
405			return VK_IMAGE_TYPE_2D;
406
407		case IMAGE_TYPE_3D:
408			return VK_IMAGE_TYPE_3D;
409
410		default:
411			DE_FATAL("Unexpected image type");
412			return VK_IMAGE_TYPE_LAST;
413	}
414}
415
416VkImageViewType	mapImageViewType (const ImageType imageType)
417{
418	switch (imageType)
419	{
420		case IMAGE_TYPE_1D:			return VK_IMAGE_VIEW_TYPE_1D;
421		case IMAGE_TYPE_1D_ARRAY:	return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
422		case IMAGE_TYPE_2D:			return VK_IMAGE_VIEW_TYPE_2D;
423		case IMAGE_TYPE_2D_ARRAY:	return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
424		case IMAGE_TYPE_3D:			return VK_IMAGE_VIEW_TYPE_3D;
425		case IMAGE_TYPE_CUBE:		return VK_IMAGE_VIEW_TYPE_CUBE;
426		case IMAGE_TYPE_CUBE_ARRAY:	return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
427
428		default:
429			DE_FATAL("Unexpected image type");
430			return VK_IMAGE_VIEW_TYPE_LAST;
431	}
432}
433
434std::string getImageTypeName (const ImageType imageType)
435{
436	switch (imageType)
437	{
438		case IMAGE_TYPE_1D:			return "1d";
439		case IMAGE_TYPE_1D_ARRAY:	return "1d_array";
440		case IMAGE_TYPE_2D:			return "2d";
441		case IMAGE_TYPE_2D_ARRAY:	return "2d_array";
442		case IMAGE_TYPE_3D:			return "3d";
443		case IMAGE_TYPE_CUBE:		return "cube";
444		case IMAGE_TYPE_CUBE_ARRAY:	return "cube_array";
445		case IMAGE_TYPE_BUFFER:		return "buffer";
446
447		default:
448			DE_FATAL("Unexpected image type");
449			return "";
450	}
451}
452
453std::string getShaderImageType (const tcu::TextureFormat& format, const ImageType imageType)
454{
455	std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
456							 tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER   ? "i" : "";
457
458	std::string imageTypePart;
459	switch (imageType)
460	{
461		case IMAGE_TYPE_1D:			imageTypePart = "1D";			break;
462		case IMAGE_TYPE_1D_ARRAY:	imageTypePart = "1DArray";		break;
463		case IMAGE_TYPE_2D:			imageTypePart = "2D";			break;
464		case IMAGE_TYPE_2D_ARRAY:	imageTypePart = "2DArray";		break;
465		case IMAGE_TYPE_3D:			imageTypePart = "3D";			break;
466		case IMAGE_TYPE_CUBE:		imageTypePart = "Cube";			break;
467		case IMAGE_TYPE_CUBE_ARRAY:	imageTypePart = "CubeArray";	break;
468		case IMAGE_TYPE_BUFFER:		imageTypePart = "Buffer";		break;
469
470		default:
471			DE_FATAL("Unexpected image type");
472	}
473
474	return formatPart + "image" + imageTypePart;
475}
476
477std::string getShaderImageType (const vk::PlanarFormatDescription& description, const ImageType imageType)
478{
479	std::string	formatPart;
480	std::string	imageTypePart;
481
482	// all PlanarFormatDescription types have at least one channel ( 0 ) and all channel types are the same :
483	switch (description.channels[0].type)
484	{
485		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
486			formatPart = "i";
487			break;
488		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
489			formatPart = "u";
490			break;
491		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
492		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
493		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
494			break;
495
496		default:
497			DE_FATAL("Unexpected channel type");
498	}
499
500	if (formatIsR64(description.planes[0].planeCompatibleFormat))
501		formatPart += "64";
502
503	switch (imageType)
504	{
505		case IMAGE_TYPE_1D:			imageTypePart = "1D";			break;
506		case IMAGE_TYPE_1D_ARRAY:	imageTypePart = "1DArray";		break;
507		case IMAGE_TYPE_2D:			imageTypePart = "2D";			break;
508		case IMAGE_TYPE_2D_ARRAY:	imageTypePart = "2DArray";		break;
509		case IMAGE_TYPE_3D:			imageTypePart = "3D";			break;
510		case IMAGE_TYPE_CUBE:		imageTypePart = "Cube";			break;
511		case IMAGE_TYPE_CUBE_ARRAY:	imageTypePart = "CubeArray";	break;
512		case IMAGE_TYPE_BUFFER:		imageTypePart = "Buffer";		break;
513
514		default:
515			DE_FATAL("Unexpected image type");
516	}
517
518	return formatPart + "image" + imageTypePart;
519}
520
521std::string getShaderImageDataType(const tcu::TextureFormat& format)
522{
523	switch (tcu::getTextureChannelClass(format.type))
524	{
525		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
526			return "uvec4";
527		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
528			return "ivec4";
529		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
530		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
531		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
532			return "vec4";
533		default:
534			DE_FATAL("Unexpected channel type");
535			return "";
536	}
537}
538
539std::string getShaderImageDataType (const vk::PlanarFormatDescription& description)
540{
541	switch (description.channels[0].type)
542	{
543		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
544			return (formatIsR64(description.planes[0].planeCompatibleFormat) ? "u64vec4" : "uvec4");
545		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
546			return (formatIsR64(description.planes[0].planeCompatibleFormat) ? "i64vec4" : "ivec4");
547		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
548		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
549		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
550			return "vec4";
551		default:
552			DE_FATAL("Unexpected channel type");
553			return "";
554	}
555}
556
557std::string getShaderImageFormatQualifier (const tcu::TextureFormat& format)
558{
559	const char* orderPart;
560	const char* typePart;
561
562	switch (format.order)
563	{
564		case tcu::TextureFormat::R:		orderPart = "r";	break;
565		case tcu::TextureFormat::RG:	orderPart = "rg";	break;
566		case tcu::TextureFormat::RGB:	orderPart = "rgb";	break;
567		case tcu::TextureFormat::RGBA:	orderPart = "rgba";	break;
568
569		default:
570			DE_FATAL("Unexpected channel order");
571			orderPart = DE_NULL;
572	}
573
574	switch (format.type)
575	{
576		case tcu::TextureFormat::FLOAT:				typePart = "32f";		break;
577		case tcu::TextureFormat::HALF_FLOAT:		typePart = "16f";		break;
578
579		case tcu::TextureFormat::UNSIGNED_INT32:	typePart = "32ui";		break;
580		case tcu::TextureFormat::UNSIGNED_INT16:	typePart = "16ui";		break;
581		case tcu::TextureFormat::UNSIGNED_INT8:		typePart = "8ui";		break;
582
583		case tcu::TextureFormat::SIGNED_INT32:		typePart = "32i";		break;
584		case tcu::TextureFormat::SIGNED_INT16:		typePart = "16i";		break;
585		case tcu::TextureFormat::SIGNED_INT8:		typePart = "8i";		break;
586
587		case tcu::TextureFormat::UNORM_INT16:		typePart = "16";		break;
588		case tcu::TextureFormat::UNORM_INT8:		typePart = "8";			break;
589
590		case tcu::TextureFormat::SNORM_INT16:		typePart = "16_snorm";	break;
591		case tcu::TextureFormat::SNORM_INT8:		typePart = "8_snorm";	break;
592
593		default:
594			DE_FATAL("Unexpected channel type");
595			typePart = DE_NULL;
596	}
597
598	return std::string() + orderPart + typePart;
599}
600
601std::string getShaderImageFormatQualifier (VkFormat format)
602{
603	switch (format)
604	{
605		case VK_FORMAT_R8_SINT:										return "r8i";
606		case VK_FORMAT_R16_SINT:									return "r16i";
607		case VK_FORMAT_R32_SINT:									return "r32i";
608		case VK_FORMAT_R64_SINT:									return "r64i";
609		case VK_FORMAT_R8_UINT:										return "r8ui";
610		case VK_FORMAT_R16_UINT:									return "r16ui";
611		case VK_FORMAT_R32_UINT:									return "r32ui";
612		case VK_FORMAT_R64_UINT:									return "r64ui";
613		case VK_FORMAT_R8_SNORM:									return "r8_snorm";
614		case VK_FORMAT_R16_SNORM:									return "r16_snorm";
615		case VK_FORMAT_R8_UNORM:									return "r8";
616		case VK_FORMAT_R16_UNORM:									return "r16";
617
618		case VK_FORMAT_R8G8_SINT:									return "rg8i";
619		case VK_FORMAT_R16G16_SINT:									return "rg16i";
620		case VK_FORMAT_R32G32_SINT:									return "rg32i";
621		case VK_FORMAT_R8G8_UINT:									return "rg8ui";
622		case VK_FORMAT_R16G16_UINT:									return "rg16ui";
623		case VK_FORMAT_R32G32_UINT:									return "rg32ui";
624		case VK_FORMAT_R8G8_SNORM:									return "rg8_snorm";
625		case VK_FORMAT_R16G16_SNORM:								return "rg16_snorm";
626		case VK_FORMAT_R8G8_UNORM:									return "rg8";
627		case VK_FORMAT_R16G16_UNORM:								return "rg16";
628
629		case VK_FORMAT_R8G8B8A8_SINT:								return "rgba8i";
630		case VK_FORMAT_R16G16B16A16_SINT:							return "rgba16i";
631		case VK_FORMAT_R32G32B32A32_SINT:							return "rgba32i";
632		case VK_FORMAT_R8G8B8A8_UINT:								return "rgba8ui";
633		case VK_FORMAT_R16G16B16A16_UINT:							return "rgba16ui";
634		case VK_FORMAT_R32G32B32A32_UINT:							return "rgba32ui";
635		case VK_FORMAT_R8G8B8A8_SNORM:								return "rgba8_snorm";
636		case VK_FORMAT_R16G16B16A16_SNORM:							return "rgba16_snorm";
637		case VK_FORMAT_R8G8B8A8_UNORM:								return "rgba8";
638		case VK_FORMAT_R16G16B16A16_UNORM:							return "rgba16";
639
640		case VK_FORMAT_G8B8G8R8_422_UNORM:							return "rgba8";
641		case VK_FORMAT_B8G8R8G8_422_UNORM:							return "rgba8";
642		case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:					return "rgba8";
643		case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:					return "rgba8";
644		case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:					return "rgba8";
645		case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:					return "rgba8";
646		case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:					return "rgba8";
647		case VK_FORMAT_R10X6_UNORM_PACK16:							return "r16";
648		case VK_FORMAT_R10X6G10X6_UNORM_2PACK16:					return "rg16";
649		case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:			return "rgba16";
650		case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16:		return "rgba16";
651		case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16:		return "rgba16";
652		case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:	return "rgba16";
653		case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:	return "rgba16";
654		case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:	return "rgba16";
655		case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:	return "rgba16";
656		case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:	return "rgba16";
657		case VK_FORMAT_R12X4_UNORM_PACK16:							return "r16";
658		case VK_FORMAT_R12X4G12X4_UNORM_2PACK16:					return "rg16";
659		case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16:			return "rgba16";
660		case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16:		return "rgba16";
661		case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16:		return "rgba16";
662		case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:	return "rgba16";
663		case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:	return "rgba16";
664		case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:	return "rgba16";
665		case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:	return "rgba16";
666		case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:	return "rgba16";
667		case VK_FORMAT_G16B16G16R16_422_UNORM:						return "rgba16";
668		case VK_FORMAT_B16G16R16G16_422_UNORM:						return "rgba16";
669		case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:				return "rgba16";
670		case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:					return "rgba16";
671		case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:				return "rgba16";
672		case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:					return "rgba16";
673		case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:				return "rgba16";
674		case VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT:				return "rgba8";
675		case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT:return "rgba16";
676		case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT:return "rgba16";
677		case VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT:				return "rgba16";
678
679		default:
680			DE_FATAL("Unexpected texture format");
681			return "error";
682	}
683}
684
685std::string getImageFormatID (VkFormat format)
686{
687	switch (format)
688	{
689		case VK_FORMAT_R8_SINT:				return "r8i";
690		case VK_FORMAT_R16_SINT:			return "r16i";
691		case VK_FORMAT_R32_SINT:			return "r32i";
692		case VK_FORMAT_R64_SINT:			return "r64i";
693		case VK_FORMAT_R8_UINT:				return "r8ui";
694		case VK_FORMAT_R16_UINT:			return "r16ui";
695		case VK_FORMAT_R32_UINT:			return "r32ui";
696		case VK_FORMAT_R64_UINT:			return "r64ui";
697		case VK_FORMAT_R8_SNORM:			return "r8_snorm";
698		case VK_FORMAT_R16_SNORM:			return "r16_snorm";
699		case VK_FORMAT_R8_UNORM:			return "r8";
700		case VK_FORMAT_R16_UNORM:			return "r16";
701
702		case VK_FORMAT_R8G8_SINT:			return "rg8i";
703		case VK_FORMAT_R16G16_SINT:			return "rg16i";
704		case VK_FORMAT_R32G32_SINT:			return "rg32i";
705		case VK_FORMAT_R8G8_UINT:			return "rg8ui";
706		case VK_FORMAT_R16G16_UINT:			return "rg16ui";
707		case VK_FORMAT_R32G32_UINT:			return "rg32ui";
708		case VK_FORMAT_R8G8_SNORM:			return "rg8_snorm";
709		case VK_FORMAT_R16G16_SNORM:		return "rg16_snorm";
710		case VK_FORMAT_R8G8_UNORM:			return "rg8";
711		case VK_FORMAT_R16G16_UNORM:		return "rg16";
712
713		case VK_FORMAT_R8G8B8A8_SINT:		return "rgba8i";
714		case VK_FORMAT_R16G16B16A16_SINT:	return "rgba16i";
715		case VK_FORMAT_R32G32B32A32_SINT:	return "rgba32i";
716		case VK_FORMAT_R8G8B8A8_UINT:		return "rgba8ui";
717		case VK_FORMAT_R16G16B16A16_UINT:	return "rgba16ui";
718		case VK_FORMAT_R32G32B32A32_UINT:	return "rgba32ui";
719		case VK_FORMAT_R8G8B8A8_SNORM:		return "rgba8_snorm";
720		case VK_FORMAT_R16G16B16A16_SNORM:	return "rgba16_snorm";
721		case VK_FORMAT_R8G8B8A8_UNORM:		return "rgba8";
722		case VK_FORMAT_R16G16B16A16_UNORM:	return "rgba16";
723
724		case VK_FORMAT_G8B8G8R8_422_UNORM:
725		case VK_FORMAT_B8G8R8G8_422_UNORM:
726		case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
727		case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
728		case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
729		case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
730		case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
731		case VK_FORMAT_R10X6_UNORM_PACK16:
732		case VK_FORMAT_R10X6G10X6_UNORM_2PACK16:
733		case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16:
734		case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16:
735		case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16:
736		case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
737		case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
738		case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
739		case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
740		case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
741		case VK_FORMAT_R12X4_UNORM_PACK16:
742		case VK_FORMAT_R12X4G12X4_UNORM_2PACK16:
743		case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16:
744		case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16:
745		case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16:
746		case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
747		case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
748		case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
749		case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
750		case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
751		case VK_FORMAT_G16B16G16R16_422_UNORM:
752		case VK_FORMAT_B16G16R16G16_422_UNORM:
753		case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
754		case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
755		case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
756		case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
757		case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
758		case VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT:
759		case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT:
760		case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT:
761		case VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT:
762#ifndef CTS_USES_VULKANSC
763		case VK_FORMAT_A8_UNORM_KHR:
764#endif // CTS_USES_VULKANSC
765			return de::toLower(std::string(getFormatName(format)).substr(10));
766
767		default:
768			DE_FATAL("Unexpected texture format");
769			return "error";
770	}
771}
772
773std::string getShaderImageCoordinates	(const ImageType	imageType,
774										 const std::string&	x,
775										 const std::string&	xy,
776										 const std::string&	xyz)
777{
778	switch (imageType)
779	{
780		case IMAGE_TYPE_1D:
781		case IMAGE_TYPE_BUFFER:
782			return x;
783
784		case IMAGE_TYPE_1D_ARRAY:
785		case IMAGE_TYPE_2D:
786			return xy;
787
788		case IMAGE_TYPE_2D_ARRAY:
789		case IMAGE_TYPE_3D:
790		case IMAGE_TYPE_CUBE:
791		case IMAGE_TYPE_CUBE_ARRAY:
792			return xyz;
793
794		default:
795			DE_FATAL("Unexpected image type");
796			return "";
797	}
798}
799
800deUint32 getImageMipLevelSizeInBytes(const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevel, const deUint32 mipmapMemoryAlignment)
801{
802	const VkExtent3D extents = mipLevelExtents(baseExtents, mipmapLevel);
803
804	return deAlign32(extents.width * extents.height * extents.depth * layersCount * tcu::getPixelSize(format), mipmapMemoryAlignment);
805}
806
807deUint32 getImageSizeInBytes(const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevelsCount, const deUint32 mipmapMemoryAlignment)
808{
809	deUint32 imageSizeInBytes = 0;
810	for (deUint32 mipmapLevel = 0; mipmapLevel < mipmapLevelsCount; ++mipmapLevel)
811		imageSizeInBytes += getImageMipLevelSizeInBytes(baseExtents, layersCount, format, mipmapLevel, mipmapMemoryAlignment);
812
813	return imageSizeInBytes;
814}
815
816deUint32 getImageMipLevelSizeInBytes (const VkExtent3D& baseExtents, const deUint32 layersCount, const vk::PlanarFormatDescription& formatDescription, const deUint32 planeNdx, const deUint32 mipmapLevel, const deUint32 mipmapMemoryAlignment)
817{
818	return layersCount * getPlaneSizeInBytes(formatDescription, baseExtents, planeNdx, mipmapLevel, mipmapMemoryAlignment);
819}
820
821deUint32 getImageSizeInBytes (const VkExtent3D& baseExtents, const deUint32 layersCount, const vk::PlanarFormatDescription& formatDescription, const deUint32 planeNdx, const deUint32 mipmapLevelsCount, const deUint32 mipmapMemoryAlignment)
822{
823	deUint32 imageSizeInBytes = 0;
824
825	for (deUint32 mipmapLevel = 0; mipmapLevel < mipmapLevelsCount; ++mipmapLevel)
826		imageSizeInBytes += getImageMipLevelSizeInBytes(baseExtents, layersCount, formatDescription, planeNdx, mipmapLevel, mipmapMemoryAlignment);
827
828	return imageSizeInBytes;
829}
830
831VkSparseImageMemoryBind	makeSparseImageMemoryBind  (const DeviceInterface&			vk,
832													const VkDevice					device,
833													const VkDeviceSize				allocationSize,
834													const deUint32					memoryType,
835													const VkImageSubresource&		subresource,
836													const VkOffset3D&				offset,
837													const VkExtent3D&				extent)
838{
839	const VkMemoryAllocateInfo	allocInfo =
840	{
841		VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,	//	VkStructureType			sType;
842		DE_NULL,								//	const void*				pNext;
843		allocationSize,							//	VkDeviceSize			allocationSize;
844		memoryType,								//	deUint32				memoryTypeIndex;
845	};
846
847	VkDeviceMemory deviceMemory = 0;
848	VK_CHECK(vk.allocateMemory(device, &allocInfo, DE_NULL, &deviceMemory));
849
850	VkSparseImageMemoryBind imageMemoryBind;
851
852	imageMemoryBind.subresource		= subresource;
853	imageMemoryBind.memory			= deviceMemory;
854	imageMemoryBind.memoryOffset	= 0u;
855	imageMemoryBind.flags			= 0u;
856	imageMemoryBind.offset			= offset;
857	imageMemoryBind.extent			= extent;
858
859	return imageMemoryBind;
860}
861
862VkSparseMemoryBind makeSparseMemoryBind	(const DeviceInterface&			vk,
863										 const VkDevice					device,
864										 const VkDeviceSize				allocationSize,
865										 const deUint32					memoryType,
866										 const VkDeviceSize				resourceOffset,
867										 const VkSparseMemoryBindFlags	flags)
868{
869	const VkMemoryAllocateInfo allocInfo =
870	{
871		VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,	//	VkStructureType	sType;
872		DE_NULL,								//	const void*		pNext;
873		allocationSize,							//	VkDeviceSize	allocationSize;
874		memoryType,								//	deUint32		memoryTypeIndex;
875	};
876
877	VkDeviceMemory deviceMemory = 0;
878	VK_CHECK(vk.allocateMemory(device, &allocInfo, DE_NULL, &deviceMemory));
879
880	VkSparseMemoryBind memoryBind;
881
882	memoryBind.resourceOffset	= resourceOffset;
883	memoryBind.size				= allocationSize;
884	memoryBind.memory			= deviceMemory;
885	memoryBind.memoryOffset		= 0u;
886	memoryBind.flags			= flags;
887
888	return memoryBind;
889}
890
891void requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags)
892{
893	const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
894
895	if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader)
896		throw tcu::NotSupportedError("Tessellation shader not supported");
897
898	if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader)
899		throw tcu::NotSupportedError("Geometry shader not supported");
900
901	if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64)
902		throw tcu::NotSupportedError("Double-precision floats not supported");
903
904	if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics)
905		throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline");
906
907	if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics)
908		throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader");
909
910	if (((flags & FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE) != 0) && !features.shaderTessellationAndGeometryPointSize)
911		throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in");
912}
913
914deUint32 findMatchingMemoryType (const InstanceInterface&		instance,
915								 const VkPhysicalDevice			physicalDevice,
916								 const VkMemoryRequirements&	objectMemoryRequirements,
917								 const MemoryRequirement&		memoryRequirement)
918{
919	const VkPhysicalDeviceMemoryProperties deviceMemoryProperties = getPhysicalDeviceMemoryProperties(instance, physicalDevice);
920
921	for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < deviceMemoryProperties.memoryTypeCount; ++memoryTypeNdx)
922	{
923		if ((objectMemoryRequirements.memoryTypeBits & (1u << memoryTypeNdx)) != 0 &&
924			memoryRequirement.matchesHeap(deviceMemoryProperties.memoryTypes[memoryTypeNdx].propertyFlags))
925		{
926			return memoryTypeNdx;
927		}
928	}
929
930	return NO_MATCH_FOUND;
931}
932
933deUint32 getHeapIndexForMemoryType (const InstanceInterface&	instance,
934									const VkPhysicalDevice		physicalDevice,
935									const deUint32				memoryType)
936{
937	const VkPhysicalDeviceMemoryProperties deviceMemoryProperties = getPhysicalDeviceMemoryProperties(instance, physicalDevice);
938	DE_ASSERT(memoryType < deviceMemoryProperties.memoryTypeCount);
939	return deviceMemoryProperties.memoryTypes[memoryType].heapIndex;
940}
941
942bool checkSparseSupportForImageType (const InstanceInterface&	instance,
943									 const VkPhysicalDevice		physicalDevice,
944									 const ImageType			imageType)
945{
946	const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(instance, physicalDevice);
947
948	if (!deviceFeatures.sparseBinding)
949		return false;
950
951	switch (mapImageType(imageType))
952	{
953		case VK_IMAGE_TYPE_2D:
954			return deviceFeatures.sparseResidencyImage2D == VK_TRUE;
955		case VK_IMAGE_TYPE_3D:
956			return deviceFeatures.sparseResidencyImage3D == VK_TRUE;
957		default:
958			DE_FATAL("Unexpected image type");
959			return false;
960	}
961}
962
963bool checkSparseSupportForImageFormat (const InstanceInterface&	instance,
964									   const VkPhysicalDevice	physicalDevice,
965									   const VkImageCreateInfo&	imageInfo)
966{
967	const std::vector<VkSparseImageFormatProperties> sparseImageFormatPropVec = getPhysicalDeviceSparseImageFormatProperties(
968		instance, physicalDevice, imageInfo.format, imageInfo.imageType, imageInfo.samples, imageInfo.usage, imageInfo.tiling);
969
970	return sparseImageFormatPropVec.size() > 0u;
971}
972
973bool checkImageFormatFeatureSupport (const InstanceInterface&	instance,
974									 const VkPhysicalDevice		physicalDevice,
975									 const VkFormat				format,
976									 const VkFormatFeatureFlags	featureFlags)
977{
978	const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(instance, physicalDevice, format);
979
980	return (formatProperties.optimalTilingFeatures & featureFlags) == featureFlags;
981}
982
983deUint32 getSparseAspectRequirementsIndex (const std::vector<VkSparseImageMemoryRequirements>&	requirements,
984										   const VkImageAspectFlags								aspectFlags)
985{
986	for (deUint32 memoryReqNdx = 0; memoryReqNdx < requirements.size(); ++memoryReqNdx)
987	{
988		if (requirements[memoryReqNdx].formatProperties.aspectMask & aspectFlags)
989			return memoryReqNdx;
990	}
991
992	return NO_MATCH_FOUND;
993}
994
995vk::VkFormat getPlaneCompatibleFormatForWriting(const vk::PlanarFormatDescription& formatInfo, deUint32 planeNdx)
996{
997	DE_ASSERT(planeNdx < formatInfo.numPlanes);
998	vk::VkFormat result = formatInfo.planes[planeNdx].planeCompatibleFormat;
999
1000	// redirect result for some of the YCbCr image formats
1001	static const std::pair<vk::VkFormat, vk::VkFormat> ycbcrFormats[] =
1002	{
1003		{ VK_FORMAT_G8B8G8R8_422_UNORM,						VK_FORMAT_R8G8B8A8_UNORM		},
1004		{ VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,	VK_FORMAT_R16G16B16A16_UNORM	},
1005		{ VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,	VK_FORMAT_R16G16B16A16_UNORM	},
1006		{ VK_FORMAT_G16B16G16R16_422_UNORM,					VK_FORMAT_R16G16B16A16_UNORM	},
1007		{ VK_FORMAT_B8G8R8G8_422_UNORM,						VK_FORMAT_R8G8B8A8_UNORM		},
1008		{ VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,	VK_FORMAT_R16G16B16A16_UNORM	},
1009		{ VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,	VK_FORMAT_R16G16B16A16_UNORM	},
1010		{ VK_FORMAT_B16G16R16G16_422_UNORM,					VK_FORMAT_R16G16B16A16_UNORM	}
1011	};
1012	auto it = std::find_if(std::begin(ycbcrFormats), std::end(ycbcrFormats), [result](const std::pair<vk::VkFormat, vk::VkFormat>& p) { return p.first == result; });
1013	if (it != std::end(ycbcrFormats))
1014		result = it->second;
1015	return result;
1016}
1017
1018bool areLsb6BitsDontCare(vk::VkFormat format)
1019{
1020	if ((format == vk::VK_FORMAT_R10X6_UNORM_PACK16)                         ||
1021		(format == vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16)                   ||
1022		(format == vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16)         ||
1023		(format == vk::VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16)     ||
1024		(format == vk::VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16)     ||
1025		(format == vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16)  ||
1026		(format == vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16) ||
1027		(format == vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16) ||
1028		(format == vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16)  ||
1029		(format == vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16))
1030	{
1031		return true;
1032	}
1033
1034	return false;
1035}
1036
1037bool areLsb4BitsDontCare(vk::VkFormat format)
1038{
1039	if ((format == vk::VK_FORMAT_R12X4_UNORM_PACK16)                         ||
1040		(format == vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16)                   ||
1041		(format == vk::VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16)         ||
1042		(format == vk::VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16)     ||
1043		(format == vk::VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16)     ||
1044		(format == vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16) ||
1045		(format == vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16)  ||
1046		(format == vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16) ||
1047		(format == vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16)  ||
1048		(format == vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16))
1049	{
1050		return true;
1051	}
1052
1053	return false;
1054}
1055
1056} // sparse
1057} // vkt
1058