diff options
| author | 2018-08-19 13:19:16 -0400 | |
|---|---|---|
| committer | 2018-08-19 13:19:16 -0400 | |
| commit | d6cb22b0df4e2b785827830e7af605477acbc9b4 (patch) | |
| tree | 8b86c1cf73dbfb0d05013886f3e99b61cdb2ec67 /src | |
| parent | Merge pull request #838 from FearlessTobi/port-3616 (diff) | |
| parent | Shader: Implemented the predicate and mode arguments of LOP. (diff) | |
| download | yuzu-d6cb22b0df4e2b785827830e7af605477acbc9b4.tar.gz yuzu-d6cb22b0df4e2b785827830e7af605477acbc9b4.tar.xz yuzu-d6cb22b0df4e2b785827830e7af605477acbc9b4.zip | |
Merge pull request #1103 from Subv/lop_pred
Shader: Implemented the predicate and mode arguments of LOP.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 43 |
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 | ||
| 217 | enum class PredicateResultMode : u64 { | ||
| 218 | None = 0x0, | ||
| 219 | NotZero = 0x3, | ||
| 220 | }; | ||
| 221 | |||
| 217 | union Instruction { | 222 | union 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: |