diff --git a/src/panfrost/vulkan/panvk_image.c b/src/panfrost/vulkan/panvk_image.c index 821684ff151..36184cd8582 100644 --- a/src/panfrost/vulkan/panvk_image.c +++ b/src/panfrost/vulkan/panvk_image.c @@ -54,29 +54,35 @@ panvk_image_can_use_afbc( { unsigned arch = pan_arch(phys_dev->kmod.props.gpu_id); struct panvk_instance *instance = to_panvk_instance(phys_dev->vk.instance); - enum pipe_format pfmt = vk_format_to_pipe_format(fmt); /* Disallow AFBC if either of these is true * - PANVK_DEBUG does not have the 'afbc' flag set * - storage image views are requested * - host image copies are requested - * - the GPU doesn't support AFBC - * - the format is not AFBC-able - * - tiling is set to linear - * - this is a 1D image - * - this is a 3D image on a pre-v7 GPU - * - this is a mutable format image on v7 + * - this is a mutable format image on v7 (the BGR emulation we have with + * the texture swizzle gets in the way). + * + * Other hardware constraints are checked by the mod handler. */ - return - (instance->debug_flags & PANVK_DEBUG_AFBC) && - !(usage & (VK_IMAGE_USAGE_STORAGE_BIT | - VK_IMAGE_USAGE_HOST_TRANSFER_BIT)) && - pan_query_afbc(&phys_dev->kmod.props) && - pan_afbc_supports_format(arch, pfmt) && - tiling == VK_IMAGE_TILING_OPTIMAL && - type != VK_IMAGE_TYPE_1D && - (type != VK_IMAGE_TYPE_3D || arch >= 7) && - (!(flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) || arch != 7); + return (instance->debug_flags & PANVK_DEBUG_AFBC) && + !(usage & + (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_HOST_TRANSFER_BIT)) && + (!(flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) || arch != 7); +} + +static enum mali_texture_dimension +panvk_image_type_to_mali_tex_dim(VkImageType type) +{ + switch (type) { + case VK_IMAGE_TYPE_1D: + return MALI_TEXTURE_DIMENSION_1D; + case VK_IMAGE_TYPE_2D: + return MALI_TEXTURE_DIMENSION_2D; + case VK_IMAGE_TYPE_3D: + return MALI_TEXTURE_DIMENSION_3D; + default: + UNREACHABLE("Invalid image type"); + } } static bool @@ -86,7 +92,6 @@ panvk_image_can_use_mod(struct panvk_image *image, uint64_t mod) to_panvk_physical_device(image->vk.base.device->physical); struct panvk_instance *instance = to_panvk_instance(image->vk.base.device->physical->instance); - enum pipe_format pfmt = vk_format_to_pipe_format(image->vk.format); bool forced_linear = (instance->debug_flags & PANVK_DEBUG_LINEAR) || image->vk.tiling == VK_IMAGE_TILING_LINEAR || image->vk.image_type == VK_IMAGE_TYPE_1D; @@ -96,43 +101,10 @@ panvk_image_can_use_mod(struct panvk_image *image, uint64_t mod) if (forced_linear) return mod == DRM_FORMAT_MOD_LINEAR; - if (drm_is_afbc(mod)) { - if (!panvk_image_can_use_afbc( - phys_dev, image->vk.format, - image->vk.usage | image->vk.stencil_usage, image->vk.image_type, - image->vk.tiling, image->vk.create_flags)) - return false; - - /* AFBC is not supported for multisample images - * - * This is not checked in panvk_image_can_use_afbc because the sample - * count is not known in vkGetPhysicalDeviceImageFormatProperties2. */ - if (image->vk.samples > 1) - return false; - - const struct util_format_description *fdesc = - util_format_description(pfmt); - bool is_rgb = fdesc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || - fdesc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB; - - if ((mod & AFBC_FORMAT_MOD_YTR) && (!is_rgb || fdesc->nr_channels >= 3)) - return false; - - /* AFBC headers point to their tile with a 32-bit offset, so we can't - * have a body size that's bigger than UINT32_MAX. */ - uint64_t body_size = (uint64_t)image->vk.extent.width * - image->vk.extent.height * image->vk.extent.depth * - util_format_get_blocksize(pfmt); - if (body_size > UINT32_MAX) - return false; - - /* We assume all other unsupported AFBC modes have been filtered out - * through pan_best_modifiers[]. */ - return true; - } - - /* Some formats can only be used with AFBC. */ - if (!pan_u_tiled_or_linear_supports_format(pfmt)) + if (drm_is_afbc(mod) && + !panvk_image_can_use_afbc( + phys_dev, image->vk.format, image->vk.usage | image->vk.stencil_usage, + image->vk.image_type, image->vk.tiling, image->vk.create_flags)) return false; if (mod == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) { @@ -157,8 +129,42 @@ panvk_image_can_use_mod(struct panvk_image *image, uint64_t mod) VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT); } - /* If we get there, it must be linear to be supported. */ - return mod == DRM_FORMAT_MOD_LINEAR; + /* Defer the rest of the checks to the mod handler. */ + struct pan_image_props iprops = { + .modifier = mod, + .format = vk_format_to_pipe_format(image->vk.format), + .dim = panvk_image_type_to_mali_tex_dim(image->vk.image_type), + .array_size = image->vk.array_layers, + .nr_samples = image->vk.samples, + .nr_slices = image->vk.mip_levels, + }; + const unsigned plane_count = + image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT + ? 2 + : vk_format_get_plane_count(image->vk.format); + + for (uint8_t plane = 0; plane < plane_count; plane++) { + VkFormat format; + + if (image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT) + format = plane == 0 ? VK_FORMAT_D32_SFLOAT : VK_FORMAT_S8_UINT; + else + format = vk_format_get_plane_format(image->vk.format, plane); + + iprops.format = vk_format_to_pipe_format(format); + iprops.extent_px = (struct pan_image_extent){ + .width = vk_format_get_plane_width(image->vk.format, plane, + image->vk.extent.width), + .height = vk_format_get_plane_height(image->vk.format, plane, + image->vk.extent.height), + .depth = image->vk.extent.depth, + }; + + if (!pan_image_test_props(&phys_dev->kmod.props, &iprops)) + return false; + } + + return true; } static uint64_t @@ -226,21 +232,6 @@ panvk_image_get_mod(struct panvk_image *image, return panvk_image_get_mod_from_list(image, NULL, 0); } -static enum mali_texture_dimension -panvk_image_type_to_mali_tex_dim(VkImageType type) -{ - switch (type) { - case VK_IMAGE_TYPE_1D: - return MALI_TEXTURE_DIMENSION_1D; - case VK_IMAGE_TYPE_2D: - return MALI_TEXTURE_DIMENSION_2D; - case VK_IMAGE_TYPE_3D: - return MALI_TEXTURE_DIMENSION_3D; - default: - UNREACHABLE("Invalid image type"); - } -} - static bool is_disjoint(const struct panvk_image *image) {