summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/shader_bytecode.h24
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp47
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
176enum class FloatRoundingOp : u64 {
177 None = 0,
178 Floor = 1,
179 Ceil = 2,
180 Trunc = 3,
181};
182
176union Instruction { 183union 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();