Home | History | Annotate | Line # | Download | only in vulkan
      1 /*
      2  * Copyright  2019 Raspberry Pi
      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 #include "vk_util.h"
     26 #include "vk_format_info.h"
     27 
     28 #include "drm-uapi/drm_fourcc.h"
     29 #include "util/format/u_format.h"
     30 #include "vulkan/wsi/wsi_common.h"
     31 
     32 const uint8_t *
     33 v3dv_get_format_swizzle(struct v3dv_device *device, VkFormat f)
     34 {
     35    const struct v3dv_format *vf = v3dv_X(device, get_format)(f);
     36    static const uint8_t fallback[] = {0, 1, 2, 3};
     37 
     38    if (!vf)
     39       return fallback;
     40 
     41    return vf->swizzle;
     42 }
     43 
     44 uint8_t
     45 v3dv_get_tex_return_size(const struct v3dv_format *vf,
     46                          bool compare_enable)
     47 {
     48    if (unlikely(V3D_DEBUG & V3D_DEBUG_TMU_16BIT))
     49       return 16;
     50 
     51    if (unlikely(V3D_DEBUG & V3D_DEBUG_TMU_32BIT))
     52       return 32;
     53 
     54    if (compare_enable)
     55       return 16;
     56 
     57    return vf->return_size;
     58 }
     59 
     60 /* Some cases of transfer operations are raw data copies that don't depend
     61  * on the semantics of the pixel format (no pixel format conversions are
     62  * involved). In these cases, it is safe to choose any format supported by
     63  * the TFU so long as it has the same texel size, which allows us to use the
     64  * TFU paths with formats that are not TFU supported otherwise.
     65  */
     66 const struct v3dv_format *
     67 v3dv_get_compatible_tfu_format(struct v3dv_device *device,
     68                                uint32_t bpp,
     69                                VkFormat *out_vk_format)
     70 {
     71    VkFormat vk_format;
     72    switch (bpp) {
     73    case 16: vk_format = VK_FORMAT_R32G32B32A32_SFLOAT;  break;
     74    case 8:  vk_format = VK_FORMAT_R16G16B16A16_SFLOAT;  break;
     75    case 4:  vk_format = VK_FORMAT_R32_SFLOAT;           break;
     76    case 2:  vk_format = VK_FORMAT_R16_SFLOAT;           break;
     77    case 1:  vk_format = VK_FORMAT_R8_UNORM;             break;
     78    default: unreachable("unsupported format bit-size"); break;
     79    };
     80 
     81    if (out_vk_format)
     82       *out_vk_format = vk_format;
     83 
     84    const struct v3dv_format *format = v3dv_X(device, get_format)(vk_format);
     85    assert(v3dv_X(device, tfu_supports_tex_format)(format->tex_type));
     86 
     87    return format;
     88 }
     89 
     90 static VkFormatFeatureFlags
     91 image_format_features(struct v3dv_physical_device *pdevice,
     92                       VkFormat vk_format,
     93                       const struct v3dv_format *v3dv_format,
     94                       VkImageTiling tiling)
     95 {
     96    if (!v3dv_format || !v3dv_format->supported)
     97       return 0;
     98 
     99    const VkImageAspectFlags aspects = vk_format_aspects(vk_format);
    100 
    101    const VkImageAspectFlags zs_aspects = VK_IMAGE_ASPECT_DEPTH_BIT |
    102                                          VK_IMAGE_ASPECT_STENCIL_BIT;
    103    const VkImageAspectFlags supported_aspects = VK_IMAGE_ASPECT_COLOR_BIT |
    104                                                 zs_aspects;
    105    if ((aspects & supported_aspects) != aspects)
    106       return 0;
    107 
    108    /* FIXME: We don't support separate stencil yet */
    109    if ((aspects & zs_aspects) == VK_IMAGE_ASPECT_STENCIL_BIT)
    110       return 0;
    111 
    112    if (v3dv_format->tex_type == TEXTURE_DATA_FORMAT_NO &&
    113        v3dv_format->rt_type == V3D_OUTPUT_IMAGE_FORMAT_NO) {
    114       return 0;
    115    }
    116 
    117    VkFormatFeatureFlags flags = 0;
    118 
    119    /* Raster format is only supported for 1D textures, so let's just
    120     * always require optimal tiling for anything that requires sampling.
    121     * Note: even if the user requests optimal for a 1D image, we will still
    122     * use raster format since that is what the HW requires.
    123     */
    124    if (v3dv_format->tex_type != TEXTURE_DATA_FORMAT_NO &&
    125        tiling == VK_IMAGE_TILING_OPTIMAL) {
    126       flags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
    127                VK_FORMAT_FEATURE_BLIT_SRC_BIT;
    128 
    129       if (v3dv_format->supports_filtering)
    130          flags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
    131    }
    132 
    133    if (v3dv_format->rt_type != V3D_OUTPUT_IMAGE_FORMAT_NO) {
    134       if (aspects & VK_IMAGE_ASPECT_COLOR_BIT) {
    135          flags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
    136                   VK_FORMAT_FEATURE_BLIT_DST_BIT;
    137          if (v3dv_X(pdevice, format_supports_blending)(v3dv_format))
    138             flags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
    139       } else if (aspects & zs_aspects) {
    140          flags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT |
    141                   VK_FORMAT_FEATURE_BLIT_DST_BIT;
    142       }
    143    }
    144 
    145    const struct util_format_description *desc =
    146       vk_format_description(vk_format);
    147    assert(desc);
    148 
    149    if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN && desc->is_array) {
    150       flags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
    151       if (desc->nr_channels == 1 && vk_format_is_int(vk_format))
    152          flags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;
    153    } else if (vk_format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 ||
    154               vk_format == VK_FORMAT_A2B10G10R10_UINT_PACK32 ||
    155               vk_format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
    156       /* To comply with shaderStorageImageExtendedFormats */
    157       flags |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
    158    }
    159 
    160    if (flags) {
    161       flags |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
    162                VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
    163    }
    164 
    165    return flags;
    166 }
    167 
    168 static VkFormatFeatureFlags
    169 buffer_format_features(VkFormat vk_format, const struct v3dv_format *v3dv_format)
    170 {
    171    if (!v3dv_format || !v3dv_format->supported)
    172       return 0;
    173 
    174    if (!v3dv_format->supported)
    175       return 0;
    176 
    177    /* We probably only want to support buffer formats that have a
    178     * color format specification.
    179     */
    180    if (!vk_format_is_color(vk_format))
    181       return 0;
    182 
    183    const struct util_format_description *desc =
    184       vk_format_description(vk_format);
    185    assert(desc);
    186 
    187    VkFormatFeatureFlags flags = 0;
    188    if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&
    189        desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB &&
    190        desc->is_array) {
    191       flags |=  VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
    192       if (v3dv_format->tex_type != TEXTURE_DATA_FORMAT_NO) {
    193          flags |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT |
    194                   VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;
    195       }
    196    } else if (vk_format == VK_FORMAT_A2B10G10R10_UNORM_PACK32) {
    197       flags |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT |
    198                VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT |
    199                VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;
    200    } else if (vk_format == VK_FORMAT_A2B10G10R10_UINT_PACK32 ||
    201               vk_format == VK_FORMAT_B10G11R11_UFLOAT_PACK32) {
    202       flags |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT |
    203                VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;
    204    }
    205 
    206    if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&
    207        desc->is_array &&
    208        desc->nr_channels == 1 &&
    209        vk_format_is_int(vk_format)) {
    210       flags |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT;
    211    }
    212 
    213    return flags;
    214 }
    215 
    216 bool
    217 v3dv_buffer_format_supports_features(struct v3dv_device *device,
    218                                      VkFormat vk_format,
    219                                      VkFormatFeatureFlags features)
    220 {
    221    const struct v3dv_format *v3dv_format = v3dv_X(device, get_format)(vk_format);
    222    const VkFormatFeatureFlags supported =
    223       buffer_format_features(vk_format, v3dv_format);
    224    return (supported & features) == features;
    225 }
    226 
    227 VKAPI_ATTR void VKAPI_CALL
    228 v3dv_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,
    229                                        VkFormat format,
    230                                        VkFormatProperties* pFormatProperties)
    231 {
    232    V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physicalDevice);
    233    const struct v3dv_format *v3dv_format = v3dv_X(pdevice, get_format)(format);
    234 
    235    *pFormatProperties = (VkFormatProperties) {
    236       .linearTilingFeatures =
    237          image_format_features(pdevice, format, v3dv_format, VK_IMAGE_TILING_LINEAR),
    238       .optimalTilingFeatures =
    239          image_format_features(pdevice, format, v3dv_format, VK_IMAGE_TILING_OPTIMAL),
    240       .bufferFeatures =
    241          buffer_format_features(format, v3dv_format),
    242    };
    243 }
    244 
    245 VKAPI_ATTR void VKAPI_CALL
    246 v3dv_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,
    247                                         VkFormat format,
    248                                         VkFormatProperties2 *pFormatProperties)
    249 {
    250    v3dv_GetPhysicalDeviceFormatProperties(physicalDevice, format,
    251                                           &pFormatProperties->formatProperties);
    252 
    253    vk_foreach_struct(ext, pFormatProperties->pNext) {
    254       switch ((unsigned)ext->sType) {
    255       case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT: {
    256          struct VkDrmFormatModifierPropertiesListEXT *list = (void *)ext;
    257          VK_OUTARRAY_MAKE(out, list->pDrmFormatModifierProperties,
    258                           &list->drmFormatModifierCount);
    259          if (pFormatProperties->formatProperties.linearTilingFeatures) {
    260             vk_outarray_append(&out, mod_props) {
    261                mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
    262                mod_props->drmFormatModifierPlaneCount = 1;
    263                mod_props->drmFormatModifierTilingFeatures =
    264                   pFormatProperties->formatProperties.linearTilingFeatures;
    265             }
    266          }
    267          if (pFormatProperties->formatProperties.optimalTilingFeatures) {
    268             vk_outarray_append(&out, mod_props) {
    269                mod_props->drmFormatModifier = DRM_FORMAT_MOD_BROADCOM_UIF;
    270                mod_props->drmFormatModifierPlaneCount = 1;
    271                mod_props->drmFormatModifierTilingFeatures =
    272                   pFormatProperties->formatProperties.optimalTilingFeatures;
    273             }
    274          }
    275          break;
    276       }
    277       default:
    278          v3dv_debug_ignored_stype(ext->sType);
    279          break;
    280       }
    281    }
    282 }
    283 
    284 static VkResult
    285 get_image_format_properties(
    286    struct v3dv_physical_device *physical_device,
    287    const VkPhysicalDeviceImageFormatInfo2 *info,
    288    VkImageTiling tiling,
    289    VkImageFormatProperties *pImageFormatProperties,
    290    VkSamplerYcbcrConversionImageFormatProperties *pYcbcrImageFormatProperties)
    291 {
    292    const struct v3dv_format *v3dv_format = v3dv_X(physical_device, get_format)(info->format);
    293    VkFormatFeatureFlags format_feature_flags =
    294       image_format_features(physical_device, info->format, v3dv_format, tiling);
    295    if (!format_feature_flags)
    296       goto unsupported;
    297 
    298    /* This allows users to create uncompressed views of compressed images,
    299     * however this is not something the hardware supports naturally and requires
    300     * the driver to lie when programming the texture state to make the hardware
    301     * sample with the uncompressed view correctly, and even then, there are
    302     * issues when running on real hardware.
    303     *
    304     * See https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11336
    305     * for details.
    306     */
    307    if (info->flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT)
    308       goto unsupported;
    309 
    310    if (info->usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
    311       if (!(format_feature_flags & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT)) {
    312          goto unsupported;
    313       }
    314 
    315       /* Sampling of raster depth/stencil images is not supported. Since 1D
    316        * images are always raster, even if the user requested optimal tiling,
    317        * we can't have them be used as transfer sources, since that includes
    318        * using them for blit sources, which might require sampling.
    319        */
    320       if (info->type == VK_IMAGE_TYPE_1D &&
    321           vk_format_is_depth_or_stencil(info->format)) {
    322          goto unsupported;
    323       }
    324    }
    325 
    326    if (info->usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
    327       if (!(format_feature_flags & VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) {
    328          goto unsupported;
    329       }
    330    }
    331 
    332    if (info->usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
    333       if (!(format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
    334          goto unsupported;
    335       }
    336 
    337       /* Sampling of raster depth/stencil images is not supported. Since 1D
    338        * images are always raster, even if the user requested optimal tiling,
    339        * we can't allow sampling if the format is depth/stencil.
    340        */
    341       if (info->type == VK_IMAGE_TYPE_1D &&
    342           vk_format_is_depth_or_stencil(info->format)) {
    343          goto unsupported;
    344       }
    345    }
    346 
    347    if (info->usage & VK_IMAGE_USAGE_STORAGE_BIT) {
    348       if (!(format_feature_flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {
    349          goto unsupported;
    350       }
    351    }
    352 
    353    if (info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
    354       if (!(format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
    355          goto unsupported;
    356       }
    357    }
    358 
    359    if (info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
    360       if (!(format_feature_flags &
    361             VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
    362          goto unsupported;
    363       }
    364    }
    365 
    366    /* FIXME: these are taken from VkPhysicalDeviceLimits, we should just put
    367     * these limits available in the physical device and read them from there
    368     * wherever we need them.
    369     */
    370    switch (info->type) {
    371    case VK_IMAGE_TYPE_1D:
    372       pImageFormatProperties->maxExtent.width = 4096;
    373       pImageFormatProperties->maxExtent.height = 1;
    374       pImageFormatProperties->maxExtent.depth = 1;
    375       pImageFormatProperties->maxArrayLayers = 2048;
    376       pImageFormatProperties->maxMipLevels = 13; /* log2(maxWidth) + 1 */
    377       break;
    378    case VK_IMAGE_TYPE_2D:
    379       pImageFormatProperties->maxExtent.width = 4096;
    380       pImageFormatProperties->maxExtent.height = 4096;
    381       pImageFormatProperties->maxExtent.depth = 1;
    382       pImageFormatProperties->maxArrayLayers = 2048;
    383       pImageFormatProperties->maxMipLevels = 13; /* log2(maxWidth) + 1 */
    384       break;
    385    case VK_IMAGE_TYPE_3D:
    386       pImageFormatProperties->maxExtent.width = 4096;
    387       pImageFormatProperties->maxExtent.height = 4096;
    388       pImageFormatProperties->maxExtent.depth = 4096;
    389       pImageFormatProperties->maxArrayLayers = 1;
    390       pImageFormatProperties->maxMipLevels = 13; /* log2(maxWidth) + 1 */
    391       break;
    392    default:
    393       unreachable("bad VkImageType");
    394    }
    395 
    396    /* Our hw doesn't support 1D compressed textures. */
    397    if (info->type == VK_IMAGE_TYPE_1D &&
    398        vk_format_is_compressed(info->format)) {
    399        goto unsupported;
    400    }
    401 
    402    /* From the Vulkan 1.0 spec, section 34.1.1. Supported Sample Counts:
    403     *
    404     * sampleCounts will be set to VK_SAMPLE_COUNT_1_BIT if at least one of the
    405     * following conditions is true:
    406     *
    407     *   - tiling is VK_IMAGE_TILING_LINEAR
    408     *   - type is not VK_IMAGE_TYPE_2D
    409     *   - flags contains VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
    410     *   - neither the VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT flag nor the
    411     *     VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT flag in
    412     *     VkFormatProperties::optimalTilingFeatures returned by
    413     *     vkGetPhysicalDeviceFormatProperties is set.
    414     */
    415    pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT;
    416    if (tiling != VK_IMAGE_TILING_LINEAR &&
    417        info->type == VK_IMAGE_TYPE_2D &&
    418        !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
    419        (format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT ||
    420         format_feature_flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
    421       pImageFormatProperties->sampleCounts |= VK_SAMPLE_COUNT_4_BIT;
    422    }
    423 
    424    if (tiling == VK_IMAGE_TILING_LINEAR)
    425       pImageFormatProperties->maxMipLevels = 1;
    426 
    427    pImageFormatProperties->maxResourceSize = 0xffffffff; /* 32-bit allocation */
    428 
    429    return VK_SUCCESS;
    430 
    431 unsupported:
    432    *pImageFormatProperties = (VkImageFormatProperties) {
    433       .maxExtent = { 0, 0, 0 },
    434       .maxMipLevels = 0,
    435       .maxArrayLayers = 0,
    436       .sampleCounts = 0,
    437       .maxResourceSize = 0,
    438    };
    439 
    440    return VK_ERROR_FORMAT_NOT_SUPPORTED;
    441 }
    442 
    443 static const VkExternalMemoryProperties prime_fd_props = {
    444    .externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
    445                              VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT,
    446    .exportFromImportedHandleTypes =
    447       VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
    448       VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
    449    .compatibleHandleTypes =
    450       VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
    451       VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
    452 };
    453 
    454 VKAPI_ATTR VkResult VKAPI_CALL
    455 v3dv_GetPhysicalDeviceImageFormatProperties(
    456    VkPhysicalDevice physicalDevice,
    457    VkFormat format,
    458    VkImageType type,
    459    VkImageTiling tiling,
    460    VkImageUsageFlags usage,
    461    VkImageCreateFlags createFlags,
    462    VkImageFormatProperties *pImageFormatProperties)
    463 {
    464    V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
    465 
    466    const VkPhysicalDeviceImageFormatInfo2 info = {
    467       .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
    468       .pNext = NULL,
    469       .format = format,
    470       .type = type,
    471       .tiling = tiling,
    472       .usage = usage,
    473       .flags = createFlags,
    474    };
    475 
    476    return get_image_format_properties(physical_device, &info, tiling,
    477                                       pImageFormatProperties, NULL);
    478 }
    479 
    480 VKAPI_ATTR VkResult VKAPI_CALL
    481 v3dv_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,
    482                                              const VkPhysicalDeviceImageFormatInfo2 *base_info,
    483                                              VkImageFormatProperties2 *base_props)
    484 {
    485    V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
    486    const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
    487    const VkPhysicalDeviceImageDrmFormatModifierInfoEXT *drm_format_mod_info = NULL;
    488    VkExternalImageFormatProperties *external_props = NULL;
    489    VkImageTiling tiling = base_info->tiling;
    490 
    491    /* Extract input structs */
    492    vk_foreach_struct_const(s, base_info->pNext) {
    493       switch (s->sType) {
    494       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
    495          external_info = (const void *) s;
    496          break;
    497       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT:
    498          drm_format_mod_info = (const void *) s;
    499          switch (drm_format_mod_info->drmFormatModifier) {
    500          case DRM_FORMAT_MOD_LINEAR:
    501             tiling = VK_IMAGE_TILING_LINEAR;
    502             break;
    503          case DRM_FORMAT_MOD_BROADCOM_UIF:
    504             tiling = VK_IMAGE_TILING_OPTIMAL;
    505             break;
    506          default:
    507             assert("Unknown DRM format modifier");
    508          }
    509          break;
    510       default:
    511          v3dv_debug_ignored_stype(s->sType);
    512          break;
    513       }
    514    }
    515 
    516    assert(tiling == VK_IMAGE_TILING_OPTIMAL ||
    517           tiling == VK_IMAGE_TILING_LINEAR);
    518 
    519    /* Extract output structs */
    520    vk_foreach_struct(s, base_props->pNext) {
    521       switch (s->sType) {
    522       case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
    523          external_props = (void *) s;
    524          break;
    525       default:
    526          v3dv_debug_ignored_stype(s->sType);
    527          break;
    528       }
    529    }
    530 
    531    VkResult result =
    532       get_image_format_properties(physical_device, base_info, tiling,
    533                                   &base_props->imageFormatProperties, NULL);
    534    if (result != VK_SUCCESS)
    535       goto done;
    536 
    537    if (external_info && external_info->handleType != 0) {
    538       switch (external_info->handleType) {
    539       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
    540       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
    541          if (external_props)
    542             external_props->externalMemoryProperties = prime_fd_props;
    543          break;
    544       default:
    545          result = VK_ERROR_FORMAT_NOT_SUPPORTED;
    546          break;
    547       }
    548    }
    549 
    550 done:
    551    return result;
    552 }
    553 
    554 VKAPI_ATTR void VKAPI_CALL
    555 v3dv_GetPhysicalDeviceSparseImageFormatProperties(
    556    VkPhysicalDevice physicalDevice,
    557    VkFormat format,
    558    VkImageType type,
    559    VkSampleCountFlagBits samples,
    560    VkImageUsageFlags usage,
    561    VkImageTiling tiling,
    562    uint32_t *pPropertyCount,
    563    VkSparseImageFormatProperties *pProperties)
    564 {
    565    *pPropertyCount = 0;
    566 }
    567 
    568 VKAPI_ATTR void VKAPI_CALL
    569 v3dv_GetPhysicalDeviceSparseImageFormatProperties2(
    570    VkPhysicalDevice physicalDevice,
    571    const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
    572    uint32_t *pPropertyCount,
    573    VkSparseImageFormatProperties2 *pProperties)
    574 {
    575    *pPropertyCount = 0;
    576 }
    577 
    578 VKAPI_ATTR void VKAPI_CALL
    579 v3dv_GetPhysicalDeviceExternalBufferProperties(
    580    VkPhysicalDevice physicalDevice,
    581    const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
    582    VkExternalBufferProperties *pExternalBufferProperties)
    583 {
    584    switch (pExternalBufferInfo->handleType) {
    585    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
    586    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
    587       pExternalBufferProperties->externalMemoryProperties = prime_fd_props;
    588       return;
    589    default: /* Unsupported */
    590       pExternalBufferProperties->externalMemoryProperties =
    591          (VkExternalMemoryProperties) {
    592             .compatibleHandleTypes = pExternalBufferInfo->handleType,
    593          };
    594       break;
    595    }
    596 }
    597