From 3aa8b644a921020beb91109f284ae86dc2f7e189 Mon Sep 17 00:00:00 2001
From: FernandoS27 <fsahmkow27@gmail.com>
Date: Fri, 19 Oct 2018 12:17:02 -0400
Subject: [PATCH] Assert Control Flow Instructions using Control Codes

---
 src/video_core/engines/shader_bytecode.h      |  3 +-
 .../renderer_opengl/gl_shader_decompiler.cpp  | 28 +++++++++++++++++--
 2 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 141b9159b..55763332e 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -1232,6 +1232,7 @@ union Instruction {
     BitField<60, 1, u64> is_b_gpr;
     BitField<59, 1, u64> is_c_gpr;
     BitField<20, 24, s64> smem_imm;
+    BitField<0, 5, ControlCode> flow_control_code;
 
     Attribute attribute;
     Sampler sampler;
@@ -1658,4 +1659,4 @@ private:
     }
 };
 
-} // namespace Tegra::Shader
\ No newline at end of file
+} // namespace Tegra::Shader
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index dcf6941b0..087baf9ed 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -3375,6 +3375,12 @@ private:
                     EmitFragmentOutputsWrite();
                 }
 
+                const Tegra::Shader::ControlCode cc = instr.flow_control_code;
+                if (cc != Tegra::Shader::ControlCode::T) {
+                    LOG_CRITICAL(HW_GPU, "EXIT Control Code used: {}", static_cast<u32>(cc));
+                    UNREACHABLE();
+                }
+
                 switch (instr.flow.cond) {
                 case Tegra::Shader::FlowCondition::Always:
                     shader.AddLine("return true;");
@@ -3404,6 +3410,11 @@ private:
 
                 // Enclose "discard" in a conditional, so that GLSL compilation does not complain
                 // about unexecuted instructions that may follow this.
+                const Tegra::Shader::ControlCode cc = instr.flow_control_code;
+                if (cc != Tegra::Shader::ControlCode::T) {
+                    LOG_CRITICAL(HW_GPU, "KIL Control Code used: {}", static_cast<u32>(cc));
+                    UNREACHABLE();
+                }
                 shader.AddLine("if (true) {");
                 ++shader.scope;
                 shader.AddLine("discard;");
@@ -3461,6 +3472,11 @@ private:
             case OpCode::Id::BRA: {
                 ASSERT_MSG(instr.bra.constant_buffer == 0,
                            "BRA with constant buffers are not implemented");
+                const Tegra::Shader::ControlCode cc = instr.flow_control_code;
+                if (cc != Tegra::Shader::ControlCode::T) {
+                    LOG_CRITICAL(HW_GPU, "BRA Control Code used: {}", static_cast<u32>(cc));
+                    UNREACHABLE();
+                }
                 const u32 target = offset + instr.bra.GetBranchTarget();
                 shader.AddLine("{ jmp_to = " + std::to_string(target) + "u; break; }");
                 break;
@@ -3501,13 +3517,21 @@ private:
             }
             case OpCode::Id::SYNC: {
                 // The SYNC opcode jumps to the address previously set by the SSY opcode
-                ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
+                const Tegra::Shader::ControlCode cc = instr.flow_control_code;
+                if (cc != Tegra::Shader::ControlCode::T) {
+                    LOG_CRITICAL(HW_GPU, "SYNC Control Code used: {}", static_cast<u32>(cc));
+                    UNREACHABLE();
+                }
                 EmitPopFromFlowStack();
                 break;
             }
             case OpCode::Id::BRK: {
                 // The BRK opcode jumps to the address previously set by the PBK opcode
-                ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
+                const Tegra::Shader::ControlCode cc = instr.flow_control_code;
+                if (cc != Tegra::Shader::ControlCode::T) {
+                    LOG_CRITICAL(HW_GPU, "BRK Control Code used: {}", static_cast<u32>(cc));
+                    UNREACHABLE();
+                }
                 EmitPopFromFlowStack();
                 break;
             }