Home | History | Annotate | Download | only in sparse_resources
      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 
     30 #include <deMath.h>
     31 
     32 using namespace vk;
     33 
     34 namespace vkt
     35 {
     36 namespace sparse
     37 {
     38 
     39 tcu::UVec3 getShaderGridSize (const ImageType imageType, const tcu::UVec3& imageSize, const deUint32 mipLevel)
     40 {
     41 	const deUint32 mipLevelX = std::max(imageSize.x() >> mipLevel, 1u);
     42 	const deUint32 mipLevelY = std::max(imageSize.y() >> mipLevel, 1u);
     43 	const deUint32 mipLevelZ = std::max(imageSize.z() >> mipLevel, 1u);
     44 
     45 	switch (imageType)
     46 	{
     47 	case IMAGE_TYPE_1D:
     48 		return tcu::UVec3(mipLevelX, 1u, 1u);
     49 
     50 	case IMAGE_TYPE_BUFFER:
     51 		return tcu::UVec3(imageSize.x(), 1u, 1u);
     52 
     53 	case IMAGE_TYPE_1D_ARRAY:
     54 		return tcu::UVec3(mipLevelX, imageSize.z(), 1u);
     55 
     56 	case IMAGE_TYPE_2D:
     57 		return tcu::UVec3(mipLevelX, mipLevelY, 1u);
     58 
     59 	case IMAGE_TYPE_2D_ARRAY:
     60 		return tcu::UVec3(mipLevelX, mipLevelY, imageSize.z());
     61 
     62 	case IMAGE_TYPE_3D:
     63 		return tcu::UVec3(mipLevelX, mipLevelY, mipLevelZ);
     64 
     65 	case IMAGE_TYPE_CUBE:
     66 		return tcu::UVec3(mipLevelX, mipLevelY, 6u);
     67 
     68 	case IMAGE_TYPE_CUBE_ARRAY:
     69 		return tcu::UVec3(mipLevelX, mipLevelY, 6u * imageSize.z());
     70 
     71 	default:
     72 		DE_FATAL("Unknown image type");
     73 		return tcu::UVec3(1u, 1u, 1u);
     74 	}
     75 }
     76 
     77 tcu::UVec3 getLayerSize (const ImageType imageType, const tcu::UVec3& imageSize)
     78 {
     79 	switch (imageType)
     80 	{
     81 	case IMAGE_TYPE_1D:
     82 	case IMAGE_TYPE_1D_ARRAY:
     83 	case IMAGE_TYPE_BUFFER:
     84 		return tcu::UVec3(imageSize.x(), 1u, 1u);
     85 
     86 	case IMAGE_TYPE_2D:
     87 	case IMAGE_TYPE_2D_ARRAY:
     88 	case IMAGE_TYPE_CUBE:
     89 	case IMAGE_TYPE_CUBE_ARRAY:
     90 		return tcu::UVec3(imageSize.x(), imageSize.y(), 1u);
     91 
     92 	case IMAGE_TYPE_3D:
     93 		return tcu::UVec3(imageSize.x(), imageSize.y(), imageSize.z());
     94 
     95 	default:
     96 		DE_FATAL("Unknown image type");
     97 		return tcu::UVec3(1u, 1u, 1u);
     98 	}
     99 }
    100 
    101 deUint32 getNumLayers (const ImageType imageType, const tcu::UVec3& imageSize)
    102 {
    103 	switch (imageType)
    104 	{
    105 	case IMAGE_TYPE_1D:
    106 	case IMAGE_TYPE_2D:
    107 	case IMAGE_TYPE_3D:
    108 	case IMAGE_TYPE_BUFFER:
    109 		return 1u;
    110 
    111 	case IMAGE_TYPE_1D_ARRAY:
    112 	case IMAGE_TYPE_2D_ARRAY:
    113 		return imageSize.z();
    114 
    115 	case IMAGE_TYPE_CUBE:
    116 		return 6u;
    117 
    118 	case IMAGE_TYPE_CUBE_ARRAY:
    119 		return imageSize.z() * 6u;
    120 
    121 	default:
    122 		DE_FATAL("Unknown image type");
    123 		return 0u;
    124 	}
    125 }
    126 
    127 deUint32 getNumPixels (const ImageType imageType, const tcu::UVec3& imageSize)
    128 {
    129 	const tcu::UVec3 gridSize = getShaderGridSize(imageType, imageSize);
    130 
    131 	return gridSize.x() * gridSize.y() * gridSize.z();
    132 }
    133 
    134 deUint32 getDimensions (const ImageType imageType)
    135 {
    136 	switch (imageType)
    137 	{
    138 	case IMAGE_TYPE_1D:
    139 	case IMAGE_TYPE_BUFFER:
    140 		return 1u;
    141 
    142 	case IMAGE_TYPE_1D_ARRAY:
    143 	case IMAGE_TYPE_2D:
    144 		return 2u;
    145 
    146 	case IMAGE_TYPE_2D_ARRAY:
    147 	case IMAGE_TYPE_CUBE:
    148 	case IMAGE_TYPE_CUBE_ARRAY:
    149 	case IMAGE_TYPE_3D:
    150 		return 3u;
    151 
    152 	default:
    153 		DE_FATAL("Unknown image type");
    154 		return 0u;
    155 	}
    156 }
    157 
    158 deUint32 getLayerDimensions (const ImageType imageType)
    159 {
    160 	switch (imageType)
    161 	{
    162 	case IMAGE_TYPE_1D:
    163 	case IMAGE_TYPE_BUFFER:
    164 	case IMAGE_TYPE_1D_ARRAY:
    165 		return 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 2u;
    172 
    173 	case IMAGE_TYPE_3D:
    174 		return 3u;
    175 
    176 	default:
    177 		DE_FATAL("Unknown image type");
    178 		return 0u;
    179 	}
    180 }
    181 
    182 bool isImageSizeSupported (const InstanceInterface& instance, const VkPhysicalDevice physicalDevice, const ImageType imageType, const tcu::UVec3& imageSize)
    183 {
    184 	const VkPhysicalDeviceProperties deviceProperties = getPhysicalDeviceProperties(instance, physicalDevice);
    185 
    186 	switch (imageType)
    187 	{
    188 		case IMAGE_TYPE_1D:
    189 			return	imageSize.x() <= deviceProperties.limits.maxImageDimension1D;
    190 		case IMAGE_TYPE_1D_ARRAY:
    191 			return	imageSize.x() <= deviceProperties.limits.maxImageDimension1D &&
    192 					imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
    193 		case IMAGE_TYPE_2D:
    194 			return	imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
    195 					imageSize.y() <= deviceProperties.limits.maxImageDimension2D;
    196 		case IMAGE_TYPE_2D_ARRAY:
    197 			return	imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
    198 					imageSize.y() <= deviceProperties.limits.maxImageDimension2D &&
    199 					imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
    200 		case IMAGE_TYPE_CUBE:
    201 			return	imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
    202 					imageSize.y() <= deviceProperties.limits.maxImageDimensionCube;
    203 		case IMAGE_TYPE_CUBE_ARRAY:
    204 			return	imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
    205 					imageSize.y() <= deviceProperties.limits.maxImageDimensionCube &&
    206 					imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
    207 		case IMAGE_TYPE_3D:
    208 			return	imageSize.x() <= deviceProperties.limits.maxImageDimension3D &&
    209 					imageSize.y() <= deviceProperties.limits.maxImageDimension3D &&
    210 					imageSize.z() <= deviceProperties.limits.maxImageDimension3D;
    211 		case IMAGE_TYPE_BUFFER:
    212 			return true;
    213 		default:
    214 			DE_FATAL("Unknown image type");
    215 			return false;
    216 	}
    217 }
    218 
    219 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize			bufferSize,
    220 										 const VkBufferUsageFlags	usage)
    221 {
    222 	const VkBufferCreateInfo bufferCreateInfo =
    223 	{
    224 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
    225 		DE_NULL,								// const void*			pNext;
    226 		0u,										// VkBufferCreateFlags	flags;
    227 		bufferSize,								// VkDeviceSize			size;
    228 		usage,									// VkBufferUsageFlags	usage;
    229 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
    230 		0u,										// deUint32				queueFamilyIndexCount;
    231 		DE_NULL,								// const deUint32*		pQueueFamilyIndices;
    232 	};
    233 	return bufferCreateInfo;
    234 }
    235 
    236 VkBufferImageCopy makeBufferImageCopy (const VkExtent3D		extent,
    237 									   const deUint32		layerCount,
    238 									   const deUint32		mipmapLevel,
    239 									   const VkDeviceSize	bufferOffset)
    240 {
    241 	const VkBufferImageCopy copyParams =
    242 	{
    243 		bufferOffset,																		//	VkDeviceSize				bufferOffset;
    244 		0u,																					//	deUint32					bufferRowLength;
    245 		0u,																					//	deUint32					bufferImageHeight;
    246 		makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, mipmapLevel, 0u, layerCount),	//	VkImageSubresourceLayers	imageSubresource;
    247 		makeOffset3D(0, 0, 0),																//	VkOffset3D					imageOffset;
    248 		extent,																				//	VkExtent3D					imageExtent;
    249 	};
    250 	return copyParams;
    251 }
    252 
    253 Move<VkCommandPool> makeCommandPool (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex)
    254 {
    255 	const VkCommandPoolCreateInfo commandPoolParams =
    256 	{
    257 		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// VkStructureType			sType;
    258 		DE_NULL,											// const void*				pNext;
    259 		VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// VkCommandPoolCreateFlags	flags;
    260 		queueFamilyIndex,									// deUint32					queueFamilyIndex;
    261 	};
    262 	return createCommandPool(vk, device, &commandPoolParams);
    263 }
    264 
    265 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&		vk,
    266 										   const VkDevice				device,
    267 										   const VkDescriptorSetLayout	descriptorSetLayout)
    268 {
    269 	const VkPipelineLayoutCreateInfo pipelineLayoutParams =
    270 	{
    271 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,						// VkStructureType					sType;
    272 		DE_NULL,															// const void*						pNext;
    273 		0u,																	// VkPipelineLayoutCreateFlags		flags;
    274 		(descriptorSetLayout != DE_NULL ? 1u : 0u),							// deUint32							setLayoutCount;
    275 		(descriptorSetLayout != DE_NULL ? &descriptorSetLayout : DE_NULL),	// const VkDescriptorSetLayout*		pSetLayouts;
    276 		0u,																	// deUint32							pushConstantRangeCount;
    277 		DE_NULL,															// const VkPushConstantRange*		pPushConstantRanges;
    278 	};
    279 	return createPipelineLayout(vk, device, &pipelineLayoutParams);
    280 }
    281 
    282 Move<VkPipeline> makeComputePipeline (const DeviceInterface&		vk,
    283 									  const VkDevice				device,
    284 									  const VkPipelineLayout		pipelineLayout,
    285 									  const VkShaderModule			shaderModule,
    286 									  const VkSpecializationInfo*	specializationInfo)
    287 {
    288 	const VkPipelineShaderStageCreateInfo pipelineShaderStageParams =
    289 	{
    290 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
    291 		DE_NULL,												// const void*							pNext;
    292 		0u,														// VkPipelineShaderStageCreateFlags		flags;
    293 		VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits				stage;
    294 		shaderModule,											// VkShaderModule						module;
    295 		"main",													// const char*							pName;
    296 		specializationInfo,										// const VkSpecializationInfo*			pSpecializationInfo;
    297 	};
    298 	const VkComputePipelineCreateInfo pipelineCreateInfo =
    299 	{
    300 		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,		// VkStructureType					sType;
    301 		DE_NULL,											// const void*						pNext;
    302 		0u,													// VkPipelineCreateFlags			flags;
    303 		pipelineShaderStageParams,							// VkPipelineShaderStageCreateInfo	stage;
    304 		pipelineLayout,										// VkPipelineLayout					layout;
    305 		DE_NULL,											// VkPipeline						basePipelineHandle;
    306 		0,													// deInt32							basePipelineIndex;
    307 	};
    308 	return createComputePipeline(vk, device, DE_NULL , &pipelineCreateInfo);
    309 }
    310 
    311 Move<VkBufferView> makeBufferView (const DeviceInterface&	vk,
    312 								   const VkDevice			vkDevice,
    313 								   const VkBuffer			buffer,
    314 								   const VkFormat			format,
    315 								   const VkDeviceSize		offset,
    316 								   const VkDeviceSize		size)
    317 {
    318 	const VkBufferViewCreateInfo bufferViewParams =
    319 	{
    320 		VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,	// VkStructureType			sType;
    321 		DE_NULL,									// const void*				pNext;
    322 		0u,											// VkBufferViewCreateFlags	flags;
    323 		buffer,										// VkBuffer					buffer;
    324 		format,										// VkFormat					format;
    325 		offset,										// VkDeviceSize				offset;
    326 		size,										// VkDeviceSize				range;
    327 	};
    328 	return createBufferView(vk, vkDevice, &bufferViewParams);
    329 }
    330 
    331 Move<VkImageView> makeImageView (const DeviceInterface&			vk,
    332 								 const VkDevice					vkDevice,
    333 								 const VkImage					image,
    334 								 const VkImageViewType			imageViewType,
    335 								 const VkFormat					format,
    336 								 const VkImageSubresourceRange	subresourceRange)
    337 {
    338 	const VkImageViewCreateInfo imageViewParams =
    339 	{
    340 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType			sType;
    341 		DE_NULL,										// const void*				pNext;
    342 		0u,												// VkImageViewCreateFlags	flags;
    343 		image,											// VkImage					image;
    344 		imageViewType,									// VkImageViewType			viewType;
    345 		format,											// VkFormat					format;
    346 		makeComponentMappingRGBA(),						// VkComponentMapping		components;
    347 		subresourceRange,								// VkImageSubresourceRange	subresourceRange;
    348 	};
    349 	return createImageView(vk, vkDevice, &imageViewParams);
    350 }
    351 
    352 Move<VkDescriptorSet> makeDescriptorSet (const DeviceInterface&			vk,
    353 										 const VkDevice					device,
    354 										 const VkDescriptorPool			descriptorPool,
    355 										 const VkDescriptorSetLayout	setLayout)
    356 {
    357 	const VkDescriptorSetAllocateInfo allocateParams =
    358 	{
    359 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType				sType;
    360 		DE_NULL,											// const void*					pNext;
    361 		descriptorPool,										// VkDescriptorPool				descriptorPool;
    362 		1u,													// deUint32						setLayoutCount;
    363 		&setLayout,											// const VkDescriptorSetLayout*	pSetLayouts;
    364 	};
    365 	return allocateDescriptorSet(vk, device, &allocateParams);
    366 }
    367 
    368 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&		vk,
    369 									 const VkDevice				device,
    370 									 const VkRenderPass			renderPass,
    371 									 const deUint32				attachmentCount,
    372 									 const VkImageView*			pAttachments,
    373 									 const deUint32				width,
    374 									 const deUint32				height,
    375 									 const deUint32				layers)
    376 {
    377 	const VkFramebufferCreateInfo framebufferInfo =
    378 	{
    379 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,		// VkStructureType				 sType;
    380 		DE_NULL,										// const void*					 pNext;
    381 		(VkFramebufferCreateFlags)0,					// VkFramebufferCreateFlags		flags;
    382 		renderPass,										// VkRenderPass					renderPass;
    383 		attachmentCount,								// uint32_t						attachmentCount;
    384 		pAttachments,									// const VkImageView*			  pAttachments;
    385 		width,											// uint32_t						width;
    386 		height,											// uint32_t						height;
    387 		layers,											// uint32_t						layers;
    388 	};
    389 
    390 	return createFramebuffer(vk, device, &framebufferInfo);
    391 }
    392 
    393 de::MovePtr<Allocation> bindImage (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImage image, const MemoryRequirement requirement)
    394 {
    395 	de::MovePtr<Allocation> alloc = allocator.allocate(getImageMemoryRequirements(vk, device, image), requirement);
    396 	VK_CHECK(vk.bindImageMemory(device, image, alloc->getMemory(), alloc->getOffset()));
    397 	return alloc;
    398 }
    399 
    400 de::MovePtr<Allocation> bindBuffer (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkBuffer buffer, const MemoryRequirement requirement)
    401 {
    402 	de::MovePtr<Allocation> alloc(allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), requirement));
    403 	VK_CHECK(vk.bindBufferMemory(device, buffer, alloc->getMemory(), alloc->getOffset()));
    404 	return alloc;
    405 }
    406 
    407 void submitCommands (const DeviceInterface&			vk,
    408 					 const VkQueue					queue,
    409 					 const VkCommandBuffer			commandBuffer,
    410 					 const deUint32					waitSemaphoreCount,
    411 					 const VkSemaphore*				pWaitSemaphores,
    412 					 const VkPipelineStageFlags*	pWaitDstStageMask,
    413 					 const deUint32					signalSemaphoreCount,
    414 					 const VkSemaphore*				pSignalSemaphores)
    415 {
    416 	const VkSubmitInfo submitInfo =
    417 	{
    418 		VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType				sType;
    419 		DE_NULL,						// const void*					pNext;
    420 		waitSemaphoreCount,				// deUint32						waitSemaphoreCount;
    421 		pWaitSemaphores,				// const VkSemaphore*			pWaitSemaphores;
    422 		pWaitDstStageMask,				// const VkPipelineStageFlags*	pWaitDstStageMask;
    423 		1u,								// deUint32						commandBufferCount;
    424 		&commandBuffer,					// const VkCommandBuffer*		pCommandBuffers;
    425 		signalSemaphoreCount,			// deUint32						signalSemaphoreCount;
    426 		pSignalSemaphores,				// const VkSemaphore*			pSignalSemaphores;
    427 	};
    428 
    429 	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, DE_NULL));
    430 }
    431 
    432 void submitCommandsAndWait (const DeviceInterface&		vk,
    433 							const VkDevice				device,
    434 							const VkQueue				queue,
    435 							const VkCommandBuffer		commandBuffer,
    436 							const deUint32				waitSemaphoreCount,
    437 							const VkSemaphore*			pWaitSemaphores,
    438 							const VkPipelineStageFlags*	pWaitDstStageMask,
    439 							const deUint32				signalSemaphoreCount,
    440 							const VkSemaphore*			pSignalSemaphores,
    441 							const bool					useDeviceGroups,
    442 							const deUint32				physicalDeviceID)
    443 {
    444 	const VkFenceCreateInfo	fenceParams				=
    445 	{
    446 		VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,				// VkStructureType		sType;
    447 		DE_NULL,											// const void*			pNext;
    448 		0u,													// VkFenceCreateFlags	flags;
    449 	};
    450 	const Unique<VkFence>	fence(createFence		(vk, device, &fenceParams));
    451 
    452 	const deUint32			deviceMask				= 1 << physicalDeviceID;
    453 	std::vector<deUint32>	deviceIndices			(waitSemaphoreCount, physicalDeviceID);
    454 	VkDeviceGroupSubmitInfo deviceGroupSubmitInfo	=
    455 	{
    456 		VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR,		//VkStructureType		sType
    457 		DE_NULL,											// const void*			pNext
    458 		waitSemaphoreCount,									// uint32_t				waitSemaphoreCount
    459 		deviceIndices.size() ? &deviceIndices[0] : DE_NULL,	// const uint32_t*		pWaitSemaphoreDeviceIndices
    460 		1u,													// uint32_t				commandBufferCount
    461 		&deviceMask,										// const uint32_t*		pCommandBufferDeviceMasks
    462 		0u,													// uint32_t				signalSemaphoreCount
    463 		DE_NULL,											// const uint32_t*		pSignalSemaphoreDeviceIndices
    464 	};
    465 	const VkSubmitInfo		submitInfo				=
    466 	{
    467 		VK_STRUCTURE_TYPE_SUBMIT_INFO,						// VkStructureType				sType;
    468 		useDeviceGroups ? &deviceGroupSubmitInfo : DE_NULL,	// const void*					pNext;
    469 		waitSemaphoreCount,									// deUint32						waitSemaphoreCount;
    470 		pWaitSemaphores,									// const VkSemaphore*			pWaitSemaphores;
    471 		pWaitDstStageMask,									// const VkPipelineStageFlags*	pWaitDstStageMask;
    472 		1u,													// deUint32						commandBufferCount;
    473 		&commandBuffer,										// const VkCommandBuffer*		pCommandBuffers;
    474 		signalSemaphoreCount,								// deUint32						signalSemaphoreCount;
    475 		pSignalSemaphores,									// const VkSemaphore*			pSignalSemaphores;
    476 	};
    477 
    478 	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
    479 	VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
    480 }
    481 
    482 VkImageType	mapImageType (const ImageType imageType)
    483 {
    484 	switch (imageType)
    485 	{
    486 		case IMAGE_TYPE_1D:
    487 		case IMAGE_TYPE_1D_ARRAY:
    488 		case IMAGE_TYPE_BUFFER:
    489 			return VK_IMAGE_TYPE_1D;
    490 
    491 		case IMAGE_TYPE_2D:
    492 		case IMAGE_TYPE_2D_ARRAY:
    493 		case IMAGE_TYPE_CUBE:
    494 		case IMAGE_TYPE_CUBE_ARRAY:
    495 			return VK_IMAGE_TYPE_2D;
    496 
    497 		case IMAGE_TYPE_3D:
    498 			return VK_IMAGE_TYPE_3D;
    499 
    500 		default:
    501 			DE_ASSERT(false);
    502 			return VK_IMAGE_TYPE_LAST;
    503 	}
    504 }
    505 
    506 VkImageViewType	mapImageViewType (const ImageType imageType)
    507 {
    508 	switch (imageType)
    509 	{
    510 		case IMAGE_TYPE_1D:			return VK_IMAGE_VIEW_TYPE_1D;
    511 		case IMAGE_TYPE_1D_ARRAY:	return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
    512 		case IMAGE_TYPE_2D:			return VK_IMAGE_VIEW_TYPE_2D;
    513 		case IMAGE_TYPE_2D_ARRAY:	return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
    514 		case IMAGE_TYPE_3D:			return VK_IMAGE_VIEW_TYPE_3D;
    515 		case IMAGE_TYPE_CUBE:		return VK_IMAGE_VIEW_TYPE_CUBE;
    516 		case IMAGE_TYPE_CUBE_ARRAY:	return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
    517 
    518 		default:
    519 			DE_ASSERT(false);
    520 			return VK_IMAGE_VIEW_TYPE_LAST;
    521 	}
    522 }
    523 
    524 std::string getImageTypeName (const ImageType imageType)
    525 {
    526 	switch (imageType)
    527 	{
    528 		case IMAGE_TYPE_1D:			return "1d";
    529 		case IMAGE_TYPE_1D_ARRAY:	return "1d_array";
    530 		case IMAGE_TYPE_2D:			return "2d";
    531 		case IMAGE_TYPE_2D_ARRAY:	return "2d_array";
    532 		case IMAGE_TYPE_3D:			return "3d";
    533 		case IMAGE_TYPE_CUBE:		return "cube";
    534 		case IMAGE_TYPE_CUBE_ARRAY:	return "cube_array";
    535 		case IMAGE_TYPE_BUFFER:		return "buffer";
    536 
    537 		default:
    538 			DE_ASSERT(false);
    539 			return "";
    540 	}
    541 }
    542 
    543 std::string getShaderImageType (const tcu::TextureFormat& format, const ImageType imageType)
    544 {
    545 	std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
    546 							 tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER   ? "i" : "";
    547 
    548 	std::string imageTypePart;
    549 	switch (imageType)
    550 	{
    551 		case IMAGE_TYPE_1D:			imageTypePart = "1D";			break;
    552 		case IMAGE_TYPE_1D_ARRAY:	imageTypePart = "1DArray";		break;
    553 		case IMAGE_TYPE_2D:			imageTypePart = "2D";			break;
    554 		case IMAGE_TYPE_2D_ARRAY:	imageTypePart = "2DArray";		break;
    555 		case IMAGE_TYPE_3D:			imageTypePart = "3D";			break;
    556 		case IMAGE_TYPE_CUBE:		imageTypePart = "Cube";			break;
    557 		case IMAGE_TYPE_CUBE_ARRAY:	imageTypePart = "CubeArray";	break;
    558 		case IMAGE_TYPE_BUFFER:		imageTypePart = "Buffer";		break;
    559 
    560 		default:
    561 			DE_ASSERT(false);
    562 	}
    563 
    564 	return formatPart + "image" + imageTypePart;
    565 }
    566 
    567 
    568 std::string getShaderImageDataType(const tcu::TextureFormat& format)
    569 {
    570 	switch (tcu::getTextureChannelClass(format.type))
    571 	{
    572 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
    573 			return "uvec4";
    574 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
    575 			return "ivec4";
    576 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
    577 			return "vec4";
    578 		default:
    579 			DE_ASSERT(false);
    580 			return "";
    581 	}
    582 }
    583 
    584 
    585 std::string getShaderImageFormatQualifier (const tcu::TextureFormat& format)
    586 {
    587 	const char* orderPart;
    588 	const char* typePart;
    589 
    590 	switch (format.order)
    591 	{
    592 		case tcu::TextureFormat::R:		orderPart = "r";	break;
    593 		case tcu::TextureFormat::RG:	orderPart = "rg";	break;
    594 		case tcu::TextureFormat::RGB:	orderPart = "rgb";	break;
    595 		case tcu::TextureFormat::RGBA:	orderPart = "rgba";	break;
    596 
    597 		default:
    598 			DE_ASSERT(false);
    599 			orderPart = DE_NULL;
    600 	}
    601 
    602 	switch (format.type)
    603 	{
    604 		case tcu::TextureFormat::FLOAT:				typePart = "32f";		break;
    605 		case tcu::TextureFormat::HALF_FLOAT:		typePart = "16f";		break;
    606 
    607 		case tcu::TextureFormat::UNSIGNED_INT32:	typePart = "32ui";		break;
    608 		case tcu::TextureFormat::UNSIGNED_INT16:	typePart = "16ui";		break;
    609 		case tcu::TextureFormat::UNSIGNED_INT8:		typePart = "8ui";		break;
    610 
    611 		case tcu::TextureFormat::SIGNED_INT32:		typePart = "32i";		break;
    612 		case tcu::TextureFormat::SIGNED_INT16:		typePart = "16i";		break;
    613 		case tcu::TextureFormat::SIGNED_INT8:		typePart = "8i";		break;
    614 
    615 		case tcu::TextureFormat::UNORM_INT16:		typePart = "16";		break;
    616 		case tcu::TextureFormat::UNORM_INT8:		typePart = "8";			break;
    617 
    618 		case tcu::TextureFormat::SNORM_INT16:		typePart = "16_snorm";	break;
    619 		case tcu::TextureFormat::SNORM_INT8:		typePart = "8_snorm";	break;
    620 
    621 		default:
    622 			DE_ASSERT(false);
    623 			typePart = DE_NULL;
    624 	}
    625 
    626 	return std::string() + orderPart + typePart;
    627 }
    628 
    629 std::string getShaderImageCoordinates	(const ImageType	imageType,
    630 										 const std::string&	x,
    631 										 const std::string&	xy,
    632 										 const std::string&	xyz)
    633 {
    634 	switch (imageType)
    635 	{
    636 		case IMAGE_TYPE_1D:
    637 		case IMAGE_TYPE_BUFFER:
    638 			return x;
    639 
    640 		case IMAGE_TYPE_1D_ARRAY:
    641 		case IMAGE_TYPE_2D:
    642 			return xy;
    643 
    644 		case IMAGE_TYPE_2D_ARRAY:
    645 		case IMAGE_TYPE_3D:
    646 		case IMAGE_TYPE_CUBE:
    647 		case IMAGE_TYPE_CUBE_ARRAY:
    648 			return xyz;
    649 
    650 		default:
    651 			DE_ASSERT(0);
    652 			return "";
    653 	}
    654 }
    655 
    656 deUint32 getImageMaxMipLevels (const VkImageFormatProperties& imageFormatProperties, const VkExtent3D& extent)
    657 {
    658 	const deUint32 widestEdge = std::max(std::max(extent.width, extent.height), extent.depth);
    659 
    660 	return std::min(static_cast<deUint32>(deFloatLog2(static_cast<float>(widestEdge))) + 1u, imageFormatProperties.maxMipLevels);
    661 }
    662 
    663 deUint32 getImageMipLevelSizeInBytes(const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevel, const deUint32 mipmapMemoryAlignment)
    664 {
    665 	const VkExtent3D extents = mipLevelExtents(baseExtents, mipmapLevel);
    666 
    667 	return deAlign32(extents.width * extents.height * extents.depth * layersCount * tcu::getPixelSize(format), mipmapMemoryAlignment);
    668 }
    669 
    670 deUint32 getImageSizeInBytes(const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevelsCount, const deUint32 mipmapMemoryAlignment)
    671 {
    672 	deUint32 imageSizeInBytes = 0;
    673 	for (deUint32 mipmapLevel = 0; mipmapLevel < mipmapLevelsCount; ++mipmapLevel)
    674 		imageSizeInBytes += getImageMipLevelSizeInBytes(baseExtents, layersCount, format, mipmapLevel, mipmapMemoryAlignment);
    675 
    676 	return imageSizeInBytes;
    677 }
    678 
    679 VkSparseImageMemoryBind	makeSparseImageMemoryBind  (const DeviceInterface&			vk,
    680 													const VkDevice					device,
    681 													const VkDeviceSize				allocationSize,
    682 													const deUint32					memoryType,
    683 													const VkImageSubresource&		subresource,
    684 													const VkOffset3D&				offset,
    685 													const VkExtent3D&				extent)
    686 {
    687 	const VkMemoryAllocateInfo	allocInfo =
    688 	{
    689 		VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,	//	VkStructureType			sType;
    690 		DE_NULL,								//	const void*				pNext;
    691 		allocationSize,							//	VkDeviceSize			allocationSize;
    692 		memoryType,								//	deUint32				memoryTypeIndex;
    693 	};
    694 
    695 	VkDeviceMemory deviceMemory = 0;
    696 	VK_CHECK(vk.allocateMemory(device, &allocInfo, DE_NULL, &deviceMemory));
    697 
    698 	VkSparseImageMemoryBind imageMemoryBind;
    699 
    700 	imageMemoryBind.subresource		= subresource;
    701 	imageMemoryBind.memory			= deviceMemory;
    702 	imageMemoryBind.memoryOffset	= 0u;
    703 	imageMemoryBind.flags			= 0u;
    704 	imageMemoryBind.offset			= offset;
    705 	imageMemoryBind.extent			= extent;
    706 
    707 	return imageMemoryBind;
    708 }
    709 
    710 VkSparseMemoryBind makeSparseMemoryBind	(const DeviceInterface&			vk,
    711 										 const VkDevice					device,
    712 										 const VkDeviceSize				allocationSize,
    713 										 const deUint32					memoryType,
    714 										 const VkDeviceSize				resourceOffset,
    715 										 const VkSparseMemoryBindFlags	flags)
    716 {
    717 	const VkMemoryAllocateInfo allocInfo =
    718 	{
    719 		VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,	//	VkStructureType	sType;
    720 		DE_NULL,								//	const void*		pNext;
    721 		allocationSize,							//	VkDeviceSize	allocationSize;
    722 		memoryType,								//	deUint32		memoryTypeIndex;
    723 	};
    724 
    725 	VkDeviceMemory deviceMemory = 0;
    726 	VK_CHECK(vk.allocateMemory(device, &allocInfo, DE_NULL, &deviceMemory));
    727 
    728 	VkSparseMemoryBind memoryBind;
    729 
    730 	memoryBind.resourceOffset	= resourceOffset;
    731 	memoryBind.size				= allocationSize;
    732 	memoryBind.memory			= deviceMemory;
    733 	memoryBind.memoryOffset		= 0u;
    734 	memoryBind.flags			= flags;
    735 
    736 	return memoryBind;
    737 }
    738 
    739 void requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags)
    740 {
    741 	const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
    742 
    743 	if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader)
    744 		throw tcu::NotSupportedError("Tessellation shader not supported");
    745 
    746 	if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader)
    747 		throw tcu::NotSupportedError("Geometry shader not supported");
    748 
    749 	if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64)
    750 		throw tcu::NotSupportedError("Double-precision floats not supported");
    751 
    752 	if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics)
    753 		throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline");
    754 
    755 	if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics)
    756 		throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader");
    757 
    758 	if (((flags & FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE) != 0) && !features.shaderTessellationAndGeometryPointSize)
    759 		throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in");
    760 }
    761 
    762 deUint32 findMatchingMemoryType (const InstanceInterface&		instance,
    763 								 const VkPhysicalDevice			physicalDevice,
    764 								 const VkMemoryRequirements&	objectMemoryRequirements,
    765 								 const MemoryRequirement&		memoryRequirement)
    766 {
    767 	const VkPhysicalDeviceMemoryProperties deviceMemoryProperties = getPhysicalDeviceMemoryProperties(instance, physicalDevice);
    768 
    769 	for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < deviceMemoryProperties.memoryTypeCount; ++memoryTypeNdx)
    770 	{
    771 		if ((objectMemoryRequirements.memoryTypeBits & (1u << memoryTypeNdx)) != 0 &&
    772 			memoryRequirement.matchesHeap(deviceMemoryProperties.memoryTypes[memoryTypeNdx].propertyFlags))
    773 		{
    774 			return memoryTypeNdx;
    775 		}
    776 	}
    777 
    778 	return NO_MATCH_FOUND;
    779 }
    780 
    781 deUint32 getHeapIndexForMemoryType (const InstanceInterface&	instance,
    782 									const VkPhysicalDevice		physicalDevice,
    783 									const deUint32				memoryType)
    784 {
    785 	const VkPhysicalDeviceMemoryProperties deviceMemoryProperties = getPhysicalDeviceMemoryProperties(instance, physicalDevice);
    786 	DE_ASSERT(memoryType < deviceMemoryProperties.memoryTypeCount);
    787 	return deviceMemoryProperties.memoryTypes[memoryType].heapIndex;
    788 }
    789 
    790 bool checkSparseSupportForImageType (const InstanceInterface&	instance,
    791 									 const VkPhysicalDevice		physicalDevice,
    792 									 const ImageType			imageType)
    793 {
    794 	const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(instance, physicalDevice);
    795 
    796 	if (!deviceFeatures.sparseBinding)
    797 		return false;
    798 
    799 	switch (mapImageType(imageType))
    800 	{
    801 		case VK_IMAGE_TYPE_2D:
    802 			return deviceFeatures.sparseResidencyImage2D == VK_TRUE;
    803 		case VK_IMAGE_TYPE_3D:
    804 			return deviceFeatures.sparseResidencyImage3D == VK_TRUE;
    805 		default:
    806 			DE_ASSERT(0);
    807 			return false;
    808 	};
    809 }
    810 
    811 bool checkSparseSupportForImageFormat (const InstanceInterface&	instance,
    812 									   const VkPhysicalDevice	physicalDevice,
    813 									   const VkImageCreateInfo&	imageInfo)
    814 {
    815 	const std::vector<VkSparseImageFormatProperties> sparseImageFormatPropVec = getPhysicalDeviceSparseImageFormatProperties(
    816 		instance, physicalDevice, imageInfo.format, imageInfo.imageType, imageInfo.samples, imageInfo.usage, imageInfo.tiling);
    817 
    818 	return sparseImageFormatPropVec.size() > 0u;
    819 }
    820 
    821 bool checkImageFormatFeatureSupport (const InstanceInterface&	instance,
    822 									 const VkPhysicalDevice		physicalDevice,
    823 									 const VkFormat				format,
    824 									 const VkFormatFeatureFlags	featureFlags)
    825 {
    826 	const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(instance, physicalDevice, format);
    827 
    828 	return (formatProperties.optimalTilingFeatures & featureFlags) == featureFlags;
    829 }
    830 
    831 deUint32 getSparseAspectRequirementsIndex (const std::vector<VkSparseImageMemoryRequirements>&	requirements,
    832 										   const VkImageAspectFlags								aspectFlags)
    833 {
    834 	for (deUint32 memoryReqNdx = 0; memoryReqNdx < requirements.size(); ++memoryReqNdx)
    835 	{
    836 		if (requirements[memoryReqNdx].formatProperties.aspectMask & aspectFlags)
    837 			return memoryReqNdx;
    838 	}
    839 
    840 	return NO_MATCH_FOUND;
    841 }
    842 
    843 } // sparse
    844 } // vkt
    845