diff options
| author | 2018-12-23 02:26:35 -0300 | |
|---|---|---|
| committer | 2019-01-15 17:54:52 -0300 | |
| commit | dd91650aaf217196a2b1ced17df24bd74349843d (patch) | |
| tree | 537f6098b72cd7fa7ccccc0c44f294faf95e96e9 /src/video_core/shader/decode | |
| parent | glsl_decompiler: Remove HNegate inlining (diff) | |
| download | yuzu-dd91650aaf217196a2b1ced17df24bd74349843d.tar.gz yuzu-dd91650aaf217196a2b1ced17df24bd74349843d.tar.xz yuzu-dd91650aaf217196a2b1ced17df24bd74349843d.zip | |
shader_decode: Implement HFMA2
Diffstat (limited to 'src/video_core/shader/decode')
| -rw-r--r-- | src/video_core/shader/decode/hfma2.cpp | 54 |
1 files changed, 53 insertions, 1 deletions
diff --git a/src/video_core/shader/decode/hfma2.cpp b/src/video_core/shader/decode/hfma2.cpp index 5ce08481e..bf7491804 100644 --- a/src/video_core/shader/decode/hfma2.cpp +++ b/src/video_core/shader/decode/hfma2.cpp | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <tuple> | ||
| 6 | |||
| 5 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 6 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 7 | #include "video_core/engines/shader_bytecode.h" | 9 | #include "video_core/engines/shader_bytecode.h" |
| @@ -9,6 +11,8 @@ | |||
| 9 | 11 | ||
| 10 | namespace VideoCommon::Shader { | 12 | namespace VideoCommon::Shader { |
| 11 | 13 | ||
| 14 | using Tegra::Shader::HalfPrecision; | ||
| 15 | using Tegra::Shader::HalfType; | ||
| 12 | using Tegra::Shader::Instruction; | 16 | using Tegra::Shader::Instruction; |
| 13 | using Tegra::Shader::OpCode; | 17 | using Tegra::Shader::OpCode; |
| 14 | 18 | ||
| @@ -16,7 +20,55 @@ u32 ShaderIR::DecodeHfma2(BasicBlock& bb, u32 pc) { | |||
| 16 | const Instruction instr = {program_code[pc]}; | 20 | const Instruction instr = {program_code[pc]}; |
| 17 | const auto opcode = OpCode::Decode(instr); | 21 | const auto opcode = OpCode::Decode(instr); |
| 18 | 22 | ||
| 19 | UNIMPLEMENTED(); | 23 | if (opcode->get().GetId() == OpCode::Id::HFMA2_RR) { |
| 24 | UNIMPLEMENTED_IF(instr.hfma2.rr.precision != HalfPrecision::None); | ||
| 25 | } else { | ||
| 26 | UNIMPLEMENTED_IF(instr.hfma2.precision != HalfPrecision::None); | ||
| 27 | } | ||
| 28 | |||
| 29 | constexpr auto identity = HalfType::H0_H1; | ||
| 30 | |||
| 31 | const HalfType type_a = instr.hfma2.type_a; | ||
| 32 | const Node op_a = GetRegister(instr.gpr8); | ||
| 33 | |||
| 34 | bool neg_b{}, neg_c{}; | ||
| 35 | auto [saturate, type_b, op_b, type_c, | ||
| 36 | op_c] = [&]() -> std::tuple<bool, HalfType, Node, HalfType, Node> { | ||
| 37 | switch (opcode->get().GetId()) { | ||
| 38 | case OpCode::Id::HFMA2_CR: | ||
| 39 | neg_b = instr.hfma2.negate_b; | ||
| 40 | neg_c = instr.hfma2.negate_c; | ||
| 41 | return {instr.hfma2.saturate, instr.hfma2.type_b, | ||
| 42 | GetConstBuffer(instr.cbuf34.index, instr.cbuf34.offset), instr.hfma2.type_reg39, | ||
| 43 | GetRegister(instr.gpr39)}; | ||
| 44 | case OpCode::Id::HFMA2_RC: | ||
| 45 | neg_b = instr.hfma2.negate_b; | ||
| 46 | neg_c = instr.hfma2.negate_c; | ||
| 47 | return {instr.hfma2.saturate, instr.hfma2.type_reg39, GetRegister(instr.gpr39), | ||
| 48 | instr.hfma2.type_b, GetConstBuffer(instr.cbuf34.index, instr.cbuf34.offset)}; | ||
| 49 | case OpCode::Id::HFMA2_RR: | ||
| 50 | neg_b = instr.hfma2.rr.negate_b; | ||
| 51 | neg_c = instr.hfma2.rr.negate_c; | ||
| 52 | return {instr.hfma2.rr.saturate, instr.hfma2.type_b, GetRegister(instr.gpr20), | ||
| 53 | instr.hfma2.rr.type_c, GetRegister(instr.gpr39)}; | ||
| 54 | case OpCode::Id::HFMA2_IMM_R: | ||
| 55 | neg_c = instr.hfma2.negate_c; | ||
| 56 | return {instr.hfma2.saturate, identity, UnpackHalfImmediate(instr, true), | ||
| 57 | instr.hfma2.type_reg39, GetRegister(instr.gpr39)}; | ||
| 58 | default: | ||
| 59 | return {false, identity, Immediate(0), identity, Immediate(0)}; | ||
| 60 | } | ||
| 61 | }(); | ||
| 62 | UNIMPLEMENTED_IF_MSG(saturate, "HFMA2 saturation is not implemented"); | ||
| 63 | |||
| 64 | op_b = GetOperandAbsNegHalf(op_b, false, neg_b); | ||
| 65 | op_c = GetOperandAbsNegHalf(op_c, false, neg_c); | ||
| 66 | |||
| 67 | MetaHalfArithmetic meta{true, {type_a, type_b, type_c}}; | ||
| 68 | Node value = Operation(OperationCode::HFma, meta, op_a, op_b, op_c); | ||
| 69 | value = HalfMerge(GetRegister(instr.gpr0), value, instr.hfma2.merge); | ||
| 70 | |||
| 71 | SetRegister(bb, instr.gpr0, value); | ||
| 20 | 72 | ||
| 21 | return pc; | 73 | return pc; |
| 22 | } | 74 | } |