diff options
author | Kenneth Graunke <[email protected]> | 2016-05-14 23:54:48 -0700 |
---|---|---|
committer | Kenneth Graunke <[email protected]> | 2016-05-16 00:20:07 -0700 |
commit | 2fd79ebe8fe4f0f0397bba1624deed9fa4e7fc3b (patch) | |
tree | 6905cd901d367d1f55f6dc6b23d66127b37fc5c7 /src/mesa/drivers/dri/i965/brw_eu_emit.c | |
parent | 2f02fad6b3a0429798c3bd4feb4501dafa5e2fc0 (diff) |
i965: Fix JIP to skip over sibling do...while loops.
We've apparently always been botching JIP for sequences such as:
do
cmp.f0.0 ...
(+f0.0) break
...
do
...
while
...
while
Because the "do" instruction doesn't actually exist, the inner "while"
is at the same depth as the "break". brw_find_next_block_end() thus
mistook the inner "while" as the end of the loop containing the "break",
and set the "break" to point to the wrong place.
Only "while" instructions that jump before our instruction are relevant.
We need to ignore the rest, as they're sibling control flow nodes (or
children, but this was already handled by the depth == 0 check).
See also commit 1ac1581f3889d5f7e6e231c05651f44fbd80f0b6.
This prevents channel masks from being screwed up, and fixes GPU
hangs(*) in dEQP-GLES31.functional.shaders.multisample_interpolation.
interpolate_at_sample.centroid_qualified.multisample_texture_16.
The test ended up executing code with no channels enabled, and that
code contained FIND_LIVE_CHANNEL, which returned 8 (out of range for
a SIMD8 program), which then was used in indirect GRF addressing,
which randomly got a boolean value (0xFFFFFFFF), interpreted it as
a sample ID, OR'd it into an indirect send message descriptor,
which corrupted the message length, sending a pixel interpolator
message with mlen 15, which is illegal. Whew :)
(*) Technically, the test doesn't GPU hang currently, but only
because another bug prevents it from issuing pixel interpolator
messages entirely...with that fixed, it hangs.
Cc: [email protected]
Signed-off-by: Kenneth Graunke <[email protected]>
Reviewed-by: Francisco Jerez <[email protected]>
Diffstat (limited to 'src/mesa/drivers/dri/i965/brw_eu_emit.c')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_eu_emit.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_eu_emit.c b/src/mesa/drivers/dri/i965/brw_eu_emit.c index cc2876b1068..d31943d001d 100644 --- a/src/mesa/drivers/dri/i965/brw_eu_emit.c +++ b/src/mesa/drivers/dri/i965/brw_eu_emit.c @@ -2689,8 +2689,13 @@ brw_find_next_block_end(struct brw_codegen *p, int start_offset) return offset; depth--; break; - case BRW_OPCODE_ELSE: case BRW_OPCODE_WHILE: + /* If the while doesn't jump before our instruction, it's the end + * of a sibling do...while loop. Ignore it. + */ + if (!while_jumps_before_offset(devinfo, insn, offset, start_offset)) + continue; + case BRW_OPCODE_ELSE: case BRW_OPCODE_HALT: if (depth == 0) return offset; |