Răsfoiți Sursa

Merge pull request #654 from bunnei/cond-exit

gl_shader_decompiler: Use FlowCondition field in EXIT instruction.
bunnei 8 ani în urmă
părinte
comite
52636f67cc

+ 9 - 0
src/video_core/engines/shader_bytecode.h

@@ -201,6 +201,11 @@ enum class IMinMaxExchange : u64 {
     XHi = 3,
 };
 
+enum class FlowCondition : u64 {
+    Always = 0xF,
+    Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for?
+};
+
 union Instruction {
     Instruction& operator=(const Instruction& instr) {
         value = instr.value;
@@ -315,6 +320,10 @@ union Instruction {
         }
     } bfe;
 
+    union {
+        BitField<0, 5, FlowCondition> cond;
+    } flow;
+
     union {
         BitField<48, 1, u64> negate_b;
         BitField<49, 1, u64> negate_c;

+ 25 - 8
src/video_core/renderer_opengl/gl_shader_decompiler.cpp

@@ -1639,16 +1639,32 @@ private:
                     shader.AddLine("color.a = " + regs.GetRegisterAsFloat(3) + ';');
                 }
 
-                shader.AddLine("return true;");
-                if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) {
-                    // If this is an unconditional exit then just end processing here, otherwise
-                    // we have to account for the possibility of the condition not being met, so
-                    // continue processing the next instruction.
-                    offset = PROGRAM_END - 1;
+                switch (instr.flow.cond) {
+                case Tegra::Shader::FlowCondition::Always:
+                    shader.AddLine("return true;");
+                    if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) {
+                        // If this is an unconditional exit then just end processing here,
+                        // otherwise we have to account for the possibility of the condition
+                        // not being met, so continue processing the next instruction.
+                        offset = PROGRAM_END - 1;
+                    }
+                    break;
+
+                case Tegra::Shader::FlowCondition::Fcsm_Tr:
+                    // TODO(bunnei): What is this used for? If we assume this conditon is not
+                    // satisifed, dual vertex shaders in Farming Simulator make more sense
+                    LOG_CRITICAL(HW_GPU, "Skipping unknown FlowCondition::Fcsm_Tr");
+                    break;
+
+                default:
+                    LOG_CRITICAL(HW_GPU, "Unhandled flow condition: {}",
+                                 static_cast<u32>(instr.flow.cond.Value()));
+                    UNREACHABLE();
                 }
                 break;
             }
             case OpCode::Id::KIL: {
+                ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
                 shader.AddLine("discard;");
                 break;
             }
@@ -1669,8 +1685,9 @@ private:
                 // can ignore this when generating GLSL code.
                 break;
             }
-            case OpCode::Id::DEPBAR:
-            case OpCode::Id::SYNC: {
+            case OpCode::Id::SYNC:
+                ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
+            case OpCode::Id::DEPBAR: {
                 // TODO(Subv): Find out if we actually have to care about these instructions or if
                 // the GLSL compiler takes care of that for us.
                 LOG_WARNING(HW_GPU, "DEPBAR/SYNC instruction is stubbed");