17ec681f3Smrg/*
27ec681f3Smrg * Copyright © 2021 Collabora Ltd.
37ec681f3Smrg *
47ec681f3Smrg * Derived from tu_formats.c which is:
57ec681f3Smrg * Copyright © 2016 Red Hat.
67ec681f3Smrg * Copyright © 2016 Bas Nieuwenhuizen
77ec681f3Smrg *
87ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
97ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
107ec681f3Smrg * to deal in the Software without restriction, including without limitation
117ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
127ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
137ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
147ec681f3Smrg *
157ec681f3Smrg * The above copyright notice and this permission notice (including the next
167ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
177ec681f3Smrg * Software.
187ec681f3Smrg *
197ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
207ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
217ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
227ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
237ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
247ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
257ec681f3Smrg * DEALINGS IN THE SOFTWARE.
267ec681f3Smrg */
277ec681f3Smrg
287ec681f3Smrg#include "panvk_private.h"
297ec681f3Smrg
307ec681f3Smrg#include "util/format_r11g11b10f.h"
317ec681f3Smrg#include "util/format_srgb.h"
327ec681f3Smrg#include "util/half_float.h"
337ec681f3Smrg#include "vulkan/util/vk_format.h"
347ec681f3Smrg#include "vk_format.h"
357ec681f3Smrg#include "vk_util.h"
367ec681f3Smrg#include "panfrost/lib/pan_texture.h"
377ec681f3Smrg
387ec681f3Smrgstatic void
397ec681f3Smrgget_format_properties(struct panvk_physical_device *physical_device,
407ec681f3Smrg                      VkFormat format,
417ec681f3Smrg                      VkFormatProperties *out_properties)
427ec681f3Smrg{
437ec681f3Smrg   struct panfrost_device *pdev = &physical_device->pdev;
447ec681f3Smrg   VkFormatFeatureFlags tex = 0, buffer = 0;
457ec681f3Smrg   enum pipe_format pfmt = vk_format_to_pipe_format(format);
467ec681f3Smrg   const struct panfrost_format fmt = pdev->formats[pfmt];
477ec681f3Smrg
487ec681f3Smrg   if (!pfmt || !fmt.hw)
497ec681f3Smrg      goto end;
507ec681f3Smrg
517ec681f3Smrg   /* 3byte formats are not supported by the buffer <-> image copy helpers. */
527ec681f3Smrg   if (util_format_get_blocksize(pfmt) == 3)
537ec681f3Smrg      goto end;
547ec681f3Smrg
557ec681f3Smrg   /* We don't support compressed formats yet: this is causing trouble when
567ec681f3Smrg    * doing a vkCmdCopyImage() between a compressed and a non-compressed format
577ec681f3Smrg    * on a tiled/AFBC resource.
587ec681f3Smrg    */
597ec681f3Smrg   if (util_format_is_compressed(pfmt))
607ec681f3Smrg      goto end;
617ec681f3Smrg
627ec681f3Smrg   buffer |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
637ec681f3Smrg             VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
647ec681f3Smrg
657ec681f3Smrg   if (fmt.bind & PIPE_BIND_VERTEX_BUFFER)
667ec681f3Smrg      buffer |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
677ec681f3Smrg
687ec681f3Smrg   if (fmt.bind & PIPE_BIND_SAMPLER_VIEW) {
697ec681f3Smrg      tex |= VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
707ec681f3Smrg             VK_FORMAT_FEATURE_TRANSFER_DST_BIT |
717ec681f3Smrg             VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
727ec681f3Smrg             VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT |
737ec681f3Smrg             VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT;
747ec681f3Smrg
757ec681f3Smrg      /* Integer formats only support nearest filtering */
767ec681f3Smrg      if (!util_format_is_scaled(pfmt) &&
777ec681f3Smrg          !util_format_is_pure_integer(pfmt))
787ec681f3Smrg         tex |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
797ec681f3Smrg
807ec681f3Smrg      buffer |= VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;
817ec681f3Smrg
827ec681f3Smrg      tex |= VK_FORMAT_FEATURE_BLIT_SRC_BIT;
837ec681f3Smrg   }
847ec681f3Smrg
857ec681f3Smrg   if (fmt.bind & PIPE_BIND_RENDER_TARGET) {
867ec681f3Smrg      tex |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
877ec681f3Smrg             VK_FORMAT_FEATURE_BLIT_DST_BIT;
887ec681f3Smrg
897ec681f3Smrg      tex |= VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
907ec681f3Smrg      buffer |= VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT;
917ec681f3Smrg
927ec681f3Smrg      /* Can always blend via blend shaders */
937ec681f3Smrg      tex |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
947ec681f3Smrg   }
957ec681f3Smrg
967ec681f3Smrg   if (fmt.bind & PIPE_BIND_DEPTH_STENCIL)
977ec681f3Smrg         tex |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
987ec681f3Smrg
997ec681f3Smrgend:
1007ec681f3Smrg   out_properties->linearTilingFeatures = tex;
1017ec681f3Smrg   out_properties->optimalTilingFeatures = tex;
1027ec681f3Smrg   out_properties->bufferFeatures = buffer;
1037ec681f3Smrg}
1047ec681f3Smrg
1057ec681f3Smrgvoid
1067ec681f3Smrgpanvk_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,
1077ec681f3Smrg                                      VkFormat format,
1087ec681f3Smrg                                      VkFormatProperties *pFormatProperties)
1097ec681f3Smrg{
1107ec681f3Smrg   VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice);
1117ec681f3Smrg
1127ec681f3Smrg   get_format_properties(physical_device, format, pFormatProperties);
1137ec681f3Smrg}
1147ec681f3Smrg
1157ec681f3Smrgvoid
1167ec681f3Smrgpanvk_GetPhysicalDeviceFormatProperties2(VkPhysicalDevice physicalDevice,
1177ec681f3Smrg                                         VkFormat format,
1187ec681f3Smrg                                         VkFormatProperties2 *pFormatProperties)
1197ec681f3Smrg{
1207ec681f3Smrg   VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice);
1217ec681f3Smrg
1227ec681f3Smrg   get_format_properties(physical_device, format,
1237ec681f3Smrg                         &pFormatProperties->formatProperties);
1247ec681f3Smrg
1257ec681f3Smrg   VkDrmFormatModifierPropertiesListEXT *list =
1267ec681f3Smrg      vk_find_struct(pFormatProperties->pNext, DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT);
1277ec681f3Smrg   if (list) {
1287ec681f3Smrg      VK_OUTARRAY_MAKE(out, list->pDrmFormatModifierProperties,
1297ec681f3Smrg                       &list->drmFormatModifierCount);
1307ec681f3Smrg
1317ec681f3Smrg      vk_outarray_append(&out, mod_props) {
1327ec681f3Smrg         mod_props->drmFormatModifier = DRM_FORMAT_MOD_LINEAR;
1337ec681f3Smrg         mod_props->drmFormatModifierPlaneCount = 1;
1347ec681f3Smrg      }
1357ec681f3Smrg   }
1367ec681f3Smrg}
1377ec681f3Smrg
1387ec681f3Smrgstatic VkResult
1397ec681f3Smrgget_image_format_properties(struct panvk_physical_device *physical_device,
1407ec681f3Smrg                            const VkPhysicalDeviceImageFormatInfo2 *info,
1417ec681f3Smrg                            VkImageFormatProperties *pImageFormatProperties,
1427ec681f3Smrg                            VkFormatFeatureFlags *p_feature_flags)
1437ec681f3Smrg{
1447ec681f3Smrg   VkFormatProperties format_props;
1457ec681f3Smrg   VkFormatFeatureFlags format_feature_flags;
1467ec681f3Smrg   VkExtent3D maxExtent;
1477ec681f3Smrg   uint32_t maxMipLevels;
1487ec681f3Smrg   uint32_t maxArraySize;
1497ec681f3Smrg   VkSampleCountFlags sampleCounts = VK_SAMPLE_COUNT_1_BIT;
1507ec681f3Smrg   enum pipe_format format = vk_format_to_pipe_format(info->format);
1517ec681f3Smrg
1527ec681f3Smrg   get_format_properties(physical_device, info->format, &format_props);
1537ec681f3Smrg
1547ec681f3Smrg   switch (info->tiling) {
1557ec681f3Smrg   case VK_IMAGE_TILING_LINEAR:
1567ec681f3Smrg      format_feature_flags = format_props.linearTilingFeatures;
1577ec681f3Smrg      break;
1587ec681f3Smrg
1597ec681f3Smrg   case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT:
1607ec681f3Smrg      /* The only difference between optimal and linear is currently whether
1617ec681f3Smrg       * depth/stencil attachments are allowed on depth/stencil formats.
1627ec681f3Smrg       * There's no reason to allow importing depth/stencil textures, so just
1637ec681f3Smrg       * disallow it and then this annoying edge case goes away.
1647ec681f3Smrg       *
1657ec681f3Smrg       * TODO: If anyone cares, we could enable this by looking at the
1667ec681f3Smrg       * modifier and checking if it's LINEAR or not.
1677ec681f3Smrg       */
1687ec681f3Smrg      if (util_format_is_depth_or_stencil(format))
1697ec681f3Smrg         goto unsupported;
1707ec681f3Smrg
1717ec681f3Smrg      assert(format_props.optimalTilingFeatures == format_props.linearTilingFeatures);
1727ec681f3Smrg      /* fallthrough */
1737ec681f3Smrg   case VK_IMAGE_TILING_OPTIMAL:
1747ec681f3Smrg      format_feature_flags = format_props.optimalTilingFeatures;
1757ec681f3Smrg      break;
1767ec681f3Smrg   default:
1777ec681f3Smrg      unreachable("bad VkPhysicalDeviceImageFormatInfo2");
1787ec681f3Smrg   }
1797ec681f3Smrg
1807ec681f3Smrg   if (format_feature_flags == 0)
1817ec681f3Smrg      goto unsupported;
1827ec681f3Smrg
1837ec681f3Smrg   if (info->type != VK_IMAGE_TYPE_2D &&
1847ec681f3Smrg       util_format_is_depth_or_stencil(format))
1857ec681f3Smrg      goto unsupported;
1867ec681f3Smrg
1877ec681f3Smrg   switch (info->type) {
1887ec681f3Smrg   default:
1897ec681f3Smrg      unreachable("bad vkimage type");
1907ec681f3Smrg   case VK_IMAGE_TYPE_1D:
1917ec681f3Smrg      maxExtent.width = 16384;
1927ec681f3Smrg      maxExtent.height = 1;
1937ec681f3Smrg      maxExtent.depth = 1;
1947ec681f3Smrg      maxMipLevels = 15; /* log2(maxWidth) + 1 */
1957ec681f3Smrg      maxArraySize = 2048;
1967ec681f3Smrg      break;
1977ec681f3Smrg   case VK_IMAGE_TYPE_2D:
1987ec681f3Smrg      maxExtent.width = 16384;
1997ec681f3Smrg      maxExtent.height = 16384;
2007ec681f3Smrg      maxExtent.depth = 1;
2017ec681f3Smrg      maxMipLevels = 15; /* log2(maxWidth) + 1 */
2027ec681f3Smrg      maxArraySize = 2048;
2037ec681f3Smrg      break;
2047ec681f3Smrg   case VK_IMAGE_TYPE_3D:
2057ec681f3Smrg      maxExtent.width = 2048;
2067ec681f3Smrg      maxExtent.height = 2048;
2077ec681f3Smrg      maxExtent.depth = 2048;
2087ec681f3Smrg      maxMipLevels = 12; /* log2(maxWidth) + 1 */
2097ec681f3Smrg      maxArraySize = 1;
2107ec681f3Smrg      break;
2117ec681f3Smrg   }
2127ec681f3Smrg
2137ec681f3Smrg   if (info->tiling == VK_IMAGE_TILING_OPTIMAL &&
2147ec681f3Smrg       info->type == VK_IMAGE_TYPE_2D &&
2157ec681f3Smrg       (format_feature_flags &
2167ec681f3Smrg        (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
2177ec681f3Smrg         VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) &&
2187ec681f3Smrg       !(info->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
2197ec681f3Smrg       !(info->usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
2207ec681f3Smrg      sampleCounts |= VK_SAMPLE_COUNT_4_BIT;
2217ec681f3Smrg   }
2227ec681f3Smrg
2237ec681f3Smrg   if (info->usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
2247ec681f3Smrg      if (!(format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
2257ec681f3Smrg         goto unsupported;
2267ec681f3Smrg      }
2277ec681f3Smrg   }
2287ec681f3Smrg
2297ec681f3Smrg   if (info->usage & VK_IMAGE_USAGE_STORAGE_BIT) {
2307ec681f3Smrg      if (!(format_feature_flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) {
2317ec681f3Smrg         goto unsupported;
2327ec681f3Smrg      }
2337ec681f3Smrg   }
2347ec681f3Smrg
2357ec681f3Smrg   if (info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
2367ec681f3Smrg      if (!(format_feature_flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) {
2377ec681f3Smrg         goto unsupported;
2387ec681f3Smrg      }
2397ec681f3Smrg   }
2407ec681f3Smrg
2417ec681f3Smrg   if (info->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
2427ec681f3Smrg      if (!(format_feature_flags &
2437ec681f3Smrg            VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
2447ec681f3Smrg         goto unsupported;
2457ec681f3Smrg      }
2467ec681f3Smrg   }
2477ec681f3Smrg
2487ec681f3Smrg   *pImageFormatProperties = (VkImageFormatProperties) {
2497ec681f3Smrg      .maxExtent = maxExtent,
2507ec681f3Smrg      .maxMipLevels = maxMipLevels,
2517ec681f3Smrg      .maxArrayLayers = maxArraySize,
2527ec681f3Smrg      .sampleCounts = sampleCounts,
2537ec681f3Smrg
2547ec681f3Smrg      /* FINISHME: Accurately calculate
2557ec681f3Smrg       * VkImageFormatProperties::maxResourceSize.
2567ec681f3Smrg       */
2577ec681f3Smrg      .maxResourceSize = UINT32_MAX,
2587ec681f3Smrg   };
2597ec681f3Smrg
2607ec681f3Smrg   if (p_feature_flags)
2617ec681f3Smrg      *p_feature_flags = format_feature_flags;
2627ec681f3Smrg
2637ec681f3Smrg   return VK_SUCCESS;
2647ec681f3Smrgunsupported:
2657ec681f3Smrg   *pImageFormatProperties = (VkImageFormatProperties) {
2667ec681f3Smrg      .maxExtent = { 0, 0, 0 },
2677ec681f3Smrg      .maxMipLevels = 0,
2687ec681f3Smrg      .maxArrayLayers = 0,
2697ec681f3Smrg      .sampleCounts = 0,
2707ec681f3Smrg      .maxResourceSize = 0,
2717ec681f3Smrg   };
2727ec681f3Smrg
2737ec681f3Smrg   return VK_ERROR_FORMAT_NOT_SUPPORTED;
2747ec681f3Smrg}
2757ec681f3Smrg
2767ec681f3Smrg
2777ec681f3SmrgVkResult
2787ec681f3Smrgpanvk_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice,
2797ec681f3Smrg                                            VkFormat format,
2807ec681f3Smrg                                            VkImageType type,
2817ec681f3Smrg                                            VkImageTiling tiling,
2827ec681f3Smrg                                            VkImageUsageFlags usage,
2837ec681f3Smrg                                            VkImageCreateFlags createFlags,
2847ec681f3Smrg                                            VkImageFormatProperties *pImageFormatProperties)
2857ec681f3Smrg{
2867ec681f3Smrg   VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice);
2877ec681f3Smrg
2887ec681f3Smrg   const VkPhysicalDeviceImageFormatInfo2 info = {
2897ec681f3Smrg      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
2907ec681f3Smrg      .pNext = NULL,
2917ec681f3Smrg      .format = format,
2927ec681f3Smrg      .type = type,
2937ec681f3Smrg      .tiling = tiling,
2947ec681f3Smrg      .usage = usage,
2957ec681f3Smrg      .flags = createFlags,
2967ec681f3Smrg   };
2977ec681f3Smrg
2987ec681f3Smrg   return get_image_format_properties(physical_device, &info,
2997ec681f3Smrg                                      pImageFormatProperties, NULL);
3007ec681f3Smrg}
3017ec681f3Smrg
3027ec681f3Smrgstatic VkResult
3037ec681f3Smrgpanvk_get_external_image_format_properties(const struct panvk_physical_device *physical_device,
3047ec681f3Smrg                                           const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
3057ec681f3Smrg                                           VkExternalMemoryHandleTypeFlagBits handleType,
3067ec681f3Smrg                                           VkExternalMemoryProperties *external_properties)
3077ec681f3Smrg{
3087ec681f3Smrg   VkExternalMemoryFeatureFlagBits flags = 0;
3097ec681f3Smrg   VkExternalMemoryHandleTypeFlags export_flags = 0;
3107ec681f3Smrg   VkExternalMemoryHandleTypeFlags compat_flags = 0;
3117ec681f3Smrg
3127ec681f3Smrg   /* From the Vulkan 1.1.98 spec:
3137ec681f3Smrg    *
3147ec681f3Smrg    *    If handleType is not compatible with the format, type, tiling,
3157ec681f3Smrg    *    usage, and flags specified in VkPhysicalDeviceImageFormatInfo2,
3167ec681f3Smrg    *    then vkGetPhysicalDeviceImageFormatProperties2 returns
3177ec681f3Smrg    *    VK_ERROR_FORMAT_NOT_SUPPORTED.
3187ec681f3Smrg    */
3197ec681f3Smrg   switch (handleType) {
3207ec681f3Smrg   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
3217ec681f3Smrg   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
3227ec681f3Smrg      switch (pImageFormatInfo->type) {
3237ec681f3Smrg      case VK_IMAGE_TYPE_2D:
3247ec681f3Smrg         flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT |
3257ec681f3Smrg                 VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
3267ec681f3Smrg                 VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
3277ec681f3Smrg         compat_flags = export_flags =
3287ec681f3Smrg            VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
3297ec681f3Smrg            VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
3307ec681f3Smrg         break;
3317ec681f3Smrg      default:
3327ec681f3Smrg         return vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED,
3337ec681f3Smrg                          "VkExternalMemoryTypeFlagBits(0x%x) unsupported for VkImageType(%d)",
3347ec681f3Smrg                          handleType, pImageFormatInfo->type);
3357ec681f3Smrg      }
3367ec681f3Smrg      break;
3377ec681f3Smrg   case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
3387ec681f3Smrg      flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT;
3397ec681f3Smrg      compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
3407ec681f3Smrg      break;
3417ec681f3Smrg   default:
3427ec681f3Smrg      return vk_errorf(physical_device, VK_ERROR_FORMAT_NOT_SUPPORTED,
3437ec681f3Smrg                       "VkExternalMemoryTypeFlagBits(0x%x) unsupported",
3447ec681f3Smrg                       handleType);
3457ec681f3Smrg   }
3467ec681f3Smrg
3477ec681f3Smrg   *external_properties = (VkExternalMemoryProperties) {
3487ec681f3Smrg      .externalMemoryFeatures = flags,
3497ec681f3Smrg      .exportFromImportedHandleTypes = export_flags,
3507ec681f3Smrg      .compatibleHandleTypes = compat_flags,
3517ec681f3Smrg   };
3527ec681f3Smrg
3537ec681f3Smrg   return VK_SUCCESS;
3547ec681f3Smrg}
3557ec681f3Smrg
3567ec681f3SmrgVkResult
3577ec681f3Smrgpanvk_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,
3587ec681f3Smrg                                              const VkPhysicalDeviceImageFormatInfo2 *base_info,
3597ec681f3Smrg                                              VkImageFormatProperties2 *base_props)
3607ec681f3Smrg{
3617ec681f3Smrg   VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice);
3627ec681f3Smrg   const VkPhysicalDeviceExternalImageFormatInfo *external_info = NULL;
3637ec681f3Smrg   const VkPhysicalDeviceImageViewImageFormatInfoEXT *image_view_info = NULL;
3647ec681f3Smrg   VkExternalImageFormatProperties *external_props = NULL;
3657ec681f3Smrg   VkFilterCubicImageViewImageFormatPropertiesEXT *cubic_props = NULL;
3667ec681f3Smrg   VkFormatFeatureFlags format_feature_flags;
3677ec681f3Smrg   VkSamplerYcbcrConversionImageFormatProperties *ycbcr_props = NULL;
3687ec681f3Smrg   VkResult result;
3697ec681f3Smrg
3707ec681f3Smrg   result = get_image_format_properties(physical_device, base_info,
3717ec681f3Smrg                                        &base_props->imageFormatProperties,
3727ec681f3Smrg                                        &format_feature_flags);
3737ec681f3Smrg   if (result != VK_SUCCESS)
3747ec681f3Smrg      return result;
3757ec681f3Smrg
3767ec681f3Smrg   /* Extract input structs */
3777ec681f3Smrg   vk_foreach_struct_const(s, base_info->pNext)
3787ec681f3Smrg   {
3797ec681f3Smrg      switch (s->sType) {
3807ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO:
3817ec681f3Smrg         external_info = (const void *) s;
3827ec681f3Smrg         break;
3837ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT:
3847ec681f3Smrg         image_view_info = (const void *) s;
3857ec681f3Smrg         break;
3867ec681f3Smrg      default:
3877ec681f3Smrg         break;
3887ec681f3Smrg      }
3897ec681f3Smrg   }
3907ec681f3Smrg
3917ec681f3Smrg   /* Extract output structs */
3927ec681f3Smrg   vk_foreach_struct(s, base_props->pNext)
3937ec681f3Smrg   {
3947ec681f3Smrg      switch (s->sType) {
3957ec681f3Smrg      case VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES:
3967ec681f3Smrg         external_props = (void *) s;
3977ec681f3Smrg         break;
3987ec681f3Smrg      case VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT:
3997ec681f3Smrg         cubic_props = (void *) s;
4007ec681f3Smrg         break;
4017ec681f3Smrg      case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES:
4027ec681f3Smrg         ycbcr_props = (void *) s;
4037ec681f3Smrg         break;
4047ec681f3Smrg      default:
4057ec681f3Smrg         break;
4067ec681f3Smrg      }
4077ec681f3Smrg   }
4087ec681f3Smrg
4097ec681f3Smrg   /* From the Vulkan 1.0.42 spec:
4107ec681f3Smrg    *
4117ec681f3Smrg    *    If handleType is 0, vkGetPhysicalDeviceImageFormatProperties2 will
4127ec681f3Smrg    *    behave as if VkPhysicalDeviceExternalImageFormatInfo was not
4137ec681f3Smrg    *    present and VkExternalImageFormatProperties will be ignored.
4147ec681f3Smrg    */
4157ec681f3Smrg   if (external_info && external_info->handleType != 0) {
4167ec681f3Smrg      result = panvk_get_external_image_format_properties(physical_device,
4177ec681f3Smrg                                                          base_info,
4187ec681f3Smrg                                                          external_info->handleType,
4197ec681f3Smrg                                                          &external_props->externalMemoryProperties);
4207ec681f3Smrg      if (result != VK_SUCCESS)
4217ec681f3Smrg         goto fail;
4227ec681f3Smrg   }
4237ec681f3Smrg
4247ec681f3Smrg   if (cubic_props) {
4257ec681f3Smrg      /* note: blob only allows cubic filtering for 2D and 2D array views
4267ec681f3Smrg       * its likely we can enable it for 1D and CUBE, needs testing however
4277ec681f3Smrg       */
4287ec681f3Smrg      if ((image_view_info->imageViewType == VK_IMAGE_VIEW_TYPE_2D ||
4297ec681f3Smrg           image_view_info->imageViewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY) &&
4307ec681f3Smrg          (format_feature_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT)) {
4317ec681f3Smrg         cubic_props->filterCubic = true;
4327ec681f3Smrg         cubic_props->filterCubicMinmax = true;
4337ec681f3Smrg      } else {
4347ec681f3Smrg         cubic_props->filterCubic = false;
4357ec681f3Smrg         cubic_props->filterCubicMinmax = false;
4367ec681f3Smrg      }
4377ec681f3Smrg   }
4387ec681f3Smrg
4397ec681f3Smrg   if (ycbcr_props)
4407ec681f3Smrg      ycbcr_props->combinedImageSamplerDescriptorCount = 1;
4417ec681f3Smrg
4427ec681f3Smrg   return VK_SUCCESS;
4437ec681f3Smrg
4447ec681f3Smrgfail:
4457ec681f3Smrg   if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) {
4467ec681f3Smrg      /* From the Vulkan 1.0.42 spec:
4477ec681f3Smrg       *
4487ec681f3Smrg       *    If the combination of parameters to
4497ec681f3Smrg       *    vkGetPhysicalDeviceImageFormatProperties2 is not supported by
4507ec681f3Smrg       *    the implementation for use in vkCreateImage, then all members of
4517ec681f3Smrg       *    imageFormatProperties will be filled with zero.
4527ec681f3Smrg       */
4537ec681f3Smrg      base_props->imageFormatProperties = (VkImageFormatProperties) {};
4547ec681f3Smrg   }
4557ec681f3Smrg
4567ec681f3Smrg   return result;
4577ec681f3Smrg}
4587ec681f3Smrg
4597ec681f3Smrgvoid
4607ec681f3Smrgpanvk_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,
4617ec681f3Smrg                                                   VkFormat format,
4627ec681f3Smrg                                                   VkImageType type,
4637ec681f3Smrg                                                   uint32_t samples,
4647ec681f3Smrg                                                   VkImageUsageFlags usage,
4657ec681f3Smrg                                                   VkImageTiling tiling,
4667ec681f3Smrg                                                   uint32_t *pNumProperties,
4677ec681f3Smrg                                                   VkSparseImageFormatProperties *pProperties)
4687ec681f3Smrg{
4697ec681f3Smrg   panvk_stub();
4707ec681f3Smrg}
4717ec681f3Smrg
4727ec681f3Smrgvoid
4737ec681f3Smrgpanvk_GetPhysicalDeviceSparseImageFormatProperties2(VkPhysicalDevice physicalDevice,
4747ec681f3Smrg                                                    const VkPhysicalDeviceSparseImageFormatInfo2 *pFormatInfo,
4757ec681f3Smrg                                                    uint32_t *pPropertyCount,
4767ec681f3Smrg                                                    VkSparseImageFormatProperties2 *pProperties)
4777ec681f3Smrg{
4787ec681f3Smrg   panvk_stub();
4797ec681f3Smrg}
4807ec681f3Smrg
4817ec681f3Smrgvoid
4827ec681f3Smrgpanvk_GetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice physicalDevice,
4837ec681f3Smrg                                                const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo,
4847ec681f3Smrg                                                VkExternalBufferProperties *pExternalBufferProperties)
4857ec681f3Smrg{
4867ec681f3Smrg   panvk_stub();
4877ec681f3Smrg}
488