diff options
| author | 2018-06-09 00:34:03 -0400 | |
|---|---|---|
| committer | 2018-06-09 00:34:03 -0400 | |
| commit | 174c22e5f6a1fd93842a8e8fda6e63e676d34866 (patch) | |
| tree | ac8613849062fe64ed2e8ddd02dbedf5e381ecaa /src | |
| parent | Merge pull request #505 from janisozaur/ccache-travis (diff) | |
| parent | gl_shader_decompiler: Implement IADD instruction. (diff) | |
| download | yuzu-174c22e5f6a1fd93842a8e8fda6e63e676d34866.tar.gz yuzu-174c22e5f6a1fd93842a8e8fda6e63e676d34866.tar.xz yuzu-174c22e5f6a1fd93842a8e8fda6e63e676d34866.zip | |
Merge pull request #549 from bunnei/iadd
gl_shader_decompiler: Implement IADD instruction.
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 18 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 56 |
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 | } |