freedreno/a6xx: Emit constant parameters for tessellation stages
authorKristian H. Kristensen <hoegsberg@google.com>
Wed, 23 Oct 2019 02:58:59 +0000 (19:58 -0700)
committerKristian H. Kristensen <hoegsberg@google.com>
Fri, 8 Nov 2019 00:40:27 +0000 (16:40 -0800)
Assemble the information the stages need and emit the constants.

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

index 1cd85457a93909e7dedf1d3203a108809952e63e..149b27bafc617a9674d4b58df99faaaeb3038d6e 100644 (file)
@@ -790,25 +790,99 @@ fd6_emit_streamout(struct fd_ringbuffer *ring, struct fd6_emit *emit, struct ir3
        }
 }
 
+static void
+emit_tess_bos(struct fd_ringbuffer *ring, struct fd6_emit *emit, struct ir3_shader_variant *s)
+{
+       struct fd_context *ctx = emit->ctx;
+       const unsigned regid = s->shader->const_state.offsets.primitive_param * 4 + 4;
+       uint32_t dwords = 16;
+
+       OUT_PKT7(ring, fd6_stage2opcode(s->type), 3);
+       OUT_RING(ring, CP_LOAD_STATE6_0_DST_OFF(regid / 4) |
+                       CP_LOAD_STATE6_0_STATE_TYPE(ST6_CONSTANTS)|
+                       CP_LOAD_STATE6_0_STATE_SRC(SS6_INDIRECT) |
+                       CP_LOAD_STATE6_0_STATE_BLOCK(fd6_stage2shadersb(s->type)) |
+                       CP_LOAD_STATE6_0_NUM_UNIT(dwords / 4));
+       OUT_RB(ring, ctx->batch->tess_addrs_constobj);
+}
+
+static void
+emit_stage_tess_consts(struct fd_ringbuffer *ring, struct ir3_shader_variant *v,
+               uint32_t *params, int num_params)
+{
+       const unsigned regid = v->shader->const_state.offsets.primitive_param;
+       int size = MIN2(1 + regid, v->constlen) - regid;
+       if (size > 0)
+               fd6_emit_const(ring, v->type, regid * 4, 0, num_params, params, NULL);
+}
+
 static void
 fd6_emit_tess_const(struct fd6_emit *emit)
 {
        struct fd_context *ctx = emit->ctx;
-       const unsigned vs_regid = emit->vs->shader->const_state.offsets.primitive_param;
-       const unsigned gs_regid = emit->gs->shader->const_state.offsets.primitive_param;
-       uint32_t num_vertices = emit->gs->shader->nir->info.gs.vertices_in;
 
-       uint32_t params[4] = {
+       struct fd_ringbuffer *constobj = fd_submit_new_ringbuffer(
+               ctx->batch->submit, 0x1000, FD_RINGBUFFER_STREAMING);
+
+       /* VS sizes are in bytes since that's what STLW/LDLW use, while the HS
+        * size is dwords, since that's what LDG/STG use.
+        */
+       unsigned num_vertices =
+               emit->hs ?
+               emit->info->vertices_per_patch :
+               emit->gs->shader->nir->info.gs.vertices_in;
+
+       uint32_t vs_params[4] = {
                emit->vs->shader->output_size * num_vertices * 4,       /* vs primitive stride */
                emit->vs->shader->output_size * 4,                                      /* vs vertex stride */
-               0, 0,
+               0,
+               0
        };
 
-       struct fd_ringbuffer *constobj = fd_submit_new_ringbuffer(
-               ctx->batch->submit, 0x1000, FD_RINGBUFFER_STREAMING);
+       emit_stage_tess_consts(constobj, emit->vs, vs_params, ARRAY_SIZE(vs_params));
+
+       if (emit->hs) {
+               uint32_t hs_params[4] = {
+                       emit->vs->shader->output_size * num_vertices * 4,       /* vs primitive stride */
+                       emit->vs->shader->output_size * 4,                                      /* vs vertex stride */
+                       emit->hs->shader->output_size,
+                       emit->info->vertices_per_patch
+               };
+
+               emit_stage_tess_consts(constobj, emit->hs, hs_params, ARRAY_SIZE(hs_params));
+               emit_tess_bos(constobj, emit, emit->hs);
+
+               if (emit->gs)
+                       num_vertices = emit->gs->shader->nir->info.gs.vertices_in;
 
-       fd6_emit_const(constobj, emit->vs->type, vs_regid * 4, 0, ARRAY_SIZE(params), params, NULL);
-       fd6_emit_const(constobj, emit->gs->type, gs_regid * 4, 0, ARRAY_SIZE(params), params, NULL);
+               uint32_t ds_params[4] = {
+                       emit->ds->shader->output_size * num_vertices * 4,       /* ds primitive stride */
+                       emit->ds->shader->output_size * 4,                                      /* ds vertex stride */
+                       emit->hs->shader->output_size,                      /* hs vertex stride (dwords) */
+                       emit->hs->shader->nir->info.tess.tcs_vertices_out
+               };
+
+               emit_stage_tess_consts(constobj, emit->ds, ds_params, ARRAY_SIZE(ds_params));
+               emit_tess_bos(constobj, emit, emit->ds);
+       }
+
+       if (emit->gs) {
+               struct ir3_shader_variant *prev;
+               if (emit->ds)
+                       prev = emit->ds;
+               else
+                       prev = emit->vs;
+
+               uint32_t gs_params[4] = {
+                       prev->shader->output_size * num_vertices * 4,   /* ds primitive stride */
+                       prev->shader->output_size * 4,                                  /* ds vertex stride */
+                       0,
+                       0,
+               };
+
+               num_vertices = emit->gs->shader->nir->info.gs.vertices_in;
+               emit_stage_tess_consts(constobj, emit->gs, gs_params, ARRAY_SIZE(gs_params));
+       }
 
        fd6_emit_take_group(emit, constobj, FD6_GROUP_PRIMITIVE_PARAMS, 0x7);
 }
@@ -990,7 +1064,7 @@ fd6_emit_state(struct fd_ringbuffer *ring, struct fd6_emit *emit)
        fd6_emit_consts(emit, gs, PIPE_SHADER_GEOMETRY, FD6_GROUP_GS_CONST, 0x7);
        fd6_emit_consts(emit, fs, PIPE_SHADER_FRAGMENT, FD6_GROUP_FS_CONST, 0x6);
 
-       if (emit->key.key.has_gs)
+       if (emit->key.key.has_gs || emit->key.key.tessellation)
                fd6_emit_tess_const(emit);
 
        /* if driver-params are needed, emit each time: */