summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/shader_bytecode.h9
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp33
2 files changed, 34 insertions, 8 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index ab978c2e2..2ec1de285 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/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;
@@ -316,6 +321,10 @@ union Instruction {
} bfe;
union {
+ BitField<0, 5, FlowCondition> cond;
+ } flow;
+
+ union {
BitField<48, 1, u64> negate_b;
BitField<49, 1, u64> negate_c;
} ffma;
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index c29cabb84..36a6f1cc5 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/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");