[Mesa-dev] [PATCH 2/2] r600g: add support for primitive id without geom shader

Glenn Kennard glenn.kennard at gmail.com
Tue Jan 27 03:36:34 PST 2015


On Tue, 27 Jan 2015 04:46:33 +0100, Dave Airlie <airlied at gmail.com> wrote:

> From: Dave Airlie <airlied at redhat.com>
>
> GLSL 1.50 specifies a fragment shader may have a primitive id
> input without a geometry shader present.
>
> On r600 hw there is a special GS scenario for this, you have
> to enable GS_SCENARIO_A and pass the primitive id through
> the vertex shader which operates in GS_A mode.
>
> This is a first pass attempt at this, and passes the piglit
> tests that test for this.
>
> TODO: r600/700 support.

r600/r700 should be just copy/paste of the evergreen_emit_shader_stages()  
changes into r600_emit_shader_stages().

> make nicer.
>
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
>  src/gallium/drivers/r600/evergreen_state.c   |  6 +++++
>  src/gallium/drivers/r600/r600_hw_context.c   |  2 +-
>  src/gallium/drivers/r600/r600_shader.c       | 33  
> ++++++++++++++++++++++++++++
>  src/gallium/drivers/r600/r600_shader.h       |  4 ++++
>  src/gallium/drivers/r600/r600_state_common.c |  5 +++++
>  5 files changed, 49 insertions(+), 1 deletion(-)
>
> diff --git a/src/gallium/drivers/r600/evergreen_state.c  
> b/src/gallium/drivers/r600/evergreen_state.c
> index 36b86aa..bc1fa48 100644
> --- a/src/gallium/drivers/r600/evergreen_state.c
> +++ b/src/gallium/drivers/r600/evergreen_state.c
> @@ -2111,6 +2111,12 @@ static void evergreen_emit_shader_stages(struct  
> r600_context *rctx, struct r600_
> 	uint32_t v = 0, v2 = 0, primid = 0;
> +	if (rctx->vs_shader->current->shader.vs_as_gs_a) {
> +		fprintf(stderr, "got fs prim id with no geom\n");

Stray debug print

> +		v2 = S_028A40_MODE(V_028A40_GS_SCENARIO_A);
> +		primid = 1;
> +	}
> +
>  	if (state->geom_enable) {
>  		uint32_t cut_val;
> diff --git a/src/gallium/drivers/r600/r600_hw_context.c  
> b/src/gallium/drivers/r600/r600_hw_context.c
> index ccc5a8b..cd57eed 100644
> --- a/src/gallium/drivers/r600/r600_hw_context.c
> +++ b/src/gallium/drivers/r600/r600_hw_context.c
> @@ -315,9 +315,9 @@ void r600_begin_new_cs(struct r600_context *ctx)
>  	ctx->stencil_ref.atom.dirty = true;
>  	ctx->vertex_fetch_shader.atom.dirty = true;
>  	ctx->export_shader.atom.dirty = true;
> +	ctx->shader_stages.atom.dirty = true;
>  	if (ctx->gs_shader) {
>  		ctx->geometry_shader.atom.dirty = true;
> -		ctx->shader_stages.atom.dirty = true;
>  		ctx->gs_rings.atom.dirty = true;
>  	}
>  	ctx->vertex_shader.atom.dirty = true;
> diff --git a/src/gallium/drivers/r600/r600_shader.c  
> b/src/gallium/drivers/r600/r600_shader.c
> index 471df91..8841b08 100644
> --- a/src/gallium/drivers/r600/r600_shader.c
> +++ b/src/gallium/drivers/r600/r600_shader.c
> @@ -596,6 +596,20 @@ static int select_twoside_color(struct  
> r600_shader_ctx *ctx, int front, int back
>  	return 0;
>  }
> +static int vs_add_primid_output(struct r600_shader_ctx *ctx)
> +{
> +	int i;
> +	i = ctx->shader->noutput++;
> +	ctx->shader->output[i].name = TGSI_SEMANTIC_PRIMID;
> +	ctx->shader->output[i].sid = 0;
> +	ctx->shader->output[i].gpr = 0;
> +	ctx->shader->output[i].interpolate = TGSI_INTERPOLATE_CONSTANT;
> +	ctx->shader->output[i].write_mask = 0x4;
> +	ctx->shader->output[i].spi_sid = ctx->shader->ps_prim_id_input;
> +
> +	return 0;
> +}
> +
>  static int tgsi_declaration(struct r600_shader_ctx *ctx)
>  {
>  	struct tgsi_full_declaration *d =  
> &ctx->parse.FullToken.FullDeclaration;
> @@ -626,6 +640,11 @@ static int tgsi_declaration(struct r600_shader_ctx  
> *ctx)
>  			case TGSI_SEMANTIC_POSITION:
>  				ctx->fragcoord_input = i;
>  				break;
> +			case TGSI_SEMANTIC_PRIMID:
> +				/* set this for now */
> +				ctx->shader->gs_prim_id_input = true;
> +				ctx->shader->ps_prim_id_input = i;
> +				break;
>  			}
>  			if (ctx->bc->chip_class >= EVERGREEN) {
>  				if ((r = evergreen_interp_input(ctx, i)))
> @@ -1800,6 +1819,9 @@ static int r600_shader_from_tgsi(struct  
> r600_context *rctx,
>  	ctx.shader = shader;
>  	ctx.native_integers = true;
> +	shader->vs_as_gs_a = key.vs_as_gs_a;
> +	if (key.vs_as_gs_a)
> +		shader->ps_prim_id_input = key.vs_prim_id_out;
>  	shader->vs_as_es = key.vs_as_es;
> 	r600_bytecode_init(ctx.bc, rscreen->b.chip_class, rscreen->b.family,
> @@ -1938,6 +1960,10 @@ static int r600_shader_from_tgsi(struct  
> r600_context *rctx,
>  	ctx.nliterals = 0;
>  	ctx.literals = NULL;
>  	shader->fs_write_all = FALSE;
> +
> +	if (shader->vs_as_gs_a)
> +		vs_add_primid_output(&ctx);
> +
>  	while (!tgsi_parse_end_of_tokens(&ctx.parse)) {
>  		tgsi_parse_token(&ctx.parse);
>  		switch (ctx.parse.FullToken.Token.Type) {
> @@ -2335,7 +2361,14 @@ static int r600_shader_from_tgsi(struct  
> r600_context *rctx,
>  					output[j].swizzle_z = 4; /* 0 */
>  					output[j].swizzle_w = 5; /* 1 */
>  					break;
> +				case TGSI_SEMANTIC_PRIMID:
> +					output[j].swizzle_x = 2;
> +					output[j].swizzle_y = 4; /* 0 */
> +					output[j].swizzle_z = 4; /* 0 */
> +					output[j].swizzle_w = 4; /* 0 */
> +					break;
>  				}
> +
>  				break;
>  			case TGSI_PROCESSOR_FRAGMENT:
>  				if (shader->output[i].name == TGSI_SEMANTIC_COLOR) {
> diff --git a/src/gallium/drivers/r600/r600_shader.h  
> b/src/gallium/drivers/r600/r600_shader.h
> index ab67013..b2559e9 100644
> --- a/src/gallium/drivers/r600/r600_shader.h
> +++ b/src/gallium/drivers/r600/r600_shader.h
> @@ -84,6 +84,8 @@ struct r600_shader {
>  	unsigned		max_arrays;
>  	unsigned		num_arrays;
>  	unsigned		vs_as_es;
> +	unsigned		vs_as_gs_a;
> +	unsigned                ps_prim_id_input;
>  	struct r600_shader_array * arrays;
>  };
> @@ -92,6 +94,8 @@ struct r600_shader_key {
>  	unsigned alpha_to_one:1;
>  	unsigned nr_cbufs:4;
>  	unsigned vs_as_es:1;
> +	unsigned vs_as_gs_a:1;
> +	unsigned vs_prim_id_out:8;
>  };
> struct r600_shader_array {
> diff --git a/src/gallium/drivers/r600/r600_state_common.c  
> b/src/gallium/drivers/r600/r600_state_common.c
> index 1030620..b498d00 100644
> --- a/src/gallium/drivers/r600/r600_state_common.c
> +++ b/src/gallium/drivers/r600/r600_state_common.c
> @@ -707,6 +707,10 @@ static INLINE struct r600_shader_key  
> r600_shader_selector_key(struct pipe_contex
>  			key.nr_cbufs = 2;
>  	} else if (sel->type == PIPE_SHADER_VERTEX) {
>  		key.vs_as_es = (rctx->gs_shader != NULL);
> +		if (rctx->ps_shader->current->shader.gs_prim_id_input &&  
> !rctx->gs_shader) {
> +			key.vs_as_gs_a = true;
> +			key.vs_prim_id_out =  
> rctx->ps_shader->current->shader.input[rctx->ps_shader->current->shader.ps_prim_id_input].spi_sid;
> +		}
>  	}
>  	return key;
>  }
> @@ -1265,6 +1269,7 @@ static bool r600_update_derived_state(struct  
> r600_context *rctx)
>  				r600_update_ps_state(ctx, rctx->ps_shader->current);
>  		}
> +		rctx->shader_stages.atom.dirty = true;
>  		update_shader_atom(ctx, &rctx->pixel_shader,  
> rctx->ps_shader->current);
>  	}
>

With r600/r700 bits added and debug print removed:
Reviewed-by: Glenn Kennard <glenn.kennard at gmail.com>


More information about the mesa-dev mailing list