radeonsi: fix hang caused by for loop with exec=0 in LS and ES
authorMarek Olšák <marek.olsak@amd.com>
Tue, 5 Jan 2021 08:23:08 +0000 (03:23 -0500)
committerMarek Olšák <marek.olsak@amd.com>
Thu, 7 Jan 2021 04:28:01 +0000 (23:28 -0500)
commitb6b6d1ff3c16aa0dfdb7f08c8ca03908022dceb6
tree01cefaae61e64c793d95e13b98a3b72dc34bce1d
parent9f9bc35dc0115a73938b85e96ab322d906de4b62
radeonsi: fix hang caused by for loop with exec=0 in LS and ES

LLVM expects that exec != 0 when entering loops and generates this code
that becomes an infinite loop if exec == 0:

BB5_1:
    vcc_lo = (inverted terminating condition)
    s_and_b32 vcc_lo, exec_lo, vcc_lo
    s_cbranch_vccnz BB5_3    // jump if vcc != 0 (break statement)
    // ... loop body ...
    s_branch BB5_1
BB5_3:

For non-monolithic VS before TCS, VS before GS, and TES before GS,
we set exec = (thread enabledmask), which sets 0 for HS-only and GS-only
waves, causing the infinite loop condition above.

Fix it as follows:
- set exec = ~0 at the beginning
- wrap the whole shader (LS and ES) in a conditional block, so that HS-only
  and GS-only waves jump over it and never enter such a loop

The TES before GS hang can be reproduced by gfxbench:
    testfw_app --gfx egl -w 1920 -h 1080 --gl_api gles -t gl_tess

Fixes: 68d6d097f15 - radeonsi/gfx9: add GFX9 and VEGA10 enums

Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8344>
src/gallium/drivers/radeonsi/si_shader.h
src/gallium/drivers/radeonsi/si_shader_internal.h
src/gallium/drivers/radeonsi/si_shader_llvm.c
src/gallium/drivers/radeonsi/si_shader_llvm_gs.c
src/gallium/drivers/radeonsi/si_shader_llvm_tess.c
src/gallium/drivers/radeonsi/si_shader_llvm_vs.c
src/gallium/drivers/radeonsi/si_state_shaders.c