[Mesa-dev] [PATCH 3/3] radeonsi: fix border color translation for integer textures

Marek Olšák maraeo at gmail.com
Wed Sep 27 10:07:55 UTC 2017


For the series:

Reviewed-by: Marek Olšák <marek.olsak at amd.com>

Marek

On Tue, Sep 26, 2017 at 4:46 PM, Nicolai Hähnle <nhaehnle at gmail.com> wrote:
> 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)
> --
> 2.11.0
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list