radeonsi: clamp border colors for upgraded depth textures
authorNicolai Hähnle <nicolai.haehnle@amd.com>
Sat, 23 Sep 2017 08:29:51 +0000 (10:29 +0200)
committerNicolai Hähnle <nicolai.haehnle@amd.com>
Fri, 29 Sep 2017 09:45:05 +0000 (11:45 +0200)
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 <marek.olsak@amd.com>
Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
src/gallium/drivers/radeonsi/si_state.c

index 8a14404f0e83262b3e544029d9f6df593476891f..1463d3c9ca1763d2fcb214e70f114497aee34811 100644 (file)
@@ -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;
 }