diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c b/src/gallium/drivers/etnaviv/etnaviv_context.c index c0e56ebecb1..afceda7861d 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_context.c +++ b/src/gallium/drivers/etnaviv/etnaviv_context.c @@ -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; } } diff --git a/src/gallium/drivers/etnaviv/etnaviv_format.c b/src/gallium/drivers/etnaviv/etnaviv_format.c index 547eee49b4d..2e423fefce3 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_format.c +++ b/src/gallium/drivers/etnaviv/etnaviv_format.c @@ -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) diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c index 703d8e449ec..e4fe4640d45 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_resource.c +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c @@ -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; diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.h b/src/gallium/drivers/etnaviv/etnaviv_resource.h index fd6f9a24b45..a4a531cdca3 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_resource.h +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.h @@ -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; diff --git a/src/gallium/drivers/etnaviv/etnaviv_texture_desc.c b/src/gallium/drivers/etnaviv/etnaviv_texture_desc.c index 013872d6c0f..75164c76cbd 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_texture_desc.c +++ b/src/gallium/drivers/etnaviv/etnaviv_texture_desc.c @@ -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){ diff --git a/src/gallium/drivers/etnaviv/etnaviv_texture_state.c b/src/gallium/drivers/etnaviv/etnaviv_texture_state.c index ddde0dd8152..675d0c26abf 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_texture_state.c +++ b/src/gallium/drivers/etnaviv/etnaviv_texture_state.c @@ -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) {