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