mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-02-03 15:10:37 +01:00
panvk: Rework the modifier selection
We move the modifier selection after the panvk_image initialization so we have less VkXxx objects to retrieve, and split the 3 cases (explicit modifier, explicit modifier list ordered by preference and driver auto-selection based on the image attributes) to make things clearer. We also check formats against the pan_best_modifiers array which is sorted by GPU order of preference and serve as an is_valid_modifier() too. Finally, we add the following new constraints on u-tiled/AFBC: - don't allow u-tiled on images with compressed formats that might have non-compressed views - don't allow u-tiled or AFBC on 1D images Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Mary Guillemard <mary.guillemard@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29451>
This commit is contained in:
parent
f74dd596d5
commit
38258138ad
1 changed files with 159 additions and 122 deletions
|
|
@ -38,6 +38,8 @@
|
|||
#include "drm-uapi/drm_fourcc.h"
|
||||
#include "util/u_atomic.h"
|
||||
#include "util/u_debug.h"
|
||||
#include "util/u_drm.h"
|
||||
|
||||
#include "vk_format.h"
|
||||
#include "vk_log.h"
|
||||
#include "vk_object.h"
|
||||
|
|
@ -45,6 +47,156 @@
|
|||
|
||||
#define PANVK_MAX_PLANES 1
|
||||
|
||||
static bool
|
||||
panvk_image_can_use_mod(struct panvk_image *image, uint64_t mod)
|
||||
{
|
||||
struct panvk_physical_device *phys_dev =
|
||||
to_panvk_physical_device(image->vk.base.device->physical);
|
||||
unsigned arch = pan_arch(phys_dev->kmod.props.gpu_prod_id);
|
||||
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;
|
||||
|
||||
/* If the image is meant to be linear, don't bother testing the
|
||||
* other cases. */
|
||||
if (forced_linear)
|
||||
return mod == DRM_FORMAT_MOD_LINEAR;
|
||||
|
||||
if (drm_is_afbc(mod)) {
|
||||
/* Disallow AFBC if either of these is true
|
||||
* - PANVK_DEBUG does not have the 'afbc' flag set
|
||||
* - storage image views are requested
|
||||
* - this is a multisample image
|
||||
* - 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
|
||||
*/
|
||||
if (!(instance->debug_flags & PANVK_DEBUG_AFBC) ||
|
||||
((image->vk.usage | image->vk.stencil_usage) &
|
||||
VK_IMAGE_USAGE_STORAGE_BIT) ||
|
||||
image->vk.samples > 1 ||
|
||||
!panfrost_query_afbc(&phys_dev->kmod.props) ||
|
||||
!panfrost_format_supports_afbc(arch, pfmt) ||
|
||||
image->vk.tiling == VK_IMAGE_TILING_LINEAR ||
|
||||
image->vk.image_type == VK_IMAGE_TYPE_1D ||
|
||||
(image->vk.image_type == VK_IMAGE_TYPE_3D && arch < 7))
|
||||
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;
|
||||
|
||||
/* We assume all other unsupported AFBC modes have been filtered out
|
||||
* through pan_best_modifiers[]. */
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mod == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
|
||||
/* If we're dealing with a compressed format that requires non-compressed
|
||||
* views we can't use U_INTERLEAVED tiling because the tiling is different
|
||||
* between compressed and non-compressed formats. If we wanted to support
|
||||
* format re-interpretation we would have to specialize the shaders
|
||||
* accessing non-compressed image views (coordinate patching for
|
||||
* sampled/storage image, frag_coord patching for color attachments). Let's
|
||||
* keep things simple for now and make all compressed images that
|
||||
* have VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT set linear. */
|
||||
return !(image->vk.create_flags &
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
panvk_image_apply_explicit_mod(
|
||||
struct panvk_image *image,
|
||||
const VkImageDrmFormatModifierExplicitCreateInfoEXT *explicit)
|
||||
{
|
||||
struct panvk_physical_device *phys_dev =
|
||||
to_panvk_physical_device(image->vk.base.device->physical);
|
||||
unsigned arch = pan_arch(phys_dev->kmod.props.gpu_prod_id);
|
||||
uint64_t mod = explicit->drmFormatModifier;
|
||||
|
||||
/* TODO: support arrays, 3D, multisample and depth-stencil. */
|
||||
struct pan_image_explicit_layout plane0_layout = {
|
||||
.offset = explicit->pPlaneLayouts[0].offset,
|
||||
.row_stride = explicit->pPlaneLayouts[0].rowPitch,
|
||||
};
|
||||
|
||||
assert(!vk_format_is_depth_or_stencil(image->vk.format));
|
||||
assert(image->vk.samples == 1);
|
||||
assert(image->vk.array_layers == 1);
|
||||
assert(image->vk.image_type != VK_IMAGE_TYPE_3D);
|
||||
assert(explicit->drmFormatModifierPlaneCount == 1);
|
||||
assert(panvk_image_can_use_mod(image, mod));
|
||||
|
||||
image->pimage.layout.modifier = mod;
|
||||
pan_image_layout_init(arch, &image->pimage.layout, &plane0_layout);
|
||||
}
|
||||
|
||||
static void
|
||||
panvk_image_select_mod_from_list(struct panvk_image *image,
|
||||
const uint64_t *mods, uint32_t mod_count)
|
||||
{
|
||||
struct panvk_physical_device *phys_dev =
|
||||
to_panvk_physical_device(image->vk.base.device->physical);
|
||||
unsigned arch = pan_arch(phys_dev->kmod.props.gpu_prod_id);
|
||||
|
||||
for (unsigned i = 0; i < PAN_MODIFIER_COUNT; ++i) {
|
||||
if (!panvk_image_can_use_mod(image, pan_best_modifiers[i]))
|
||||
continue;
|
||||
|
||||
if (!mod_count ||
|
||||
drm_find_modifier(pan_best_modifiers[i], mods, mod_count)) {
|
||||
image->pimage.layout.modifier = pan_best_modifiers[i];
|
||||
pan_image_layout_init(arch, &image->pimage.layout, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we reached that point without finding a proper modifier, there's
|
||||
* a serious issue. */
|
||||
image->pimage.layout.modifier = DRM_FORMAT_MOD_INVALID;
|
||||
assert(!"Invalid modifier");
|
||||
}
|
||||
|
||||
static void
|
||||
panvk_image_select_mod(struct panvk_image *image,
|
||||
const VkImageCreateInfo *pCreateInfo)
|
||||
{
|
||||
if (pCreateInfo->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
|
||||
const VkImageDrmFormatModifierListCreateInfoEXT *mod_list =
|
||||
vk_find_struct_const(pCreateInfo->pNext,
|
||||
IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
|
||||
const VkImageDrmFormatModifierExplicitCreateInfoEXT *explicit_mod =
|
||||
vk_find_struct_const(
|
||||
pCreateInfo->pNext,
|
||||
IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);
|
||||
|
||||
if (explicit_mod)
|
||||
panvk_image_apply_explicit_mod(image, explicit_mod);
|
||||
else if (mod_list)
|
||||
panvk_image_select_mod_from_list(image, mod_list->pDrmFormatModifiers,
|
||||
mod_list->drmFormatModifierCount);
|
||||
else
|
||||
assert(!"Missing modifier info");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
panvk_image_select_mod_from_list(image, NULL, 0);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
panvk_image_get_total_size(const struct panvk_image *image)
|
||||
{
|
||||
|
|
@ -67,22 +219,18 @@ panvk_image_type_to_mali_tex_dim(VkImageType type)
|
|||
}
|
||||
}
|
||||
|
||||
static VkResult
|
||||
panvk_image_create(VkDevice _device, const VkImageCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *alloc, VkImage *pImage,
|
||||
uint64_t modifier, const VkSubresourceLayout *plane_layouts)
|
||||
VKAPI_ATTR VkResult VKAPI_CALL
|
||||
panvk_CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator, VkImage *pImage)
|
||||
{
|
||||
VK_FROM_HANDLE(panvk_device, device, _device);
|
||||
struct panvk_physical_device *phys_dev =
|
||||
to_panvk_physical_device(device->vk.physical);
|
||||
struct panvk_image *image = NULL;
|
||||
VK_FROM_HANDLE(panvk_device, dev, device);
|
||||
|
||||
image = vk_image_create(&device->vk, pCreateInfo, alloc, sizeof(*image));
|
||||
struct panvk_image *image =
|
||||
vk_image_create(&dev->vk, pCreateInfo, pAllocator, sizeof(*image));
|
||||
if (!image)
|
||||
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
image->pimage.layout = (struct pan_image_layout){
|
||||
.modifier = modifier,
|
||||
.format = vk_format_to_pipe_format(image->vk.format),
|
||||
.dim = panvk_image_type_to_mali_tex_dim(image->vk.image_type),
|
||||
.width = image->vk.extent.width,
|
||||
|
|
@ -93,123 +241,12 @@ panvk_image_create(VkDevice _device, const VkImageCreateInfo *pCreateInfo,
|
|||
.nr_slices = image->vk.mip_levels,
|
||||
};
|
||||
|
||||
unsigned arch = pan_arch(phys_dev->kmod.props.gpu_prod_id);
|
||||
pan_image_layout_init(arch, &image->pimage.layout, NULL);
|
||||
panvk_image_select_mod(image, pCreateInfo);
|
||||
|
||||
*pImage = panvk_image_to_handle(image);
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
panvk_image_select_mod(VkDevice _device, const VkImageCreateInfo *pCreateInfo,
|
||||
const VkSubresourceLayout **plane_layouts)
|
||||
{
|
||||
VK_FROM_HANDLE(panvk_device, device, _device);
|
||||
struct panvk_instance *instance =
|
||||
to_panvk_instance(device->vk.physical->instance);
|
||||
struct panvk_physical_device *phys_dev =
|
||||
to_panvk_physical_device(device->vk.physical);
|
||||
enum pipe_format fmt = vk_format_to_pipe_format(pCreateInfo->format);
|
||||
bool noafbc = !(instance->debug_flags & PANVK_DEBUG_AFBC);
|
||||
bool linear = instance->debug_flags & PANVK_DEBUG_LINEAR;
|
||||
|
||||
*plane_layouts = NULL;
|
||||
|
||||
if (pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR)
|
||||
return DRM_FORMAT_MOD_LINEAR;
|
||||
|
||||
if (pCreateInfo->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
|
||||
const VkImageDrmFormatModifierListCreateInfoEXT *mod_info =
|
||||
vk_find_struct_const(pCreateInfo->pNext,
|
||||
IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
|
||||
const VkImageDrmFormatModifierExplicitCreateInfoEXT *drm_explicit_info =
|
||||
vk_find_struct_const(
|
||||
pCreateInfo->pNext,
|
||||
IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);
|
||||
|
||||
assert(mod_info || drm_explicit_info);
|
||||
|
||||
uint64_t modifier;
|
||||
|
||||
if (mod_info) {
|
||||
modifier = DRM_FORMAT_MOD_LINEAR;
|
||||
for (unsigned i = 0; i < mod_info->drmFormatModifierCount; i++) {
|
||||
if (drm_is_afbc(mod_info->pDrmFormatModifiers[i]) && !noafbc) {
|
||||
modifier = mod_info->pDrmFormatModifiers[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
modifier = drm_explicit_info->drmFormatModifier;
|
||||
assert(modifier == DRM_FORMAT_MOD_LINEAR ||
|
||||
modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED ||
|
||||
(drm_is_afbc(modifier) && !noafbc));
|
||||
*plane_layouts = drm_explicit_info->pPlaneLayouts;
|
||||
}
|
||||
|
||||
return modifier;
|
||||
}
|
||||
|
||||
const struct wsi_image_create_info *wsi_info =
|
||||
vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);
|
||||
if (wsi_info && wsi_info->scanout)
|
||||
return DRM_FORMAT_MOD_LINEAR;
|
||||
|
||||
assert(pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL);
|
||||
|
||||
if (linear)
|
||||
return DRM_FORMAT_MOD_LINEAR;
|
||||
|
||||
/* Image store don't work on AFBC images */
|
||||
if (pCreateInfo->usage & VK_IMAGE_USAGE_STORAGE_BIT)
|
||||
return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
|
||||
|
||||
/* AFBC does not support layered multisampling */
|
||||
if (pCreateInfo->samples > 1)
|
||||
return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
|
||||
|
||||
if (!panfrost_query_afbc(&phys_dev->kmod.props))
|
||||
return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
|
||||
|
||||
/* Only a small selection of formats are AFBC'able */
|
||||
unsigned arch = pan_arch(phys_dev->kmod.props.gpu_prod_id);
|
||||
if (!panfrost_format_supports_afbc(arch, fmt))
|
||||
return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
|
||||
|
||||
/* 3D AFBC is only supported on Bifrost v7+. It's supposed to
|
||||
* be supported on Midgard but it doesn't seem to work.
|
||||
*/
|
||||
if (pCreateInfo->imageType == VK_IMAGE_TYPE_3D && arch < 7)
|
||||
return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
|
||||
|
||||
/* For one tile, AFBC is a loss compared to u-interleaved */
|
||||
if (pCreateInfo->extent.width <= 16 && pCreateInfo->extent.height <= 16)
|
||||
return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
|
||||
|
||||
if (noafbc)
|
||||
return DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
|
||||
|
||||
uint64_t afbc_type =
|
||||
AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_SPARSE;
|
||||
|
||||
if (panfrost_afbc_can_ytr(fmt))
|
||||
afbc_type |= AFBC_FORMAT_MOD_YTR;
|
||||
|
||||
return DRM_FORMAT_MOD_ARM_AFBC(afbc_type);
|
||||
}
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL
|
||||
panvk_CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator, VkImage *pImage)
|
||||
{
|
||||
const VkSubresourceLayout *plane_layouts;
|
||||
uint64_t modifier =
|
||||
panvk_image_select_mod(device, pCreateInfo, &plane_layouts);
|
||||
|
||||
return panvk_image_create(device, pCreateInfo, pAllocator, pImage, modifier,
|
||||
plane_layouts);
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
panvk_DestroyImage(VkDevice _device, VkImage _image,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue