Module: Mesa
Branch: master
Commit: 349df23eb0d119e3f22ff6149824497414f07505
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=349df23eb0d119e3f22ff6149824497414f07505

Author: Dave Airlie <airl...@redhat.com>
Date:   Tue Jan 27 13:39:51 2015 +1000

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.kenn...@gmail.com>
Signed-off-by: Dave Airlie <airl...@redhat.com>

---

 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 36b86aa..ea58aea 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 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..16e820e 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 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.c 
b/src/gallium/drivers/r600/r600_state.c
index 9a4b972..3c2fdfa 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 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);
        }
 

_______________________________________________
mesa-commit mailing list
mesa-commit@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to