From 03a30e7c3d6cd6737ce60e35b23eec5e7b1a46ba Mon Sep 17 00:00:00 2001 From: "Kristian H. Kristensen" Date: Tue, 22 Oct 2019 19:58:59 -0700 Subject: [PATCH] freedreno/a6xx: Emit constant parameters for tessellation stages Assemble the information the stages need and emit the constants. Signed-off-by: Kristian H. Kristensen Acked-by: Eric Anholt Reviewed-by: Rob Clark --- src/gallium/drivers/freedreno/a6xx/fd6_emit.c | 94 +++++++++++++++++-- 1 file changed, 84 insertions(+), 10 deletions(-) diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c index 1cd85457a93..149b27bafc6 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c @@ -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: */ -- 2.30.2