From: Nicolai Hähnle <nicolai.haeh...@amd.com> 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") --- 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 551bb17503c..2a27ea0c503 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -3888,96 +3888,85 @@ static void si_sampler_view_destroy(struct pipe_context *ctx, static bool wrap_mode_uses_border_color(unsigned wrap, bool linear_filter) { return wrap == PIPE_TEX_WRAP_CLAMP_TO_BORDER || wrap == PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER || (linear_filter && (wrap == PIPE_TEX_WRAP_CLAMP || 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, const struct pipe_sampler_state *state) { 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 rstate->val[0] = (S_008F30_CLAMP_X(si_tex_wrap(state->wrap_s)) | S_008F30_CLAMP_Y(si_tex_wrap(state->wrap_t)) | S_008F30_CLAMP_Z(si_tex_wrap(state->wrap_r)) | S_008F30_MAX_ANISO_RATIO(max_aniso_ratio) | S_008F30_DEPTH_COMPARE_FUNC(si_tex_compare(state->compare_func)) | S_008F30_FORCE_UNNORMALIZED(!state->normalized_coords) | S_008F30_ANISO_THRESHOLD(max_aniso_ratio >> 1) | @@ -3988,25 +3977,37 @@ static void *si_create_sampler_state(struct pipe_context *ctx, S_008F34_MAX_LOD(S_FIXED(CLAMP(state->max_lod, 0, 15), 8)) | S_008F34_PERF_MIP(max_aniso_ratio ? max_aniso_ratio + 6 : 0)); rstate->val[2] = (S_008F38_LOD_BIAS(S_FIXED(CLAMP(state->lod_bias, -16, 16), 8)) | S_008F38_XY_MAG_FILTER(eg_tex_filter(state->mag_img_filter, max_aniso)) | S_008F38_XY_MIN_FILTER(eg_tex_filter(state->min_img_filter, max_aniso)) | S_008F38_MIP_FILTER(si_tex_mipfilter(state->min_mip_filter)) | S_008F38_MIP_POINT_PRECLAMP(0) | 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; } static void si_set_sample_mask(struct pipe_context *ctx, unsigned sample_mask) { struct si_context *sctx = (struct si_context *)ctx; if (sctx->sample_mask.sample_mask == (uint16_t)sample_mask) return; -- 2.11.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev