nvk: Add a more competent GetPhysicalDeviceImageFormatProperties
authorFaith Ekstrand <faith.ekstrand@collabora.com>
Tue, 31 Jan 2023 02:11:50 +0000 (20:11 -0600)
committerMarge Bot <emma+marge@anholt.net>
Fri, 4 Aug 2023 21:31:55 +0000 (21:31 +0000)
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>

src/nouveau/vulkan/nvk_image.c
src/nouveau/vulkan/nvk_physical_device.c

index 20cbe7c..a7ca98d 100644 (file)
@@ -103,6 +103,117 @@ nvk_get_image_format_features(struct nvk_physical_device *pdevice,
    return features;
 }
 
+static VkFormatFeatureFlags2KHR
+vk_image_usage_to_format_features(VkImageUsageFlagBits usage_flag)
+{
+   assert(util_bitcount(usage_flag) == 1);
+   switch (usage_flag) {
+   case VK_IMAGE_USAGE_TRANSFER_SRC_BIT:
+      return VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT_KHR |
+             VK_FORMAT_FEATURE_BLIT_SRC_BIT;
+   case VK_IMAGE_USAGE_TRANSFER_DST_BIT:
+      return VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT_KHR |
+             VK_FORMAT_FEATURE_BLIT_DST_BIT;
+   case VK_IMAGE_USAGE_SAMPLED_BIT:
+      return VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT;
+   case VK_IMAGE_USAGE_STORAGE_BIT:
+      return VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT;
+   case VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT:
+      return VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT;
+   case VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT:
+      return VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT;
+   default:
+      return 0;
+   }
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+nvk_GetPhysicalDeviceImageFormatProperties2(
+   VkPhysicalDevice physicalDevice,
+   const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
+   VkImageFormatProperties2 *pImageFormatProperties)
+{
+   VK_FROM_HANDLE(nvk_physical_device, pdevice, physicalDevice);
+
+   VkFormatFeatureFlags2KHR features =
+      nvk_get_image_format_features(pdevice, pImageFormatInfo->format,
+                                             pImageFormatInfo->tiling);
+   if (features == 0)
+      return VK_ERROR_FORMAT_NOT_SUPPORTED;
+
+   if (vk_format_is_compressed(pImageFormatInfo->format) &&
+       pImageFormatInfo->type != VK_IMAGE_TYPE_2D)
+      return VK_ERROR_FORMAT_NOT_SUPPORTED;
+
+   VkExtent3D maxExtent;
+   uint32_t maxMipLevels;
+   uint32_t maxArraySize;
+   VkSampleCountFlags sampleCounts;
+   switch (pImageFormatInfo->type) {
+   case VK_IMAGE_TYPE_1D:
+      maxExtent = (VkExtent3D) { 16384, 1, 1 },
+      maxMipLevels = 15;
+      maxArraySize = 2048;
+      sampleCounts = VK_SAMPLE_COUNT_1_BIT;
+      break;
+   case VK_IMAGE_TYPE_2D:
+      maxExtent = (VkExtent3D) { 16384, 16384, 1 };
+      maxMipLevels = 15;
+      maxArraySize = 2048;
+      sampleCounts = VK_SAMPLE_COUNT_1_BIT; /* TODO: MSAA */
+      break;
+   case VK_IMAGE_TYPE_3D:
+      maxExtent = (VkExtent3D) { 2048, 2048, 2048 };
+      maxMipLevels = 12;
+      maxArraySize = 1;
+      sampleCounts = VK_SAMPLE_COUNT_1_BIT;
+      break;
+   default:
+      unreachable("Invalid image type");
+   }
+
+   /* From the Vulkan 1.2.199 spec:
+    *
+    *    "VK_IMAGE_CREATE_EXTENDED_USAGE_BIT specifies that the image can be
+    *    created with usage flags that are not supported for the format the
+    *    image is created with but are supported for at least one format a
+    *    VkImageView created from the image can have."
+    *
+    * If VK_IMAGE_CREATE_EXTENDED_USAGE_BIT is set, views can be created with
+    * different usage than the image so we can't always filter on usage.
+    * There is one exception to this below for storage.
+    */
+   const VkImageUsageFlags image_usage = pImageFormatInfo->usage;
+   VkImageUsageFlags view_usage = image_usage;
+   if (pImageFormatInfo->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT)
+      view_usage = 0;
+
+   u_foreach_bit(b, view_usage) {
+      VkFormatFeatureFlags2KHR usage_features =
+         vk_image_usage_to_format_features(1 << b);
+      if (usage_features && !(features & usage_features))
+         return VK_ERROR_FORMAT_NOT_SUPPORTED;
+   }
+
+   pImageFormatProperties->imageFormatProperties = (VkImageFormatProperties) {
+      .maxExtent = maxExtent,
+      .maxMipLevels = maxMipLevels,
+      .maxArrayLayers = maxArraySize,
+      .sampleCounts = sampleCounts,
+      .maxResourceSize = UINT32_MAX, /* TODO */
+   };
+
+   vk_foreach_struct(s, pImageFormatProperties->pNext) {
+      switch (s->sType) {
+      default:
+         nvk_debug_ignored_stype(s->sType);
+         break;
+      }
+   }
+
+   return VK_SUCCESS;
+}
+
 static enum nil_image_dim
 vk_image_type_to_nil_dim(VkImageType type)
 {
index 14d7dc8..73e79e8 100644 (file)
@@ -409,51 +409,3 @@ nvk_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,
       p->queueFamilyProperties.minImageTransferGranularity = (VkExtent3D){1, 1, 1};
    }
 }
-
-VKAPI_ATTR VkResult VKAPI_CALL
-nvk_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice,
-   const VkPhysicalDeviceImageFormatInfo2 *base_info,
-   VkImageFormatProperties2 *base_props)
-{
-   if (base_info->usage & ~(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT))
-      return VK_ERROR_FORMAT_NOT_SUPPORTED;
-
-   const struct nvk_format *format = nvk_get_format(base_info->format);
-   if (format == NULL)
-      return VK_ERROR_FORMAT_NOT_SUPPORTED;
-
-   if (!format->supports_2d_blit)
-      return VK_ERROR_FORMAT_NOT_SUPPORTED;
-
-   if (base_info->type == VK_IMAGE_TYPE_1D)
-      base_props->imageFormatProperties.maxExtent = (VkExtent3D){32768, 1, 1};
-   else if (base_info->type == VK_IMAGE_TYPE_2D)
-      base_props->imageFormatProperties.maxExtent = (VkExtent3D){32768, 32768, 1};
-   else
-      return VK_ERROR_FORMAT_NOT_SUPPORTED;
-
-   base_props->imageFormatProperties.maxMipLevels = 15;
-   base_props->imageFormatProperties.maxArrayLayers = 2048;
-   base_props->imageFormatProperties.sampleCounts = 0;
-   base_props->imageFormatProperties.maxResourceSize = 0xffffffff; // TODO proper value
-
-   vk_foreach_struct(s, base_props->pNext) {
-      switch (s->sType) {
-      default:
-         nvk_debug_ignored_stype(s->sType);
-         break;
-      }
-   }
-
-   vk_foreach_struct(ext, base_info->pNext)
-   {
-      /* Use unsigned since some cases are not in the VkStructureType enum. */
-      switch ((unsigned)ext->sType) {
-      default:
-         nvk_debug_ignored_stype(ext->sType);
-         break;
-      }
-   }
-
-   return VK_SUCCESS;
-}