summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Ho <brian@brkho.com>2020-04-24 12:20:10 -0700
committerMarge Bot <eric+marge@anholt.net>2020-06-22 14:35:45 +0000
commit8cb226b2588edbe67488d23a3425a78e78152004 (patch)
tree761fd0541026e025b3586ae333640ff48d805fb0
parentf08a80dcd493c64922c04a2563025bddabcac230 (diff)
turnip: Update VFD_CONTROL with tess system values
Support for TessCoord, PatchID, TCSHeader. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5059>
-rw-r--r--src/freedreno/vulkan/tu_clear_blit.c2
-rw-r--r--src/freedreno/vulkan/tu_pipeline.c144
-rw-r--r--src/freedreno/vulkan/tu_private.h2
3 files changed, 136 insertions, 12 deletions
diff --git a/src/freedreno/vulkan/tu_clear_blit.c b/src/freedreno/vulkan/tu_clear_blit.c
index c452d7e8f05..d17b990f491 100644
--- a/src/freedreno/vulkan/tu_clear_blit.c
+++ b/src/freedreno/vulkan/tu_clear_blit.c
@@ -517,7 +517,7 @@ r3d_common(struct tu_cmd_buffer *cmd, struct tu_cs *cs, bool blit, uint32_t num_
tu_cs_emit_regs(cs, A6XX_PC_PRIMITIVE_CNTL_0());
tu_cs_emit_regs(cs, A6XX_VFD_CONTROL_0());
- tu6_emit_vpc(cs, &vs, gs, &fs, NULL);
+ tu6_emit_vpc(cs, &vs, NULL, NULL, gs, &fs, NULL);
/* REPL_MODE for varying with RECTLIST (2 vertices only) */
tu_cs_emit_regs(cs, A6XX_VPC_VARYING_INTERP_MODE(0, 0));
diff --git a/src/freedreno/vulkan/tu_pipeline.c b/src/freedreno/vulkan/tu_pipeline.c
index 5e21b6031fa..a0c11b679ab 100644
--- a/src/freedreno/vulkan/tu_pipeline.c
+++ b/src/freedreno/vulkan/tu_pipeline.c
@@ -494,6 +494,8 @@ tu6_emit_cs_config(struct tu_cs *cs, const struct tu_shader *shader,
static void
tu6_emit_vs_system_values(struct tu_cs *cs,
const struct ir3_shader_variant *vs,
+ const struct ir3_shader_variant *hs,
+ const struct ir3_shader_variant *ds,
const struct ir3_shader_variant *gs,
bool primid_passthru)
{
@@ -501,6 +503,21 @@ tu6_emit_vs_system_values(struct tu_cs *cs,
ir3_find_sysval_regid(vs, SYSTEM_VALUE_VERTEX_ID);
const uint32_t instanceid_regid =
ir3_find_sysval_regid(vs, SYSTEM_VALUE_INSTANCE_ID);
+ const uint32_t tess_coord_x_regid = hs ?
+ ir3_find_sysval_regid(ds, SYSTEM_VALUE_TESS_COORD) :
+ regid(63, 0);
+ const uint32_t tess_coord_y_regid = VALIDREG(tess_coord_x_regid) ?
+ tess_coord_x_regid + 1 :
+ regid(63, 0);
+ const uint32_t hs_patch_regid = hs ?
+ ir3_find_sysval_regid(hs, SYSTEM_VALUE_PRIMITIVE_ID) :
+ regid(63, 0);
+ const uint32_t ds_patch_regid = hs ?
+ ir3_find_sysval_regid(ds, SYSTEM_VALUE_PRIMITIVE_ID) :
+ regid(63, 0);
+ const uint32_t hs_invocation_regid = hs ?
+ ir3_find_sysval_regid(hs, SYSTEM_VALUE_TCS_HEADER_IR3) :
+ regid(63, 0);
const uint32_t primitiveid_regid = gs ?
ir3_find_sysval_regid(gs, SYSTEM_VALUE_PRIMITIVE_ID) :
regid(63, 0);
@@ -513,8 +530,12 @@ tu6_emit_vs_system_values(struct tu_cs *cs,
A6XX_VFD_CONTROL_1_REGID4INST(instanceid_regid) |
A6XX_VFD_CONTROL_1_REGID4PRIMID(primitiveid_regid) |
0xfc000000);
- tu_cs_emit(cs, 0x0000fcfc); /* VFD_CONTROL_2 */
- tu_cs_emit(cs, 0xfcfcfcfc); /* VFD_CONTROL_3 */
+ tu_cs_emit(cs, A6XX_VFD_CONTROL_2_REGID_HSPATCHID(hs_patch_regid) |
+ A6XX_VFD_CONTROL_2_REGID_INVOCATIONID(hs_invocation_regid));
+ tu_cs_emit(cs, A6XX_VFD_CONTROL_3_REGID_DSPATCHID(ds_patch_regid) |
+ A6XX_VFD_CONTROL_3_REGID_TESSX(tess_coord_x_regid) |
+ A6XX_VFD_CONTROL_3_REGID_TESSY(tess_coord_y_regid) |
+ 0xfc);
tu_cs_emit(cs, 0x000000fc); /* VFD_CONTROL_4 */
tu_cs_emit(cs, A6XX_VFD_CONTROL_5_REGID_GSHEADER(gsheader_regid) |
0xfc00); /* VFD_CONTROL_5 */
@@ -652,7 +673,9 @@ tu6_emit_const(struct tu_cs *cs, uint32_t opcode, uint32_t base,
static void
tu6_emit_link_map(struct tu_cs *cs,
const struct ir3_shader_variant *producer,
- const struct ir3_shader_variant *consumer) {
+ const struct ir3_shader_variant *consumer,
+ enum a6xx_state_block sb)
+{
const struct ir3_const_state *const_state = ir3_const_state(consumer);
uint32_t base = const_state->offsets.primitive_map;
uint32_t patch_locs[MAX_VARYING] = { }, num_loc;
@@ -663,8 +686,8 @@ tu6_emit_link_map(struct tu_cs *cs,
if (size <= 0)
return;
- tu6_emit_const(cs, CP_LOAD_STATE6_GEOM, base, SB6_GS_SHADER, 0,
- size, patch_locs);
+ tu6_emit_const(cs, CP_LOAD_STATE6_GEOM, base, sb, 0, size,
+ patch_locs);
}
static uint16_t
@@ -684,11 +707,20 @@ gl_primitive_to_tess(uint16_t primitive) {
void
tu6_emit_vpc(struct tu_cs *cs,
const struct ir3_shader_variant *vs,
+ const struct ir3_shader_variant *hs,
+ const struct ir3_shader_variant *ds,
const struct ir3_shader_variant *gs,
const struct ir3_shader_variant *fs,
struct tu_streamout_state *tf)
{
- const struct ir3_shader_variant *last_shader = gs ?: vs;
+ const struct ir3_shader_variant *last_shader;
+ if (gs) {
+ last_shader = gs;
+ } else if (hs) {
+ last_shader = ds;
+ } else {
+ last_shader = vs;
+ }
struct ir3_shader_linkage linkage = { .primid_loc = 0xff };
if (fs)
ir3_link_shaders(&linkage, last_shader, fs, true);
@@ -700,7 +732,7 @@ tu6_emit_vpc(struct tu_cs *cs,
* passthrough needs to be enabled.
*/
bool primid_passthru = linkage.primid_loc != 0xff;
- tu6_emit_vs_system_values(cs, vs, gs, primid_passthru);
+ tu6_emit_vs_system_values(cs, vs, hs, ds, gs, primid_passthru);
tu_cs_emit_pkt4(cs, REG_A6XX_VPC_VAR_DISABLE(0), 4);
tu_cs_emit(cs, ~linkage.varmask[0]);
@@ -749,12 +781,16 @@ tu6_emit_vpc(struct tu_cs *cs,
if (gs)
tu_cs_emit_pkt4(cs, REG_A6XX_SP_GS_OUT_REG(0), sp_out_count);
+ else if (hs)
+ tu_cs_emit_pkt4(cs, REG_A6XX_SP_DS_OUT_REG(0), sp_out_count);
else
tu_cs_emit_pkt4(cs, REG_A6XX_SP_VS_OUT_REG(0), sp_out_count);
tu_cs_emit_array(cs, sp_out, sp_out_count);
if (gs)
tu_cs_emit_pkt4(cs, REG_A6XX_SP_GS_VPC_DST_REG(0), sp_vpc_dst_count);
+ else if (hs)
+ tu_cs_emit_pkt4(cs, REG_A6XX_SP_DS_VPC_DST_REG(0), sp_vpc_dst_count);
else
tu_cs_emit_pkt4(cs, REG_A6XX_SP_VS_VPC_DST_REG(0), sp_vpc_dst_count);
tu_cs_emit_array(cs, sp_vpc_dst, sp_vpc_dst_count);
@@ -770,14 +806,100 @@ tu6_emit_vpc(struct tu_cs *cs,
tu_cs_emit_pkt4(cs, REG_A6XX_VPC_PACK, 1);
tu_cs_emit(cs, A6XX_VPC_PACK_POSITIONLOC(position_loc) |
- A6XX_VPC_PACK_PSIZELOC(pointsize_loc) |
- A6XX_VPC_PACK_STRIDE_IN_VPC(linkage.max_loc));
+ A6XX_VPC_PACK_PSIZELOC(pointsize_loc) |
+ A6XX_VPC_PACK_STRIDE_IN_VPC(linkage.max_loc));
+
+ if (hs) {
+ shader_info *hs_info = &hs->shader->nir->info;
+ tu_cs_emit_pkt4(cs, REG_A6XX_PC_TESS_NUM_VERTEX, 1);
+ tu_cs_emit(cs, hs_info->tess.tcs_vertices_out);
+
+ /* Total attribute slots in HS incoming patch. */
+ tu_cs_emit_pkt4(cs, REG_A6XX_PC_UNKNOWN_9801, 1);
+ tu_cs_emit(cs,
+ hs_info->tess.tcs_vertices_out * vs->output_size / 4);
+
+ tu_cs_emit_pkt4(cs, REG_A6XX_SP_HS_UNKNOWN_A831, 1);
+ tu_cs_emit(cs, vs->output_size);
+ /* In SPIR-V generated from GLSL, the tessellation primitive params are
+ * are specified in the tess eval shader, but in SPIR-V generated from
+ * HLSL, they are specified in the tess control shader. */
+ shader_info *tess_info =
+ ds->shader->nir->info.tess.spacing == TESS_SPACING_UNSPECIFIED ?
+ &hs->shader->nir->info : &ds->shader->nir->info;
+ tu_cs_emit_pkt4(cs, REG_A6XX_PC_TESS_CNTL, 1);
+ uint32_t output;
+ if (tess_info->tess.point_mode)
+ output = TESS_POINTS;
+ else if (tess_info->tess.primitive_mode == GL_ISOLINES)
+ output = TESS_LINES;
+ else if (tess_info->tess.ccw)
+ output = TESS_CCW_TRIS;
+ else
+ output = TESS_CW_TRIS;
+
+ enum a6xx_tess_spacing spacing;
+ switch (tess_info->tess.spacing) {
+ case TESS_SPACING_EQUAL:
+ spacing = TESS_EQUAL;
+ break;
+ case TESS_SPACING_FRACTIONAL_ODD:
+ spacing = TESS_FRACTIONAL_ODD;
+ break;
+ case TESS_SPACING_FRACTIONAL_EVEN:
+ spacing = TESS_FRACTIONAL_EVEN;
+ break;
+ case TESS_SPACING_UNSPECIFIED:
+ default:
+ unreachable("invalid tess spacing");
+ }
+ tu_cs_emit(cs, A6XX_PC_TESS_CNTL_SPACING(spacing) |
+ A6XX_PC_TESS_CNTL_OUTPUT(output));
+
+ /* xxx: Misc tess unknowns: */
+ tu_cs_emit_pkt4(cs, REG_A6XX_VPC_UNKNOWN_9103, 1);
+ tu_cs_emit(cs, 0x00ffff00);
+
+ tu_cs_emit_pkt4(cs, REG_A6XX_VPC_UNKNOWN_9106, 1);
+ tu_cs_emit(cs, 0x0000ffff);
+
+ tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_UNKNOWN_809D, 1);
+ tu_cs_emit(cs, 0x0);
+
+ tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_UNKNOWN_8002, 1);
+ tu_cs_emit(cs, 0x0);
+
+ tu_cs_emit_pkt4(cs, REG_A6XX_VPC_PACK, 1);
+ tu_cs_emit(cs, A6XX_VPC_PACK_POSITIONLOC(position_loc) |
+ A6XX_VPC_PACK_PSIZELOC(255) |
+ A6XX_VPC_PACK_STRIDE_IN_VPC(linkage.max_loc));
+
+ tu_cs_emit_pkt4(cs, REG_A6XX_VPC_PACK_3, 1);
+ tu_cs_emit(cs, A6XX_VPC_PACK_3_POSITIONLOC(position_loc) |
+ A6XX_VPC_PACK_3_PSIZELOC(pointsize_loc) |
+ A6XX_VPC_PACK_3_STRIDE_IN_VPC(linkage.max_loc));
+
+ tu_cs_emit_pkt4(cs, REG_A6XX_SP_DS_PRIMITIVE_CNTL, 1);
+ tu_cs_emit(cs, A6XX_SP_DS_PRIMITIVE_CNTL_DSOUT(linkage.cnt));
+
+ tu_cs_emit_pkt4(cs, REG_A6XX_PC_PRIMITIVE_CNTL_4, 1);
+ tu_cs_emit(cs, A6XX_PC_PRIMITIVE_CNTL_4_STRIDE_IN_VPC(linkage.max_loc) |
+ CONDREG(pointsize_regid, 0x100));
+
+ tu6_emit_link_map(cs, vs, hs, SB6_HS_SHADER);
+ tu6_emit_link_map(cs, hs, ds, SB6_DS_SHADER);
+ }
+
if (gs) {
uint32_t vertices_out, invocations, output, vec4_size;
/* this detects the tu_clear_blit path, which doesn't set ->nir */
if (gs->shader->nir) {
- tu6_emit_link_map(cs, vs, gs);
+ if (hs) {
+ tu6_emit_link_map(cs, ds, gs, SB6_GS_SHADER);
+ } else {
+ tu6_emit_link_map(cs, vs, gs, SB6_GS_SHADER);
+ }
vertices_out = gs->shader->nir->info.gs.vertices_out - 1;
output = gl_primitive_to_tess(gs->shader->nir->info.gs.output_primitive);
invocations = gs->shader->nir->info.gs.invocations - 1;
@@ -1233,7 +1355,7 @@ tu6_emit_program(struct tu_cs *cs,
tu_cs_emit_pkt4(cs, REG_A6XX_SP_HS_UNKNOWN_A831, 1);
tu_cs_emit(cs, 0);
- tu6_emit_vpc(cs, vs, gs, fs, tf);
+ tu6_emit_vpc(cs, vs, hs, ds, gs, fs, tf);
tu6_emit_vpc_varying_modes(cs, fs);
if (fs) {
diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h
index 153184f5999..ab7cdc65491 100644
--- a/src/freedreno/vulkan/tu_private.h
+++ b/src/freedreno/vulkan/tu_private.h
@@ -1161,6 +1161,8 @@ tu6_emit_xs_config(struct tu_cs *cs,
void
tu6_emit_vpc(struct tu_cs *cs,
const struct ir3_shader_variant *vs,
+ const struct ir3_shader_variant *hs,
+ const struct ir3_shader_variant *ds,
const struct ir3_shader_variant *gs,
const struct ir3_shader_variant *fs,
struct tu_streamout_state *tf);