xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/modifiers/vktModifiersTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2020 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
21  * \brief Modifiers tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktModifiersTests.hpp"
25 #include "vktTestCase.hpp"
26 #include "vktTestGroupUtil.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktExternalMemoryUtil.hpp"
29 #include "vktImageTestsUtil.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vkBufferWithMemory.hpp"
32 #include "vkBarrierUtil.hpp"
33 #include "vkCmdUtil.hpp"
34 #include "vkObjUtil.hpp"
35 #include "vkImageUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "tcuTestLog.hpp"
38 #include "tcuTexture.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "tcuImageIO.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuMaybe.hpp"
43 #include "deUniquePtr.hpp"
44 #include "deStringUtil.hpp"
45 
46 #include <string>
47 #include <vector>
48 #include <algorithm>
49 #include <iterator>
50 
51 namespace vkt
52 {
53 namespace modifiers
54 {
55 namespace
56 {
57 using namespace vk;
58 using tcu::TestLog;
59 using tcu::UVec2;
60 
61 struct ExplicitModifier
62 {
63     uint64_t modifier;
64     uint32_t modifierPlaneCount;
65     VkSubresourceLayout *pPlaneLayouts;
66 };
67 
checkModifiersSupported(Context & context,VkFormat format)68 void checkModifiersSupported(Context &context, VkFormat format)
69 {
70     if (!context.isDeviceFunctionalitySupported("VK_EXT_image_drm_format_modifier"))
71         TCU_THROW(NotSupportedError, "VK_EXT_image_drm_format_modifier is not supported");
72 
73     if (!context.isInstanceFunctionalitySupported("VK_KHR_get_physical_device_properties2"))
74         TCU_THROW(NotSupportedError, "VK_KHR_get_physical_device_properties2 not supported");
75 
76     if (!context.isDeviceFunctionalitySupported("VK_KHR_bind_memory2"))
77         TCU_THROW(NotSupportedError, "VK_KHR_bind_memory2 not supported");
78 
79     if (!context.isDeviceFunctionalitySupported("VK_KHR_image_format_list"))
80         TCU_THROW(NotSupportedError, "VK_KHR_image_format_list not supported");
81 
82 #ifndef CTS_USES_VULKANSC
83     if (format == VK_FORMAT_A8_UNORM_KHR || format == VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR)
84         context.requireDeviceFunctionality("VK_KHR_maintenance5");
85 #endif // CTS_USES_VULKANSC
86 }
87 
checkModifiersList2Supported(Context & context,VkFormat fmt)88 void checkModifiersList2Supported(Context &context, VkFormat fmt)
89 {
90     checkModifiersSupported(context, fmt);
91 
92     if (!context.isDeviceFunctionalitySupported("VK_KHR_format_feature_flags2"))
93         TCU_THROW(NotSupportedError, "VK_KHR_format_feature_flags2 not supported");
94 }
95 
getFormatCaseName(VkFormat format)96 std::string getFormatCaseName(VkFormat format)
97 {
98     return de::toLower(de::toString(getFormatStr(format)).substr(10));
99 }
100 
101 template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
getDrmFormatModifiers(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkFormat format)102 std::vector<ModifierProps> getDrmFormatModifiers(const InstanceInterface &vki, VkPhysicalDevice physicalDevice,
103                                                  VkFormat format)
104 {
105     ModifierList modifierProperties;
106     deMemset(&modifierProperties, 0, sizeof(modifierProperties));
107 
108     modifierProperties.sType = modifierListSType;
109     VkFormatProperties2 formatProperties;
110     deMemset(&formatProperties, 0, sizeof(formatProperties));
111 
112     std::vector<ModifierProps> drmFormatModifiers;
113     formatProperties.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
114     formatProperties.pNext = &modifierProperties;
115 
116     vki.getPhysicalDeviceFormatProperties2(physicalDevice, format, &formatProperties);
117 
118     drmFormatModifiers.resize(modifierProperties.drmFormatModifierCount);
119     modifierProperties.pDrmFormatModifierProperties = drmFormatModifiers.data();
120 
121     vki.getPhysicalDeviceFormatProperties2(physicalDevice, format, &formatProperties);
122 
123     return drmFormatModifiers;
124 }
125 
126 // Returns true if the image with the given parameters and modifiers supports the given handle type.
verifyHandleTypeForFormatModifier(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const VkFormat format,const VkImageType imageType,const VkImageUsageFlags imageUsages,const VkExternalMemoryHandleTypeFlags handleType,const uint64_t drmFormatModifier)127 bool verifyHandleTypeForFormatModifier(const InstanceInterface &vki, VkPhysicalDevice physicalDevice,
128                                        const VkFormat format, const VkImageType imageType,
129                                        const VkImageUsageFlags imageUsages,
130                                        const VkExternalMemoryHandleTypeFlags handleType,
131                                        const uint64_t drmFormatModifier)
132 {
133     const VkPhysicalDeviceImageDrmFormatModifierInfoEXT imageFormatModifierInfo = {
134         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
135         DE_NULL,
136         drmFormatModifier,
137         VK_SHARING_MODE_EXCLUSIVE,
138         0,
139         DE_NULL,
140     };
141 
142     const VkPhysicalDeviceExternalImageFormatInfo externalImageFormatInfo = {
143         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
144         &imageFormatModifierInfo,
145         (VkExternalMemoryHandleTypeFlagBits)handleType,
146     };
147 
148     const VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {
149         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
150         &externalImageFormatInfo,
151         format,
152         imageType,
153         VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
154         imageUsages,
155         0,
156     };
157 
158     VkExternalImageFormatProperties externalImageProperties = initVulkanStructure();
159     VkImageFormatProperties2 imageProperties                = initVulkanStructure(&externalImageProperties);
160 
161     if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &imageFormatInfo, &imageProperties) ==
162         VK_ERROR_FORMAT_NOT_SUPPORTED)
163         return false;
164 
165     vk::VkExternalMemoryFeatureFlags required_bits =
166         VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
167     if ((externalImageProperties.externalMemoryProperties.compatibleHandleTypes & handleType) != handleType ||
168         !((externalImageProperties.externalMemoryProperties.externalMemoryFeatures & required_bits) == required_bits))
169         return false;
170 
171     return true;
172 }
173 
174 template <typename FlagsType>
featuresCompatible(FlagsType modifierFeatures,VkFormatFeatureFlags testFeatures)175 static bool featuresCompatible(FlagsType modifierFeatures, VkFormatFeatureFlags testFeatures)
176 {
177     // All the format feature flags alias with their equivalents in the lower
178     // 32 bits of VkFormatFeatureFlags2KHR, so as long as we're casting "up",
179     // this should always be safe
180     DE_STATIC_ASSERT(sizeof(modifierFeatures) >= sizeof(testFeatures));
181     return ((modifierFeatures & static_cast<FlagsType>(testFeatures)) == static_cast<FlagsType>(testFeatures));
182 }
183 
184 template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
getExportImportCompatibleModifiers(Context & context,VkFormat format)185 std::vector<ModifierProps> getExportImportCompatibleModifiers(Context &context, VkFormat format)
186 {
187     const auto &vki = context.getInstanceInterface();
188     const auto drmFormatModifiers =
189         getDrmFormatModifiers<ModifierList, ModifierProps, modifierListSType>(vki, context.getPhysicalDevice(), format);
190     std::vector<ModifierProps> compatibleModifiers;
191 
192     if (drmFormatModifiers.empty())
193         return compatibleModifiers;
194 
195     const VkFormatFeatureFlags testFeatures = (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT |
196                                                VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT);
197 
198     for (const auto &modifierProps : drmFormatModifiers)
199     {
200         if (modifierProps.drmFormatModifierTilingFeatures == 0)
201             TCU_FAIL(de::toString(format) + " does not support any DRM modifier tiling features");
202 
203         if (!featuresCompatible(modifierProps.drmFormatModifierTilingFeatures, testFeatures))
204             continue;
205 
206         const auto &modifier = modifierProps.drmFormatModifier;
207         const auto supported =
208             verifyHandleTypeForFormatModifier(vki, context.getPhysicalDevice(), format, VK_IMAGE_TYPE_2D,
209                                               (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
210                                               VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, modifier);
211 
212         if (!supported)
213             continue;
214 
215         compatibleModifiers.push_back(modifierProps);
216     }
217 
218     return compatibleModifiers;
219 }
220 
221 template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
checkExportImportExtensions(Context & context,VkFormat format)222 void checkExportImportExtensions(Context &context, VkFormat format)
223 {
224     // tcuTexture.cpp getChannelSize, that is used by intThresholdCompare does not support the following formats.
225     // TODO: Add tcuTexture.cpp support for the following formats.
226     const VkFormat skippedFormats[] = {
227         VK_FORMAT_B10G11R11_UFLOAT_PACK32,    VK_FORMAT_A2R10G10B10_UNORM_PACK32,   VK_FORMAT_A2R10G10B10_SNORM_PACK32,
228         VK_FORMAT_A2R10G10B10_USCALED_PACK32, VK_FORMAT_A2R10G10B10_SSCALED_PACK32, VK_FORMAT_A2R10G10B10_UINT_PACK32,
229         VK_FORMAT_A2R10G10B10_SINT_PACK32,    VK_FORMAT_A2B10G10R10_UNORM_PACK32,   VK_FORMAT_A2B10G10R10_SNORM_PACK32,
230         VK_FORMAT_A2B10G10R10_USCALED_PACK32, VK_FORMAT_A2B10G10R10_SSCALED_PACK32, VK_FORMAT_A2B10G10R10_UINT_PACK32,
231         VK_FORMAT_A2B10G10R10_SINT_PACK32,    VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
232     };
233 
234     if (std::find(std::begin(skippedFormats), std::end(skippedFormats), format) != std::end(skippedFormats))
235         TCU_THROW(NotSupportedError, de::toString(format) + " can't be checked for correctness");
236 
237     if (!context.isDeviceFunctionalitySupported("VK_KHR_external_memory_fd"))
238         TCU_THROW(NotSupportedError, "VK_KHR_external_memory_fd not supported");
239 
240     if (modifierListSType == VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT)
241         checkModifiersSupported(context, format);
242     else
243         checkModifiersList2Supported(context, format);
244 
245     const auto compatibleModifiers =
246         getExportImportCompatibleModifiers<ModifierList, ModifierProps, modifierListSType>(context, format);
247     if (compatibleModifiers.empty())
248         TCU_THROW(NotSupportedError,
249                   "Could not find a format modifier supporting required transfer features for " + de::toString(format));
250 }
251 
isModifierCompatibleWithImageProperties(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const VkFormat * formats,const uint32_t nFormats,const VkImageType imageType,const VkImageUsageFlags imageUsages,const VkExternalMemoryHandleTypeFlags handleType,const uint64_t drmFormatModifier,VkImageFormatProperties2 & imageProperties)252 bool isModifierCompatibleWithImageProperties(const InstanceInterface &vki, VkPhysicalDevice physicalDevice,
253                                              const VkFormat *formats, const uint32_t nFormats,
254                                              const VkImageType imageType, const VkImageUsageFlags imageUsages,
255                                              const VkExternalMemoryHandleTypeFlags handleType,
256                                              const uint64_t drmFormatModifier,
257                                              VkImageFormatProperties2 &imageProperties)
258 {
259     const VkPhysicalDeviceImageDrmFormatModifierInfoEXT imageFormatModifierInfo = {
260         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
261         DE_NULL,
262         drmFormatModifier,
263         VK_SHARING_MODE_EXCLUSIVE,
264         0,
265         DE_NULL,
266     };
267 
268     const VkPhysicalDeviceExternalImageFormatInfo externalImageFormatInfo = {
269         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
270         &imageFormatModifierInfo,
271         (VkExternalMemoryHandleTypeFlagBits)handleType,
272     };
273 
274     const VkImageFormatListCreateInfo imageFormatListInfo = {
275         VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
276         &externalImageFormatInfo,
277         nFormats,
278         formats,
279     };
280 
281     const VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {
282         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
283         &imageFormatListInfo,
284         formats[0],
285         imageType,
286         VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
287         imageUsages,
288         0,
289     };
290 
291     VkExternalImageFormatProperties externalImageProperties = initVulkanStructure();
292     imageProperties.sType                                   = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
293     imageProperties.pNext                                   = &externalImageProperties;
294 
295     if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &imageFormatInfo, &imageProperties) ==
296         VK_ERROR_FORMAT_NOT_SUPPORTED)
297         return false;
298 
299     if ((externalImageProperties.externalMemoryProperties.compatibleHandleTypes & handleType) != handleType)
300         return false;
301 
302     return true;
303 }
304 
305 template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
listModifiersCase(Context & context,VkFormat format)306 tcu::TestStatus listModifiersCase(Context &context, VkFormat format)
307 {
308     TestLog &log                 = context.getTestContext().getLog();
309     const InstanceInterface &vki = context.getInstanceInterface();
310     const auto drmFormatModifiers =
311         getDrmFormatModifiers<ModifierList, ModifierProps, modifierListSType>(vki, context.getPhysicalDevice(), format);
312     bool noneCompatible = true;
313 
314     if (drmFormatModifiers.empty())
315         TCU_THROW(NotSupportedError, de::toString(format) + " does not support any DRM modifiers");
316 
317     for (uint32_t m = 0; m < drmFormatModifiers.size(); m++)
318     {
319         VkImageFormatProperties2 imageProperties{};
320         bool isCompatible = isModifierCompatibleWithImageProperties(
321             vki, context.getPhysicalDevice(), &format, 1u, VK_IMAGE_TYPE_2D,
322             (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
323             VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, drmFormatModifiers[m].drmFormatModifier, imageProperties);
324 
325         if (drmFormatModifiers[m].drmFormatModifierTilingFeatures == 0)
326             TCU_FAIL(de::toString(format) + " does not support any DRM modifier tiling features");
327 
328         if (!isCompatible)
329             continue;
330         noneCompatible = false;
331 
332         TCU_CHECK(imageProperties.imageFormatProperties.maxExtent.width >= 1 &&
333                   imageProperties.imageFormatProperties.maxExtent.height >= 1);
334         TCU_CHECK(imageProperties.imageFormatProperties.maxArrayLayers >= 1);
335 
336         log << TestLog::Message << "format modifier " << m << ":\n"
337             << drmFormatModifiers[m] << "\n"
338             << imageProperties << TestLog::EndMessage;
339     }
340 
341     if (noneCompatible)
342         TCU_THROW(NotSupportedError,
343                   de::toString(format) + " does not support any DRM modifiers for the requested image features");
344 
345     return tcu::TestStatus::pass("OK");
346 }
347 
createImageNoModifiers(const DeviceInterface & vkd,const VkDevice device,const VkImageUsageFlags imageUsages,const VkFormat format,const UVec2 & size)348 Move<VkImage> createImageNoModifiers(const DeviceInterface &vkd, const VkDevice device,
349                                      const VkImageUsageFlags imageUsages, const VkFormat format, const UVec2 &size)
350 {
351     const VkImageCreateInfo createInfo = {
352         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
353         DE_NULL,
354         0,
355         VK_IMAGE_TYPE_2D,
356         format,
357         makeExtent3D(size.x(), size.y(), 1u),
358         1u, // mipLevels
359         1u, // arrayLayers
360         VK_SAMPLE_COUNT_1_BIT,
361         VK_IMAGE_TILING_OPTIMAL,
362         imageUsages,
363         VK_SHARING_MODE_EXCLUSIVE,
364         0u,
365         (const uint32_t *)DE_NULL,
366         VK_IMAGE_LAYOUT_PREINITIALIZED,
367     };
368 
369     return createImage(vkd, device, &createInfo);
370 }
371 
createImageWithDrmFormatExplicitModifier(const DeviceInterface & vkd,const VkDevice device,const VkImageType imageType,const VkImageUsageFlags imageUsages,const VkExternalMemoryHandleTypeFlags externalMemoryHandleTypeFlags,const std::vector<VkFormat> & formats,const UVec2 & size,const ExplicitModifier drmFormatModifier)372 Move<VkImage> createImageWithDrmFormatExplicitModifier(
373     const DeviceInterface &vkd, const VkDevice device, const VkImageType imageType, const VkImageUsageFlags imageUsages,
374     const VkExternalMemoryHandleTypeFlags externalMemoryHandleTypeFlags, const std::vector<VkFormat> &formats,
375     const UVec2 &size, const ExplicitModifier drmFormatModifier)
376 {
377     const VkImageDrmFormatModifierExplicitCreateInfoEXT modifierExplicitCreateInfo = {
378         VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
379         DE_NULL,
380         drmFormatModifier.modifier,
381         drmFormatModifier.modifierPlaneCount,
382         drmFormatModifier.pPlaneLayouts,
383     };
384 
385     const VkExternalMemoryImageCreateInfo externalMemoryCreateInfo = {
386         VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
387         &modifierExplicitCreateInfo,
388         externalMemoryHandleTypeFlags,
389     };
390 
391     const void *pNext = &externalMemoryCreateInfo;
392     if (!externalMemoryHandleTypeFlags)
393     {
394         pNext = &modifierExplicitCreateInfo;
395     }
396 
397     const VkImageFormatListCreateInfo imageFormatListInfo = {
398         VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
399         pNext,
400         de::sizeU32(formats),
401         de::dataOrNull(formats),
402     };
403 
404     const VkImageCreateInfo createInfo = {
405         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
406         &imageFormatListInfo,
407         0,
408         imageType,
409         formats.front(),
410         makeExtent3D(size.x(), size.y(), 1u),
411         1u, // mipLevels
412         1u, // arrayLayers
413         VK_SAMPLE_COUNT_1_BIT,
414         VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
415         imageUsages,
416         VK_SHARING_MODE_EXCLUSIVE,
417         0u,
418         nullptr,
419         VK_IMAGE_LAYOUT_UNDEFINED,
420     };
421 
422     return createImage(vkd, device, &createInfo);
423 }
424 
createImageWithDrmFormatModifiers(const DeviceInterface & vkd,const VkDevice device,const VkImageType imageType,const VkImageUsageFlags imageUsages,const VkExternalMemoryHandleTypeFlags externalMemoryHandleTypeFlags,const std::vector<VkFormat> & formats,const UVec2 & size,const std::vector<uint64_t> & drmFormatModifiers)425 Move<VkImage> createImageWithDrmFormatModifiers(const DeviceInterface &vkd, const VkDevice device,
426                                                 const VkImageType imageType, const VkImageUsageFlags imageUsages,
427                                                 const VkExternalMemoryHandleTypeFlags externalMemoryHandleTypeFlags,
428                                                 const std::vector<VkFormat> &formats, const UVec2 &size,
429                                                 const std::vector<uint64_t> &drmFormatModifiers)
430 {
431     const VkImageDrmFormatModifierListCreateInfoEXT modifierListCreateInfo = {
432         VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT,
433         DE_NULL,
434         (uint32_t)drmFormatModifiers.size(),
435         drmFormatModifiers.data(),
436     };
437 
438     const VkExternalMemoryImageCreateInfo externalMemoryCreateInfo = {
439         VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
440         &modifierListCreateInfo,
441         externalMemoryHandleTypeFlags,
442     };
443 
444     const void *pNext = &externalMemoryCreateInfo;
445     if (!externalMemoryHandleTypeFlags)
446     {
447         pNext = &modifierListCreateInfo;
448     }
449 
450     const VkImageFormatListCreateInfo imageFormatListInfo = {
451         VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
452         pNext,
453         static_cast<uint32_t>(formats.size()),
454         formats.data(),
455     };
456 
457     const VkImageCreateInfo createInfo = {
458         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
459         &imageFormatListInfo,
460         0,
461         imageType,
462         formats.front(),
463         makeExtent3D(size.x(), size.y(), 1u),
464         1u, // mipLevels
465         1u, // arrayLayers
466         VK_SAMPLE_COUNT_1_BIT,
467         VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
468         imageUsages,
469         VK_SHARING_MODE_EXCLUSIVE,
470         0u,
471         (const uint32_t *)DE_NULL,
472         VK_IMAGE_LAYOUT_UNDEFINED,
473     };
474 
475     return createImage(vkd, device, &createInfo);
476 }
477 
478 template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
createImageListModifiersCase(Context & context,const VkFormat format)479 tcu::TestStatus createImageListModifiersCase(Context &context, const VkFormat format)
480 {
481     const InstanceInterface &vki = context.getInstanceInterface();
482     const DeviceInterface &vkd   = context.getDeviceInterface();
483     const VkDevice device        = context.getDevice();
484     const auto drmFormatModifiers =
485         getDrmFormatModifiers<ModifierList, ModifierProps, modifierListSType>(vki, context.getPhysicalDevice(), format);
486 
487     if (drmFormatModifiers.empty())
488         TCU_THROW(NotSupportedError, de::toString(format) + " does not support any DRM modifiers");
489 
490     // Get the list of modifiers supported for some specific image parameters.
491     std::vector<uint64_t> modifiers;
492 
493     for (const auto &modProps : drmFormatModifiers)
494     {
495         VkImageFormatProperties2 imgFormatProperties = initVulkanStructure();
496         const auto isCompatible                      = isModifierCompatibleWithImageProperties(
497             vki, context.getPhysicalDevice(), &format, 1u, VK_IMAGE_TYPE_2D,
498             (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
499             VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, modProps.drmFormatModifier, imgFormatProperties);
500         if (isCompatible)
501             modifiers.push_back(modProps.drmFormatModifier);
502         if (modProps.drmFormatModifierTilingFeatures == 0)
503             TCU_FAIL(de::toString(format) + " does not support any DRM modifier tiling features");
504     }
505 
506     if (modifiers.empty())
507         TCU_THROW(NotSupportedError,
508                   de::toString(format) + " does not support any DRM modifiers for the requested image features");
509 
510     // Test with lists of compatible modifiers of increasing lengths.
511     for (size_t len = 1u; len <= modifiers.size(); ++len)
512     {
513         std::vector<uint64_t> creationModifiers;
514         creationModifiers.reserve(len);
515         std::copy_n(begin(modifiers), len, std::back_inserter(creationModifiers));
516 
517         VkImageDrmFormatModifierPropertiesEXT properties = initVulkanStructure();
518 
519         {
520             std::vector<VkFormat> formats(1u, format);
521             const auto image = createImageWithDrmFormatModifiers(
522                 vkd, device, VK_IMAGE_TYPE_2D, (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT), 0,
523                 formats, UVec2(64, 64), creationModifiers);
524 
525             VK_CHECK(vkd.getImageDrmFormatModifierPropertiesEXT(device, *image, &properties));
526         }
527 
528         if (!de::contains(begin(creationModifiers), end(creationModifiers), properties.drmFormatModifier))
529             return tcu::TestStatus::fail("Image created with modifier not specified in the create list");
530     }
531 
532     return tcu::TestStatus::pass("OK");
533 }
534 
535 template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
createImageModifierExplicitCase(Context & context,const VkFormat format)536 tcu::TestStatus createImageModifierExplicitCase(Context &context, const VkFormat format)
537 {
538     const InstanceInterface &vki = context.getInstanceInterface();
539     const DeviceInterface &vkd   = context.getDeviceInterface();
540     const VkDevice device        = context.getDevice();
541     const auto drmFormatModifiers =
542         getDrmFormatModifiers<ModifierList, ModifierProps, modifierListSType>(vki, context.getPhysicalDevice(), format);
543 
544     if (drmFormatModifiers.empty())
545         TCU_THROW(NotSupportedError, de::toString(format) + " does not support any DRM modifiers");
546 
547     // Get the list of modifiers supported for some specific image parameters.
548     std::vector<ExplicitModifier> modifiers;
549 
550     for (const auto &modProps : drmFormatModifiers)
551     {
552         if (modProps.drmFormatModifierTilingFeatures == 0)
553             TCU_FAIL(de::toString(format) + " does not support any DRM modifier tiling features");
554 
555         VkImageFormatProperties2 imgFormatProperties = initVulkanStructure();
556         const auto isCompatible                      = isModifierCompatibleWithImageProperties(
557             vki, context.getPhysicalDevice(), &format, 1u, VK_IMAGE_TYPE_2D,
558             (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
559             VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, modProps.drmFormatModifier, imgFormatProperties);
560         if (isCompatible)
561         {
562             const ExplicitModifier modifier = {
563                 modProps.drmFormatModifier,           // modifier
564                 modProps.drmFormatModifierPlaneCount, // modifierPlaneCount
565                 DE_NULL,                              // pPlaneLayouts
566             };
567 
568             modifiers.push_back(modifier);
569         }
570     }
571 
572     if (modifiers.empty())
573         TCU_THROW(NotSupportedError,
574                   de::toString(format) + " does not support any DRM modifiers for the requested image features");
575 
576     for (auto &modifier : modifiers)
577     {
578         std::vector<VkFormat> formats(1u, format);
579         std::vector<uint64_t> creationModifier(1u, modifier.modifier);
580 
581         VkImageDrmFormatModifierPropertiesEXT properties = initVulkanStructure();
582 
583         const auto imageRef = createImageWithDrmFormatModifiers(
584             vkd, device, VK_IMAGE_TYPE_2D, (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT), 0,
585             formats, UVec2(64, 64), creationModifier);
586 
587         std::vector<VkSubresourceLayout> planeLayouts;
588         for (uint32_t i = 0; i < modifier.modifierPlaneCount; i++)
589         {
590             VkImageSubresource imageSubresource;
591             VkSubresourceLayout subresourceLayout;
592 
593             deMemset(&imageSubresource, 0, sizeof(imageSubresource));
594 
595             imageSubresource.aspectMask = VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT << i;
596 
597             vkd.getImageSubresourceLayout(device, *imageRef, &imageSubresource, &subresourceLayout);
598 
599             // From the spec:
600             //   VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-size-02267
601             //   For each element of pPlaneLayouts, size must be 0
602             //
603             //   VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-arrayPitch-02268
604             //   For each element of pPlaneLayouts, arrayPitch must be 0 if VkImageCreateInfo::arrayLayers is 1
605             //
606             //   VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-depthPitch-02269
607             //   For each element of pPlaneLayouts, depthPitch must be 0 if VkImageCreateInfo::extent.depth is 1
608             subresourceLayout.size       = 0;
609             subresourceLayout.arrayPitch = 0;
610             subresourceLayout.depthPitch = 0;
611 
612             planeLayouts.push_back(subresourceLayout);
613         }
614         modifier.pPlaneLayouts = planeLayouts.data();
615 
616         const auto image = createImageWithDrmFormatExplicitModifier(
617             vkd, device, VK_IMAGE_TYPE_2D, (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT), 0,
618             formats, UVec2(64, 64), modifier);
619         VK_CHECK(vkd.getImageDrmFormatModifierPropertiesEXT(device, *image, &properties));
620 
621         if (modifier.modifier != properties.drmFormatModifier)
622             return tcu::TestStatus::fail("The created image's modifier with an explicit modifier not matched");
623     }
624 
625     return tcu::TestStatus::pass("OK");
626 }
627 
chooseMemoryType(uint32_t bits)628 uint32_t chooseMemoryType(uint32_t bits)
629 {
630     DE_ASSERT(bits != 0);
631 
632     for (uint32_t memoryTypeIndex = 0; (1u << memoryTypeIndex) <= bits; memoryTypeIndex++)
633     {
634         if ((bits & (1u << memoryTypeIndex)) != 0)
635             return memoryTypeIndex;
636     }
637 
638     DE_FATAL("No supported memory types");
639     return -1;
640 }
641 
642 template <typename ModifierProps>
exportImportMemoryExplicitModifiersCase(Context & context,const VkFormat format,const ModifierProps & modifier)643 bool exportImportMemoryExplicitModifiersCase(Context &context, const VkFormat format, const ModifierProps &modifier)
644 {
645     const InstanceInterface &vki = context.getInstanceInterface();
646     const DeviceInterface &vkd   = context.getDeviceInterface();
647     const VkDevice device        = context.getDevice();
648 
649     const auto supported =
650         verifyHandleTypeForFormatModifier(vki, context.getPhysicalDevice(), format, VK_IMAGE_TYPE_2D,
651                                           (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
652                                           VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, modifier.drmFormatModifier);
653 
654     if (!supported)
655         TCU_FAIL("Modifier " + de::toString(modifier.drmFormatModifier) + " for format " + de::toString(format) +
656                  " expected to be compatible");
657 
658     std::vector<uint64_t> modifiers;
659     modifiers.push_back(modifier.drmFormatModifier);
660 
661     const UVec2 imageSize(64, 64);
662     const tcu::TextureFormat referenceTextureFormat(mapVkFormat(format));
663     uint32_t bufferSize = 1 << 16;
664     const de::UniquePtr<BufferWithMemory> inputBuffer(new BufferWithMemory(
665         vkd, device, context.getDefaultAllocator(), makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
666         MemoryRequirement::HostVisible));
667     tcu::PixelBufferAccess referenceImage(referenceTextureFormat, imageSize.x(), imageSize.y(), 1,
668                                           inputBuffer->getAllocation().getHostPtr());
669     const de::UniquePtr<BufferWithMemory> outputBuffer(new BufferWithMemory(
670         vkd, device, context.getDefaultAllocator(), makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT),
671         MemoryRequirement::HostVisible));
672     Unique<VkCommandPool> cmdPool(createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
673                                                     context.getUniversalQueueFamilyIndex(), DE_NULL));
674     vkt::ExternalMemoryUtil::NativeHandle inputImageMemFd;
675 
676     const tcu::TextureFormatInfo formatInfo(tcu::getTextureFormatInfo(referenceTextureFormat));
677     tcu::fillWithComponentGradients(referenceImage, formatInfo.valueMin, formatInfo.valueMax);
678 
679     flushAlloc(vkd, device, inputBuffer->getAllocation());
680 
681     Move<VkImage> srcImage(createImageNoModifiers(
682         vkd, device, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, format, UVec2(64, 64)));
683     VkMemoryRequirements srcImageMemoryReq        = getImageMemoryRequirements(vkd, device, *srcImage);
684     const vk::VkMemoryAllocateInfo allocationInfo = {
685         vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
686         DE_NULL,
687         srcImageMemoryReq.size,
688         chooseMemoryType(srcImageMemoryReq.memoryTypeBits),
689     };
690     vk::Move<vk::VkDeviceMemory> srcMemory(vk::allocateMemory(vkd, device, &allocationInfo));
691     VK_CHECK(vkd.bindImageMemory(device, *srcImage, *srcMemory, 0));
692 
693     Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
694     const VkCommandBufferBeginInfo cmdBufferBeginInfo = {
695         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
696         DE_NULL,
697         VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
698         (const VkCommandBufferInheritanceInfo *)DE_NULL,
699     };
700 
701     VK_CHECK(vkd.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
702 
703     {
704         const VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT;
705         std::vector<VkBufferImageCopy> copies;
706 
707         copies.push_back(image::makeBufferImageCopy(makeExtent3D(imageSize.x(), imageSize.y(), 1u), 1u));
708         copyBufferToImage(vkd, *cmdBuffer, inputBuffer->get(), bufferSize, copies, aspect, 1, 1, *srcImage,
709                           VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
710     }
711 
712     Move<VkImage> dstImage(createImageWithDrmFormatModifiers(
713         vkd, device, VK_IMAGE_TYPE_2D, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
714         VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, {format}, UVec2(64, 64), modifiers));
715     VkMemoryRequirements dstImageMemoryReq = getImageMemoryRequirements(vkd, device, *dstImage);
716     vk::Move<vk::VkDeviceMemory> dstMemory(vkt::ExternalMemoryUtil::allocateExportableMemory(
717         vkd, device, dstImageMemoryReq.size, chooseMemoryType(dstImageMemoryReq.memoryTypeBits),
718         VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, *dstImage));
719 
720     VK_CHECK(vkd.bindImageMemory(device, *dstImage, *dstMemory, 0));
721     const VkImageMemoryBarrier srcImageBarrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
722                                                   DE_NULL,                                // const void* pNext;
723                                                   VK_ACCESS_TRANSFER_WRITE_BIT,         // VkAccessFlags srcAccessMask;
724                                                   VK_ACCESS_TRANSFER_WRITE_BIT,         // VkAccessFlags dstAccessMask;
725                                                   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
726                                                   VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
727                                                   VK_QUEUE_FAMILY_IGNORED,              // uint32_t srcQueueFamilyIndex;
728                                                   VK_QUEUE_FAMILY_IGNORED,              // uint32_t dstQueueFamilyIndex;
729                                                   *srcImage,                            // VkImage image;
730                                                   {
731                                                       // VkImageSubresourceRange subresourceRange;
732                                                       VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
733                                                       0u,                        // uint32_t baseMipLevel;
734                                                       1u,                        // uint32_t mipLevels;
735                                                       0u,                        // uint32_t baseArraySlice;
736                                                       1u                         // uint32_t arraySize;
737                                                   }};
738     const VkImageMemoryBarrier dstImageBarrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
739                                                   DE_NULL,                                // const void* pNext;
740                                                   VK_ACCESS_TRANSFER_WRITE_BIT,         // VkAccessFlags srcAccessMask;
741                                                   VK_ACCESS_TRANSFER_WRITE_BIT,         // VkAccessFlags dstAccessMask;
742                                                   VK_IMAGE_LAYOUT_UNDEFINED,            // VkImageLayout oldLayout;
743                                                   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
744                                                   VK_QUEUE_FAMILY_IGNORED,              // uint32_t srcQueueFamilyIndex;
745                                                   VK_QUEUE_FAMILY_IGNORED,              // uint32_t dstQueueFamilyIndex;
746                                                   *dstImage,                            // VkImage image;
747                                                   {
748                                                       // VkImageSubresourceRange subresourceRange;
749                                                       VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
750                                                       0u,                        // uint32_t baseMipLevel;
751                                                       1u,                        // uint32_t mipLevels;
752                                                       0u,                        // uint32_t baseArraySlice;
753                                                       1u                         // uint32_t arraySize;
754                                                   }};
755     vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
756                            (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
757                            (const VkBufferMemoryBarrier *)DE_NULL, 1, &srcImageBarrier);
758     vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
759                            (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
760                            (const VkBufferMemoryBarrier *)DE_NULL, 1, &dstImageBarrier);
761 
762     VkImageBlit imageBlit{
763         {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
764         {{0, 0, 0}, {64, 64, 1}},
765         {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
766         {{0, 0, 0}, {64, 64, 1}},
767     };
768     vkd.cmdBlitImage(*cmdBuffer, *srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dstImage,
769                      VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageBlit, VK_FILTER_NEAREST);
770 
771     const VkImageMemoryBarrier exportImageBarrier = {
772         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
773         DE_NULL,                                // const void* pNext;
774         VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
775         VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags srcAccessMask;
776         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout oldLayout;
777         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,   // VkImageLayout newLayout;
778         context.getUniversalQueueFamilyIndex(), // uint32_t dstQueueFamilyIndex;
779         VK_QUEUE_FAMILY_FOREIGN_EXT,            // uint32_t srcQueueFamilyIndex;
780         *dstImage,                              // VkImage image;
781         {
782             // VkImageSubresourceRange subresourceRange;
783             VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
784             0u,                        // uint32_t baseMipLevel;
785             1u,                        // uint32_t mipLevels;
786             0u,                        // uint32_t baseArraySlice;
787             1u                         // uint32_t arraySize;
788         }};
789 
790     vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
791                            (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
792                            (const VkBufferMemoryBarrier *)DE_NULL, 1, &exportImageBarrier);
793     VK_CHECK(vkd.endCommandBuffer(*cmdBuffer));
794     submitCommandsAndWait(vkd, device, context.getUniversalQueue(), *cmdBuffer);
795     VkImageDrmFormatModifierPropertiesEXT properties;
796     deMemset(&properties, 0, sizeof(properties));
797     properties.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT;
798     VK_CHECK(vkd.getImageDrmFormatModifierPropertiesEXT(device, *dstImage, &properties));
799     TCU_CHECK(properties.drmFormatModifier == modifiers.front());
800     inputImageMemFd =
801         vkt::ExternalMemoryUtil::getMemoryFd(vkd, device, *dstMemory, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT);
802 
803     ExplicitModifier explicitModifier = {
804         modifier.drmFormatModifier, modifier.drmFormatModifierPlaneCount,
805         DE_NULL, // pPlaneLayouts
806     };
807     std::vector<VkSubresourceLayout> planeLayouts;
808     for (uint32_t i = 0; i < modifier.drmFormatModifierPlaneCount; i++)
809     {
810         VkImageSubresource imageSubresource;
811         VkSubresourceLayout subresourceLayout;
812 
813         deMemset(&imageSubresource, 0, sizeof(imageSubresource));
814 
815         imageSubresource.aspectMask = VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT << i;
816 
817         vkd.getImageSubresourceLayout(device, *dstImage, &imageSubresource, &subresourceLayout);
818 
819         subresourceLayout.size       = 0;
820         subresourceLayout.arrayPitch = 0;
821         subresourceLayout.depthPitch = 0;
822 
823         planeLayouts.push_back(subresourceLayout);
824     }
825     explicitModifier.pPlaneLayouts = planeLayouts.data();
826 
827     Move<VkImage> importedSrcImage(createImageWithDrmFormatExplicitModifier(
828         vkd, device, VK_IMAGE_TYPE_2D, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
829         VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, {format}, UVec2(64, 64), explicitModifier));
830 
831     VkMemoryRequirements importedSrcImageMemoryReq = getImageMemoryRequirements(vkd, device, *importedSrcImage);
832 
833     Move<VkDeviceMemory> importedMemory(vkt::ExternalMemoryUtil::importDedicatedMemory(
834         vkd, device, *importedSrcImage, importedSrcImageMemoryReq, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, ~0u,
835         inputImageMemFd));
836     VK_CHECK(vkd.bindImageMemory(device, *importedSrcImage, *importedMemory, 0));
837 
838     Move<VkImage> outImage(createImageNoModifiers(
839         vkd, device, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, format, UVec2(64, 64)));
840     VkMemoryRequirements outImageMemoryReq           = getImageMemoryRequirements(vkd, device, *outImage);
841     const vk::VkMemoryAllocateInfo outAllocationInfo = {
842         vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
843         DE_NULL,
844         outImageMemoryReq.size,
845         chooseMemoryType(outImageMemoryReq.memoryTypeBits),
846     };
847     vk::Move<vk::VkDeviceMemory> outMemory(vk::allocateMemory(vkd, device, &outAllocationInfo));
848     VK_CHECK(vkd.bindImageMemory(device, *outImage, *outMemory, 0));
849 
850     Unique<VkCommandBuffer> cmdBuffer2(allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
851     VK_CHECK(vkd.beginCommandBuffer(*cmdBuffer2, &cmdBufferBeginInfo));
852 
853     const VkImageMemoryBarrier importedImageBarrier = {
854         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
855         DE_NULL,                                // const void* pNext;
856         VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags srcAccessMask;
857         VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
858         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout oldLayout;
859         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,   // VkImageLayout newLayout;
860         VK_QUEUE_FAMILY_FOREIGN_EXT,            // uint32_t srcQueueFamilyIndex;
861         context.getUniversalQueueFamilyIndex(), // uint32_t dstQueueFamilyIndex;
862         *importedSrcImage,                      // VkImage image;
863         {
864             // VkImageSubresourceRange subresourceRange;
865             VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
866             0u,                        // uint32_t baseMipLevel;
867             1u,                        // uint32_t mipLevels;
868             0u,                        // uint32_t baseArraySlice;
869             1u                         // uint32_t arraySize;
870         }};
871     const VkImageMemoryBarrier outImageBarrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
872                                                   DE_NULL,                                // const void* pNext;
873                                                   VK_ACCESS_TRANSFER_WRITE_BIT,         // VkAccessFlags srcAccessMask;
874                                                   VK_ACCESS_TRANSFER_WRITE_BIT,         // VkAccessFlags dstAccessMask;
875                                                   VK_IMAGE_LAYOUT_UNDEFINED,            // VkImageLayout oldLayout;
876                                                   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
877                                                   VK_QUEUE_FAMILY_IGNORED,              // uint32_t srcQueueFamilyIndex;
878                                                   VK_QUEUE_FAMILY_IGNORED,              // uint32_t dstQueueFamilyIndex;
879                                                   *outImage,                            // VkImage image;
880                                                   {
881                                                       // VkImageSubresourceRange subresourceRange;
882                                                       VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
883                                                       0u,                        // uint32_t baseMipLevel;
884                                                       1u,                        // uint32_t mipLevels;
885                                                       0u,                        // uint32_t baseArraySlice;
886                                                       1u                         // uint32_t arraySize;
887                                                   }};
888 
889     vkd.cmdPipelineBarrier(*cmdBuffer2, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
890                            (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
891                            (const VkBufferMemoryBarrier *)DE_NULL, 1, &importedImageBarrier);
892     vkd.cmdPipelineBarrier(*cmdBuffer2, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
893                            (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
894                            (const VkBufferMemoryBarrier *)DE_NULL, 1, &outImageBarrier);
895 
896     VkImageBlit imageBlit2{
897         {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
898         {{0, 0, 0}, {64, 64, 1}},
899         {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
900         {{0, 0, 0}, {64, 64, 1}},
901     };
902     vkd.cmdBlitImage(*cmdBuffer2, *importedSrcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *outImage,
903                      VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageBlit2, VK_FILTER_NEAREST);
904 
905     copyImageToBuffer(vkd, *cmdBuffer2, *outImage, outputBuffer->get(), tcu::IVec2(imageSize.x(), imageSize.y()),
906                       VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1);
907 
908     VK_CHECK(vkd.endCommandBuffer(*cmdBuffer2));
909 
910     submitCommandsAndWait(vkd, device, context.getUniversalQueue(), *cmdBuffer2);
911 
912     tcu::ConstPixelBufferAccess result(referenceTextureFormat, imageSize.x(), imageSize.y(), 1,
913                                        outputBuffer->getAllocation().getHostPtr());
914     const tcu::UVec4 threshold(0u);
915 
916     invalidateAlloc(vkd, device, outputBuffer->getAllocation());
917 
918     return tcu::intThresholdCompare(context.getTestContext().getLog(), "Compare", "Result comparison", referenceImage,
919                                     result, threshold, tcu::COMPARE_LOG_RESULT);
920 }
921 
922 template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
exportImportMemoryExplicitModifiersCase(Context & context,const VkFormat format)923 tcu::TestStatus exportImportMemoryExplicitModifiersCase(Context &context, const VkFormat format)
924 {
925     const auto compatibleModifiers =
926         getExportImportCompatibleModifiers<ModifierList, ModifierProps, modifierListSType>(context, format);
927 
928     if (compatibleModifiers.empty())
929         TCU_FAIL("Expected non-empty list of compatible modifiers for the given format");
930 
931     for (const auto &modifier : compatibleModifiers)
932     {
933         if (!exportImportMemoryExplicitModifiersCase(context, format, modifier))
934             return tcu::TestStatus::fail("Unexpected copy image result");
935     }
936 
937     return tcu::TestStatus::pass("OK");
938 }
939 
940 } // namespace
941 
createTests(tcu::TestContext & testCtx,const std::string & name)942 tcu::TestCaseGroup *createTests(tcu::TestContext &testCtx, const std::string &name)
943 {
944     de::MovePtr<tcu::TestCaseGroup> drmFormatModifiersGroup(new tcu::TestCaseGroup(testCtx, name.c_str()));
945     const VkFormat formats[] = {
946         VK_FORMAT_R4G4_UNORM_PACK8,
947         VK_FORMAT_R4G4B4A4_UNORM_PACK16,
948         VK_FORMAT_B4G4R4A4_UNORM_PACK16,
949         VK_FORMAT_R5G6B5_UNORM_PACK16,
950         VK_FORMAT_B5G6R5_UNORM_PACK16,
951         VK_FORMAT_R5G5B5A1_UNORM_PACK16,
952         VK_FORMAT_B5G5R5A1_UNORM_PACK16,
953         VK_FORMAT_A1R5G5B5_UNORM_PACK16,
954 #ifndef CTS_USES_VULKANSC
955         VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR,
956 #endif // CTS_USES_VULKANSC
957         VK_FORMAT_R8_UNORM,
958         VK_FORMAT_R8_SNORM,
959         VK_FORMAT_R8_USCALED,
960         VK_FORMAT_R8_SSCALED,
961         VK_FORMAT_R8_UINT,
962         VK_FORMAT_R8_SINT,
963         VK_FORMAT_R8_SRGB,
964 #ifndef CTS_USES_VULKANSC
965         VK_FORMAT_A8_UNORM_KHR,
966 #endif // CTS_USES_VULKANSC
967         VK_FORMAT_R8G8_UNORM,
968         VK_FORMAT_R8G8_SNORM,
969         VK_FORMAT_R8G8_USCALED,
970         VK_FORMAT_R8G8_SSCALED,
971         VK_FORMAT_R8G8_UINT,
972         VK_FORMAT_R8G8_SINT,
973         VK_FORMAT_R8G8_SRGB,
974         VK_FORMAT_R8G8B8_UNORM,
975         VK_FORMAT_R8G8B8_SNORM,
976         VK_FORMAT_R8G8B8_USCALED,
977         VK_FORMAT_R8G8B8_SSCALED,
978         VK_FORMAT_R8G8B8_UINT,
979         VK_FORMAT_R8G8B8_SINT,
980         VK_FORMAT_R8G8B8_SRGB,
981         VK_FORMAT_B8G8R8_UNORM,
982         VK_FORMAT_B8G8R8_SNORM,
983         VK_FORMAT_B8G8R8_USCALED,
984         VK_FORMAT_B8G8R8_SSCALED,
985         VK_FORMAT_B8G8R8_UINT,
986         VK_FORMAT_B8G8R8_SINT,
987         VK_FORMAT_B8G8R8_SRGB,
988         VK_FORMAT_R8G8B8A8_UNORM,
989         VK_FORMAT_R8G8B8A8_SNORM,
990         VK_FORMAT_R8G8B8A8_USCALED,
991         VK_FORMAT_R8G8B8A8_SSCALED,
992         VK_FORMAT_R8G8B8A8_UINT,
993         VK_FORMAT_R8G8B8A8_SINT,
994         VK_FORMAT_R8G8B8A8_SRGB,
995         VK_FORMAT_B8G8R8A8_UNORM,
996         VK_FORMAT_B8G8R8A8_SNORM,
997         VK_FORMAT_B8G8R8A8_USCALED,
998         VK_FORMAT_B8G8R8A8_SSCALED,
999         VK_FORMAT_B8G8R8A8_UINT,
1000         VK_FORMAT_B8G8R8A8_SINT,
1001         VK_FORMAT_B8G8R8A8_SRGB,
1002         VK_FORMAT_A8B8G8R8_UNORM_PACK32,
1003         VK_FORMAT_A8B8G8R8_SNORM_PACK32,
1004         VK_FORMAT_A8B8G8R8_USCALED_PACK32,
1005         VK_FORMAT_A8B8G8R8_SSCALED_PACK32,
1006         VK_FORMAT_A8B8G8R8_UINT_PACK32,
1007         VK_FORMAT_A8B8G8R8_SINT_PACK32,
1008         VK_FORMAT_A8B8G8R8_SRGB_PACK32,
1009         VK_FORMAT_A2R10G10B10_UNORM_PACK32,
1010         VK_FORMAT_A2R10G10B10_SNORM_PACK32,
1011         VK_FORMAT_A2R10G10B10_USCALED_PACK32,
1012         VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
1013         VK_FORMAT_A2R10G10B10_UINT_PACK32,
1014         VK_FORMAT_A2R10G10B10_SINT_PACK32,
1015         VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1016         VK_FORMAT_A2B10G10R10_SNORM_PACK32,
1017         VK_FORMAT_A2B10G10R10_USCALED_PACK32,
1018         VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
1019         VK_FORMAT_A2B10G10R10_UINT_PACK32,
1020         VK_FORMAT_A2B10G10R10_SINT_PACK32,
1021         VK_FORMAT_R16_UNORM,
1022         VK_FORMAT_R16_SNORM,
1023         VK_FORMAT_R16_USCALED,
1024         VK_FORMAT_R16_SSCALED,
1025         VK_FORMAT_R16_UINT,
1026         VK_FORMAT_R16_SINT,
1027         VK_FORMAT_R16_SFLOAT,
1028         VK_FORMAT_R16G16_UNORM,
1029         VK_FORMAT_R16G16_SNORM,
1030         VK_FORMAT_R16G16_USCALED,
1031         VK_FORMAT_R16G16_SSCALED,
1032         VK_FORMAT_R16G16_UINT,
1033         VK_FORMAT_R16G16_SINT,
1034         VK_FORMAT_R16G16_SFLOAT,
1035         VK_FORMAT_R16G16B16_UNORM,
1036         VK_FORMAT_R16G16B16_SNORM,
1037         VK_FORMAT_R16G16B16_USCALED,
1038         VK_FORMAT_R16G16B16_SSCALED,
1039         VK_FORMAT_R16G16B16_UINT,
1040         VK_FORMAT_R16G16B16_SINT,
1041         VK_FORMAT_R16G16B16_SFLOAT,
1042         VK_FORMAT_R16G16B16A16_UNORM,
1043         VK_FORMAT_R16G16B16A16_SNORM,
1044         VK_FORMAT_R16G16B16A16_USCALED,
1045         VK_FORMAT_R16G16B16A16_SSCALED,
1046         VK_FORMAT_R16G16B16A16_UINT,
1047         VK_FORMAT_R16G16B16A16_SINT,
1048         VK_FORMAT_R16G16B16A16_SFLOAT,
1049         VK_FORMAT_R32_UINT,
1050         VK_FORMAT_R32_SINT,
1051         VK_FORMAT_R32_SFLOAT,
1052         VK_FORMAT_R32G32_UINT,
1053         VK_FORMAT_R32G32_SINT,
1054         VK_FORMAT_R32G32_SFLOAT,
1055         VK_FORMAT_R32G32B32_UINT,
1056         VK_FORMAT_R32G32B32_SINT,
1057         VK_FORMAT_R32G32B32_SFLOAT,
1058         VK_FORMAT_R32G32B32A32_UINT,
1059         VK_FORMAT_R32G32B32A32_SINT,
1060         VK_FORMAT_R32G32B32A32_SFLOAT,
1061         VK_FORMAT_R64_UINT,
1062         VK_FORMAT_R64_SINT,
1063         VK_FORMAT_R64_SFLOAT,
1064         VK_FORMAT_R64G64_UINT,
1065         VK_FORMAT_R64G64_SINT,
1066         VK_FORMAT_R64G64_SFLOAT,
1067         VK_FORMAT_R64G64B64_UINT,
1068         VK_FORMAT_R64G64B64_SINT,
1069         VK_FORMAT_R64G64B64_SFLOAT,
1070         VK_FORMAT_R64G64B64A64_UINT,
1071         VK_FORMAT_R64G64B64A64_SINT,
1072         VK_FORMAT_R64G64B64A64_SFLOAT,
1073         VK_FORMAT_B10G11R11_UFLOAT_PACK32,
1074         VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
1075         VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,
1076         VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,
1077     };
1078 
1079     {
1080         // Check that listing supported modifiers is functional
1081         de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "list_modifiers"));
1082         // Check that listing supported modifiers is functional with VK_KHR_format_feature_flags2
1083         de::MovePtr<tcu::TestCaseGroup> group2(new tcu::TestCaseGroup(testCtx, "list_modifiers_fmt_features2"));
1084 
1085         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1086         {
1087             // Check that listing supported modifiers is functional
1088             addFunctionCase(group.get(), getFormatCaseName(formats[formatNdx]), checkModifiersSupported,
1089                             listModifiersCase<VkDrmFormatModifierPropertiesListEXT, VkDrmFormatModifierPropertiesEXT,
1090                                               VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT>,
1091                             formats[formatNdx]);
1092             // Check that listing supported modifiers is functional
1093             addFunctionCase(group2.get(), getFormatCaseName(formats[formatNdx]), checkModifiersList2Supported,
1094                             listModifiersCase<VkDrmFormatModifierPropertiesList2EXT, VkDrmFormatModifierProperties2EXT,
1095                                               VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT>,
1096                             formats[formatNdx]);
1097         }
1098 
1099         drmFormatModifiersGroup->addChild(group.release());
1100         drmFormatModifiersGroup->addChild(group2.release());
1101     }
1102 
1103     {
1104         de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "create_list_modifiers"));
1105         de::MovePtr<tcu::TestCaseGroup> group2(new tcu::TestCaseGroup(testCtx, "create_list_modifiers_fmt_features2"));
1106 
1107         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1108         {
1109             // Check that creating images with modifier list is functional
1110             addFunctionCase(
1111                 group.get(), getFormatCaseName(formats[formatNdx]), checkModifiersSupported,
1112                 createImageListModifiersCase<VkDrmFormatModifierPropertiesListEXT, VkDrmFormatModifierPropertiesEXT,
1113                                              VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT>,
1114                 formats[formatNdx]);
1115             // Check that creating images with modifier list is functional
1116             addFunctionCase(
1117                 group2.get(), getFormatCaseName(formats[formatNdx]), checkModifiersList2Supported,
1118                 createImageListModifiersCase<VkDrmFormatModifierPropertiesList2EXT, VkDrmFormatModifierProperties2EXT,
1119                                              VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT>,
1120                 formats[formatNdx]);
1121         }
1122 
1123         drmFormatModifiersGroup->addChild(group.release());
1124         drmFormatModifiersGroup->addChild(group2.release());
1125     }
1126 
1127     {
1128         de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "create_explicit_modifier"));
1129         de::MovePtr<tcu::TestCaseGroup> group2(
1130             new tcu::TestCaseGroup(testCtx, "create_explicit_modifier_fmt_features2"));
1131 
1132         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1133         {
1134             // Check that creating images with an explicit modifier is functional
1135             addFunctionCase(
1136                 group.get(), getFormatCaseName(formats[formatNdx]), checkModifiersSupported,
1137                 createImageModifierExplicitCase<VkDrmFormatModifierPropertiesListEXT, VkDrmFormatModifierPropertiesEXT,
1138                                                 VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT>,
1139                 formats[formatNdx]);
1140             // Check that creating images with an explicit modifier is functional
1141             addFunctionCase(
1142                 group2.get(), getFormatCaseName(formats[formatNdx]), checkModifiersList2Supported,
1143                 createImageModifierExplicitCase<VkDrmFormatModifierPropertiesList2EXT,
1144                                                 VkDrmFormatModifierProperties2EXT,
1145                                                 VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT>,
1146                 formats[formatNdx]);
1147         }
1148 
1149         drmFormatModifiersGroup->addChild(group.release());
1150         drmFormatModifiersGroup->addChild(group2.release());
1151     }
1152 
1153     {
1154         de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "export_import"));
1155         de::MovePtr<tcu::TestCaseGroup> group2(new tcu::TestCaseGroup(testCtx, "export_import_fmt_features2"));
1156 
1157         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1158         {
1159             // Test exporting/importing images with modifiers
1160             addFunctionCase(
1161                 group.get(), getFormatCaseName(formats[formatNdx]),
1162                 checkExportImportExtensions<VkDrmFormatModifierPropertiesListEXT, VkDrmFormatModifierPropertiesEXT,
1163                                             VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT>,
1164                 exportImportMemoryExplicitModifiersCase<VkDrmFormatModifierPropertiesListEXT,
1165                                                         VkDrmFormatModifierPropertiesEXT,
1166                                                         VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT>,
1167                 formats[formatNdx]);
1168             // Test exporting/importing images with modifiers
1169             addFunctionCase(
1170                 group2.get(), getFormatCaseName(formats[formatNdx]),
1171                 checkExportImportExtensions<VkDrmFormatModifierPropertiesList2EXT, VkDrmFormatModifierProperties2EXT,
1172                                             VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT>,
1173                 exportImportMemoryExplicitModifiersCase<VkDrmFormatModifierPropertiesList2EXT,
1174                                                         VkDrmFormatModifierProperties2EXT,
1175                                                         VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT>,
1176                 formats[formatNdx]);
1177         }
1178 
1179         drmFormatModifiersGroup->addChild(group.release());
1180         drmFormatModifiersGroup->addChild(group2.release());
1181     }
1182 
1183     return drmFormatModifiersGroup.release();
1184 }
1185 
1186 } // namespace modifiers
1187 } // namespace vkt
1188