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 *
v3dv_get_format_swizzle(struct v3dv_device * device,VkFormat f)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
v3dv_get_tex_return_size(const struct v3dv_format * vf,bool compare_enable)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 *
v3dv_get_compatible_tfu_format(struct v3dv_device * device,uint32_t bpp,VkFormat * out_vk_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
image_format_features(struct v3dv_physical_device * pdevice,VkFormat vk_format,const struct v3dv_format * v3dv_format,VkImageTiling tiling)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
buffer_format_features(VkFormat vk_format,const struct v3dv_format * v3dv_format)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
v3dv_buffer_format_supports_features(struct v3dv_device * device,VkFormat vk_format,VkFormatFeatureFlags features)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
v3dv_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties * pFormatProperties)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
v3dv_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,VkFormat format,VkFormatProperties2 * pFormatProperties)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
get_image_format_properties(struct v3dv_physical_device * physical_device,const VkPhysicalDeviceImageFormatInfo2 * info,VkImageTiling tiling,VkImageFormatProperties * pImageFormatProperties,VkSamplerYcbcrConversionImageFormatProperties * pYcbcrImageFormatProperties)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
v3dv_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkImageTiling tiling,VkImageUsageFlags usage,VkImageCreateFlags createFlags,VkImageFormatProperties * pImageFormatProperties)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
v3dv_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceImageFormatInfo2 * base_info,VkImageFormatProperties2 * base_props)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
v3dv_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,VkFormat format,VkImageType type,VkSampleCountFlagBits samples,VkImageUsageFlags usage,VkImageTiling tiling,uint32_t * pPropertyCount,VkSparseImageFormatProperties * pProperties)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
v3dv_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo,uint32_t * pPropertyCount,VkSparseImageFormatProperties2 * pProperties)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
v3dv_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalBufferInfo * pExternalBufferInfo,VkExternalBufferProperties * pExternalBufferProperties)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