diff options
author | Rob Clark <[email protected]> | 2016-04-19 09:02:23 -0400 |
---|---|---|
committer | Rob Clark <[email protected]> | 2016-04-24 13:40:57 -0400 |
commit | adf795432f788b33822d3a94b704be4ca536c8f1 (patch) | |
tree | ea8b334ab469492fa9666eabba7a75a19172aca8 /src/gallium/drivers/freedreno/a4xx | |
parent | a148300b13fbda239146c163549868cc903c0a70 (diff) |
freedreno/a4xx: better workaround for astc+srgb
This *seems* like a hw bug, and maybe only applies to certain a4xx
variants/revisions. But setting the SRGB bit in sampler view state
(texconst0) causes invalid alpha for ASTC textures. Work around this
setting up a second texture state and using that to sample alpha
separately.
This way, srgb->linear conversion happens in hw *prior* to
interpolation.
This fixes 546 dEQP tests: dEQP-GLES3.functional.texture.*astc*srgb*
Signed-off-by: Rob Clark <[email protected]>
Diffstat (limited to 'src/gallium/drivers/freedreno/a4xx')
-rw-r--r-- | src/gallium/drivers/freedreno/a4xx/fd4_context.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/a4xx/fd4_draw.c | 11 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/a4xx/fd4_emit.c | 41 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/a4xx/fd4_texture.c | 42 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/a4xx/fd4_texture.h | 1 |
5 files changed, 88 insertions, 10 deletions
diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_context.h b/src/gallium/drivers/freedreno/a4xx/fd4_context.h index 8996de932b8..9467fc529bf 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_context.h +++ b/src/gallium/drivers/freedreno/a4xx/fd4_context.h @@ -85,6 +85,9 @@ struct fd4_context { */ uint16_t fsaturate_s, fsaturate_t, fsaturate_r; + /* bitmask of samplers which need astc srgb workaround: */ + uint16_t vastc_srgb, fastc_srgb; + /* some state changes require a different shader variant. Keep * track of this so we know when we need to re-emit shader state * due to variant change. See fixup_shader_state() diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_draw.c b/src/gallium/drivers/freedreno/a4xx/fd4_draw.c index e874d223187..68e1f53e2dd 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_draw.c +++ b/src/gallium/drivers/freedreno/a4xx/fd4_draw.c @@ -93,12 +93,14 @@ fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key) if (last_key->has_per_samp || key->has_per_samp) { if ((last_key->vsaturate_s != key->vsaturate_s) || (last_key->vsaturate_t != key->vsaturate_t) || - (last_key->vsaturate_r != key->vsaturate_r)) + (last_key->vsaturate_r != key->vsaturate_r) || + (last_key->vastc_srgb != key->vastc_srgb)) ctx->prog.dirty |= FD_SHADER_DIRTY_VP; if ((last_key->fsaturate_s != key->fsaturate_s) || (last_key->fsaturate_t != key->fsaturate_t) || - (last_key->fsaturate_r != key->fsaturate_r)) + (last_key->fsaturate_r != key->fsaturate_r) || + (last_key->fastc_srgb != key->fastc_srgb)) ctx->prog.dirty |= FD_SHADER_DIRTY_FP; } @@ -132,13 +134,16 @@ fd4_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info) // ie. float16 and smaller use half, float32 use full.. .half_precision = !!(fd_mesa_debug & FD_DBG_FRAGHALF), .ucp_enables = ctx->rasterizer->clip_plane_enable, - .has_per_samp = (fd4_ctx->fsaturate || fd4_ctx->vsaturate), + .has_per_samp = (fd4_ctx->fsaturate || fd4_ctx->vsaturate || + fd4_ctx->fastc_srgb || fd4_ctx->vastc_srgb), .vsaturate_s = fd4_ctx->vsaturate_s, .vsaturate_t = fd4_ctx->vsaturate_t, .vsaturate_r = fd4_ctx->vsaturate_r, .fsaturate_s = fd4_ctx->fsaturate_s, .fsaturate_t = fd4_ctx->fsaturate_t, .fsaturate_r = fd4_ctx->fsaturate_r, + .vastc_srgb = fd4_ctx->vastc_srgb, + .fastc_srgb = fd4_ctx->fastc_srgb, }, .rasterflat = ctx->rasterizer->flatshade, .sprite_coord_enable = ctx->rasterizer->sprite_coord_enable, diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_emit.c b/src/gallium/drivers/freedreno/a4xx/fd4_emit.c index ba5d48909fa..27614f07de5 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_emit.c +++ b/src/gallium/drivers/freedreno/a4xx/fd4_emit.c @@ -123,7 +123,8 @@ fd4_emit_const_bo(struct fd_ringbuffer *ring, enum shader_t type, boolean write, static void emit_textures(struct fd_context *ctx, struct fd_ringbuffer *ring, - enum adreno_state_block sb, struct fd_texture_stateobj *tex) + enum adreno_state_block sb, struct fd_texture_stateobj *tex, + const struct ir3_shader_variant *v) { static const uint32_t bcolor_reg[] = { [SB_VERT_TEX] = REG_A4XX_TPL1_TP_VS_BORDER_COLOR_BASE_ADDR, @@ -174,12 +175,14 @@ emit_textures(struct fd_context *ctx, struct fd_ringbuffer *ring, } if (tex->num_textures > 0) { + unsigned num_textures = tex->num_textures + v->astc_srgb.count; + /* emit texture state: */ - OUT_PKT3(ring, CP_LOAD_STATE, 2 + (8 * tex->num_textures)); + OUT_PKT3(ring, CP_LOAD_STATE, 2 + (8 * num_textures)); OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(0) | CP_LOAD_STATE_0_STATE_SRC(SS_DIRECT) | CP_LOAD_STATE_0_STATE_BLOCK(sb) | - CP_LOAD_STATE_0_NUM_UNIT(tex->num_textures)); + CP_LOAD_STATE_0_NUM_UNIT(num_textures)); OUT_RING(ring, CP_LOAD_STATE_1_STATE_TYPE(ST_CONSTANTS) | CP_LOAD_STATE_1_EXT_SRC_ADDR(0)); for (i = 0; i < tex->num_textures; i++) { @@ -202,6 +205,34 @@ emit_textures(struct fd_context *ctx, struct fd_ringbuffer *ring, OUT_RING(ring, 0x00000000); OUT_RING(ring, 0x00000000); } + + for (i = 0; i < v->astc_srgb.count; i++) { + static const struct fd4_pipe_sampler_view dummy_view = {}; + const struct fd4_pipe_sampler_view *view; + unsigned idx = v->astc_srgb.orig_idx[i]; + + view = tex->textures[idx] ? + fd4_pipe_sampler_view(tex->textures[idx]) : + &dummy_view; + + debug_assert(view->texconst0 & A4XX_TEX_CONST_0_SRGB); + + OUT_RING(ring, view->texconst0 & ~A4XX_TEX_CONST_0_SRGB); + OUT_RING(ring, view->texconst1); + OUT_RING(ring, view->texconst2); + OUT_RING(ring, view->texconst3); + if (view->base.texture) { + struct fd_resource *rsc = fd_resource(view->base.texture); + OUT_RELOC(ring, rsc->bo, view->offset, view->texconst4, 0); + } else { + OUT_RING(ring, 0x00000000); + } + OUT_RING(ring, 0x00000000); + OUT_RING(ring, 0x00000000); + OUT_RING(ring, 0x00000000); + } + } else { + debug_assert(v->astc_srgb.count == 0); } OUT_PKT0(ring, bcolor_reg[sb], 1); @@ -681,14 +712,14 @@ fd4_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, if (dirty & FD_DIRTY_VERTTEX) { if (vp->has_samp) - emit_textures(ctx, ring, SB_VERT_TEX, &ctx->verttex); + emit_textures(ctx, ring, SB_VERT_TEX, &ctx->verttex, vp); else dirty &= ~FD_DIRTY_VERTTEX; } if (dirty & FD_DIRTY_FRAGTEX) { if (fp->has_samp) - emit_textures(ctx, ring, SB_FRAG_TEX, &ctx->fragtex); + emit_textures(ctx, ring, SB_FRAG_TEX, &ctx->fragtex, fp); else dirty &= ~FD_DIRTY_FRAGTEX; } diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_texture.c b/src/gallium/drivers/freedreno/a4xx/fd4_texture.c index 38348580e21..6d9ecb7da24 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_texture.c +++ b/src/gallium/drivers/freedreno/a4xx/fd4_texture.c @@ -209,6 +209,13 @@ tex_type(unsigned target) } } +static bool +use_astc_srgb_workaround(struct pipe_context *pctx, enum pipe_format format) +{ + return (fd_screen(pctx->screen)->gpu_id == 420) && + (util_format_description(format)->layout == UTIL_FORMAT_LAYOUT_ASTC); +} + static struct pipe_sampler_view * fd4_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc, const struct pipe_sampler_view *cso) @@ -233,8 +240,11 @@ fd4_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc, fd4_tex_swiz(cso->format, cso->swizzle_r, cso->swizzle_g, cso->swizzle_b, cso->swizzle_a); - if (util_format_is_srgb(cso->format)) + if (util_format_is_srgb(cso->format)) { + if (use_astc_srgb_workaround(pctx, cso->format)) + so->astc_srgb = true; so->texconst0 |= A4XX_TEX_CONST_0_SRGB; + } if (cso->target == PIPE_BUFFER) { unsigned elements = cso->u.buf.last_element - @@ -296,11 +306,39 @@ fd4_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc, return &so->base; } +static void +fd4_set_sampler_views(struct pipe_context *pctx, unsigned shader, + unsigned start, unsigned nr, + struct pipe_sampler_view **views) +{ + struct fd_context *ctx = fd_context(pctx); + struct fd4_context *fd4_ctx = fd4_context(ctx); + uint16_t astc_srgb = 0; + unsigned i; + + for (i = 0; i < nr; i++) { + if (views[i]) { + struct fd4_pipe_sampler_view *view = + fd4_pipe_sampler_view(views[i]); + if (view->astc_srgb) + astc_srgb |= (1 << i); + } + } + + fd_set_sampler_views(pctx, shader, start, nr, views); + + if (shader == PIPE_SHADER_FRAGMENT) { + fd4_ctx->fastc_srgb = astc_srgb; + } else if (shader == PIPE_SHADER_VERTEX) { + fd4_ctx->vastc_srgb = astc_srgb; + } +} + void fd4_texture_init(struct pipe_context *pctx) { pctx->create_sampler_state = fd4_sampler_state_create; pctx->bind_sampler_states = fd4_sampler_states_bind; pctx->create_sampler_view = fd4_sampler_view_create; - pctx->set_sampler_views = fd_set_sampler_views; + pctx->set_sampler_views = fd4_set_sampler_views; } diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_texture.h b/src/gallium/drivers/freedreno/a4xx/fd4_texture.h index 6ca34ade60d..21ceadd8c63 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_texture.h +++ b/src/gallium/drivers/freedreno/a4xx/fd4_texture.h @@ -53,6 +53,7 @@ struct fd4_pipe_sampler_view { struct pipe_sampler_view base; uint32_t texconst0, texconst1, texconst2, texconst3, texconst4; uint32_t offset; + bool astc_srgb; }; static inline struct fd4_pipe_sampler_view * |