diff options
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 24 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 47 |
2 files changed, 64 insertions, 7 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 22c122fcc..93654eb66 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -173,6 +173,13 @@ enum class SubOp : u64 { | |||
| 173 | Min = 0x8, | 173 | Min = 0x8, |
| 174 | }; | 174 | }; |
| 175 | 175 | ||
| 176 | enum class FloatRoundingOp : u64 { | ||
| 177 | None = 0, | ||
| 178 | Floor = 1, | ||
| 179 | Ceil = 2, | ||
| 180 | Trunc = 3, | ||
| 181 | }; | ||
| 182 | |||
| 176 | union Instruction { | 183 | union Instruction { |
| 177 | Instruction& operator=(const Instruction& instr) { | 184 | Instruction& operator=(const Instruction& instr) { |
| 178 | value = instr.value; | 185 | value = instr.value; |
| @@ -277,11 +284,20 @@ union Instruction { | |||
| 277 | 284 | ||
| 278 | union { | 285 | union { |
| 279 | BitField<10, 2, Register::Size> size; | 286 | BitField<10, 2, Register::Size> size; |
| 280 | BitField<13, 1, u64> is_signed; | 287 | BitField<12, 1, u64> is_output_signed; |
| 288 | BitField<13, 1, u64> is_input_signed; | ||
| 281 | BitField<41, 2, u64> selector; | 289 | BitField<41, 2, u64> selector; |
| 282 | BitField<45, 1, u64> negate_a; | 290 | BitField<45, 1, u64> negate_a; |
| 283 | BitField<49, 1, u64> abs_a; | 291 | BitField<49, 1, u64> abs_a; |
| 284 | BitField<50, 1, u64> saturate_a; | 292 | BitField<50, 1, u64> saturate_a; |
| 293 | |||
| 294 | union { | ||
| 295 | BitField<39, 2, FloatRoundingOp> rounding; | ||
| 296 | } f2i; | ||
| 297 | |||
| 298 | union { | ||
| 299 | BitField<39, 4, u64> rounding; | ||
| 300 | } f2f; | ||
| 285 | } conversion; | 301 | } conversion; |
| 286 | 302 | ||
| 287 | union { | 303 | union { |
| @@ -535,9 +551,9 @@ private: | |||
| 535 | INST("0100110010101---", Id::F2F_C, Type::Conversion, "F2F_C"), | 551 | INST("0100110010101---", Id::F2F_C, Type::Conversion, "F2F_C"), |
| 536 | INST("0101110010101---", Id::F2F_R, Type::Conversion, "F2F_R"), | 552 | INST("0101110010101---", Id::F2F_R, Type::Conversion, "F2F_R"), |
| 537 | INST("0011100-10101---", Id::F2F_IMM, Type::Conversion, "F2F_IMM"), | 553 | INST("0011100-10101---", Id::F2F_IMM, Type::Conversion, "F2F_IMM"), |
| 538 | INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"), | 554 | INST("0100110010110---", Id::F2I_C, Type::Conversion, "F2I_C"), |
| 539 | INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"), | 555 | INST("0101110010110---", Id::F2I_R, Type::Conversion, "F2I_R"), |
| 540 | INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"), | 556 | INST("0011100-10110---", Id::F2I_IMM, Type::Conversion, "F2I_IMM"), |
| 541 | INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"), | 557 | INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"), |
| 542 | INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"), | 558 | INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"), |
| 543 | INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"), | 559 | INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"), |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 9943394c6..4b14bb47e 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -929,18 +929,20 @@ private: | |||
| 929 | ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); | 929 | ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); |
| 930 | 930 | ||
| 931 | std::string op_a = | 931 | std::string op_a = |
| 932 | regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_signed); | 932 | regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_input_signed); |
| 933 | 933 | ||
| 934 | if (instr.conversion.abs_a) { | 934 | if (instr.conversion.abs_a) { |
| 935 | op_a = "abs(" + op_a + ')'; | 935 | op_a = "abs(" + op_a + ')'; |
| 936 | } | 936 | } |
| 937 | 937 | ||
| 938 | regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_signed, 0, op_a, 1, 1); | 938 | regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, |
| 939 | 1); | ||
| 939 | break; | 940 | break; |
| 940 | } | 941 | } |
| 941 | case OpCode::Id::I2F_R: { | 942 | case OpCode::Id::I2F_R: { |
| 943 | ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); | ||
| 942 | std::string op_a = | 944 | std::string op_a = |
| 943 | regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_signed); | 945 | regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_input_signed); |
| 944 | 946 | ||
| 945 | if (instr.conversion.abs_a) { | 947 | if (instr.conversion.abs_a) { |
| 946 | op_a = "abs(" + op_a + ')'; | 948 | op_a = "abs(" + op_a + ')'; |
| @@ -950,6 +952,8 @@ private: | |||
| 950 | break; | 952 | break; |
| 951 | } | 953 | } |
| 952 | case OpCode::Id::F2F_R: { | 954 | case OpCode::Id::F2F_R: { |
| 955 | // TODO(Subv): Implement rounding operations. | ||
| 956 | ASSERT_MSG(instr.conversion.f2f.rounding == 0, "Unimplemented rounding operation"); | ||
| 953 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); | 957 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); |
| 954 | 958 | ||
| 955 | if (instr.conversion.abs_a) { | 959 | if (instr.conversion.abs_a) { |
| @@ -959,6 +963,43 @@ private: | |||
| 959 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); | 963 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); |
| 960 | break; | 964 | break; |
| 961 | } | 965 | } |
| 966 | case OpCode::Id::F2I_R: { | ||
| 967 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 968 | |||
| 969 | if (instr.conversion.abs_a) { | ||
| 970 | op_a = "abs(" + op_a + ')'; | ||
| 971 | } | ||
| 972 | |||
| 973 | using Tegra::Shader::FloatRoundingOp; | ||
| 974 | switch (instr.conversion.f2i.rounding) { | ||
| 975 | case FloatRoundingOp::None: | ||
| 976 | break; | ||
| 977 | case FloatRoundingOp::Floor: | ||
| 978 | op_a = "floor(" + op_a + ')'; | ||
| 979 | break; | ||
| 980 | case FloatRoundingOp::Ceil: | ||
| 981 | op_a = "ceil(" + op_a + ')'; | ||
| 982 | break; | ||
| 983 | case FloatRoundingOp::Trunc: | ||
| 984 | op_a = "trunc(" + op_a + ')'; | ||
| 985 | break; | ||
| 986 | default: | ||
| 987 | NGLOG_CRITICAL(HW_GPU, "Unimplemented f2i rounding mode {}", | ||
| 988 | static_cast<u32>(instr.conversion.f2i.rounding.Value())); | ||
| 989 | UNREACHABLE(); | ||
| 990 | break; | ||
| 991 | } | ||
| 992 | |||
| 993 | if (instr.conversion.is_output_signed) { | ||
| 994 | op_a = "int(" + op_a + ')'; | ||
| 995 | } else { | ||
| 996 | op_a = "uint(" + op_a + ')'; | ||
| 997 | } | ||
| 998 | |||
| 999 | regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, | ||
| 1000 | 1); | ||
| 1001 | break; | ||
| 1002 | } | ||
| 962 | default: { | 1003 | default: { |
| 963 | NGLOG_CRITICAL(HW_GPU, "Unhandled conversion instruction: {}", opcode->GetName()); | 1004 | NGLOG_CRITICAL(HW_GPU, "Unhandled conversion instruction: {}", opcode->GetName()); |
| 964 | UNREACHABLE(); | 1005 | UNREACHABLE(); |