[Mesa-dev] [PATCH 2/3] radeonsi: clamp border colors for upgraded depth textures
Nicolai Hähnle
nhaehnle at gmail.com
Tue Sep 26 14:46:09 UTC 2017
From: Nicolai Hähnle <nicolai.haehnle at 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
More information about the mesa-dev
mailing list