diff options
Diffstat (limited to 'src/shader_recompiler/frontend')
3 files changed, 182 insertions, 10 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/maxwell.inc b/src/shader_recompiler/frontend/maxwell/maxwell.inc index b47fb9c2e..c759bd4d4 100644 --- a/src/shader_recompiler/frontend/maxwell/maxwell.inc +++ b/src/shader_recompiler/frontend/maxwell/maxwell.inc | |||
| @@ -261,8 +261,8 @@ INST(TLDS, "TLDS", "1101 -01- ---- ----") | |||
| 261 | INST(TMML, "TMML", "1101 1111 0101 1---") | 261 | INST(TMML, "TMML", "1101 1111 0101 1---") |
| 262 | INST(TMML_b, "TMML (b)", "1101 1111 0110 0---") | 262 | INST(TMML_b, "TMML (b)", "1101 1111 0110 0---") |
| 263 | INST(TXA, "TXA", "1101 1111 0100 0---") | 263 | INST(TXA, "TXA", "1101 1111 0100 0---") |
| 264 | INST(TXD, "TXD", "1101 1110 0011 10--") | 264 | INST(TXD, "TXD", "1101 1110 00-- ----") |
| 265 | INST(TXD_b, "TXD (b)", "1101 1110 0111 10--") | 265 | INST(TXD_b, "TXD (b)", "1101 1110 01-- ----") |
| 266 | INST(TXQ, "TXQ", "1101 1111 0100 1---") | 266 | INST(TXQ, "TXQ", "1101 1111 0100 1---") |
| 267 | INST(TXQ_b, "TXQ (b)", "1101 1111 0101 0---") | 267 | INST(TXQ_b, "TXQ (b)", "1101 1111 0101 0---") |
| 268 | INST(VABSDIFF, "VABSDIFF", "0101 0100 ---- ----") | 268 | INST(VABSDIFF, "VABSDIFF", "0101 0100 ---- ----") |
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 9f5ea7775..ba526817a 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp | |||
| @@ -317,14 +317,6 @@ void TranslatorVisitor::TXA(u64) { | |||
| 317 | ThrowNotImplemented(Opcode::TXA); | 317 | ThrowNotImplemented(Opcode::TXA); |
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | void TranslatorVisitor::TXD(u64) { | ||
| 321 | ThrowNotImplemented(Opcode::TXD); | ||
| 322 | } | ||
| 323 | |||
| 324 | void TranslatorVisitor::TXD_b(u64) { | ||
| 325 | ThrowNotImplemented(Opcode::TXD_b); | ||
| 326 | } | ||
| 327 | |||
| 328 | void TranslatorVisitor::VABSDIFF(u64) { | 320 | void TranslatorVisitor::VABSDIFF(u64) { |
| 329 | ThrowNotImplemented(Opcode::VABSDIFF); | 321 | ThrowNotImplemented(Opcode::VABSDIFF); |
| 330 | } | 322 | } |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gradient.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gradient.cpp new file mode 100644 index 000000000..00768e167 --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_gradient.cpp | |||
| @@ -0,0 +1,180 @@ | |||
| 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 | |||
| 15 | enum class TextureType : u64 { | ||
| 16 | _1D, | ||
| 17 | ARRAY_1D, | ||
| 18 | _2D, | ||
| 19 | ARRAY_2D, | ||
| 20 | _3D, | ||
| 21 | ARRAY_3D, | ||
| 22 | CUBE, | ||
| 23 | ARRAY_CUBE, | ||
| 24 | }; | ||
| 25 | |||
| 26 | Shader::TextureType GetType(TextureType type, bool dc) { | ||
| 27 | switch (type) { | ||
| 28 | case TextureType::_1D: | ||
| 29 | return dc ? Shader::TextureType::Shadow1D : Shader::TextureType::Color1D; | ||
| 30 | case TextureType::ARRAY_1D: | ||
| 31 | return dc ? Shader::TextureType::ShadowArray1D : Shader::TextureType::ColorArray1D; | ||
| 32 | case TextureType::_2D: | ||
| 33 | return dc ? Shader::TextureType::Shadow2D : Shader::TextureType::Color2D; | ||
| 34 | case TextureType::ARRAY_2D: | ||
| 35 | return dc ? Shader::TextureType::ShadowArray2D : Shader::TextureType::ColorArray2D; | ||
| 36 | case TextureType::_3D: | ||
| 37 | return dc ? Shader::TextureType::Shadow3D : Shader::TextureType::Color3D; | ||
| 38 | case TextureType::ARRAY_3D: | ||
| 39 | throw NotImplementedException("3D array texture type"); | ||
| 40 | case TextureType::CUBE: | ||
| 41 | return dc ? Shader::TextureType::ShadowCube : Shader::TextureType::ColorCube; | ||
| 42 | case TextureType::ARRAY_CUBE: | ||
| 43 | return dc ? Shader::TextureType::ShadowArrayCube : Shader::TextureType::ColorArrayCube; | ||
| 44 | } | ||
| 45 | throw NotImplementedException("Invalid texture type {}", type); | ||
| 46 | } | ||
| 47 | |||
| 48 | IR::Value MakeOffset(TranslatorVisitor& v, IR::Reg reg, bool has_lod_clamp) { | ||
| 49 | const IR::U32 value{v.X(reg)}; | ||
| 50 | const u32 base = has_lod_clamp ? 12 : 16; | ||
| 51 | return v.ir.CompositeConstruct( | ||
| 52 | v.ir.BitFieldExtract(value, v.ir.Imm32(base), v.ir.Imm32(4), true), | ||
| 53 | v.ir.BitFieldExtract(value, v.ir.Imm32(base + 4), v.ir.Imm32(4), true)); | ||
| 54 | } | ||
| 55 | |||
| 56 | void Impl(TranslatorVisitor& v, u64 insn, bool is_bindless) { | ||
| 57 | union { | ||
| 58 | u64 raw; | ||
| 59 | BitField<49, 1, u64> nodep; | ||
| 60 | BitField<35, 1, u64> aoffi; | ||
| 61 | BitField<50, 1, u64> lc; | ||
| 62 | BitField<51, 3, IR::Pred> sparse_pred; | ||
| 63 | BitField<0, 8, IR::Reg> dest_reg; | ||
| 64 | BitField<8, 8, IR::Reg> coord_reg; | ||
| 65 | BitField<20, 8, IR::Reg> derivate_reg; | ||
| 66 | BitField<28, 3, TextureType> type; | ||
| 67 | BitField<31, 4, u64> mask; | ||
| 68 | BitField<36, 13, u64> cbuf_offset; | ||
| 69 | } const txd{insn}; | ||
| 70 | |||
| 71 | const bool has_lod_clamp = txd.lc != 0; | ||
| 72 | if (has_lod_clamp) { | ||
| 73 | throw NotImplementedException("TXD.LC - CLAMP is not implemented"); | ||
| 74 | } | ||
| 75 | |||
| 76 | IR::Value coords; | ||
| 77 | u32 num_derivates; | ||
| 78 | IR::Reg base_reg = txd.coord_reg; | ||
| 79 | IR::Reg last_reg; | ||
| 80 | IR::Value handle; | ||
| 81 | if (!is_bindless) { | ||
| 82 | handle = v.ir.Imm32(static_cast<u32>(txd.cbuf_offset.Value() * 4)); | ||
| 83 | } else { | ||
| 84 | handle = v.X(base_reg++); | ||
| 85 | } | ||
| 86 | |||
| 87 | const auto read_array{[&]() -> IR::F32 { | ||
| 88 | return v.ir.ConvertUToF(32, 16, | ||
| 89 | v.ir.BitFieldExtract(v.X(last_reg), v.ir.Imm32(0), | ||
| 90 | v.ir.Imm32(has_lod_clamp ? 12 : 16))); | ||
| 91 | }}; | ||
| 92 | switch (txd.type) { | ||
| 93 | case TextureType::_1D: { | ||
| 94 | coords = v.F(base_reg); | ||
| 95 | num_derivates = 1; | ||
| 96 | last_reg = base_reg + 1; | ||
| 97 | break; | ||
| 98 | } | ||
| 99 | case TextureType::ARRAY_1D: { | ||
| 100 | last_reg = base_reg + 1; | ||
| 101 | coords = v.ir.CompositeConstruct(v.F(base_reg), read_array()); | ||
| 102 | num_derivates = 1; | ||
| 103 | break; | ||
| 104 | } | ||
| 105 | case TextureType::_2D: { | ||
| 106 | last_reg = base_reg + 2; | ||
| 107 | coords = v.ir.CompositeConstruct(v.F(base_reg), v.F(base_reg + 1)); | ||
| 108 | num_derivates = 2; | ||
| 109 | break; | ||
| 110 | } | ||
| 111 | case TextureType::ARRAY_2D: { | ||
| 112 | last_reg = base_reg + 2; | ||
| 113 | coords = v.ir.CompositeConstruct(v.F(base_reg), v.F(base_reg + 1), read_array()); | ||
| 114 | num_derivates = 2; | ||
| 115 | break; | ||
| 116 | } | ||
| 117 | default: | ||
| 118 | throw NotImplementedException("Invalid texture type"); | ||
| 119 | } | ||
| 120 | |||
| 121 | const IR::Reg derivate_reg{txd.derivate_reg}; | ||
| 122 | IR::Value derivates; | ||
| 123 | switch (num_derivates) { | ||
| 124 | case 1: { | ||
| 125 | derivates = v.ir.CompositeConstruct(v.F(derivate_reg), v.F(derivate_reg + 1)); | ||
| 126 | break; | ||
| 127 | } | ||
| 128 | case 2: { | ||
| 129 | derivates = v.ir.CompositeConstruct(v.F(derivate_reg), v.F(derivate_reg + 1), | ||
| 130 | v.F(derivate_reg + 2), v.F(derivate_reg + 3)); | ||
| 131 | break; | ||
| 132 | } | ||
| 133 | default: | ||
| 134 | throw NotImplementedException("Invalid texture type"); | ||
| 135 | } | ||
| 136 | |||
| 137 | IR::Value offset; | ||
| 138 | if (txd.aoffi != 0) { | ||
| 139 | offset = MakeOffset(v, last_reg, has_lod_clamp); | ||
| 140 | } | ||
| 141 | |||
| 142 | IR::F32 lod_clamp; | ||
| 143 | if (has_lod_clamp) { | ||
| 144 | const IR::F32 conv4_8fixp_f = v.ir.Imm32(Common::BitCast<f32>(0x3b800000U)); | ||
| 145 | const IR::F32 tmp = v.ir.ConvertUToF( | ||
| 146 | 32, 16, v.ir.BitFieldExtract(v.X(last_reg), v.ir.Imm32(20), v.ir.Imm32(12))); | ||
| 147 | lod_clamp = v.ir.FPMul(tmp, conv4_8fixp_f); | ||
| 148 | } | ||
| 149 | |||
| 150 | IR::TextureInstInfo info{}; | ||
| 151 | info.type.Assign(GetType(txd.type, false)); | ||
| 152 | info.num_derivates.Assign(num_derivates); | ||
| 153 | info.has_lod_clamp.Assign(has_lod_clamp ? 1 : 0); | ||
| 154 | const IR::Value sample{[&]() -> IR::Value { | ||
| 155 | return v.ir.ImageGradient(handle, coords, derivates, offset, lod_clamp, info); | ||
| 156 | }()}; | ||
| 157 | |||
| 158 | IR::Reg dest_reg{txd.dest_reg}; | ||
| 159 | for (size_t element = 0; element < 4; ++element) { | ||
| 160 | if (((txd.mask >> element) & 1) == 0) { | ||
| 161 | continue; | ||
| 162 | } | ||
| 163 | v.F(dest_reg, IR::F32{v.ir.CompositeExtract(sample, element)}); | ||
| 164 | ++dest_reg; | ||
| 165 | } | ||
| 166 | if (txd.sparse_pred != IR::Pred::PT) { | ||
| 167 | v.ir.SetPred(txd.sparse_pred, v.ir.LogicalNot(v.ir.GetSparseFromOp(sample))); | ||
| 168 | } | ||
| 169 | } | ||
| 170 | } // Anonymous namespace | ||
| 171 | |||
| 172 | void TranslatorVisitor::TXD(u64 insn) { | ||
| 173 | Impl(*this, insn, false); | ||
| 174 | } | ||
| 175 | |||
| 176 | void TranslatorVisitor::TXD_b(u64 insn) { | ||
| 177 | Impl(*this, insn, true); | ||
| 178 | } | ||
| 179 | |||
| 180 | } // namespace Shader::Maxwell | ||