summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp11
1 files changed, 10 insertions, 1 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 4cfd6f042..c802532db 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -115,7 +115,16 @@ private:
if (const auto opcode = OpCode::Decode(instr)) {
switch (opcode->GetId()) {
case OpCode::Id::EXIT: {
- return exit_method = ExitMethod::AlwaysEnd;
+ // The EXIT instruction can be predicated, which means that the shader can
+ // conditionally end on this instruction. We have to consider the case where the
+ // condition is not met and check the exit method of that other basic block.
+ using Tegra::Shader::Pred;
+ if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) {
+ return exit_method = ExitMethod::AlwaysEnd;
+ } else {
+ ExitMethod not_met = Scan(offset + 1, end, labels);
+ return exit_method = ParallelExit(ExitMethod::AlwaysEnd, not_met);
+ }
}
case OpCode::Id::BRA: {
u32 target = offset + instr.bra.GetBranchTarget();