From 6b154706f3e90b47c34891a0b8d03c470400cd1b Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Tue, 5 Dec 2023 12:29:24 +0100 Subject: [PATCH] etnaviv: TS usage for MRT needs HALTI2 I have not seen any usage of TS when MRTs are used in my traces for GC2000. I think that this is related to gcvFEATURE_MRT_TILE_STATUS_BUFFER found in some galcore kernel headers. We need to take extra care as those render targets might already have valid TS state, because they have been fast cleared or have been rendered to with a state that did allow TS usage. Fixes piglit's related to MRTs on GC2000. Signed-off-by: Christian Gmeiner Reviewed-by: Lucas Stach Part-of: --- src/gallium/drivers/etnaviv/etnaviv_rs.c | 13 +++++++++---- src/gallium/drivers/etnaviv/etnaviv_state.c | 7 +++++++ src/gallium/drivers/etnaviv/etnaviv_state.h | 19 +++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/gallium/drivers/etnaviv/etnaviv_rs.c b/src/gallium/drivers/etnaviv/etnaviv_rs.c index ba0956dae61..ffb8a17f5b2 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_rs.c +++ b/src/gallium/drivers/etnaviv/etnaviv_rs.c @@ -32,6 +32,7 @@ #include "etnaviv_format.h" #include "etnaviv_resource.h" #include "etnaviv_screen.h" +#include "etnaviv_state.h" #include "etnaviv_surface.h" #include "etnaviv_tiling.h" #include "etnaviv_translate.h" @@ -326,14 +327,14 @@ etna_rs_gen_clear_surface(struct etna_context *ctx, struct etna_surface *surf, static void etna_blit_clear_color_rs(struct pipe_context *pctx, unsigned idx, - const union pipe_color_union *color) + const union pipe_color_union *color, bool use_ts) { struct etna_context *ctx = etna_context(pctx); struct pipe_surface *dst = ctx->framebuffer_s.cbufs[idx]; struct etna_surface *surf = etna_surface(dst); uint64_t new_clear_value = etna_clear_blit_pack_rgba(surf->base.format, color); - if (surf->level->ts_size) { /* TS: use precompiled clear command */ + if (use_ts && surf->level->ts_size) { /* TS: use precompiled clear command */ if (idx == 0) { ctx->framebuffer.TS_COLOR_CLEAR_VALUE = new_clear_value; ctx->framebuffer.TS_COLOR_CLEAR_VALUE_EXT = new_clear_value >> 32; @@ -358,7 +359,7 @@ etna_blit_clear_color_rs(struct pipe_context *pctx, unsigned idx, etna_submit_rs_state(ctx, &surf->ts_clear_command); etna_resource_level_ts_mark_valid(surf->level); - ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_TS; + ctx->dirty |= ETNA_DIRTY_TS; } else { /* Queue normal RS clear for non-TS surfaces */ /* If clear color changed or no valid command yet (re-)generate * stored command */ @@ -367,8 +368,10 @@ etna_blit_clear_color_rs(struct pipe_context *pctx, unsigned idx, etna_rs_gen_clear_surface(ctx, surf, new_clear_value); etna_submit_rs_state(ctx, &surf->clear_command); + etna_resource_level_ts_mark_invalid(surf->level); } + ctx->dirty |= ETNA_DIRTY_DERIVE_TS; surf->level->clear_value = new_clear_value; resource_written(ctx, surf->base.texture); etna_resource_level_mark_changed(surf->level); @@ -488,13 +491,15 @@ etna_clear_rs(struct pipe_context *pctx, unsigned buffers, const struct pipe_sci * resolve and copy) do not require the TS state. */ if (buffers & PIPE_CLEAR_COLOR) { + const bool use_ts = etna_use_ts_for_mrt(ctx->screen, &ctx->framebuffer_s); + for (int idx = 0; idx < ctx->framebuffer_s.nr_cbufs; ++idx) { struct etna_surface *surf = etna_surface(ctx->framebuffer_s.cbufs[idx]); if (!surf) continue; - etna_blit_clear_color_rs(pctx, idx, color); + etna_blit_clear_color_rs(pctx, idx, color, use_ts); if (!etna_resource(surf->prsc)->explicit_flush) etna_context_add_flush_resource(ctx, surf->prsc); diff --git a/src/gallium/drivers/etnaviv/etnaviv_state.c b/src/gallium/drivers/etnaviv/etnaviv_state.c index 99e634c8f6f..5f4be37e94b 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_state.c +++ b/src/gallium/drivers/etnaviv/etnaviv_state.c @@ -146,6 +146,7 @@ etna_set_framebuffer_state(struct pipe_context *pctx, uint32_t pe_mem_config = 0; uint32_t pe_logic_op = 0; + const bool use_ts = etna_use_ts_for_mrt(screen, fb); unsigned rt = 0; for (unsigned i = 0; i < fb->nr_cbufs; i++) { @@ -157,6 +158,12 @@ etna_set_framebuffer_state(struct pipe_context *pctx, bool color_supertiled = (res->layout & ETNA_LAYOUT_BIT_SUPER) != 0; uint32_t fmt = translate_pe_format(cbuf->base.format); + /* Resolve TS if needed */ + if (!use_ts) { + etna_copy_resource(pctx, &res->base, &res->base, cbuf->base.u.tex.level, cbuf->base.u.tex.level); + etna_resource_level_ts_mark_invalid(&res->levels[cbuf->base.u.tex.level]); + } + assert((res->layout & ETNA_LAYOUT_BIT_TILE) || VIV_FEATURE(screen, ETNA_FEATURE_LINEAR_PE)); etna_update_render_surface(pctx, cbuf); diff --git a/src/gallium/drivers/etnaviv/etnaviv_state.h b/src/gallium/drivers/etnaviv/etnaviv_state.h index 939c2982f08..1820df0de1b 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_state.h +++ b/src/gallium/drivers/etnaviv/etnaviv_state.h @@ -29,6 +29,7 @@ #define ETNAVIV_STATE_H_ #include "etnaviv_context.h" +#include "etnaviv_screen.h" #include "pipe/p_context.h" static inline bool @@ -43,6 +44,24 @@ etna_stencil_enabled(struct etna_context *ctx) return ctx->zsa && ctx->zsa->stencil[0].enabled; } +static inline bool +etna_use_ts_for_mrt(const struct etna_screen *screen, const struct pipe_framebuffer_state *fb) +{ + if (screen->info->halti >= 2) + return true; + + unsigned count = 0; + + for (unsigned i = 0; i < fb->nr_cbufs; i++) { + if (!fb->cbufs[i]) + continue; + + count++; + } + + return count <= 1; +} + bool etna_state_update(struct etna_context *ctx);