summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/shader_bytecode.h5
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp27
2 files changed, 26 insertions, 6 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 7eb1bf8d9..8ea26c9c1 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -193,6 +193,11 @@ union Instruction {
BitField<50, 1, u64> abs_d;
BitField<56, 1, u64> negate_imm;
+ union {
+ BitField<39, 3, u64> pred;
+ BitField<42, 1, u64> negate_pred;
+ } fmnmx;
+
float GetImm20_19() const {
float result{};
u32 imm{static_cast<u32>(imm20_19)};
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index abbf0893d..1aa24da46 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -580,14 +580,17 @@ private:
* @param instr Instruction to generate the if condition for.
* @returns string containing the predicate condition.
*/
- std::string GetPredicateCondition(Instruction instr) const {
+ std::string GetPredicateCondition(u64 index, bool negate) const {
using Tegra::Shader::Pred;
- ASSERT(instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex));
+ std::string variable;
- std::string variable =
- 'p' + std::to_string(static_cast<u64>(instr.pred.pred_index.Value()));
+ // Index 7 is used as an 'Always True' condition.
+ if (index == static_cast<u64>(Pred::UnusedIndex))
+ variable = "true";
+ else
+ variable = 'p' + std::to_string(index);
- if (instr.negate_pred) {
+ if (negate) {
return "!(" + variable + ')';
}
@@ -634,7 +637,9 @@ private:
"NeverExecute predicate not implemented");
if (instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) {
- shader.AddLine("if (" + GetPredicateCondition(instr) + ')');
+ shader.AddLine("if (" +
+ GetPredicateCondition(instr.pred.pred_index, instr.negate_pred != 0) +
+ ')');
shader.AddLine('{');
++shader.scope;
}
@@ -730,6 +735,16 @@ private:
}
break;
}
+ case OpCode::Id::FMNMX: {
+ std::string condition =
+ GetPredicateCondition(instr.alu.fmnmx.pred, instr.alu.fmnmx.negate_pred != 0);
+ std::string parameters = op_a + ',' + op_b;
+ regs.SetRegisterToFloat(instr.gpr0, 0,
+ '(' + condition + ") ? min(" + parameters + ") : max(" +
+ parameters + ')',
+ 1, 1);
+ break;
+ }
case OpCode::Id::RRO: {
NGLOG_DEBUG(HW_GPU, "Skipping RRO instruction");
break;