aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/freedreno
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/freedreno')
-rw-r--r--src/gallium/drivers/freedreno/a6xx/fd6_emit.c25
-rw-r--r--src/gallium/drivers/freedreno/a6xx/fd6_emit.h1
-rw-r--r--src/gallium/drivers/freedreno/a6xx/fd6_program.c9
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_gallium.c48
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_gallium.h3
5 files changed, 82 insertions, 4 deletions
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
index b732372f055..6d27b341935 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
@@ -790,6 +790,28 @@ fd6_emit_streamout(struct fd_ringbuffer *ring, struct fd6_emit *emit, struct ir3
}
}
+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] = {
+ emit->vs->shader->output_size * num_vertices * 4, /* vs primitive stride */
+ emit->vs->shader->output_size * 4, /* vs vertex stride */
+ 0, 0,
+ };
+
+ struct fd_ringbuffer *constobj = fd_submit_new_ringbuffer(
+ ctx->batch->submit, 0x1000, FD_RINGBUFFER_STREAMING);
+
+ 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);
+
+ fd6_emit_take_group(emit, constobj, FD6_GROUP_PRIMITIVE_PARAMS, 0x7);
+}
static void
fd6_emit_consts(struct fd6_emit *emit, const struct ir3_shader_variant *v,
@@ -968,6 +990,9 @@ 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)
+ fd6_emit_tess_const(emit);
+
/* if driver-params are needed, emit each time: */
if (ir3_needs_vs_driver_params(vs)) {
struct fd_ringbuffer *dpconstobj = fd_submit_new_ringbuffer(
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_emit.h b/src/gallium/drivers/freedreno/a6xx/fd6_emit.h
index 107723fb076..f2f1a7f8085 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_emit.h
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_emit.h
@@ -55,6 +55,7 @@ enum fd6_state_id {
FD6_GROUP_GS_CONST,
FD6_GROUP_FS_CONST,
FD6_GROUP_VS_DRIVER_PARAMS,
+ FD6_GROUP_PRIMITIVE_PARAMS,
FD6_GROUP_VS_TEX,
FD6_GROUP_HS_TEX,
FD6_GROUP_DS_TEX,
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_program.c b/src/gallium/drivers/freedreno/a6xx/fd6_program.c
index 045658ce2c0..f64cb982cd7 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_program.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_program.c
@@ -537,6 +537,11 @@ setup_stateobj(struct fd_ringbuffer *ring, struct fd_screen *screen,
A6XX_VPC_PACK_PSIZELOC(psize_loc) |
A6XX_VPC_PACK_STRIDE_IN_VPC(l.max_loc));
+ if (gs) {
+ ir3_emit_immediates(screen, gs, ring);
+ ir3_emit_link_map(screen, vs, gs, ring);
+ }
+
if (!binning_pass) {
/* figure out VARYING_INTERP / VARYING_PS_REPL register values: */
for (j = -1; (j = ir3_next_varying(fs, j)) < (int)fs->inputs_count; ) {
@@ -589,10 +594,6 @@ setup_stateobj(struct fd_ringbuffer *ring, struct fd_screen *screen,
ir3_emit_immediates(screen, ds, ring);
}
- if (gs) {
- ir3_emit_immediates(screen, gs, ring);
- }
-
if (!binning_pass)
ir3_emit_immediates(screen, fs, ring);
}
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_gallium.c b/src/gallium/drivers/freedreno/ir3/ir3_gallium.c
index 11a4dc78161..e5ea424b221 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_gallium.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_gallium.c
@@ -396,6 +396,54 @@ ir3_emit_immediates(struct fd_screen *screen, const struct ir3_shader_variant *v
}
}
+static uint32_t
+link_geometry_stages(const struct ir3_shader_variant *producer,
+ const struct ir3_shader_variant *consumer,
+ uint32_t *locs)
+{
+ uint32_t num_loc = 0;
+
+ nir_foreach_variable(in_var, &consumer->shader->nir->inputs) {
+ nir_foreach_variable(out_var, &producer->shader->nir->outputs) {
+ if (in_var->data.location == out_var->data.location) {
+ locs[in_var->data.driver_location] =
+ producer->shader->output_loc[out_var->data.driver_location] * 4;
+
+ debug_assert(num_loc <= in_var->data.driver_location + 1);
+ num_loc = in_var->data.driver_location + 1;
+ }
+ }
+ }
+
+ return num_loc;
+}
+
+void
+ir3_emit_link_map(struct fd_screen *screen,
+ const struct ir3_shader_variant *producer,
+ const struct ir3_shader_variant *v, struct fd_ringbuffer *ring)
+{
+ const struct ir3_const_state *const_state = &v->shader->const_state;
+ uint32_t base = const_state->offsets.primitive_map;
+ uint32_t patch_locs[MAX_VARYING] = { }, num_loc;
+
+ num_loc = link_geometry_stages(producer, v, patch_locs);
+
+ int size = DIV_ROUND_UP(num_loc, 4);
+
+ /* truncate size to avoid writing constants that shader
+ * does not use:
+ */
+ size = MIN2(size + base, v->constlen) - base;
+
+ /* convert out of vec4: */
+ base *= 4;
+ size *= 4;
+
+ if (size > 0)
+ emit_const(screen, ring, v, base, 0, size, patch_locs, NULL);
+}
+
/* emit stream-out buffers: */
static void
emit_tfbos(struct fd_context *ctx, const struct ir3_shader_variant *v,
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_gallium.h b/src/gallium/drivers/freedreno/ir3/ir3_gallium.h
index 5352df51990..33a94a6a9f8 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_gallium.h
+++ b/src/gallium/drivers/freedreno/ir3/ir3_gallium.h
@@ -63,6 +63,9 @@ void ir3_emit_image_dims(struct fd_screen *screen, const struct ir3_shader_varia
struct fd_ringbuffer *ring, struct fd_shaderimg_stateobj *si);
void ir3_emit_immediates(struct fd_screen *screen, const struct ir3_shader_variant *v,
struct fd_ringbuffer *ring);
+void ir3_emit_link_map(struct fd_screen *screen,
+ const struct ir3_shader_variant *producer,
+ const struct ir3_shader_variant *v, struct fd_ringbuffer *ring);
static inline bool
ir3_needs_vs_driver_params(const struct ir3_shader_variant *v)