summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar ameerj2021-03-18 02:53:57 -0400
committerGravatar ameerj2021-07-22 21:51:23 -0400
commit72990df7bad1c81d6ebc51179d34e1bfc71e0caf (patch)
treefd681d1875c91bd823841d8ca76138f729338526
parentshader: Implement CSET and CSETP (diff)
downloadyuzu-72990df7bad1c81d6ebc51179d34e1bfc71e0caf.tar.gz
yuzu-72990df7bad1c81d6ebc51179d34e1bfc71e0caf.tar.xz
yuzu-72990df7bad1c81d6ebc51179d34e1bfc71e0caf.zip
shader: Implement DADD
Diffstat (limited to '')
-rw-r--r--src/shader_recompiler/CMakeLists.txt1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.cpp2
-rw-r--r--src/shader_recompiler/frontend/ir/value.cpp8
-rw-r--r--src/shader_recompiler/frontend/ir/value.h1
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/double_add.cpp67
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp52
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/impl.h3
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp12
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
156f64 Value::F64() const {
157 if (IsIdentity()) {
158 return inst->Arg(0).F64();
159 }
160 ValidateAccess(Type::F64);
161 return imm_f64;
162}
163
156bool Value::operator==(const Value& other) const { 164bool 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
10namespace Shader::Maxwell {
11namespace {
12
13void 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
55void TranslatorVisitor::DADD_reg(u64 insn) {
56 DADD(*this, insn, GetDoubleReg20(insn));
57}
58
59void TranslatorVisitor::DADD_cbuf(u64 insn) {
60 DADD(*this, insn, GetDoubleCbuf(insn));
61}
62
63void 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
9namespace Shader::Maxwell { 9namespace Shader::Maxwell {
10namespace {
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
11IR::U32 TranslatorVisitor::X(IR::Reg reg) { 20IR::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
68IR::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
59static std::pair<IR::U32, IR::U32> CbufAddr(u64 insn) { 80static 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
77IR::U32 TranslatorVisitor::GetCbuf(u64 insn) { 98IR::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
82IR::F32 TranslatorVisitor::GetFloatCbuf(u64 insn) { 103IR::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
108IR::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
87IR::U32 TranslatorVisitor::GetImm20(u64 insn) { 124IR::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
150IR::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
113IR::U32 TranslatorVisitor::GetImm32(u64 insn) { 161IR::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
88void TranslatorVisitor::DADD_reg(u64) {
89 ThrowNotImplemented(Opcode::DADD_reg);
90}
91
92void TranslatorVisitor::DADD_cbuf(u64) {
93 ThrowNotImplemented(Opcode::DADD_cbuf);
94}
95
96void TranslatorVisitor::DADD_imm(u64) {
97 ThrowNotImplemented(Opcode::DADD_imm);
98}
99
100void TranslatorVisitor::DEPBAR() { 88void TranslatorVisitor::DEPBAR() {
101 // DEPBAR is a no-op 89 // DEPBAR is a no-op
102} 90}