v3dv_formats.c revision 7ec681f3
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
32const uint8_t *
33v3dv_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
44uint8_t
45v3dv_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 */
66const struct v3dv_format *
67v3dv_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
90static VkFormatFeatureFlags
91image_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
168static VkFormatFeatureFlags
169buffer_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
216bool
217v3dv_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
227VKAPI_ATTR void VKAPI_CALL
228v3dv_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
245VKAPI_ATTR void VKAPI_CALL
246v3dv_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
284static VkResult
285get_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
431unsupported:
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
443static 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
454VKAPI_ATTR VkResult VKAPI_CALL
455v3dv_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
480VKAPI_ATTR VkResult VKAPI_CALL
481v3dv_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
550done:
551   return result;
552}
553
554VKAPI_ATTR void VKAPI_CALL
555v3dv_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
568VKAPI_ATTR void VKAPI_CALL
569v3dv_GetPhysicalDeviceSparseImageFormatProperties2(
570   VkPhysicalDevice physicalDevice,
571   const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
572   uint32_t *pPropertyCount,
573   VkSparseImageFormatProperties2 *pProperties)
574{
575   *pPropertyCount = 0;
576}
577
578VKAPI_ATTR void VKAPI_CALL
579v3dv_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