agx: add "is helper program?" key bit

so we can enforce correctness a bit more at build-time. if the helper program
does not fit in the required RA, spilling will be broken in the driver; now this
is a build-time failure instead of a silent runtime one.

Closes https://gitlab.freedesktop.org/asahi/mesa/-/issues/36

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27616>
This commit is contained in:
Alyssa Rosenzweig 2024-02-09 13:18:38 -04:00 committed by Marge Bot
parent a3f647fde1
commit c116d1efbb
4 changed files with 21 additions and 1 deletions

View file

@ -507,7 +507,10 @@ main(int argc, char **argv)
UNUSED struct agx_uncompiled_shader_info info;
UNUSED struct agx_shader_info compiled_info;
struct agx_shader_key key = {.libagx = nir};
struct agx_shader_key key = {
.libagx = nir,
.is_helper = true,
};
agx_preprocess_nir(b.shader, nir, false, &info);
agx_compile_shader_nir(b.shader, &key, NULL, &binary, &compiled_info);

View file

@ -1256,6 +1256,7 @@ agx_emit_intrinsic(agx_builder *b, nir_intrinsic_instr *instr)
}
case nir_intrinsic_fence_helper_exit_agx: {
assert(b->shader->key->is_helper);
agx_memory_barrier(b);
agx_unknown_barrier_1(b);
agx_memory_barrier_2(b);
@ -1329,12 +1330,15 @@ agx_emit_intrinsic(agx_builder *b, nir_intrinsic_instr *instr)
return agx_get_sr_to(b, dst, AGX_SR_CORE_ID);
case nir_intrinsic_load_helper_op_id_agx:
assert(b->shader->key->is_helper);
return agx_get_sr_barrier_to(b, dst, AGX_SR_HELPER_OP);
case nir_intrinsic_load_helper_arg_lo_agx:
assert(b->shader->key->is_helper);
return agx_get_sr_barrier_to(b, dst, AGX_SR_HELPER_ARG_L);
case nir_intrinsic_load_helper_arg_hi_agx:
assert(b->shader->key->is_helper);
return agx_get_sr_barrier_to(b, dst, AGX_SR_HELPER_ARG_H);
case nir_intrinsic_load_barycentric_sample:

View file

@ -232,6 +232,11 @@ struct agx_shader_key {
/* Whether scratch memory is available in the given shader stage */
bool has_scratch;
/* Whether we're compiling the helper program used for scratch allocation.
* This has special register allocation requirements.
*/
bool is_helper;
union {
struct agx_vs_shader_key vs;
struct agx_fs_shader_key fs;

View file

@ -1141,6 +1141,11 @@ agx_ra(agx_context *ctx)
agx_max_registers_for_occupancy(threads_per_workgroup);
}
/* The helper program is unspillable and has a limited register file */
if (ctx->key->is_helper) {
max_possible_regs = 32;
}
/* Calculate the demand. We'll use it to determine if we need to spill and to
* bound register assignment.
*/
@ -1211,6 +1216,9 @@ agx_ra(agx_context *ctx)
* affecting occupancy. This reduces live range splitting.
*/
unsigned max_regs = agx_occupancy_for_register_count(demand).max_registers;
if (ctx->key->is_helper)
max_regs = 32;
max_regs = ROUND_DOWN_TO(max_regs, reg_file_alignment);
/* Or, we can bound tightly for debugging */