summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend/maxwell
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-03-08 18:31:53 -0300
committerGravatar ameerj2021-07-22 21:51:23 -0400
commitab463712474de5f99eec137a9c6233e55fe184f0 (patch)
tree30d79ac64dd03d5cfafd07c0c42c2baadc82de98 /src/shader_recompiler/frontend/maxwell
parentshader: Implement R2P (diff)
downloadyuzu-ab463712474de5f99eec137a9c6233e55fe184f0.tar.gz
yuzu-ab463712474de5f99eec137a9c6233e55fe184f0.tar.xz
yuzu-ab463712474de5f99eec137a9c6233e55fe184f0.zip
shader: Initial support for textures and TEX
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell')
-rw-r--r--src/shader_recompiler/frontend/maxwell/maxwell.inc4
-rw-r--r--src/shader_recompiler/frontend/maxwell/program.cpp1
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp8
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/texture_sample.cpp232
4 files changed, 235 insertions, 10 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/maxwell.inc b/src/shader_recompiler/frontend/maxwell/maxwell.inc
index 5d0b91598..f2a2ff331 100644
--- a/src/shader_recompiler/frontend/maxwell/maxwell.inc
+++ b/src/shader_recompiler/frontend/maxwell/maxwell.inc
@@ -249,8 +249,8 @@ INST(SULD, "SULD", "1110 1011 000- ----")
249INST(SURED, "SURED", "1110 1011 010- ----") 249INST(SURED, "SURED", "1110 1011 010- ----")
250INST(SUST, "SUST", "1110 1011 001- ----") 250INST(SUST, "SUST", "1110 1011 001- ----")
251INST(SYNC, "SYNC", "1111 0000 1111 1---") 251INST(SYNC, "SYNC", "1111 0000 1111 1---")
252INST(TEX, "TEX", "1100 00-- --11 1---") 252INST(TEX, "TEX", "1100 0--- ---- ----")
253INST(TEX_b, "TEX (b)", "1101 1110 1011 1---") 253INST(TEX_b, "TEX (b)", "1101 1110 10-- ----")
254INST(TEXS, "TEXS", "1101 -00- ---- ----") 254INST(TEXS, "TEXS", "1101 -00- ---- ----")
255INST(TLD, "TLD", "1101 1100 --11 1---") 255INST(TLD, "TLD", "1101 1100 --11 1---")
256INST(TLD_b, "TLD (b)", "1101 1101 --11 1---") 256INST(TLD_b, "TLD (b)", "1101 1101 --11 1---")
diff --git a/src/shader_recompiler/frontend/maxwell/program.cpp b/src/shader_recompiler/frontend/maxwell/program.cpp
index dbfc04f75..b270bbccd 100644
--- a/src/shader_recompiler/frontend/maxwell/program.cpp
+++ b/src/shader_recompiler/frontend/maxwell/program.cpp
@@ -62,6 +62,7 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo
62 Optimization::SsaRewritePass(function.post_order_blocks); 62 Optimization::SsaRewritePass(function.post_order_blocks);
63 } 63 }
64 Optimization::GlobalMemoryToStorageBufferPass(program); 64 Optimization::GlobalMemoryToStorageBufferPass(program);
65 Optimization::TexturePass(env, program);
65 for (IR::Function& function : functions) { 66 for (IR::Function& function : functions) {
66 Optimization::PostOrderInvoke(Optimization::ConstantPropagationPass, function); 67 Optimization::PostOrderInvoke(Optimization::ConstantPropagationPass, function);
67 Optimization::PostOrderInvoke(Optimization::DeadCodeEliminationPass, function); 68 Optimization::PostOrderInvoke(Optimization::DeadCodeEliminationPass, function);
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 fc6030e04..ff429c126 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp
@@ -585,14 +585,6 @@ void TranslatorVisitor::SYNC(u64) {
585 ThrowNotImplemented(Opcode::SYNC); 585 ThrowNotImplemented(Opcode::SYNC);
586} 586}
587 587
588void TranslatorVisitor::TEX(u64) {
589 ThrowNotImplemented(Opcode::TEX);
590}
591
592void TranslatorVisitor::TEX_b(u64) {
593 ThrowNotImplemented(Opcode::TEX_b);
594}
595
596void TranslatorVisitor::TEXS(u64) { 588void TranslatorVisitor::TEXS(u64) {
597 ThrowNotImplemented(Opcode::TEXS); 589 ThrowNotImplemented(Opcode::TEXS);
598} 590}
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_sample.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_sample.cpp
new file mode 100644
index 000000000..98d9f4c64
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_sample.cpp
@@ -0,0 +1,232 @@
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 <optional>
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 Blod : u64 {
15 None,
16 LZ,
17 LB,
18 LL,
19 INVALIDBLOD4,
20 INVALIDBLOD5,
21 LBA,
22 LLA,
23};
24
25enum class TextureType : u64 {
26 _1D,
27 ARRAY_1D,
28 _2D,
29 ARRAY_2D,
30 _3D,
31 ARRAY_3D,
32 CUBE,
33 ARRAY_CUBE,
34};
35
36Shader::TextureType GetType(TextureType type, bool dc) {
37 switch (type) {
38 case TextureType::_1D:
39 return dc ? Shader::TextureType::Shadow1D : Shader::TextureType::Color1D;
40 case TextureType::ARRAY_1D:
41 return dc ? Shader::TextureType::ShadowArray1D : Shader::TextureType::ColorArray1D;
42 case TextureType::_2D:
43 return dc ? Shader::TextureType::Shadow2D : Shader::TextureType::Color2D;
44 case TextureType::ARRAY_2D:
45 return dc ? Shader::TextureType::ShadowArray2D : Shader::TextureType::ColorArray2D;
46 case TextureType::_3D:
47 return dc ? Shader::TextureType::Shadow3D : Shader::TextureType::Color3D;
48 case TextureType::ARRAY_3D:
49 throw NotImplementedException("3D array texture type");
50 case TextureType::CUBE:
51 return dc ? Shader::TextureType::ShadowCube : Shader::TextureType::ColorCube;
52 case TextureType::ARRAY_CUBE:
53 return dc ? Shader::TextureType::ShadowArrayCube : Shader::TextureType::ColorArrayCube;
54 }
55 throw NotImplementedException("Invalid texture type {}", type);
56}
57
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)); }};
60 switch (type) {
61 case TextureType::_1D:
62 return v.F(reg);
63 case TextureType::ARRAY_1D:
64 return v.ir.CompositeConstruct(read_array(), v.F(reg + 1));
65 case TextureType::_2D:
66 return v.ir.CompositeConstruct(v.F(reg), v.F(reg + 1));
67 case TextureType::ARRAY_2D:
68 return v.ir.CompositeConstruct(read_array(), v.F(reg + 1), v.F(reg + 2));
69 case TextureType::_3D:
70 return v.ir.CompositeConstruct(v.F(reg), v.F(reg + 1), v.F(reg + 2));
71 case TextureType::ARRAY_3D:
72 throw NotImplementedException("3D array texture type");
73 case TextureType::CUBE:
74 return v.ir.CompositeConstruct(v.F(reg), v.F(reg + 1), v.F(reg + 2));
75 case TextureType::ARRAY_CUBE:
76 return v.ir.CompositeConstruct(read_array(), v.F(reg + 1), v.F(reg + 2), v.F(reg + 3));
77 }
78 throw NotImplementedException("Invalid texture type {}", type);
79}
80
81IR::F32 MakeLod(TranslatorVisitor& v, IR::Reg& reg, Blod blod) {
82 switch (blod) {
83 case Blod::None:
84 return v.ir.Imm32(0.0f);
85 case Blod::LZ:
86 return v.ir.Imm32(0.0f);
87 case Blod::LB:
88 case Blod::LL:
89 case Blod::LBA:
90 case Blod::LLA:
91 return v.F(reg++);
92 case Blod::INVALIDBLOD4:
93 case Blod::INVALIDBLOD5:
94 break;
95 }
96 throw NotImplementedException("Invalid blod {}", blod);
97}
98
99IR::Value MakeOffset(TranslatorVisitor& v, IR::Reg& reg, TextureType type) {
100 const IR::U32 value{v.X(reg++)};
101 switch (type) {
102 case TextureType::_1D:
103 case TextureType::ARRAY_1D:
104 return v.ir.BitFieldExtract(value, v.ir.Imm32(0), v.ir.Imm32(4));
105 case TextureType::_2D:
106 case TextureType::ARRAY_2D:
107 return v.ir.CompositeConstruct(v.ir.BitFieldExtract(value, v.ir.Imm32(0), v.ir.Imm32(4)),
108 v.ir.BitFieldExtract(value, v.ir.Imm32(4), v.ir.Imm32(4)));
109 case TextureType::_3D:
110 case TextureType::ARRAY_3D:
111 return v.ir.CompositeConstruct(v.ir.BitFieldExtract(value, v.ir.Imm32(0), v.ir.Imm32(4)),
112 v.ir.BitFieldExtract(value, v.ir.Imm32(4), v.ir.Imm32(4)),
113 v.ir.BitFieldExtract(value, v.ir.Imm32(8), v.ir.Imm32(4)));
114 case TextureType::CUBE:
115 case TextureType::ARRAY_CUBE:
116 throw NotImplementedException("Illegal offset on CUBE sample");
117 }
118 throw NotImplementedException("Invalid texture type {}", type);
119}
120
121bool HasExplicitLod(Blod blod) {
122 switch (blod) {
123 case Blod::LL:
124 case Blod::LLA:
125 case Blod::LZ:
126 return true;
127 default:
128 return false;
129 }
130}
131
132void Impl(TranslatorVisitor& v, u64 insn, bool aoffi, Blod blod, bool lc,
133 std::optional<u32> cbuf_offset) {
134 union {
135 u64 raw;
136 BitField<35, 1, u64> ndv;
137 BitField<49, 1, u64> nodep;
138 BitField<50, 1, u64> dc;
139 BitField<51, 3, IR::Pred> sparse_pred;
140 BitField<0, 8, IR::Reg> dest_reg;
141 BitField<8, 8, IR::Reg> coord_reg;
142 BitField<20, 8, IR::Reg> meta_reg;
143 BitField<28, 3, TextureType> type;
144 BitField<31, 4, u64> mask;
145 } const tex{insn};
146
147 if (lc) {
148 throw NotImplementedException("LC");
149 }
150 const IR::Value coords{MakeCoords(v, tex.coord_reg, tex.type)};
151
152 IR::Reg meta_reg{tex.meta_reg};
153 IR::Value handle;
154 IR::Value offset;
155 IR::F32 dref;
156 IR::F32 lod_clamp;
157 if (cbuf_offset) {
158 handle = v.ir.Imm32(*cbuf_offset);
159 } else {
160 handle = v.X(meta_reg++);
161 }
162 const IR::F32 lod{MakeLod(v, meta_reg, blod)};
163 if (aoffi) {
164 offset = MakeOffset(v, meta_reg, tex.type);
165 }
166 if (tex.dc != 0) {
167 dref = v.F(meta_reg++);
168 }
169 IR::TextureInstInfo info{};
170 info.type.Assign(GetType(tex.type, tex.dc != 0));
171 info.has_bias.Assign(blod == Blod::LB || blod == Blod::LBA ? 1 : 0);
172 info.has_lod_clamp.Assign(lc ? 1 : 0);
173
174 const IR::Value sample{[&]() -> IR::Value {
175 if (tex.dc == 0) {
176 if (HasExplicitLod(blod)) {
177 return v.ir.ImageSampleExplicitLod(handle, coords, lod, offset, lod_clamp, info);
178 } else {
179 return v.ir.ImageSampleImplicitLod(handle, coords, lod, offset, lod_clamp, info);
180 }
181 }
182 if (HasExplicitLod(blod)) {
183 return v.ir.ImageSampleDrefExplicitLod(handle, coords, dref, lod, offset, lod_clamp,
184 info);
185 } else {
186 return v.ir.ImageSampleDrefImplicitLod(handle, coords, dref, lod, offset, lod_clamp,
187 info);
188 }
189 }()};
190
191 for (int element = 0; element < 4; ++element) {
192 if (((tex.mask >> element) & 1) == 0) {
193 continue;
194 }
195 IR::F32 value;
196 if (tex.dc != 0) {
197 value = element < 3 ? IR::F32{sample} : v.ir.Imm32(1.0f);
198 } else {
199 value = IR::F32{v.ir.CompositeExtract(sample, element)};
200 }
201 v.F(tex.dest_reg + element, value);
202 }
203 if (tex.sparse_pred != IR::Pred::PT) {
204 v.ir.SetPred(tex.sparse_pred, v.ir.LogicalNot(v.ir.GetSparseFromOp(sample)));
205 }
206}
207} // Anonymous namespace
208
209void TranslatorVisitor::TEX(u64 insn) {
210 union {
211 u64 raw;
212 BitField<54, 1, u64> aoffi;
213 BitField<55, 3, Blod> blod;
214 BitField<58, 1, u64> lc;
215 BitField<36, 13, u64> cbuf_offset;
216 } const tex{insn};
217
218 Impl(*this, insn, tex.aoffi != 0, tex.blod, tex.lc != 0, static_cast<u32>(tex.cbuf_offset));
219}
220
221void TranslatorVisitor::TEX_b(u64 insn) {
222 union {
223 u64 raw;
224 BitField<36, 1, u64> aoffi;
225 BitField<37, 3, Blod> blod;
226 BitField<40, 1, u64> lc;
227 } const tex{insn};
228
229 Impl(*this, insn, tex.aoffi != 0, tex.blod, tex.lc != 0, std::nullopt);
230}
231
232} // namespace Shader::Maxwell