[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