diff --git a/src/asahi/compiler/README.md b/src/asahi/compiler/README.md index 192aca1d667..0fc72520dca 100644 --- a/src/asahi/compiler/README.md +++ b/src/asahi/compiler/README.md @@ -15,9 +15,12 @@ The following section describes the ABI used by non-monolithic programs. Registers have the following layout at the beginning of the vertex shader (written by the vertex prolog): -* `r0-r4` and `r7` undefined. This avoids preloading into the nesting counter or +* `r0-r3` and `r7` undefined. This avoids preloading into the nesting counter or having unaligned values. The prolog is free to use these registers as temporaries. +* `r4` is the zero-based vertex ID if the vertex shader is running as a hardware + compute shader, useful to avoid a redundant special register read in the main + shader. Undefined in hardware vertex shaders. * `r5-r6` retain their usual meanings, even if the vertex shader is running as a hardware compute shader. This allows software index fetch code to run in the prolog without contaminating the main shader key. diff --git a/src/asahi/compiler/agx_compile.c b/src/asahi/compiler/agx_compile.c index 3f1011a61e1..e541017c883 100644 --- a/src/asahi/compiler/agx_compile.c +++ b/src/asahi/compiler/agx_compile.c @@ -99,6 +99,13 @@ agx_tess_coord_y(agx_builder *b) return agx_cached_preload(b->shader, 6, AGX_SIZE_32); } +static agx_index +agx_vertex_id_zero_base(agx_builder *b) +{ + return agx_cached_preload(b->shader, AGX_ABI_VIN_VERTEX_ID_ZERO_BASE, + AGX_SIZE_32); +} + static agx_index agx_vertex_id(agx_builder *b) { @@ -1417,6 +1424,10 @@ agx_emit_intrinsic(agx_builder *b, nir_intrinsic_instr *instr) agx_get_sr_coverage(b, 32, AGX_SR_IS_ACTIVE_THREAD), agx_zero(), AGX_ICOND_UEQ, false); + case nir_intrinsic_load_vertex_id_zero_base: + assert(stage == MESA_SHADER_COMPUTE && "only for SW VS"); + return agx_mov_to(b, dst, agx_abs(agx_vertex_id_zero_base(b))); + case nir_intrinsic_load_vertex_id: /* We don't assert the HW stage since we use this same ABI with SW VS */ return agx_mov_to(b, dst, agx_abs(agx_vertex_id(b))); diff --git a/src/asahi/lib/agx_abi.h b/src/asahi/lib/agx_abi.h index 20b6a37fef9..a4e52a55ebb 100644 --- a/src/asahi/lib/agx_abi.h +++ b/src/asahi/lib/agx_abi.h @@ -8,9 +8,10 @@ /* See compiler/README.md for the ABI */ -#define AGX_ABI_VIN_ATTRIB(i) (2 * (8 + i)) -#define AGX_ABI_VIN_VERTEX_ID (2 * 5) -#define AGX_ABI_VIN_INSTANCE_ID (2 * 6) +#define AGX_ABI_VIN_ATTRIB(i) (2 * (8 + i)) +#define AGX_ABI_VIN_VERTEX_ID_ZERO_BASE (2 * 4) +#define AGX_ABI_VIN_VERTEX_ID (2 * 5) +#define AGX_ABI_VIN_INSTANCE_ID (2 * 6) #define AGX_ABI_FIN_SAMPLE_MASK (2) diff --git a/src/asahi/lib/agx_nir_prolog_epilog.c b/src/asahi/lib/agx_nir_prolog_epilog.c index 5be15916198..c26d1a11e0b 100644 --- a/src/asahi/lib/agx_nir_prolog_epilog.c +++ b/src/asahi/lib/agx_nir_prolog_epilog.c @@ -193,6 +193,11 @@ agx_nir_vs_prolog(nir_builder *b, const void *key_) nir_export_agx(b, nir_channel(b, vec, c), .base = AGX_ABI_VIN_ATTRIB(i)); } + if (!key->hw) { + nir_export_agx(b, nir_channel(b, nir_load_global_invocation_id(b, 32), 0), + .base = AGX_ABI_VIN_VERTEX_ID_ZERO_BASE); + } + nir_export_agx(b, nir_load_vertex_id(b), .base = AGX_ABI_VIN_VERTEX_ID); nir_export_agx(b, nir_load_instance_id(b), .base = AGX_ABI_VIN_INSTANCE_ID);