From 8c208bc41e2d56217e7a2f9bd685a2688cf62d8a Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 4 Sep 2025 15:10:57 +0200 Subject: [PATCH] pan/afbc: Cache the pan_afbc_mode selection One we have selected a pan_afbc_mode (AKA AFBC format) for an image, there's no reason for it change, so let's cache that at the pan_image_layout level and re-use it when we can instead of doing the pipe format -> afbc mode conversion over and over again. Signed-off-by: Boris Brezillon Reviewed-by: Eric R. Smith Reviewed-by: Christoph Pillmayer Part-of: --- src/panfrost/lib/pan_afbc.h | 14 ++++++------ src/panfrost/lib/pan_desc.c | 4 ++-- src/panfrost/lib/pan_layout.c | 5 +++++ src/panfrost/lib/pan_layout.h | 6 ++++++ src/panfrost/lib/pan_mod.c | 39 ++++++++++++++++++++++++++++------ src/panfrost/lib/pan_mod.h | 7 ++++++ src/panfrost/lib/pan_texture.c | 2 +- 7 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/panfrost/lib/pan_afbc.h b/src/panfrost/lib/pan_afbc.h index 11f667dd007..9adc3606e34 100644 --- a/src/panfrost/lib/pan_afbc.h +++ b/src/panfrost/lib/pan_afbc.h @@ -599,8 +599,7 @@ pan_afbc_can_ytr(enum pipe_format format) } static inline bool -pan_afbc_can_split(unsigned arch, enum pipe_format format, uint64_t modifier, - unsigned plane_idx) +pan_afbc_can_split(unsigned arch, enum pan_afbc_mode mode, uint64_t modifier) { unsigned block_width = pan_afbc_superblock_width(modifier); @@ -610,7 +609,6 @@ pan_afbc_can_split(unsigned arch, enum pipe_format format, uint64_t modifier, if (block_width == 16) { return true; } else if (block_width == 32) { - enum pan_afbc_mode mode = pan_afbc_format(arch, format, plane_idx); return (mode == PAN_AFBC_MODE_R8G8B8A8 || mode == PAN_AFBC_MODE_R10G10B10A2); } @@ -640,13 +638,13 @@ pan_afbc_can_tile(unsigned arch) #if PAN_ARCH >= 9 static inline enum mali_afbc_compression_mode -pan_afbc_compression_mode(enum pipe_format format, unsigned plane_idx) +pan_afbc_compression_mode(enum pan_afbc_mode mode) { /* Map canonical formats to the hardware enum. This only * needs to handle the subset of formats returned by * pan_afbc_format. */ - switch (pan_afbc_format(PAN_ARCH, format, plane_idx)) { + switch (mode) { case PAN_AFBC_MODE_R8: return MALI_AFBC_COMPRESSION_MODE_R8; case PAN_AFBC_MODE_R8G8: @@ -698,16 +696,16 @@ pan_afbc_compression_mode(enum pipe_format format, unsigned plane_idx) static inline enum mali_afbc_compression_mode pan_afbc_decompression_mode(enum pipe_format view_format, - enum pipe_format img_format, unsigned plane_idx) + enum pan_afbc_mode img_mode) { /* There are special cases for texture views of stencil images. */ - if (img_format == PIPE_FORMAT_Z24_UNORM_S8_UINT && + if (img_mode == PAN_AFBC_MODE_R8G8B8A8 && view_format == PIPE_FORMAT_X24S8_UINT) return MALI_AFBC_COMPRESSION_MODE_X24S8; else if (view_format == PIPE_FORMAT_S8_UINT) return MALI_AFBC_COMPRESSION_MODE_S8; - return pan_afbc_compression_mode(img_format, plane_idx); + return pan_afbc_compression_mode(img_mode); } #endif diff --git a/src/panfrost/lib/pan_desc.c b/src/panfrost/lib/pan_desc.c index a672b204896..f89ed8aed55 100644 --- a/src/panfrost/lib/pan_desc.c +++ b/src/panfrost/lib/pan_desc.c @@ -710,8 +710,8 @@ GENX(pan_emit_afbc_color_attachment)(const struct pan_fb_info *fb, cfg.header = header; cfg.body_offset = body_offset; cfg.row_stride = hdr_row_stride; - cfg.compression_mode = - pan_afbc_compression_mode(image->props.format, pref.plane_idx); + cfg.compression_mode = pan_afbc_compression_mode( + image->planes[pref.plane_idx]->layout.afbc.mode); #else cfg.header = header; cfg.body = header + body_offset; diff --git a/src/panfrost/lib/pan_layout.c b/src/panfrost/lib/pan_layout.c index 5659c46bb97..9d6cfd9a8bc 100644 --- a/src/panfrost/lib/pan_layout.c +++ b/src/panfrost/lib/pan_layout.c @@ -113,6 +113,11 @@ pan_image_layout_init( if (plane_idx >= util_format_get_num_planes(props->format)) return false; + /* Init plane layout data. */ + if (mod_handler->init_plane_layout && + !mod_handler->init_plane_layout(props, plane_idx, layout)) + return false; + /* MSAA is implemented as a 3D texture with z corresponding to the * sample #, horrifyingly enough */ diff --git a/src/panfrost/lib/pan_layout.h b/src/panfrost/lib/pan_layout.h index 970d37a8ebf..855395fb98a 100644 --- a/src/panfrost/lib/pan_layout.h +++ b/src/panfrost/lib/pan_layout.h @@ -110,6 +110,12 @@ struct pan_image_props { struct pan_image_layout { struct pan_image_slice_layout slices[MAX_MIP_LEVELS]; + union { + struct { + int mode; + } afbc; + }; + /* Image plane data size in bytes */ uint64_t data_size_B; uint64_t array_stride_B; diff --git a/src/panfrost/lib/pan_mod.c b/src/panfrost/lib/pan_mod.c index 4eb4906d435..bd3fc9cb651 100644 --- a/src/panfrost/lib/pan_mod.c +++ b/src/panfrost/lib/pan_mod.c @@ -51,6 +51,20 @@ pan_mod_afbc_get_wsi_row_pitch(const struct pan_image *image, return tile_row_payload_size_B / pan_afbc_superblock_height(props->modifier); } +static bool +pan_mod_afbc_init_plane_layout(const struct pan_image_props *props, + unsigned plane_idx, + struct pan_image_layout *plane_layout) +{ + enum pan_afbc_mode mode = + pan_afbc_format(PAN_ARCH, props->format, plane_idx); + if (mode == PAN_AFBC_MODE_INVALID) + return false; + + plane_layout->afbc.mode = mode; + return true; +} + static bool pan_mod_afbc_init_slice_layout( const struct pan_image_props *props, unsigned plane_idx, @@ -184,9 +198,17 @@ pan_mod_afbc_test_props(const struct pan_kmod_dev_props *dprops, if (!pan_query_afbc(dprops)) return PAN_MOD_NOT_SUPPORTED; + unsigned plane_count = util_format_get_num_planes(iprops->format); + const struct util_format_description *fdesc = + util_format_description(iprops->format); + /* Check if the format is supported first. */ - if (!pan_afbc_supports_format(PAN_ARCH, iprops->format)) - return PAN_MOD_NOT_SUPPORTED; + enum pan_afbc_mode plane_modes[3]; + for (unsigned p = 0; p < plane_count; p++) { + plane_modes[p] = pan_afbc_format(PAN_ARCH, iprops->format, p); + if (plane_modes[p] == PAN_AFBC_MODE_INVALID) + return PAN_MOD_NOT_SUPPORTED; + } /* AFBC can't do multisampling. */ if (iprops->nr_samples > 1) @@ -197,10 +219,6 @@ pan_mod_afbc_test_props(const struct pan_kmod_dev_props *dprops, iprops->dim != MALI_TEXTURE_DIMENSION_2D) return PAN_MOD_NOT_SUPPORTED; - unsigned plane_count = util_format_get_num_planes(iprops->format); - const struct util_format_description *fdesc = - util_format_description(iprops->format); - /* ZS buffer descriptors can't pass split/wide/YTR modifiers. */ if (iusage && (iusage->bind & PAN_BIND_DEPTH_STENCIL) && (pan_afbc_superblock_width(iprops->modifier) != 16 || @@ -215,7 +233,7 @@ pan_mod_afbc_test_props(const struct pan_kmod_dev_props *dprops, /* Make sure all planes support split mode. */ if ((iprops->modifier & AFBC_FORMAT_MOD_SPLIT)) { for (unsigned p = 0; p < plane_count; p++) { - if (!pan_afbc_can_split(PAN_ARCH, iprops->format, iprops->modifier, p)) + if (!pan_afbc_can_split(PAN_ARCH, plane_modes[p], iprops->modifier)) return PAN_MOD_NOT_SUPPORTED; } } @@ -328,6 +346,8 @@ pan_mod_afrc_get_wsi_row_pitch(const struct pan_image *image, tile_extent_px.height; } +#define pan_mod_afrc_init_plane_layout NULL + static bool pan_mod_afrc_init_slice_layout( const struct pan_image_props *props, unsigned plane_idx, @@ -453,6 +473,8 @@ pan_mod_u_tiled_get_wsi_row_pitch(const struct pan_image *image, pan_u_interleaved_tile_size_el(props->format).height; } +#define pan_mod_u_tiled_init_plane_layout NULL + static bool pan_mod_u_tiled_init_slice_layout( const struct pan_image_props *props, unsigned plane_idx, @@ -589,6 +611,8 @@ pan_mod_linear_get_wsi_row_pitch(const struct pan_image *image, return layout->slices[mip_level].tiled_or_linear.row_stride_B; } +#define pan_mod_linear_init_plane_layout NULL + static bool pan_mod_linear_init_slice_layout( const struct pan_image_props *props, unsigned plane_idx, @@ -689,6 +713,7 @@ pan_mod_linear_init_slice_layout( .match = pan_mod_##__name##_match, \ .test_props = pan_mod_##__name##_test_props, \ .get_wsi_row_pitch = pan_mod_##__name##_get_wsi_row_pitch, \ + .init_plane_layout = pan_mod_##__name##_init_plane_layout, \ .init_slice_layout = pan_mod_##__name##_init_slice_layout, \ .emit_tex_payload_entry = pan_mod_##__name##_emit_tex_payload_entry, \ EMIT_ATT(__name), \ diff --git a/src/panfrost/lib/pan_mod.h b/src/panfrost/lib/pan_mod.h index ce1ab08f9f8..1d684506020 100644 --- a/src/panfrost/lib/pan_mod.h +++ b/src/panfrost/lib/pan_mod.h @@ -40,6 +40,13 @@ struct pan_mod_handler { const struct pan_image_props *iprops, const struct pan_image_usage *iusage); + /* Optional method used to initialize modifier-specific per-plane layout + * data. This is called before init_slice_layout(). + */ + bool (*init_plane_layout)(const struct pan_image_props *props, + unsigned plane_idx, + struct pan_image_layout *plane_layout); + bool (*init_slice_layout)( const struct pan_image_props *props, unsigned plane_idx, struct pan_image_extent mip_extent_px, diff --git a/src/panfrost/lib/pan_texture.c b/src/panfrost/lib/pan_texture.c index 825df6411e3..247924ced68 100644 --- a/src/panfrost/lib/pan_texture.c +++ b/src/panfrost/lib/pan_texture.c @@ -684,7 +684,7 @@ emit_afbc_plane(const struct pan_image_view *iview, int plane_idx, cfg.tiled_header = (props->modifier & AFBC_FORMAT_MOD_TILED); cfg.prefetch = true; cfg.compression_mode = pan_afbc_decompression_mode( - iview->format, props->format, pref.plane_idx); + iview->format, image->planes[pref.plane_idx]->layout.afbc.mode); PLANE_SET_SIZE(cfg, plane_size); cfg.pointer = header_addr; cfg.header_row_stride = header_row_stride;