From 6eb9483912539f0962fd62bc50039c6f768f1621 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Nicolai=20H=C3=A4hnle?= Date: Sat, 23 Sep 2017 10:29:51 +0200 Subject: [PATCH] radeonsi: clamp border colors for upgraded depth textures MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The hardware does this automatically for unorm formats, but we need to do it manually for unorm depth formats that have been upgraded to Z32_FLOAT. Fixes dEQP-GLES31.functional.texture.border_clamp.range_clamp.nearest_unorm_depth and others. Fixes: d4d9ec55c589 ("radeonsi: implement TC-compatible HTILE") Reviewed-by: Marek Olšák Tested-by: Dieter Nützel --- src/gallium/drivers/radeonsi/si_state.c | 119 ++++++++++++------------ 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index 8a14404f0e8..1463d3c9ca1 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -3895,16 +3895,54 @@ static bool wrap_mode_uses_border_color(unsigned wrap, bool linear_filter) wrap == PIPE_TEX_WRAP_MIRROR_CLAMP)); } -static bool sampler_state_needs_border_color(const struct pipe_sampler_state *state) +static uint32_t si_translate_border_color(struct si_context *sctx, + const struct pipe_sampler_state *state, + const union pipe_color_union *color) { bool linear_filter = state->min_img_filter != PIPE_TEX_FILTER_NEAREST || state->mag_img_filter != PIPE_TEX_FILTER_NEAREST; - return (state->border_color.ui[0] || state->border_color.ui[1] || - state->border_color.ui[2] || state->border_color.ui[3]) && - (wrap_mode_uses_border_color(state->wrap_s, linear_filter) || - wrap_mode_uses_border_color(state->wrap_t, linear_filter) || - wrap_mode_uses_border_color(state->wrap_r, linear_filter)); + if ((color->f[0] == 0 && color->f[1] == 0 && + color->f[2] == 0 && color->f[3] == 0) || + (!wrap_mode_uses_border_color(state->wrap_s, linear_filter) && + !wrap_mode_uses_border_color(state->wrap_t, linear_filter) && + !wrap_mode_uses_border_color(state->wrap_r, linear_filter))) + return S_008F3C_BORDER_COLOR_TYPE(V_008F3C_SQ_TEX_BORDER_COLOR_TRANS_BLACK); + + if (color->f[0] == 0 && color->f[1] == 0 && + color->f[2] == 0 && color->f[3] == 1) + return S_008F3C_BORDER_COLOR_TYPE(V_008F3C_SQ_TEX_BORDER_COLOR_OPAQUE_BLACK); + if (color->f[0] == 1 && color->f[1] == 1 && + color->f[2] == 1 && color->f[3] == 1) + return S_008F3C_BORDER_COLOR_TYPE(V_008F3C_SQ_TEX_BORDER_COLOR_OPAQUE_WHITE); + + int i; + + /* Check if the border has been uploaded already. */ + for (i = 0; i < sctx->border_color_count; i++) + if (memcmp(&sctx->border_color_table[i], color, + sizeof(*color)) == 0) + break; + + if (i >= SI_MAX_BORDER_COLORS) { + /* Getting 4096 unique border colors is very unlikely. */ + fprintf(stderr, "radeonsi: The border color table is full. " + "Any new border colors will be just black. " + "Please file a bug.\n"); + return S_008F3C_BORDER_COLOR_TYPE(V_008F3C_SQ_TEX_BORDER_COLOR_TRANS_BLACK); + } + + if (i == sctx->border_color_count) { + /* Upload a new border color. */ + memcpy(&sctx->border_color_table[i], color, + sizeof(*color)); + util_memcpy_cpu_to_le32(&sctx->border_color_map[i], + color, sizeof(*color)); + sctx->border_color_count++; + } + + return S_008F3C_BORDER_COLOR_PTR(i) | + S_008F3C_BORDER_COLOR_TYPE(V_008F3C_SQ_TEX_BORDER_COLOR_REGISTER); } static void *si_create_sampler_state(struct pipe_context *ctx, @@ -3913,64 +3951,15 @@ static void *si_create_sampler_state(struct pipe_context *ctx, struct si_context *sctx = (struct si_context *)ctx; struct r600_common_screen *rscreen = sctx->b.screen; struct si_sampler_state *rstate = CALLOC_STRUCT(si_sampler_state); - unsigned border_color_type, border_color_index = 0; unsigned max_aniso = rscreen->force_aniso >= 0 ? rscreen->force_aniso : state->max_anisotropy; unsigned max_aniso_ratio = r600_tex_aniso_filter(max_aniso); + union pipe_color_union clamped_border_color; if (!rstate) { return NULL; } - if (!sampler_state_needs_border_color(state)) - border_color_type = V_008F3C_SQ_TEX_BORDER_COLOR_TRANS_BLACK; - else if (state->border_color.f[0] == 0 && - state->border_color.f[1] == 0 && - state->border_color.f[2] == 0 && - state->border_color.f[3] == 0) - border_color_type = V_008F3C_SQ_TEX_BORDER_COLOR_TRANS_BLACK; - else if (state->border_color.f[0] == 0 && - state->border_color.f[1] == 0 && - state->border_color.f[2] == 0 && - state->border_color.f[3] == 1) - border_color_type = V_008F3C_SQ_TEX_BORDER_COLOR_OPAQUE_BLACK; - else if (state->border_color.f[0] == 1 && - state->border_color.f[1] == 1 && - state->border_color.f[2] == 1 && - state->border_color.f[3] == 1) - border_color_type = V_008F3C_SQ_TEX_BORDER_COLOR_OPAQUE_WHITE; - else { - int i; - - border_color_type = V_008F3C_SQ_TEX_BORDER_COLOR_REGISTER; - - /* Check if the border has been uploaded already. */ - for (i = 0; i < sctx->border_color_count; i++) - if (memcmp(&sctx->border_color_table[i], &state->border_color, - sizeof(state->border_color)) == 0) - break; - - if (i >= SI_MAX_BORDER_COLORS) { - /* Getting 4096 unique border colors is very unlikely. */ - fprintf(stderr, "radeonsi: The border color table is full. " - "Any new border colors will be just black. " - "Please file a bug.\n"); - border_color_type = V_008F3C_SQ_TEX_BORDER_COLOR_TRANS_BLACK; - } else { - if (i == sctx->border_color_count) { - /* Upload a new border color. */ - memcpy(&sctx->border_color_table[i], &state->border_color, - sizeof(state->border_color)); - util_memcpy_cpu_to_le32(&sctx->border_color_map[i], - &state->border_color, - sizeof(state->border_color)); - sctx->border_color_count++; - } - - border_color_index = i; - } - } - #ifdef DEBUG rstate->magic = SI_SAMPLER_STATE_MAGIC; #endif @@ -3995,11 +3984,23 @@ static void *si_create_sampler_state(struct pipe_context *ctx, S_008F38_DISABLE_LSB_CEIL(sctx->b.chip_class <= VI) | S_008F38_FILTER_PREC_FIX(1) | S_008F38_ANISO_OVERRIDE(sctx->b.chip_class >= VI)); - rstate->val[3] = S_008F3C_BORDER_COLOR_PTR(border_color_index) | - S_008F3C_BORDER_COLOR_TYPE(border_color_type); + rstate->val[3] = si_translate_border_color(sctx, state, &state->border_color); + /* Create sampler resource for upgraded depth textures. */ memcpy(rstate->upgraded_depth_val, rstate->val, sizeof(rstate->val)); - rstate->upgraded_depth_val[3] |= S_008F3C_UPGRADED_DEPTH(1); + + for (unsigned i = 0; i < 4; ++i) { + /* Use channel 0 on purpose, so that we can use OPAQUE_WHITE + * when the border color is 1.0. */ + clamped_border_color.f[i] = CLAMP(state->border_color.f[0], 0, 1); + } + + if (memcmp(&state->border_color, &clamped_border_color, sizeof(clamped_border_color)) == 0) + rstate->upgraded_depth_val[3] |= S_008F3C_UPGRADED_DEPTH(1); + else + rstate->upgraded_depth_val[3] = + si_translate_border_color(sctx, state, &clamped_border_color) | + S_008F3C_UPGRADED_DEPTH(1); return rstate; } -- 2.30.2