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