mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-06 13:10:10 +01:00
pan/va: Handle terminal barriers
If a shader ends with a workgroup barrier, it must wait for slot #7 at the end to finish the barrier. After inserting flow control, we get: BARRIER NOP.wait NOP.end Currently, the flow control pass assumes that .end implies all other control flow, and will merge this down to BARRIER.end However, this is incorrect. Slot #7 is no longer waited on. In theory, this cannot affect the correctness of the shader. In practice, the hardware checks that all barriers are reached. Terminating without waiting on slot #7 first raises an INSTR_BARRIER_FAULT. We need to weaken the flow control merging slightly to avoid this incorrect merge, instead emitting: BARRIER.wait NOP.end Of course, all of these cases are inefficient: terminal barriers shouldn't be emitted in the first place. I wrote out an optimization for this. We can merge it if we find a workload that it actually helps. Fixes test_half.vstore_half. Signed-off-by: Alyssa Rosenzweig <alyssa@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17264>
This commit is contained in:
parent
4ee6345d2e
commit
154929d731
2 changed files with 15 additions and 2 deletions
|
|
@ -292,3 +292,14 @@ TEST_F(MergeFlow, DeletePointlessDiscard) {
|
|||
});
|
||||
}
|
||||
|
||||
TEST_F(MergeFlow, PreserveTerminalBarriers) {
|
||||
CASE({
|
||||
bi_barrier(b);
|
||||
flow(WAIT);
|
||||
flow(END);
|
||||
},
|
||||
{
|
||||
bi_barrier(b)->flow = VA_FLOW_WAIT;
|
||||
flow(END);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,9 +83,11 @@ merge_end_reconverge(bi_block *block)
|
|||
if (last->op != BI_OPCODE_NOP) return;
|
||||
if (last->flow != VA_FLOW_RECONVERGE && last->flow != VA_FLOW_END) return;
|
||||
|
||||
/* End implies all other flow control, so remove blocking flow control */
|
||||
/* End implies all other flow control except for waiting on barriers (slot
|
||||
* #7, with VA_FLOW_WAIT), so remove blocking flow control.
|
||||
*/
|
||||
if (last->flow == VA_FLOW_END) {
|
||||
while (penult->op == BI_OPCODE_NOP) {
|
||||
while (penult->op == BI_OPCODE_NOP && penult->flow != VA_FLOW_WAIT) {
|
||||
bi_remove_instruction(penult);
|
||||
|
||||
/* There may be nothing left */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue