mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-07 09:18:04 +02:00
etnaviv: Use shader R/B swap for LINEAR_PE shared resources
On LINEAR_PE GPUs, shared linear resources are render-compatible so
no render shadow exists - the PE renders directly into the shared
buffer. Rather than adding a dedicated flush-time blit to swap R/B
(which would introduce bandwidth that doesn't exist today), use the
frag_rb_swap shader key to swap channels at render time.
In etna_draw_vbo, detect LINEAR_PE + shared + linear + RB_SWAP format
and set the per-RT frag_rb_swap bits. Track shared_native_order so
etna_flush_resource can skip the dedicated blit when the shader
already produced correct byte order.
Fixes: a5766e75e48 ("etnaviv: Use BGRA-internal texture format with BLT/RS R/B swizzle")
Signed-off-by: Christian Gmeiner <cgmeiner@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40029>
This commit is contained in:
parent
99bf43dd08
commit
567a65bbbf
2 changed files with 40 additions and 21 deletions
|
|
@ -283,27 +283,28 @@ etna_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
|
|||
}
|
||||
} else if (flush_rb_swap) {
|
||||
/* No render shadow and no TS — PE rendered directly into the shared
|
||||
* buffer. We still need to R<->B swap the contents.
|
||||
* Can't use etna_copy_resource(src==dst) here because it skips levels
|
||||
* without valid TS, so issue the blit directly. */
|
||||
assert(prsc->last_level == 0);
|
||||
struct etna_resource_level *lev = &rsc->levels[0];
|
||||
struct pipe_blit_info blit = {
|
||||
.mask = util_format_get_mask(prsc->format),
|
||||
.filter = PIPE_TEX_FILTER_NEAREST,
|
||||
.src.resource = blit.dst.resource = prsc,
|
||||
.src.format = blit.dst.format = prsc->format,
|
||||
.src.box.width = blit.dst.box.width = lev->width,
|
||||
.src.box.height = blit.dst.box.height = lev->height,
|
||||
.src.box.depth = blit.dst.box.depth = 1,
|
||||
};
|
||||
* buffer. If the fragment shader already swapped R/B (LINEAR_PE),
|
||||
* bytes are already correct. Otherwise we need to swap here. */
|
||||
if (!rsc->shared_native_order) {
|
||||
assert(prsc->last_level == 0);
|
||||
struct etna_resource_level *lev = &rsc->levels[0];
|
||||
struct pipe_blit_info blit = {
|
||||
.mask = util_format_get_mask(prsc->format),
|
||||
.filter = PIPE_TEX_FILTER_NEAREST,
|
||||
.src.resource = blit.dst.resource = prsc,
|
||||
.src.format = blit.dst.format = prsc->format,
|
||||
.src.box.width = blit.dst.box.width = lev->width,
|
||||
.src.box.height = blit.dst.box.height = lev->height,
|
||||
.src.box.depth = blit.dst.box.depth = 1,
|
||||
};
|
||||
|
||||
ctx->blit_rb_swap = true;
|
||||
ctx->blit(pctx, &blit);
|
||||
ctx->blit_rb_swap = false;
|
||||
ctx->blit_rb_swap = true;
|
||||
ctx->blit(pctx, &blit);
|
||||
ctx->blit_rb_swap = false;
|
||||
|
||||
rsc->shared_native_order = true;
|
||||
etna_resource_level_mark_changed(&rsc->levels[0]);
|
||||
rsc->shared_native_order = true;
|
||||
etna_resource_level_mark_changed(&rsc->levels[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "etnaviv_debug.h"
|
||||
#include "etnaviv_emit.h"
|
||||
#include "etnaviv_fence.h"
|
||||
#include "etnaviv_format.h"
|
||||
#include "etnaviv_ml.h"
|
||||
#include "etnaviv_query.h"
|
||||
#include "etnaviv_query_acc.h"
|
||||
|
|
@ -417,6 +418,22 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
|
|||
if (screen->info->halti >= 5)
|
||||
key.flatshade = ctx->rasterizer->flatshade;
|
||||
|
||||
/* On LINEAR_PE GPUs rendering directly to a linear shared resource,
|
||||
* use shader-based R/B swap so bytes in memory have the correct order
|
||||
* for external consumers. This avoids a dedicated flush-time blit.
|
||||
* Per-RT bitmask so MRT with mixed shared/non-shared targets works. */
|
||||
if (VIV_FEATURE(screen, ETNA_FEATURE_LINEAR_PE)) {
|
||||
for (i = 0; i < pfb->nr_cbufs; i++) {
|
||||
if (pfb->cbufs[i].texture) {
|
||||
struct etna_resource *rsc = etna_resource(pfb->cbufs[i].texture);
|
||||
if (rsc->shared && rsc->layout == ETNA_LAYOUT_LINEAR &&
|
||||
translate_pe_format_rb_swap(pfb->cbufs[i].format)) {
|
||||
key.frag_rb_swap |= (1 << i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!etna_get_vs(ctx, &key) || !etna_get_fs(ctx, &key)) {
|
||||
BUG("compiled shaders are not okay");
|
||||
return;
|
||||
|
|
@ -563,9 +580,10 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
|
|||
etna_resource_level_mark_changed(level);
|
||||
|
||||
/* PE rendered directly to the shared buffer (no render shadow).
|
||||
* Data is now in PE-internal byte order (BGRA for RB_SWAP formats). */
|
||||
* If the shader swapped R/B, data is in native byte order.
|
||||
* Otherwise it's in PE-internal order (BGRA for RB_SWAP formats). */
|
||||
if (rsc->shared && res == rsc)
|
||||
rsc->shared_native_order = false;
|
||||
rsc->shared_native_order = !!(key.frag_rb_swap & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue