brw: allocate physical register sizes for spilling

All of the spilling code should work with physical register units
because for example SEND messages will expect a physical register as
destination.

So always allocate a full physical register for the spilled/unspilled
values and adjust the offsets of the registers to physical sizes too.

Cc: mesa-stable
Fixes: aa494cba ("brw: align spilling offsets to physical register sizes")
Closes: mesa/mesa#11967

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Found-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
(cherry picked from commit a21cd8c5b6)

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32261>
This commit is contained in:
Lionel Landwerlin 2024-11-13 11:08:26 +02:00 committed by Dylan Baker
parent c1517edde6
commit 9c55d78353
2 changed files with 17 additions and 5 deletions

View file

@ -114,7 +114,7 @@
"description": "brw: allocate physical register sizes for spilling",
"nominated": true,
"nomination_type": 2,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": "aa494cbacf3bfa57163bbed8b5552ad25434e713",
"notes": null

View file

@ -1078,13 +1078,19 @@ fs_reg_alloc::spill_reg(unsigned spill_reg)
for (unsigned int i = 0; i < inst->sources; i++) {
if (inst->src[i].file == VGRF &&
inst->src[i].nr == spill_reg) {
int count = regs_read(inst, i);
/* Count registers needed in units of physical registers */
int count = align(regs_read(inst, i), reg_unit(devinfo));
/* Align the spilling offset the physical register size */
int subset_spill_offset = spill_offset +
ROUND_DOWN_TO(inst->src[i].offset, REG_SIZE * reg_unit(devinfo));
brw_reg unspill_dst = alloc_spill_reg(count, ip);
inst->src[i].nr = unspill_dst.nr;
inst->src[i].offset %= REG_SIZE;
/* The unspilled register is aligned to physical register, so
* adjust the offset to the remaining within the physical register
* size.
*/
inst->src[i].offset %= REG_SIZE * reg_unit(devinfo);
/* We read the largest power-of-two divisor of the register count
* (because only POT scratch read blocks are allowed by the
@ -1108,12 +1114,18 @@ fs_reg_alloc::spill_reg(unsigned spill_reg)
if (inst->dst.file == VGRF &&
inst->dst.nr == spill_reg &&
inst->opcode != SHADER_OPCODE_UNDEF) {
/* Count registers needed in units of physical registers */
int count = align(regs_written(inst), reg_unit(devinfo));
/* Align the spilling offset the physical register size */
int subset_spill_offset = spill_offset +
ROUND_DOWN_TO(inst->dst.offset, reg_unit(devinfo) * REG_SIZE);
brw_reg spill_src = alloc_spill_reg(regs_written(inst), ip);
brw_reg spill_src = alloc_spill_reg(count, ip);
inst->dst.nr = spill_src.nr;
inst->dst.offset %= REG_SIZE;
/* The spilled register is aligned to physical register, so adjust
* the offset to the remaining within the physical register size.
*/
inst->dst.offset %= REG_SIZE * reg_unit(devinfo);
/* If we're immediately spilling the register, we should not use
* destination dependency hints. Doing so will cause the GPU do