pan/crc: Simplify CRC buffer initialization

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 <loic.molinari@collabora.com>
This commit is contained in:
Loïc Molinari 2026-02-09 15:35:02 +01:00
parent 789ae79688
commit d911ef7c9d
3 changed files with 24 additions and 34 deletions

View file

@ -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;

View file

@ -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

View file

@ -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;