summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/frontend')
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.cpp8
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.h3
-rw-r--r--src/shader_recompiler/frontend/ir/modifiers.h3
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp4
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch.cpp (renamed from src/shader_recompiler/frontend/maxwell/translate/impl/texture_sample.cpp)0
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp262
6 files changed, 275 insertions, 5 deletions
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
index 556961fa4..d94596ee9 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
@@ -512,6 +512,14 @@ Value IREmitter::UnpackFloat2x16(const U32& value) {
512 return Inst(Opcode::UnpackFloat2x16, value); 512 return Inst(Opcode::UnpackFloat2x16, value);
513} 513}
514 514
515U32 IREmitter::PackHalf2x16(const Value& vector) {
516 return Inst<U32>(Opcode::PackHalf2x16, vector);
517}
518
519Value IREmitter::UnpackHalf2x16(const U32& value) {
520 return Inst(Opcode::UnpackHalf2x16, value);
521}
522
515F64 IREmitter::PackDouble2x32(const Value& vector) { 523F64 IREmitter::PackDouble2x32(const Value& vector) {
516 return Inst<F64>(Opcode::PackDouble2x32, vector); 524 return Inst<F64>(Opcode::PackDouble2x32, vector);
517} 525}
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h
index 74fb3dbcb..27ff5a29d 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.h
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.h
@@ -115,6 +115,9 @@ public:
115 [[nodiscard]] U32 PackFloat2x16(const Value& vector); 115 [[nodiscard]] U32 PackFloat2x16(const Value& vector);
116 [[nodiscard]] Value UnpackFloat2x16(const U32& value); 116 [[nodiscard]] Value UnpackFloat2x16(const U32& value);
117 117
118 [[nodiscard]] U32 PackHalf2x16(const Value& vector);
119 [[nodiscard]] Value UnpackHalf2x16(const U32& value);
120
118 [[nodiscard]] F64 PackDouble2x32(const Value& vector); 121 [[nodiscard]] F64 PackDouble2x32(const Value& vector);
119 [[nodiscard]] Value UnpackDouble2x32(const F64& value); 122 [[nodiscard]] Value UnpackDouble2x32(const F64& value);
120 123
diff --git a/src/shader_recompiler/frontend/ir/modifiers.h b/src/shader_recompiler/frontend/ir/modifiers.h
index ad07700ae..308c00153 100644
--- a/src/shader_recompiler/frontend/ir/modifiers.h
+++ b/src/shader_recompiler/frontend/ir/modifiers.h
@@ -36,7 +36,8 @@ union TextureInstInfo {
36 u32 raw; 36 u32 raw;
37 BitField<0, 8, TextureType> type; 37 BitField<0, 8, TextureType> type;
38 BitField<8, 1, u32> has_bias; 38 BitField<8, 1, u32> has_bias;
39 BitField<16, 1, u32> has_lod_clamp; 39 BitField<9, 1, u32> has_lod_clamp;
40 BitField<10, 1, u32> relaxed_precision;
40}; 41};
41static_assert(sizeof(TextureInstInfo) <= sizeof(u32)); 42static_assert(sizeof(TextureInstInfo) <= sizeof(u32));
42 43
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 92da5c7e8..9aa7b836c 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp
@@ -553,10 +553,6 @@ void TranslatorVisitor::SYNC(u64) {
553 ThrowNotImplemented(Opcode::SYNC); 553 ThrowNotImplemented(Opcode::SYNC);
554} 554}
555 555
556void TranslatorVisitor::TEXS(u64) {
557 ThrowNotImplemented(Opcode::TEXS);
558}
559
560void TranslatorVisitor::TLD(u64) { 556void TranslatorVisitor::TLD(u64) {
561 ThrowNotImplemented(Opcode::TLD); 557 ThrowNotImplemented(Opcode::TLD);
562} 558}
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_sample.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch.cpp
index 98d9f4c64..98d9f4c64 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_sample.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch.cpp
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
new file mode 100644
index 000000000..ac1615b00
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp
@@ -0,0 +1,262 @@
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 <utility>
6
7#include "common/bit_field.h"
8#include "common/common_types.h"
9#include "shader_recompiler/frontend/ir/modifiers.h"
10#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
11
12namespace Shader::Maxwell {
13namespace {
14enum class Precision : u64 {
15 F16,
16 F32,
17};
18
19union Encoding {
20 u64 raw;
21 BitField<59, 1, Precision> precision;
22 BitField<53, 4, u64> encoding;
23 BitField<49, 1, u64> nodep;
24 BitField<28, 8, IR::Reg> dest_reg_b;
25 BitField<0, 8, IR::Reg> dest_reg_a;
26 BitField<8, 8, IR::Reg> src_reg_a;
27 BitField<20, 8, IR::Reg> src_reg_b;
28 BitField<36, 13, u64> cbuf_offset;
29 BitField<50, 3, u64> swizzle;
30};
31
32constexpr unsigned R = 1;
33constexpr unsigned G = 2;
34constexpr unsigned B = 4;
35constexpr unsigned A = 8;
36
37constexpr std::array RG_LUT{
38 R, //
39 G, //
40 B, //
41 A, //
42 R | G, //
43 R | A, //
44 G | A, //
45 B | A, //
46};
47
48constexpr std::array RGBA_LUT{
49 R | G | B, //
50 R | G | A, //
51 R | B | A, //
52 G | B | A, //
53 R | G | B | A, //
54};
55
56void CheckAlignment(IR::Reg reg, int alignment) {
57 if (!IR::IsAligned(reg, alignment)) {
58 throw NotImplementedException("Unaligned source register {}", reg);
59 }
60}
61
62template <typename... Args>
63IR::Value Composite(TranslatorVisitor& v, Args... regs) {
64 return v.ir.CompositeConstruct(v.F(regs)...);
65}
66
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)));
69}
70
71IR::Value Sample(TranslatorVisitor& v, u64 insn) {
72 const Encoding texs{insn};
73 const IR::U32 handle{v.ir.Imm32(static_cast<u32>(texs.cbuf_offset))};
74 const IR::F32 zero{v.ir.Imm32(0.0f)};
75 const IR::Reg reg_a{texs.src_reg_a};
76 const IR::Reg reg_b{texs.src_reg_b};
77 IR::TextureInstInfo info{};
78 if (texs.precision == Precision::F16) {
79 info.relaxed_precision.Assign(1);
80 }
81 switch (texs.encoding) {
82 case 0: // 1D.LZ
83 info.type.Assign(TextureType::Color1D);
84 return v.ir.ImageSampleExplicitLod(handle, v.F(reg_a), zero, {}, {}, info);
85 case 1: // 2D
86 info.type.Assign(TextureType::Color2D);
87 return v.ir.ImageSampleImplicitLod(handle, Composite(v, reg_a, reg_b), {}, {}, {}, info);
88 case 2: // 2D.LZ
89 info.type.Assign(TextureType::Color2D);
90 return v.ir.ImageSampleExplicitLod(handle, Composite(v, reg_a, reg_b), zero, {}, {}, info);
91 case 3: // 2D.LL
92 CheckAlignment(reg_a, 2);
93 info.type.Assign(TextureType::Color2D);
94 return v.ir.ImageSampleExplicitLod(handle, Composite(v, reg_a, reg_a + 1), v.F(reg_b), {},
95 {}, info);
96 case 4: // 2D.DC
97 CheckAlignment(reg_a, 2);
98 info.type.Assign(TextureType::Shadow2D);
99 return v.ir.ImageSampleDrefImplicitLod(handle, Composite(v, reg_a, reg_a + 1), v.F(reg_b),
100 {}, {}, {}, info);
101 case 5: // 2D.LL.DC
102 CheckAlignment(reg_a, 2);
103 CheckAlignment(reg_b, 2);
104 info.type.Assign(TextureType::Shadow2D);
105 return v.ir.ImageSampleDrefExplicitLod(handle, Composite(v, reg_a, reg_a + 1),
106 v.F(reg_b + 1), v.F(reg_b), {}, {}, info);
107 case 6: // 2D.LZ.DC
108 CheckAlignment(reg_a, 2);
109 info.type.Assign(TextureType::Shadow2D);
110 return v.ir.ImageSampleDrefExplicitLod(handle, Composite(v, reg_a, reg_a + 1), v.F(reg_b),
111 zero, {}, {}, info);
112 case 7: // ARRAY_2D
113 CheckAlignment(reg_a, 2);
114 info.type.Assign(TextureType::ColorArray2D);
115 return v.ir.ImageSampleImplicitLod(
116 handle, v.ir.CompositeConstruct(v.F(reg_a + 1), v.F(reg_b), ReadArray(v, v.X(reg_a))),
117 {}, {}, {}, info);
118 case 8: // ARRAY_2D.LZ
119 CheckAlignment(reg_a, 2);
120 info.type.Assign(TextureType::ColorArray2D);
121 return v.ir.ImageSampleExplicitLod(
122 handle, v.ir.CompositeConstruct(v.F(reg_a + 1), v.F(reg_b), ReadArray(v, v.X(reg_a))),
123 zero, {}, {}, info);
124 case 9: // ARRAY_2D.LZ.DC
125 CheckAlignment(reg_a, 2);
126 CheckAlignment(reg_b, 2);
127 info.type.Assign(TextureType::ShadowArray2D);
128 return v.ir.ImageSampleDrefExplicitLod(
129 handle, v.ir.CompositeConstruct(v.F(reg_a + 1), v.F(reg_b), ReadArray(v, v.X(reg_a))),
130 v.F(reg_b + 1), zero, {}, {}, info);
131 case 10: // 3D
132 CheckAlignment(reg_a, 2);
133 info.type.Assign(TextureType::Color3D);
134 return v.ir.ImageSampleImplicitLod(handle, Composite(v, reg_a, reg_a + 1, reg_b), {}, {},
135 {}, info);
136 case 11: // 3D.LZ
137 CheckAlignment(reg_a, 2);
138 info.type.Assign(TextureType::Color3D);
139 return v.ir.ImageSampleExplicitLod(handle, Composite(v, reg_a, reg_a + 1, reg_b), zero, {},
140 {}, info);
141 case 12: // CUBE
142 CheckAlignment(reg_a, 2);
143 info.type.Assign(TextureType::ColorCube);
144 return v.ir.ImageSampleImplicitLod(handle, Composite(v, reg_a, reg_a + 1, reg_b), {}, {},
145 {}, info);
146 case 13: // CUBE.LL
147 CheckAlignment(reg_a, 2);
148 CheckAlignment(reg_b, 2);
149 info.type.Assign(TextureType::ColorCube);
150 return v.ir.ImageSampleExplicitLod(handle, Composite(v, reg_a, reg_a + 1, reg_b),
151 v.F(reg_b + 1), {}, {}, info);
152 default:
153 throw NotImplementedException("Illegal encoding {}", texs.encoding.Value());
154 }
155}
156
157unsigned Swizzle(u64 insn) {
158 const Encoding texs{insn};
159 const size_t encoding{texs.swizzle};
160 if (texs.dest_reg_b == IR::Reg::RZ) {
161 if (encoding >= RG_LUT.size()) {
162 throw NotImplementedException("Illegal RG encoding {}", encoding);
163 }
164 return RG_LUT[encoding];
165 } else {
166 if (encoding >= RGBA_LUT.size()) {
167 throw NotImplementedException("Illegal RGBA encoding {}", encoding);
168 }
169 return RGBA_LUT[encoding];
170 }
171}
172
173IR::F32 Extract(TranslatorVisitor& v, const IR::Value& sample, unsigned component) {
174 const bool is_shadow{sample.Type() == IR::Type::F32};
175 if (is_shadow) {
176 const bool is_alpha{component == 3};
177 return is_alpha ? v.ir.Imm32(1.0f) : IR::F32{sample};
178 } else {
179 return IR::F32{v.ir.CompositeExtract(sample, component)};
180 }
181}
182
183IR::Reg RegStoreComponent32(u64 insn, unsigned index) {
184 const Encoding texs{insn};
185 switch (index) {
186 case 0:
187 return texs.dest_reg_a;
188 case 1:
189 CheckAlignment(texs.dest_reg_a, 2);
190 return texs.dest_reg_a + 1;
191 case 2:
192 return texs.dest_reg_b;
193 case 3:
194 CheckAlignment(texs.dest_reg_b, 2);
195 return texs.dest_reg_b + 1;
196 }
197 throw LogicError("Invalid store index {}", index);
198}
199
200void Store32(TranslatorVisitor& v, u64 insn, const IR::Value& sample) {
201 const unsigned swizzle{Swizzle(insn)};
202 unsigned store_index{0};
203 for (unsigned component = 0; component < 4; ++component) {
204 if (((swizzle >> component) & 1) == 0) {
205 continue;
206 }
207 const IR::Reg dest{RegStoreComponent32(insn, store_index)};
208 v.F(dest, Extract(v, sample, component));
209 ++store_index;
210 }
211}
212
213IR::U32 Pack(TranslatorVisitor& v, const IR::F32& lhs, const IR::F32& rhs) {
214 return v.ir.PackHalf2x16(v.ir.CompositeConstruct(lhs, rhs));
215}
216
217void Store16(TranslatorVisitor& v, u64 insn, const IR::Value& sample) {
218 const unsigned swizzle{Swizzle(insn)};
219 unsigned store_index{0};
220 std::array<IR::F32, 4> swizzled;
221 for (unsigned component = 0; component < 4; ++component) {
222 if (((swizzle >> component) & 1) == 0) {
223 continue;
224 }
225 swizzled[store_index] = Extract(v, sample, component);
226 ++store_index;
227 }
228 const IR::F32 zero{v.ir.Imm32(0.0f)};
229 const Encoding texs{insn};
230 switch (store_index) {
231 case 1:
232 v.X(texs.dest_reg_a, Pack(v, swizzled[0], zero));
233 break;
234 case 2:
235 case 3:
236 case 4:
237 v.X(texs.dest_reg_a, Pack(v, swizzled[0], swizzled[1]));
238 switch (store_index) {
239 case 2:
240 break;
241 case 3:
242 v.X(texs.dest_reg_b, Pack(v, swizzled[2], zero));
243 break;
244 case 4:
245 v.X(texs.dest_reg_b, Pack(v, swizzled[2], swizzled[3]));
246 break;
247 }
248 break;
249 }
250}
251} // Anonymous namespace
252
253void TranslatorVisitor::TEXS(u64 insn) {
254 const IR::Value sample{Sample(*this, insn)};
255 if (Encoding{insn}.precision == Precision::F32) {
256 Store32(*this, insn, sample);
257 } else {
258 Store16(*this, insn, sample);
259 }
260}
261
262} // namespace Shader::Maxwell