diff options
| author | 2021-03-08 18:31:53 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:23 -0400 | |
| commit | ab463712474de5f99eec137a9c6233e55fe184f0 (patch) | |
| tree | 30d79ac64dd03d5cfafd07c0c42c2baadc82de98 /src/shader_recompiler/frontend/maxwell | |
| parent | shader: Implement R2P (diff) | |
| download | yuzu-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')
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- ----") | |||
| 249 | INST(SURED, "SURED", "1110 1011 010- ----") | 249 | INST(SURED, "SURED", "1110 1011 010- ----") |
| 250 | INST(SUST, "SUST", "1110 1011 001- ----") | 250 | INST(SUST, "SUST", "1110 1011 001- ----") |
| 251 | INST(SYNC, "SYNC", "1111 0000 1111 1---") | 251 | INST(SYNC, "SYNC", "1111 0000 1111 1---") |
| 252 | INST(TEX, "TEX", "1100 00-- --11 1---") | 252 | INST(TEX, "TEX", "1100 0--- ---- ----") |
| 253 | INST(TEX_b, "TEX (b)", "1101 1110 1011 1---") | 253 | INST(TEX_b, "TEX (b)", "1101 1110 10-- ----") |
| 254 | INST(TEXS, "TEXS", "1101 -00- ---- ----") | 254 | INST(TEXS, "TEXS", "1101 -00- ---- ----") |
| 255 | INST(TLD, "TLD", "1101 1100 --11 1---") | 255 | INST(TLD, "TLD", "1101 1100 --11 1---") |
| 256 | INST(TLD_b, "TLD (b)", "1101 1101 --11 1---") | 256 | INST(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 | ||
| 588 | void TranslatorVisitor::TEX(u64) { | ||
| 589 | ThrowNotImplemented(Opcode::TEX); | ||
| 590 | } | ||
| 591 | |||
| 592 | void TranslatorVisitor::TEX_b(u64) { | ||
| 593 | ThrowNotImplemented(Opcode::TEX_b); | ||
| 594 | } | ||
| 595 | |||
| 596 | void TranslatorVisitor::TEXS(u64) { | 588 | void 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 | |||
| 12 | namespace Shader::Maxwell { | ||
| 13 | namespace { | ||
| 14 | enum class Blod : u64 { | ||
| 15 | None, | ||
| 16 | LZ, | ||
| 17 | LB, | ||
| 18 | LL, | ||
| 19 | INVALIDBLOD4, | ||
| 20 | INVALIDBLOD5, | ||
| 21 | LBA, | ||
| 22 | LLA, | ||
| 23 | }; | ||
| 24 | |||
| 25 | enum 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 | |||
| 36 | Shader::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 | |||
| 58 | IR::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 | |||
| 81 | IR::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 | |||
| 99 | IR::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 | |||
| 121 | bool 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 | |||
| 132 | void 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 | |||
| 209 | void 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 | |||
| 221 | void 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 | ||