pan/format: Draw a clear line between native and emulated modifiers

Mali GPUs don't support DRM_FORMAT_MOD_MTK_16L_32S_TILE natively, so
it doesn't make sense to teach the common layer about this format,
especially since it would require adding more hacks to make sense of
the tiled -> linear view of such resources.

Given the only user of this format is the gallium driver, move the
MTK_TILED definitions there and start differentiating native and
emulated modifiers.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Tested-by: Eric R. Smith <eric.smith@collabora.com>
Reviewed-by: Eric R. Smith <eric.smith@collabora.com>
Reviewed-by: Mary Guillemard <mary.guillemard@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35015>
This commit is contained in:
Boris Brezillon 2025-05-21 17:04:57 +02:00 committed by Marge Bot
parent cf3ec8d3b9
commit ce197c8018
8 changed files with 129 additions and 76 deletions

View file

@ -1697,7 +1697,7 @@ panfrost_create_sampler_view_bo(struct panfrost_sampler_view *so,
so->texture_bo = prsrc->image.data.base;
so->texture_size = prsrc->image.layout.data_size_B;
so->modifier = prsrc->image.props.modifier;
so->modifier = prsrc->modifier;
/* MSAA only supported for 2D textures */
@ -1820,7 +1820,7 @@ panfrost_create_sampler_view_bo(struct panfrost_sampler_view *so,
util_format_description(format);
if ((device->debug & PAN_DBG_YUV) && pan_format_is_yuv(format) &&
!(is_shadow && pan_format_supports_mtk_tiled(format))) {
!(is_shadow && panfrost_format_supports_mtk_tiled(format))) {
if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) {
iview.swizzle[1] = PIPE_SWIZZLE_0;
iview.swizzle[2] = PIPE_SWIZZLE_1;
@ -1846,7 +1846,7 @@ panfrost_update_sampler_view(struct panfrost_sampler_view *view,
struct panfrost_resource *rsrc = pan_resource(view->base.texture);
if (view->texture_bo != rsrc->image.data.base ||
view->texture_size != rsrc->image.layout.data_size_B ||
view->modifier != rsrc->image.props.modifier) {
view->modifier != rsrc->modifier) {
panfrost_bo_unreference(view->state.bo);
panfrost_create_sampler_view_bo(view, pctx, &rsrc->base);
}

View file

@ -278,8 +278,7 @@ panfrost_set_shader_images(struct pipe_context *pctx,
/* Images don't work with AFBC/AFRC, since they require pixel-level
* granularity */
if (drm_is_afbc(rsrc->image.props.modifier) ||
drm_is_afrc(rsrc->image.props.modifier)) {
if (drm_is_afbc(rsrc->modifier) || drm_is_afrc(rsrc->modifier)) {
pan_resource_modifier_convert(
ctx, rsrc, DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED, true,
"Shader image");

View file

@ -449,7 +449,7 @@ panfrost_get_mod_convert_shaders(struct panfrost_context *ctx,
{
struct pipe_context *pctx = &ctx->base;
struct panfrost_screen *screen = pan_screen(ctx->base.screen);
bool tiled = rsrc->image.props.modifier & AFBC_FORMAT_MOD_TILED;
bool tiled = rsrc->modifier & AFBC_FORMAT_MOD_TILED;
struct pan_mod_convert_shader_key key = {
.bpp = util_format_get_blocksizebits(rsrc->base.format),
.align = align,

View file

@ -28,6 +28,8 @@
#include "panfrost/util/pan_ir.h"
#include "drm-uapi/drm_fourcc.h"
struct panfrost_context;
struct panfrost_resource;
struct panfrost_screen;
@ -84,4 +86,40 @@ struct pan_mod_convert_shader_data *
panfrost_get_mod_convert_shaders(struct panfrost_context *ctx,
struct panfrost_resource *rsrc, unsigned align);
#define drm_is_mtk_tiled(mod) \
((mod >> 52) == (0 | (DRM_FORMAT_MOD_VENDOR_MTK << 4)))
/* check for whether a format can be used with MTK_16L32S format */
static inline bool
panfrost_format_supports_mtk_tiled(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_NV12:
case PIPE_FORMAT_R8_G8B8_420_UNORM:
case PIPE_FORMAT_R8_UNORM:
case PIPE_FORMAT_R8G8_UNORM:
return true;
default:
return false;
}
}
#define PANFROST_EMULATED_MODIFIERS(__name) \
static const uint64_t __name[] = { \
DRM_FORMAT_MOD_MTK_16L_32S_TILE, \
}
static inline bool panfrost_is_emulated_mod(uint64_t mod)
{
PANFROST_EMULATED_MODIFIERS(emulated_mods);
for (unsigned i = 0; i < ARRAY_SIZE(emulated_mods); i++) {
if (emulated_mods[i] == mod)
return true;
}
return false;
}
#endif

View file

@ -136,8 +136,11 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen,
.row_pitch_B = whandle->stride,
};
rsc->modifier = mod;
rsc->image.props = (struct pan_image_props){
.modifier = mod,
/* pan_layout doesn't know about MTK modifiers, so make it
* linear before calling pan_image_layout_init(). */
.modifier = panfrost_is_emulated_mod(mod) ? DRM_FORMAT_MOD_LINEAR : mod,
.format = templat->format,
.dim = dim,
.extent_px = {
@ -199,7 +202,7 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen,
rsrc = pan_resource(plane_res);
scanout = rsrc->scanout;
handle->modifier = rsrc->image.props.modifier;
handle->modifier = rsrc->modifier;
rsrc->modifier_constant = true;
if (handle->type == WINSYS_HANDLE_TYPE_KMS && dev->ro) {
@ -249,7 +252,7 @@ panfrost_resource_get_param(struct pipe_screen *pscreen,
.offset_B;
return true;
case PIPE_RESOURCE_PARAM_MODIFIER:
*value = rsrc->image.props.modifier;
*value = rsrc->modifier;
return true;
case PIPE_RESOURCE_PARAM_NPLANES:
*value = util_resource_num(prsc);
@ -397,9 +400,9 @@ panfrost_should_pack_afbc(struct panfrost_device *dev,
PIPE_BIND_SAMPLER_VIEW;
return pan_afbc_can_pack(prsrc->base.format) && panfrost_is_2d(prsrc) &&
drm_is_afbc(prsrc->image.props.modifier) &&
(prsrc->image.props.modifier & AFBC_FORMAT_MOD_SPARSE) &&
!(prsrc->image.props.modifier & AFBC_FORMAT_MOD_SPLIT) &&
drm_is_afbc(prsrc->modifier) &&
(prsrc->modifier & AFBC_FORMAT_MOD_SPARSE) &&
!(prsrc->modifier & AFBC_FORMAT_MOD_SPLIT) &&
(prsrc->base.bind & ~valid_binding) == 0 &&
!prsrc->modifier_constant && prsrc->base.array_size == 1 &&
prsrc->base.width0 >= 32 && prsrc->base.height0 >= 32 ;
@ -571,8 +574,10 @@ panfrost_resource_setup(struct pipe_screen *screen,
if (fmt == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)
fmt = PIPE_FORMAT_Z32_FLOAT;
pres->modifier = chosen_mod;
pres->image.props = (struct pan_image_props){
.modifier = chosen_mod,
.modifier = panfrost_is_emulated_mod(chosen_mod) ? DRM_FORMAT_MOD_LINEAR
: chosen_mod,
.format = fmt,
.dim = dim,
.extent_px = {
@ -872,7 +877,7 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen,
so->constant_stencil = true;
}
if (drm_is_afbc(so->image.props.modifier)) {
if (drm_is_afbc(so->modifier)) {
if (panfrost_resource_init_afbc_headers(so)) {
FREE(so);
return NULL;
@ -905,12 +910,20 @@ panfrost_resource_create_with_modifiers(struct pipe_screen *screen,
const struct pipe_resource *template,
const uint64_t *modifiers, int count)
{
PAN_SUPPORTED_MODIFIERS(supported_mods);
PANFROST_EMULATED_MODIFIERS(emulated_mods);
PAN_SUPPORTED_MODIFIERS(native_mods);
for (unsigned i = 0; i < ARRAY_SIZE(supported_mods); ++i) {
if (drm_find_modifier(supported_mods[i], modifiers, count)) {
for (unsigned i = 0; i < ARRAY_SIZE(native_mods); ++i) {
if (drm_find_modifier(native_mods[i], modifiers, count)) {
return panfrost_resource_create_with_modifier(screen, template,
supported_mods[i]);
native_mods[i]);
}
}
for (unsigned i = 0; i < ARRAY_SIZE(emulated_mods); ++i) {
if (drm_find_modifier(emulated_mods[i], modifiers, count)) {
return panfrost_resource_create_with_modifier(screen, template,
emulated_mods[i]);
}
}
@ -1100,7 +1113,7 @@ dump_block(struct panfrost_resource *rsrc, uint32_t idx)
uint32_t body_base_ptr = header[0];
uint32_t *body = (uint32_t *)(ptr + body_base_ptr);
struct pan_image_block_size block_sz =
pan_afbc_subblock_size(rsrc->image.props.modifier);
pan_afbc_subblock_size(rsrc->modifier);
unsigned pixel_sz = util_format_get_blocksize(rsrc->base.format);
unsigned uncompressed_size = pixel_sz * block_sz.width * block_sz.height;
unsigned size = get_superblock_size(header, uncompressed_size);
@ -1129,7 +1142,7 @@ pan_dump_resource(struct panfrost_context *ctx, struct panfrost_resource *rsc)
struct pipe_box box;
char buffer[1024];
if (rsc->image.props.modifier != DRM_FORMAT_MOD_LINEAR) {
if (rsc->modifier != DRM_FORMAT_MOD_LINEAR) {
tmpl.bind |= PIPE_BIND_LINEAR;
tmpl.bind &= ~PAN_BIND_SHARED_MASK;
@ -1249,7 +1262,7 @@ panfrost_ptr_map(struct pipe_context *pctx, struct pipe_resource *resource,
/* Can't map tiled/compressed directly */
if ((usage & PIPE_MAP_DIRECTLY) &&
rsrc->image.props.modifier != DRM_FORMAT_MOD_LINEAR)
rsrc->modifier != DRM_FORMAT_MOD_LINEAR)
return NULL;
struct panfrost_transfer *transfer = rzalloc(pctx, struct panfrost_transfer);
@ -1264,8 +1277,8 @@ panfrost_ptr_map(struct pipe_context *pctx, struct pipe_resource *resource,
rsrc->constant_stencil = false;
/* We don't have s/w routines for AFBC/AFRC, so use a staging texture */
if (drm_is_afbc(rsrc->image.props.modifier) ||
drm_is_afrc(rsrc->image.props.modifier)) {
if (drm_is_afbc(rsrc->modifier) ||
drm_is_afrc(rsrc->modifier)) {
struct panfrost_resource *staging =
pan_alloc_staging(ctx, rsrc, level, box);
assert(staging);
@ -1392,7 +1405,7 @@ panfrost_ptr_map(struct pipe_context *pctx, struct pipe_resource *resource,
rsrc->bo = newbo;
rsrc->image.data.base = newbo->ptr.gpu;
if (!copy_resource && drm_is_afbc(rsrc->image.props.modifier)) {
if (!copy_resource && drm_is_afbc(rsrc->modifier)) {
if (panfrost_resource_init_afbc_headers(rsrc))
return NULL;
}
@ -1425,7 +1438,7 @@ panfrost_ptr_map(struct pipe_context *pctx, struct pipe_resource *resource,
struct pipe_box box_blocks;
u_box_pixels_to_blocks(&box_blocks, box, format);
switch(rsrc->image.props.modifier) {
switch(rsrc->modifier) {
case DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED:
case DRM_FORMAT_MOD_MTK_16L_32S_TILE:
transfer->base.stride = box_blocks.width * bytes_per_block;
@ -1438,7 +1451,7 @@ panfrost_ptr_map(struct pipe_context *pctx, struct pipe_resource *resource,
return transfer->map;
default:
assert(rsrc->image.props.modifier == DRM_FORMAT_MOD_LINEAR);
assert(rsrc->modifier == DRM_FORMAT_MOD_LINEAR);
/* Direct, persistent writes create holes in time for
* caching... I don't know if this is actually possible but we
@ -1488,7 +1501,7 @@ pan_resource_modifier_convert(struct panfrost_context *ctx,
if (template.next) {
struct pipe_resource second_template = *template.next;
bool fix_stride;
assert(drm_is_mtk_tiled(rsrc->image.props.modifier));
assert(drm_is_mtk_tiled(rsrc->modifier));
/* fix up the stride */
switch (rsrc->base.format) {
case PIPE_FORMAT_R8_G8B8_420_UNORM:
@ -1548,7 +1561,7 @@ pan_resource_modifier_convert(struct panfrost_context *ctx,
util_num_layers(&rsrc->base, i), &blit.dst.box);
blit.src.box = blit.dst.box;
if (drm_is_mtk_tiled(rsrc->image.props.modifier))
if (drm_is_mtk_tiled(rsrc->modifier))
screen->vtbl.mtk_detile(ctx, &blit);
else
panfrost_blit_no_afbc_legalization(&ctx->base, &blit);
@ -1598,21 +1611,21 @@ pan_legalize_format(struct panfrost_context *ctx,
bool compatible = true;
uint64_t dest_modifier = DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
if (!drm_is_afbc(rsrc->image.props.modifier) &&
!drm_is_afrc(rsrc->image.props.modifier) &&
!drm_is_mtk_tiled(rsrc->image.props.modifier))
if (!drm_is_afbc(rsrc->modifier) &&
!drm_is_afrc(rsrc->modifier) &&
!drm_is_mtk_tiled(rsrc->modifier))
return;
if (drm_is_afbc(rsrc->image.props.modifier)) {
if (drm_is_afbc(rsrc->modifier)) {
compatible = (pan_afbc_format(dev->arch, old_format) ==
pan_afbc_format(dev->arch, new_format));
} else if (drm_is_afrc(rsrc->image.props.modifier)) {
} else if (drm_is_afrc(rsrc->modifier)) {
struct pan_afrc_format_info old_info =
pan_afrc_get_format_info(old_format);
struct pan_afrc_format_info new_info =
pan_afrc_get_format_info(new_format);
compatible = !memcmp(&old_info, &new_info, sizeof(old_info));
} else if (drm_is_mtk_tiled(rsrc->image.props.modifier)) {
} else if (drm_is_mtk_tiled(rsrc->modifier)) {
compatible = false;
dest_modifier = DRM_FORMAT_MOD_LINEAR;
}
@ -1620,18 +1633,18 @@ pan_legalize_format(struct panfrost_context *ctx,
if (!compatible) {
pan_resource_modifier_convert(
ctx, rsrc, dest_modifier, !discard,
drm_is_afbc(rsrc->image.props.modifier)
drm_is_afbc(rsrc->modifier)
? "Reinterpreting AFBC surface as incompatible format"
: "Reinterpreting tiled surface as incompatible format");
return;
}
/* Can't write to AFBC-P resources */
if (write && drm_is_afbc(rsrc->image.props.modifier) &&
(rsrc->image.props.modifier & AFBC_FORMAT_MOD_SPARSE) == 0) {
if (write && drm_is_afbc(rsrc->modifier) &&
(rsrc->modifier & AFBC_FORMAT_MOD_SPARSE) == 0) {
pan_resource_modifier_convert(
ctx, rsrc, rsrc->image.props.modifier | AFBC_FORMAT_MOD_SPARSE,
!discard, "Legalizing resource to allow writing");
ctx, rsrc, rsrc->modifier | AFBC_FORMAT_MOD_SPARSE, !discard,
"Legalizing resource to allow writing");
}
}
@ -1720,7 +1733,7 @@ panfrost_pack_afbc(struct panfrost_context *ctx,
assert(prsrc->base.array_size == 1);
uint64_t src_modifier = prsrc->image.props.modifier;
uint64_t src_modifier = prsrc->modifier;
uint64_t dst_modifier =
src_modifier & ~(AFBC_FORMAT_MOD_TILED | AFBC_FORMAT_MOD_SPARSE);
bool is_tiled = src_modifier & AFBC_FORMAT_MOD_TILED;
@ -1850,7 +1863,9 @@ panfrost_pack_afbc(struct panfrost_context *ctx,
panfrost_flush_batches_accessing_rsrc(ctx, prsrc, "AFBC compaction flush");
assert(!panfrost_is_emulated_mod(dst_modifier));
prsrc->image.props.modifier = dst_modifier;
prsrc->modifier = dst_modifier;
panfrost_bo_unreference(prsrc->bo);
prsrc->bo = dst;
prsrc->image.data.base = dst->ptr.gpu;
@ -1920,7 +1935,7 @@ panfrost_ptr_unmap(struct pipe_context *pctx, struct pipe_transfer *transfer)
if (transfer->usage & PIPE_MAP_WRITE) {
BITSET_SET(prsrc->valid.data, transfer->level);
if (prsrc->image.props.modifier ==
if (prsrc->modifier ==
DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
if (panfrost_should_linear_convert(ctx, prsrc, transfer)) {
panfrost_resource_setup(screen, prsrc, DRM_FORMAT_MOD_LINEAR,

View file

@ -61,6 +61,10 @@ struct panfrost_resource {
/* Description of the resource layout */
struct pan_image image;
/* In case of emulated modifiers, the image.props.modifier won't match this
* modifier. */
uint64_t modifier;
struct panfrost_bo *bo;
struct {

View file

@ -275,42 +275,60 @@ panfrost_walk_dmabuf_modifiers(struct pipe_screen *screen,
bool ytr = pan_afbc_can_ytr(format);
bool tiled_afbc = pan_afbc_can_tile(dev->arch);
bool afrc = allow_afrc && dev->has_afrc && pan_format_supports_afrc(format);
PAN_SUPPORTED_MODIFIERS(supported_mods);
PANFROST_EMULATED_MODIFIERS(emulated_mods);
PAN_SUPPORTED_MODIFIERS(native_mods);
unsigned count = 0;
for (unsigned i = 0; i < ARRAY_SIZE(supported_mods); ++i) {
if (drm_is_afbc(supported_mods[i])) {
for (unsigned i = 0; i < ARRAY_SIZE(native_mods); ++i) {
if (drm_is_afbc(native_mods[i])) {
if (!afbc)
continue;
if ((supported_mods[i] & AFBC_FORMAT_MOD_SPLIT) &&
!pan_afbc_can_split(dev->arch, format, supported_mods[i]))
if ((native_mods[i] & AFBC_FORMAT_MOD_SPLIT) &&
!pan_afbc_can_split(dev->arch, format, native_mods[i]))
continue;
if ((supported_mods[i] & AFBC_FORMAT_MOD_YTR) && !ytr)
if ((native_mods[i] & AFBC_FORMAT_MOD_YTR) && !ytr)
continue;
if ((supported_mods[i] & AFBC_FORMAT_MOD_TILED) && !tiled_afbc)
if ((native_mods[i] & AFBC_FORMAT_MOD_TILED) && !tiled_afbc)
continue;
}
if (drm_is_afrc(supported_mods[i]) && !afrc)
if (drm_is_afrc(native_mods[i]) && !afrc)
continue;
if (drm_is_mtk_tiled(supported_mods[i]) &&
!pan_format_supports_mtk_tiled(format))
if (drm_is_mtk_tiled(native_mods[i]) &&
!panfrost_format_supports_mtk_tiled(format))
continue;
if (test_modifier != DRM_FORMAT_MOD_INVALID &&
test_modifier != supported_mods[i])
test_modifier != native_mods[i])
continue;
if (max > (int)count) {
modifiers[count] = supported_mods[i];
modifiers[count] = native_mods[i];
if (external_only)
external_only[count] = drm_is_mtk_tiled(modifiers[count]);
external_only[count] = false;
}
count++;
}
for (unsigned i = 0; i < ARRAY_SIZE(emulated_mods); ++i) {
if (drm_is_mtk_tiled(emulated_mods[i]) &&
!panfrost_format_supports_mtk_tiled(format))
continue;
if (test_modifier != DRM_FORMAT_MOD_INVALID &&
test_modifier != emulated_mods[i])
continue;
if (max > (int)count) {
modifiers[count] = emulated_mods[i];
if (external_only)
external_only[count] = true;
}
count++;
}

View file

@ -81,8 +81,6 @@
DRM_FORMAT_MOD_ARM_AFRC( \
AFRC_FORMAT_MOD_CU_SIZE_P0(AFRC_FORMAT_MOD_CU_SIZE_32) | \
AFRC_FORMAT_MOD_LAYOUT_SCAN), \
\
DRM_FORMAT_MOD_MTK_16L_32S_TILE, \
}
/* DRM modifier helper */
@ -95,25 +93,6 @@
((mod >> 52) == \
(DRM_FORMAT_MOD_ARM_TYPE_AFRC | (DRM_FORMAT_MOD_VENDOR_ARM << 4)))
#define drm_is_mtk_tiled(mod) \
((mod >> 52) == (0 | (DRM_FORMAT_MOD_VENDOR_MTK << 4)))
/* check for whether a format can be used with MTK_16L32S format */
static inline bool
pan_format_supports_mtk_tiled(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_NV12:
case PIPE_FORMAT_R8_G8B8_420_UNORM:
case PIPE_FORMAT_R8_UNORM:
case PIPE_FORMAT_R8G8_UNORM:
return true;
default:
return false;
}
}
/* Formats */
typedef uint32_t mali_pixel_format;