[Mesa-dev] [PATCH 3/3] radeonsi: fix border color translation for integer textures
Dieter Nützel
Dieter at nuetzel-hh.de
Wed Sep 27 15:29:36 UTC 2017
For the series:
Tested-by: Dieter Nützel <Dieter at nuetzel-hh.de>
Dieter
Am 26.09.2017 16:46, schrieb Nicolai Hähnle:
> From: Nicolai Hähnle <nicolai.haehnle at amd.com>
>
> This fixes the extremely unlikely case that an application uses
> 0x80000000 or 0x3f800000 as border color for an integer texture and
> helps in the also, but perhaps slightly less, unlikely case that 1 is
> used as a border color.
> ---
> src/gallium/drivers/radeonsi/si_descriptors.c | 37
> ++++++++++++--------
> src/gallium/drivers/radeonsi/si_pipe.h | 2 ++
> src/gallium/drivers/radeonsi/si_state.c | 50
> +++++++++++++++++++--------
> 3 files changed, 60 insertions(+), 29 deletions(-)
>
> diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c
> b/src/gallium/drivers/radeonsi/si_descriptors.c
> index 27239c25389..db77b1cb982 100644
> --- a/src/gallium/drivers/radeonsi/si_descriptors.c
> +++ b/src/gallium/drivers/radeonsi/si_descriptors.c
> @@ -372,20 +372,34 @@ void si_set_mutable_tex_desc_fields(struct
> si_screen *sscreen,
> unsigned pitch = base_level_info->nblk_x * block_width;
> unsigned index = si_tile_mode_index(tex, base_level, is_stencil);
>
> state[3] &= C_008F1C_TILING_INDEX;
> state[3] |= S_008F1C_TILING_INDEX(index);
> state[4] &= C_008F20_PITCH_GFX6;
> state[4] |= S_008F20_PITCH_GFX6(pitch - 1);
> }
> }
>
> +static void si_set_sampler_state_desc(struct si_sampler_state *sstate,
> + struct si_sampler_view *sview,
> + struct r600_texture *tex,
> + uint32_t *desc)
> +{
> + if (sview && sview->is_integer)
> + memcpy(desc, sstate->integer_val, 4*4);
> + else if (tex && tex->upgraded_depth &&
> + (!sview || !sview->is_stencil_sampler))
> + memcpy(desc, sstate->upgraded_depth_val, 4*4);
> + else
> + memcpy(desc, sstate->val, 4*4);
> +}
> +
> static void si_set_sampler_view_desc(struct si_context *sctx,
> struct si_sampler_view *sview,
> struct si_sampler_state *sstate,
> uint32_t *desc)
> {
> struct pipe_sampler_view *view = &sview->base;
> struct r600_texture *rtex = (struct r600_texture *)view->texture;
> bool is_buffer = rtex->resource.b.b.target == PIPE_BUFFER;
>
> if (unlikely(!is_buffer && sview->dcc_incompatible)) {
> @@ -415,27 +429,24 @@ static void si_set_sampler_view_desc(struct
> si_context *sctx,
> is_separate_stencil,
> desc);
> }
>
> if (!is_buffer && rtex->fmask.size) {
> memcpy(desc + 8, sview->fmask_state, 8*4);
> } else {
> /* Disable FMASK and bind sampler state in [12:15]. */
> memcpy(desc + 8, null_texture_descriptor, 4*4);
>
> - if (sstate) {
> - if (!is_buffer && rtex->upgraded_depth &&
> - !sview->is_stencil_sampler)
> - memcpy(desc + 12, sstate->upgraded_depth_val, 4*4);
> - else
> - memcpy(desc + 12, sstate->val, 4*4);
> - }
> + if (sstate)
> + si_set_sampler_state_desc(sstate, sview,
> + is_buffer ? NULL : rtex,
> + desc + 12);
> }
> }
>
> static void si_set_sampler_view(struct si_context *sctx,
> unsigned shader,
> unsigned slot, struct pipe_sampler_view *view,
> bool disallow_early_out)
> {
> struct si_sampler_views *views = &sctx->samplers[shader].views;
> struct si_sampler_view *rview = (struct si_sampler_view*)view;
> @@ -463,22 +474,22 @@ static void si_set_sampler_view(struct si_context
> *sctx,
> si_sampler_view_add_buffer(sctx, view->texture,
> RADEON_USAGE_READ,
> rview->is_stencil_sampler, true);
> } else {
> pipe_sampler_view_reference(&views->views[slot], NULL);
> memcpy(desc, null_texture_descriptor, 8*4);
> /* Only clear the lower dwords of FMASK. */
> memcpy(desc + 8, null_texture_descriptor, 4*4);
> /* Re-set the sampler state if we are transitioning from FMASK. */
> if (views->sampler_states[slot])
> - memcpy(desc + 12,
> - views->sampler_states[slot]->val, 4*4);
> + si_set_sampler_state_desc(views->sampler_states[slot], NULL, NULL,
> + desc + 12);
>
> views->enabled_mask &= ~(1u << slot);
> }
>
> sctx->descriptors_dirty |= 1u <<
> si_sampler_and_image_descriptors_idx(shader);
> }
>
> static bool color_needs_decompression(struct r600_texture *rtex)
> {
> return rtex->fmask.size ||
> @@ -855,26 +866,22 @@ static void si_bind_sampler_states(struct
> pipe_context *ctx,
>
> struct r600_texture *tex = NULL;
>
> if (sview && sview->base.texture &&
> sview->base.texture->target != PIPE_BUFFER)
> tex = (struct r600_texture *)sview->base.texture;
>
> if (tex && tex->fmask.size)
> continue;
>
> - if (tex && tex->upgraded_depth && !sview->is_stencil_sampler)
> - memcpy(desc->list + desc_slot * 16 + 12,
> - sstates[i]->upgraded_depth_val, 4*4);
> - else
> - memcpy(desc->list + desc_slot * 16 + 12,
> - sstates[i]->val, 4*4);
> + si_set_sampler_state_desc(sstates[i], sview, tex,
> + desc->list + desc_slot * 16 + 12);
>
> sctx->descriptors_dirty |= 1u <<
> si_sampler_and_image_descriptors_idx(shader);
> }
> }
>
> /* BUFFER RESOURCES */
>
> static void si_init_buffer_resources(struct si_buffer_resources
> *buffers,
> struct si_descriptors *descs,
> unsigned num_buffers,
> diff --git a/src/gallium/drivers/radeonsi/si_pipe.h
> b/src/gallium/drivers/radeonsi/si_pipe.h
> index 80f38ea29bb..46c89e2f38a 100644
> --- a/src/gallium/drivers/radeonsi/si_pipe.h
> +++ b/src/gallium/drivers/radeonsi/si_pipe.h
> @@ -150,30 +150,32 @@ struct si_blend_color {
> struct si_sampler_view {
> struct pipe_sampler_view base;
> /* [0..7] = image descriptor
> * [4..7] = buffer descriptor */
> uint32_t state[8];
> uint32_t fmask_state[8];
> const struct legacy_surf_level *base_level_info;
> ubyte base_level;
> ubyte block_width;
> bool is_stencil_sampler;
> + bool is_integer;
> bool dcc_incompatible;
> };
>
> #define SI_SAMPLER_STATE_MAGIC 0x34f1c35a
>
> struct si_sampler_state {
> #ifdef DEBUG
> unsigned magic;
> #endif
> uint32_t val[4];
> + uint32_t integer_val[4];
> uint32_t upgraded_depth_val[4];
> };
>
> struct si_cs_shader_state {
> struct si_compute *program;
> struct si_compute *emitted_program;
> unsigned offset;
> bool initialized;
> bool uses_scratch;
> };
> diff --git a/src/gallium/drivers/radeonsi/si_state.c
> b/src/gallium/drivers/radeonsi/si_state.c
> index 2a27ea0c503..75042b6dfd3 100644
> --- a/src/gallium/drivers/radeonsi/si_state.c
> +++ b/src/gallium/drivers/radeonsi/si_state.c
> @@ -3854,20 +3854,26 @@ si_create_sampler_view_custom(struct
> pipe_context *ctx,
> state->u.tex.first_level,
> state->format);
>
> si_make_texture_descriptor(sctx->screen, tmp, true,
> state->target, pipe_format, state_swizzle,
> first_level, last_level,
> state->u.tex.first_layer, last_layer,
> width, height, depth,
> view->state, view->fmask_state);
>
> + unsigned num_format = G_008F14_NUM_FORMAT_GFX6(view->state[1]);
> + view->is_integer =
> + num_format == V_008F14_IMG_NUM_FORMAT_USCALED ||
> + num_format == V_008F14_IMG_NUM_FORMAT_SSCALED ||
> + num_format == V_008F14_IMG_NUM_FORMAT_UINT ||
> + num_format == V_008F14_IMG_NUM_FORMAT_SINT;
> view->base_level_info = &surflevel[base_level];
> view->base_level = base_level;
> view->block_width = util_format_get_blockwidth(pipe_format);
> return &view->base;
> }
>
> static struct pipe_sampler_view *
> si_create_sampler_view(struct pipe_context *ctx,
> struct pipe_resource *texture,
> const struct pipe_sampler_view *state)
> @@ -3890,38 +3896,50 @@ 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 uint32_t si_translate_border_color(struct si_context *sctx,
> const struct pipe_sampler_state *state,
> - const union pipe_color_union *color)
> + const union pipe_color_union *color,
> + bool is_integer)
> {
> bool linear_filter = state->min_img_filter != PIPE_TEX_FILTER_NEAREST
> ||
> state->mag_img_filter != PIPE_TEX_FILTER_NEAREST;
>
> - 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)))
> + if (!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);
> +#define simple_border_types(elt) \
> +do { \
> + if (color->elt[0] == 0 && color->elt[1] == 0 &&
> \
> + color->elt[2] == 0 && color->elt[3] == 0)
> \
> + return
> S_008F3C_BORDER_COLOR_TYPE(V_008F3C_SQ_TEX_BORDER_COLOR_TRANS_BLACK);
> \
> + if (color->elt[0] == 0 && color->elt[1] == 0 &&
> \
> + color->elt[2] == 0 && color->elt[3] == 1)
> \
> + return
> S_008F3C_BORDER_COLOR_TYPE(V_008F3C_SQ_TEX_BORDER_COLOR_OPAQUE_BLACK);
> \
> + if (color->elt[0] == 1 && color->elt[1] == 1 &&
> \
> + color->elt[2] == 1 && color->elt[3] == 1)
> \
> + return
> S_008F3C_BORDER_COLOR_TYPE(V_008F3C_SQ_TEX_BORDER_COLOR_OPAQUE_WHITE);
> \
> +} while (false)
> +
> + if (is_integer)
> + simple_border_types(ui);
> + else
> + simple_border_types(f);
> +
> +#undef simple_border_types
>
> 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) {
> @@ -3977,36 +3995,40 @@ 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] = si_translate_border_color(sctx, state,
> &state->border_color);
> + rstate->val[3] = si_translate_border_color(sctx, state,
> &state->border_color, false);
> +
> + /* Create sampler resource for integer textures. */
> + memcpy(rstate->integer_val, rstate->val, sizeof(rstate->val));
> + rstate->integer_val[3] = si_translate_border_color(sctx, state,
> &state->border_color, true);
>
> /* Create sampler resource for upgraded depth textures. */
> memcpy(rstate->upgraded_depth_val, rstate->val, sizeof(rstate->val));
>
> 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) |
> + si_translate_border_color(sctx, state, &clamped_border_color,
> false) |
> 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)
More information about the mesa-dev
mailing list