diff options
Diffstat (limited to 'src')
| -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 38757c038..4eb507325 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; |
| @@ -290,11 +297,20 @@ union Instruction { | |||
| 290 | 297 | ||
| 291 | union { | 298 | union { |
| 292 | BitField<10, 2, Register::Size> size; | 299 | BitField<10, 2, Register::Size> size; |
| 293 | BitField<13, 1, u64> is_signed; | 300 | BitField<12, 1, u64> is_output_signed; |
| 301 | BitField<13, 1, u64> is_input_signed; | ||
| 294 | BitField<41, 2, u64> selector; | 302 | BitField<41, 2, u64> selector; |
| 295 | BitField<45, 1, u64> negate_a; | 303 | BitField<45, 1, u64> negate_a; |
| 296 | BitField<49, 1, u64> abs_a; | 304 | BitField<49, 1, u64> abs_a; |
| 297 | BitField<50, 1, u64> saturate_a; | 305 | BitField<50, 1, u64> saturate_a; |
| 306 | |||
| 307 | union { | ||
| 308 | BitField<39, 2, FloatRoundingOp> rounding; | ||
| 309 | } f2i; | ||
| 310 | |||
| 311 | union { | ||
| 312 | BitField<39, 4, u64> rounding; | ||
| 313 | } f2f; | ||
| 298 | } conversion; | 314 | } conversion; |
| 299 | 315 | ||
| 300 | union { | 316 | union { |
| @@ -560,9 +576,9 @@ private: | |||
| 560 | INST("0100110010101---", Id::F2F_C, Type::Conversion, "F2F_C"), | 576 | INST("0100110010101---", Id::F2F_C, Type::Conversion, "F2F_C"), |
| 561 | INST("0101110010101---", Id::F2F_R, Type::Conversion, "F2F_R"), | 577 | INST("0101110010101---", Id::F2F_R, Type::Conversion, "F2F_R"), |
| 562 | INST("0011100-10101---", Id::F2F_IMM, Type::Conversion, "F2F_IMM"), | 578 | INST("0011100-10101---", Id::F2F_IMM, Type::Conversion, "F2F_IMM"), |
| 563 | INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"), | 579 | INST("0100110010110---", Id::F2I_C, Type::Conversion, "F2I_C"), |
| 564 | INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"), | 580 | INST("0101110010110---", Id::F2I_R, Type::Conversion, "F2I_R"), |
| 565 | INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"), | 581 | INST("0011100-10110---", Id::F2I_IMM, Type::Conversion, "F2I_IMM"), |
| 566 | INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"), | 582 | INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"), |
| 567 | INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"), | 583 | INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"), |
| 568 | INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"), | 584 | 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 f886e49ca..4a41e7798 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -991,18 +991,20 @@ private: | |||
| 991 | ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); | 991 | ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); |
| 992 | 992 | ||
| 993 | std::string op_a = | 993 | std::string op_a = |
| 994 | regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_signed); | 994 | regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_input_signed); |
| 995 | 995 | ||
| 996 | if (instr.conversion.abs_a) { | 996 | if (instr.conversion.abs_a) { |
| 997 | op_a = "abs(" + op_a + ')'; | 997 | op_a = "abs(" + op_a + ')'; |
| 998 | } | 998 | } |
| 999 | 999 | ||
| 1000 | regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_signed, 0, op_a, 1, 1); | 1000 | regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, |
| 1001 | 1); | ||
| 1001 | break; | 1002 | break; |
| 1002 | } | 1003 | } |
| 1003 | case OpCode::Id::I2F_R: { | 1004 | case OpCode::Id::I2F_R: { |
| 1005 | ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); | ||
| 1004 | std::string op_a = | 1006 | std::string op_a = |
| 1005 | regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_signed); | 1007 | regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_input_signed); |
| 1006 | 1008 | ||
| 1007 | if (instr.conversion.abs_a) { | 1009 | if (instr.conversion.abs_a) { |
| 1008 | op_a = "abs(" + op_a + ')'; | 1010 | op_a = "abs(" + op_a + ')'; |
| @@ -1012,6 +1014,8 @@ private: | |||
| 1012 | break; | 1014 | break; |
| 1013 | } | 1015 | } |
| 1014 | case OpCode::Id::F2F_R: { | 1016 | case OpCode::Id::F2F_R: { |
| 1017 | // TODO(Subv): Implement rounding operations. | ||
| 1018 | ASSERT_MSG(instr.conversion.f2f.rounding == 0, "Unimplemented rounding operation"); | ||
| 1015 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); | 1019 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); |
| 1016 | 1020 | ||
| 1017 | if (instr.conversion.abs_a) { | 1021 | if (instr.conversion.abs_a) { |
| @@ -1021,6 +1025,43 @@ private: | |||
| 1021 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); | 1025 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); |
| 1022 | break; | 1026 | break; |
| 1023 | } | 1027 | } |
| 1028 | case OpCode::Id::F2I_R: { | ||
| 1029 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 1030 | |||
| 1031 | if (instr.conversion.abs_a) { | ||
| 1032 | op_a = "abs(" + op_a + ')'; | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | using Tegra::Shader::FloatRoundingOp; | ||
| 1036 | switch (instr.conversion.f2i.rounding) { | ||
| 1037 | case FloatRoundingOp::None: | ||
| 1038 | break; | ||
| 1039 | case FloatRoundingOp::Floor: | ||
| 1040 | op_a = "floor(" + op_a + ')'; | ||
| 1041 | break; | ||
| 1042 | case FloatRoundingOp::Ceil: | ||
| 1043 | op_a = "ceil(" + op_a + ')'; | ||
| 1044 | break; | ||
| 1045 | case FloatRoundingOp::Trunc: | ||
| 1046 | op_a = "trunc(" + op_a + ')'; | ||
| 1047 | break; | ||
| 1048 | default: | ||
| 1049 | NGLOG_CRITICAL(HW_GPU, "Unimplemented f2i rounding mode {}", | ||
| 1050 | static_cast<u32>(instr.conversion.f2i.rounding.Value())); | ||
| 1051 | UNREACHABLE(); | ||
| 1052 | break; | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | if (instr.conversion.is_output_signed) { | ||
| 1056 | op_a = "int(" + op_a + ')'; | ||
| 1057 | } else { | ||
| 1058 | op_a = "uint(" + op_a + ')'; | ||
| 1059 | } | ||
| 1060 | |||
| 1061 | regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, | ||
| 1062 | 1); | ||
| 1063 | break; | ||
| 1064 | } | ||
| 1024 | default: { | 1065 | default: { |
| 1025 | NGLOG_CRITICAL(HW_GPU, "Unhandled conversion instruction: {}", opcode->GetName()); | 1066 | NGLOG_CRITICAL(HW_GPU, "Unhandled conversion instruction: {}", opcode->GetName()); |
| 1026 | UNREACHABLE(); | 1067 | UNREACHABLE(); |