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  vktSparseResourcesImageMemoryAliasing.cpp
     21  * \brief Sparse image memory aliasing tests
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "vktSparseResourcesImageMemoryAliasing.hpp"
     25 #include "vktSparseResourcesTestsUtil.hpp"
     26 #include "vktSparseResourcesBase.hpp"
     27 #include "vktTestCaseUtil.hpp"
     28 
     29 #include "vkDefs.hpp"
     30 #include "vkRef.hpp"
     31 #include "vkRefUtil.hpp"
     32 #include "vkPlatform.hpp"
     33 #include "vkPrograms.hpp"
     34 #include "vkRefUtil.hpp"
     35 #include "vkMemUtil.hpp"
     36 #include "vkBarrierUtil.hpp"
     37 #include "vkQueryUtil.hpp"
     38 #include "vkBuilderUtil.hpp"
     39 #include "vkTypeUtil.hpp"
     40 #include "vkCmdUtil.hpp"
     41 
     42 #include "deStringUtil.hpp"
     43 #include "deUniquePtr.hpp"
     44 #include "deSharedPtr.hpp"
     45 #include "tcuTexture.hpp"
     46 
     47 #include <deMath.h>
     48 #include <string>
     49 #include <vector>
     50 
     51 using namespace vk;
     52 
     53 namespace vkt
     54 {
     55 namespace sparse
     56 {
     57 namespace
     58 {
     59 
     60 enum ShaderParameters
     61 {
     62 	MODULO_DIVISOR = 128
     63 };
     64 
     65 const std::string getCoordStr  (const ImageType		imageType,
     66 								const std::string&	x,
     67 								const std::string&	y,
     68 								const std::string&	z)
     69 {
     70 	switch (imageType)
     71 	{
     72 		case IMAGE_TYPE_1D:
     73 		case IMAGE_TYPE_BUFFER:
     74 			return x;
     75 
     76 		case IMAGE_TYPE_1D_ARRAY:
     77 		case IMAGE_TYPE_2D:
     78 			return "ivec2(" + x + "," + y + ")";
     79 
     80 		case IMAGE_TYPE_2D_ARRAY:
     81 		case IMAGE_TYPE_3D:
     82 		case IMAGE_TYPE_CUBE:
     83 		case IMAGE_TYPE_CUBE_ARRAY:
     84 			return "ivec3(" + x + "," + y + "," + z + ")";
     85 
     86 		default:
     87 			DE_ASSERT(false);
     88 			return "";
     89 	}
     90 }
     91 
     92 class ImageSparseMemoryAliasingCase : public TestCase
     93 {
     94 public:
     95 					ImageSparseMemoryAliasingCase	(tcu::TestContext&			testCtx,
     96 													 const std::string&			name,
     97 													 const std::string&			description,
     98 													 const ImageType			imageType,
     99 													 const tcu::UVec3&			imageSize,
    100 													 const tcu::TextureFormat&	format,
    101 													 const glu::GLSLVersion		glslVersion,
    102 													 const bool					useDeviceGroups);
    103 
    104 	void			initPrograms					(SourceCollections&			sourceCollections) const;
    105 	TestInstance*	createInstance					(Context&					context) const;
    106 
    107 
    108 private:
    109 	const bool					m_useDeviceGroups;
    110 	const ImageType				m_imageType;
    111 	const tcu::UVec3			m_imageSize;
    112 	const tcu::TextureFormat	m_format;
    113 	const glu::GLSLVersion		m_glslVersion;
    114 };
    115 
    116 ImageSparseMemoryAliasingCase::ImageSparseMemoryAliasingCase (tcu::TestContext&			testCtx,
    117 															  const std::string&		name,
    118 															  const std::string&		description,
    119 															  const ImageType			imageType,
    120 															  const tcu::UVec3&			imageSize,
    121 															  const tcu::TextureFormat&	format,
    122 															  const glu::GLSLVersion	glslVersion,
    123 															  const bool				useDeviceGroups)
    124 	: TestCase				(testCtx, name, description)
    125 	, m_useDeviceGroups		(useDeviceGroups)
    126 	, m_imageType			(imageType)
    127 	, m_imageSize			(imageSize)
    128 	, m_format				(format)
    129 	, m_glslVersion			(glslVersion)
    130 {
    131 }
    132 
    133 class ImageSparseMemoryAliasingInstance : public SparseResourcesBaseInstance
    134 {
    135 public:
    136 					ImageSparseMemoryAliasingInstance	(Context&								context,
    137 														 const ImageType						imageType,
    138 														 const tcu::UVec3&						imageSize,
    139 														 const tcu::TextureFormat&				format,
    140 														 const bool								useDeviceGroups);
    141 
    142 	tcu::TestStatus	iterate								(void);
    143 
    144 private:
    145 	const bool					m_useDeviceGroups;
    146 	const ImageType				m_imageType;
    147 	const tcu::UVec3			m_imageSize;
    148 	const tcu::TextureFormat	m_format;
    149 };
    150 
    151 ImageSparseMemoryAliasingInstance::ImageSparseMemoryAliasingInstance (Context&					context,
    152 																	  const ImageType			imageType,
    153 																	  const tcu::UVec3&			imageSize,
    154 																	  const tcu::TextureFormat&	format,
    155 																	  const bool				useDeviceGroups)
    156 	: SparseResourcesBaseInstance	(context, useDeviceGroups)
    157 	, m_useDeviceGroups				(useDeviceGroups)
    158 	, m_imageType					(imageType)
    159 	, m_imageSize					(imageSize)
    160 	, m_format						(format)
    161 {
    162 }
    163 
    164 tcu::TestStatus ImageSparseMemoryAliasingInstance::iterate (void)
    165 {
    166 	const InstanceInterface&			instance				= m_context.getInstanceInterface();
    167 
    168 	{
    169 		// Create logical device supporting both sparse and compute queues
    170 		QueueRequirementsVec queueRequirements;
    171 		queueRequirements.push_back(QueueRequirements(VK_QUEUE_SPARSE_BINDING_BIT, 1u));
    172 		queueRequirements.push_back(QueueRequirements(VK_QUEUE_COMPUTE_BIT, 1u));
    173 
    174 		createDeviceSupportingQueues(queueRequirements);
    175 	}
    176 
    177 	const VkPhysicalDevice				physicalDevice			= getPhysicalDevice();
    178 	const tcu::UVec3					maxWorkGroupSize		= tcu::UVec3(128u, 128u, 64u);
    179 	const tcu::UVec3					maxWorkGroupCount		= tcu::UVec3(65535u, 65535u, 65535u);
    180 	const deUint32						maxWorkGroupInvocations	= 128u;
    181 	VkImageCreateInfo					imageSparseInfo;
    182 	VkSparseImageMemoryRequirements		aspectRequirements;
    183 	std::vector<DeviceMemorySp>			deviceMemUniquePtrVec;
    184 
    185 	//vsk checking these flags should be after creating m_imageType
    186 	//getting queues should be outside the loop
    187 	//see these in all image files
    188 
    189 	// Check if image size does not exceed device limits
    190 	if (!isImageSizeSupported(instance, physicalDevice, m_imageType, m_imageSize))
    191 		TCU_THROW(NotSupportedError, "Image size not supported for device");
    192 
    193 	// Check if sparse memory aliasing is supported
    194 	if (!getPhysicalDeviceFeatures(instance, physicalDevice).sparseResidencyAliased)
    195 		TCU_THROW(NotSupportedError, "Sparse memory aliasing not supported");
    196 
    197 	// Check if device supports sparse operations for image type
    198 	if (!checkSparseSupportForImageType(instance, physicalDevice, m_imageType))
    199 		TCU_THROW(NotSupportedError, "Sparse residency for image type is not supported");
    200 
    201 	const DeviceInterface&	deviceInterface	= getDeviceInterface();
    202 	const Queue&			sparseQueue		= getQueue(VK_QUEUE_SPARSE_BINDING_BIT, 0);
    203 	const Queue&			computeQueue	= getQueue(VK_QUEUE_COMPUTE_BIT, 0);
    204 
    205 	// Go through all physical devices
    206 	for (deUint32 physDevID = 0; physDevID < m_numPhysicalDevices; physDevID++)
    207 	{
    208 		const deUint32	firstDeviceID	= physDevID;
    209 		const deUint32	secondDeviceID	= (firstDeviceID + 1) % m_numPhysicalDevices;
    210 
    211 		imageSparseInfo.sType					= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
    212 		imageSparseInfo.pNext					= DE_NULL;
    213 		imageSparseInfo.flags					= VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT |
    214 												  VK_IMAGE_CREATE_SPARSE_ALIASED_BIT   |
    215 												  VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
    216 		imageSparseInfo.imageType				= mapImageType(m_imageType);
    217 		imageSparseInfo.format					= mapTextureFormat(m_format);
    218 		imageSparseInfo.extent					= makeExtent3D(getLayerSize(m_imageType, m_imageSize));
    219 		imageSparseInfo.arrayLayers				= getNumLayers(m_imageType, m_imageSize);
    220 		imageSparseInfo.samples					= VK_SAMPLE_COUNT_1_BIT;
    221 		imageSparseInfo.tiling					= VK_IMAGE_TILING_OPTIMAL;
    222 		imageSparseInfo.initialLayout			= VK_IMAGE_LAYOUT_UNDEFINED;
    223 		imageSparseInfo.usage					= VK_IMAGE_USAGE_TRANSFER_DST_BIT |
    224 												  VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
    225 												  VK_IMAGE_USAGE_STORAGE_BIT;
    226 		imageSparseInfo.sharingMode				= VK_SHARING_MODE_EXCLUSIVE;
    227 		imageSparseInfo.queueFamilyIndexCount	= 0u;
    228 		imageSparseInfo.pQueueFamilyIndices		= DE_NULL;
    229 
    230 		if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
    231 			imageSparseInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
    232 
    233 		{
    234 			// Assign maximum allowed mipmap levels to image
    235 			VkImageFormatProperties imageFormatProperties;
    236 			instance.getPhysicalDeviceImageFormatProperties(physicalDevice,
    237 				imageSparseInfo.format,
    238 				imageSparseInfo.imageType,
    239 				imageSparseInfo.tiling,
    240 				imageSparseInfo.usage,
    241 				imageSparseInfo.flags,
    242 				&imageFormatProperties);
    243 
    244 			imageSparseInfo.mipLevels = getImageMaxMipLevels(imageFormatProperties, imageSparseInfo.extent);
    245 		}
    246 
    247 		// Check if device supports sparse operations for image format
    248 		if (!checkSparseSupportForImageFormat(instance, physicalDevice, imageSparseInfo))
    249 			TCU_THROW(NotSupportedError, "The image format does not support sparse operations");
    250 
    251 		// Create sparse image
    252 		const Unique<VkImage> imageRead(createImage(deviceInterface, getDevice(), &imageSparseInfo));
    253 		const Unique<VkImage> imageWrite(createImage(deviceInterface, getDevice(), &imageSparseInfo));
    254 
    255 		// Create semaphores to synchronize sparse binding operations with other operations on the sparse images
    256 		const Unique<VkSemaphore> memoryBindSemaphoreTransfer(createSemaphore(deviceInterface, getDevice()));
    257 		const Unique<VkSemaphore> memoryBindSemaphoreCompute(createSemaphore(deviceInterface, getDevice()));
    258 
    259 		const VkSemaphore imageMemoryBindSemaphores[] = { memoryBindSemaphoreTransfer.get(), memoryBindSemaphoreCompute.get() };
    260 
    261 		{
    262 			std::vector<VkSparseImageMemoryBind> imageResidencyMemoryBinds;
    263 			std::vector<VkSparseMemoryBind>		 imageReadMipTailBinds;
    264 			std::vector<VkSparseMemoryBind>		 imageWriteMipTailBinds;
    265 
    266 			// Get sparse image general memory requirements
    267 			const VkMemoryRequirements imageMemoryRequirements = getImageMemoryRequirements(deviceInterface, getDevice(), *imageRead);
    268 
    269 			// Check if required image memory size does not exceed device limits
    270 			if (imageMemoryRequirements.size > getPhysicalDeviceProperties(instance, getPhysicalDevice(secondDeviceID)).limits.sparseAddressSpaceSize)
    271 				TCU_THROW(NotSupportedError, "Required memory size for sparse resource exceeds device limits");
    272 
    273 			DE_ASSERT((imageMemoryRequirements.size % imageMemoryRequirements.alignment) == 0);
    274 
    275 			// Get sparse image sparse memory requirements
    276 			const std::vector<VkSparseImageMemoryRequirements> sparseMemoryRequirements = getImageSparseMemoryRequirements(deviceInterface, getDevice(), *imageRead);
    277 
    278 			DE_ASSERT(sparseMemoryRequirements.size() != 0);
    279 
    280 			const deUint32 colorAspectIndex = getSparseAspectRequirementsIndex(sparseMemoryRequirements, VK_IMAGE_ASPECT_COLOR_BIT);
    281 
    282 			if (colorAspectIndex == NO_MATCH_FOUND)
    283 				TCU_THROW(NotSupportedError, "Not supported image aspect - the test supports currently only VK_IMAGE_ASPECT_COLOR_BIT");
    284 
    285 			aspectRequirements = sparseMemoryRequirements[colorAspectIndex];
    286 
    287 			const VkImageAspectFlags	aspectMask			= aspectRequirements.formatProperties.aspectMask;
    288 			const VkExtent3D			imageGranularity	= aspectRequirements.formatProperties.imageGranularity;
    289 
    290 			DE_ASSERT((aspectRequirements.imageMipTailSize % imageMemoryRequirements.alignment) == 0);
    291 
    292 			const deUint32 memoryType = findMatchingMemoryType(instance, getPhysicalDevice(secondDeviceID), imageMemoryRequirements, MemoryRequirement::Any);
    293 
    294 			if (memoryType == NO_MATCH_FOUND)
    295 				return tcu::TestStatus::fail("No matching memory type found");
    296 
    297 			if (firstDeviceID != secondDeviceID)
    298 			{
    299 				VkPeerMemoryFeatureFlags	peerMemoryFeatureFlags = (VkPeerMemoryFeatureFlags)0;
    300 				const deUint32				heapIndex = getHeapIndexForMemoryType(instance, getPhysicalDevice(secondDeviceID), memoryType);
    301 				deviceInterface.getDeviceGroupPeerMemoryFeatures(getDevice(), heapIndex, firstDeviceID, secondDeviceID, &peerMemoryFeatureFlags);
    302 
    303 				if (((peerMemoryFeatureFlags & VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT)    == 0) ||
    304 					((peerMemoryFeatureFlags & VK_PEER_MEMORY_FEATURE_COPY_DST_BIT)    == 0) ||
    305 					((peerMemoryFeatureFlags & VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT) == 0))
    306 				{
    307 					TCU_THROW(NotSupportedError, "Peer memory does not support COPY_SRC, COPY_DST, and GENERIC_DST");
    308 				}
    309 			}
    310 
    311 			// Bind memory for each layer
    312 			for (deUint32 layerNdx = 0; layerNdx < imageSparseInfo.arrayLayers; ++layerNdx)
    313 			{
    314 				for (deUint32 mipLevelNdx = 0; mipLevelNdx < aspectRequirements.imageMipTailFirstLod; ++mipLevelNdx)
    315 				{
    316 					const VkExtent3D			mipExtent		= mipLevelExtents(imageSparseInfo.extent, mipLevelNdx);
    317 					const tcu::UVec3			sparseBlocks	= alignedDivide(mipExtent, imageGranularity);
    318 					const deUint32				numSparseBlocks = sparseBlocks.x() * sparseBlocks.y() * sparseBlocks.z();
    319 					const VkImageSubresource	subresource		= { aspectMask, mipLevelNdx, layerNdx };
    320 
    321 					const VkSparseImageMemoryBind imageMemoryBind = makeSparseImageMemoryBind(deviceInterface, getDevice(),
    322 						imageMemoryRequirements.alignment * numSparseBlocks, memoryType, subresource, makeOffset3D(0u, 0u, 0u), mipExtent);
    323 
    324 					deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
    325 
    326 					imageResidencyMemoryBinds.push_back(imageMemoryBind);
    327 				}
    328 
    329 				if (!(aspectRequirements.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT) && aspectRequirements.imageMipTailFirstLod < imageSparseInfo.mipLevels)
    330 				{
    331 					const VkSparseMemoryBind imageReadMipTailMemoryBind = makeSparseMemoryBind(deviceInterface, getDevice(),
    332 						aspectRequirements.imageMipTailSize, memoryType, aspectRequirements.imageMipTailOffset + layerNdx * aspectRequirements.imageMipTailStride);
    333 
    334 					deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageReadMipTailMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
    335 
    336 					imageReadMipTailBinds.push_back(imageReadMipTailMemoryBind);
    337 
    338 					const VkSparseMemoryBind imageWriteMipTailMemoryBind = makeSparseMemoryBind(deviceInterface, getDevice(),
    339 						aspectRequirements.imageMipTailSize, memoryType, aspectRequirements.imageMipTailOffset + layerNdx * aspectRequirements.imageMipTailStride);
    340 
    341 					deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageWriteMipTailMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
    342 
    343 					imageWriteMipTailBinds.push_back(imageWriteMipTailMemoryBind);
    344 				}
    345 			}
    346 
    347 			if ((aspectRequirements.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT) && aspectRequirements.imageMipTailFirstLod < imageSparseInfo.mipLevels)
    348 			{
    349 				const VkSparseMemoryBind imageReadMipTailMemoryBind = makeSparseMemoryBind(deviceInterface, getDevice(),
    350 					aspectRequirements.imageMipTailSize, memoryType, aspectRequirements.imageMipTailOffset);
    351 
    352 				deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageReadMipTailMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
    353 
    354 				imageReadMipTailBinds.push_back(imageReadMipTailMemoryBind);
    355 
    356 				const VkSparseMemoryBind imageWriteMipTailMemoryBind = makeSparseMemoryBind(deviceInterface, getDevice(),
    357 					aspectRequirements.imageMipTailSize, memoryType, aspectRequirements.imageMipTailOffset);
    358 
    359 				deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageWriteMipTailMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
    360 
    361 				imageWriteMipTailBinds.push_back(imageWriteMipTailMemoryBind);
    362 			}
    363 
    364 			const VkDeviceGroupBindSparseInfo devGroupBindSparseInfo =
    365 			{
    366 				VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHR,	//VkStructureType							sType;
    367 				DE_NULL,												//const void*								pNext;
    368 				firstDeviceID,											//deUint32									resourceDeviceIndex;
    369 				secondDeviceID,											//deUint32									memoryDeviceIndex;
    370 			};
    371 
    372 			VkBindSparseInfo bindSparseInfo =
    373 			{
    374 				VK_STRUCTURE_TYPE_BIND_SPARSE_INFO,						//VkStructureType							sType;
    375 				m_useDeviceGroups ? &devGroupBindSparseInfo : DE_NULL,	//const void*								pNext;
    376 				0u,														//deUint32									waitSemaphoreCount;
    377 				DE_NULL,												//const VkSemaphore*						pWaitSemaphores;
    378 				0u,														//deUint32									bufferBindCount;
    379 				DE_NULL,												//const VkSparseBufferMemoryBindInfo*		pBufferBinds;
    380 				0u,														//deUint32									imageOpaqueBindCount;
    381 				DE_NULL,												//const VkSparseImageOpaqueMemoryBindInfo*	pImageOpaqueBinds;
    382 				0u,														//deUint32									imageBindCount;
    383 				DE_NULL,												//const VkSparseImageMemoryBindInfo*		pImageBinds;
    384 				2u,														//deUint32									signalSemaphoreCount;
    385 				imageMemoryBindSemaphores								//const VkSemaphore*						pSignalSemaphores;
    386 			};
    387 
    388 			VkSparseImageMemoryBindInfo		  imageResidencyBindInfo[2];
    389 			VkSparseImageOpaqueMemoryBindInfo imageMipTailBindInfo[2];
    390 
    391 			if (imageResidencyMemoryBinds.size() > 0)
    392 			{
    393 				imageResidencyBindInfo[0].image		= *imageRead;
    394 				imageResidencyBindInfo[0].bindCount = static_cast<deUint32>(imageResidencyMemoryBinds.size());
    395 				imageResidencyBindInfo[0].pBinds	= &imageResidencyMemoryBinds[0];
    396 
    397 				imageResidencyBindInfo[1].image		= *imageWrite;
    398 				imageResidencyBindInfo[1].bindCount = static_cast<deUint32>(imageResidencyMemoryBinds.size());
    399 				imageResidencyBindInfo[1].pBinds	= &imageResidencyMemoryBinds[0];
    400 
    401 				bindSparseInfo.imageBindCount		= 2u;
    402 				bindSparseInfo.pImageBinds			= imageResidencyBindInfo;
    403 			}
    404 
    405 			if (imageReadMipTailBinds.size() > 0)
    406 			{
    407 				imageMipTailBindInfo[0].image		= *imageRead;
    408 				imageMipTailBindInfo[0].bindCount	= static_cast<deUint32>(imageReadMipTailBinds.size());
    409 				imageMipTailBindInfo[0].pBinds		= &imageReadMipTailBinds[0];
    410 
    411 				imageMipTailBindInfo[1].image		= *imageWrite;
    412 				imageMipTailBindInfo[1].bindCount	= static_cast<deUint32>(imageWriteMipTailBinds.size());
    413 				imageMipTailBindInfo[1].pBinds		= &imageWriteMipTailBinds[0];
    414 
    415 				bindSparseInfo.imageOpaqueBindCount = 2u;
    416 				bindSparseInfo.pImageOpaqueBinds	= imageMipTailBindInfo;
    417 			}
    418 
    419 			// Submit sparse bind commands for execution
    420 			VK_CHECK(deviceInterface.queueBindSparse(sparseQueue.queueHandle, 1u, &bindSparseInfo, DE_NULL));
    421 		}
    422 
    423 		// Create command buffer for compute and transfer oparations
    424 		const Unique<VkCommandPool>	  commandPool  (makeCommandPool(deviceInterface, getDevice(), computeQueue.queueFamilyIndex));
    425 		const Unique<VkCommandBuffer> commandBuffer(allocateCommandBuffer(deviceInterface, getDevice(), *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
    426 
    427 		std::vector<VkBufferImageCopy> bufferImageCopy(imageSparseInfo.mipLevels);
    428 
    429 		{
    430 			deUint32 bufferOffset = 0u;
    431 			for (deUint32 mipLevelNdx = 0u; mipLevelNdx < imageSparseInfo.mipLevels; ++mipLevelNdx)
    432 			{
    433 				bufferImageCopy[mipLevelNdx] = makeBufferImageCopy(mipLevelExtents(imageSparseInfo.extent, mipLevelNdx), imageSparseInfo.arrayLayers, mipLevelNdx, bufferOffset);
    434 				bufferOffset += getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_format, mipLevelNdx, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY);
    435 			}
    436 		}
    437 
    438 		// Start recording commands
    439 		beginCommandBuffer(deviceInterface, *commandBuffer);
    440 
    441 		const deUint32					imageSizeInBytes		= getImageSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_format, imageSparseInfo.mipLevels, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY);
    442 		const VkBufferCreateInfo		inputBufferCreateInfo	= makeBufferCreateInfo(imageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
    443 		const Unique<VkBuffer>			inputBuffer				(createBuffer(deviceInterface, getDevice(), &inputBufferCreateInfo));
    444 		const de::UniquePtr<Allocation>	inputBufferAlloc		(bindBuffer(deviceInterface, getDevice(), getAllocator(), *inputBuffer, MemoryRequirement::HostVisible));
    445 
    446 		std::vector<deUint8> referenceData(imageSizeInBytes);
    447 
    448 		for (deUint32 mipLevelNdx = 0u; mipLevelNdx < imageSparseInfo.mipLevels; ++mipLevelNdx)
    449 		{
    450 			const deUint32 mipLevelSizeInBytes	= getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_format, mipLevelNdx);
    451 			const deUint32 bufferOffset			= static_cast<deUint32>(bufferImageCopy[mipLevelNdx].bufferOffset);
    452 
    453 			deMemset(&referenceData[bufferOffset], mipLevelNdx + 1u, mipLevelSizeInBytes);
    454 		}
    455 
    456 		deMemcpy(inputBufferAlloc->getHostPtr(), &referenceData[0], imageSizeInBytes);
    457 
    458 		flushAlloc(deviceInterface, getDevice(), *inputBufferAlloc);
    459 
    460 		{
    461 			const VkBufferMemoryBarrier inputBufferBarrier = makeBufferMemoryBarrier
    462 			(
    463 				VK_ACCESS_HOST_WRITE_BIT,
    464 				VK_ACCESS_TRANSFER_READ_BIT,
    465 				*inputBuffer,
    466 				0u,
    467 				imageSizeInBytes
    468 			);
    469 
    470 			deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 1u, &inputBufferBarrier, 0u, DE_NULL);
    471 		}
    472 
    473 		{
    474 			const VkImageMemoryBarrier imageSparseTransferDstBarrier = makeImageMemoryBarrier
    475 			(
    476 				0u,
    477 				VK_ACCESS_TRANSFER_WRITE_BIT,
    478 				VK_IMAGE_LAYOUT_UNDEFINED,
    479 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
    480 				*imageRead,
    481 				makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers),
    482 				sparseQueue.queueFamilyIndex != computeQueue.queueFamilyIndex ? sparseQueue.queueFamilyIndex : VK_QUEUE_FAMILY_IGNORED,
    483 				sparseQueue.queueFamilyIndex != computeQueue.queueFamilyIndex ? computeQueue.queueFamilyIndex : VK_QUEUE_FAMILY_IGNORED
    484 				);
    485 
    486 			deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageSparseTransferDstBarrier);
    487 		}
    488 
    489 		deviceInterface.cmdCopyBufferToImage(*commandBuffer, *inputBuffer, *imageRead, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, static_cast<deUint32>(bufferImageCopy.size()), &bufferImageCopy[0]);
    490 
    491 		{
    492 			const VkImageMemoryBarrier imageSparseTransferSrcBarrier = makeImageMemoryBarrier
    493 			(
    494 				VK_ACCESS_TRANSFER_WRITE_BIT,
    495 				VK_ACCESS_TRANSFER_READ_BIT,
    496 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
    497 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
    498 				*imageRead,
    499 				makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers)
    500 			);
    501 
    502 			deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageSparseTransferSrcBarrier);
    503 		}
    504 
    505 		{
    506 			const VkImageMemoryBarrier imageSparseShaderStorageBarrier = makeImageMemoryBarrier
    507 			(
    508 				0u,
    509 				VK_ACCESS_SHADER_WRITE_BIT,
    510 				VK_IMAGE_LAYOUT_UNDEFINED,
    511 				VK_IMAGE_LAYOUT_GENERAL,
    512 				*imageWrite,
    513 				makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers)
    514 			);
    515 
    516 			deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageSparseShaderStorageBarrier);
    517 		}
    518 
    519 		// Create descriptor set layout
    520 		const Unique<VkDescriptorSetLayout> descriptorSetLayout(
    521 			DescriptorSetLayoutBuilder()
    522 			.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
    523 			.build(deviceInterface, getDevice()));
    524 
    525 		Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(deviceInterface, getDevice(), *descriptorSetLayout));
    526 
    527 		Unique<VkDescriptorPool> descriptorPool(
    528 			DescriptorPoolBuilder()
    529 			.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, imageSparseInfo.mipLevels)
    530 			.build(deviceInterface, getDevice(), VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, imageSparseInfo.mipLevels));
    531 
    532 		typedef de::SharedPtr< Unique<VkImageView> >		SharedVkImageView;
    533 		std::vector<SharedVkImageView>						imageViews;
    534 		imageViews.resize(imageSparseInfo.mipLevels);
    535 
    536 		typedef de::SharedPtr< Unique<VkDescriptorSet> >	SharedVkDescriptorSet;
    537 		std::vector<SharedVkDescriptorSet>					descriptorSets;
    538 		descriptorSets.resize(imageSparseInfo.mipLevels);
    539 
    540 		typedef de::SharedPtr< Unique<VkPipeline> >			SharedVkPipeline;
    541 		std::vector<SharedVkPipeline>						computePipelines;
    542 		computePipelines.resize(imageSparseInfo.mipLevels);
    543 
    544 		for (deUint32 mipLevelNdx = 0u; mipLevelNdx < imageSparseInfo.mipLevels; ++mipLevelNdx)
    545 		{
    546 			std::ostringstream name;
    547 			name << "comp" << mipLevelNdx;
    548 
    549 			// Create and bind compute pipeline
    550 			Unique<VkShaderModule> shaderModule(createShaderModule(deviceInterface, getDevice(), m_context.getBinaryCollection().get(name.str()), DE_NULL));
    551 
    552 			computePipelines[mipLevelNdx]	= makeVkSharedPtr(makeComputePipeline(deviceInterface, getDevice(), *pipelineLayout, *shaderModule));
    553 			VkPipeline computePipeline		= **computePipelines[mipLevelNdx];
    554 
    555 			deviceInterface.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline);
    556 
    557 			// Create and bind descriptor set
    558 			descriptorSets[mipLevelNdx]		= makeVkSharedPtr(makeDescriptorSet(deviceInterface, getDevice(), *descriptorPool, *descriptorSetLayout));
    559 			VkDescriptorSet descriptorSet	= **descriptorSets[mipLevelNdx];
    560 
    561 			// Select which mipmap level to bind
    562 			const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevelNdx, 1u, 0u, imageSparseInfo.arrayLayers);
    563 
    564 			imageViews[mipLevelNdx] = makeVkSharedPtr(makeImageView(deviceInterface, getDevice(), *imageWrite, mapImageViewType(m_imageType), imageSparseInfo.format, subresourceRange));
    565 			VkImageView imageView	= **imageViews[mipLevelNdx];
    566 
    567 			const VkDescriptorImageInfo sparseImageInfo = makeDescriptorImageInfo(DE_NULL, imageView, VK_IMAGE_LAYOUT_GENERAL);
    568 
    569 			DescriptorSetUpdateBuilder()
    570 				.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &sparseImageInfo)
    571 				.update(deviceInterface, getDevice());
    572 
    573 			deviceInterface.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
    574 
    575 			const tcu::UVec3	gridSize			= getShaderGridSize(m_imageType, m_imageSize, mipLevelNdx);
    576 			const deUint32		xWorkGroupSize		= std::min(std::min(gridSize.x(), maxWorkGroupSize.x()), maxWorkGroupInvocations);
    577 			const deUint32		yWorkGroupSize		= std::min(std::min(gridSize.y(), maxWorkGroupSize.y()), maxWorkGroupInvocations / xWorkGroupSize);
    578 			const deUint32		zWorkGroupSize		= std::min(std::min(gridSize.z(), maxWorkGroupSize.z()), maxWorkGroupInvocations / (xWorkGroupSize * yWorkGroupSize));
    579 
    580 			const deUint32		xWorkGroupCount		= gridSize.x() / xWorkGroupSize + (gridSize.x() % xWorkGroupSize ? 1u : 0u);
    581 			const deUint32		yWorkGroupCount		= gridSize.y() / yWorkGroupSize + (gridSize.y() % yWorkGroupSize ? 1u : 0u);
    582 			const deUint32		zWorkGroupCount		= gridSize.z() / zWorkGroupSize + (gridSize.z() % zWorkGroupSize ? 1u : 0u);
    583 
    584 			if (maxWorkGroupCount.x() < xWorkGroupCount ||
    585 				maxWorkGroupCount.y() < yWorkGroupCount ||
    586 				maxWorkGroupCount.z() < zWorkGroupCount)
    587 				TCU_THROW(NotSupportedError, "Image size is not supported");
    588 
    589 			deviceInterface.cmdDispatch(*commandBuffer, xWorkGroupCount, yWorkGroupCount, zWorkGroupCount);
    590 		}
    591 
    592 		{
    593 			const VkMemoryBarrier memoryBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
    594 
    595 			deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1u, &memoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
    596 		}
    597 
    598 		const VkBufferCreateInfo		outputBufferCreateInfo	= makeBufferCreateInfo(imageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
    599 		const Unique<VkBuffer>			outputBuffer			(createBuffer(deviceInterface, getDevice(), &outputBufferCreateInfo));
    600 		const de::UniquePtr<Allocation>	outputBufferAlloc		(bindBuffer(deviceInterface, getDevice(), getAllocator(), *outputBuffer, MemoryRequirement::HostVisible));
    601 
    602 		deviceInterface.cmdCopyImageToBuffer(*commandBuffer, *imageRead, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *outputBuffer, static_cast<deUint32>(bufferImageCopy.size()), &bufferImageCopy[0]);
    603 
    604 		{
    605 			const VkBufferMemoryBarrier outputBufferBarrier = makeBufferMemoryBarrier
    606 			(
    607 				VK_ACCESS_TRANSFER_WRITE_BIT,
    608 				VK_ACCESS_HOST_READ_BIT,
    609 				*outputBuffer,
    610 				0u,
    611 				imageSizeInBytes
    612 			);
    613 
    614 			deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &outputBufferBarrier, 0u, DE_NULL);
    615 		}
    616 
    617 		// End recording commands
    618 		endCommandBuffer(deviceInterface, *commandBuffer);
    619 
    620 		const VkPipelineStageFlags stageBits[] = { VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT };
    621 
    622 		// Submit commands for execution and wait for completion
    623 		submitCommandsAndWait(deviceInterface, getDevice(), computeQueue.queueHandle, *commandBuffer, 2u, imageMemoryBindSemaphores, stageBits,
    624 								0, DE_NULL, m_useDeviceGroups, firstDeviceID);
    625 
    626 		// Retrieve data from buffer to host memory
    627 		invalidateAlloc(deviceInterface, getDevice(), *outputBufferAlloc);
    628 
    629 		const deUint8* outputData = static_cast<const deUint8*>(outputBufferAlloc->getHostPtr());
    630 
    631 		// Wait for sparse queue to become idle
    632 		deviceInterface.queueWaitIdle(sparseQueue.queueHandle);
    633 
    634 		for (deUint32 mipLevelNdx = 0; mipLevelNdx < aspectRequirements.imageMipTailFirstLod; ++mipLevelNdx)
    635 		{
    636 			const tcu::UVec3				  gridSize		= getShaderGridSize(m_imageType, m_imageSize, mipLevelNdx);
    637 			const deUint32					  bufferOffset	= static_cast<deUint32>(bufferImageCopy[mipLevelNdx].bufferOffset);
    638 			const tcu::ConstPixelBufferAccess pixelBuffer	= tcu::ConstPixelBufferAccess(m_format, gridSize.x(), gridSize.y(), gridSize.z(), outputData + bufferOffset);
    639 
    640 			for (deUint32 offsetZ = 0u; offsetZ < gridSize.z(); ++offsetZ)
    641 			for (deUint32 offsetY = 0u; offsetY < gridSize.y(); ++offsetY)
    642 			for (deUint32 offsetX = 0u; offsetX < gridSize.x(); ++offsetX)
    643 			{
    644 				const deUint32 index			= offsetX + (offsetY + offsetZ * gridSize.y()) * gridSize.x();
    645 				const tcu::UVec4 referenceValue = tcu::UVec4(index % MODULO_DIVISOR, index % MODULO_DIVISOR, index % MODULO_DIVISOR, 1u);
    646 				const tcu::UVec4 outputValue	= pixelBuffer.getPixelUint(offsetX, offsetY, offsetZ);
    647 
    648 				if (deMemCmp(&outputValue, &referenceValue, sizeof(deUint32) * getNumUsedChannels(m_format.order)) != 0)
    649 					return tcu::TestStatus::fail("Failed");
    650 			}
    651 		}
    652 
    653 		for (deUint32 mipLevelNdx = aspectRequirements.imageMipTailFirstLod; mipLevelNdx < imageSparseInfo.mipLevels; ++mipLevelNdx)
    654 		{
    655 			const deUint32 mipLevelSizeInBytes	= getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_format, mipLevelNdx);
    656 			const deUint32 bufferOffset			= static_cast<deUint32>(bufferImageCopy[mipLevelNdx].bufferOffset);
    657 
    658 			if (deMemCmp(outputData + bufferOffset, &referenceData[bufferOffset], mipLevelSizeInBytes) != 0)
    659 				return tcu::TestStatus::fail("Failed");
    660 		}
    661 	}
    662 
    663 	return tcu::TestStatus::pass("Passed");
    664 }
    665 
    666 void ImageSparseMemoryAliasingCase::initPrograms(SourceCollections&	sourceCollections) const
    667 {
    668 	const char* const	versionDecl				= glu::getGLSLVersionDeclaration(m_glslVersion);
    669 	const std::string	imageTypeStr			= getShaderImageType(m_format, m_imageType);
    670 	const std::string	formatQualifierStr		= getShaderImageFormatQualifier(m_format);
    671 	const std::string	formatDataStr			= getShaderImageDataType(m_format);
    672 	const deUint32		maxWorkGroupInvocations = 128u;
    673 	const tcu::UVec3	maxWorkGroupSize		= tcu::UVec3(128u, 128u, 64u);
    674 
    675 	const tcu::UVec3	layerSize				= getLayerSize(m_imageType, m_imageSize);
    676 	const deUint32		widestEdge				= std::max(std::max(layerSize.x(), layerSize.y()), layerSize.z());
    677 	const deUint32		mipLevels				= static_cast<deUint32>(deFloatLog2(static_cast<float>(widestEdge))) + 1u;
    678 
    679 	for (deUint32 mipLevelNdx = 0; mipLevelNdx < mipLevels; ++mipLevelNdx)
    680 	{
    681 		// Create compute program
    682 		const tcu::UVec3	gridSize		= getShaderGridSize(m_imageType, m_imageSize, mipLevelNdx);
    683 		const deUint32		xWorkGroupSize  = std::min(std::min(gridSize.x(), maxWorkGroupSize.x()), maxWorkGroupInvocations);
    684 		const deUint32		yWorkGroupSize  = std::min(std::min(gridSize.y(), maxWorkGroupSize.y()), maxWorkGroupInvocations / xWorkGroupSize);
    685 		const deUint32		zWorkGroupSize  = std::min(std::min(gridSize.z(), maxWorkGroupSize.z()), maxWorkGroupInvocations / (xWorkGroupSize * yWorkGroupSize));
    686 
    687 		std::ostringstream src;
    688 
    689 		src << versionDecl << "\n"
    690 			<< "layout (local_size_x = " << xWorkGroupSize << ", local_size_y = " << yWorkGroupSize << ", local_size_z = " << zWorkGroupSize << ") in; \n"
    691 			<< "layout (binding = 0, " << formatQualifierStr << ") writeonly uniform highp " << imageTypeStr << " u_image;\n"
    692 			<< "void main (void)\n"
    693 			<< "{\n"
    694 			<< "	if( gl_GlobalInvocationID.x < " << gridSize.x() << " ) \n"
    695 			<< "	if( gl_GlobalInvocationID.y < " << gridSize.y() << " ) \n"
    696 			<< "	if( gl_GlobalInvocationID.z < " << gridSize.z() << " ) \n"
    697 			<< "	{\n"
    698 			<< "		int index = int(gl_GlobalInvocationID.x + (gl_GlobalInvocationID.y + gl_GlobalInvocationID.z*" << gridSize.y() << ")*" << gridSize.x() << ");\n"
    699 			<< "		imageStore(u_image, " << getCoordStr(m_imageType, "gl_GlobalInvocationID.x", "gl_GlobalInvocationID.y", "gl_GlobalInvocationID.z") << ","
    700 			<< formatDataStr << "( index % " << MODULO_DIVISOR << ", index % " << MODULO_DIVISOR << ", index % " << MODULO_DIVISOR << ", 1 )); \n"
    701 			<< "	}\n"
    702 			<< "}\n";
    703 
    704 		std::ostringstream name;
    705 		name << "comp" << mipLevelNdx;
    706 		sourceCollections.glslSources.add(name.str()) << glu::ComputeSource(src.str());
    707 	}
    708 }
    709 
    710 TestInstance* ImageSparseMemoryAliasingCase::createInstance (Context& context) const
    711 {
    712 	return new ImageSparseMemoryAliasingInstance(context, m_imageType, m_imageSize, m_format, m_useDeviceGroups);
    713 }
    714 
    715 } // anonymous ns
    716 
    717 tcu::TestCaseGroup* createImageSparseMemoryAliasingTestsCommon(tcu::TestContext& testCtx, de::MovePtr<tcu::TestCaseGroup> testGroup, const bool useDeviceGroup = false)
    718 {
    719 	static const deUint32 sizeCountPerImageType = 4u;
    720 
    721 	struct ImageParameters
    722 	{
    723 		ImageType	imageType;
    724 		tcu::UVec3	imageSizes[sizeCountPerImageType];
    725 	};
    726 
    727 	static const ImageParameters imageParametersArray[] =
    728 	{
    729 		{ IMAGE_TYPE_2D,		{ tcu::UVec3(512u, 256u, 1u),	tcu::UVec3(128u, 128u, 1u),	tcu::UVec3(503u, 137u, 1u),	tcu::UVec3(11u, 37u, 1u) } },
    730 		{ IMAGE_TYPE_2D_ARRAY,	{ tcu::UVec3(512u, 256u, 6u),	tcu::UVec3(128u, 128u, 8u),	tcu::UVec3(503u, 137u, 3u),	tcu::UVec3(11u, 37u, 3u) } },
    731 		{ IMAGE_TYPE_CUBE,		{ tcu::UVec3(256u, 256u, 1u),	tcu::UVec3(128u, 128u, 1u),	tcu::UVec3(137u, 137u, 1u),	tcu::UVec3(11u, 11u, 1u) } },
    732 		{ IMAGE_TYPE_CUBE_ARRAY,{ tcu::UVec3(256u, 256u, 6u),	tcu::UVec3(128u, 128u, 8u),	tcu::UVec3(137u, 137u, 3u),	tcu::UVec3(11u, 11u, 3u) } },
    733 		{ IMAGE_TYPE_3D,		{ tcu::UVec3(256u, 256u, 16u),	tcu::UVec3(128u, 128u, 8u),	tcu::UVec3(503u, 137u, 3u),	tcu::UVec3(11u, 37u, 3u) } }
    734 	};
    735 
    736 	static const tcu::TextureFormat formats[] =
    737 	{
    738 		tcu::TextureFormat(tcu::TextureFormat::R,	 tcu::TextureFormat::SIGNED_INT32),
    739 		tcu::TextureFormat(tcu::TextureFormat::R,	 tcu::TextureFormat::SIGNED_INT16),
    740 		tcu::TextureFormat(tcu::TextureFormat::R,	 tcu::TextureFormat::SIGNED_INT8),
    741 		tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32),
    742 		tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT16),
    743 		tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT8)
    744 	};
    745 
    746 	for (deInt32 imageTypeNdx = 0; imageTypeNdx < DE_LENGTH_OF_ARRAY(imageParametersArray); ++imageTypeNdx)
    747 	{
    748 		const ImageType					imageType = imageParametersArray[imageTypeNdx].imageType;
    749 		de::MovePtr<tcu::TestCaseGroup> imageTypeGroup(new tcu::TestCaseGroup(testCtx, getImageTypeName(imageType).c_str(), ""));
    750 
    751 		for (deInt32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
    752 		{
    753 			const tcu::TextureFormat&		format = formats[formatNdx];
    754 			de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, getShaderImageFormatQualifier(format).c_str(), ""));
    755 
    756 			for (deInt32 imageSizeNdx = 0; imageSizeNdx < DE_LENGTH_OF_ARRAY(imageParametersArray[imageTypeNdx].imageSizes); ++imageSizeNdx)
    757 			{
    758 				const tcu::UVec3 imageSize = imageParametersArray[imageTypeNdx].imageSizes[imageSizeNdx];
    759 
    760 				std::ostringstream stream;
    761 				stream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z();
    762 
    763 				formatGroup->addChild(new ImageSparseMemoryAliasingCase(testCtx, stream.str(), "", imageType, imageSize, format, glu::GLSL_VERSION_440, useDeviceGroup));
    764 			}
    765 			imageTypeGroup->addChild(formatGroup.release());
    766 		}
    767 		testGroup->addChild(imageTypeGroup.release());
    768 	}
    769 
    770 	return testGroup.release();
    771 }
    772 
    773 tcu::TestCaseGroup* createImageSparseMemoryAliasingTests(tcu::TestContext& testCtx)
    774 {
    775 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "image_sparse_memory_aliasing", "Sparse Image Memory Aliasing"));
    776 	return createImageSparseMemoryAliasingTestsCommon(testCtx, testGroup);
    777 }
    778 
    779 tcu::TestCaseGroup* createDeviceGroupImageSparseMemoryAliasingTests(tcu::TestContext& testCtx)
    780 {
    781 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "device_group_image_sparse_memory_aliasing", "Sparse Image Memory Aliasing"));
    782 	return createImageSparseMemoryAliasingTestsCommon(testCtx, testGroup, true);
    783 }
    784 
    785 } // sparse
    786 } // vkt
    787