From d911ef7c9d3bc29ad1adae12ee132902f4a0541d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Molinari?= Date: Mon, 9 Feb 2026 15:35:02 +0100 Subject: [PATCH] pan/crc: Simplify CRC buffer initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Transaction Elimination on a RT is disabled until there's a full frame render with all tiles forcefully written back. This is currently done by letting the Gallium driver track states and fix up FB preload by disabling clean_fragment_write on the pre-frame DCD and by setting the pre-frame mode to "always" (instead of "intersect"). This commit forces the write-back of all the tiles by setting clean_tile_write_enable on the FBD instead. This simplifies the code and removes most of the CRC state tracking from the Gallium driver. Signed-off-by: Loïc Molinari --- src/gallium/drivers/panfrost/pan_fb_preload.c | 29 ++++--------------- src/panfrost/lib/pan_desc.c | 27 ++++++++++++----- src/panfrost/lib/pan_desc.h | 2 -- 3 files changed, 24 insertions(+), 34 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_fb_preload.c b/src/gallium/drivers/panfrost/pan_fb_preload.c index 46bf5388d9f..73d11412d58 100644 --- a/src/gallium/drivers/panfrost/pan_fb_preload.c +++ b/src/gallium/drivers/panfrost/pan_fb_preload.c @@ -1018,8 +1018,7 @@ pan_preload_emit_viewport(struct pan_pool *pool, uint16_t minx, uint16_t miny, static void pan_preload_emit_dcd(struct pan_fb_preload_cache *cache, struct pan_pool *pool, struct pan_fb_info *fb, bool zs, uint64_t coordinates, - uint64_t tsd, struct mali_draw_packed *out, - bool always_write) + uint64_t tsd, struct mali_draw_packed *out) { unsigned tex_count = 0; uint64_t textures = pan_preload_emit_textures(pool, fb, zs, &tex_count); @@ -1031,7 +1030,7 @@ pan_preload_emit_dcd(struct pan_fb_preload_cache *cache, struct pan_pool *pool, /* Tiles updated by preload shaders are still considered clean (separate * for colour and Z/S), allowing us to suppress unnecessary writeback */ - UNUSED bool clean_fragment_write = !always_write; + UNUSED bool clean_fragment_write = true; /* Image view used when patching stencil formats for combined * depth/stencil preloads. @@ -1186,25 +1185,8 @@ pan_preload_emit_pre_frame_dcd(struct pan_fb_preload_cache *cache, void *dcd = fb->bifrost.pre_post.dcds.cpu + (dcd_idx * pan_size(DRAW)); - /* We only use crc_rt to determine whether to force writes for updating - * the CRCs, so use a conservative tile size (16x16). - */ - int crc_rt = GENX(pan_select_crc_rt)(fb, 16 * 16); + pan_preload_emit_dcd(cache, desc_pool, fb, zs, coords, tsd, dcd); - bool always_write = false; - - /* If CRC data is currently invalid and this batch will make it valid, - * write even clean tiles to make sure CRC data is updated. */ - if (crc_rt >= 0) { - bool *valid = fb->rts[crc_rt].crc_valid; - bool full = pan_fb_info_is_fully_covered(fb); - - if (full && !(*valid)) - always_write = true; - } - - pan_preload_emit_dcd(cache, desc_pool, fb, zs, coords, tsd, dcd, - always_write); if (zs) { enum pipe_format fmt = fb->zs.view.zs ? fb->zs.view.zs->planes[0].image->props.format @@ -1264,8 +1246,7 @@ pan_preload_emit_pre_frame_dcd(struct pan_fb_preload_cache *cache, #endif } else { fb->bifrost.pre_post.modes[dcd_idx] = - always_write ? MALI_PRE_POST_FRAME_SHADER_MODE_ALWAYS - : MALI_PRE_POST_FRAME_SHADER_MODE_INTERSECT; + MALI_PRE_POST_FRAME_SHADER_MODE_INTERSECT; } } #else @@ -1280,7 +1261,7 @@ pan_preload_emit_tiler_job(struct pan_fb_preload_cache *cache, return (struct pan_ptr){0}; pan_preload_emit_dcd(cache, desc_pool, fb, zs, coords, tsd, - pan_section_ptr(job.cpu, TILER_JOB, DRAW), false); + pan_section_ptr(job.cpu, TILER_JOB, DRAW)); pan_section_pack(job.cpu, TILER_JOB, PRIMITIVE, cfg) { cfg.draw_mode = MALI_DRAW_MODE_TRIANGLE_STRIP; diff --git a/src/panfrost/lib/pan_desc.c b/src/panfrost/lib/pan_desc.c index 921afbf4698..cc9dd8e288e 100644 --- a/src/panfrost/lib/pan_desc.c +++ b/src/panfrost/lib/pan_desc.c @@ -1045,8 +1045,8 @@ pan_fb_color_attachment_should_crc(const struct pan_fb_color_attachment *rt, return true; } -int -GENX(pan_select_crc_rt)(const struct pan_fb_info *fb, unsigned tile_size) +static int +pan_select_crc_rt(const struct pan_fb_info *fb) { int best_rt = -1; @@ -1059,7 +1059,7 @@ GENX(pan_select_crc_rt)(const struct pan_fb_info *fb, unsigned tile_size) * CRCs are more expensive at smaller tile sizes, reducing the benefit. * Restricting CRC to 16x16 should work in practice. */ - if (tile_size < 16 * 16) + if (fb->tile_size < 16 * 16) return best_rt; #if PAN_ARCH <= 6 @@ -1069,7 +1069,7 @@ GENX(pan_select_crc_rt)(const struct pan_fb_info *fb, unsigned tile_size) for (unsigned i = 0; i < fb->rt_count; i++) { /* Skip unusable RTs. */ - if (!pan_fb_color_attachment_should_crc(&fb->rts[i], tile_size)) + if (!pan_fb_color_attachment_should_crc(&fb->rts[i], fb->tile_size)) continue; /* Select the first RT with a valid CRC buffer. */ @@ -1118,8 +1118,18 @@ GENX(pan_force_clean_write_on)(const struct pan_image *image, #endif } +static bool +pan_force_clean_write_crc(const struct pan_fb_info *fb, int index, int crc_rt) +{ + bool match = index == crc_rt; + bool valid = *(fb->rts[index].crc_valid); + bool full = pan_fb_info_is_fully_covered(fb); + + return match && !valid && full; +} + static struct pan_clean_tile -pan_get_clean_tile_info(const struct pan_fb_info *fb) +pan_get_clean_tile_info(const struct pan_fb_info *fb, int crc_rt) { struct pan_clean_tile clean_tile = { 0, }; const struct pan_image *img; @@ -1134,7 +1144,8 @@ pan_get_clean_tile_info(const struct pan_fb_info *fb) img = fb->rts[i].view ? pan_image_view_get_color_plane(fb->rts[i].view).image : NULL; if (fb->rts[i].clear || - GENX(pan_force_clean_write_on)(img, fb->tile_size)) + GENX(pan_force_clean_write_on)(img, fb->tile_size) || + pan_force_clean_write_crc(fb, i, crc_rt)) clean_tile.write_rt_mask |= 1 << i; } @@ -1195,9 +1206,9 @@ GENX(pan_emit_fbd)(const struct pan_fb_info *fb, unsigned layer_idx, GENX(pan_emit_tls)(tls, pan_section_ptr(fbd, FRAMEBUFFER, LOCAL_STORAGE)); #endif - int crc_rt = GENX(pan_select_crc_rt)(fb, fb->tile_size); + int crc_rt = pan_select_crc_rt(fb); bool has_zs_crc_ext = (fb->zs.view.zs || fb->zs.view.s || crc_rt >= 0); - struct pan_clean_tile clean_tile = pan_get_clean_tile_info(fb); + struct pan_clean_tile clean_tile = pan_get_clean_tile_info(fb, crc_rt); pan_section_pack(fbd, FRAMEBUFFER, PARAMETERS, cfg) { #if PAN_ARCH >= 6 diff --git a/src/panfrost/lib/pan_desc.h b/src/panfrost/lib/pan_desc.h index fddcfbae78a..08ac5c588b8 100644 --- a/src/panfrost/lib/pan_desc.h +++ b/src/panfrost/lib/pan_desc.h @@ -303,8 +303,6 @@ bool GENX(pan_force_clean_write_on)(const struct pan_image *image, void GENX(pan_emit_tls)(const struct pan_tls_info *info, struct mali_local_storage_packed *out); -int GENX(pan_select_crc_rt)(const struct pan_fb_info *fb, unsigned tile_size); - struct pan_attachment_info { const struct pan_image_view *iview; unsigned layer_or_z_slice;