summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-01-27 13:39:51 +1000
committerDave Airlie <airlied@redhat.com>2015-01-28 09:51:21 +1000
commit349df23eb0d119e3f22ff6149824497414f07505 (patch)
tree048b6c2ba1a2cfb032664e2ce2ee61ee6f214000
parentcc2fc095bfae1c0494240e4f06931e2ca90e182c (diff)
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 <glenn.kennard@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--src/gallium/drivers/r600/evergreen_state.c5
-rw-r--r--src/gallium/drivers/r600/r600_hw_context.c2
-rw-r--r--src/gallium/drivers/r600/r600_shader.c31
-rw-r--r--src/gallium/drivers/r600/r600_shader.h4
-rw-r--r--src/gallium/drivers/r600/r600_state.c5
-rw-r--r--src/gallium/drivers/r600/r600_state_common.c5
6 files changed, 51 insertions, 1 deletions
diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
index 36b86aa6d8..ea58aeab0b 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 ccc5a8b294..cd57eedf5b 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 471df91d8f..16e820ee21 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 ab67013d8c..b2559e9b66 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 9a4b9725ab..3c2fdfaed4 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 10306207b4..b498d00b5b 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);
}