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)
{
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;
-}