}
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);
}
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: */