summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/shader_bytecode.h18
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp56
2 files changed, 55 insertions, 19 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 32800392b..dc3dd8a80 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -213,6 +213,7 @@ union Instruction {
213 BitField<28, 8, Register> gpr28; 213 BitField<28, 8, Register> gpr28;
214 BitField<39, 8, Register> gpr39; 214 BitField<39, 8, Register> gpr39;
215 BitField<48, 16, u64> opcode; 215 BitField<48, 16, u64> opcode;
216 BitField<50, 1, u64> saturate_a;
216 217
217 union { 218 union {
218 BitField<20, 19, u64> imm20_19; 219 BitField<20, 19, u64> imm20_19;
@@ -263,7 +264,7 @@ union Instruction {
263 BitField<39, 5, u64> shift_amount; 264 BitField<39, 5, u64> shift_amount;
264 BitField<48, 1, u64> negate_b; 265 BitField<48, 1, u64> negate_b;
265 BitField<49, 1, u64> negate_a; 266 BitField<49, 1, u64> negate_a;
266 } iscadd; 267 } alu_integer;
267 268
268 union { 269 union {
269 BitField<20, 8, u64> shift_position; 270 BitField<20, 8, u64> shift_position;
@@ -331,7 +332,6 @@ union Instruction {
331 BitField<41, 2, u64> selector; 332 BitField<41, 2, u64> selector;
332 BitField<45, 1, u64> negate_a; 333 BitField<45, 1, u64> negate_a;
333 BitField<49, 1, u64> abs_a; 334 BitField<49, 1, u64> abs_a;
334 BitField<50, 1, u64> saturate_a;
335 335
336 union { 336 union {
337 BitField<39, 2, F2iRoundingOp> rounding; 337 BitField<39, 2, F2iRoundingOp> rounding;
@@ -434,6 +434,9 @@ public:
434 FMUL_R, 434 FMUL_R,
435 FMUL_IMM, 435 FMUL_IMM,
436 FMUL32_IMM, 436 FMUL32_IMM,
437 IADD_C,
438 IADD_R,
439 IADD_IMM,
437 ISCADD_C, // Scale and Add 440 ISCADD_C, // Scale and Add
438 ISCADD_R, 441 ISCADD_R,
439 ISCADD_IMM, 442 ISCADD_IMM,
@@ -489,10 +492,10 @@ public:
489 enum class Type { 492 enum class Type {
490 Trivial, 493 Trivial,
491 Arithmetic, 494 Arithmetic,
495 ArithmeticInteger,
492 Bfe, 496 Bfe,
493 Logic, 497 Logic,
494 Shift, 498 Shift,
495 ScaledAdd,
496 Ffma, 499 Ffma,
497 Flow, 500 Flow,
498 Memory, 501 Memory,
@@ -617,9 +620,12 @@ private:
617 INST("0101110001101---", Id::FMUL_R, Type::Arithmetic, "FMUL_R"), 620 INST("0101110001101---", Id::FMUL_R, Type::Arithmetic, "FMUL_R"),
618 INST("0011100-01101---", Id::FMUL_IMM, Type::Arithmetic, "FMUL_IMM"), 621 INST("0011100-01101---", Id::FMUL_IMM, Type::Arithmetic, "FMUL_IMM"),
619 INST("00011110--------", Id::FMUL32_IMM, Type::Arithmetic, "FMUL32_IMM"), 622 INST("00011110--------", Id::FMUL32_IMM, Type::Arithmetic, "FMUL32_IMM"),
620 INST("0100110000011---", Id::ISCADD_C, Type::ScaledAdd, "ISCADD_C"), 623 INST("0100110000010---", Id::IADD_C, Type::ArithmeticInteger, "IADD_C"),
621 INST("0101110000011---", Id::ISCADD_R, Type::ScaledAdd, "ISCADD_R"), 624 INST("0101110000010---", Id::IADD_R, Type::ArithmeticInteger, "IADD_R"),
622 INST("0011100-00011---", Id::ISCADD_IMM, Type::ScaledAdd, "ISCADD_IMM"), 625 INST("0011100-00010---", Id::IADD_IMM, Type::ArithmeticInteger, "IADD_IMM"),
626 INST("0100110000011---", Id::ISCADD_C, Type::ArithmeticInteger, "ISCADD_C"),
627 INST("0101110000011---", Id::ISCADD_R, Type::ArithmeticInteger, "ISCADD_R"),
628 INST("0011100-00011---", Id::ISCADD_IMM, Type::ArithmeticInteger, "ISCADD_IMM"),
623 INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), 629 INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"),
624 INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"), 630 INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"),
625 INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"), 631 INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"),
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 94c6bc4b2..4e248d328 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -808,6 +808,8 @@ private:
808 case OpCode::Id::FMUL_C: 808 case OpCode::Id::FMUL_C:
809 case OpCode::Id::FMUL_R: 809 case OpCode::Id::FMUL_R:
810 case OpCode::Id::FMUL_IMM: { 810 case OpCode::Id::FMUL_IMM: {
811 ASSERT_MSG(!instr.saturate_a, "Unimplemented");
812
811 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b, 1, 1, instr.alu.abs_d); 813 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b, 1, 1, instr.alu.abs_d);
812 break; 814 break;
813 } 815 }
@@ -821,10 +823,14 @@ private:
821 case OpCode::Id::FADD_C: 823 case OpCode::Id::FADD_C:
822 case OpCode::Id::FADD_R: 824 case OpCode::Id::FADD_R:
823 case OpCode::Id::FADD_IMM: { 825 case OpCode::Id::FADD_IMM: {
826 ASSERT_MSG(!instr.saturate_a, "Unimplemented");
827
824 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, instr.alu.abs_d); 828 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, instr.alu.abs_d);
825 break; 829 break;
826 } 830 }
827 case OpCode::Id::MUFU: { 831 case OpCode::Id::MUFU: {
832 ASSERT_MSG(!instr.saturate_a, "Unimplemented");
833
828 switch (instr.sub_op) { 834 switch (instr.sub_op) {
829 case SubOp::Cos: 835 case SubOp::Cos:
830 regs.SetRegisterToFloat(instr.gpr0, 0, "cos(" + op_a + ')', 1, 1, 836 regs.SetRegisterToFloat(instr.gpr0, 0, "cos(" + op_a + ')', 1, 1,
@@ -986,13 +992,13 @@ private:
986 break; 992 break;
987 } 993 }
988 994
989 case OpCode::Type::ScaledAdd: { 995 case OpCode::Type::ArithmeticInteger: {
990 std::string op_a = regs.GetRegisterAsInteger(instr.gpr8); 996 std::string op_a = regs.GetRegisterAsInteger(instr.gpr8);
991 997
992 if (instr.iscadd.negate_a) 998 if (instr.alu_integer.negate_a)
993 op_a = '-' + op_a; 999 op_a = '-' + op_a;
994 1000
995 std::string op_b = instr.iscadd.negate_b ? "-" : ""; 1001 std::string op_b = instr.alu_integer.negate_b ? "-" : "";
996 1002
997 if (instr.is_b_imm) { 1003 if (instr.is_b_imm) {
998 op_b += '(' + std::to_string(instr.alu.GetSignedImm20_20()) + ')'; 1004 op_b += '(' + std::to_string(instr.alu.GetSignedImm20_20()) + ')';
@@ -1005,13 +1011,35 @@ private:
1005 } 1011 }
1006 } 1012 }
1007 1013
1008 std::string shift = std::to_string(instr.iscadd.shift_amount.Value()); 1014 switch (opcode->GetId()) {
1015 case OpCode::Id::IADD_C:
1016 case OpCode::Id::IADD_R:
1017 case OpCode::Id::IADD_IMM: {
1018 ASSERT_MSG(!instr.saturate_a, "Unimplemented");
1019 regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " + " + op_b, 1, 1);
1020 break;
1021 }
1022 case OpCode::Id::ISCADD_C:
1023 case OpCode::Id::ISCADD_R:
1024 case OpCode::Id::ISCADD_IMM: {
1025 std::string shift = std::to_string(instr.alu_integer.shift_amount.Value());
1026
1027 regs.SetRegisterToInteger(instr.gpr0, true, 0,
1028 "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1);
1029 break;
1030 }
1031 default: {
1032 NGLOG_CRITICAL(HW_GPU, "Unhandled ArithmeticInteger instruction: {}",
1033 opcode->GetName());
1034 UNREACHABLE();
1035 }
1036 }
1009 1037
1010 regs.SetRegisterToInteger(instr.gpr0, true, 0,
1011 "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1);
1012 break; 1038 break;
1013 } 1039 }
1014 case OpCode::Type::Ffma: { 1040 case OpCode::Type::Ffma: {
1041 ASSERT_MSG(!instr.saturate_a, "Unimplemented");
1042
1015 std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 1043 std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
1016 std::string op_b = instr.ffma.negate_b ? "-" : ""; 1044 std::string op_b = instr.ffma.negate_b ? "-" : "";
1017 std::string op_c = instr.ffma.negate_c ? "-" : ""; 1045 std::string op_c = instr.ffma.negate_c ? "-" : "";
@@ -1051,7 +1079,7 @@ private:
1051 case OpCode::Type::Conversion: { 1079 case OpCode::Type::Conversion: {
1052 ASSERT_MSG(instr.conversion.size == Register::Size::Word, "Unimplemented"); 1080 ASSERT_MSG(instr.conversion.size == Register::Size::Word, "Unimplemented");
1053 ASSERT_MSG(!instr.conversion.negate_a, "Unimplemented"); 1081 ASSERT_MSG(!instr.conversion.negate_a, "Unimplemented");
1054 ASSERT_MSG(!instr.conversion.saturate_a, "Unimplemented"); 1082 ASSERT_MSG(!instr.saturate_a, "Unimplemented");
1055 1083
1056 switch (opcode->GetId()) { 1084 switch (opcode->GetId()) {
1057 case OpCode::Id::I2I_R: { 1085 case OpCode::Id::I2I_R: {
@@ -1081,6 +1109,8 @@ private:
1081 break; 1109 break;
1082 } 1110 }
1083 case OpCode::Id::F2F_R: { 1111 case OpCode::Id::F2F_R: {
1112 ASSERT_MSG(!instr.saturate_a, "Unimplemented");
1113
1084 std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); 1114 std::string op_a = regs.GetRegisterAsFloat(instr.gpr20);
1085 1115
1086 switch (instr.conversion.f2f.rounding) { 1116 switch (instr.conversion.f2f.rounding) {
@@ -1198,8 +1228,8 @@ private:
1198 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 1228 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
1199 const std::string sampler = GetSampler(instr.sampler); 1229 const std::string sampler = GetSampler(instr.sampler);
1200 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; 1230 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");";
1201 // Add an extra scope and declare the texture coords inside to prevent overwriting 1231 // Add an extra scope and declare the texture coords inside to prevent
1202 // them in case they are used as outputs of the texs instruction. 1232 // overwriting them in case they are used as outputs of the texs instruction.
1203 shader.AddLine("{"); 1233 shader.AddLine("{");
1204 ++shader.scope; 1234 ++shader.scope;
1205 shader.AddLine(coord); 1235 shader.AddLine(coord);
@@ -1230,8 +1260,8 @@ private:
1230 shader.AddLine(coord); 1260 shader.AddLine(coord);
1231 const std::string texture = "texture(" + sampler + ", coords)"; 1261 const std::string texture = "texture(" + sampler + ", coords)";
1232 1262
1233 // TEXS has two destination registers. RG goes into gpr0+0 and gpr0+1, and BA goes 1263 // TEXS has two destination registers. RG goes into gpr0+0 and gpr0+1, and BA
1234 // into gpr28+0 and gpr28+1 1264 // goes into gpr28+0 and gpr28+1
1235 size_t offset{}; 1265 size_t offset{};
1236 1266
1237 for (const auto& dest : {instr.gpr0.Value(), instr.gpr28.Value()}) { 1267 for (const auto& dest : {instr.gpr0.Value(), instr.gpr28.Value()}) {
@@ -1412,8 +1442,8 @@ private:
1412 1442
1413 shader.AddLine("return true;"); 1443 shader.AddLine("return true;");
1414 if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) { 1444 if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) {
1415 // If this is an unconditional exit then just end processing here, otherwise we 1445 // If this is an unconditional exit then just end processing here, otherwise
1416 // have to account for the possibility of the condition not being met, so 1446 // we have to account for the possibility of the condition not being met, so
1417 // continue processing the next instruction. 1447 // continue processing the next instruction.
1418 offset = PROGRAM_END - 1; 1448 offset = PROGRAM_END - 1;
1419 } 1449 }