Home | History | Annotate | Download | only in image
      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
     21  * \brief Image Tests Utility Classes
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "vktImageTestsUtil.hpp"
     25 #include "vkQueryUtil.hpp"
     26 #include "vkTypeUtil.hpp"
     27 #include "tcuTextureUtil.hpp"
     28 
     29 using namespace vk;
     30 
     31 namespace vkt
     32 {
     33 namespace image
     34 {
     35 
     36 Buffer::Buffer (const DeviceInterface&		vk,
     37 				const VkDevice				device,
     38 				Allocator&					allocator,
     39 				const VkBufferCreateInfo&	bufferCreateInfo,
     40 				const MemoryRequirement		memoryRequirement)
     41 {
     42 	m_buffer = createBuffer(vk, device, &bufferCreateInfo);
     43 	m_allocation = allocator.allocate(getBufferMemoryRequirements(vk, device, *m_buffer), memoryRequirement);
     44 	VK_CHECK(vk.bindBufferMemory(device, *m_buffer, m_allocation->getMemory(), m_allocation->getOffset()));
     45 }
     46 
     47 Image::Image (const DeviceInterface&	vk,
     48 			  const VkDevice			device,
     49 			  Allocator&				allocator,
     50 			  const VkImageCreateInfo&	imageCreateInfo,
     51 			  const MemoryRequirement	memoryRequirement)
     52 {
     53 	m_image = createImage(vk, device, &imageCreateInfo);
     54 	m_allocation = allocator.allocate(getImageMemoryRequirements(vk, device, *m_image), memoryRequirement);
     55 	VK_CHECK(vk.bindImageMemory(device, *m_image, m_allocation->getMemory(), m_allocation->getOffset()));
     56 }
     57 
     58 tcu::UVec3 getShaderGridSize (const ImageType imageType, const tcu::UVec3& imageSize)
     59 {
     60 	switch (imageType)
     61 	{
     62 		case IMAGE_TYPE_1D:
     63 		case IMAGE_TYPE_BUFFER:
     64 			return tcu::UVec3(imageSize.x(), 1u, 1u);
     65 
     66 		case IMAGE_TYPE_1D_ARRAY:
     67 			return tcu::UVec3(imageSize.x(), imageSize.z(), 1u);
     68 
     69 		case IMAGE_TYPE_2D:
     70 			return tcu::UVec3(imageSize.x(), imageSize.y(), 1u);
     71 
     72 		case IMAGE_TYPE_2D_ARRAY:
     73 		case IMAGE_TYPE_3D:
     74 			return tcu::UVec3(imageSize.x(), imageSize.y(), imageSize.z());
     75 
     76 		case IMAGE_TYPE_CUBE:
     77 			return tcu::UVec3(imageSize.x(), imageSize.y(), 6u);
     78 
     79 		case IMAGE_TYPE_CUBE_ARRAY:
     80 			return tcu::UVec3(imageSize.x(), imageSize.y(), 6u * imageSize.z());
     81 
     82 		default:
     83 			DE_FATAL("Unknown image type");
     84 			return tcu::UVec3(1u, 1u, 1u);
     85 	}
     86 }
     87 
     88 tcu::UVec3 getLayerSize (const ImageType imageType, const tcu::UVec3& imageSize)
     89 {
     90 	switch (imageType)
     91 	{
     92 		case IMAGE_TYPE_1D:
     93 		case IMAGE_TYPE_1D_ARRAY:
     94 		case IMAGE_TYPE_BUFFER:
     95 			return tcu::UVec3(imageSize.x(), 1u, 1u);
     96 
     97 		case IMAGE_TYPE_2D:
     98 		case IMAGE_TYPE_2D_ARRAY:
     99 		case IMAGE_TYPE_CUBE:
    100 		case IMAGE_TYPE_CUBE_ARRAY:
    101 			return tcu::UVec3(imageSize.x(), imageSize.y(), 1u);
    102 
    103 		case IMAGE_TYPE_3D:
    104 			return tcu::UVec3(imageSize.x(), imageSize.y(), imageSize.z());
    105 
    106 		default:
    107 			DE_FATAL("Unknown image type");
    108 			return tcu::UVec3(1u, 1u, 1u);
    109 	}
    110 }
    111 
    112 deUint32 getNumLayers (const ImageType imageType, const tcu::UVec3& imageSize)
    113 {
    114 	switch (imageType)
    115 	{
    116 		case IMAGE_TYPE_1D:
    117 		case IMAGE_TYPE_2D:
    118 		case IMAGE_TYPE_3D:
    119 		case IMAGE_TYPE_BUFFER:
    120 			return 1u;
    121 
    122 		case IMAGE_TYPE_1D_ARRAY:
    123 		case IMAGE_TYPE_2D_ARRAY:
    124 			return imageSize.z();
    125 
    126 		case IMAGE_TYPE_CUBE:
    127 			return 6u;
    128 
    129 		case IMAGE_TYPE_CUBE_ARRAY:
    130 			return imageSize.z() * 6u;
    131 
    132 		default:
    133 			DE_FATAL("Unknown image type");
    134 			return 0u;
    135 	}
    136 }
    137 
    138 deUint32 getNumPixels (const ImageType imageType, const tcu::UVec3& imageSize)
    139 {
    140 	const tcu::UVec3 gridSize = getShaderGridSize(imageType, imageSize);
    141 
    142 	return gridSize.x() * gridSize.y() * gridSize.z();
    143 }
    144 
    145 deUint32 getDimensions (const ImageType imageType)
    146 {
    147 	switch (imageType)
    148 	{
    149 		case IMAGE_TYPE_1D:
    150 		case IMAGE_TYPE_BUFFER:
    151 			return 1u;
    152 
    153 		case IMAGE_TYPE_1D_ARRAY:
    154 		case IMAGE_TYPE_2D:
    155 			return 2u;
    156 
    157 		case IMAGE_TYPE_2D_ARRAY:
    158 		case IMAGE_TYPE_CUBE:
    159 		case IMAGE_TYPE_CUBE_ARRAY:
    160 		case IMAGE_TYPE_3D:
    161 			return 3u;
    162 
    163 		default:
    164 			DE_FATAL("Unknown image type");
    165 			return 0u;
    166 	}
    167 }
    168 
    169 deUint32 getLayerDimensions (const ImageType imageType)
    170 {
    171 	switch (imageType)
    172 	{
    173 		case IMAGE_TYPE_1D:
    174 		case IMAGE_TYPE_BUFFER:
    175 		case IMAGE_TYPE_1D_ARRAY:
    176 			return 1u;
    177 
    178 		case IMAGE_TYPE_2D:
    179 		case IMAGE_TYPE_2D_ARRAY:
    180 		case IMAGE_TYPE_CUBE:
    181 		case IMAGE_TYPE_CUBE_ARRAY:
    182 			return 2u;
    183 
    184 		case IMAGE_TYPE_3D:
    185 			return 3u;
    186 
    187 		default:
    188 			DE_FATAL("Unknown image type");
    189 			return 0u;
    190 	}
    191 }
    192 
    193 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize			bufferSize,
    194 										 const VkBufferUsageFlags	usage)
    195 {
    196 	const VkBufferCreateInfo bufferCreateInfo =
    197 	{
    198 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
    199 		DE_NULL,								// const void*			pNext;
    200 		0u,										// VkBufferCreateFlags	flags;
    201 		bufferSize,								// VkDeviceSize			size;
    202 		usage,									// VkBufferUsageFlags	usage;
    203 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
    204 		0u,										// deUint32				queueFamilyIndexCount;
    205 		DE_NULL,								// const deUint32*		pQueueFamilyIndices;
    206 	};
    207 	return bufferCreateInfo;
    208 }
    209 
    210 VkBufferImageCopy makeBufferImageCopy (const VkExtent3D extent,
    211 									   const deUint32	arraySize)
    212 {
    213 	const VkBufferImageCopy copyParams =
    214 	{
    215 		0ull,																		//	VkDeviceSize				bufferOffset;
    216 		0u,																			//	deUint32					bufferRowLength;
    217 		0u,																			//	deUint32					bufferImageHeight;
    218 		makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, arraySize),	//	VkImageSubresourceLayers	imageSubresource;
    219 		makeOffset3D(0, 0, 0),														//	VkOffset3D					imageOffset;
    220 		extent,																		//	VkExtent3D					imageExtent;
    221 	};
    222 	return copyParams;
    223 }
    224 
    225 Move<VkCommandPool> makeCommandPool (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex)
    226 {
    227 	const VkCommandPoolCreateInfo commandPoolParams =
    228 	{
    229 		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// VkStructureType			sType;
    230 		DE_NULL,											// const void*				pNext;
    231 		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// VkCommandPoolCreateFlags	flags;
    232 		queueFamilyIndex,									// deUint32					queueFamilyIndex;
    233 	};
    234 	return createCommandPool(vk, device, &commandPoolParams);
    235 }
    236 
    237 Move<VkCommandBuffer> makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool)
    238 {
    239 	const VkCommandBufferAllocateInfo bufferAllocateParams =
    240 	{
    241 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,		// VkStructureType			sType;
    242 		DE_NULL,											// const void*				pNext;
    243 		commandPool,										// VkCommandPool			commandPool;
    244 		VK_COMMAND_BUFFER_LEVEL_PRIMARY,					// VkCommandBufferLevel		level;
    245 		1u,													// deUint32					bufferCount;
    246 	};
    247 	return allocateCommandBuffer(vk, device, &bufferAllocateParams);
    248 }
    249 
    250 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&		vk,
    251 										   const VkDevice				device,
    252 										   const VkDescriptorSetLayout	descriptorSetLayout)
    253 {
    254 	const VkPipelineLayoutCreateInfo pipelineLayoutParams =
    255 	{
    256 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
    257 		DE_NULL,											// const void*						pNext;
    258 		0u,													// VkPipelineLayoutCreateFlags		flags;
    259 		1u,													// deUint32							setLayoutCount;
    260 		&descriptorSetLayout,								// const VkDescriptorSetLayout*		pSetLayouts;
    261 		0u,													// deUint32							pushConstantRangeCount;
    262 		DE_NULL,											// const VkPushConstantRange*		pPushConstantRanges;
    263 	};
    264 	return createPipelineLayout(vk, device, &pipelineLayoutParams);
    265 }
    266 
    267 Move<VkPipeline> makeComputePipeline (const DeviceInterface&	vk,
    268 									  const VkDevice			device,
    269 									  const VkPipelineLayout	pipelineLayout,
    270 									  const VkShaderModule		shaderModule)
    271 {
    272 	const VkPipelineShaderStageCreateInfo pipelineShaderStageParams =
    273 	{
    274 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
    275 		DE_NULL,												// const void*							pNext;
    276 		0u,														// VkPipelineShaderStageCreateFlags		flags;
    277 		VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits				stage;
    278 		shaderModule,											// VkShaderModule						module;
    279 		"main",													// const char*							pName;
    280 		DE_NULL,												// const VkSpecializationInfo*			pSpecializationInfo;
    281 	};
    282 	const VkComputePipelineCreateInfo pipelineCreateInfo =
    283 	{
    284 		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,		// VkStructureType					sType;
    285 		DE_NULL,											// const void*						pNext;
    286 		0u,													// VkPipelineCreateFlags			flags;
    287 		pipelineShaderStageParams,							// VkPipelineShaderStageCreateInfo	stage;
    288 		pipelineLayout,										// VkPipelineLayout					layout;
    289 		DE_NULL,											// VkPipeline						basePipelineHandle;
    290 		0,													// deInt32							basePipelineIndex;
    291 	};
    292 	return createComputePipeline(vk, device, DE_NULL , &pipelineCreateInfo);
    293 }
    294 
    295 Move<VkBufferView> makeBufferView (const DeviceInterface&	vk,
    296 								   const VkDevice			vkDevice,
    297 								   const VkBuffer			buffer,
    298 								   const VkFormat			format,
    299 								   const VkDeviceSize		offset,
    300 								   const VkDeviceSize		size)
    301 {
    302 	const VkBufferViewCreateInfo bufferViewParams =
    303 	{
    304 		VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,	// VkStructureType			sType;
    305 		DE_NULL,									// const void*				pNext;
    306 		0u,											// VkBufferViewCreateFlags	flags;
    307 		buffer,										// VkBuffer					buffer;
    308 		format,										// VkFormat					format;
    309 		offset,										// VkDeviceSize				offset;
    310 		size,										// VkDeviceSize				range;
    311 	};
    312 	return createBufferView(vk, vkDevice, &bufferViewParams);
    313 }
    314 
    315 Move<VkImageView> makeImageView (const DeviceInterface&			vk,
    316 								 const VkDevice					vkDevice,
    317 								 const VkImage					image,
    318 								 const VkImageViewType			imageViewType,
    319 								 const VkFormat					format,
    320 								 const VkImageSubresourceRange	subresourceRange)
    321 {
    322 	const VkImageViewCreateInfo imageViewParams =
    323 	{
    324 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
    325 		DE_NULL,										// const void*				pNext;
    326 		0u,												// VkImageViewCreateFlags	flags;
    327 		image,											// VkImage					image;
    328 		imageViewType,									// VkImageViewType			viewType;
    329 		format,											// VkFormat					format;
    330 		makeComponentMappingRGBA(),						// VkComponentMapping		components;
    331 		subresourceRange,								// VkImageSubresourceRange	subresourceRange;
    332 	};
    333 	return createImageView(vk, vkDevice, &imageViewParams);
    334 }
    335 
    336 Move<VkDescriptorSet> makeDescriptorSet (const DeviceInterface&			vk,
    337 										 const VkDevice					device,
    338 										 const VkDescriptorPool			descriptorPool,
    339 										 const VkDescriptorSetLayout	setLayout)
    340 {
    341 	const VkDescriptorSetAllocateInfo allocateParams =
    342 	{
    343 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
    344 		DE_NULL,											// const void*					pNext;
    345 		descriptorPool,										// VkDescriptorPool				descriptorPool;
    346 		1u,													// deUint32						setLayoutCount;
    347 		&setLayout,											// const VkDescriptorSetLayout*	pSetLayouts;
    348 	};
    349 	return allocateDescriptorSet(vk, device, &allocateParams);
    350 }
    351 
    352 VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags	srcAccessMask,
    353 											   const VkAccessFlags	dstAccessMask,
    354 											   const VkBuffer		buffer,
    355 											   const VkDeviceSize	offset,
    356 											   const VkDeviceSize	bufferSizeBytes)
    357 {
    358 	const VkBufferMemoryBarrier barrier =
    359 	{
    360 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
    361 		DE_NULL,									// const void*		pNext;
    362 		srcAccessMask,								// VkAccessFlags	srcAccessMask;
    363 		dstAccessMask,								// VkAccessFlags	dstAccessMask;
    364 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
    365 		VK_QUEUE_FAMILY_IGNORED,					// deUint32			destQueueFamilyIndex;
    366 		buffer,										// VkBuffer			buffer;
    367 		offset,										// VkDeviceSize		offset;
    368 		bufferSizeBytes,							// VkDeviceSize		size;
    369 	};
    370 	return barrier;
    371 }
    372 
    373 VkImageMemoryBarrier makeImageMemoryBarrier	(const VkAccessFlags			srcAccessMask,
    374 											 const VkAccessFlags			dstAccessMask,
    375 											 const VkImageLayout			oldLayout,
    376 											 const VkImageLayout			newLayout,
    377 											 const VkImage					image,
    378 											 const VkImageSubresourceRange	subresourceRange)
    379 {
    380 	const VkImageMemoryBarrier barrier =
    381 	{
    382 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
    383 		DE_NULL,										// const void*				pNext;
    384 		srcAccessMask,									// VkAccessFlags			outputMask;
    385 		dstAccessMask,									// VkAccessFlags			inputMask;
    386 		oldLayout,										// VkImageLayout			oldLayout;
    387 		newLayout,										// VkImageLayout			newLayout;
    388 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
    389 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
    390 		image,											// VkImage					image;
    391 		subresourceRange,								// VkImageSubresourceRange	subresourceRange;
    392 	};
    393 	return barrier;
    394 }
    395 
    396 void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
    397 {
    398 	const VkCommandBufferBeginInfo commandBufBeginParams =
    399 	{
    400 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
    401 		DE_NULL,										// const void*						pNext;
    402 		0u,												// VkCommandBufferUsageFlags		flags;
    403 		(const VkCommandBufferInheritanceInfo*)DE_NULL,
    404 	};
    405 	VK_CHECK(vk.beginCommandBuffer(commandBuffer, &commandBufBeginParams));
    406 }
    407 void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
    408 {
    409 	VK_CHECK(vk.endCommandBuffer(commandBuffer));
    410 }
    411 
    412 void submitCommandsAndWait (const DeviceInterface&	vk,
    413 							const VkDevice			device,
    414 							const VkQueue			queue,
    415 							const VkCommandBuffer	commandBuffer)
    416 {
    417 	const VkFenceCreateInfo	fenceParams =
    418 	{
    419 		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
    420 		DE_NULL,								// const void*			pNext;
    421 		0u,										// VkFenceCreateFlags	flags;
    422 	};
    423 	const Unique<VkFence> fence(createFence(vk, device, &fenceParams));
    424 
    425 	const VkSubmitInfo submitInfo =
    426 	{
    427 		VK_STRUCTURE_TYPE_SUBMIT_INFO,		// VkStructureType			sType;
    428 		DE_NULL,							// const void*				pNext;
    429 		0u,									// deUint32					waitSemaphoreCount;
    430 		DE_NULL,							// const VkSemaphore*		pWaitSemaphores;
    431 		(const VkPipelineStageFlags*)DE_NULL,
    432 		1u,									// deUint32					commandBufferCount;
    433 		&commandBuffer,						// const VkCommandBuffer*	pCommandBuffers;
    434 		0u,									// deUint32					signalSemaphoreCount;
    435 		DE_NULL,							// const VkSemaphore*		pSignalSemaphores;
    436 	};
    437 
    438 	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
    439 	VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
    440 }
    441 
    442 VkImageType	mapImageType (const ImageType imageType)
    443 {
    444 	switch (imageType)
    445 	{
    446 		case IMAGE_TYPE_1D:
    447 		case IMAGE_TYPE_1D_ARRAY:
    448 		case IMAGE_TYPE_BUFFER:
    449 			return VK_IMAGE_TYPE_1D;
    450 
    451 		case IMAGE_TYPE_2D:
    452 		case IMAGE_TYPE_2D_ARRAY:
    453 		case IMAGE_TYPE_CUBE:
    454 		case IMAGE_TYPE_CUBE_ARRAY:
    455 			return VK_IMAGE_TYPE_2D;
    456 
    457 		case IMAGE_TYPE_3D:
    458 			return VK_IMAGE_TYPE_3D;
    459 
    460 		default:
    461 			DE_ASSERT(false);
    462 			return VK_IMAGE_TYPE_LAST;
    463 	}
    464 }
    465 
    466 VkImageViewType	mapImageViewType (const ImageType imageType)
    467 {
    468 	switch (imageType)
    469 	{
    470 		case IMAGE_TYPE_1D:			return VK_IMAGE_VIEW_TYPE_1D;
    471 		case IMAGE_TYPE_1D_ARRAY:	return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
    472 		case IMAGE_TYPE_2D:			return VK_IMAGE_VIEW_TYPE_2D;
    473 		case IMAGE_TYPE_2D_ARRAY:	return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
    474 		case IMAGE_TYPE_3D:			return VK_IMAGE_VIEW_TYPE_3D;
    475 		case IMAGE_TYPE_CUBE:		return VK_IMAGE_VIEW_TYPE_CUBE;
    476 		case IMAGE_TYPE_CUBE_ARRAY:	return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
    477 
    478 		default:
    479 			DE_ASSERT(false);
    480 			return VK_IMAGE_VIEW_TYPE_LAST;
    481 	}
    482 }
    483 
    484 std::string getImageTypeName (const ImageType imageType)
    485 {
    486 	switch (imageType)
    487 	{
    488 		case IMAGE_TYPE_1D:			return "1d";
    489 		case IMAGE_TYPE_1D_ARRAY:	return "1d_array";
    490 		case IMAGE_TYPE_2D:			return "2d";
    491 		case IMAGE_TYPE_2D_ARRAY:	return "2d_array";
    492 		case IMAGE_TYPE_3D:			return "3d";
    493 		case IMAGE_TYPE_CUBE:		return "cube";
    494 		case IMAGE_TYPE_CUBE_ARRAY:	return "cube_array";
    495 		case IMAGE_TYPE_BUFFER:		return "buffer";
    496 
    497 		default:
    498 			DE_ASSERT(false);
    499 			return "";
    500 	}
    501 }
    502 
    503 std::string getShaderImageType (const tcu::TextureFormat& format, const ImageType imageType, const bool multisample)
    504 {
    505 	std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
    506 							 tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER   ? "i" : "";
    507 
    508 	std::string imageTypePart;
    509 	if (multisample)
    510 	{
    511 		switch (imageType)
    512 		{
    513 			case IMAGE_TYPE_2D:			imageTypePart = "2DMS";			break;
    514 			case IMAGE_TYPE_2D_ARRAY:	imageTypePart = "2DMSArray";	break;
    515 
    516 			default:
    517 				DE_ASSERT(false);
    518 		}
    519 	}
    520 	else
    521 	{
    522 		switch (imageType)
    523 		{
    524 			case IMAGE_TYPE_1D:			imageTypePart = "1D";			break;
    525 			case IMAGE_TYPE_1D_ARRAY:	imageTypePart = "1DArray";		break;
    526 			case IMAGE_TYPE_2D:			imageTypePart = "2D";			break;
    527 			case IMAGE_TYPE_2D_ARRAY:	imageTypePart = "2DArray";		break;
    528 			case IMAGE_TYPE_3D:			imageTypePart = "3D";			break;
    529 			case IMAGE_TYPE_CUBE:		imageTypePart = "Cube";			break;
    530 			case IMAGE_TYPE_CUBE_ARRAY:	imageTypePart = "CubeArray";	break;
    531 			case IMAGE_TYPE_BUFFER:		imageTypePart = "Buffer";		break;
    532 
    533 			default:
    534 				DE_ASSERT(false);
    535 		}
    536 	}
    537 
    538 	return formatPart + "image" + imageTypePart;
    539 }
    540 
    541 std::string getShaderImageFormatQualifier (const tcu::TextureFormat& format)
    542 {
    543 	const char* orderPart;
    544 	const char* typePart;
    545 
    546 	switch (format.order)
    547 	{
    548 		case tcu::TextureFormat::R:		orderPart = "r";	break;
    549 		case tcu::TextureFormat::RG:	orderPart = "rg";	break;
    550 		case tcu::TextureFormat::RGB:	orderPart = "rgb";	break;
    551 		case tcu::TextureFormat::RGBA:	orderPart = "rgba";	break;
    552 
    553 		default:
    554 			DE_ASSERT(false);
    555 			orderPart = DE_NULL;
    556 	}
    557 
    558 	switch (format.type)
    559 	{
    560 		case tcu::TextureFormat::FLOAT:				typePart = "32f";		break;
    561 		case tcu::TextureFormat::HALF_FLOAT:		typePart = "16f";		break;
    562 
    563 		case tcu::TextureFormat::UNSIGNED_INT32:	typePart = "32ui";		break;
    564 		case tcu::TextureFormat::UNSIGNED_INT16:	typePart = "16ui";		break;
    565 		case tcu::TextureFormat::UNSIGNED_INT8:		typePart = "8ui";		break;
    566 
    567 		case tcu::TextureFormat::SIGNED_INT32:		typePart = "32i";		break;
    568 		case tcu::TextureFormat::SIGNED_INT16:		typePart = "16i";		break;
    569 		case tcu::TextureFormat::SIGNED_INT8:		typePart = "8i";		break;
    570 
    571 		case tcu::TextureFormat::UNORM_INT16:		typePart = "16";		break;
    572 		case tcu::TextureFormat::UNORM_INT8:		typePart = "8";			break;
    573 
    574 		case tcu::TextureFormat::SNORM_INT16:		typePart = "16_snorm";	break;
    575 		case tcu::TextureFormat::SNORM_INT8:		typePart = "8_snorm";	break;
    576 
    577 		default:
    578 			DE_ASSERT(false);
    579 			typePart = DE_NULL;
    580 	}
    581 
    582 	return std::string() + orderPart + typePart;
    583 }
    584 
    585 std::string getFormatShortString (const VkFormat format)
    586 {
    587 	const std::string fullName = getFormatName(format);
    588 
    589 	DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
    590 
    591 	return de::toLower(fullName.substr(10));
    592 }
    593 
    594 } // image
    595 } // vkt
    596