etnaviv: blt: Enable scissored clear
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

The main challenge is handling tile status (TS) correctly. Full clears
simply mark tiles as "cleared" in TS metadata without touching pixels.
Scissored clears must first decompress existing TS tiles using the
current clear color, then apply the new color to the scissor region.

The implementation maintains the original surface clear color for TS
decompression operations while using the new color for actual clearing.
This prevents rendering artifacts when mixing BLT and 3D operations.

BLT engine operates directly with pixel positions and handles all TS
tile complexity automatically.

Signed-off-by: Christian Gmeiner <cgmeiner@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35956>
This commit is contained in:
Christian Gmeiner 2025-07-04 00:30:36 +02:00 committed by Marge Bot
parent f2c4c5493e
commit 2d8f8f82bd
2 changed files with 59 additions and 25 deletions

View file

@ -265,20 +265,38 @@ emit_blt_genmipmap(struct etna_cmd_stream *stream, const struct blt_genmipmap_op
etna_stall(stream, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
}
static inline bool
etna_blt_will_fastclear(const struct etna_resource_level *level,
const struct pipe_scissor_state *scissor_state)
{
if (!scissor_state)
return true;
return scissor_state->minx == 0 &&
scissor_state->miny == 0 &&
scissor_state->maxx >= level->width &&
scissor_state->maxy >= level->height;
}
static void
etna_blit_clear_color_blt(struct pipe_context *pctx, unsigned idx,
const union pipe_color_union *color)
const union pipe_color_union *color,
const struct pipe_scissor_state *scissor_state)
{
struct etna_context *ctx = etna_context(pctx);
struct pipe_surface *dst = &ctx->framebuffer_s.cbufs[idx];
struct etna_resource *dst_res = etna_resource_get_render_compatible(pctx, dst->texture);
struct etna_resource_level *dst_level = &dst_res->levels[dst->level];
uint64_t new_clear_value = etna_clear_blit_pack_rgba(dst->format, color);
bool fast_clear = etna_blt_will_fastclear(dst_level, scissor_state);
int msaa_xscale = 1, msaa_yscale = 1;
translate_samples_to_xyscale(dst->texture->nr_samples,
&msaa_xscale, &msaa_yscale);
if (fast_clear)
dst_level->clear_value = new_clear_value;
struct blt_clear_op clr = {};
clr.dest.addr.bo = dst_res->bo;
clr.dest.addr.offset = dst_level->offset + dst->first_layer * dst_level->layer_stride;
@ -292,8 +310,8 @@ etna_blit_clear_color_blt(struct pipe_context *pctx, unsigned idx,
clr.dest.ts_addr.bo = dst_res->ts_bo;
clr.dest.ts_addr.offset = dst_level->ts_offset;
clr.dest.ts_addr.flags = ETNA_RELOC_WRITE;
clr.dest.ts_clear_value[0] = new_clear_value;
clr.dest.ts_clear_value[1] = new_clear_value >> 32;
clr.dest.ts_clear_value[0] = dst_level->clear_value;
clr.dest.ts_clear_value[1] = dst_level->clear_value >> 32;
clr.dest.ts_mode = dst_level->ts_mode;
clr.dest.ts_compress_fmt = dst_level->ts_compress_fmt;
}
@ -302,46 +320,54 @@ etna_blit_clear_color_blt(struct pipe_context *pctx, unsigned idx,
clr.clear_value[1] = new_clear_value >> 32;
clr.clear_bits[0] = 0xffffffff; /* TODO: Might want to clear only specific channels? */
clr.clear_bits[1] = 0xffffffff;
clr.rect_x = 0; /* What about scissors? */
clr.rect_y = 0;
clr.rect_w = dst_level->width * msaa_xscale;
clr.rect_h = dst_level->height * msaa_yscale;
if (scissor_state) {
clr.rect_x = scissor_state->minx * msaa_xscale;
clr.rect_y = scissor_state->miny * msaa_yscale;
clr.rect_w = (scissor_state->maxx - scissor_state->minx) * msaa_xscale;
clr.rect_h = (scissor_state->maxy - scissor_state->miny) * msaa_yscale;
} else {
clr.rect_x = 0;
clr.rect_y = 0;
clr.rect_w = dst_level->width * msaa_xscale;
clr.rect_h = dst_level->height * msaa_yscale;
}
emit_blt_clearimage(ctx->stream, &clr);
/* This made the TS valid */
if (dst_level->ts_size) {
if (idx == 0) {
ctx->framebuffer.TS_COLOR_CLEAR_VALUE = new_clear_value;
ctx->framebuffer.TS_COLOR_CLEAR_VALUE_EXT = new_clear_value >> 32;
ctx->framebuffer.TS_COLOR_CLEAR_VALUE = dst_level->clear_value;
ctx->framebuffer.TS_COLOR_CLEAR_VALUE_EXT = dst_level->clear_value >> 32;
} else {
ctx->framebuffer.RT_TS_COLOR_CLEAR_VALUE[idx - 1] = new_clear_value;
ctx->framebuffer.RT_TS_COLOR_CLEAR_VALUE_EXT[idx - 1] = new_clear_value >> 32;
ctx->framebuffer.RT_TS_COLOR_CLEAR_VALUE[idx - 1] = dst_level->clear_value;
ctx->framebuffer.RT_TS_COLOR_CLEAR_VALUE_EXT[idx - 1] = dst_level->clear_value >> 32;
}
/* update clear color in SW meta area of the buffer if TS is exported */
if (unlikely(new_clear_value != dst_level->clear_value &&
etna_resource_ext_ts(etna_resource(dst->texture))))
dst_level->ts_meta->v0.clear_value = new_clear_value;
if (unlikely(etna_resource_ext_ts(etna_resource(dst->texture))))
dst_level->ts_meta->v0.clear_value = dst_level->clear_value;
etna_resource_level_ts_mark_valid(dst_level);
etna_resource_level_mark_unflushed(dst_level);
ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_TS;
}
dst_level->clear_value = new_clear_value;
resource_written(ctx, &dst_res->base);
etna_resource_level_mark_changed(dst_level);
}
static void
etna_blit_clear_zs_blt(struct pipe_context *pctx, struct pipe_surface *dst,
unsigned buffers, double depth, unsigned stencil)
unsigned buffers, double depth, unsigned stencil,
const struct pipe_scissor_state *scissor_state)
{
struct etna_context *ctx = etna_context(pctx);
struct etna_resource *dst_res = etna_resource_get_render_compatible(pctx, dst->texture);
struct etna_resource_level *dst_level = &dst_res->levels[dst->level];
uint32_t new_clear_value = translate_clear_depth_stencil(dst->format, depth, stencil);
bool fast_clear = etna_blt_will_fastclear(dst_level, scissor_state);
uint32_t new_clear_bits = 0, clear_bits_depth, clear_bits_stencil;
int msaa_xscale = 1, msaa_yscale = 1;
@ -369,8 +395,7 @@ etna_blit_clear_zs_blt(struct pipe_context *pctx, struct pipe_surface *dst,
if (buffers & PIPE_CLEAR_STENCIL)
new_clear_bits |= clear_bits_stencil;
/* if all bits are cleared, update TS clear value */
if (new_clear_bits == 0xffffffff)
if (new_clear_bits == 0xffffffff && fast_clear)
dst_level->clear_value = new_clear_value;
/* TODO unduplicate this */
@ -397,10 +422,18 @@ etna_blit_clear_zs_blt(struct pipe_context *pctx, struct pipe_surface *dst,
clr.clear_value[1] = new_clear_value;
clr.clear_bits[0] = new_clear_bits;
clr.clear_bits[1] = new_clear_bits;
clr.rect_x = 0; /* What about scissors? */
clr.rect_y = 0;
clr.rect_w = dst_level->width * msaa_xscale;
clr.rect_h = dst_level->height * msaa_yscale;
if (scissor_state) {
clr.rect_x = scissor_state->minx * msaa_xscale;
clr.rect_y = scissor_state->miny * msaa_yscale;
clr.rect_w = (scissor_state->maxx - scissor_state->minx) * msaa_xscale;
clr.rect_h = (scissor_state->maxy - scissor_state->miny) * msaa_yscale;
} else {
clr.rect_x = 0;
clr.rect_y = 0;
clr.rect_w = dst_level->width * msaa_xscale;
clr.rect_h = dst_level->height * msaa_yscale;
}
emit_blt_clearimage(ctx->stream, &clr);
@ -438,7 +471,7 @@ etna_clear_blt(struct pipe_context *pctx, unsigned buffers, const struct pipe_sc
if (!(buffers & (PIPE_CLEAR_COLOR0 << idx)))
continue;
etna_blit_clear_color_blt(pctx, idx, color);
etna_blit_clear_color_blt(pctx, idx, color, scissor_state);
if (!etna_resource(psurf->texture)->explicit_flush)
etna_context_add_flush_resource(ctx, psurf->texture);
@ -446,7 +479,7 @@ etna_clear_blt(struct pipe_context *pctx, unsigned buffers, const struct pipe_sc
}
if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && ctx->framebuffer_s.zsbuf.texture != NULL)
etna_blit_clear_zs_blt(pctx, &ctx->framebuffer_s.zsbuf, buffers, depth, stencil);
etna_blit_clear_zs_blt(pctx, &ctx->framebuffer_s.zsbuf, buffers, depth, stencil, scissor_state);
etna_stall(ctx->stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_BLT);

View file

@ -232,7 +232,8 @@ etna_init_screen_caps(struct etna_screen *screen)
caps->fs_position_is_sysval = true;
caps->fs_face_is_integer_sysval = true; /* note: not integer */
caps->fs_point_is_sysval = false;
caps->generate_mipmap = screen->specs.use_blt;
caps->generate_mipmap =
caps->clear_scissored = screen->specs.use_blt;
/* Memory */
caps->constant_buffer_offset_alignment = 256;