radeonsi: clamp border colors for upgraded depth textures

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: d4d9ec55c5 ("radeonsi: implement TC-compatible HTILE")
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
This commit is contained in:
Nicolai Hähnle 2017-09-23 10:29:51 +02:00
parent 4c56e07029
commit 6eb9483912
1 changed files with 60 additions and 59 deletions

View 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;
}