diff --git a/src/asahi/clc/asahi_clc.c b/src/asahi/clc/asahi_clc.c index 9e6028ad0fb..3c40ec81569 100644 --- a/src/asahi/clc/asahi_clc.c +++ b/src/asahi/clc/asahi_clc.c @@ -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); diff --git a/src/asahi/compiler/agx_compile.c b/src/asahi/compiler/agx_compile.c index afdbfd36b36..4c773b4c019 100644 --- a/src/asahi/compiler/agx_compile.c +++ b/src/asahi/compiler/agx_compile.c @@ -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: diff --git a/src/asahi/compiler/agx_compile.h b/src/asahi/compiler/agx_compile.h index ccff88f9389..00bfb23154a 100644 --- a/src/asahi/compiler/agx_compile.h +++ b/src/asahi/compiler/agx_compile.h @@ -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; diff --git a/src/asahi/compiler/agx_register_allocate.c b/src/asahi/compiler/agx_register_allocate.c index d4b9da765e4..64224b43bfc 100644 --- a/src/asahi/compiler/agx_register_allocate.c +++ b/src/asahi/compiler/agx_register_allocate.c @@ -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 */