[Mesa-dev] [PATCH 52/61] radeonsi/gfx9: 2nd shader of merged shaders should hold a reference of the 1st

Nicolai Hähnle nhaehnle at gmail.com
Fri Apr 28 11:51:09 UTC 2017


On 24.04.2017 10:45, Marek Olšák wrote:
> From: Marek Olšák <marek.olsak at amd.com>
>
> ---
>  src/gallium/drivers/radeonsi/si_shader.h        |  1 +
>  src/gallium/drivers/radeonsi/si_state_shaders.c | 35 ++++++++++++++++++-------
>  2 files changed, 26 insertions(+), 10 deletions(-)
>
> diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h
> index 514bb3c..5b665b5 100644
> --- a/src/gallium/drivers/radeonsi/si_shader.h
> +++ b/src/gallium/drivers/radeonsi/si_shader.h
> @@ -498,20 +498,21 @@ struct si_shader_info {
>  	char			face_vgpr_index;
>  	bool			uses_instanceid;
>  	ubyte			nr_pos_exports;
>  	ubyte			nr_param_exports;
>  };
>
>  struct si_shader {
>  	struct si_compiler_ctx_state	compiler_ctx_state;
>
>  	struct si_shader_selector	*selector;
> +	struct si_shader_selector	*previous_stage_sel; /* for refcounting */
>  	struct si_shader		*next_variant;
>
>  	struct si_shader_part		*prolog;
>  	struct si_shader		*previous_stage; /* for GFX9 */
>  	struct si_shader_part		*prolog2;
>  	struct si_shader_part		*epilog;
>
>  	struct si_pm4_state		*pm4;
>  	struct r600_resource		*bo;
>  	struct r600_resource		*scratch_bo;
> diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c
> index c5fa01d..94fc0e4 100644
> --- a/src/gallium/drivers/radeonsi/si_state_shaders.c
> +++ b/src/gallium/drivers/radeonsi/si_state_shaders.c
> @@ -1517,20 +1517,21 @@ static void si_shader_selector_reference(struct si_context *sctx,
>  }
>
>  /* Select the hw shader variant depending on the current state. */
>  static int si_shader_select_with_key(struct si_screen *sscreen,
>  				     struct si_shader_ctx_state *state,
>  				     struct si_compiler_ctx_state *compiler_state,
>  				     struct si_shader_key *key,
>  				     int thread_index)
>  {
>  	struct si_shader_selector *sel = state->cso;
> +	struct si_shader_selector *previous_stage_sel = NULL;
>  	struct si_shader *current = state->current;
>  	struct si_shader *iter, *shader = NULL;
>
>  	if (unlikely(sscreen->b.debug_flags & DBG_NO_OPT_VARIANT)) {
>  		memset(&key->opt, 0, sizeof(key->opt));
>  	}
>
>  again:
>  	/* Check if we don't need to change anything.
>  	 * This path is also used for most shaders that don't need multiple
> @@ -1584,64 +1585,77 @@ again:
>  	/* Build a new shader. */
>  	shader = CALLOC_STRUCT(si_shader);
>  	if (!shader) {
>  		mtx_unlock(&sel->mutex);
>  		return -ENOMEM;
>  	}
>  	shader->selector = sel;
>  	shader->key = *key;
>  	shader->compiler_ctx_state = *compiler_state;
>
> +	/* If this is a merged shader, get the first shader's selector. */
> +	if (sscreen->b.chip_class >= GFX9) {
> +		if (sel->type == PIPE_SHADER_TESS_CTRL)
> +			previous_stage_sel  = key->part.tcs.ls;
> +		else if (sel->type == PIPE_SHADER_GEOMETRY)
> +			previous_stage_sel  = key->part.gs.es;

Extra space around the '='.

Cheers,
Nicolai


> +	}
> +
>  	/* Compile the main shader part if it doesn't exist. This can happen
>  	 * if the initial guess was wrong. */
>  	bool is_pure_monolithic =
>  		sscreen->use_monolithic_shaders ||
>  		memcmp(&key->mono, &zeroed.mono, sizeof(key->mono)) != 0;
>
>  	if (!is_pure_monolithic) {
>  		bool ok;
>
>  		/* Make sure the main shader part is present. This is needed
>  		 * for shaders that can be compiled as VS, LS, or ES, and only
>  		 * one of them is compiled at creation.
>  		 *
>  		 * For merged shaders, check that the starting shader's main
>  		 * part is present.
>  		 */
> -		if (sscreen->b.chip_class >= GFX9 &&
> -		    (sel->type == PIPE_SHADER_TESS_CTRL ||
> -		     sel->type == PIPE_SHADER_GEOMETRY)) {
> -			struct si_shader_selector *shader1 = NULL;
> +		if (previous_stage_sel) {
>  			struct si_shader_key shader1_key = zeroed;
>
> -			if (sel->type == PIPE_SHADER_TESS_CTRL) {
> -				shader1 = key->part.tcs.ls;
> +			if (sel->type == PIPE_SHADER_TESS_CTRL)
>  				shader1_key.as_ls = 1;
> -			} else if (sel->type == PIPE_SHADER_GEOMETRY) {
> -				shader1 = key->part.gs.es;
> +			else if (sel->type == PIPE_SHADER_GEOMETRY)
>  				shader1_key.as_es = 1;
> -			} else
> +			else
>  				assert(0);
>
> -			ok = si_check_missing_main_part(sscreen, shader1,
> +			ok = si_check_missing_main_part(sscreen,
> +							previous_stage_sel,
>  							compiler_state, &shader1_key);
>  		} else {
>  			ok = si_check_missing_main_part(sscreen, sel,
>  							compiler_state, key);
>  		}
>  		if (!ok) {
>  			FREE(shader);
>  			mtx_unlock(&sel->mutex);
>  			return -ENOMEM; /* skip the draw call */
>  		}
>  	}
>
> +	/* Keep the reference to the 1st shader of merged shaders, so that
> +	 * Gallium can't destroy it before we destroy the 2nd shader.
> +	 *
> +	 * Set sctx = NULL, because it's unused if we're not releasing
> +	 * the shader, and we don't have any sctx here.
> +	 */
> +	si_shader_selector_reference(NULL, &shader->previous_stage_sel,
> +				     previous_stage_sel);
> +
>  	/* Monolithic-only shaders don't make a distinction between optimized
>  	 * and unoptimized. */
>  	shader->is_monolithic =
>  		is_pure_monolithic ||
>  		memcmp(&key->opt, &zeroed.opt, sizeof(key->opt)) != 0;
>
>  	shader->is_optimized =
>  		!is_pure_monolithic &&
>  		memcmp(&key->opt, &zeroed.opt, sizeof(key->opt)) != 0;
>  	if (shader->is_optimized)
> @@ -2237,20 +2251,21 @@ static void si_delete_shader(struct si_context *sctx, struct si_shader *shader)
>  				si_pm4_delete_state(sctx, vs, shader->pm4);
>  			else
>  				si_pm4_delete_state(sctx, gs, shader->pm4);
>  			break;
>  		case PIPE_SHADER_FRAGMENT:
>  			si_pm4_delete_state(sctx, ps, shader->pm4);
>  			break;
>  		}
>  	}
>
> +	si_shader_selector_reference(sctx, &shader->previous_stage_sel, NULL);
>  	si_shader_destroy(shader);
>  	free(shader);
>  }
>
>  static void si_destroy_shader_selector(struct si_context *sctx,
>  				       struct si_shader_selector *sel)
>  {
>  	struct si_shader *p = sel->first_variant, *c;
>  	struct si_shader_ctx_state *current_shader[SI_NUM_SHADERS] = {
>  		[PIPE_SHADER_VERTEX] = &sctx->vs_shader,
>


-- 
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.


More information about the mesa-dev mailing list