diff options
| author | 2021-03-18 02:53:57 -0400 | |
|---|---|---|
| committer | 2021-07-22 21:51:23 -0400 | |
| commit | 72990df7bad1c81d6ebc51179d34e1bfc71e0caf (patch) | |
| tree | fd681d1875c91bd823841d8ca76138f729338526 | |
| parent | shader: Implement CSET and CSETP (diff) | |
| download | yuzu-72990df7bad1c81d6ebc51179d34e1bfc71e0caf.tar.gz yuzu-72990df7bad1c81d6ebc51179d34e1bfc71e0caf.tar.xz yuzu-72990df7bad1c81d6ebc51179d34e1bfc71e0caf.zip | |
shader: Implement DADD
Diffstat (limited to '')
8 files changed, 132 insertions, 14 deletions
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index e4e7749c7..b870e9937 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt | |||
| @@ -64,6 +64,7 @@ add_library(shader_recompiler STATIC | |||
| 64 | frontend/maxwell/translate/impl/common_funcs.cpp | 64 | frontend/maxwell/translate/impl/common_funcs.cpp |
| 65 | frontend/maxwell/translate/impl/common_funcs.h | 65 | frontend/maxwell/translate/impl/common_funcs.h |
| 66 | frontend/maxwell/translate/impl/condition_code_set.cpp | 66 | frontend/maxwell/translate/impl/condition_code_set.cpp |
| 67 | frontend/maxwell/translate/impl/double_add.cpp | ||
| 67 | frontend/maxwell/translate/impl/find_leading_one.cpp | 68 | frontend/maxwell/translate/impl/find_leading_one.cpp |
| 68 | frontend/maxwell/translate/impl/floating_point_add.cpp | 69 | frontend/maxwell/translate/impl/floating_point_add.cpp |
| 69 | frontend/maxwell/translate/impl/floating_point_compare.cpp | 70 | frontend/maxwell/translate/impl/floating_point_compare.cpp |
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index f848c6175..204389d74 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp | |||
| @@ -94,6 +94,8 @@ Id EmitContext::Def(const IR::Value& value) { | |||
| 94 | return Constant(U32[1], value.U32()); | 94 | return Constant(U32[1], value.U32()); |
| 95 | case IR::Type::F32: | 95 | case IR::Type::F32: |
| 96 | return Constant(F32[1], value.F32()); | 96 | return Constant(F32[1], value.F32()); |
| 97 | case IR::Type::F64: | ||
| 98 | return Constant(F64[1], value.F64()); | ||
| 97 | default: | 99 | default: |
| 98 | throw NotImplementedException("Immediate type {}", value.Type()); | 100 | throw NotImplementedException("Immediate type {}", value.Type()); |
| 99 | } | 101 | } |
diff --git a/src/shader_recompiler/frontend/ir/value.cpp b/src/shader_recompiler/frontend/ir/value.cpp index 791ba2690..e8e4662e7 100644 --- a/src/shader_recompiler/frontend/ir/value.cpp +++ b/src/shader_recompiler/frontend/ir/value.cpp | |||
| @@ -153,6 +153,14 @@ u64 Value::U64() const { | |||
| 153 | return imm_u64; | 153 | return imm_u64; |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | f64 Value::F64() const { | ||
| 157 | if (IsIdentity()) { | ||
| 158 | return inst->Arg(0).F64(); | ||
| 159 | } | ||
| 160 | ValidateAccess(Type::F64); | ||
| 161 | return imm_f64; | ||
| 162 | } | ||
| 163 | |||
| 156 | bool Value::operator==(const Value& other) const { | 164 | bool Value::operator==(const Value& other) const { |
| 157 | if (type != other.type) { | 165 | if (type != other.type) { |
| 158 | return false; | 166 | return false; |
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index 3602883d6..b27601e70 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h | |||
| @@ -52,6 +52,7 @@ public: | |||
| 52 | [[nodiscard]] u32 U32() const; | 52 | [[nodiscard]] u32 U32() const; |
| 53 | [[nodiscard]] f32 F32() const; | 53 | [[nodiscard]] f32 F32() const; |
| 54 | [[nodiscard]] u64 U64() const; | 54 | [[nodiscard]] u64 U64() const; |
| 55 | [[nodiscard]] f64 F64() const; | ||
| 55 | 56 | ||
| 56 | [[nodiscard]] bool operator==(const Value& other) const; | 57 | [[nodiscard]] bool operator==(const Value& other) const; |
| 57 | [[nodiscard]] bool operator!=(const Value& other) const; | 58 | [[nodiscard]] bool operator!=(const Value& other) const; |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/double_add.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/double_add.cpp new file mode 100644 index 000000000..bece191d7 --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/double_add.cpp | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/common_types.h" | ||
| 6 | #include "shader_recompiler/exception.h" | ||
| 7 | #include "shader_recompiler/frontend/maxwell/translate/impl/common_encoding.h" | ||
| 8 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||
| 9 | |||
| 10 | namespace Shader::Maxwell { | ||
| 11 | namespace { | ||
| 12 | |||
| 13 | void DADD(TranslatorVisitor& v, u64 insn, const IR::F64& src_b) { | ||
| 14 | union { | ||
| 15 | u64 raw; | ||
| 16 | BitField<0, 8, IR::Reg> dest_reg; | ||
| 17 | BitField<8, 8, IR::Reg> src_a_reg; | ||
| 18 | BitField<39, 2, FpRounding> fp_rounding; | ||
| 19 | BitField<45, 1, u64> neg_b; | ||
| 20 | BitField<46, 1, u64> abs_a; | ||
| 21 | BitField<47, 1, u64> cc; | ||
| 22 | BitField<48, 1, u64> neg_a; | ||
| 23 | BitField<49, 1, u64> abs_b; | ||
| 24 | } const dadd{insn}; | ||
| 25 | |||
| 26 | if (!IR::IsAligned(dadd.dest_reg, 2)) { | ||
| 27 | throw NotImplementedException("Unaligned destination register {}", dadd.dest_reg.Value()); | ||
| 28 | } | ||
| 29 | if (!IR::IsAligned(dadd.src_a_reg, 2)) { | ||
| 30 | throw NotImplementedException("Unaligned destination register {}", dadd.src_a_reg.Value()); | ||
| 31 | } | ||
| 32 | if (dadd.cc != 0) { | ||
| 33 | throw NotImplementedException("DADD CC"); | ||
| 34 | } | ||
| 35 | |||
| 36 | const IR::Reg reg_a{dadd.src_a_reg}; | ||
| 37 | const IR::F64 src_a{v.ir.PackDouble2x32(v.ir.CompositeConstruct(v.X(reg_a), v.X(reg_a + 1)))}; | ||
| 38 | const IR::F64 op_a{v.ir.FPAbsNeg(src_a, dadd.abs_a != 0, dadd.neg_a != 0)}; | ||
| 39 | const IR::F64 op_b{v.ir.FPAbsNeg(src_b, dadd.abs_b != 0, dadd.neg_b != 0)}; | ||
| 40 | |||
| 41 | IR::FpControl control{ | ||
| 42 | .no_contraction{true}, | ||
| 43 | .rounding{CastFpRounding(dadd.fp_rounding)}, | ||
| 44 | .fmz_mode{IR::FmzMode::None}, | ||
| 45 | }; | ||
| 46 | const IR::F64 value{v.ir.FPAdd(op_a, op_b, control)}; | ||
| 47 | const IR::Value result{v.ir.UnpackDouble2x32(value)}; | ||
| 48 | |||
| 49 | for (int i = 0; i < 2; i++) { | ||
| 50 | v.X(dadd.dest_reg + i, IR::U32{v.ir.CompositeExtract(result, i)}); | ||
| 51 | } | ||
| 52 | } | ||
| 53 | } // Anonymous namespace | ||
| 54 | |||
| 55 | void TranslatorVisitor::DADD_reg(u64 insn) { | ||
| 56 | DADD(*this, insn, GetDoubleReg20(insn)); | ||
| 57 | } | ||
| 58 | |||
| 59 | void TranslatorVisitor::DADD_cbuf(u64 insn) { | ||
| 60 | DADD(*this, insn, GetDoubleCbuf(insn)); | ||
| 61 | } | ||
| 62 | |||
| 63 | void TranslatorVisitor::DADD_imm(u64 insn) { | ||
| 64 | DADD(*this, insn, GetDoubleImm20(insn)); | ||
| 65 | } | ||
| 66 | |||
| 67 | } // namespace Shader::Maxwell | ||
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp index 7564aeeb2..e444dcd4f 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp | |||
| @@ -7,6 +7,15 @@ | |||
| 7 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | 7 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" |
| 8 | 8 | ||
| 9 | namespace Shader::Maxwell { | 9 | namespace Shader::Maxwell { |
| 10 | namespace { | ||
| 11 | [[nodiscard]] IR::U32 CbufLowerBits(IR::IREmitter& ir, bool unaligned, const IR::U32& binding, | ||
| 12 | u32 offset) { | ||
| 13 | if (unaligned) { | ||
| 14 | return ir.Imm32(0); | ||
| 15 | } | ||
| 16 | return ir.GetCbuf(binding, IR::U32{IR::Value{offset}}); | ||
| 17 | } | ||
| 18 | } // Anonymous namespace | ||
| 10 | 19 | ||
| 11 | IR::U32 TranslatorVisitor::X(IR::Reg reg) { | 20 | IR::U32 TranslatorVisitor::X(IR::Reg reg) { |
| 12 | return ir.GetReg(reg); | 21 | return ir.GetReg(reg); |
| @@ -56,6 +65,18 @@ IR::F32 TranslatorVisitor::GetFloatReg39(u64 insn) { | |||
| 56 | return ir.BitCast<IR::F32>(GetReg39(insn)); | 65 | return ir.BitCast<IR::F32>(GetReg39(insn)); |
| 57 | } | 66 | } |
| 58 | 67 | ||
| 68 | IR::F64 TranslatorVisitor::GetDoubleReg20(u64 insn) { | ||
| 69 | union { | ||
| 70 | u64 raw; | ||
| 71 | BitField<20, 8, IR::Reg> src; | ||
| 72 | } const index{insn}; | ||
| 73 | const IR::Reg reg{index.src}; | ||
| 74 | if (!IR::IsAligned(reg, 2)) { | ||
| 75 | throw NotImplementedException("Unaligned source register {}", reg); | ||
| 76 | } | ||
| 77 | return ir.PackDouble2x32(ir.CompositeConstruct(X(reg), X(reg + 1))); | ||
| 78 | } | ||
| 79 | |||
| 59 | static std::pair<IR::U32, IR::U32> CbufAddr(u64 insn) { | 80 | static std::pair<IR::U32, IR::U32> CbufAddr(u64 insn) { |
| 60 | union { | 81 | union { |
| 61 | u64 raw; | 82 | u64 raw; |
| @@ -75,15 +96,31 @@ static std::pair<IR::U32, IR::U32> CbufAddr(u64 insn) { | |||
| 75 | } | 96 | } |
| 76 | 97 | ||
| 77 | IR::U32 TranslatorVisitor::GetCbuf(u64 insn) { | 98 | IR::U32 TranslatorVisitor::GetCbuf(u64 insn) { |
| 78 | const auto[binding, byte_offset]{CbufAddr(insn)}; | 99 | const auto [binding, byte_offset]{CbufAddr(insn)}; |
| 79 | return ir.GetCbuf(binding, byte_offset); | 100 | return ir.GetCbuf(binding, byte_offset); |
| 80 | } | 101 | } |
| 81 | 102 | ||
| 82 | IR::F32 TranslatorVisitor::GetFloatCbuf(u64 insn) { | 103 | IR::F32 TranslatorVisitor::GetFloatCbuf(u64 insn) { |
| 83 | const auto[binding, byte_offset]{CbufAddr(insn)}; | 104 | const auto [binding, byte_offset]{CbufAddr(insn)}; |
| 84 | return ir.GetFloatCbuf(binding, byte_offset); | 105 | return ir.GetFloatCbuf(binding, byte_offset); |
| 85 | } | 106 | } |
| 86 | 107 | ||
| 108 | IR::F64 TranslatorVisitor::GetDoubleCbuf(u64 insn) { | ||
| 109 | union { | ||
| 110 | u64 raw; | ||
| 111 | BitField<20, 1, u64> unaligned; | ||
| 112 | } const cbuf{insn}; | ||
| 113 | |||
| 114 | const auto [binding, offset_value]{CbufAddr(insn)}; | ||
| 115 | const bool unaligned{cbuf.unaligned != 0}; | ||
| 116 | const u32 offset{offset_value.U32()}; | ||
| 117 | const IR::Value addr{unaligned ? offset | 4 : (offset & ~7) | 4}; | ||
| 118 | |||
| 119 | const IR::U32 value{ir.GetCbuf(binding, IR::U32{addr})}; | ||
| 120 | const IR::U32 lower_bits{CbufLowerBits(ir, unaligned, binding, offset)}; | ||
| 121 | return ir.PackDouble2x32(ir.CompositeConstruct(lower_bits, value)); | ||
| 122 | } | ||
| 123 | |||
| 87 | IR::U32 TranslatorVisitor::GetImm20(u64 insn) { | 124 | IR::U32 TranslatorVisitor::GetImm20(u64 insn) { |
| 88 | union { | 125 | union { |
| 89 | u64 raw; | 126 | u64 raw; |
| @@ -110,6 +147,17 @@ IR::F32 TranslatorVisitor::GetFloatImm20(u64 insn) { | |||
| 110 | return ir.Imm32(Common::BitCast<f32>(value | sign_bit)); | 147 | return ir.Imm32(Common::BitCast<f32>(value | sign_bit)); |
| 111 | } | 148 | } |
| 112 | 149 | ||
| 150 | IR::F64 TranslatorVisitor::GetDoubleImm20(u64 insn) { | ||
| 151 | union { | ||
| 152 | u64 raw; | ||
| 153 | BitField<20, 19, u64> value; | ||
| 154 | BitField<56, 1, u64> is_negative; | ||
| 155 | } const imm{insn}; | ||
| 156 | const u64 sign_bit{imm.is_negative != 0 ? (1ULL << 63) : 0}; | ||
| 157 | const u64 value{imm.value << 44}; | ||
| 158 | return ir.Imm64(Common::BitCast<f64>(value | sign_bit)); | ||
| 159 | } | ||
| 160 | |||
| 113 | IR::U32 TranslatorVisitor::GetImm32(u64 insn) { | 161 | IR::U32 TranslatorVisitor::GetImm32(u64 insn) { |
| 114 | union { | 162 | union { |
| 115 | u64 raw; | 163 | u64 raw; |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h index 761b64666..e3e298c3b 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h | |||
| @@ -351,12 +351,15 @@ public: | |||
| 351 | [[nodiscard]] IR::U32 GetReg39(u64 insn); | 351 | [[nodiscard]] IR::U32 GetReg39(u64 insn); |
| 352 | [[nodiscard]] IR::F32 GetFloatReg20(u64 insn); | 352 | [[nodiscard]] IR::F32 GetFloatReg20(u64 insn); |
| 353 | [[nodiscard]] IR::F32 GetFloatReg39(u64 insn); | 353 | [[nodiscard]] IR::F32 GetFloatReg39(u64 insn); |
| 354 | [[nodiscard]] IR::F64 GetDoubleReg20(u64 insn); | ||
| 354 | 355 | ||
| 355 | [[nodiscard]] IR::U32 GetCbuf(u64 insn); | 356 | [[nodiscard]] IR::U32 GetCbuf(u64 insn); |
| 356 | [[nodiscard]] IR::F32 GetFloatCbuf(u64 insn); | 357 | [[nodiscard]] IR::F32 GetFloatCbuf(u64 insn); |
| 358 | [[nodiscard]] IR::F64 GetDoubleCbuf(u64 insn); | ||
| 357 | 359 | ||
| 358 | [[nodiscard]] IR::U32 GetImm20(u64 insn); | 360 | [[nodiscard]] IR::U32 GetImm20(u64 insn); |
| 359 | [[nodiscard]] IR::F32 GetFloatImm20(u64 insn); | 361 | [[nodiscard]] IR::F32 GetFloatImm20(u64 insn); |
| 362 | [[nodiscard]] IR::F64 GetDoubleImm20(u64 insn); | ||
| 360 | 363 | ||
| 361 | [[nodiscard]] IR::U32 GetImm32(u64 insn); | 364 | [[nodiscard]] IR::U32 GetImm32(u64 insn); |
| 362 | [[nodiscard]] IR::F32 GetFloatImm32(u64 insn); | 365 | [[nodiscard]] IR::F32 GetFloatImm32(u64 insn); |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp index 0325f14ea..9675cef54 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp | |||
| @@ -85,18 +85,6 @@ void TranslatorVisitor::CS2R(u64) { | |||
| 85 | ThrowNotImplemented(Opcode::CS2R); | 85 | ThrowNotImplemented(Opcode::CS2R); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | void TranslatorVisitor::DADD_reg(u64) { | ||
| 89 | ThrowNotImplemented(Opcode::DADD_reg); | ||
| 90 | } | ||
| 91 | |||
| 92 | void TranslatorVisitor::DADD_cbuf(u64) { | ||
| 93 | ThrowNotImplemented(Opcode::DADD_cbuf); | ||
| 94 | } | ||
| 95 | |||
| 96 | void TranslatorVisitor::DADD_imm(u64) { | ||
| 97 | ThrowNotImplemented(Opcode::DADD_imm); | ||
| 98 | } | ||
| 99 | |||
| 100 | void TranslatorVisitor::DEPBAR() { | 88 | void TranslatorVisitor::DEPBAR() { |
| 101 | // DEPBAR is a no-op | 89 | // DEPBAR is a no-op |
| 102 | } | 90 | } |