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  vktSparseResourcesImageSparseBinding.cpp
21  * \brief Sparse fully resident images with mipmaps tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktSparseResourcesBufferSparseBinding.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 "vkMemUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 
42 #include "deUniquePtr.hpp"
43 #include "deStringUtil.hpp"
44 
45 #include <string>
46 #include <vector>
47 
48 using namespace vk;
49 
50 namespace vkt
51 {
52 namespace sparse
53 {
54 namespace
55 {
56 
57 class ImageSparseBindingCase : public TestCase
58 {
59 public:
60 					ImageSparseBindingCase	(tcu::TestContext&			testCtx,
61 											 const std::string&			name,
62 											 const std::string&			description,
63 											 const ImageType			imageType,
64 											 const tcu::UVec3&			imageSize,
65 											 const tcu::TextureFormat&	format,
66 											 const bool					useDeviceGroups = false);
67 
68 	TestInstance*	createInstance			(Context&					context) const;
69 
70 private:
71 	const bool					m_useDeviceGroups;
72 	const ImageType				m_imageType;
73 	const tcu::UVec3			m_imageSize;
74 	const tcu::TextureFormat	m_format;
75 };
76 
ImageSparseBindingCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const ImageType imageType,const tcu::UVec3 & imageSize,const tcu::TextureFormat & format,const bool useDeviceGroups)77 ImageSparseBindingCase::ImageSparseBindingCase (tcu::TestContext&			testCtx,
78 												const std::string&			name,
79 												const std::string&			description,
80 												const ImageType				imageType,
81 												const tcu::UVec3&			imageSize,
82 												const tcu::TextureFormat&	format,
83 												const bool					useDeviceGroups)
84 
85 	: TestCase				(testCtx, name, description)
86 	, m_useDeviceGroups		(useDeviceGroups)
87 	, m_imageType			(imageType)
88 	, m_imageSize			(imageSize)
89 	, m_format				(format)
90 {
91 }
92 
93 class ImageSparseBindingInstance : public SparseResourcesBaseInstance
94 {
95 public:
96 					ImageSparseBindingInstance	(Context&					context,
97 												 const ImageType			imageType,
98 												 const tcu::UVec3&			imageSize,
99 												 const tcu::TextureFormat&	format,
100 												 const bool					useDeviceGroups);
101 
102 	tcu::TestStatus	iterate						(void);
103 
104 private:
105 	const bool					m_useDeviceGroups;
106 	const ImageType				m_imageType;
107 	const tcu::UVec3			m_imageSize;
108 	const tcu::TextureFormat	m_format;
109 };
110 
ImageSparseBindingInstance(Context & context,const ImageType imageType,const tcu::UVec3 & imageSize,const tcu::TextureFormat & format,const bool useDeviceGroups)111 ImageSparseBindingInstance::ImageSparseBindingInstance (Context&					context,
112 														const ImageType				imageType,
113 														const tcu::UVec3&			imageSize,
114 														const tcu::TextureFormat&	format,
115 														const bool					useDeviceGroups)
116 
117 	: SparseResourcesBaseInstance	(context, useDeviceGroups)
118 	, m_useDeviceGroups				(useDeviceGroups)
119 	, m_imageType					(imageType)
120 	, m_imageSize					(imageSize)
121 	, m_format						(format)
122 {
123 }
124 
iterate(void)125 tcu::TestStatus ImageSparseBindingInstance::iterate (void)
126 {
127 	const InstanceInterface&	instance		= m_context.getInstanceInterface();
128 
129 	{
130 		// Create logical device supporting both sparse and compute queues
131 		QueueRequirementsVec queueRequirements;
132 		queueRequirements.push_back(QueueRequirements(VK_QUEUE_SPARSE_BINDING_BIT, 1u));
133 		queueRequirements.push_back(QueueRequirements(VK_QUEUE_COMPUTE_BIT, 1u));
134 
135 		createDeviceSupportingQueues(queueRequirements);
136 	}
137 
138 	const VkPhysicalDevice		physicalDevice	= getPhysicalDevice();
139 	VkImageCreateInfo			imageSparseInfo;
140 	std::vector<DeviceMemorySp>	deviceMemUniquePtrVec;
141 
142 	// Check if image size does not exceed device limits
143 	if (!isImageSizeSupported(instance, physicalDevice, m_imageType, m_imageSize))
144 		TCU_THROW(NotSupportedError, "Image size not supported for device");
145 
146 	// Check if device supports sparse binding
147 	if (!getPhysicalDeviceFeatures(instance, physicalDevice).sparseBinding)
148 		TCU_THROW(NotSupportedError, "Device does not support sparse binding");
149 
150 	const DeviceInterface&	deviceInterface	= getDeviceInterface();
151 	const Queue&			sparseQueue		= getQueue(VK_QUEUE_SPARSE_BINDING_BIT, 0);
152 	const Queue&			computeQueue	= getQueue(VK_QUEUE_COMPUTE_BIT, 0);
153 
154 	// Go through all physical devices
155 	for (deUint32 physDevID = 0; physDevID < m_numPhysicalDevices; physDevID++)
156 	{
157 		const deUint32	firstDeviceID	= physDevID;
158 		const deUint32	secondDeviceID	= (firstDeviceID + 1) % m_numPhysicalDevices;
159 
160 		imageSparseInfo.sType					= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;					//VkStructureType		sType;
161 		imageSparseInfo.pNext					= DE_NULL;												//const void*			pNext;
162 		imageSparseInfo.flags					= VK_IMAGE_CREATE_SPARSE_BINDING_BIT;					//VkImageCreateFlags	flags;
163 		imageSparseInfo.imageType				= mapImageType(m_imageType);							//VkImageType			imageType;
164 		imageSparseInfo.format					= mapTextureFormat(m_format);							//VkFormat				format;
165 		imageSparseInfo.extent					= makeExtent3D(getLayerSize(m_imageType, m_imageSize));	//VkExtent3D			extent;
166 		imageSparseInfo.arrayLayers				= getNumLayers(m_imageType, m_imageSize);				//deUint32				arrayLayers;
167 		imageSparseInfo.samples					= VK_SAMPLE_COUNT_1_BIT;								//VkSampleCountFlagBits	samples;
168 		imageSparseInfo.tiling					= VK_IMAGE_TILING_OPTIMAL;								//VkImageTiling			tiling;
169 		imageSparseInfo.initialLayout			= VK_IMAGE_LAYOUT_UNDEFINED;							//VkImageLayout			initialLayout;
170 		imageSparseInfo.usage					= VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
171 												  VK_IMAGE_USAGE_TRANSFER_DST_BIT;						//VkImageUsageFlags		usage;
172 		imageSparseInfo.sharingMode				= VK_SHARING_MODE_EXCLUSIVE;							//VkSharingMode			sharingMode;
173 		imageSparseInfo.queueFamilyIndexCount	= 0u;													//deUint32				queueFamilyIndexCount;
174 		imageSparseInfo.pQueueFamilyIndices		= DE_NULL;												//const deUint32*		pQueueFamilyIndices;
175 
176 		if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
177 		{
178 			imageSparseInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
179 		}
180 
181 		{
182 			VkImageFormatProperties imageFormatProperties;
183 			instance.getPhysicalDeviceImageFormatProperties(physicalDevice,
184 				imageSparseInfo.format,
185 				imageSparseInfo.imageType,
186 				imageSparseInfo.tiling,
187 				imageSparseInfo.usage,
188 				imageSparseInfo.flags,
189 				&imageFormatProperties);
190 
191 			imageSparseInfo.mipLevels = getImageMaxMipLevels(imageFormatProperties, imageSparseInfo.extent);
192 		}
193 
194 		// Create sparse image
195 		const Unique<VkImage> imageSparse(createImage(deviceInterface, getDevice(), &imageSparseInfo));
196 
197 		// Create sparse image memory bind semaphore
198 		const Unique<VkSemaphore> imageMemoryBindSemaphore(createSemaphore(deviceInterface, getDevice()));
199 
200 		// Get sparse image general memory requirements
201 		const VkMemoryRequirements imageSparseMemRequirements = getImageMemoryRequirements(deviceInterface, getDevice(), *imageSparse);
202 
203 		// Check if required image memory size does not exceed device limits
204 		if (imageSparseMemRequirements.size > getPhysicalDeviceProperties(instance, getPhysicalDevice(secondDeviceID)).limits.sparseAddressSpaceSize)
205 			TCU_THROW(NotSupportedError, "Required memory size for sparse resource exceeds device limits");
206 
207 		DE_ASSERT((imageSparseMemRequirements.size % imageSparseMemRequirements.alignment) == 0);
208 
209 		{
210 			std::vector<VkSparseMemoryBind>	sparseMemoryBinds;
211 			const deUint32					numSparseBinds	= static_cast<deUint32>(imageSparseMemRequirements.size / imageSparseMemRequirements.alignment);
212 			const deUint32					memoryType		= findMatchingMemoryType(instance, getPhysicalDevice(secondDeviceID), imageSparseMemRequirements, MemoryRequirement::Any);
213 
214 			if (memoryType == NO_MATCH_FOUND)
215 				return tcu::TestStatus::fail("No matching memory type found");
216 
217 			if (firstDeviceID != secondDeviceID)
218 			{
219 				VkPeerMemoryFeatureFlags	peerMemoryFeatureFlags = (VkPeerMemoryFeatureFlags)0;
220 				const deUint32				heapIndex = getHeapIndexForMemoryType(instance, getPhysicalDevice(secondDeviceID), memoryType);
221 				deviceInterface.getDeviceGroupPeerMemoryFeatures(getDevice(), heapIndex, firstDeviceID, secondDeviceID, &peerMemoryFeatureFlags);
222 
223 				if (((peerMemoryFeatureFlags & VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT) == 0) ||
224 					((peerMemoryFeatureFlags & VK_PEER_MEMORY_FEATURE_COPY_DST_BIT) == 0))
225 				{
226 					TCU_THROW(NotSupportedError, "Peer memory does not support COPY_SRC and COPY_DST");
227 				}
228 			}
229 
230 			for (deUint32 sparseBindNdx = 0; sparseBindNdx < numSparseBinds; ++sparseBindNdx)
231 			{
232 				const VkSparseMemoryBind sparseMemoryBind = makeSparseMemoryBind(deviceInterface, getDevice(),
233 					imageSparseMemRequirements.alignment, memoryType, imageSparseMemRequirements.alignment * sparseBindNdx);
234 
235 				deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(sparseMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
236 
237 				sparseMemoryBinds.push_back(sparseMemoryBind);
238 			}
239 
240 			const VkSparseImageOpaqueMemoryBindInfo opaqueBindInfo = makeSparseImageOpaqueMemoryBindInfo(*imageSparse, numSparseBinds, &sparseMemoryBinds[0]);
241 
242 			const VkDeviceGroupBindSparseInfo devGroupBindSparseInfo =
243 			{
244 				VK_STRUCTURE_TYPE_DEVICE_GROUP_BIND_SPARSE_INFO_KHR,	//VkStructureType							sType;
245 				DE_NULL,												//const void*								pNext;
246 				firstDeviceID,											//deUint32									resourceDeviceIndex;
247 				secondDeviceID,											//deUint32									memoryDeviceIndex;
248 			};
249 
250 			const VkBindSparseInfo bindSparseInfo =
251 			{
252 				VK_STRUCTURE_TYPE_BIND_SPARSE_INFO,						//VkStructureType							sType;
253 				m_useDeviceGroups ? &devGroupBindSparseInfo : DE_NULL,	//const void*								pNext;
254 				0u,														//deUint32									waitSemaphoreCount;
255 				DE_NULL,												//const VkSemaphore*						pWaitSemaphores;
256 				0u,														//deUint32									bufferBindCount;
257 				DE_NULL,												//const VkSparseBufferMemoryBindInfo*		pBufferBinds;
258 				1u,														//deUint32									imageOpaqueBindCount;
259 				&opaqueBindInfo,										//const VkSparseImageOpaqueMemoryBindInfo*	pImageOpaqueBinds;
260 				0u,														//deUint32									imageBindCount;
261 				DE_NULL,												//const VkSparseImageMemoryBindInfo*		pImageBinds;
262 				1u,														//deUint32									signalSemaphoreCount;
263 				&imageMemoryBindSemaphore.get()							//const VkSemaphore*						pSignalSemaphores;
264 			};
265 
266 			// Submit sparse bind commands for execution
267 			VK_CHECK(deviceInterface.queueBindSparse(sparseQueue.queueHandle, 1u, &bindSparseInfo, DE_NULL));
268 		}
269 
270 		// Create command buffer for compute and transfer oparations
271 		const Unique<VkCommandPool>	  commandPool(makeCommandPool(deviceInterface, getDevice(), computeQueue.queueFamilyIndex));
272 		const Unique<VkCommandBuffer> commandBuffer(allocateCommandBuffer(deviceInterface, getDevice(), *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
273 
274 		std::vector<VkBufferImageCopy> bufferImageCopy(imageSparseInfo.mipLevels);
275 
276 		{
277 			deUint32 bufferOffset = 0;
278 			for (deUint32 mipmapNdx = 0; mipmapNdx < imageSparseInfo.mipLevels; mipmapNdx++)
279 			{
280 				bufferImageCopy[mipmapNdx] = makeBufferImageCopy(mipLevelExtents(imageSparseInfo.extent, mipmapNdx), imageSparseInfo.arrayLayers, mipmapNdx, static_cast<VkDeviceSize>(bufferOffset));
281 				bufferOffset += getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_format, mipmapNdx, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY);
282 			}
283 		}
284 
285 		// Start recording commands
286 		beginCommandBuffer(deviceInterface, *commandBuffer);
287 
288 		const deUint32					imageSizeInBytes		= getImageSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_format, imageSparseInfo.mipLevels, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY);
289 		const VkBufferCreateInfo		inputBufferCreateInfo	= makeBufferCreateInfo(imageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
290 		const Unique<VkBuffer>			inputBuffer				(createBuffer(deviceInterface, getDevice(), &inputBufferCreateInfo));
291 		const de::UniquePtr<Allocation>	inputBufferAlloc		(bindBuffer(deviceInterface, getDevice(), getAllocator(), *inputBuffer, MemoryRequirement::HostVisible));
292 
293 		std::vector<deUint8> referenceData(imageSizeInBytes);
294 
295 		for (deUint32 valueNdx = 0; valueNdx < imageSizeInBytes; ++valueNdx)
296 		{
297 			referenceData[valueNdx] = static_cast<deUint8>((valueNdx % imageSparseMemRequirements.alignment) + 1u);
298 		}
299 
300 		deMemcpy(inputBufferAlloc->getHostPtr(), &referenceData[0], imageSizeInBytes);
301 
302 		flushAlloc(deviceInterface, getDevice(), *inputBufferAlloc);
303 
304 		{
305 			const VkBufferMemoryBarrier inputBufferBarrier = makeBufferMemoryBarrier
306 			(
307 				VK_ACCESS_HOST_WRITE_BIT,
308 				VK_ACCESS_TRANSFER_READ_BIT,
309 				*inputBuffer,
310 				0u,
311 				imageSizeInBytes
312 			);
313 
314 			deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 1u, &inputBufferBarrier, 0u, DE_NULL);
315 		}
316 
317 		{
318 			const VkImageMemoryBarrier imageSparseTransferDstBarrier = makeImageMemoryBarrier
319 			(
320 				0u,
321 				VK_ACCESS_TRANSFER_WRITE_BIT,
322 				VK_IMAGE_LAYOUT_UNDEFINED,
323 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
324 				*imageSparse,
325 				makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers),
326 				sparseQueue.queueFamilyIndex != computeQueue.queueFamilyIndex ? sparseQueue.queueFamilyIndex : VK_QUEUE_FAMILY_IGNORED,
327 				sparseQueue.queueFamilyIndex != computeQueue.queueFamilyIndex ? computeQueue.queueFamilyIndex : VK_QUEUE_FAMILY_IGNORED
328 				);
329 
330 			deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageSparseTransferDstBarrier);
331 		}
332 
333 		deviceInterface.cmdCopyBufferToImage(*commandBuffer, *inputBuffer, *imageSparse, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, static_cast<deUint32>(bufferImageCopy.size()), &bufferImageCopy[0]);
334 
335 		{
336 			const VkImageMemoryBarrier imageSparseTransferSrcBarrier = makeImageMemoryBarrier
337 			(
338 				VK_ACCESS_TRANSFER_WRITE_BIT,
339 				VK_ACCESS_TRANSFER_READ_BIT,
340 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
341 				VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
342 				*imageSparse,
343 				makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers)
344 			);
345 
346 			deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageSparseTransferSrcBarrier);
347 		}
348 
349 		const VkBufferCreateInfo		outputBufferCreateInfo	= makeBufferCreateInfo(imageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
350 		const Unique<VkBuffer>			outputBuffer			(createBuffer(deviceInterface, getDevice(), &outputBufferCreateInfo));
351 		const de::UniquePtr<Allocation>	outputBufferAlloc		(bindBuffer(deviceInterface, getDevice(), getAllocator(), *outputBuffer, MemoryRequirement::HostVisible));
352 
353 		deviceInterface.cmdCopyImageToBuffer(*commandBuffer, *imageSparse, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *outputBuffer, static_cast<deUint32>(bufferImageCopy.size()), &bufferImageCopy[0]);
354 
355 		{
356 			const VkBufferMemoryBarrier outputBufferBarrier = makeBufferMemoryBarrier
357 			(
358 				VK_ACCESS_TRANSFER_WRITE_BIT,
359 				VK_ACCESS_HOST_READ_BIT,
360 				*outputBuffer,
361 				0u,
362 				imageSizeInBytes
363 			);
364 
365 			deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &outputBufferBarrier, 0u, DE_NULL);
366 		}
367 
368 		// End recording commands
369 		endCommandBuffer(deviceInterface, *commandBuffer);
370 
371 		const VkPipelineStageFlags stageBits[] = { VK_PIPELINE_STAGE_TRANSFER_BIT };
372 
373 		// Submit commands for execution and wait for completion
374 		submitCommandsAndWait(deviceInterface, getDevice(), computeQueue.queueHandle, *commandBuffer, 1u, &imageMemoryBindSemaphore.get(), stageBits,
375 			0, DE_NULL, m_useDeviceGroups, firstDeviceID);
376 
377 		// Retrieve data from buffer to host memory
378 		invalidateAlloc(deviceInterface, getDevice(), *outputBufferAlloc);
379 
380 		const deUint8* outputData = static_cast<const deUint8*>(outputBufferAlloc->getHostPtr());
381 
382 		// Wait for sparse queue to become idle
383 		deviceInterface.queueWaitIdle(sparseQueue.queueHandle);
384 
385 		for (deUint32 mipmapNdx = 0; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
386 		{
387 			const deUint32 mipLevelSizeInBytes	= getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_format, mipmapNdx);
388 			const deUint32 bufferOffset			= static_cast<deUint32>(bufferImageCopy[mipmapNdx].bufferOffset);
389 
390 			if (deMemCmp(outputData + bufferOffset, &referenceData[bufferOffset], mipLevelSizeInBytes) != 0)
391 				return tcu::TestStatus::fail("Failed");
392 		}
393 	}
394 
395 	return tcu::TestStatus::pass("Passed");
396 }
397 
createInstance(Context & context) const398 TestInstance* ImageSparseBindingCase::createInstance (Context& context) const
399 {
400 	return new ImageSparseBindingInstance(context, m_imageType, m_imageSize, m_format, m_useDeviceGroups);
401 }
402 
403 } // anonymous ns
404 
createImageSparseBindingTestsCommon(tcu::TestContext & testCtx,de::MovePtr<tcu::TestCaseGroup> testGroup,const bool useDeviceGroup=false)405 tcu::TestCaseGroup* createImageSparseBindingTestsCommon(tcu::TestContext& testCtx, de::MovePtr<tcu::TestCaseGroup> testGroup, const bool useDeviceGroup = false)
406 {
407 	static const deUint32 sizeCountPerImageType = 3u;
408 
409 	struct ImageParameters
410 	{
411 		ImageType	imageType;
412 		tcu::UVec3	imageSizes[sizeCountPerImageType];
413 	};
414 
415 	static const ImageParameters imageParametersArray[] =
416 	{
417 		{ IMAGE_TYPE_1D,		{ tcu::UVec3(512u, 1u,   1u ), tcu::UVec3(1024u, 1u,   1u), tcu::UVec3(11u,  1u,   1u) } },
418 		{ IMAGE_TYPE_1D_ARRAY,  { tcu::UVec3(512u, 1u,   64u), tcu::UVec3(1024u, 1u,   8u), tcu::UVec3(11u,  1u,   3u) } },
419 		{ IMAGE_TYPE_2D,		{ tcu::UVec3(512u, 256u, 1u ), tcu::UVec3(1024u, 128u, 1u), tcu::UVec3(11u,  137u, 1u) } },
420 		{ IMAGE_TYPE_2D_ARRAY,	{ tcu::UVec3(512u, 256u, 6u ), tcu::UVec3(1024u, 128u, 8u), tcu::UVec3(11u,  137u, 3u) } },
421 		{ IMAGE_TYPE_3D,		{ tcu::UVec3(512u, 256u, 6u ), tcu::UVec3(1024u, 128u, 8u), tcu::UVec3(11u,  137u, 3u) } },
422 		{ IMAGE_TYPE_CUBE,		{ tcu::UVec3(256u, 256u, 1u ), tcu::UVec3(128u,  128u, 1u), tcu::UVec3(137u, 137u, 1u) } },
423 		{ IMAGE_TYPE_CUBE_ARRAY,{ tcu::UVec3(256u, 256u, 6u ), tcu::UVec3(128u,  128u, 8u), tcu::UVec3(137u, 137u, 3u) } }
424 	};
425 
426 	static const tcu::TextureFormat formats[] =
427 	{
428 		tcu::TextureFormat(tcu::TextureFormat::R,		tcu::TextureFormat::SIGNED_INT32),
429 		tcu::TextureFormat(tcu::TextureFormat::R,		tcu::TextureFormat::SIGNED_INT16),
430 		tcu::TextureFormat(tcu::TextureFormat::R,		tcu::TextureFormat::SIGNED_INT8),
431 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNSIGNED_INT32),
432 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNSIGNED_INT16),
433 		tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNSIGNED_INT8)
434 	};
435 
436 
437 	for (deInt32 imageTypeNdx = 0; imageTypeNdx < DE_LENGTH_OF_ARRAY(imageParametersArray); ++imageTypeNdx)
438 	{
439 		const ImageType					imageType = imageParametersArray[imageTypeNdx].imageType;
440 		de::MovePtr<tcu::TestCaseGroup> imageTypeGroup(new tcu::TestCaseGroup(testCtx, getImageTypeName(imageType).c_str(), ""));
441 
442 		for (deInt32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
443 		{
444 			const tcu::TextureFormat&		format = formats[formatNdx];
445 			de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, getShaderImageFormatQualifier(format).c_str(), ""));
446 
447 			for (deInt32 imageSizeNdx = 0; imageSizeNdx < DE_LENGTH_OF_ARRAY(imageParametersArray[imageTypeNdx].imageSizes); ++imageSizeNdx)
448 			{
449 				const tcu::UVec3 imageSize = imageParametersArray[imageTypeNdx].imageSizes[imageSizeNdx];
450 				std::ostringstream	stream;
451 				stream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z();
452 
453 				formatGroup->addChild(new ImageSparseBindingCase(testCtx, stream.str(), "", imageType, imageSize, format, useDeviceGroup));
454 			}
455 			imageTypeGroup->addChild(formatGroup.release());
456 		}
457 		testGroup->addChild(imageTypeGroup.release());
458 	}
459 
460 	return testGroup.release();
461 }
462 
createImageSparseBindingTests(tcu::TestContext & testCtx)463 tcu::TestCaseGroup* createImageSparseBindingTests(tcu::TestContext& testCtx)
464 {
465 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "image_sparse_binding", "Image Sparse Binding"));
466 	return createImageSparseBindingTestsCommon(testCtx, testGroup);
467 }
468 
createDeviceGroupImageSparseBindingTests(tcu::TestContext & testCtx)469 tcu::TestCaseGroup* createDeviceGroupImageSparseBindingTests(tcu::TestContext& testCtx)
470 {
471 	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "device_group_image_sparse_binding", "Device Group Image Sparse Binding"));
472 	return createImageSparseBindingTestsCommon(testCtx, testGroup, true);
473 }
474 
475 } // sparse
476 } // vkt
477