From 72cd592cf92e6b37609308fa80b07e555940f457 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 20 Mar 2015 17:25:28 +0000 Subject: [PATCH] i965: Don't use the same register for src and dest in vec4 send Organization: Intel Corporation (UK) Ltd. - Co. Reg. #1134945 - Pipers Way, Swindon SN3 1RJ Using the same source and dest register seems to cause trouble when sampling via a send instruction. This patch tries to prevent that by setting the interval of the source register to include the current instruction whenever the opcode might be a send instruction. This problem was manifesting itself as a rendering bug in ETQW on Skylake. However if I hack Mesa to force it to allocate the same register for send and receive then it also seems to break on Haswell so it may be that the restriction is valid everywhere and it's just coincidence that the registers are allocated that way in this particular game on Skylake. The patch is not complete because I can't find any mention of this restriction in the BSpec so I don't know exactly where it applies. We would probably have to do something similar for the FS allocator and there are probably more opcodes that can generate send instructions that we would need to catch. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=89058 --- src/mesa/drivers/dri/i965/brw_vec4_live_variables.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/mesa/drivers/dri/i965/brw_vec4_live_variables.cpp b/src/mesa/drivers/dri/i965/brw_vec4_live_variables.cpp index c562b2e..f8e3313 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_live_variables.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_live_variables.cpp @@ -247,6 +247,21 @@ vec4_visitor::calculate_live_intervals() */ int ip = 0; foreach_block_and_inst(block, vec4_instruction, inst, cfg) { + int src_end_ip = ip; + + /* The same register can't be used as the source and dest in a send + * instruction so in this case we need to mark that the source is used + * during the instruction to prevent it being chosen as the destination + * as well */ + switch (inst->opcode) { + case BRW_OPCODE_SEND: + case BRW_OPCODE_SENDC: + case VS_OPCODE_PULL_CONSTANT_LOAD: + case VS_OPCODE_PULL_CONSTANT_LOAD_GEN7: + src_end_ip++; + break; + } + for (unsigned int i = 0; i < 3; i++) { if (inst->src[i].file == GRF) { int reg = inst->src[i].reg; @@ -255,7 +270,7 @@ vec4_visitor::calculate_live_intervals() int c = BRW_GET_SWZ(inst->src[i].swizzle, j); start[reg * 4 + c] = MIN2(start[reg * 4 + c], ip); - end[reg * 4 + c] = ip; + end[reg * 4 + c] = src_end_ip; } } } -- 1.9.3