summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend/maxwell/translate/impl
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-03-20 05:04:12 -0300
committerGravatar ameerj2021-07-22 21:51:23 -0400
commitf91859efd259995806c2944f7941b105b58300d3 (patch)
tree489e587bcac6c0833c02378a106222c4db107c14 /src/shader_recompiler/frontend/maxwell/translate/impl
parentshader: Implement ISCADD (imm) (diff)
downloadyuzu-f91859efd259995806c2944f7941b105b58300d3.tar.gz
yuzu-f91859efd259995806c2944f7941b105b58300d3.tar.xz
yuzu-f91859efd259995806c2944f7941b105b58300d3.zip
shader: Implement I2F
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell/translate/impl')
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp21
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/impl.h2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/integer_floating_point_conversion.cpp173
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp12
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch.cpp2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp2
6 files changed, 198 insertions, 14 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp
index e444dcd4f..c9af83010 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp
@@ -121,6 +121,22 @@ IR::F64 TranslatorVisitor::GetDoubleCbuf(u64 insn) {
121 return ir.PackDouble2x32(ir.CompositeConstruct(lower_bits, value)); 121 return ir.PackDouble2x32(ir.CompositeConstruct(lower_bits, value));
122} 122}
123 123
124IR::U64 TranslatorVisitor::GetPackedCbuf(u64 insn) {
125 union {
126 u64 raw;
127 BitField<20, 1, u64> unaligned;
128 } const cbuf{insn};
129
130 if (cbuf.unaligned != 0) {
131 throw NotImplementedException("Unaligned packed constant buffer read");
132 }
133 const auto [binding, lower_offset]{CbufAddr(insn)};
134 const IR::U32 upper_offset{ir.Imm32(lower_offset.U32() + 4)};
135 const IR::U32 lower_value{ir.GetCbuf(binding, lower_offset)};
136 const IR::U32 upper_value{ir.GetCbuf(binding, upper_offset)};
137 return ir.PackUint2x32(ir.CompositeConstruct(lower_value, upper_value));
138}
139
124IR::U32 TranslatorVisitor::GetImm20(u64 insn) { 140IR::U32 TranslatorVisitor::GetImm20(u64 insn) {
125 union { 141 union {
126 u64 raw; 142 u64 raw;
@@ -158,6 +174,11 @@ IR::F64 TranslatorVisitor::GetDoubleImm20(u64 insn) {
158 return ir.Imm64(Common::BitCast<f64>(value | sign_bit)); 174 return ir.Imm64(Common::BitCast<f64>(value | sign_bit));
159} 175}
160 176
177IR::U64 TranslatorVisitor::GetPackedImm20(u64 insn) {
178 const s64 value{GetImm20(insn).U32()};
179 return ir.Imm64(static_cast<u64>(static_cast<s64>(value) << 32));
180}
181
161IR::U32 TranslatorVisitor::GetImm32(u64 insn) { 182IR::U32 TranslatorVisitor::GetImm32(u64 insn) {
162 union { 183 union {
163 u64 raw; 184 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 ed81d9c36..cb66cca25 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h
@@ -356,10 +356,12 @@ public:
356 [[nodiscard]] IR::U32 GetCbuf(u64 insn); 356 [[nodiscard]] IR::U32 GetCbuf(u64 insn);
357 [[nodiscard]] IR::F32 GetFloatCbuf(u64 insn); 357 [[nodiscard]] IR::F32 GetFloatCbuf(u64 insn);
358 [[nodiscard]] IR::F64 GetDoubleCbuf(u64 insn); 358 [[nodiscard]] IR::F64 GetDoubleCbuf(u64 insn);
359 [[nodiscard]] IR::U64 GetPackedCbuf(u64 insn);
359 360
360 [[nodiscard]] IR::U32 GetImm20(u64 insn); 361 [[nodiscard]] IR::U32 GetImm20(u64 insn);
361 [[nodiscard]] IR::F32 GetFloatImm20(u64 insn); 362 [[nodiscard]] IR::F32 GetFloatImm20(u64 insn);
362 [[nodiscard]] IR::F64 GetDoubleImm20(u64 insn); 363 [[nodiscard]] IR::F64 GetDoubleImm20(u64 insn);
364 [[nodiscard]] IR::U64 GetPackedImm20(u64 insn);
363 365
364 [[nodiscard]] IR::U32 GetImm32(u64 insn); 366 [[nodiscard]] IR::U32 GetImm32(u64 insn);
365 [[nodiscard]] IR::F32 GetFloatImm32(u64 insn); 367 [[nodiscard]] IR::F32 GetFloatImm32(u64 insn);
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_floating_point_conversion.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_floating_point_conversion.cpp
new file mode 100644
index 000000000..e8b5ae1d2
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_floating_point_conversion.cpp
@@ -0,0 +1,173 @@
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/bit_field.h"
6#include "common/common_types.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 {
12enum class FloatFormat : u64 {
13 F16 = 1,
14 F32 = 2,
15 F64 = 3,
16};
17
18enum class IntFormat : u64 {
19 U8 = 0,
20 U16 = 1,
21 U32 = 2,
22 U64 = 3,
23};
24
25union Encoding {
26 u64 raw;
27 BitField<0, 8, IR::Reg> dest_reg;
28 BitField<8, 2, FloatFormat> float_format;
29 BitField<10, 2, IntFormat> int_format;
30 BitField<13, 1, u64> is_signed;
31 BitField<39, 2, FpRounding> fp_rounding;
32 BitField<41, 2, u64> selector;
33 BitField<47, 1, u64> cc;
34 BitField<45, 1, u64> neg;
35 BitField<49, 1, u64> abs;
36};
37
38bool Is64(u64 insn) {
39 return Encoding{insn}.int_format == IntFormat::U64;
40}
41
42int BitSize(FloatFormat format) {
43 switch (format) {
44 case FloatFormat::F16:
45 return 16;
46 case FloatFormat::F32:
47 return 32;
48 case FloatFormat::F64:
49 return 64;
50 }
51 throw NotImplementedException("Invalid float format {}", format);
52}
53
54IR::U32 SmallAbs(TranslatorVisitor& v, const IR::U32& value, int bitsize) {
55 const IR::U32 least_value{v.ir.Imm32(-(1 << (bitsize - 1)))};
56 const IR::U32 mask{v.ir.ShiftRightArithmetic(value, v.ir.Imm32(bitsize - 1))};
57 const IR::U32 absolute{v.ir.BitwiseXor(v.ir.IAdd(value, mask), mask)};
58 const IR::U1 is_least{v.ir.IEqual(value, least_value)};
59 return IR::U32{v.ir.Select(is_least, value, absolute)};
60}
61
62void I2F(TranslatorVisitor& v, u64 insn, IR::U32U64 src) {
63 const Encoding i2f{insn};
64 if (i2f.cc != 0) {
65 throw NotImplementedException("CC");
66 }
67 const bool is_signed{i2f.is_signed != 0};
68 int src_bitsize{};
69 switch (i2f.int_format) {
70 case IntFormat::U8:
71 src = v.ir.BitFieldExtract(src, v.ir.Imm32(static_cast<u32>(i2f.selector) * 8),
72 v.ir.Imm32(8), is_signed);
73 if (i2f.abs != 0) {
74 src = SmallAbs(v, src, 8);
75 }
76 src_bitsize = 8;
77 break;
78 case IntFormat::U16:
79 if (i2f.selector == 1 || i2f.selector == 3) {
80 throw NotImplementedException("Invalid U16 selector {}", i2f.selector.Value());
81 }
82 src = v.ir.BitFieldExtract(src, v.ir.Imm32(static_cast<u32>(i2f.selector) * 8),
83 v.ir.Imm32(16), is_signed);
84 if (i2f.abs != 0) {
85 src = SmallAbs(v, src, 16);
86 }
87 src_bitsize = 16;
88 break;
89 case IntFormat::U32:
90 case IntFormat::U64:
91 if (i2f.selector != 0) {
92 throw NotImplementedException("Unexpected selector {}", i2f.selector.Value());
93 }
94 if (i2f.abs != 0 && is_signed) {
95 src = v.ir.IAbs(src);
96 }
97 src_bitsize = i2f.int_format == IntFormat::U64 ? 64 : 32;
98 break;
99 }
100 const int conversion_src_bitsize{i2f.int_format == IntFormat::U64 ? 64 : 32};
101 const int dst_bitsize{BitSize(i2f.float_format)};
102 IR::F16F32F64 value{v.ir.ConvertIToF(dst_bitsize, conversion_src_bitsize, is_signed, src)};
103 if (i2f.neg != 0) {
104 if (i2f.abs != 0 || !is_signed) {
105 // We know the value is positive
106 value = v.ir.FPNeg(value);
107 } else {
108 // Only negate if the input isn't the lowest value
109 IR::U1 is_least;
110 if (src_bitsize == 64) {
111 is_least = v.ir.IEqual(src, v.ir.Imm64(std::numeric_limits<s64>::min()));
112 } else {
113 const IR::U32 least_value{v.ir.Imm32(-(1 << (src_bitsize - 1)))};
114 is_least = v.ir.IEqual(src, least_value);
115 }
116 value = IR::F16F32F64{v.ir.Select(is_least, value, v.ir.FPNeg(value))};
117 }
118 }
119 switch (i2f.float_format) {
120 case FloatFormat::F16: {
121 const IR::F16 zero{v.ir.FPConvert(16, v.ir.Imm32(0.0f))};
122 v.X(i2f.dest_reg, v.ir.PackFloat2x16(v.ir.CompositeConstruct(value, zero)));
123 break;
124 }
125 case FloatFormat::F32:
126 v.F(i2f.dest_reg, value);
127 break;
128 case FloatFormat::F64: {
129 if (!IR::IsAligned(i2f.dest_reg, 2)) {
130 throw NotImplementedException("Unaligned destination {}", i2f.dest_reg.Value());
131 }
132 const IR::Value vector{v.ir.UnpackDouble2x32(value)};
133 for (int i = 0; i < 2; ++i) {
134 v.X(i2f.dest_reg + i, IR::U32{v.ir.CompositeExtract(vector, i)});
135 }
136 break;
137 }
138 default:
139 throw NotImplementedException("Invalid float format {}", i2f.float_format.Value());
140 }
141}
142} // Anonymous namespace
143
144void TranslatorVisitor::I2F_reg(u64 insn) {
145 if (Is64(insn)) {
146 union {
147 u64 raw;
148 BitField<20, 8, IR::Reg> reg;
149 } const value{insn};
150 const IR::Value regs{ir.CompositeConstruct(ir.GetReg(value.reg), ir.GetReg(value.reg + 1))};
151 I2F(*this, insn, ir.PackUint2x32(regs));
152 } else {
153 I2F(*this, insn, GetReg20(insn));
154 }
155}
156
157void TranslatorVisitor::I2F_cbuf(u64 insn) {
158 if (Is64(insn)) {
159 I2F(*this, insn, GetPackedCbuf(insn));
160 } else {
161 I2F(*this, insn, GetCbuf(insn));
162 }
163}
164
165void TranslatorVisitor::I2F_imm(u64 insn) {
166 if (Is64(insn)) {
167 I2F(*this, insn, GetPackedImm20(insn));
168 } else {
169 I2F(*this, insn, GetImm20(insn));
170 }
171}
172
173} // namespace Shader::Maxwell \ No newline at end of file
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 a4367fc5a..4078feafa 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp
@@ -241,18 +241,6 @@ void TranslatorVisitor::HSETP2_imm(u64) {
241 ThrowNotImplemented(Opcode::HSETP2_imm); 241 ThrowNotImplemented(Opcode::HSETP2_imm);
242} 242}
243 243
244void TranslatorVisitor::I2F_reg(u64) {
245 ThrowNotImplemented(Opcode::I2F_reg);
246}
247
248void TranslatorVisitor::I2F_cbuf(u64) {
249 ThrowNotImplemented(Opcode::I2F_cbuf);
250}
251
252void TranslatorVisitor::I2F_imm(u64) {
253 ThrowNotImplemented(Opcode::I2F_imm);
254}
255
256void TranslatorVisitor::IDE(u64) { 244void TranslatorVisitor::IDE(u64) {
257 ThrowNotImplemented(Opcode::IDE); 245 ThrowNotImplemented(Opcode::IDE);
258} 246}
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch.cpp
index 0fbb87ec4..b691b4d1f 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch.cpp
@@ -56,7 +56,7 @@ Shader::TextureType GetType(TextureType type, bool dc) {
56} 56}
57 57
58IR::Value MakeCoords(TranslatorVisitor& v, IR::Reg reg, TextureType type) { 58IR::Value MakeCoords(TranslatorVisitor& v, IR::Reg reg, TextureType type) {
59 const auto read_array{[&]() -> IR::F32 { return v.ir.ConvertUToF(32, v.X(reg)); }}; 59 const auto read_array{[&]() -> IR::F32 { return v.ir.ConvertUToF(32, 16, v.X(reg)); }};
60 switch (type) { 60 switch (type) {
61 case TextureType::_1D: 61 case TextureType::_1D:
62 return v.F(reg); 62 return v.F(reg);
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp
index 54f0df754..d5fda20f4 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp
@@ -65,7 +65,7 @@ IR::Value Composite(TranslatorVisitor& v, Args... regs) {
65} 65}
66 66
67IR::F32 ReadArray(TranslatorVisitor& v, const IR::U32& value) { 67IR::F32 ReadArray(TranslatorVisitor& v, const IR::U32& value) {
68 return v.ir.ConvertUToF(32, v.ir.BitFieldExtract(value, v.ir.Imm32(0), v.ir.Imm32(16))); 68 return v.ir.ConvertUToF(32, 16, v.ir.BitFieldExtract(value, v.ir.Imm32(0), v.ir.Imm32(16)));
69} 69}
70 70
71IR::Value Sample(TranslatorVisitor& v, u64 insn) { 71IR::Value Sample(TranslatorVisitor& v, u64 insn) {