From: Rob Clark Date: Tue, 19 Apr 2016 13:02:23 +0000 (-0400) Subject: freedreno/a4xx: lower srgb in shader for astc textures X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=899bd63acefd49a668e11c42d2ad92fa55aa157d;p=mesa.git freedreno/a4xx: lower srgb in shader for astc textures 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 by doing the srgb->linear conversion in the shader instead. This fixes 392 dEQP tests: dEQP-GLES3.functional.texture.*astc*srgb* (The remaining fails seem to be a bug w/ ASTC + linear filtering, also possibly a420.0 specific.) Signed-off-by: Rob Clark --- diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_context.h b/src/gallium/drivers/freedreno/a4xx/fd4_context.h index 8996de932b8..a08c3c3119b 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 srgb lowering in vertex/frag shader: */ + uint16_t vlower_srgb, flower_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..a0866261fcb 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->vlower_srgb != key->vlower_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->flower_srgb != key->flower_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->flower_srgb || fd4_ctx->vlower_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, + .vlower_srgb = fd4_ctx->vlower_srgb, + .flower_srgb = fd4_ctx->flower_srgb, }, .rasterflat = ctx->rasterizer->flatshade, .sprite_coord_enable = ctx->rasterizer->sprite_coord_enable, diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_texture.c b/src/gallium/drivers/freedreno/a4xx/fd4_texture.c index 38348580e21..eee7a39adfd 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_srgb_lowering(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,12 @@ 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)) - so->texconst0 |= A4XX_TEX_CONST_0_SRGB; + if (util_format_is_srgb(cso->format)) { + if (use_srgb_lowering(pctx, cso->format)) + so->lower_srgb = true; + else + so->texconst0 |= A4XX_TEX_CONST_0_SRGB; + } if (cso->target == PIPE_BUFFER) { unsigned elements = cso->u.buf.last_element - @@ -296,11 +307,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 lower_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->lower_srgb) + lower_srgb |= (1 << i); + } + } + + fd_set_sampler_views(pctx, shader, start, nr, views); + + if (shader == PIPE_SHADER_FRAGMENT) { + fd4_ctx->flower_srgb = lower_srgb; + } else if (shader == PIPE_SHADER_VERTEX) { + fd4_ctx->vlower_srgb = lower_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..af2140db504 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 lower_srgb; }; static inline struct fd4_pipe_sampler_view * diff --git a/src/gallium/drivers/freedreno/ir3/ir3_nir.c b/src/gallium/drivers/freedreno/ir3/ir3_nir.c index 897b3b963be..7836789de8f 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_nir.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_nir.c @@ -58,6 +58,7 @@ ir3_key_lowers_nir(const struct ir3_shader_key *key) { return key->fsaturate_s | key->fsaturate_t | key->fsaturate_r | key->vsaturate_s | key->vsaturate_t | key->vsaturate_r | + key->vlower_srgb | key->flower_srgb | key->ucp_enables | key->color_two_side; } @@ -85,11 +86,13 @@ ir3_optimize_nir(struct ir3_shader *shader, nir_shader *s, tex_options.saturate_s = key->fsaturate_s; tex_options.saturate_t = key->fsaturate_t; tex_options.saturate_r = key->fsaturate_r; + tex_options.lower_srgb = key->flower_srgb; break; case SHADER_VERTEX: tex_options.saturate_s = key->vsaturate_s; tex_options.saturate_t = key->vsaturate_t; tex_options.saturate_r = key->vsaturate_r; + tex_options.lower_srgb = key->vlower_srgb; break; } } diff --git a/src/gallium/drivers/freedreno/ir3/ir3_shader.c b/src/gallium/drivers/freedreno/ir3/ir3_shader.c index c05b52e7a5e..3d38088510a 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_shader.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_shader.c @@ -223,6 +223,7 @@ ir3_shader_variant(struct ir3_shader *shader, struct ir3_shader_key key) key.vsaturate_s = 0; key.vsaturate_t = 0; key.vsaturate_r = 0; + key.vlower_srgb = 0; } break; case SHADER_VERTEX: @@ -233,6 +234,7 @@ ir3_shader_variant(struct ir3_shader *shader, struct ir3_shader_key key) key.fsaturate_s = 0; key.fsaturate_t = 0; key.fsaturate_r = 0; + key.flower_srgb = 0; } break; } diff --git a/src/gallium/drivers/freedreno/ir3/ir3_shader.h b/src/gallium/drivers/freedreno/ir3/ir3_shader.h index c89dc29ff08..82cde51e635 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_shader.h +++ b/src/gallium/drivers/freedreno/ir3/ir3_shader.h @@ -104,6 +104,9 @@ struct ir3_shader_key { * shader: */ uint16_t fsaturate_s, fsaturate_t, fsaturate_r; + + /* bitmask of samplers which need srgb->linear lowering: */ + uint16_t vlower_srgb, flower_srgb; }; static inline bool