xref: /aosp_15_r20/external/mesa3d/src/broadcom/vulkan/v3dv_formats.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2019 Raspberry Pi Ltd
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "v3dv_private.h"
25 #if DETECT_OS_ANDROID
26 #include "vk_android.h"
27 #endif
28 #include "vk_enum_defines.h"
29 #include "vk_util.h"
30 
31 #include "drm-uapi/drm_fourcc.h"
32 #include "util/format/u_format.h"
33 #include "vulkan/wsi/wsi_common.h"
34 
35 #include <vulkan/vulkan_android.h>
36 
37 const uint8_t *
v3dv_get_format_swizzle(struct v3dv_device * device,VkFormat f,uint8_t plane)38 v3dv_get_format_swizzle(struct v3dv_device *device, VkFormat f, uint8_t plane)
39 {
40    const struct v3dv_format *vf = v3dv_X(device, get_format)(f);
41    static const uint8_t fallback[] = {0, 1, 2, 3};
42 
43    if (!vf)
44       return fallback;
45 
46    return vf->planes[plane].swizzle;
47 }
48 
49 bool
v3dv_format_swizzle_needs_rb_swap(const uint8_t * swizzle)50 v3dv_format_swizzle_needs_rb_swap(const uint8_t *swizzle)
51 {
52    /* Normal case */
53    if (swizzle[0] == PIPE_SWIZZLE_Z)
54       return swizzle[2] == PIPE_SWIZZLE_X;
55 
56    /* Format uses reverse flag */
57    if (swizzle[0] == PIPE_SWIZZLE_Y)
58       return swizzle[2] == PIPE_SWIZZLE_W;
59 
60    return false;
61 }
62 
63 bool
v3dv_format_swizzle_needs_reverse(const uint8_t * swizzle)64 v3dv_format_swizzle_needs_reverse(const uint8_t *swizzle)
65 {
66    /* Normal case */
67    if (swizzle[0] == PIPE_SWIZZLE_W &&
68        swizzle[1] == PIPE_SWIZZLE_Z &&
69        swizzle[2] == PIPE_SWIZZLE_Y &&
70        swizzle[3] == PIPE_SWIZZLE_X) {
71       return true;
72    }
73 
74    /* Format uses RB swap flag */
75    if (swizzle[0] == PIPE_SWIZZLE_Y &&
76        swizzle[1] == PIPE_SWIZZLE_Z &&
77        swizzle[2] == PIPE_SWIZZLE_W &&
78        swizzle[3] == PIPE_SWIZZLE_X) {
79       return true;
80    }
81 
82    return false;
83 }
84 
85 /* Some cases of transfer operations are raw data copies that don't depend
86  * on the semantics of the pixel format (no pixel format conversions are
87  * involved). In these cases, it is safe to choose any format supported by
88  * the TFU so long as it has the same texel size, which allows us to use the
89  * TFU paths with formats that are not TFU supported otherwise.
90  *
91  * Even when copying multi-plane images, we are copying per-plane, so the
92  * compatible TFU format will be single-plane.
93  */
94 const struct v3dv_format *
v3dv_get_compatible_tfu_format(struct v3dv_device * device,uint32_t bpp,VkFormat * out_vk_format)95 v3dv_get_compatible_tfu_format(struct v3dv_device *device,
96                                uint32_t bpp,
97                                VkFormat *out_vk_format)
98 {
99    VkFormat vk_format;
100    switch (bpp) {
101    case 16: vk_format = VK_FORMAT_R32G32B32A32_SFLOAT;  break;
102    case 8:  vk_format = VK_FORMAT_R16G16B16A16_SFLOAT;  break;
103    case 4:  vk_format = VK_FORMAT_R32_SFLOAT;           break;
104    case 2:  vk_format = VK_FORMAT_R16_SFLOAT;           break;
105    case 1:  vk_format = VK_FORMAT_R8_UNORM;             break;
106    default: unreachable("unsupported format bit-size"); break;
107    };
108 
109    if (out_vk_format)
110       *out_vk_format = vk_format;
111 
112    const struct v3dv_format *format = v3dv_X(device, get_format)(vk_format);
113    assert(format->plane_count == 1);
114    assert(v3dv_X(device, tfu_supports_tex_format)(format->planes[0].tex_type));
115 
116    return format;
117 }
118 
119 static VkFormatFeatureFlags2
image_format_plane_features(struct v3dv_physical_device * pdevice,VkFormat vk_format,const struct v3dv_format_plane * v3dv_format,VkImageTiling tiling)120 image_format_plane_features(struct v3dv_physical_device *pdevice,
121                             VkFormat vk_format,
122                             const struct v3dv_format_plane *v3dv_format,
123                             VkImageTiling tiling)
124 {
125    const VkImageAspectFlags aspects = vk_format_aspects(vk_format);
126 
127    const VkImageAspectFlags zs_aspects = VK_IMAGE_ASPECT_DEPTH_BIT |
128                                          VK_IMAGE_ASPECT_STENCIL_BIT;
129    const VkImageAspectFlags supported_aspects = VK_IMAGE_ASPECT_COLOR_BIT |
130                                                 zs_aspects;
131    if ((aspects & supported_aspects) != aspects)
132       return 0;
133 
134    /* FIXME: We don't support separate stencil yet */
135    if ((aspects & zs_aspects) == VK_IMAGE_ASPECT_STENCIL_BIT)
136       return 0;
137 
138    if (v3dv_format->tex_type == TEXTURE_DATA_FORMAT_NO &&
139        v3dv_format->rt_type == V3D_OUTPUT_IMAGE_FORMAT_NO) {
140       return 0;
141    }
142 
143    VkFormatFeatureFlags2 flags = 0;
144 
145    /* Raster format is only supported for 1D textures, so let's just
146     * always require optimal tiling for anything that requires sampling.
147     * Note: even if the user requests optimal for a 1D image, we will still
148     * use raster format since that is what the HW requires.
149     */
150    if (v3dv_format->tex_type != TEXTURE_DATA_FORMAT_NO &&
151        tiling == VK_IMAGE_TILING_OPTIMAL) {
152       flags |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT |
153                VK_FORMAT_FEATURE_2_BLIT_SRC_BIT;
154 
155    }
156 
157    if (v3dv_format->rt_type != V3D_OUTPUT_IMAGE_FORMAT_NO) {
158       if (aspects & VK_IMAGE_ASPECT_COLOR_BIT) {
159          flags |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
160                   VK_FORMAT_FEATURE_2_BLIT_DST_BIT;
161       } else if (aspects & zs_aspects) {
162          flags |= VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT |
163                   VK_FORMAT_FEATURE_2_BLIT_DST_BIT;
164       }
165    }
166 
167    const struct util_format_description *desc =
168       vk_format_description(vk_format);
169 
170    if (tiling != VK_IMAGE_TILING_LINEAR) {
171       if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN && desc->is_array) {
172          flags |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT |
173                   VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT;
174          if (desc->nr_channels == 1 && vk_format_is_int(vk_format))
175             flags |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT;
176       } else if (vk_format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 ||
177                  vk_format == VK_FORMAT_A2R10G10B10_UNORM_PACK32 ||
178                  vk_format == VK_FORMAT_A2B10G10R10_UINT_PACK32 ||
179                  vk_format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
180          /* To comply with shaderStorageImageExtendedFormats */
181          flags |= VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT |
182                   VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT;
183       }
184    }
185 
186    /* All our depth formats support shadow comparisons. */
187    if (vk_format_has_depth(vk_format) &&
188        (flags & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT)) {
189       flags |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT;
190    }
191 
192    if (flags) {
193       flags |= VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT |
194                VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT;
195    }
196 
197    return flags;
198 }
199 
200 static VkFormatFeatureFlags2
image_format_features(struct v3dv_physical_device * pdevice,VkFormat vk_format,const struct v3dv_format * v3dv_format,VkImageTiling tiling)201 image_format_features(struct v3dv_physical_device *pdevice,
202                        VkFormat vk_format,
203                        const struct v3dv_format *v3dv_format,
204                        VkImageTiling tiling)
205 {
206    if (!v3dv_format || !v3dv_format->plane_count)
207       return 0;
208 
209    VkFormatFeatureFlags2 flags = ~0ull;
210    for (uint8_t plane = 0;
211         flags && plane < v3dv_format->plane_count;
212         plane++) {
213       VkFormat plane_format = vk_format_get_plane_format(vk_format, plane);
214 
215       flags &= image_format_plane_features(pdevice,
216                                            plane_format,
217                                            &v3dv_format->planes[plane],
218                                            tiling);
219    }
220 
221    const struct vk_format_ycbcr_info *ycbcr_info =
222       vk_format_get_ycbcr_info(vk_format);
223 
224    if (ycbcr_info) {
225       assert(v3dv_format->plane_count == ycbcr_info->n_planes);
226 
227       flags |= VK_FORMAT_FEATURE_2_DISJOINT_BIT;
228 
229       if (flags & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT) {
230          flags |= VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT;
231          for (unsigned p = 0; p < ycbcr_info->n_planes; p++) {
232             if (ycbcr_info->planes[p].denominator_scales[0] > 1 ||
233                 ycbcr_info->planes[p].denominator_scales[1] > 1) {
234                flags |= VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT;
235                break;
236             }
237          }
238       }
239 
240       /* FIXME: in the future we should be able to support BLIT_SRC via the
241        * blit_shader path
242        */
243       const VkFormatFeatureFlags2 disallowed_ycbcr_image_features =
244          VK_FORMAT_FEATURE_2_BLIT_SRC_BIT |
245          VK_FORMAT_FEATURE_2_BLIT_DST_BIT |
246          VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
247          VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT |
248          VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT;
249 
250       flags &= ~disallowed_ycbcr_image_features;
251    }
252 
253    if (flags & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT &&
254        v3dv_format->supports_filtering) {
255       flags |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
256    }
257 
258    if (flags & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT &&
259        v3dv_X(pdevice, format_supports_blending)(v3dv_format)) {
260       flags |= VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT;
261    }
262 
263    return flags;
264 }
265 
266 static VkFormatFeatureFlags2
buffer_format_features(VkFormat vk_format,const struct v3dv_format * v3dv_format)267 buffer_format_features(VkFormat vk_format, const struct v3dv_format *v3dv_format)
268 {
269    if (!v3dv_format)
270       return 0;
271 
272    if (v3dv_format->plane_count != 1)
273       return 0;
274 
275    /* We probably only want to support buffer formats that have a
276     * color format specification.
277     */
278    if (!vk_format_is_color(vk_format))
279       return 0;
280 
281    const struct util_format_description *desc =
282       vk_format_description(vk_format);
283 
284    VkFormatFeatureFlags2 flags = 0;
285    if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&
286        desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB &&
287        desc->is_array) {
288       flags |=  VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT;
289       if (v3dv_format->planes[0].tex_type != TEXTURE_DATA_FORMAT_NO) {
290          /* STORAGE_READ_WITHOUT_FORMAT can also be applied for buffers. From spec:
291           *   "VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT specifies
292           *    that image views or buffer views created with this format can
293           *    be used as storage images for read operations without
294           *    specifying a format."
295           */
296          flags |= VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT |
297                   VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT |
298                   VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT;
299       }
300    } else if (vk_format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 ||
301               vk_format == VK_FORMAT_A2R10G10B10_UNORM_PACK32) {
302       flags |= VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT |
303                VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT |
304                VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT;
305    } else if (vk_format == VK_FORMAT_A2B10G10R10_UINT_PACK32 ||
306               vk_format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
307       flags |= VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT |
308                VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT;
309    }
310 
311    if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&
312        desc->is_array &&
313        desc->nr_channels == 1 &&
314        vk_format_is_int(vk_format)) {
315       flags |= VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT;
316    }
317 
318    return flags;
319 }
320 
321 bool
v3dv_buffer_format_supports_features(struct v3dv_device * device,VkFormat vk_format,VkFormatFeatureFlags2 features)322 v3dv_buffer_format_supports_features(struct v3dv_device *device,
323                                      VkFormat vk_format,
324                                      VkFormatFeatureFlags2 features)
325 {
326    const struct v3dv_format *v3dv_format = v3dv_X(device, get_format)(vk_format);
327    const VkFormatFeatureFlags2 supported =
328       buffer_format_features(vk_format, v3dv_format);
329    return (supported & features) == features;
330 }
331 
332 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties2 * pFormatProperties)333 v3dv_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,
334                                         VkFormat format,
335                                         VkFormatProperties2 *pFormatProperties)
336 {
337    V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physicalDevice);
338    const struct v3dv_format *v3dv_format = v3dv_X(pdevice, get_format)(format);
339 
340    VkFormatFeatureFlags2 linear2, optimal2, buffer2;
341    linear2 = image_format_features(pdevice, format, v3dv_format,
342                                    VK_IMAGE_TILING_LINEAR);
343    optimal2 = image_format_features(pdevice, format, v3dv_format,
344                                     VK_IMAGE_TILING_OPTIMAL);
345    buffer2 = buffer_format_features(format, v3dv_format);
346    pFormatProperties->formatProperties = (VkFormatProperties) {
347       .linearTilingFeatures = vk_format_features2_to_features(linear2),
348       .optimalTilingFeatures = vk_format_features2_to_features(optimal2),
349       .bufferFeatures = vk_format_features2_to_features(buffer2),
350    };
351 
352    vk_foreach_struct(ext, pFormatProperties->pNext) {
353       switch ((unsigned)ext->sType) {
354       case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT: {
355          struct VkDrmFormatModifierPropertiesListEXT *list = (void *)ext;
356          VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierPropertiesEXT, out,
357                                 list->pDrmFormatModifierProperties,
358                                 &list->drmFormatModifierCount);
359          if (pFormatProperties->formatProperties.linearTilingFeatures) {
360             vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT,
361                                      &out, mod_props) {
362                mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
363                mod_props->drmFormatModifierPlaneCount = 1;
364                mod_props->drmFormatModifierTilingFeatures =
365                   pFormatProperties->formatProperties.linearTilingFeatures;
366             }
367          }
368          if (pFormatProperties->formatProperties.optimalTilingFeatures) {
369             vk_outarray_append_typed(VkDrmFormatModifierPropertiesEXT,
370                                      &out, mod_props) {
371                mod_props->drmFormatModifier = DRM_FORMAT_MOD_BROADCOM_UIF;
372                mod_props->drmFormatModifierPlaneCount = 1;
373                mod_props->drmFormatModifierTilingFeatures =
374                   pFormatProperties->formatProperties.optimalTilingFeatures;
375             }
376          }
377          break;
378       }
379       case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT: {
380          struct VkDrmFormatModifierPropertiesList2EXT *list = (void *)ext;
381          VK_OUTARRAY_MAKE_TYPED(VkDrmFormatModifierProperties2EXT, out,
382                                 list->pDrmFormatModifierProperties,
383                                 &list->drmFormatModifierCount);
384          if (linear2) {
385             vk_outarray_append_typed(VkDrmFormatModifierProperties2EXT,
386                                      &out, mod_props) {
387                mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
388                mod_props->drmFormatModifierPlaneCount = 1;
389                mod_props->drmFormatModifierTilingFeatures = linear2;
390             }
391          }
392          if (optimal2) {
393             vk_outarray_append_typed(VkDrmFormatModifierProperties2EXT,
394                                      &out, mod_props) {
395                mod_props->drmFormatModifier = DRM_FORMAT_MOD_BROADCOM_UIF;
396                mod_props->drmFormatModifierPlaneCount = 1;
397                mod_props->drmFormatModifierTilingFeatures = optimal2;
398             }
399          }
400          break;
401       }
402       case VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3: {
403          VkFormatProperties3 *props = (VkFormatProperties3 *)ext;
404          props->linearTilingFeatures = linear2;
405          props->optimalTilingFeatures = optimal2;
406          props->bufferFeatures = buffer2;
407          break;
408       }
409       default:
410          vk_debug_ignored_stype(ext->sType);
411          break;
412       }
413    }
414 }
415 
416 static VkResult
get_image_format_properties(struct v3dv_physical_device * physical_device,const VkPhysicalDeviceImageFormatInfo2 * info,VkImageTiling tiling,VkImageFormatProperties * pImageFormatProperties,VkSamplerYcbcrConversionImageFormatProperties * pYcbcrImageFormatProperties)417 get_image_format_properties(
418    struct v3dv_physical_device *physical_device,
419    const VkPhysicalDeviceImageFormatInfo2 *info,
420    VkImageTiling tiling,
421    VkImageFormatProperties *pImageFormatProperties,
422    VkSamplerYcbcrConversionImageFormatProperties *pYcbcrImageFormatProperties)
423 {
424    const struct v3dv_format *v3dv_format = v3dv_X(physical_device, get_format)(info->format);
425    VkFormatFeatureFlags2 format_feature_flags =
426       image_format_features(physical_device, info->format, v3dv_format, tiling);
427    if (!format_feature_flags)
428       goto unsupported;
429 
430    /* This allows users to create uncompressed views of compressed images,
431     * however this is not something the hardware supports naturally and requires
432     * the driver to lie when programming the texture state to make the hardware
433     * sample with the uncompressed view correctly, and even then, there are
434     * issues when running on real hardware.
435     *
436     * See https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11336
437     * for details.
438     */
439    if (info->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT)
440       goto unsupported;
441 
442    const VkImageStencilUsageCreateInfo *stencil_usage_info =
443       vk_find_struct_const(info->pNext, IMAGE_STENCIL_USAGE_CREATE_INFO);
444 
445    VkImageUsageFlags image_usage =
446       info->usage | (stencil_usage_info ? stencil_usage_info->stencilUsage : 0);
447 
448    /* If VK_IMAGE_CREATE_EXTENDED_USAGE_BIT is set it means the usage flags may
449     * not be be supported for the image format but are supported for at least
450     * one compatible format from which an image view can be created for the
451     * image. This means we should not report the format as unsupported based
452     * on the usage flags when usage refers to how an image view may be used
453     * (i.e. as a framebuffer attachment, for sampling, etc).
454     */
455    VkImageUsageFlags view_usage =
456       info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT ? 0 : image_usage;
457 
458    if (image_usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
459       if (!(format_feature_flags & VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT)) {
460          goto unsupported;
461       }
462 
463       /* Sampling of raster depth/stencil images is not supported. Since 1D
464        * images are always raster, even if the user requested optimal tiling,
465        * we can't have them be used as transfer sources, since that includes
466        * using them for blit sources, which might require sampling.
467        */
468       if (info->type == VK_IMAGE_TYPE_1D &&
469           vk_format_is_depth_or_stencil(info->format)) {
470          goto unsupported;
471       }
472    }
473 
474    if (image_usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
475       if (!(format_feature_flags & VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT)) {
476          goto unsupported;
477       }
478    }
479 
480    if (view_usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
481                      VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
482       if (!(format_feature_flags & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT))
483          goto unsupported;
484 
485       /* Sampling of raster depth/stencil images is not supported. Since 1D
486        * images are always raster, even if the user requested optimal tiling,
487        * we can't allow sampling if the format is depth/stencil.
488        */
489       if (info->type == VK_IMAGE_TYPE_1D &&
490           vk_format_is_depth_or_stencil(info->format)) {
491          goto unsupported;
492       }
493    }
494 
495    if (view_usage & VK_IMAGE_USAGE_STORAGE_BIT) {
496       if (!(format_feature_flags & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT)) {
497          goto unsupported;
498       }
499    }
500 
501    if (view_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
502       if (!(format_feature_flags & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT)) {
503          goto unsupported;
504       }
505    }
506 
507    if (view_usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
508       if (!(format_feature_flags &
509             VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)) {
510          goto unsupported;
511       }
512    }
513 
514    switch (info->type) {
515    case VK_IMAGE_TYPE_1D:
516       pImageFormatProperties->maxExtent.width = V3D_MAX_IMAGE_DIMENSION;
517       pImageFormatProperties->maxExtent.height = 1;
518       pImageFormatProperties->maxExtent.depth = 1;
519       pImageFormatProperties->maxArrayLayers = V3D_MAX_ARRAY_LAYERS;
520       pImageFormatProperties->maxMipLevels = V3D_MAX_MIP_LEVELS;
521       break;
522    case VK_IMAGE_TYPE_2D:
523       pImageFormatProperties->maxExtent.width = V3D_MAX_IMAGE_DIMENSION;
524       pImageFormatProperties->maxExtent.height = V3D_MAX_IMAGE_DIMENSION;
525       pImageFormatProperties->maxExtent.depth = 1;
526       pImageFormatProperties->maxArrayLayers =
527          v3dv_format->plane_count == 1 ? V3D_MAX_ARRAY_LAYERS : 1;
528       pImageFormatProperties->maxMipLevels = V3D_MAX_MIP_LEVELS;
529       break;
530    case VK_IMAGE_TYPE_3D:
531       pImageFormatProperties->maxExtent.width = V3D_MAX_IMAGE_DIMENSION;
532       pImageFormatProperties->maxExtent.height = V3D_MAX_IMAGE_DIMENSION;
533       pImageFormatProperties->maxExtent.depth = V3D_MAX_IMAGE_DIMENSION;
534       pImageFormatProperties->maxArrayLayers = 1;
535       pImageFormatProperties->maxMipLevels = V3D_MAX_MIP_LEVELS;
536       break;
537    default:
538       unreachable("bad VkImageType");
539    }
540 
541    /* Our hw doesn't support 1D compressed textures. */
542    if (info->type == VK_IMAGE_TYPE_1D &&
543        vk_format_is_compressed(info->format)) {
544        goto unsupported;
545    }
546 
547    /* From the Vulkan 1.0 spec, section 34.1.1. Supported Sample Counts:
548     *
549     * sampleCounts will be set to VK_SAMPLE_COUNT_1_BIT if at least one of the
550     * following conditions is true:
551     *
552     *   - tiling is VK_IMAGE_TILING_LINEAR
553     *   - type is not VK_IMAGE_TYPE_2D
554     *   - flags contains VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
555     *   - neither the VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT flag nor the
556     *     VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT flag in
557     *     VkFormatProperties::optimalTilingFeatures returned by
558     *     vkGetPhysicalDeviceFormatProperties is set.
559     */
560    pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT;
561    if (tiling != VK_IMAGE_TILING_LINEAR &&
562        info->type == VK_IMAGE_TYPE_2D &&
563        !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
564        (format_feature_flags & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT ||
565         format_feature_flags & VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT)) {
566       pImageFormatProperties->sampleCounts |= VK_SAMPLE_COUNT_4_BIT;
567    }
568 
569    if (tiling == VK_IMAGE_TILING_LINEAR)
570       pImageFormatProperties->maxMipLevels = 1;
571 
572    /* From the Vulkan 1.2 spec, section 12.3. Images, VkImageCreateInfo structure:
573     *
574     *   "Images created with one of the formats that require a sampler Y′CBCR
575     *    conversion, have further restrictions on their limits and
576     *    capabilities compared to images created with other formats. Creation
577     *    of images with a format requiring Y′CBCR conversion may not be
578     *    supported unless other parameters meet all of the constraints:
579     *
580     *    * imageType is VK_IMAGE_TYPE_2D
581     *    * mipLevels is 1
582     *    * arrayLayers is 1, unless the ycbcrImageArrays feature is enabled, or
583     *      otherwise indicated by VkImageFormatProperties::maxArrayLayers, as
584     *      returned by vkGetPhysicalDeviceImageFormatProperties
585     *    * samples is VK_SAMPLE_COUNT_1_BIT
586     *
587     * Implementations may support additional limits and capabilities beyond
588     * those listed above."
589     *
590     * We don't provide such additional limits, so we set those limits, or just
591     * return unsupported.
592     */
593    if (vk_format_get_plane_count(info->format) > 1) {
594       if (info->type != VK_IMAGE_TYPE_2D)
595          goto unsupported;
596       pImageFormatProperties->maxMipLevels = 1;
597       pImageFormatProperties->maxArrayLayers = 1;
598       pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT;
599    }
600 
601    pImageFormatProperties->maxResourceSize = 0xffffffff; /* 32-bit allocation */
602 
603    if (pYcbcrImageFormatProperties) {
604       pYcbcrImageFormatProperties->combinedImageSamplerDescriptorCount =
605           vk_format_get_plane_count(info->format);
606    }
607 
608    return VK_SUCCESS;
609 
610 unsupported:
611    *pImageFormatProperties = (VkImageFormatProperties) {
612       .maxExtent = { 0, 0, 0 },
613       .maxMipLevels = 0,
614       .maxArrayLayers = 0,
615       .sampleCounts = 0,
616       .maxResourceSize = 0,
617    };
618 
619    return VK_ERROR_FORMAT_NOT_SUPPORTED;
620 }
621 
622 static const VkExternalMemoryProperties prime_fd_props = {
623    .externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
624                              VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT,
625    .exportFromImportedHandleTypes =
626       VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
627       VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
628    .compatibleHandleTypes =
629       VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
630       VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
631 };
632 
633 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkImageTiling tiling,VkImageUsageFlags usage,VkImageCreateFlags createFlags,VkImageFormatProperties * pImageFormatProperties)634 v3dv_GetPhysicalDeviceImageFormatProperties(
635    VkPhysicalDevice physicalDevice,
636    VkFormat format,
637    VkImageType type,
638    VkImageTiling tiling,
639    VkImageUsageFlags usage,
640    VkImageCreateFlags createFlags,
641    VkImageFormatProperties *pImageFormatProperties)
642 {
643    V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
644 
645    const VkPhysicalDeviceImageFormatInfo2 info = {
646       .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
647       .pNext = NULL,
648       .format = format,
649       .type = type,
650       .tiling = tiling,
651       .usage = usage,
652       .flags = createFlags,
653    };
654 
655    return get_image_format_properties(physical_device, &info, tiling,
656                                       pImageFormatProperties, NULL);
657 }
658 
659 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2 * base_info,VkImageFormatProperties2 * base_props)660 v3dv_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,
661                                              const VkPhysicalDeviceImageFormatInfo2 *base_info,
662                                              VkImageFormatProperties2 *base_props)
663 {
664    V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
665    const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
666    const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *drm_format_mod_info = NULL;
667    VkExternalImageFormatProperties *external_props = NULL;
668    UNUSED VkAndroidHardwareBufferUsageANDROID *android_usage = NULL;
669    VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;
670    VkImageTiling tiling = base_info->tiling;
671 
672    /* Extract input structs */
673    vk_foreach_struct_const(s, base_info->pNext) {
674       switch (s->sType) {
675       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
676          external_info = (const void *) s;
677          break;
678       case VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO:
679          /* Do nothing, get_image_format_properties() below will handle it */;
680          break;
681       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT:
682          drm_format_mod_info = (const void *) s;
683          switch (drm_format_mod_info->drmFormatModifier) {
684          case DRM_FORMAT_MOD_LINEAR:
685             tiling = VK_IMAGE_TILING_LINEAR;
686             break;
687          case DRM_FORMAT_MOD_BROADCOM_UIF:
688             tiling = VK_IMAGE_TILING_OPTIMAL;
689             break;
690          default:
691             assert("Unknown DRM format modifier");
692          }
693          break;
694       default:
695          vk_debug_ignored_stype(s->sType);
696          break;
697       }
698    }
699 
700    assert(tiling == VK_IMAGE_TILING_OPTIMAL ||
701           tiling == VK_IMAGE_TILING_LINEAR);
702 
703    /* Extract output structs */
704    vk_foreach_struct(s, base_props->pNext) {
705       switch (s->sType) {
706       case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
707          external_props = (void *) s;
708          break;
709       case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID:
710          android_usage = (void *)s;
711          break;
712       case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:
713          ycbcr_props = (void *) s;
714          break;
715       default:
716          vk_debug_ignored_stype(s->sType);
717          break;
718       }
719    }
720 
721    VkResult result =
722       get_image_format_properties(physical_device, base_info, tiling,
723                                   &base_props->imageFormatProperties,
724                                   ycbcr_props);
725    if (result != VK_SUCCESS)
726       goto done;
727 
728    if (external_info && external_info->handleType != 0) {
729       switch (external_info->handleType) {
730       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
731       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
732          if (external_props)
733             external_props->externalMemoryProperties = prime_fd_props;
734          break;
735 #if DETECT_OS_ANDROID
736       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:
737          if (external_props) {
738             external_props->externalMemoryProperties.exportFromImportedHandleTypes = 0;
739             external_props->externalMemoryProperties.compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
740             external_props->externalMemoryProperties.externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
741          }
742          break;
743 #endif
744       default:
745          result = VK_ERROR_FORMAT_NOT_SUPPORTED;
746          break;
747       }
748    }
749 
750    if (android_usage) {
751 #if DETECT_OS_ANDROID
752       android_usage->androidHardwareBufferUsage =
753          vk_image_usage_to_ahb_usage(base_info->flags, base_info->usage);
754 #endif
755    }
756 
757 done:
758    return result;
759 }
760 
761 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkSampleCountFlagBits samples,VkImageUsageFlags usage,VkImageTiling tiling,uint32_t * pPropertyCount,VkSparseImageFormatProperties * pProperties)762 v3dv_GetPhysicalDeviceSparseImageFormatProperties(
763    VkPhysicalDevice physicalDevice,
764    VkFormat format,
765    VkImageType type,
766    VkSampleCountFlagBits samples,
767    VkImageUsageFlags usage,
768    VkImageTiling tiling,
769    uint32_t *pPropertyCount,
770    VkSparseImageFormatProperties *pProperties)
771 {
772    *pPropertyCount = 0;
773 }
774 
775 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2 * pProperties)776 v3dv_GetPhysicalDeviceSparseImageFormatProperties2(
777    VkPhysicalDevice physicalDevice,
778    const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
779    uint32_t *pPropertyCount,
780    VkSparseImageFormatProperties2 *pProperties)
781 {
782    *pPropertyCount = 0;
783 }
784 
785 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalBufferInfo * pExternalBufferInfo,VkExternalBufferProperties * pExternalBufferProperties)786 v3dv_GetPhysicalDeviceExternalBufferProperties(
787    VkPhysicalDevice physicalDevice,
788    const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
789    VkExternalBufferProperties *pExternalBufferProperties)
790 {
791    switch (pExternalBufferInfo->handleType) {
792    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
793    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
794       pExternalBufferProperties->externalMemoryProperties = prime_fd_props;
795       return;
796    default: /* Unsupported */
797       pExternalBufferProperties->externalMemoryProperties =
798          (VkExternalMemoryProperties) {
799             .compatibleHandleTypes = pExternalBufferInfo->handleType,
800          };
801       break;
802    }
803 }
804