xref: /aosp_15_r20/external/mesa3d/src/freedreno/vulkan/tu_formats.cc (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2016 Red Hat.
3  * Copyright © 2016 Bas Nieuwenhuizen
4  * SPDX-License-Identifier: MIT
5  */
6 
7 #include "tu_formats.h"
8 
9 #include "fdl/fd6_format_table.h"
10 #include "common/freedreno_ubwc.h"
11 
12 #include "vk_android.h"
13 #include "vk_enum_defines.h"
14 #include "vk_util.h"
15 #include "drm-uapi/drm_fourcc.h"
16 
17 #include "tu_android.h"
18 #include "tu_device.h"
19 #include "tu_image.h"
20 
21 #include <vulkan/vulkan_android.h>
22 
23 static bool
tu6_format_vtx_supported(enum pipe_format format)24 tu6_format_vtx_supported(enum pipe_format format)
25 {
26    return fd6_vertex_format(format) != FMT6_NONE;
27 }
28 
29 struct tu_native_format
tu6_format_vtx(enum pipe_format format)30 tu6_format_vtx(enum pipe_format format)
31 {
32    struct tu_native_format fmt = {
33       .fmt = fd6_vertex_format(format),
34       .swap = fd6_vertex_swap(format),
35    };
36    assert(tu6_format_vtx_supported(format));
37    return fmt;
38 }
39 
40 static bool
tu6_format_color_supported(enum pipe_format format)41 tu6_format_color_supported(enum pipe_format format)
42 {
43    return fd6_color_format(format, TILE6_LINEAR) != FMT6_NONE;
44 }
45 
46 struct tu_native_format
tu6_format_color(enum pipe_format format,enum a6xx_tile_mode tile_mode)47 tu6_format_color(enum pipe_format format, enum a6xx_tile_mode tile_mode)
48 {
49    struct tu_native_format fmt = {
50       .fmt = fd6_color_format(format, tile_mode),
51       .swap = fd6_color_swap(format, tile_mode),
52    };
53    assert(fmt.fmt != FMT6_NONE);
54    return fmt;
55 }
56 
57 static bool
tu6_format_texture_supported(enum pipe_format format)58 tu6_format_texture_supported(enum pipe_format format)
59 {
60    return fd6_texture_format(format, TILE6_LINEAR) != FMT6_NONE;
61 }
62 
63 struct tu_native_format
tu6_format_texture(enum pipe_format format,enum a6xx_tile_mode tile_mode)64 tu6_format_texture(enum pipe_format format, enum a6xx_tile_mode tile_mode)
65 {
66    struct tu_native_format fmt = {
67       .fmt = fd6_texture_format(format, tile_mode),
68       .swap = fd6_texture_swap(format, tile_mode),
69    };
70    assert(fmt.fmt != FMT6_NONE);
71    return fmt;
72 }
73 
74 static enum fd6_ubwc_compat_type
tu6_ubwc_compat_mode(const struct fd_dev_info * info,VkFormat format)75 tu6_ubwc_compat_mode(const struct fd_dev_info *info, VkFormat format)
76 {
77    return fd6_ubwc_compat_mode(info, vk_format_to_pipe_format(format));
78 }
79 
80 bool
tu6_mutable_format_list_ubwc_compatible(const struct fd_dev_info * info,const VkImageFormatListCreateInfo * fmt_list)81 tu6_mutable_format_list_ubwc_compatible(const struct fd_dev_info *info,
82                                         const VkImageFormatListCreateInfo *fmt_list)
83 {
84    if (!fmt_list || !fmt_list->viewFormatCount)
85       return false;
86 
87    /* We're only looking at format list cross compatibility here, check
88     * ubwc_possible() for the base "is the format UBWC-able at all?"
89     */
90    if (fmt_list->viewFormatCount == 1)
91       return true;
92 
93    enum fd6_ubwc_compat_type type =
94       tu6_ubwc_compat_mode(info, fmt_list->pViewFormats[0]);
95    if (type == FD6_UBWC_UNKNOWN_COMPAT)
96       return false;
97 
98    for (uint32_t i = 1; i < fmt_list->viewFormatCount; i++) {
99       if (tu6_ubwc_compat_mode(info, fmt_list->pViewFormats[i]) != type)
100          return false;
101    }
102 
103    return true;
104 }
105 
106 static void
tu_physical_device_get_format_properties(struct tu_physical_device * physical_device,VkFormat vk_format,VkFormatProperties3 * out_properties)107 tu_physical_device_get_format_properties(
108    struct tu_physical_device *physical_device,
109    VkFormat vk_format,
110    VkFormatProperties3 *out_properties)
111 {
112    VkFormatFeatureFlags2 linear = 0, optimal = 0, buffer = 0;
113    enum pipe_format format = vk_format_to_pipe_format(vk_format);
114    const struct util_format_description *desc = util_format_description(format);
115 
116    bool supported_vtx = tu6_format_vtx_supported(format);
117    bool supported_color = tu6_format_color_supported(format);
118    bool supported_tex = tu6_format_texture_supported(format);
119    bool is_npot = !util_is_power_of_two_or_zero(desc->block.bits);
120 
121    if (format == PIPE_FORMAT_NONE ||
122        !(supported_vtx || supported_color || supported_tex)) {
123       goto end;
124    }
125 
126    /* We don't support BufferToImage/ImageToBuffer for npot formats */
127    if (!is_npot)
128       buffer |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
129 
130    if (supported_vtx)
131       buffer |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
132 
133    if (supported_tex)
134       buffer |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;
135 
136    /* Don't support anything but texel buffers for non-power-of-two formats
137     * with 3 components. We'd need several workarounds for copying and
138     * clearing them because they're not renderable.
139     */
140    if (supported_tex && !is_npot) {
141       optimal |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
142                  VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
143                  VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
144                  VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT;
145 
146       /* no blit src bit for YUYV/NV12/I420 formats */
147       if (desc->layout != UTIL_FORMAT_LAYOUT_SUBSAMPLED &&
148           desc->layout != UTIL_FORMAT_LAYOUT_PLANAR2 &&
149           desc->layout != UTIL_FORMAT_LAYOUT_PLANAR3) {
150          optimal |= VK_FORMAT_FEATURE_BLIT_SRC_BIT;
151       } else {
152          optimal |= VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
153 
154          if (desc->layout != UTIL_FORMAT_LAYOUT_SUBSAMPLED) {
155             optimal |= VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT |
156                        VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT;
157             if (physical_device->info->a6xx.has_separate_chroma_filter)
158                optimal |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT;
159          }
160       }
161 
162       if (!vk_format_is_int(vk_format)) {
163          optimal |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
164 
165          if (physical_device->vk.supported_extensions.EXT_filter_cubic)
166             optimal |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT;
167       }
168 
169       /* We sample on the CPU so we can technically support anything as long
170        * as it's floating point, but this restricts it to "reasonable" formats
171        * to use, which means two channels and not something weird like
172        * luminance-alpha.
173        */
174       if (util_format_is_float(format) &&
175           desc->nr_channels == 2 && desc->swizzle[0] == PIPE_SWIZZLE_X &&
176           desc->swizzle[1] == PIPE_SWIZZLE_Y) {
177          optimal |= VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT;
178       }
179    }
180 
181    if (supported_color) {
182       assert(supported_tex);
183       optimal |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
184                  VK_FORMAT_FEATURE_BLIT_DST_BIT |
185                  VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT |
186                  VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT |
187                  VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT;
188 
189       buffer |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT |
190                 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT |
191                 VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT;
192 
193       /* TODO: The blob also exposes these for R16G16_UINT/R16G16_SINT, but we
194        * don't have any tests for those.
195        */
196       if (vk_format == VK_FORMAT_R32_UINT || vk_format == VK_FORMAT_R32_SINT) {
197          optimal |= VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;
198          buffer |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT;
199       }
200 
201       if (!util_format_is_pure_integer(format))
202          optimal |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
203    }
204 
205    /* For the most part, we can do anything with a linear image that we could
206     * do with a tiled image. However, we can't support sysmem rendering with a
207     * linear depth texture, because we don't know if there's a bit to control
208     * the tiling of the depth buffer in BYPASS mode, and the blob also
209     * disables linear depth rendering, so there's no way to discover it. We
210     * also can't force GMEM mode, because there are other situations where we
211     * have to use sysmem rendering. So follow the blob here, and only enable
212     * DEPTH_STENCIL_ATTACHMENT_BIT for the optimal features.
213     */
214    linear = optimal;
215    if (tu6_pipe2depth(vk_format) != DEPTH6_NONE)
216       optimal |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
217 
218    if (!tiling_possible(vk_format) &&
219        /* We don't actually support tiling for this format, but we need to
220         * fake it as it's required by VK_KHR_sampler_ycbcr_conversion.
221         */
222        vk_format != VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM) {
223       optimal = 0;
224    }
225 
226    if (vk_format == VK_FORMAT_G8B8G8R8_422_UNORM ||
227        vk_format == VK_FORMAT_B8G8R8G8_422_UNORM ||
228        vk_format == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM ||
229        vk_format == VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM) {
230       /* Disable buffer texturing of subsampled (422) and planar YUV textures.
231        * The subsampling requirement comes from "If format is a block-compressed
232        * format, then bufferFeatures must not support any features for the
233        * format" plus the specification of subsampled as 2x1 compressed block
234        * format.  I couldn't find the citation for planar, but 1D access of
235        * planar YUV would be really silly.
236        */
237       buffer = 0;
238    }
239 
240    /* We don't support writing into VK_FORMAT_*_PACK16 images/buffers  */
241    if (desc->nr_channels > 2 && desc->block.bits == 16) {
242       buffer &= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;
243       linear &= ~(VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT |
244                   VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT);
245       optimal &= ~(VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT |
246                    VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT);
247    }
248 
249    /* All our depth formats support shadow comparisons. */
250    if (vk_format_has_depth(vk_format) && (optimal & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
251       optimal |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT;
252       linear |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT;
253    }
254 
255    /* From the Vulkan 1.3.205 spec, section 19.3 "43.3. Required Format Support":
256     *
257     *    Mandatory format support: depth/stencil with VkImageType
258     *    VK_IMAGE_TYPE_2D
259     *    [...]
260     *    bufferFeatures must not support any features for these formats
261     */
262    if (vk_format_is_depth_or_stencil(vk_format))
263       buffer = 0;
264 
265    /* D32_SFLOAT_S8_UINT is tiled as two images, so no linear format
266     * blob enables some linear features, but its not useful, so don't bother.
267     */
268    if (vk_format == VK_FORMAT_D32_SFLOAT_S8_UINT)
269       linear = 0;
270 
271 end:
272    out_properties->linearTilingFeatures = linear;
273    out_properties->optimalTilingFeatures = optimal;
274    out_properties->bufferFeatures = buffer;
275 }
276 
277 VKAPI_ATTR void VKAPI_CALL
tu_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties2 * pFormatProperties)278 tu_GetPhysicalDeviceFormatProperties2(
279    VkPhysicalDevice physicalDevice,
280    VkFormat format,
281    VkFormatProperties2 *pFormatProperties)
282 {
283    VK_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
284 
285    VkFormatProperties3 local_props3;
286    VkFormatProperties3 *props3 =
287       vk_find_struct(pFormatProperties->pNext, FORMAT_PROPERTIES_3);
288    if (!props3)
289       props3 = &local_props3;
290 
291    tu_physical_device_get_format_properties(
292       physical_device, format, props3);
293 
294    pFormatProperties->formatProperties = (VkFormatProperties) {
295       .linearTilingFeatures =
296          vk_format_features2_to_features(props3->linearTilingFeatures),
297       .optimalTilingFeatures =
298          vk_format_features2_to_features(props3->optimalTilingFeatures),
299       .bufferFeatures =
300          vk_format_features2_to_features(props3->bufferFeatures),
301    };
302 
303    VkDrmFormatModifierPropertiesListEXT *list =
304       vk_find_struct(pFormatProperties->pNext, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT);
305    if (list) {
306       VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierPropertiesEXT, out,
307                              list->pDrmFormatModifierProperties,
308                              &list->drmFormatModifierCount);
309 
310       if (pFormatProperties->formatProperties.linearTilingFeatures) {
311          vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT, &out, mod_props) {
312             mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
313             mod_props->drmFormatModifierPlaneCount = tu6_plane_count(format);
314             mod_props->drmFormatModifierTilingFeatures =
315                pFormatProperties->formatProperties.linearTilingFeatures;
316          }
317       }
318 
319       /* note: ubwc_possible() argument values to be ignored except for format */
320       if (pFormatProperties->formatProperties.optimalTilingFeatures &&
321           tiling_possible(format) &&
322           ubwc_possible(NULL, format, VK_IMAGE_TYPE_2D, 0, 0,
323                         physical_device->info, VK_SAMPLE_COUNT_1_BIT,
324                         false)) {
325          vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT, &out, mod_props) {
326             mod_props->drmFormatModifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
327             mod_props->drmFormatModifierPlaneCount = tu6_plane_count(format);
328             mod_props->drmFormatModifierTilingFeatures =
329                pFormatProperties->formatProperties.optimalTilingFeatures;
330          }
331       }
332    }
333 }
334 
335 static VkResult
tu_image_unsupported_format(VkImageFormatProperties * pImageFormatProperties)336 tu_image_unsupported_format(VkImageFormatProperties *pImageFormatProperties)
337 {
338    *pImageFormatProperties = (VkImageFormatProperties) {
339       .maxExtent = { 0, 0, 0 },
340       .maxMipLevels = 0,
341       .maxArrayLayers = 0,
342       .sampleCounts = 0,
343       .maxResourceSize = 0,
344    };
345 
346    return VK_ERROR_FORMAT_NOT_SUPPORTED;
347 }
348 
349 static VkResult
tu_get_image_format_properties(struct tu_physical_device * physical_device,const VkPhysicalDeviceImageFormatInfo2 * info,VkImageFormatProperties * pImageFormatProperties,VkFormatFeatureFlags * p_feature_flags)350 tu_get_image_format_properties(
351    struct tu_physical_device *physical_device,
352    const VkPhysicalDeviceImageFormatInfo2 *info,
353    VkImageFormatProperties *pImageFormatProperties,
354    VkFormatFeatureFlags *p_feature_flags)
355 {
356    VkFormatProperties3 format_props;
357    VkFormatFeatureFlags format_feature_flags;
358    VkExtent3D maxExtent;
359    uint32_t maxMipLevels;
360    uint32_t maxArraySize;
361    BITMASK_ENUM(VkSampleCountFlagBits) sampleCounts = VK_SAMPLE_COUNT_1_BIT;
362 
363    tu_physical_device_get_format_properties(physical_device, info->format,
364                                             &format_props);
365 
366    switch (info->tiling) {
367    case VK_IMAGE_TILING_LINEAR:
368       format_feature_flags = format_props.linearTilingFeatures;
369       break;
370 
371    case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT: {
372       const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *drm_info =
373          vk_find_struct_const(info->pNext, PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT);
374 
375       /* Subsampled format isn't stable yet, so don't allow
376        * importing/exporting with modifiers yet.
377        */
378       if (info->flags & VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT)
379          return VK_ERROR_FORMAT_NOT_SUPPORTED;
380 
381       switch (drm_info->drmFormatModifier) {
382       case DRM_FORMAT_MOD_QCOM_COMPRESSED:
383          /* falling back to linear/non-UBWC isn't possible with explicit modifier */
384 
385          /* formats which don't support tiling */
386          if (!format_props.optimalTilingFeatures ||
387              !tiling_possible(info->format))
388             return VK_ERROR_FORMAT_NOT_SUPPORTED;
389 
390          if (info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
391             const VkImageFormatListCreateInfo *format_list =
392                vk_find_struct_const(info->pNext,
393                                     IMAGE_FORMAT_LIST_CREATE_INFO);
394             if (!tu6_mutable_format_list_ubwc_compatible(physical_device->info,
395                                                          format_list))
396                return VK_ERROR_FORMAT_NOT_SUPPORTED;
397          }
398 
399          if (!ubwc_possible(NULL, info->format, info->type, info->usage,
400                             info->usage, physical_device->info, sampleCounts,
401                             false)) {
402             return VK_ERROR_FORMAT_NOT_SUPPORTED;
403          }
404 
405          format_feature_flags = format_props.optimalTilingFeatures;
406          break;
407       case DRM_FORMAT_MOD_LINEAR:
408          format_feature_flags = format_props.linearTilingFeatures;
409          break;
410       default:
411          return VK_ERROR_FORMAT_NOT_SUPPORTED;
412       }
413    } break;
414    case VK_IMAGE_TILING_OPTIMAL:
415       format_feature_flags = format_props.optimalTilingFeatures;
416       break;
417    default:
418       unreachable("bad VkPhysicalDeviceImageFormatInfo2");
419    }
420 
421    if (format_feature_flags == 0)
422       return tu_image_unsupported_format(pImageFormatProperties);
423 
424    if (info->type != VK_IMAGE_TYPE_2D &&
425        vk_format_is_depth_or_stencil(info->format))
426       return tu_image_unsupported_format(pImageFormatProperties);
427 
428    switch (info->type) {
429    default:
430       unreachable("bad vkimage type\n");
431    case VK_IMAGE_TYPE_1D:
432       maxExtent.width = 16384;
433       maxExtent.height = 1;
434       maxExtent.depth = 1;
435       maxMipLevels = 15; /* log2(maxWidth) + 1 */
436       maxArraySize = 2048;
437       break;
438    case VK_IMAGE_TYPE_2D:
439       maxExtent.width = 16384;
440       maxExtent.height = 16384;
441       maxExtent.depth = 1;
442       maxMipLevels = 15; /* log2(maxWidth) + 1 */
443       maxArraySize = 2048;
444       break;
445    case VK_IMAGE_TYPE_3D:
446       maxExtent.width = 2048;
447       maxExtent.height = 2048;
448       maxExtent.depth = 2048;
449       maxMipLevels = 12; /* log2(maxWidth) + 1 */
450       maxArraySize = 1;
451       break;
452    }
453 
454    if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
455        info->type == VK_IMAGE_TYPE_2D &&
456        (format_feature_flags &
457         (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
458          VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
459        !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
460        !(info->usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
461       sampleCounts |= VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT;
462       /* note: most operations support 8 samples (GMEM render/resolve do at least)
463        * but some do not (which ones?), just disable 8 samples completely,
464        * (no 8x msaa matches the blob driver behavior)
465        */
466    }
467 
468    /* From the Vulkan 1.3.206 spec:
469     *
470     * "VK_IMAGE_CREATE_EXTENDED_USAGE_BIT specifies that the image can be
471     * created with usage flags that are not supported for the format the image
472     * is created with but are supported for at least one format a VkImageView
473     * created from the image can have."
474     *
475     * This means we should relax checks that only depend on the
476     * format_feature_flags, to allow the user to create images that may be
477     * e.g. reinterpreted as storage when the original format doesn't allow it.
478     * The user will have to check against the format features anyway.
479     * Otherwise we'd unnecessarily disallow it.
480     */
481 
482    VkImageUsageFlags image_usage = info->usage;
483    if (info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT)
484       image_usage = 0;
485 
486    if (image_usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
487       if (!(format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
488          return tu_image_unsupported_format(pImageFormatProperties);
489       }
490    }
491 
492    if (image_usage & VK_IMAGE_USAGE_STORAGE_BIT) {
493       if (!(format_feature_flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {
494          return tu_image_unsupported_format(pImageFormatProperties);
495       }
496    }
497 
498    if (image_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
499       if (!(format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
500          return tu_image_unsupported_format(pImageFormatProperties);
501       }
502    }
503 
504    if (image_usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
505       if (!(format_feature_flags &
506             VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
507          return tu_image_unsupported_format(pImageFormatProperties);
508       }
509    }
510 
511    if (image_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
512       if (!(format_feature_flags &
513             (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
514              VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))) {
515          return tu_image_unsupported_format(pImageFormatProperties);
516       }
517    }
518 
519    *pImageFormatProperties = (VkImageFormatProperties) {
520       .maxExtent = maxExtent,
521       .maxMipLevels = maxMipLevels,
522       .maxArrayLayers = maxArraySize,
523       .sampleCounts = sampleCounts,
524 
525       /* FINISHME: Accurately calculate
526        * VkImageFormatProperties::maxResourceSize.
527        */
528       .maxResourceSize = UINT32_MAX,
529    };
530 
531    if (p_feature_flags)
532       *p_feature_flags = format_feature_flags;
533 
534    return VK_SUCCESS;
535 }
536 
537 static VkResult
tu_get_external_image_format_properties(const struct tu_physical_device * physical_device,const VkPhysicalDeviceImageFormatInfo2 * pImageFormatInfo,VkExternalMemoryHandleTypeFlagBits handleType,VkExternalImageFormatProperties * external_properties)538 tu_get_external_image_format_properties(
539    const struct tu_physical_device *physical_device,
540    const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
541    VkExternalMemoryHandleTypeFlagBits handleType,
542    VkExternalImageFormatProperties *external_properties)
543 {
544    BITMASK_ENUM(VkExternalMemoryFeatureFlagBits) flags = 0;
545    VkExternalMemoryHandleTypeFlags export_flags = 0;
546    VkExternalMemoryHandleTypeFlags compat_flags = 0;
547 
548    /* From the Vulkan 1.1.98 spec:
549     *
550     *    If handleType is not compatible with the format, type, tiling,
551     *    usage, and flags specified in VkPhysicalDeviceImageFormatInfo2,
552     *    then vkGetPhysicalDeviceImageFormatProperties2 returns
553     *    VK_ERROR_FORMAT_NOT_SUPPORTED.
554     */
555 
556    switch (handleType) {
557    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
558    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
559       switch (pImageFormatInfo->type) {
560       case VK_IMAGE_TYPE_2D:
561          flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT |
562                  VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
563                  VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
564          compat_flags = export_flags =
565             VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
566             VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
567          break;
568       default:
569          return vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED,
570                           "VkExternalMemoryTypeFlagBits(0x%x) unsupported for VkImageType(%d)",
571                           handleType, pImageFormatInfo->type);
572       }
573       break;
574 #if DETECT_OS_ANDROID
575    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:
576       flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT |
577               VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
578               VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
579       compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
580       break;
581 #endif
582    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
583       flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
584       compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
585       break;
586    default:
587       return vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED,
588                        "VkExternalMemoryTypeFlagBits(0x%x) unsupported",
589                        handleType);
590    }
591 
592    if (external_properties) {
593       external_properties->externalMemoryProperties =
594          (VkExternalMemoryProperties) {
595             .externalMemoryFeatures = flags,
596             .exportFromImportedHandleTypes = export_flags,
597             .compatibleHandleTypes = compat_flags,
598          };
599    }
600 
601    return VK_SUCCESS;
602 }
603 
604 VKAPI_ATTR VkResult VKAPI_CALL
tu_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2 * base_info,VkImageFormatProperties2 * base_props)605 tu_GetPhysicalDeviceImageFormatProperties2(
606    VkPhysicalDevice physicalDevice,
607    const VkPhysicalDeviceImageFormatInfo2 *base_info,
608    VkImageFormatProperties2 *base_props)
609 {
610    VK_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
611    const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
612    const VkPhysicalDeviceImageViewImageFormatInfoEXT *image_view_info = NULL;
613    VkExternalImageFormatProperties *external_props = NULL;
614    VkAndroidHardwareBufferUsageANDROID *android_usage = NULL;
615    VkFilterCubicImageViewImageFormatPropertiesEXT *cubic_props = NULL;
616    VkFormatFeatureFlags format_feature_flags;
617    VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;
618    VkResult result;
619 
620    result = tu_get_image_format_properties(physical_device,
621       base_info, &base_props->imageFormatProperties, &format_feature_flags);
622    if (result != VK_SUCCESS)
623       return result;
624 
625    /* Extract input structs */
626    vk_foreach_struct_const(s, base_info->pNext)
627    {
628       switch (s->sType) {
629       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
630          external_info = (const VkPhysicalDeviceExternalImageFormatInfo *) s;
631          break;
632       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT:
633          image_view_info = (const VkPhysicalDeviceImageViewImageFormatInfoEXT *) s;
634          break;
635       default:
636          break;
637       }
638    }
639 
640    /* Extract output structs */
641    vk_foreach_struct(s, base_props->pNext)
642    {
643       switch (s->sType) {
644       case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
645          external_props = (VkExternalImageFormatProperties *) s;
646          break;
647       case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID:
648          android_usage = (VkAndroidHardwareBufferUsageANDROID *) s;
649          break;
650       case VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT:
651          cubic_props = (VkFilterCubicImageViewImageFormatPropertiesEXT *) s;
652          break;
653       case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:
654          ycbcr_props = (VkSamplerYcbcrConversionImageFormatProperties *) s;
655          break;
656       default:
657          break;
658       }
659    }
660 
661    /* From the Vulkan 1.0.42 spec:
662     *
663     *    If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will
664     *    behave as if VkPhysicalDeviceExternalImageFormatInfo was not
665     *    present and VkExternalImageFormatProperties will be ignored.
666     */
667    if (external_info && external_info->handleType != 0) {
668       result = tu_get_external_image_format_properties(
669          physical_device, base_info, external_info->handleType,
670          external_props);
671       if (result != VK_SUCCESS)
672          goto fail;
673    }
674 
675    if (cubic_props) {
676       /* note: blob only allows cubic filtering for 2D and 2D array views
677        * its likely we can enable it for 1D and CUBE, needs testing however
678        */
679       if ((image_view_info->imageViewType == VK_IMAGE_VIEW_TYPE_2D ||
680            image_view_info->imageViewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY) &&
681           (format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT)) {
682          cubic_props->filterCubic = true;
683          cubic_props->filterCubicMinmax = true;
684       } else {
685          cubic_props->filterCubic = false;
686          cubic_props->filterCubicMinmax = false;
687       }
688    }
689 
690    if (android_usage) {
691       /* Don't expect gralloc to be able to allocate anything other than 3D: */
692       if (base_info->type != VK_IMAGE_TYPE_2D) {
693          result = vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED,
694                             "type (%u) unsupported for AHB", base_info->type);
695          goto fail;
696       }
697       VkImageFormatProperties *props = &base_props->imageFormatProperties;
698       if (!(props->sampleCounts & VK_SAMPLE_COUNT_1_BIT)) {
699          result = vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED,
700                           "sampleCounts (%x) unsupported for AHB", props->sampleCounts);
701          goto fail;
702       }
703       android_usage->androidHardwareBufferUsage =
704          vk_image_usage_to_ahb_usage(base_info->flags, base_info->usage);
705       uint32_t format = vk_image_format_to_ahb_format(base_info->format);
706       if (!format) {
707          result = vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED,
708                             "format (%u) unsupported for AHB", base_info->format);
709          goto fail;
710       }
711       /* We can't advertise support for anything that gralloc cannot allocate
712        * so we are stuck without any better option than attempting a test
713        * allocation:
714        */
715       if (!vk_ahb_probe_format(base_info->format, base_info->flags, base_info->usage)) {
716          result = vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED,
717                             "format (%x) with flags (%x) and usage (%x) unsupported for AHB",
718                             base_info->format, base_info->flags, base_info->usage);
719          goto fail;
720       }
721 
722       /* AHBs with mipmap usage will ignore this property */
723       props->maxMipLevels = 1;
724       props->sampleCounts = VK_SAMPLE_COUNT_1_BIT;
725    }
726 
727    if (ycbcr_props)
728       ycbcr_props->combinedImageSamplerDescriptorCount = 1;
729 
730    return VK_SUCCESS;
731 
732 fail:
733    if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) {
734       /* From the Vulkan 1.0.42 spec:
735        *
736        *    If the combination of parameters to
737        *    vkGetPhysicalDeviceImageFormatProperties2 is not supported by
738        *    the implementation for use in vkCreateImage, then all members of
739        *    imageFormatProperties will be filled with zero.
740        */
741       base_props->imageFormatProperties = (VkImageFormatProperties) {};
742    }
743 
744    return result;
745 }
746 
747 VKAPI_ATTR void VKAPI_CALL
tu_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2 * pProperties)748 tu_GetPhysicalDeviceSparseImageFormatProperties2(
749    VkPhysicalDevice physicalDevice,
750    const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
751    uint32_t *pPropertyCount,
752    VkSparseImageFormatProperties2 *pProperties)
753 {
754    /* Sparse images are not yet supported. */
755    *pPropertyCount = 0;
756 }
757