freedreno/ir3: Setup inputs and outputs for tessellation stages
authorKristian H. Kristensen <hoegsberg@google.com>
Wed, 23 Oct 2019 02:37:53 +0000 (19:37 -0700)
committerKristian H. Kristensen <hoegsberg@google.com>
Fri, 8 Nov 2019 00:40:27 +0000 (16:40 -0800)
Similar to GS, some inputs are reused when the chsh from VS to TCS or
TES to GS, so we need to make sure we setup the right inputs and make
the shared system values outputs so they don't get clobbered.

Signed-off-by: Kristian H. Kristensen <hoegsberg@google.com>
Acked-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Rob Clark <robdclark@gmail.com>
src/freedreno/ir3/ir3_compiler_nir.c

index 2341c359324e9178181c9043f1a9103f0473b428..f58f1a04b558dbaf2ad947ec26cbe0010aad2aed 100644 (file)
@@ -2883,6 +2883,7 @@ setup_output(struct ir3_context *ctx, nir_variable *out)
                                        gl_frag_result_name(slot));
                }
        } else if (ctx->so->type == MESA_SHADER_VERTEX ||
+                       ctx->so->type == MESA_SHADER_TESS_EVAL ||
                        ctx->so->type == MESA_SHADER_GEOMETRY) {
                switch (slot) {
                case VARYING_SLOT_POS:
@@ -2914,6 +2915,9 @@ setup_output(struct ir3_context *ctx, nir_variable *out)
                                        _mesa_shader_stage_to_string(ctx->so->type),
                                        gl_varying_slot_name(slot));
                }
+       } else if (ctx->so->type == MESA_SHADER_TESS_CTRL) {
+               /* output lowered to buffer writes. */
+               return;
        } else {
                ir3_context_error(ctx, "unknown shader type: %d\n", ctx->so->type);
        }
@@ -2958,6 +2962,8 @@ max_drvloc(struct exec_list *vars)
 
 static const unsigned max_sysvals[] = {
        [MESA_SHADER_VERTEX]  = 16,
+       [MESA_SHADER_TESS_CTRL] = 16,
+       [MESA_SHADER_TESS_EVAL] = 16,
        [MESA_SHADER_GEOMETRY] = 16,
        [MESA_SHADER_FRAGMENT] = 24,  // TODO
        [MESA_SHADER_COMPUTE] = 16, // TODO how many do we actually need?
@@ -2976,7 +2982,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)
+       if (ctx->so->type == MESA_SHADER_VERTEX ||
+                       ctx->so->type == MESA_SHADER_TESS_EVAL)
                noutputs += 8; /* gs or tess header + primitive_id */
 
        ctx->ir = ir3_create(ctx->compiler, ctx->so->type, ninputs, noutputs);
@@ -2988,12 +2995,38 @@ 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) {
+       /* Tesselation shaders always need primitive ID for indexing the
+        * BO. Geometry shaders don't always need it but when they do it has be
+        * delivered and unclobbered in the VS. To make things easy, we always
+        * make room for it in VS/DS.
+        */
+       bool has_tess = ctx->so->key.tessellation != IR3_TESS_NONE;
+       bool has_gs = ctx->so->key.has_gs;
+       switch (ctx->so->type) {
+       case MESA_SHADER_VERTEX:
+               if (has_tess) {
+                       ctx->tcs_header = create_input(ctx, 0);
+                       ctx->primitive_id = create_input(ctx, 0);
+               } else if (has_gs) {
                        ctx->gs_header = create_input(ctx, 0);
                        ctx->primitive_id = create_input(ctx, 0);
                }
+               break;
+       case MESA_SHADER_TESS_CTRL:
+               ctx->tcs_header = create_input(ctx, 0);
+               ctx->primitive_id = create_input(ctx, 0);
+               break;
+       case MESA_SHADER_TESS_EVAL:
+               if (has_gs)
+                       ctx->gs_header = create_input(ctx, 0);
+               ctx->primitive_id = create_input(ctx, 0);
+               break;
+       case MESA_SHADER_GEOMETRY:
+               ctx->gs_header = create_input(ctx, 0);
+               ctx->primitive_id = create_input(ctx, 0);
+               break;
+       default:
+               break;
        }
 
        /* for fragment shader, the vcoord input register is used as the
@@ -3032,15 +3065,19 @@ emit_instructions(struct ir3_context *ctx)
                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);
+       if (ctx->tcs_header)
+               add_sysval_input(ctx, SYSTEM_VALUE_TCS_HEADER_IR3, ctx->tcs_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) {
+       /* Set up the shared system values as outputs for the vertex and tess eval
+        * shaders so they don't clobber them for the next shader in the pipeline.
+        */
+       if (ctx->so->type == MESA_SHADER_VERTEX ||
+                       (has_gs && ctx->so->type == MESA_SHADER_TESS_EVAL)) {
                struct ir3_shader_variant *so = ctx->so;
                if (ctx->primitive_id) {
                        unsigned n = so->outputs_count++;
@@ -3060,6 +3097,14 @@ emit_instructions(struct ir3_context *ctx)
                        compile_assert(ctx, n * 4 < ctx->ir->noutputs);
                }
 
+               if (ctx->tcs_header) {
+                       unsigned n = so->outputs_count++;
+                       so->outputs[n].slot = VARYING_SLOT_TCS_HEADER_IR3;
+                       so->outputs[n].regid = regid(n, 0);
+                       ctx->ir->outputs[n * 4] = ctx->tcs_header;
+
+                       compile_assert(ctx, n * 4 < ctx->ir->noutputs);
+               }
        }
 
        /* Find # of samplers: */