X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fetnaviv%2Fetnaviv_texture.c;h=f3ca6a736fca271737a916f9f49190333c418317;hb=5f7c5f5dd202d27a0a1075e5e11858c960afce9c;hp=b8ebab60822eb4919a3971f9802df25f83f12f68;hpb=58c3ce071c28b2d132cb15e309b3168953d957bd;p=mesa.git diff --git a/src/gallium/drivers/etnaviv/etnaviv_texture.c b/src/gallium/drivers/etnaviv/etnaviv_texture.c index b8ebab60822..f3ca6a736fc 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_texture.c +++ b/src/gallium/drivers/etnaviv/etnaviv_texture.c @@ -32,45 +32,13 @@ #include "etnaviv_context.h" #include "etnaviv_emit.h" #include "etnaviv_format.h" +#include "etnaviv_texture_desc.h" +#include "etnaviv_texture_state.h" #include "etnaviv_translate.h" #include "util/u_inlines.h" #include "util/u_memory.h" -#include - -static void * -etna_create_sampler_state(struct pipe_context *pipe, - const struct pipe_sampler_state *ss) -{ - struct etna_sampler_state *cs = CALLOC_STRUCT(etna_sampler_state); - - if (!cs) - return NULL; - - cs->TE_SAMPLER_CONFIG0 = - VIVS_TE_SAMPLER_CONFIG0_UWRAP(translate_texture_wrapmode(ss->wrap_s)) | - VIVS_TE_SAMPLER_CONFIG0_VWRAP(translate_texture_wrapmode(ss->wrap_t)) | - VIVS_TE_SAMPLER_CONFIG0_MIN(translate_texture_filter(ss->min_img_filter)) | - VIVS_TE_SAMPLER_CONFIG0_MIP(translate_texture_mipfilter(ss->min_mip_filter)) | - VIVS_TE_SAMPLER_CONFIG0_MAG(translate_texture_filter(ss->mag_img_filter)) | - COND(ss->normalized_coords, VIVS_TE_SAMPLER_CONFIG0_ROUND_UV); - cs->TE_SAMPLER_CONFIG1 = 0; /* VIVS_TE_SAMPLER_CONFIG1 (swizzle, extended - format) fully determined by sampler view */ - cs->TE_SAMPLER_LOD_CONFIG = - COND(ss->lod_bias != 0.0, VIVS_TE_SAMPLER_LOD_CONFIG_BIAS_ENABLE) | - VIVS_TE_SAMPLER_LOD_CONFIG_BIAS(etna_float_to_fixp55(ss->lod_bias)); - - if (ss->min_mip_filter != PIPE_TEX_MIPFILTER_NONE) { - cs->min_lod = etna_float_to_fixp55(ss->min_lod); - cs->max_lod = etna_float_to_fixp55(ss->max_lod); - } else { - /* when not mipmapping, we need to set max/min lod so that always - * lowest LOD is selected */ - cs->min_lod = cs->max_lod = etna_float_to_fixp55(ss->min_lod); - } - - return cs; -} +#include "drm-uapi/drm_fourcc.h" static void etna_bind_sampler_states(struct pipe_context *pctx, enum pipe_shader_type shader, @@ -106,20 +74,82 @@ etna_bind_sampler_states(struct pipe_context *pctx, enum pipe_shader_type shader ctx->dirty |= ETNA_DIRTY_SAMPLERS; } -static void -etna_delete_sampler_state(struct pipe_context *pctx, void *ss) +static bool +etna_configure_sampler_ts(struct etna_sampler_ts *sts, struct pipe_sampler_view *pview, bool enable) { - FREE(ss); + bool dirty = (sts->enable != enable); + + assert(sts); + sts->enable = enable; + + if (!enable) { + sts->TS_SAMPLER_CONFIG = 0; + sts->TS_SAMPLER_STATUS_BASE.bo = NULL; + return dirty; + } + + struct etna_resource *rsc = etna_resource(pview->texture); + struct etna_resource_level *lev = &rsc->levels[0]; + + if (lev->clear_value != sts->TS_SAMPLER_CLEAR_VALUE) + dirty = true; + + assert(rsc->ts_bo && lev->ts_valid); + + sts->mode = lev->ts_mode; + sts->TS_SAMPLER_CONFIG = + VIVS_TS_SAMPLER_CONFIG_ENABLE | + COND(lev->ts_compress_fmt >= 0, VIVS_TS_SAMPLER_CONFIG_COMPRESSION) | + VIVS_TS_SAMPLER_CONFIG_COMPRESSION_FORMAT(lev->ts_compress_fmt); + sts->TS_SAMPLER_CLEAR_VALUE = lev->clear_value; + sts->TS_SAMPLER_CLEAR_VALUE2 = lev->clear_value >> 32; + sts->TS_SAMPLER_STATUS_BASE.bo = rsc->ts_bo; + sts->TS_SAMPLER_STATUS_BASE.offset = lev->ts_offset; + sts->TS_SAMPLER_STATUS_BASE.flags = ETNA_RELOC_READ; + + return dirty; } -static void -etna_update_sampler_source(struct pipe_sampler_view *view) +/* Return true if the GPU can use sampler TS with this sampler view. + * Sampler TS is an optimization used when rendering to textures, where + * a resolve-in-place can be avoided when rendering has left a (valid) TS. + */ +static bool +etna_can_use_sampler_ts(struct pipe_sampler_view *view, int num) +{ + /* Can use sampler TS when: + * - the hardware supports sampler TS. + * - the sampler view will be bound to sampler texture); + struct etna_screen *screen = etna_screen(rsc->base.screen); + + return VIV_FEATURE(screen, chipMinorFeatures2, TEXTURE_TILED_READ) && + num < VIVS_TS_SAMPLER__LEN && + rsc->base.target != PIPE_BUFFER && + (rsc->levels[0].ts_compress_fmt < 0 || screen->specs.v4_compression) && + view->u.tex.first_level == 0 && MIN2(view->u.tex.last_level, rsc->base.last_level) == 0 && + rsc->levels[0].ts_valid; +} + +void +etna_update_sampler_source(struct pipe_sampler_view *view, int num) { struct etna_resource *base = etna_resource(view->texture); struct etna_resource *to = base, *from = base; + struct etna_context *ctx = etna_context(view->context); + bool enable_sampler_ts = false; - if (base->external && etna_resource_newer(etna_resource(base->external), base)) - from = etna_resource(base->external); + if (base->render && etna_resource_newer(etna_resource(base->render), base)) + from = etna_resource(base->render); if (base->texture) to = etna_resource(base->texture); @@ -128,11 +158,26 @@ etna_update_sampler_source(struct pipe_sampler_view *view) etna_copy_resource(view->context, &to->base, &from->base, 0, view->texture->last_level); to->seqno = from->seqno; + ctx->dirty |= ETNA_DIRTY_TEXTURE_CACHES; } else if ((to == from) && etna_resource_needs_flush(to)) { - /* Resolve TS if needed, remove when adding sampler TS */ - etna_copy_resource(view->context, &to->base, &from->base, 0, - view->texture->last_level); + if (ctx->ts_for_sampler_view && etna_can_use_sampler_ts(view, num)) { + enable_sampler_ts = true; + /* Do not set flush_seqno because the resolve-to-self was bypassed */ + } else { + /* Resolve TS if needed */ + etna_copy_resource(view->context, &to->base, &from->base, 0, + view->texture->last_level); + to->flush_seqno = from->seqno; + ctx->dirty |= ETNA_DIRTY_TEXTURE_CACHES; + } + } else if ((to == from) && (to->flush_seqno < from->seqno)) { to->flush_seqno = from->seqno; + ctx->dirty |= ETNA_DIRTY_TEXTURE_CACHES; + } + if (ctx->ts_for_sampler_view && + etna_configure_sampler_ts(ctx->ts_for_sampler_view(view), view, enable_sampler_ts)) { + ctx->dirty |= ETNA_DIRTY_SAMPLER_VIEWS | ETNA_DIRTY_TEXTURE_CACHES; + ctx->dirty_sampler_views |= (1 << num); } } @@ -147,7 +192,9 @@ etna_resource_sampler_compatible(struct etna_resource *res) if (res->layout == ETNA_LAYOUT_SUPER_TILED && VIV_FEATURE(screen, chipMinorFeatures2, SUPERTILED_TEXTURE)) return true; - /* TODO: LINEAR_TEXTURE_SUPPORT */ + /* This GPU supports texturing from linear textures? */ + if (res->layout == ETNA_LAYOUT_LINEAR && VIV_FEATURE(screen, chipMinorFeatures1, LINEAR_TEXTURE_SUPPORT)) + return true; /* Otherwise, only support tiled layouts */ if (res->layout != ETNA_LAYOUT_TILED) @@ -164,22 +211,10 @@ etna_resource_sampler_compatible(struct etna_resource *res) return true; } -static struct pipe_sampler_view * -etna_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc, - const struct pipe_sampler_view *so) +struct etna_resource * +etna_texture_handle_incompatible(struct pipe_context *pctx, struct pipe_resource *prsc) { - struct etna_sampler_view *sv = CALLOC_STRUCT(etna_sampler_view); struct etna_resource *res = etna_resource(prsc); - struct etna_context *ctx = etna_context(pctx); - const uint32_t format = translate_texture_format(so->format); - const bool ext = !!(format & EXT_FORMAT); - const uint32_t swiz = get_texture_swiz(so->format, so->swizzle_r, - so->swizzle_g, so->swizzle_b, - so->swizzle_a); - - if (!sv) - return NULL; - if (!etna_resource_sampler_compatible(res)) { /* The original resource is not compatible with the sampler. * Allocate an appropriately tiled texture. */ @@ -194,79 +229,11 @@ etna_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc, } if (!res->texture) { - free(sv); return NULL; } res = etna_resource(res->texture); } - - sv->base = *so; - pipe_reference_init(&sv->base.reference, 1); - sv->base.texture = NULL; - pipe_resource_reference(&sv->base.texture, prsc); - sv->base.context = pctx; - - /* merged with sampler state */ - sv->TE_SAMPLER_CONFIG0 = COND(!ext, VIVS_TE_SAMPLER_CONFIG0_FORMAT(format)); - sv->TE_SAMPLER_CONFIG0_MASK = 0xffffffff; - - switch (sv->base.target) { - case PIPE_TEXTURE_1D: - /* For 1D textures, we will have a height of 1, so we can use 2D - * but set T wrap to repeat */ - sv->TE_SAMPLER_CONFIG0_MASK = ~VIVS_TE_SAMPLER_CONFIG0_VWRAP__MASK; - sv->TE_SAMPLER_CONFIG0 |= VIVS_TE_SAMPLER_CONFIG0_VWRAP(TEXTURE_WRAPMODE_REPEAT); - /* fallthrough */ - case PIPE_TEXTURE_2D: - case PIPE_TEXTURE_RECT: - sv->TE_SAMPLER_CONFIG0 |= VIVS_TE_SAMPLER_CONFIG0_TYPE(TEXTURE_TYPE_2D); - break; - case PIPE_TEXTURE_CUBE: - sv->TE_SAMPLER_CONFIG0 |= VIVS_TE_SAMPLER_CONFIG0_TYPE(TEXTURE_TYPE_CUBE_MAP); - break; - default: - BUG("Unhandled texture target"); - free(sv); - return NULL; - } - - sv->TE_SAMPLER_CONFIG1 = COND(ext, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(format)) | - VIVS_TE_SAMPLER_CONFIG1_HALIGN(res->halign) | swiz; - sv->TE_SAMPLER_SIZE = VIVS_TE_SAMPLER_SIZE_WIDTH(res->base.width0) | - VIVS_TE_SAMPLER_SIZE_HEIGHT(res->base.height0); - sv->TE_SAMPLER_LOG_SIZE = - VIVS_TE_SAMPLER_LOG_SIZE_WIDTH(etna_log2_fixp55(res->base.width0)) | - VIVS_TE_SAMPLER_LOG_SIZE_HEIGHT(etna_log2_fixp55(res->base.height0)); - - /* Set up levels-of-detail */ - for (int lod = 0; lod <= res->base.last_level; ++lod) { - sv->TE_SAMPLER_LOD_ADDR[lod].bo = res->bo; - sv->TE_SAMPLER_LOD_ADDR[lod].offset = res->levels[lod].offset; - sv->TE_SAMPLER_LOD_ADDR[lod].flags = ETNA_RELOC_READ; - } - sv->min_lod = sv->base.u.tex.first_level << 5; - sv->max_lod = MIN2(sv->base.u.tex.last_level, res->base.last_level) << 5; - - /* Workaround for npot textures -- it appears that only CLAMP_TO_EDGE is - * supported when the appropriate capability is not set. */ - if (!ctx->specs.npot_tex_any_wrap && - (!util_is_power_of_two(res->base.width0) || !util_is_power_of_two(res->base.height0))) { - sv->TE_SAMPLER_CONFIG0_MASK = ~(VIVS_TE_SAMPLER_CONFIG0_UWRAP__MASK | - VIVS_TE_SAMPLER_CONFIG0_VWRAP__MASK); - sv->TE_SAMPLER_CONFIG0 |= - VIVS_TE_SAMPLER_CONFIG0_UWRAP(TEXTURE_WRAPMODE_CLAMP_TO_EDGE) | - VIVS_TE_SAMPLER_CONFIG0_VWRAP(TEXTURE_WRAPMODE_CLAMP_TO_EDGE); - } - - return &sv->base; -} - -static void -etna_sampler_view_destroy(struct pipe_context *pctx, - struct pipe_sampler_view *view) -{ - pipe_resource_reference(&view->texture, NULL); - FREE(view); + return res; } static void @@ -275,12 +242,14 @@ set_sampler_views(struct etna_context *ctx, unsigned start, unsigned end, { unsigned i, j; uint32_t mask = 1 << start; + uint32_t prev_active_sampler_views = ctx->active_sampler_views; for (i = start, j = 0; j < nr; i++, j++, mask <<= 1) { pipe_sampler_view_reference(&ctx->sampler_view[i], views[j]); - if (views[j]) + if (views[j]) { ctx->active_sampler_views |= mask; - else + ctx->dirty_sampler_views |= mask; + } else ctx->active_sampler_views &= ~mask; } @@ -288,6 +257,9 @@ set_sampler_views(struct etna_context *ctx, unsigned start, unsigned end, pipe_sampler_view_reference(&ctx->sampler_view[i], NULL); ctx->active_sampler_views &= ~mask; } + + /* sampler views that changed state (even to inactive) are also dirty */ + ctx->dirty_sampler_views |= ctx->active_sampler_views ^ prev_active_sampler_views; } static inline void @@ -322,11 +294,6 @@ etna_set_sampler_views(struct pipe_context *pctx, enum pipe_shader_type shader, ctx->dirty |= ETNA_DIRTY_SAMPLER_VIEWS | ETNA_DIRTY_TEXTURE_CACHES; - for (unsigned idx = 0; idx < num_views; ++idx) { - if (views[idx]) - etna_update_sampler_source(views[idx]); - } - switch (shader) { case PIPE_SHADER_FRAGMENT: etna_fragtex_set_sampler_views(ctx, num_views, views); @@ -344,17 +311,28 @@ etna_texture_barrier(struct pipe_context *pctx, unsigned flags) struct etna_context *ctx = etna_context(pctx); /* clear color and texture cache to make sure that texture unit reads * what has been written */ + mtx_lock(&ctx->lock); etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_TEXTURE); + mtx_unlock(&ctx->lock); +} + +uint32_t +active_samplers_bits(struct etna_context *ctx) +{ + return ctx->active_sampler_views & ctx->active_samplers; } void etna_texture_init(struct pipe_context *pctx) { - pctx->create_sampler_state = etna_create_sampler_state; + struct etna_context *ctx = etna_context(pctx); + pctx->bind_sampler_states = etna_bind_sampler_states; - pctx->delete_sampler_state = etna_delete_sampler_state; pctx->set_sampler_views = etna_set_sampler_views; - pctx->create_sampler_view = etna_create_sampler_view; - pctx->sampler_view_destroy = etna_sampler_view_destroy; pctx->texture_barrier = etna_texture_barrier; + + if (ctx->specs.halti >= 5) + etna_texture_desc_init(pctx); + else + etna_texture_state_init(pctx); }