• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 Google 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  vktImageTransfer.cpp
21  * \brief Tests for image transfers
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktTestCase.hpp"
25 
26 #include "vkImageUtil.hpp"
27 #include "vkBarrierUtil.hpp"
28 #include "vkTypeUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkStrUtil.hpp"
31 #include "vkBufferWithMemory.hpp"
32 #include "vkImageWithMemory.hpp"
33 
34 #include "tcuTestLog.hpp"
35 #include "vktTestCase.hpp"
36 #include "tcuTextureUtil.hpp"
37 #include "tcuCommandLine.hpp"
38 #include "vktImageTestsUtil.hpp"
39 #include "vkRefUtil.hpp"
40 #include "deRandom.hpp"
41 #include "ycbcr/vktYCbCrUtil.hpp"
42 
43 #include <vector>
44 #include <string>
45 
46 using namespace vk;
47 
48 namespace vkt
49 {
50 using namespace ycbcr;
51 namespace image
52 {
53 namespace
54 {
55 
56 class TransferQueueCase : public vkt::TestCase
57 {
58 public:
59 	struct TestParams
60 	{
61 		VkImageType	imageType;
62 		VkFormat	imageFormat;
63 		VkExtent3D	dimensions;		// .depth will be the number of layers for 2D images and the depth for 3D images.
64 	};
65 
66 							TransferQueueCase				(tcu::TestContext& testCtx, const std::string& name, const TestParams& params);
~TransferQueueCase(void)67 	virtual					~TransferQueueCase				(void) {}
68 
initPrograms(vk::SourceCollections &) const69 	virtual void			initPrograms					(vk::SourceCollections&) const {}
70 	virtual TestInstance*	createInstance					(Context& context) const;
71 	virtual void			checkSupport					(Context& context) const;
72 private:
73 	TestParams m_params;
74 };
75 
76 class TransferQueueInstance : public vkt::TestInstance
77 {
78 public:
79 								TransferQueueInstance			(Context& context, const TransferQueueCase::TestParams& params);
~TransferQueueInstance(void)80 	virtual						~TransferQueueInstance			(void) {}
81 
82 	virtual tcu::TestStatus		iterate							(void);
83 private:
84 	TransferQueueCase::TestParams m_params;
85 	Move<VkCommandPool>					m_cmdPool;
86 	Move<VkCommandBuffer>				m_cmdBuffer;
87 };
88 
TransferQueueCase(tcu::TestContext & testCtx,const std::string & name,const TestParams & params)89 TransferQueueCase::TransferQueueCase (tcu::TestContext& testCtx, const std::string& name, const TestParams& params)
90 	: vkt::TestCase	(testCtx, name)
91 	, m_params		(params)
92 {
93 }
94 
createInstance(Context & context) const95 TestInstance* TransferQueueCase::createInstance (Context& context) const
96 {
97 	return new TransferQueueInstance (context, m_params);
98 }
99 
checkSupport(Context & context) const100 void TransferQueueCase::checkSupport (Context& context) const
101 {
102 	const auto& vki				= context.getInstanceInterface();
103 	const auto	physicalDevice	= context.getPhysicalDevice();
104 
105 #ifndef CTS_USES_VULKANSC
106 	if (m_params.imageFormat == VK_FORMAT_A8_UNORM_KHR || m_params.imageFormat == VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR)
107 		context.requireDeviceFunctionality("VK_KHR_maintenance5");
108 #endif // CTS_USES_VULKANSC
109 
110 	VkImageFormatProperties	formatProperties;
111 	const auto result = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, m_params.imageFormat, m_params.imageType, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0u, &formatProperties);
112 	if (result != VK_SUCCESS)
113 	{
114 		if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
115 			TCU_THROW(NotSupportedError, "format " + de::toString(m_params.imageFormat) + " does not support the required features");
116 		else
117 			TCU_FAIL("vkGetPhysicalDeviceImageFormatProperties returned unexpected error");
118 	}
119 }
120 
TransferQueueInstance(Context & context,const TransferQueueCase::TestParams & params)121 TransferQueueInstance::TransferQueueInstance (Context& context, const TransferQueueCase::TestParams& params)
122 	: vkt::TestInstance	(context)
123 	, m_params			(params)
124 {
125 	const auto& vk					= context.getDeviceInterface();
126 	const auto& device				= context.getDevice();
127 	const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
128 
129 	// Create command pool
130 	m_cmdPool = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
131 
132 	// Create command buffer
133 	m_cmdBuffer = allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
134 }
135 
iterate(void)136 tcu::TestStatus TransferQueueInstance::iterate (void)
137 {
138 	// Test every aspect supported by the image format.
139 	const auto tcuFormat			= mapVkFormat(m_params.imageFormat);
140 
141 	Allocator& allocator			= m_context.getDefaultAllocator();
142 	const auto& vk					= m_context.getDeviceInterface();
143 	const auto device				= m_context.getDevice();
144 	const auto queue				= getDeviceQueue(m_context.getDeviceInterface(), device, m_context.getUniversalQueueFamilyIndex(), 0u);
145 
146 	const auto width				= m_params.dimensions.width;
147 	const auto height				= m_params.dimensions.height;
148 	const auto layers				= m_params.imageType == vk::VK_IMAGE_TYPE_3D ? 1u : m_params.dimensions.depth;
149 	const auto depth				= m_params.imageType == vk::VK_IMAGE_TYPE_3D ? m_params.dimensions.depth : 1u;
150 	const uint32_t pixelDataSize	= tcuFormat.getPixelSize() * width * height * layers * depth;
151 
152 	const vk::VkBufferCreateInfo bufferCreateInfo =
153 	{
154 		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
155 		DE_NULL,
156 		0u,																						// flags
157 		static_cast<VkDeviceSize>(pixelDataSize),												// size
158 		vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// usage
159 		vk::VK_SHARING_MODE_EXCLUSIVE,															// sharingMode
160 		0u,																						// queueFamilyCount
161 		DE_NULL,																				// pQueueFamilyIndices
162 	};
163 
164 	BufferWithMemory srcBuffer(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible);
165 	BufferWithMemory dstBuffer(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible);
166 
167 	vk::VkExtent3D extent = { m_params.dimensions.width, m_params.dimensions.height, depth };
168 	const vk::VkImageCreateInfo	imageCreateInfo =
169 	{
170 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType		sType;
171 		DE_NULL,								// const void*			pNext;
172 		0,										// VkImageCreateFlags	flags;
173 		m_params.imageType,						// VkImageType			imageType;
174 		m_params.imageFormat,					// VkFormat				format;
175 		extent,									// VkExtent3D			extent;
176 		1u,										// deUint32				mipLevels;
177 		layers,									// deUint32				arraySize;
178 		VK_SAMPLE_COUNT_1_BIT,					// deUint32				samples;
179 		VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling		tiling;
180 		VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
181 			VK_IMAGE_USAGE_TRANSFER_DST_BIT,	// VkImageUsageFlags	usage;
182 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
183 		0u,										// deUint32				queueFamilyIndexCount;
184 		(const deUint32*)DE_NULL,				// const deUint32*		pQueueFamilyIndices;
185 		VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout		initialLayout;
186 	};
187 	Image image(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any);
188 
189 	// Generate data for source buffer and copy it into buffer
190 	std::vector<deUint8>			generatedData	(pixelDataSize);
191 	de::Random						randomGen		(deInt32Hash((deUint32)m_params.imageFormat) ^
192 													 deInt32Hash((deUint32)m_params.imageType) ^
193 													 deInt32Hash((deUint32)m_params.dimensions.width) ^
194 													 deInt32Hash((deUint32)m_params.dimensions.height) ^
195 													 deInt32Hash((deUint32)m_params.dimensions.depth));
196 	{
197 		fillRandomNoNaN(&randomGen, generatedData.data(), (deUint32)generatedData.size(), m_params.imageFormat);
198 		const Allocation& alloc = srcBuffer.getAllocation();
199 		deMemcpy(alloc.getHostPtr(), generatedData.data(), generatedData.size());
200 		flushAlloc(vk, device, alloc);
201 	}
202 
203 	beginCommandBuffer(vk, *m_cmdBuffer);
204 	const VkImageSubresourceRange			subresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, layers);
205 	const VkImageMemoryBarrier				imageBarrier		= makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, *image, subresourceRange);
206 	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1u, &imageBarrier);
207 	// Copy buffer to image
208 	{
209 		const bool		isCompressed	= isCompressedFormat(m_params.imageFormat);
210 		const deUint32	blockHeight		= (isCompressed) ? getBlockHeight(m_params.imageFormat) : 1u;
211 		deUint32		imageHeight		= ((height + blockHeight - 1) / blockHeight) * blockHeight;
212 
213 		const vk::VkBufferImageCopy	copyRegion =
214 		{
215 			0u,												// VkDeviceSize				bufferOffset;
216 			0,												// deUint32					bufferRowLength;
217 			imageHeight,									// deUint32					bufferImageHeight;
218 			{
219 				VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags		aspect;
220 				0,											// deUint32					mipLevel;
221 				0u,											// deUint32					baseArrayLayer;
222 				layers,										// deUint32					layerCount;
223 			},												// VkImageSubresourceLayers	imageSubresource;
224 			{ 0, 0, 0 },									// VkOffset3D				imageOffset;
225 			extent											// VkExtent3D				imageExtent;
226 		};
227 
228 		const VkImageMemoryBarrier		postImageBarrier =
229 		{
230 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
231 			DE_NULL,										// const void*				pNext;
232 			VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			srcAccessMask;
233 			VK_ACCESS_TRANSFER_READ_BIT,					// VkAccessFlags			dstAccessMask;
234 			VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout			oldLayout;
235 			VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout			newLayout;
236 			VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
237 			VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex;
238 			*image,											// VkImage					image;
239 			{												// VkImageSubresourceRange	subresourceRange;
240 				VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspect;
241 				0u,							// deUint32				baseMipLevel;
242 				1,							// deUint32				mipLevels;
243 				0u,							// deUint32				baseArraySlice;
244 				layers,						// deUint32				arraySize;
245 			}
246 		};
247 
248 		vk.cmdCopyBufferToImage(*m_cmdBuffer, *srcBuffer, *image, VK_IMAGE_LAYOUT_GENERAL, 1, &copyRegion);
249 
250 		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
251 
252 		vk.cmdCopyImageToBuffer(*m_cmdBuffer, *image, VK_IMAGE_LAYOUT_GENERAL, *dstBuffer, 1, &copyRegion);
253 	}
254 	endCommandBuffer(vk, *m_cmdBuffer);
255 
256 	submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
257 
258 	{
259 		std::vector<deUint8> resultData(pixelDataSize);
260 		const Allocation& alloc = dstBuffer.getAllocation();
261 		invalidateAlloc(vk, device, alloc);
262 		deMemcpy(resultData.data(), alloc.getHostPtr(), resultData.size());
263 
264 		for (uint32_t i = 0; i < pixelDataSize; ++i) {
265 			if (resultData[i] != generatedData[i]) {
266 				return tcu::TestStatus::fail("Transfer queue test");
267 			}
268 		}
269 	}
270 
271 	return tcu::TestStatus::pass("Pass");
272 }
273 
274 } // anonymous namespace
275 
getAspectFlags(tcu::TextureFormat format)276 VkImageAspectFlags getAspectFlags (tcu::TextureFormat format)
277 {
278 	VkImageAspectFlags	aspectFlag = 0;
279 	aspectFlag |= (tcu::hasDepthComponent(format.order) ? VK_IMAGE_ASPECT_DEPTH_BIT : 0);
280 	aspectFlag |= (tcu::hasStencilComponent(format.order) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0);
281 
282 	if (!aspectFlag)
283 		aspectFlag = VK_IMAGE_ASPECT_COLOR_BIT;
284 
285 	return aspectFlag;
286 }
287 
createTransferQueueImageTests(tcu::TestContext & testCtx)288 tcu::TestCaseGroup* createTransferQueueImageTests (tcu::TestContext& testCtx)
289 {
290 	de::MovePtr<tcu::TestCaseGroup> layoutTestGroup (new tcu::TestCaseGroup(testCtx, "queue_transfer"));
291 
292 	struct
293 	{
294 		VkImageType	type;
295 		bool		array;
296 		const char*	name;
297 	} imageClass[] =
298 	{
299 		// 2D images
300 		{ VK_IMAGE_TYPE_2D,	false,	"2d"},
301 		// 2D images with multiple layers
302 		{ VK_IMAGE_TYPE_2D,	true,	"2d_array"},
303 		// 3D images
304 		{ VK_IMAGE_TYPE_3D,	false,	"3d"},
305 	};
306 
307 	struct
308 	{
309 		VkExtent3D	extent;
310 		const char*	name;
311 		const char*	desc;
312 	} extents[] =
313 	{
314 		{ {4u,	3u,		1u},							"4x3x1",			"4x3x1 extent"				},
315 		{ {16u, 15u,	1u},							"16x15x1",			"16x15x1 extent"			},
316 		{ {64u, 31u,	1u},							"64x31x1",			"64x31x1 extent"			},
317 		{ {4u,	3u,		2u},							"4x3x2",			"4x3x2extent"				},
318 		{ {16u, 15u,	16u},							"16x15x16",			"16x15x16 extent"			},
319 	};
320 
321 	VkFormat testFormats[] =
322 	{
323 		VK_FORMAT_R4G4_UNORM_PACK8,
324 		VK_FORMAT_R4G4B4A4_UNORM_PACK16,
325 		VK_FORMAT_B4G4R4A4_UNORM_PACK16,
326 		VK_FORMAT_R5G6B5_UNORM_PACK16,
327 		VK_FORMAT_B5G6R5_UNORM_PACK16,
328 		VK_FORMAT_R5G5B5A1_UNORM_PACK16,
329 		VK_FORMAT_B5G5R5A1_UNORM_PACK16,
330 		VK_FORMAT_A1R5G5B5_UNORM_PACK16,
331 #ifndef CTS_USES_VULKANSC
332 		VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR,
333 #endif // CTS_USES_VULKANSC
334 		VK_FORMAT_R8_UNORM,
335 		VK_FORMAT_R8_SNORM,
336 		VK_FORMAT_R8_USCALED,
337 		VK_FORMAT_R8_SSCALED,
338 		VK_FORMAT_R8_UINT,
339 		VK_FORMAT_R8_SINT,
340 		VK_FORMAT_R8_SRGB,
341 #ifndef CTS_USES_VULKANSC
342 		VK_FORMAT_A8_UNORM_KHR,
343 #endif // CTS_USES_VULKANSC
344 		VK_FORMAT_R8G8_UNORM,
345 		VK_FORMAT_R8G8_SNORM,
346 		VK_FORMAT_R8G8_USCALED,
347 		VK_FORMAT_R8G8_SSCALED,
348 		VK_FORMAT_R8G8_UINT,
349 		VK_FORMAT_R8G8_SINT,
350 		VK_FORMAT_R8G8_SRGB,
351 		VK_FORMAT_R8G8B8_UNORM,
352 		VK_FORMAT_R8G8B8_SNORM,
353 		VK_FORMAT_R8G8B8_USCALED,
354 		VK_FORMAT_R8G8B8_SSCALED,
355 		VK_FORMAT_R8G8B8_UINT,
356 		VK_FORMAT_R8G8B8_SINT,
357 		VK_FORMAT_R8G8B8_SRGB,
358 		VK_FORMAT_B8G8R8_UNORM,
359 		VK_FORMAT_B8G8R8_SNORM,
360 		VK_FORMAT_B8G8R8_USCALED,
361 		VK_FORMAT_B8G8R8_SSCALED,
362 		VK_FORMAT_B8G8R8_UINT,
363 		VK_FORMAT_B8G8R8_SINT,
364 		VK_FORMAT_B8G8R8_SRGB,
365 		VK_FORMAT_R8G8B8A8_UNORM,
366 		VK_FORMAT_R8G8B8A8_SNORM,
367 		VK_FORMAT_R8G8B8A8_USCALED,
368 		VK_FORMAT_R8G8B8A8_SSCALED,
369 		VK_FORMAT_R8G8B8A8_UINT,
370 		VK_FORMAT_R8G8B8A8_SINT,
371 		VK_FORMAT_R8G8B8A8_SRGB,
372 		VK_FORMAT_B8G8R8A8_UNORM,
373 		VK_FORMAT_B8G8R8A8_SNORM,
374 		VK_FORMAT_B8G8R8A8_USCALED,
375 		VK_FORMAT_B8G8R8A8_SSCALED,
376 		VK_FORMAT_B8G8R8A8_UINT,
377 		VK_FORMAT_B8G8R8A8_SINT,
378 		VK_FORMAT_B8G8R8A8_SRGB,
379 		VK_FORMAT_A8B8G8R8_UNORM_PACK32,
380 		VK_FORMAT_A8B8G8R8_SNORM_PACK32,
381 		VK_FORMAT_A8B8G8R8_USCALED_PACK32,
382 		VK_FORMAT_A8B8G8R8_SSCALED_PACK32,
383 		VK_FORMAT_A8B8G8R8_UINT_PACK32,
384 		VK_FORMAT_A8B8G8R8_SINT_PACK32,
385 		VK_FORMAT_A8B8G8R8_SRGB_PACK32,
386 		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
387 		VK_FORMAT_A2R10G10B10_SNORM_PACK32,
388 		VK_FORMAT_A2R10G10B10_USCALED_PACK32,
389 		VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
390 		VK_FORMAT_A2R10G10B10_UINT_PACK32,
391 		VK_FORMAT_A2R10G10B10_SINT_PACK32,
392 		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
393 		VK_FORMAT_A2B10G10R10_SNORM_PACK32,
394 		VK_FORMAT_A2B10G10R10_USCALED_PACK32,
395 		VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
396 		VK_FORMAT_A2B10G10R10_UINT_PACK32,
397 		VK_FORMAT_A2B10G10R10_SINT_PACK32,
398 		VK_FORMAT_R16_UNORM,
399 		VK_FORMAT_R16_SNORM,
400 		VK_FORMAT_R16_USCALED,
401 		VK_FORMAT_R16_SSCALED,
402 		VK_FORMAT_R16_UINT,
403 		VK_FORMAT_R16_SINT,
404 		VK_FORMAT_R16_SFLOAT,
405 		VK_FORMAT_R16G16_UNORM,
406 		VK_FORMAT_R16G16_SNORM,
407 		VK_FORMAT_R16G16_USCALED,
408 		VK_FORMAT_R16G16_SSCALED,
409 		VK_FORMAT_R16G16_UINT,
410 		VK_FORMAT_R16G16_SINT,
411 		VK_FORMAT_R16G16_SFLOAT,
412 		VK_FORMAT_R16G16B16_UNORM,
413 		VK_FORMAT_R16G16B16_SNORM,
414 		VK_FORMAT_R16G16B16_USCALED,
415 		VK_FORMAT_R16G16B16_SSCALED,
416 		VK_FORMAT_R16G16B16_UINT,
417 		VK_FORMAT_R16G16B16_SINT,
418 		VK_FORMAT_R16G16B16_SFLOAT,
419 		VK_FORMAT_R16G16B16A16_UNORM,
420 		VK_FORMAT_R16G16B16A16_SNORM,
421 		VK_FORMAT_R16G16B16A16_USCALED,
422 		VK_FORMAT_R16G16B16A16_SSCALED,
423 		VK_FORMAT_R16G16B16A16_UINT,
424 		VK_FORMAT_R16G16B16A16_SINT,
425 		VK_FORMAT_R16G16B16A16_SFLOAT,
426 		VK_FORMAT_R32_UINT,
427 		VK_FORMAT_R32_SINT,
428 		VK_FORMAT_R32_SFLOAT,
429 		VK_FORMAT_R32G32_UINT,
430 		VK_FORMAT_R32G32_SINT,
431 		VK_FORMAT_R32G32_SFLOAT,
432 		VK_FORMAT_R32G32B32_UINT,
433 		VK_FORMAT_R32G32B32_SINT,
434 		VK_FORMAT_R32G32B32_SFLOAT,
435 		VK_FORMAT_R32G32B32A32_UINT,
436 		VK_FORMAT_R32G32B32A32_SINT,
437 		VK_FORMAT_R32G32B32A32_SFLOAT,
438 		VK_FORMAT_R64_UINT,
439 		VK_FORMAT_R64_SINT,
440 		VK_FORMAT_R64_SFLOAT,
441 		VK_FORMAT_R64G64_UINT,
442 		VK_FORMAT_R64G64_SINT,
443 		VK_FORMAT_R64G64_SFLOAT,
444 		VK_FORMAT_R64G64B64_UINT,
445 		VK_FORMAT_R64G64B64_SINT,
446 		VK_FORMAT_R64G64B64_SFLOAT,
447 		VK_FORMAT_R64G64B64A64_UINT,
448 		VK_FORMAT_R64G64B64A64_SINT,
449 		VK_FORMAT_R64G64B64A64_SFLOAT,
450 	};
451 
452 	for (int classIdx = 0; classIdx < DE_LENGTH_OF_ARRAY(imageClass); ++classIdx)
453 	{
454 		const auto& imgClass = imageClass[classIdx];
455 		de::MovePtr<tcu::TestCaseGroup> classGroup (new tcu::TestCaseGroup(testCtx, imgClass.name));
456 
457 		for (int extentIdx = 0; extentIdx < DE_LENGTH_OF_ARRAY(extents); ++extentIdx)
458 		{
459 			const auto &extent = extents[extentIdx];
460 			de::MovePtr<tcu::TestCaseGroup> mipGroup (new tcu::TestCaseGroup(testCtx, extent.name));
461 
462 			for (int formatIdx = 0; formatIdx < DE_LENGTH_OF_ARRAY(testFormats); ++formatIdx)
463 			{
464 				static const auto	prefixLen	= std::string("VK_FORMAT_").size();
465 				const auto			format		= testFormats[formatIdx];
466 				const auto			fmtName		= std::string(getFormatName(format));
467 				const auto			name		= de::toLower(fmtName.substr(prefixLen)); // Remove VK_FORMAT_ prefix.
468 
469 				TransferQueueCase::TestParams params;
470 				params.imageFormat	= format;
471 				params.imageType	= imgClass.type;
472 				params.dimensions	= {extent.extent.width, extent.extent.height, extent.extent.depth};
473 
474 				mipGroup->addChild(new TransferQueueCase(testCtx, name,params));
475 			}
476 
477 			classGroup->addChild(mipGroup.release());
478 		}
479 
480 		layoutTestGroup->addChild(classGroup.release());
481 	}
482 
483 	return layoutTestGroup.release();
484 }
485 
486 } // namespace image
487 } // namespace vkt
488