freedreno/ir3: Setup ir3 inputs and outputs for GS
authorKristian H. Kristensen <hoegsberg@google.com>
Fri, 11 Oct 2019 19:24:12 +0000 (12:24 -0700)
committerKristian H. Kristensen <hoegsberg@google.com>
Thu, 17 Oct 2019 20:43:53 +0000 (13:43 -0700)
Inputs are the GS header, which contains vertex ID, local primitive ID
and thread ID as well as primitive ID. The setup is a little different
from other sysvals, since we always have to receive them in the VS so
that it can pass them on into the GS.

The vertex flag outputs from GS is set up as a proper nir output in
the lowering pass and doesn't need special handling here.

Signed-off-by: Kristian H. Kristensen <hoegsberg@google.com>
src/freedreno/ir3/ir3_compiler_nir.c

index 04c44b90dfea8a7515a887a91137cec21af45acf..1d51bb0aaec921ac5d8ec42ca43166ff34c7b58c 100644 (file)
@@ -1359,6 +1359,14 @@ emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr)
                dst[0] = create_uniform(b, primitive_map + idx);
                break;
 
+       case nir_intrinsic_load_gs_header_ir3:
+               dst[0] = ctx->gs_header;
+               break;
+
+       case nir_intrinsic_load_primitive_id:
+               dst[0] = ctx->primitive_id;
+               break;
+
        case nir_intrinsic_load_ubo:
                emit_intrinsic_load_ubo(ctx, intr, dst);
                break;
@@ -2488,6 +2496,12 @@ setup_input(struct ir3_context *ctx, nir_variable *in)
        unsigned frac = in->data.location_frac;
        unsigned slot = in->data.location;
 
+       /* Inputs are loaded using ldlw or ldg for these stages. */
+       if (ctx->so->type == MESA_SHADER_TESS_CTRL ||
+                       ctx->so->type == MESA_SHADER_TESS_EVAL ||
+                       ctx->so->type == MESA_SHADER_GEOMETRY)
+               return;
+
        /* skip unread inputs, we could end up with (for example), unsplit
         * matrix/etc inputs in the case they are not read, so just silently
         * skip these.
@@ -2685,7 +2699,8 @@ setup_output(struct ir3_context *ctx, nir_variable *out)
                        ir3_context_error(ctx, "unknown FS output name: %s\n",
                                        gl_frag_result_name(slot));
                }
-       } else if (ctx->so->type == MESA_SHADER_VERTEX) {
+       } else if (ctx->so->type == MESA_SHADER_VERTEX ||
+                       ctx->so->type == MESA_SHADER_GEOMETRY) {
                switch (slot) {
                case VARYING_SLOT_POS:
                        so->writes_pos = true;
@@ -2693,6 +2708,11 @@ setup_output(struct ir3_context *ctx, nir_variable *out)
                case VARYING_SLOT_PSIZ:
                        so->writes_psize = true;
                        break;
+               case VARYING_SLOT_PRIMITIVE_ID:
+               case VARYING_SLOT_LAYER:
+               case VARYING_SLOT_GS_VERTEX_FLAGS_IR3:
+                       debug_assert(ctx->so->type == MESA_SHADER_GEOMETRY);
+                       /* fall through */
                case VARYING_SLOT_COL0:
                case VARYING_SLOT_COL1:
                case VARYING_SLOT_BFC0:
@@ -2707,7 +2727,8 @@ setup_output(struct ir3_context *ctx, nir_variable *out)
                                break;
                        if ((VARYING_SLOT_TEX0 <= slot) && (slot <= VARYING_SLOT_TEX7))
                                break;
-                       ir3_context_error(ctx, "unknown VS output name: %s\n",
+                       ir3_context_error(ctx, "unknown %s shader output name: %s\n",
+                                       _mesa_shader_stage_to_string(ctx->so->type),
                                        gl_varying_slot_name(slot));
                }
        } else {
@@ -2753,8 +2774,9 @@ max_drvloc(struct exec_list *vars)
 }
 
 static const unsigned max_sysvals[] = {
-       [MESA_SHADER_FRAGMENT] = 24,  // TODO
        [MESA_SHADER_VERTEX]  = 16,
+       [MESA_SHADER_GEOMETRY] = 16,
+       [MESA_SHADER_FRAGMENT] = 24,  // TODO
        [MESA_SHADER_COMPUTE] = 16, // TODO how many do we actually need?
        [MESA_SHADER_KERNEL]  = 16, // TODO how many do we actually need?
 };
@@ -2771,6 +2793,8 @@ emit_instructions(struct ir3_context *ctx)
        /* we need to leave room for sysvals:
         */
        ninputs += max_sysvals[ctx->so->type];
+       if (ctx->so->type == MESA_SHADER_VERTEX)
+               noutputs += 8; /* gs or tess header + primitive_id */
 
        ctx->ir = ir3_create(ctx->compiler, ctx->so->type, ninputs, noutputs);
 
@@ -2781,6 +2805,14 @@ emit_instructions(struct ir3_context *ctx)
 
        ninputs -= max_sysvals[ctx->so->type];
 
+       if (ctx->so->key.has_gs) {
+               if (ctx->so->type == MESA_SHADER_VERTEX ||
+                       ctx->so->type == MESA_SHADER_GEOMETRY) {
+                       ctx->gs_header = create_input(ctx, 0);
+                       ctx->primitive_id = create_input(ctx, 0);
+               }
+       }
+
        /* for fragment shader, the vcoord input register is used as the
         * base for bary.f varying fetch instrs:
         *
@@ -2813,11 +2845,40 @@ emit_instructions(struct ir3_context *ctx)
                                0x3, vcoord);
        }
 
+       if (ctx->primitive_id)
+               add_sysval_input(ctx, SYSTEM_VALUE_PRIMITIVE_ID, ctx->primitive_id);
+       if (ctx->gs_header)
+               add_sysval_input(ctx, SYSTEM_VALUE_GS_HEADER_IR3, ctx->gs_header);
+
        /* Setup outputs: */
        nir_foreach_variable(var, &ctx->s->outputs) {
                setup_output(ctx, var);
        }
 
+       /* Set up the gs header as an output for the vertex shader so it won't
+        * clobber it for the tess ctrl shader. */
+       if (ctx->so->type == MESA_SHADER_VERTEX) {
+               struct ir3_shader_variant *so = ctx->so;
+               if (ctx->primitive_id) {
+                       unsigned n = so->outputs_count++;
+                       so->outputs[n].slot = VARYING_SLOT_PRIMITIVE_ID;
+                       so->outputs[n].regid = regid(n, 0);
+                       ctx->ir->outputs[n * 4] = ctx->primitive_id;
+
+                       compile_assert(ctx, n * 4 < ctx->ir->noutputs);
+               }
+
+               if (ctx->gs_header) {
+                       unsigned n = so->outputs_count++;
+                       so->outputs[n].slot = VARYING_SLOT_GS_HEADER_IR3;
+                       so->outputs[n].regid = regid(n, 0);
+                       ctx->ir->outputs[n * 4] = ctx->gs_header;
+
+                       compile_assert(ctx, n * 4 < ctx->ir->noutputs);
+               }
+
+       }
+
        /* Find # of samplers: */
        nir_foreach_variable(var, &ctx->s->uniforms) {
                ctx->so->num_samp += glsl_type_get_sampler_count(var->type);