From 349df23eb0d119e3f22ff6149824497414f07505 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 27 Jan 2015 13:39:51 +1000 Subject: [PATCH] r600g: add support for primitive id without geom shader (v2) 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. v1.1: clean up debug print + no need to assign key value to setup output. v2: add r600 support Reviewed-by: Glenn Kennard Signed-off-by: Dave Airlie --- src/gallium/drivers/r600/evergreen_state.c | 5 ++++ src/gallium/drivers/r600/r600_hw_context.c | 2 +- src/gallium/drivers/r600/r600_shader.c | 31 ++++++++++++++++++++ src/gallium/drivers/r600/r600_shader.h | 4 +++ src/gallium/drivers/r600/r600_state.c | 5 ++++ src/gallium/drivers/r600/r600_state_common.c | 5 ++++ 6 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index 36b86aa6d8f..ea58aeab0b4 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -2111,6 +2111,11 @@ 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) { + 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 ccc5a8b2946..cd57eedf5bd 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 471df91d8f3..16e820ee215 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 prim_id_sid) +{ + 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 = prim_id_sid; + + 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,7 @@ 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; shader->vs_as_es = key.vs_as_es; r600_bytecode_init(ctx.bc, rscreen->b.chip_class, rscreen->b.family, @@ -1938,6 +1958,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, key.vs_prim_id_out); + while (!tgsi_parse_end_of_tokens(&ctx.parse)) { tgsi_parse_token(&ctx.parse); switch (ctx.parse.FullToken.Token.Type) { @@ -2335,7 +2359,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 ab67013d8c3..b2559e9b661 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.c b/src/gallium/drivers/r600/r600_state.c index 9a4b9725ab8..3c2fdfaed42 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -1943,6 +1943,11 @@ static void r600_emit_shader_stages(struct r600_context *rctx, struct r600_atom uint32_t v2 = 0, primid = 0; + if (rctx->vs_shader->current->shader.vs_as_gs_a) { + 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_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 10306207b46..b498d00b5b5 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); } -- 2.30.2