summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Subv2018-08-18 14:36:37 -0500
committerGravatar Subv2018-08-18 14:36:37 -0500
commit8335b2f115d8c2e082f1b085eedb54d334489f6d (patch)
tree108bfacaaa4d40d36a0e0aa41701d7330ded4ee6 /src
parentMerge pull request #1100 from ogniK5377/missing-pred (diff)
downloadyuzu-8335b2f115d8c2e082f1b085eedb54d334489f6d.tar.gz
yuzu-8335b2f115d8c2e082f1b085eedb54d334489f6d.tar.xz
yuzu-8335b2f115d8c2e082f1b085eedb54d334489f6d.zip
Shader: Implemented the predicate and mode arguments of LOP.
The mode can be used to set the predicate to true depending on the result of the logic operation. In some cases, this means discarding the result (writing it to register 0xFF (Zero)). This is used by Super Mario Odyssey.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/shader_bytecode.h7
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp43
2 files changed, 39 insertions, 11 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index b038a9d92..6cfb9c5f8 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -214,6 +214,11 @@ enum class FlowCondition : u64 {
214 Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for? 214 Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for?
215}; 215};
216 216
217enum class PredicateResultMode : u64 {
218 None = 0x0,
219 NotZero = 0x3,
220};
221
217union Instruction { 222union Instruction {
218 Instruction& operator=(const Instruction& instr) { 223 Instruction& operator=(const Instruction& instr) {
219 value = instr.value; 224 value = instr.value;
@@ -254,7 +259,7 @@ union Instruction {
254 BitField<39, 1, u64> invert_a; 259 BitField<39, 1, u64> invert_a;
255 BitField<40, 1, u64> invert_b; 260 BitField<40, 1, u64> invert_b;
256 BitField<41, 2, LogicOperation> operation; 261 BitField<41, 2, LogicOperation> operation;
257 BitField<44, 2, u64> unk44; 262 BitField<44, 2, PredicateResultMode> pred_result_mode;
258 BitField<48, 3, Pred> pred48; 263 BitField<48, 3, Pred> pred48;
259 } lop; 264 } lop;
260 265
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index bb01b3c27..77974b9d2 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -756,28 +756,51 @@ private:
756 } 756 }
757 757
758 void WriteLogicOperation(Register dest, LogicOperation logic_op, const std::string& op_a, 758 void WriteLogicOperation(Register dest, LogicOperation logic_op, const std::string& op_a,
759 const std::string& op_b) { 759 const std::string& op_b,
760 Tegra::Shader::PredicateResultMode predicate_mode,
761 Tegra::Shader::Pred predicate) {
762 std::string result{};
760 switch (logic_op) { 763 switch (logic_op) {
761 case LogicOperation::And: { 764 case LogicOperation::And: {
762 regs.SetRegisterToInteger(dest, true, 0, '(' + op_a + " & " + op_b + ')', 1, 1); 765 result = '(' + op_a + " & " + op_b + ')';
763 break; 766 break;
764 } 767 }
765 case LogicOperation::Or: { 768 case LogicOperation::Or: {
766 regs.SetRegisterToInteger(dest, true, 0, '(' + op_a + " | " + op_b + ')', 1, 1); 769 result = '(' + op_a + " | " + op_b + ')';
767 break; 770 break;
768 } 771 }
769 case LogicOperation::Xor: { 772 case LogicOperation::Xor: {
770 regs.SetRegisterToInteger(dest, true, 0, '(' + op_a + " ^ " + op_b + ')', 1, 1); 773 result = '(' + op_a + " ^ " + op_b + ')';
771 break; 774 break;
772 } 775 }
773 case LogicOperation::PassB: { 776 case LogicOperation::PassB: {
774 regs.SetRegisterToInteger(dest, true, 0, op_b, 1, 1); 777 result = op_b;
775 break; 778 break;
776 } 779 }
777 default: 780 default:
778 LOG_CRITICAL(HW_GPU, "Unimplemented logic operation: {}", static_cast<u32>(logic_op)); 781 LOG_CRITICAL(HW_GPU, "Unimplemented logic operation: {}", static_cast<u32>(logic_op));
779 UNREACHABLE(); 782 UNREACHABLE();
780 } 783 }
784
785 if (dest != Tegra::Shader::Register::ZeroIndex) {
786 regs.SetRegisterToInteger(dest, true, 0, result, 1, 1);
787 }
788
789 using Tegra::Shader::PredicateResultMode;
790 // Write the predicate value depending on the predicate mode.
791 switch (predicate_mode) {
792 case PredicateResultMode::None:
793 // Do nothing.
794 return;
795 case PredicateResultMode::NotZero:
796 // Set the predicate to true if the result is not zero.
797 SetPredicate(static_cast<u64>(predicate), '(' + result + ") != 0");
798 break;
799 default:
800 LOG_CRITICAL(HW_GPU, "Unimplemented predicate result mode: {}",
801 static_cast<u32>(predicate_mode));
802 UNREACHABLE();
803 }
781 } 804 }
782 805
783 void WriteTexsInstruction(const Instruction& instr, const std::string& coord, 806 void WriteTexsInstruction(const Instruction& instr, const std::string& coord,
@@ -1099,7 +1122,9 @@ private:
1099 if (instr.alu.lop32i.invert_b) 1122 if (instr.alu.lop32i.invert_b)
1100 op_b = "~(" + op_b + ')'; 1123 op_b = "~(" + op_b + ')';
1101 1124
1102 WriteLogicOperation(instr.gpr0, instr.alu.lop32i.operation, op_a, op_b); 1125 WriteLogicOperation(instr.gpr0, instr.alu.lop32i.operation, op_a, op_b,
1126 Tegra::Shader::PredicateResultMode::None,
1127 Tegra::Shader::Pred::UnusedIndex);
1103 break; 1128 break;
1104 } 1129 }
1105 default: { 1130 default: {
@@ -1165,16 +1190,14 @@ private:
1165 case OpCode::Id::LOP_C: 1190 case OpCode::Id::LOP_C:
1166 case OpCode::Id::LOP_R: 1191 case OpCode::Id::LOP_R:
1167 case OpCode::Id::LOP_IMM: { 1192 case OpCode::Id::LOP_IMM: {
1168 ASSERT_MSG(!instr.alu.lop.unk44, "Unimplemented");
1169 ASSERT_MSG(instr.alu.lop.pred48 == Pred::UnusedIndex, "Unimplemented");
1170
1171 if (instr.alu.lop.invert_a) 1193 if (instr.alu.lop.invert_a)
1172 op_a = "~(" + op_a + ')'; 1194 op_a = "~(" + op_a + ')';
1173 1195
1174 if (instr.alu.lop.invert_b) 1196 if (instr.alu.lop.invert_b)
1175 op_b = "~(" + op_b + ')'; 1197 op_b = "~(" + op_b + ')';
1176 1198
1177 WriteLogicOperation(instr.gpr0, instr.alu.lop.operation, op_a, op_b); 1199 WriteLogicOperation(instr.gpr0, instr.alu.lop.operation, op_a, op_b,
1200 instr.alu.lop.pred_result_mode, instr.alu.lop.pred48);
1178 break; 1201 break;
1179 } 1202 }
1180 case OpCode::Id::IMNMX_C: 1203 case OpCode::Id::IMNMX_C: