diff options
| author | 2018-06-17 12:49:34 -0400 | |
|---|---|---|
| committer | 2018-06-17 13:31:39 -0400 | |
| commit | 5673ce39c71ead786e207fd70abd8f83d51024e0 (patch) | |
| tree | c25ee5e19263821ebb0a850a99af99b2d6ccf0cc /src | |
| parent | Merge pull request #565 from bunnei/shader_conversions (diff) | |
| download | yuzu-5673ce39c71ead786e207fd70abd8f83d51024e0.tar.gz yuzu-5673ce39c71ead786e207fd70abd8f83d51024e0.tar.xz yuzu-5673ce39c71ead786e207fd70abd8f83d51024e0.zip | |
gl_shader_decompiler: Refactor LOP32I instruction a bit in support of LOP.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 5 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 94 |
2 files changed, 42 insertions, 57 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index ceef8087c..800b70dbf 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -233,7 +233,7 @@ union Instruction { | |||
| 233 | BitField<53, 2, LogicOperation> operation; | 233 | BitField<53, 2, LogicOperation> operation; |
| 234 | BitField<55, 1, u64> invert_a; | 234 | BitField<55, 1, u64> invert_a; |
| 235 | BitField<56, 1, u64> invert_b; | 235 | BitField<56, 1, u64> invert_b; |
| 236 | } lop; | 236 | } lop32i; |
| 237 | 237 | ||
| 238 | float GetImm20_19() const { | 238 | float GetImm20_19() const { |
| 239 | float result{}; | 239 | float result{}; |
| @@ -518,7 +518,6 @@ public: | |||
| 518 | ArithmeticInteger, | 518 | ArithmeticInteger, |
| 519 | ArithmeticIntegerImmediate, | 519 | ArithmeticIntegerImmediate, |
| 520 | Bfe, | 520 | Bfe, |
| 521 | Logic, | ||
| 522 | Shift, | 521 | Shift, |
| 523 | Ffma, | 522 | Ffma, |
| 524 | Flow, | 523 | Flow, |
| @@ -676,7 +675,7 @@ private: | |||
| 676 | INST("0100110000000---", Id::BFE_C, Type::Bfe, "BFE_C"), | 675 | INST("0100110000000---", Id::BFE_C, Type::Bfe, "BFE_C"), |
| 677 | INST("0101110000000---", Id::BFE_R, Type::Bfe, "BFE_R"), | 676 | INST("0101110000000---", Id::BFE_R, Type::Bfe, "BFE_R"), |
| 678 | INST("0011100-00000---", Id::BFE_IMM, Type::Bfe, "BFE_IMM"), | 677 | INST("0011100-00000---", Id::BFE_IMM, Type::Bfe, "BFE_IMM"), |
| 679 | INST("000001----------", Id::LOP32I, Type::Logic, "LOP32I"), | 678 | INST("000001----------", Id::LOP32I, Type::ArithmeticIntegerImmediate, "LOP32I"), |
| 680 | INST("0100110001001---", Id::SHL_C, Type::Shift, "SHL_C"), | 679 | INST("0100110001001---", Id::SHL_C, Type::Shift, "SHL_C"), |
| 681 | INST("0101110001001---", Id::SHL_R, Type::Shift, "SHL_R"), | 680 | INST("0101110001001---", Id::SHL_R, Type::Shift, "SHL_R"), |
| 682 | INST("0011100-01001---", Id::SHL_IMM, Type::Shift, "SHL_IMM"), | 681 | INST("0011100-01001---", Id::SHL_IMM, Type::Shift, "SHL_IMM"), |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index af68c3bda..b7b49cf72 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -16,6 +16,7 @@ namespace Decompiler { | |||
| 16 | 16 | ||
| 17 | using Tegra::Shader::Attribute; | 17 | using Tegra::Shader::Attribute; |
| 18 | using Tegra::Shader::Instruction; | 18 | using Tegra::Shader::Instruction; |
| 19 | using Tegra::Shader::LogicOperation; | ||
| 19 | using Tegra::Shader::OpCode; | 20 | using Tegra::Shader::OpCode; |
| 20 | using Tegra::Shader::Register; | 21 | using Tegra::Shader::Register; |
| 21 | using Tegra::Shader::Sampler; | 22 | using Tegra::Shader::Sampler; |
| @@ -759,6 +760,31 @@ private: | |||
| 759 | return (absolute_offset % SchedPeriod) == 0; | 760 | return (absolute_offset % SchedPeriod) == 0; |
| 760 | } | 761 | } |
| 761 | 762 | ||
| 763 | void WriteLogicOperation(Register dest, LogicOperation logic_op, const std::string& op_a, | ||
| 764 | const std::string& op_b) { | ||
| 765 | switch (logic_op) { | ||
| 766 | case LogicOperation::And: { | ||
| 767 | regs.SetRegisterToInteger(dest, true, 0, '(' + op_a + " & " + op_b + ')', 1, 1); | ||
| 768 | break; | ||
| 769 | } | ||
| 770 | case LogicOperation::Or: { | ||
| 771 | regs.SetRegisterToInteger(dest, true, 0, '(' + op_a + " | " + op_b + ')', 1, 1); | ||
| 772 | break; | ||
| 773 | } | ||
| 774 | case LogicOperation::Xor: { | ||
| 775 | regs.SetRegisterToInteger(dest, true, 0, '(' + op_a + " ^ " + op_b + ')', 1, 1); | ||
| 776 | break; | ||
| 777 | } | ||
| 778 | case LogicOperation::PassB: { | ||
| 779 | regs.SetRegisterToInteger(dest, true, 0, op_b, 1, 1); | ||
| 780 | break; | ||
| 781 | } | ||
| 782 | default: | ||
| 783 | NGLOG_CRITICAL(HW_GPU, "Unimplemented logic operation: {}", static_cast<u32>(logic_op)); | ||
| 784 | UNREACHABLE(); | ||
| 785 | } | ||
| 786 | } | ||
| 787 | |||
| 762 | /** | 788 | /** |
| 763 | * Compiles a single instruction from Tegra to GLSL. | 789 | * Compiles a single instruction from Tegra to GLSL. |
| 764 | * @param offset the offset of the Tegra shader instruction. | 790 | * @param offset the offset of the Tegra shader instruction. |
| @@ -942,55 +968,6 @@ private: | |||
| 942 | 968 | ||
| 943 | break; | 969 | break; |
| 944 | } | 970 | } |
| 945 | case OpCode::Type::Logic: { | ||
| 946 | std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, true); | ||
| 947 | |||
| 948 | if (instr.alu.lop.invert_a) | ||
| 949 | op_a = "~(" + op_a + ')'; | ||
| 950 | |||
| 951 | switch (opcode->GetId()) { | ||
| 952 | case OpCode::Id::LOP32I: { | ||
| 953 | u32 imm = static_cast<u32>(instr.alu.imm20_32.Value()); | ||
| 954 | |||
| 955 | if (instr.alu.lop.invert_b) | ||
| 956 | imm = ~imm; | ||
| 957 | |||
| 958 | std::string op_b = std::to_string(imm); | ||
| 959 | |||
| 960 | switch (instr.alu.lop.operation) { | ||
| 961 | case Tegra::Shader::LogicOperation::And: { | ||
| 962 | regs.SetRegisterToInteger(instr.gpr0, true, 0, '(' + op_a + " & " + op_b + ')', | ||
| 963 | 1, 1); | ||
| 964 | break; | ||
| 965 | } | ||
| 966 | case Tegra::Shader::LogicOperation::Or: { | ||
| 967 | regs.SetRegisterToInteger(instr.gpr0, true, 0, '(' + op_a + " | " + op_b + ')', | ||
| 968 | 1, 1); | ||
| 969 | break; | ||
| 970 | } | ||
| 971 | case Tegra::Shader::LogicOperation::Xor: { | ||
| 972 | regs.SetRegisterToInteger(instr.gpr0, true, 0, '(' + op_a + " ^ " + op_b + ')', | ||
| 973 | 1, 1); | ||
| 974 | break; | ||
| 975 | } | ||
| 976 | case Tegra::Shader::LogicOperation::PassB: { | ||
| 977 | regs.SetRegisterToInteger(instr.gpr0, true, 0, op_b, 1, 1); | ||
| 978 | break; | ||
| 979 | } | ||
| 980 | default: | ||
| 981 | NGLOG_CRITICAL(HW_GPU, "Unimplemented lop32i operation: {}", | ||
| 982 | static_cast<u32>(instr.alu.lop.operation.Value())); | ||
| 983 | UNREACHABLE(); | ||
| 984 | } | ||
| 985 | break; | ||
| 986 | } | ||
| 987 | default: { | ||
| 988 | NGLOG_CRITICAL(HW_GPU, "Unhandled logic instruction: {}", opcode->GetName()); | ||
| 989 | UNREACHABLE(); | ||
| 990 | } | ||
| 991 | } | ||
| 992 | break; | ||
| 993 | } | ||
| 994 | 971 | ||
| 995 | case OpCode::Type::Shift: { | 972 | case OpCode::Type::Shift: { |
| 996 | std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, true); | 973 | std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, true); |
| @@ -1036,17 +1013,26 @@ private: | |||
| 1036 | 1013 | ||
| 1037 | case OpCode::Type::ArithmeticIntegerImmediate: { | 1014 | case OpCode::Type::ArithmeticIntegerImmediate: { |
| 1038 | std::string op_a = regs.GetRegisterAsInteger(instr.gpr8); | 1015 | std::string op_a = regs.GetRegisterAsInteger(instr.gpr8); |
| 1039 | 1016 | std::string op_b = std::to_string(instr.alu.imm20_32.Value()); | |
| 1040 | if (instr.iadd32i.negate_a) | ||
| 1041 | op_a = '-' + op_a; | ||
| 1042 | |||
| 1043 | std::string op_b = '(' + std::to_string(instr.alu.imm20_32.Value()) + ')'; | ||
| 1044 | 1017 | ||
| 1045 | switch (opcode->GetId()) { | 1018 | switch (opcode->GetId()) { |
| 1046 | case OpCode::Id::IADD32I: | 1019 | case OpCode::Id::IADD32I: |
| 1020 | if (instr.iadd32i.negate_a) | ||
| 1021 | op_a = "-(" + op_a + ')'; | ||
| 1022 | |||
| 1047 | regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " + " + op_b, 1, 1, | 1023 | regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " + " + op_b, 1, 1, |
| 1048 | instr.iadd32i.saturate != 0); | 1024 | instr.iadd32i.saturate != 0); |
| 1049 | break; | 1025 | break; |
| 1026 | case OpCode::Id::LOP32I: { | ||
| 1027 | if (instr.alu.lop32i.invert_a) | ||
| 1028 | op_a = "~(" + op_a + ')'; | ||
| 1029 | |||
| 1030 | if (instr.alu.lop32i.invert_b) | ||
| 1031 | op_b = "~(" + op_b + ')'; | ||
| 1032 | |||
| 1033 | WriteLogicOperation(instr.gpr0, instr.alu.lop32i.operation, op_a, op_b); | ||
| 1034 | break; | ||
| 1035 | } | ||
| 1050 | default: { | 1036 | default: { |
| 1051 | NGLOG_CRITICAL(HW_GPU, "Unhandled ArithmeticIntegerImmediate instruction: {}", | 1037 | NGLOG_CRITICAL(HW_GPU, "Unhandled ArithmeticIntegerImmediate instruction: {}", |
| 1052 | opcode->GetName()); | 1038 | opcode->GetName()); |