nvk: Add a more competent GetPhysicalDeviceImageFormatProperties

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>
This commit is contained in:
Faith Ekstrand 2023-01-30 20:11:50 -06:00 committed by Marge Bot
parent fc19173014
commit 20d8d1e239
2 changed files with 111 additions and 48 deletions

View 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)
{

View 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;
}