summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/shader_bytecode.h14
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp28
2 files changed, 42 insertions, 0 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 83a6fd875..5b84bcb24 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -365,6 +365,11 @@ enum class HalfPrecision : u64 {
FMZ = 2,
};
+enum class R2pMode : u64 {
+ Pr = 0,
+ Cc = 1,
+};
+
enum class IpaInterpMode : u64 {
Linear = 0,
Perspective = 1,
@@ -855,6 +860,12 @@ union Instruction {
} hsetp2;
union {
+ BitField<40, 1, R2pMode> mode;
+ BitField<41, 2, u64> byte;
+ BitField<20, 7, u64> immediate_mask;
+ } r2p;
+
+ union {
BitField<39, 3, u64> pred39;
BitField<42, 1, u64> neg_pred;
BitField<43, 1, u64> neg_a;
@@ -1381,6 +1392,7 @@ public:
PSETP,
PSET,
CSETP,
+ R2P_IMM,
XMAD_IMM,
XMAD_CR,
XMAD_RC,
@@ -1410,6 +1422,7 @@ public:
HalfSetPredicate,
PredicateSetPredicate,
PredicateSetRegister,
+ RegisterSetPredicate,
Conversion,
Xmad,
Unknown,
@@ -1647,6 +1660,7 @@ private:
INST("0101000010001---", Id::PSET, Type::PredicateSetRegister, "PSET"),
INST("0101000010010---", Id::PSETP, Type::PredicateSetPredicate, "PSETP"),
INST("010100001010----", Id::CSETP, Type::PredicateSetPredicate, "CSETP"),
+ INST("0011100-11110---", Id::R2P_IMM, Type::RegisterSetPredicate, "R2P_IMM"),
INST("0011011-00------", Id::XMAD_IMM, Type::Xmad, "XMAD_IMM"),
INST("0100111---------", Id::XMAD_CR, Type::Xmad, "XMAD_CR"),
INST("010100010-------", Id::XMAD_RC, Type::Xmad, "XMAD_RC"),
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 5fde22ad4..30050b585 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -3260,6 +3260,34 @@ private:
}
break;
}
+ case OpCode::Type::RegisterSetPredicate: {
+ UNIMPLEMENTED_IF(instr.r2p.mode != Tegra::Shader::R2pMode::Pr);
+
+ const std::string apply_mask = [&]() {
+ switch (opcode->get().GetId()) {
+ case OpCode::Id::R2P_IMM:
+ return std::to_string(instr.r2p.immediate_mask);
+ default:
+ UNREACHABLE();
+ }
+ }();
+ const std::string mask = '(' + regs.GetRegisterAsInteger(instr.gpr8, 0, false) +
+ " >> " + std::to_string(instr.r2p.byte) + ')';
+
+ constexpr u64 programmable_preds = 7;
+ for (u64 pred = 0; pred < programmable_preds; ++pred) {
+ const auto shift = std::to_string(1 << pred);
+
+ shader.AddLine("if ((" + apply_mask + " & " + shift + ") != 0) {");
+ ++shader.scope;
+
+ SetPredicate(pred, '(' + mask + " & " + shift + ") != 0");
+
+ --shader.scope;
+ shader.AddLine('}');
+ }
+ break;
+ }
case OpCode::Type::FloatSet: {
const std::string op_a = GetOperandAbsNeg(regs.GetRegisterAsFloat(instr.gpr8),
instr.fset.abs_a != 0, instr.fset.neg_a != 0);