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, ©Region);
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, ©Region);
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