diff --git a/src/intel/compiler/brw_compiler.h b/src/intel/compiler/brw_compiler.h index f0fcf83fd44..e373d022c02 100644 --- a/src/intel/compiler/brw_compiler.h +++ b/src/intel/compiler/brw_compiler.h @@ -128,6 +128,15 @@ struct brw_compiler { */ bool use_bindless_sampler_offset; + /** + * Calling the ra_allocate function after each register spill can take + * several minutes. This option speeds up shader compilation by spilling + * more registers after the ra_allocate failure. Required for + * Cyberpunk 2077, which uses a watchdog thread to terminate the process + * in case the render thread hasn't responded within 2 minutes. + */ + int spilling_rate; + struct nir_shader *clc_shader; struct { diff --git a/src/intel/compiler/brw_fs_reg_allocate.cpp b/src/intel/compiler/brw_fs_reg_allocate.cpp index 9a6fe4db0cb..3b71a1d22a5 100644 --- a/src/intel/compiler/brw_fs_reg_allocate.cpp +++ b/src/intel/compiler/brw_fs_reg_allocate.cpp @@ -1308,7 +1308,7 @@ fs_reg_alloc::assign_regs(bool allow_spilling, bool spill_all) { build_interference_graph(fs->spilled_any_registers || spill_all); - bool spilled = false; + unsigned spilled = 0; while (1) { /* Debug of register spilling: Go spill everything. */ if (unlikely(spill_all)) { @@ -1325,24 +1325,33 @@ fs_reg_alloc::assign_regs(bool allow_spilling, bool spill_all) if (!allow_spilling) return false; - /* Failed to allocate registers. Spill a reg, and the caller will + /* Failed to allocate registers. Spill some regs, and the caller will * loop back into here to try again. */ - int reg = choose_spill_reg(); - if (reg == -1) - return false; + unsigned nr_spills = 1; + if (compiler->spilling_rate) + nr_spills = MAX2(1, spilled / compiler->spilling_rate); - /* If we're going to spill but we've never spilled before, we need to - * re-build the interference graph with MRFs enabled to allow spilling. - */ - if (!fs->spilled_any_registers) { - discard_interference_graph(); - build_interference_graph(true); + for (unsigned j = 0; j < nr_spills; j++) { + int reg = choose_spill_reg(); + if (reg == -1) { + if (j == 0) + return false; /* Nothing to spill */ + break; + } + + /* If we're going to spill but we've never spilled before, we need + * to re-build the interference graph with MRFs enabled to allow + * spilling. + */ + if (!fs->spilled_any_registers) { + discard_interference_graph(); + build_interference_graph(true); + } + + spill_reg(reg); + spilled++; } - - spilled = true; - - spill_reg(reg); } if (spilled)