mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 21:50:12 +01:00
etnaviv: blt: Enable scissored clear
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:
parent
f2c4c5493e
commit
2d8f8f82bd
2 changed files with 59 additions and 25 deletions
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue