etnaviv: remove copy of resource level in etna_surface

Keeping a full copy of the resource level around in the surface is
confusing and this confusion has caused real bugs already. Get rid
of the copy by retrieving most of the information directly from the
etna_resource_level pointed at from the surface. Only the precomputed
offsets into the target and TS BOs need to be kept in the surface.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19814>
This commit is contained in:
Lucas Stach 2022-11-17 16:07:06 +01:00 committed by Marge Bot
parent b6fa3cdb0e
commit 2de7d6d1d8
5 changed files with 48 additions and 53 deletions

View File

@ -226,16 +226,16 @@ etna_blit_clear_color_blt(struct pipe_context *pctx, struct pipe_surface *dst,
struct etna_resource *res = etna_resource(surf->base.texture);
struct blt_clear_op clr = {};
clr.dest.addr.bo = res->bo;
clr.dest.addr.offset = surf->surf.offset;
clr.dest.addr.offset = surf->offset;
clr.dest.addr.flags = ETNA_RELOC_WRITE;
clr.dest.bpp = util_format_get_blocksize(surf->base.format);
clr.dest.stride = surf->surf.stride;
clr.dest.stride = surf->level->stride;
clr.dest.tiling = res->layout;
if (surf->surf.ts_size) {
if (surf->level->ts_size) {
clr.dest.use_ts = 1;
clr.dest.ts_addr.bo = res->ts_bo;
clr.dest.ts_addr.offset = surf->surf.ts_offset;
clr.dest.ts_addr.offset = surf->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;
@ -249,13 +249,13 @@ etna_blit_clear_color_blt(struct pipe_context *pctx, struct pipe_surface *dst,
clr.clear_bits[1] = 0xffffffff;
clr.rect_x = 0; /* What about scissors? */
clr.rect_y = 0;
clr.rect_w = surf->surf.width * msaa_xscale;
clr.rect_h = surf->surf.height * msaa_yscale;
clr.rect_w = surf->level->width * msaa_xscale;
clr.rect_h = surf->level->height * msaa_yscale;
emit_blt_clearimage(ctx->stream, &clr);
/* This made the TS valid */
if (surf->surf.ts_size) {
if (surf->level->ts_size) {
ctx->framebuffer.TS_COLOR_CLEAR_VALUE = new_clear_value;
ctx->framebuffer.TS_COLOR_CLEAR_VALUE_EXT = new_clear_value >> 32;
@ -315,16 +315,16 @@ etna_blit_clear_zs_blt(struct pipe_context *pctx, struct pipe_surface *dst,
struct etna_resource *res = etna_resource(surf->base.texture);
struct blt_clear_op clr = {};
clr.dest.addr.bo = res->bo;
clr.dest.addr.offset = surf->surf.offset;
clr.dest.addr.offset = surf->offset;
clr.dest.addr.flags = ETNA_RELOC_WRITE;
clr.dest.bpp = util_format_get_blocksize(surf->base.format);
clr.dest.stride = surf->surf.stride;
clr.dest.stride = surf->level->stride;
clr.dest.tiling = res->layout;
if (surf->surf.ts_size) {
if (surf->level->ts_size) {
clr.dest.use_ts = 1;
clr.dest.ts_addr.bo = res->ts_bo;
clr.dest.ts_addr.offset = surf->surf.ts_offset;
clr.dest.ts_addr.offset = surf->ts_offset;
clr.dest.ts_addr.flags = ETNA_RELOC_WRITE;
clr.dest.ts_clear_value[0] = surf->level->clear_value;
clr.dest.ts_clear_value[1] = surf->level->clear_value;
@ -338,13 +338,13 @@ etna_blit_clear_zs_blt(struct pipe_context *pctx, struct pipe_surface *dst,
clr.clear_bits[1] = new_clear_bits;
clr.rect_x = 0; /* What about scissors? */
clr.rect_y = 0;
clr.rect_w = surf->surf.width * msaa_xscale;
clr.rect_h = surf->surf.height * msaa_yscale;
clr.rect_w = surf->level->width * msaa_xscale;
clr.rect_h = surf->level->height * msaa_yscale;
emit_blt_clearimage(ctx->stream, &clr);
/* This made the TS valid */
if (surf->surf.ts_size) {
if (surf->level->ts_size) {
ctx->framebuffer.TS_DEPTH_CLEAR_VALUE = surf->level->clear_value;
surf->level->ts_valid = true;
ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_TS;

View File

@ -304,20 +304,20 @@ etna_rs_gen_clear_surface(struct etna_context *ctx, struct etna_surface *surf,
}
/* use tiled clear if width is multiple of 16 */
bool tiled_clear = (surf->surf.padded_width & ETNA_RS_WIDTH_MASK) == 0 &&
(surf->surf.padded_height & ETNA_RS_HEIGHT_MASK) == 0;
bool tiled_clear = (surf->level->padded_width & ETNA_RS_WIDTH_MASK) == 0 &&
(surf->level->padded_height & ETNA_RS_HEIGHT_MASK) == 0;
etna_compile_rs_state( ctx, &surf->clear_command, &(struct rs_state) {
.source_format = format,
.dest_format = format,
.dest = dst->bo,
.dest_offset = surf->surf.offset,
.dest_stride = surf->surf.stride,
.dest_padded_height = surf->surf.padded_height,
.dest_offset = surf->offset,
.dest_stride = surf->level->stride,
.dest_padded_height = surf->level->padded_height,
.dest_tiling = tiled_clear ? dst->layout : ETNA_LAYOUT_LINEAR,
.dither = {0xffffffff, 0xffffffff},
.width = surf->surf.padded_width, /* These must be padded to 16x4 if !LINEAR, otherwise RS will hang */
.height = surf->surf.padded_height,
.width = surf->level->padded_width, /* These must be padded to 16x4 if !LINEAR, otherwise RS will hang */
.height = surf->level->padded_height,
.clear_value = {clear_value, clear_value >> 32, clear_value, clear_value >> 32},
.clear_mode = VIVS_RS_CLEAR_CONTROL_MODE_ENABLED1,
.clear_bits = 0xffff
@ -332,14 +332,14 @@ etna_blit_clear_color_rs(struct pipe_context *pctx, struct pipe_surface *dst,
struct etna_surface *surf = etna_surface(dst);
uint64_t new_clear_value = etna_clear_blit_pack_rgba(surf->base.format, color);
if (surf->surf.ts_size) { /* TS: use precompiled clear command */
if (surf->level->ts_size) { /* TS: use precompiled clear command */
ctx->framebuffer.TS_COLOR_CLEAR_VALUE = new_clear_value;
ctx->framebuffer.TS_COLOR_CLEAR_VALUE_EXT = new_clear_value >> 32;
if (VIV_FEATURE(ctx->screen, chipMinorFeatures1, AUTO_DISABLE)) {
/* Set number of color tiles to be filled */
etna_set_state(ctx->stream, VIVS_TS_COLOR_AUTO_DISABLE_COUNT,
surf->surf.padded_width * surf->surf.padded_height / 16);
surf->level->padded_width * surf->level->padded_height / 16);
ctx->framebuffer.TS_MEM_CONFIG |= VIVS_TS_MEM_CONFIG_COLOR_AUTO_DISABLE;
}
@ -397,13 +397,13 @@ etna_blit_clear_zs_rs(struct pipe_context *pctx, struct pipe_surface *dst,
* We may be better off recording the pending clear operation,
* delaying the actual clear to the first use. This way, we can merge
* consecutive clears together. */
if (surf->surf.ts_size) { /* TS: use precompiled clear command */
if (surf->level->ts_size) { /* TS: use precompiled clear command */
/* Set new clear depth value */
ctx->framebuffer.TS_DEPTH_CLEAR_VALUE = new_clear_value;
if (VIV_FEATURE(ctx->screen, chipMinorFeatures1, AUTO_DISABLE)) {
/* Set number of depth tiles to be filled */
etna_set_state(ctx->stream, VIVS_TS_DEPTH_AUTO_DISABLE_COUNT,
surf->surf.padded_width * surf->surf.padded_height / 16);
surf->level->padded_width * surf->level->padded_height / 16);
ctx->framebuffer.TS_MEM_CONFIG |= VIVS_TS_MEM_CONFIG_DEPTH_AUTO_DISABLE;
}
@ -442,13 +442,14 @@ etna_clear_rs(struct pipe_context *pctx, unsigned buffers, const struct pipe_sci
bool need_ts_flush = false;
if ((buffers & PIPE_CLEAR_COLOR) && ctx->framebuffer_s.nr_cbufs) {
struct etna_surface *surf = etna_surface(ctx->framebuffer_s.cbufs[0]);
if (surf->surf.ts_size)
if (surf->level->ts_size)
need_ts_flush = true;
}
if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && ctx->framebuffer_s.zsbuf != NULL) {
struct etna_surface *surf = etna_surface(ctx->framebuffer_s.zsbuf);
if (surf->surf.ts_size)
if (surf->level->ts_size)
need_ts_flush = true;
}

View File

@ -179,15 +179,15 @@ etna_set_framebuffer_state(struct pipe_context *pctx,
* VIVS_PE_COLOR_FORMAT_OVERWRITE comes from blend_state
* but only if we set the bits above. */
/* merged with depth_stencil_alpha */
if ((cbuf->surf.offset & 63) ||
(((cbuf->surf.stride * 4) & 63) && cbuf->surf.height > 4)) {
if ((cbuf->offset & 63) ||
(((cbuf->level->stride * 4) & 63) && cbuf->level->height > 4)) {
/* XXX Must make temporary surface here.
* Need the same mechanism on gc2000 when we want to do mipmap
* generation by
* rendering to levels > 1 due to multitiled / tiled conversion. */
BUG("Alignment error, trying to render to offset %08x with tile "
"stride %i",
cbuf->surf.offset, cbuf->surf.stride * 4);
cbuf->offset, cbuf->level->stride * 4);
}
if (screen->specs.halti >= 0 && screen->model != 0x880) {
@ -204,9 +204,9 @@ etna_set_framebuffer_state(struct pipe_context *pctx,
cs->PE_COLOR_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
}
cs->PE_COLOR_STRIDE = cbuf->surf.stride;
cs->PE_COLOR_STRIDE = cbuf->level->stride;
if (cbuf->surf.ts_size) {
if (cbuf->level->ts_size) {
cs->TS_COLOR_CLEAR_VALUE = cbuf->level->clear_value;
cs->TS_COLOR_CLEAR_VALUE_EXT = cbuf->level->clear_value >> 32;
@ -283,11 +283,11 @@ etna_set_framebuffer_state(struct pipe_context *pctx,
cs->PE_DEPTH_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE;
}
cs->PE_DEPTH_STRIDE = zsbuf->surf.stride;
cs->PE_DEPTH_STRIDE = zsbuf->level->stride;
cs->PE_HDEPTH_CONTROL = VIVS_PE_HDEPTH_CONTROL_FORMAT_DISABLED;
cs->PE_DEPTH_NORMALIZE = fui(exp2f(depth_bits) - 1.0f);
if (zsbuf->surf.ts_size) {
if (zsbuf->level->ts_size) {
cs->TS_DEPTH_CLEAR_VALUE = zsbuf->level->clear_value;
cs->TS_DEPTH_STATUS_BASE = zsbuf->ts_reloc;

View File

@ -90,6 +90,7 @@ etna_create_surface(struct pipe_context *pctx, struct pipe_resource *prsc,
unsigned layer = templat->u.tex.first_layer;
unsigned level = templat->u.tex.level;
struct etna_resource *rsc = etna_render_handle_incompatible(pctx, prsc, level);
struct etna_resource_level *lev = &rsc->levels[level];
struct etna_surface *surf = CALLOC_STRUCT(etna_surface);
if (!surf)
@ -127,22 +128,15 @@ etna_create_surface(struct pipe_context *pctx, struct pipe_resource *prsc,
surf->base.height = rsc->levels[level].height;
surf->base.writable = templat->writable; /* what is this for anyway */
surf->base.u = templat->u;
surf->level = &rsc->levels[level]; /* Keep pointer to actual level to set
* clear color on underlying resource
* instead of surface */
surf->surf = rsc->levels [level]; /* Make copy of level to narrow down
* address to layer */
surf->level = lev;
/* XXX we don't really need a copy but it's convenient */
surf->surf.offset += layer * surf->surf.layer_stride;
struct etna_resource_level *lev = &rsc->levels[level];
surf->offset = lev->offset + layer * lev->layer_stride;
/* Setup template relocations for this surface */
for (unsigned pipe = 0; pipe < screen->specs.pixel_pipes; ++pipe) {
surf->reloc[pipe].bo = rsc->bo;
surf->reloc[pipe].offset = surf->surf.offset;
surf->reloc[pipe].offset = surf->offset;
surf->reloc[pipe].flags = 0;
}
@ -151,17 +145,16 @@ etna_create_surface(struct pipe_context *pctx, struct pipe_resource *prsc,
* point halfway the image vertically.
*/
if (rsc->layout & ETNA_LAYOUT_BIT_MULTI)
surf->reloc[1].offset = surf->surf.offset + lev->stride * lev->padded_height / 2;
surf->reloc[1].offset = surf->offset + lev->stride * lev->padded_height / 2;
if (surf->surf.ts_size) {
unsigned int layer_offset = layer * surf->surf.ts_layer_stride;
assert(layer_offset < surf->surf.ts_size);
if (surf->level->ts_size) {
unsigned int layer_offset = layer * lev->ts_layer_stride;
assert(layer_offset < surf->level->ts_size);
surf->surf.ts_offset += layer_offset;
surf->surf.ts_valid = false;
surf->ts_offset = surf->level->ts_offset + layer_offset;
surf->ts_reloc.bo = rsc->ts_bo;
surf->ts_reloc.offset = surf->surf.ts_offset;
surf->ts_reloc.offset = surf->ts_offset;
surf->ts_reloc.flags = 0;
if (!screen->specs.use_blt) {
@ -173,7 +166,7 @@ etna_create_surface(struct pipe_context *pctx, struct pipe_resource *prsc,
.source_format = RS_FORMAT_A8R8G8B8,
.dest_format = RS_FORMAT_A8R8G8B8,
.dest = ts_bo,
.dest_offset = surf->surf.ts_offset,
.dest_offset = surf->ts_offset,
.dest_stride = 0x40,
.dest_tiling = ETNA_LAYOUT_TILED,
.dither = {0xffffffff, 0xffffffff},

View File

@ -35,12 +35,13 @@
struct etna_surface {
struct pipe_surface base;
struct etna_resource_level surf;
struct compiled_rs_state clear_command;
/* Keep pointer to resource level, for fast clear */
struct etna_resource_level *level;
struct etna_reloc reloc[ETNA_MAX_PIXELPIPES];
struct etna_reloc ts_reloc;
uint32_t offset; /* pre-calculated level + layer offset */
uint32_t ts_offset; /* pre-calculated level + layer TS offset */
/* keep pointer to original resource (for when a render compatible resource is used) */
struct pipe_resource *prsc;
};