mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-07 04:58:05 +02:00
etnaviv: Select texture format dynamically for shared RB_SWAP resources
The previous patches statically remapped the texture format at sampler
view creation time (A8R8G8B8 -> A8B8G8R8) for shared resources with
RB_SWAP formats. This is correct when the shared buffer holds
externally-produced RGBA data (import) or after flush_resource has done
the R<->B swap.
However, if the PE renders directly to a shared buffer (LINEAR_PE, no
render shadow), the data becomes BGRA. The static A8B8G8R8 format then
reads BGRA as RGBA - R and B are swapped.
Fix this by tracking whether the shared buffer holds native (RGBA) or
PE-internal (BGRA) byte order via a new shared_native_order flag, and
selecting the texture format dynamically at emit time.
The flag is set to true on import and export (data is native byte order
at that point), cleared when the PE renders directly to a shared buffer
without a render shadow, and set back to true after flush_resource
performs the R<->B swap.
Both the state-based and descriptor-based texture paths pre-compute the
native format variant at sampler view creation time, avoiding any
per-frame overhead beyond a single branch in the emit path.
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
4172e9a918
commit
cfa8deaad9
6 changed files with 95 additions and 22 deletions
|
|
@ -556,10 +556,16 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
|
|||
|
||||
for (i = 0; i < pfb->nr_cbufs; i++) {
|
||||
if (pfb->cbufs[i].texture) {
|
||||
struct etna_resource *rsc = etna_resource(pfb->cbufs[i].texture);
|
||||
struct etna_resource *res = etna_resource_get_render_compatible(pctx, pfb->cbufs[i].texture);
|
||||
struct etna_resource_level *level = &res->levels[pfb->cbufs[i].level];
|
||||
|
||||
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 (rsc->shared && res == rsc)
|
||||
rsc->shared_native_order = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -395,10 +395,10 @@ translate_pe_format_rb_swap(enum pipe_format fmt)
|
|||
return formats[fmt].pe & PE_FORMAT_RB_SWAP;
|
||||
}
|
||||
|
||||
/* For shared resources with RB_SWAP formats, remaps the HW texture format
|
||||
* back to the one matching the actual byte order in memory (e.g., A8B8G8R8
|
||||
* for RGBA data). Normally we use A8R8G8B8 to match PE-internal BGRA byte
|
||||
* order, but shared resources store data in the standard byte order.
|
||||
/* For RB_SWAP formats, remaps the HW texture format to the one matching
|
||||
* native byte order in memory (e.g., A8B8G8R8 for RGBA data). Normally we
|
||||
* use A8R8G8B8 to match PE-internal BGRA byte order, but shared resources
|
||||
* that have been flushed store data in the standard byte order.
|
||||
*/
|
||||
uint32_t
|
||||
remap_texture_format_rb_swap(uint32_t format)
|
||||
|
|
|
|||
|
|
@ -835,6 +835,7 @@ etna_resource_from_handle(struct pipe_screen *pscreen,
|
|||
rsc->modifier = modifier;
|
||||
|
||||
rsc->shared = true;
|
||||
rsc->shared_native_order = true;
|
||||
if (usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH)
|
||||
rsc->explicit_flush = true;
|
||||
|
||||
|
|
@ -937,7 +938,12 @@ etna_resource_get_handle(struct pipe_screen *pscreen,
|
|||
}
|
||||
handle->modifier = etna_resource_modifier(rsc);
|
||||
|
||||
/* Mark as shared. Data is in native byte order at export time (either
|
||||
* empty or CPU-written). draw_vbo will set shared_native_order = false
|
||||
* when the PE renders to this resource. */
|
||||
rsc->shared = true;
|
||||
rsc->shared_native_order = true;
|
||||
|
||||
if (!(usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH))
|
||||
rsc->explicit_flush = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -227,6 +227,9 @@ struct etna_resource {
|
|||
bool explicit_flush;
|
||||
/* resource is shared outside of the screen */
|
||||
bool shared;
|
||||
/* shared buffer has standard byte order (RGBA for R8G8B8A8_UNORM).
|
||||
* false when PE has written BGRA directly to the shared buffer. */
|
||||
bool shared_native_order;
|
||||
|
||||
struct pipe_box *damage;
|
||||
unsigned num_damage;
|
||||
|
|
|
|||
|
|
@ -64,9 +64,12 @@ struct etna_sampler_view_desc {
|
|||
uint32_t SAMP_CTRL0;
|
||||
uint32_t SAMP_CTRL0_MASK;
|
||||
uint32_t SAMP_CTRL1;
|
||||
bool has_rb_swap;
|
||||
|
||||
struct pipe_resource *res;
|
||||
struct etna_reloc DESC_ADDR[2]; /* [0] = seamless disabled, [1] = seamless enabled */
|
||||
/* [0]=non-seamless PE-internal, [1]=seamless PE-internal,
|
||||
* [2]=non-seamless native, [3]=seamless native */
|
||||
struct etna_reloc DESC_ADDR[4];
|
||||
struct etna_sampler_ts ts;
|
||||
};
|
||||
|
||||
|
|
@ -139,11 +142,10 @@ etna_create_sampler_view_desc(struct pipe_context *pctx, struct pipe_resource *p
|
|||
struct etna_context *ctx = etna_context(pctx);
|
||||
uint32_t format = translate_texture_format(so->format);
|
||||
|
||||
/* Shared resources store data in standard byte order (e.g., RGBA for
|
||||
* R8G8B8A8_UNORM). Use the native texture format to read them correctly,
|
||||
* bypassing the BGRA-internal optimization used for internal resources. */
|
||||
if (etna_resource(prsc)->shared && translate_pe_format_rb_swap(so->format))
|
||||
format = remap_texture_format_rb_swap(format);
|
||||
/* For RB_SWAP formats, pre-compute the alternative texture format for when
|
||||
* shared resources hold data in native byte order (RGBA). */
|
||||
bool rb_swap = translate_pe_format_rb_swap(so->format);
|
||||
uint32_t native_format = rb_swap ? remap_texture_format_rb_swap(format) : 0;
|
||||
|
||||
const bool ext = !!(format & EXT_FORMAT);
|
||||
const bool astc = !!(format & ASTC_FORMAT);
|
||||
|
|
@ -177,8 +179,10 @@ etna_create_sampler_view_desc(struct pipe_context *pctx, struct pipe_resource *p
|
|||
if (util_format_is_srgb(so->format))
|
||||
sv->SAMP_CTRL1 |= VIVS_NTE_DESCRIPTOR_SAMP_CTRL1_SRGB;
|
||||
|
||||
/* Create two texture descriptors: one with seamless cube map disabled, one enabled */
|
||||
u_suballocator_alloc(&ctx->tex_desc_allocator, TEXTURE_DESC_SIZE * 2, 64,
|
||||
/* Create texture descriptors: 2 normally (non-seamless + seamless),
|
||||
* or 4 for RB_SWAP formats (2 PE-internal + 2 native byte order). */
|
||||
unsigned num_descs = rb_swap ? 4 : 2;
|
||||
u_suballocator_alloc(&ctx->tex_desc_allocator, TEXTURE_DESC_SIZE * num_descs, 64,
|
||||
&suballoc_offset, &sv->res);
|
||||
if (!sv->res)
|
||||
goto error;
|
||||
|
|
@ -250,7 +254,7 @@ etna_create_sampler_view_desc(struct pipe_context *pctx, struct pipe_resource *p
|
|||
memcpy(seamless, buf, TEXTURE_DESC_SIZE);
|
||||
seamless[(TEXDESC_CONFIG1) >> 2] |= VIVS_TE_SAMPLER_CONFIG1_SEAMLESS_CUBE_MAP;
|
||||
|
||||
/* Setup relocations for both descriptors. */
|
||||
/* Setup relocations for PE-internal format descriptors. */
|
||||
sv->DESC_ADDR[0].bo = etna_buffer_resource(sv->res)->bo;
|
||||
sv->DESC_ADDR[0].offset = suballoc_offset;
|
||||
sv->DESC_ADDR[0].flags = ETNA_RELOC_READ;
|
||||
|
|
@ -259,6 +263,30 @@ etna_create_sampler_view_desc(struct pipe_context *pctx, struct pipe_resource *p
|
|||
sv->DESC_ADDR[1].offset = suballoc_offset + TEXTURE_DESC_SIZE;
|
||||
sv->DESC_ADDR[1].flags = ETNA_RELOC_READ;
|
||||
|
||||
if (rb_swap) {
|
||||
/* Build descriptors 2,3 with native byte order format.
|
||||
* Copy from descriptors 0,1 and patch the CONFIG0 format field. */
|
||||
uint32_t *native = buf + 2 * (TEXTURE_DESC_SIZE / sizeof(uint32_t));
|
||||
memcpy(native, buf, TEXTURE_DESC_SIZE);
|
||||
native[(TEXDESC_CONFIG0) >> 2] = (native[(TEXDESC_CONFIG0) >> 2] &
|
||||
~VIVS_TE_SAMPLER_CONFIG0_FORMAT__MASK) |
|
||||
VIVS_TE_SAMPLER_CONFIG0_FORMAT(native_format);
|
||||
|
||||
uint32_t *native_seamless = native + (TEXTURE_DESC_SIZE / sizeof(uint32_t));
|
||||
memcpy(native_seamless, native, TEXTURE_DESC_SIZE);
|
||||
native_seamless[(TEXDESC_CONFIG1) >> 2] |= VIVS_TE_SAMPLER_CONFIG1_SEAMLESS_CUBE_MAP;
|
||||
|
||||
sv->DESC_ADDR[2].bo = etna_buffer_resource(sv->res)->bo;
|
||||
sv->DESC_ADDR[2].offset = suballoc_offset + 2 * TEXTURE_DESC_SIZE;
|
||||
sv->DESC_ADDR[2].flags = ETNA_RELOC_READ;
|
||||
|
||||
sv->DESC_ADDR[3].bo = etna_buffer_resource(sv->res)->bo;
|
||||
sv->DESC_ADDR[3].offset = suballoc_offset + 3 * TEXTURE_DESC_SIZE;
|
||||
sv->DESC_ADDR[3].flags = ETNA_RELOC_READ;
|
||||
|
||||
sv->has_rb_swap = true;
|
||||
}
|
||||
|
||||
return &sv->base;
|
||||
|
||||
error:
|
||||
|
|
@ -361,8 +389,17 @@ etna_emit_texture_desc(struct etna_context *ctx)
|
|||
if ((1 << x) & active_samplers) {
|
||||
struct etna_sampler_state_desc *ss = etna_sampler_state_desc(ctx->sampler[x]);
|
||||
struct etna_sampler_view_desc *sv = etna_sampler_view_desc(ctx->sampler_view[x]);
|
||||
int desc_base = 0;
|
||||
|
||||
if (sv->has_rb_swap) {
|
||||
struct etna_resource *rsc = etna_resource(sv->base.texture);
|
||||
|
||||
if (rsc->shared && rsc->shared_native_order)
|
||||
desc_base = 2;
|
||||
}
|
||||
|
||||
struct etna_reloc *desc_addr = ss->base.seamless_cube_map ?
|
||||
&sv->DESC_ADDR[1] : &sv->DESC_ADDR[0];
|
||||
&sv->DESC_ADDR[desc_base + 1] : &sv->DESC_ADDR[desc_base];
|
||||
etna_sampler_view_update_descriptor(ctx, stream, sv);
|
||||
etna_set_state_reloc(stream, VIVS_NTE_DESCRIPTOR_ADDR(x), desc_addr);
|
||||
} else if ((1 << x) & ctx->prev_active_samplers){
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ struct etna_sampler_view {
|
|||
/* sampler offset +4*sampler, interleave when committing state */
|
||||
uint32_t config0;
|
||||
uint32_t config0_mask;
|
||||
uint32_t config0_native; /* config0 with native byte order format (A8B8G8R8) */
|
||||
bool has_rb_swap;
|
||||
uint32_t config1;
|
||||
uint32_t config_3d;
|
||||
uint32_t size;
|
||||
|
|
@ -81,6 +83,21 @@ etna_sampler_view(struct pipe_sampler_view *view)
|
|||
return (struct etna_sampler_view *)view;
|
||||
}
|
||||
|
||||
/* Return the config0 value for the sampler view, selecting between PE-internal
|
||||
* format and native byte order format based on the resource's shared state. */
|
||||
static inline uint32_t
|
||||
etna_sampler_view_config0(struct etna_sampler_view *sv)
|
||||
{
|
||||
if (sv->has_rb_swap) {
|
||||
struct etna_resource *rsc = etna_resource(sv->base.texture);
|
||||
|
||||
if (rsc->shared && rsc->shared_native_order)
|
||||
return sv->config0_native;
|
||||
}
|
||||
|
||||
return sv->config0;
|
||||
}
|
||||
|
||||
static void *
|
||||
etna_create_sampler_state_state(struct pipe_context *pipe,
|
||||
const struct pipe_sampler_state *ss)
|
||||
|
|
@ -166,11 +183,10 @@ etna_create_sampler_view_state(struct pipe_context *pctx, struct pipe_resource *
|
|||
struct etna_screen *screen = ctx->screen;
|
||||
uint32_t format = translate_texture_format(so->format);
|
||||
|
||||
/* Shared resources store data in standard byte order (e.g., RGBA for
|
||||
* R8G8B8A8_UNORM). Use the native texture format to read them correctly,
|
||||
* bypassing the BGRA-internal optimization used for internal resources. */
|
||||
if (etna_resource(prsc)->shared && translate_pe_format_rb_swap(so->format))
|
||||
format = remap_texture_format_rb_swap(format);
|
||||
/* For RB_SWAP formats, pre-compute the alternative texture format for when
|
||||
* shared resources hold data in native byte order (RGBA). */
|
||||
const bool rb_swap = translate_pe_format_rb_swap(so->format);
|
||||
const uint32_t native_format = rb_swap ? remap_texture_format_rb_swap(format) : 0;
|
||||
|
||||
const bool ext = !!(format & EXT_FORMAT);
|
||||
const bool astc = !!(format & ASTC_FORMAT);
|
||||
|
|
@ -278,6 +294,12 @@ etna_create_sampler_view_state(struct pipe_context *pctx, struct pipe_resource *
|
|||
VIVS_TE_SAMPLER_CONFIG0_VWRAP(TEXTURE_WRAPMODE_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
if (rb_swap) {
|
||||
sv->config0_native = (sv->config0 & ~VIVS_TE_SAMPLER_CONFIG0_FORMAT__MASK) |
|
||||
VIVS_TE_SAMPLER_CONFIG0_FORMAT(native_format);
|
||||
sv->has_rb_swap = true;
|
||||
}
|
||||
|
||||
return &sv->base;
|
||||
}
|
||||
|
||||
|
|
@ -362,7 +384,7 @@ etna_emit_new_texture_state(struct etna_context *ctx)
|
|||
struct etna_sampler_state *ss = etna_sampler_state(ctx->sampler[x]);
|
||||
struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]);
|
||||
|
||||
val = (ss->config0 & sv->config0_mask) | sv->config0;
|
||||
val = (ss->config0 & sv->config0_mask) | etna_sampler_view_config0(sv);
|
||||
|
||||
if (util_format_description(sv->base.format)->colorspace == UTIL_FORMAT_COLORSPACE_ZS &&
|
||||
ss->base.min_mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
|
||||
|
|
@ -507,8 +529,7 @@ etna_emit_texture_state(struct etna_context *ctx)
|
|||
if ((1 << x) & active_samplers) {
|
||||
struct etna_sampler_state *ss = etna_sampler_state(ctx->sampler[x]);
|
||||
struct etna_sampler_view *sv = etna_sampler_view(ctx->sampler_view[x]);
|
||||
|
||||
val = (ss->config0 & sv->config0_mask) | sv->config0;
|
||||
val = (ss->config0 & sv->config0_mask) | etna_sampler_view_config0(sv);
|
||||
|
||||
if (util_format_description(sv->base.format)->colorspace == UTIL_FORMAT_COLORSPACE_ZS &&
|
||||
ss->base.min_mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue