diff options
| author | 2023-11-17 22:29:12 -0500 | |
|---|---|---|
| committer | 2023-11-17 22:29:12 -0500 | |
| commit | 9343b81afd5132aa41f50fe033faca4f9713b8cf (patch) | |
| tree | 2d173ac3aa11d08da5bb13dde5d12688648867ce /src | |
| parent | Merge pull request #12053 from german77/no_functional (diff) | |
| download | yuzu-9343b81afd5132aa41f50fe033faca4f9713b8cf.tar.gz yuzu-9343b81afd5132aa41f50fe033faca4f9713b8cf.tar.xz yuzu-9343b81afd5132aa41f50fe033faca4f9713b8cf.zip | |
shader_recompiler: add byteswap pattern workaround for Nvidia
Diffstat (limited to '')
| -rw-r--r-- | src/shader_recompiler/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/maxwell/translate_program.cpp | 1 | ||||
| -rw-r--r-- | src/shader_recompiler/ir_opt/passes.h | 1 | ||||
| -rw-r--r-- | src/shader_recompiler/ir_opt/vendor_workaround_pass.cpp | 79 |
4 files changed, 82 insertions, 0 deletions
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index 83b763447..19db17c6d 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt | |||
| @@ -231,6 +231,7 @@ add_library(shader_recompiler STATIC | |||
| 231 | ir_opt/rescaling_pass.cpp | 231 | ir_opt/rescaling_pass.cpp |
| 232 | ir_opt/ssa_rewrite_pass.cpp | 232 | ir_opt/ssa_rewrite_pass.cpp |
| 233 | ir_opt/texture_pass.cpp | 233 | ir_opt/texture_pass.cpp |
| 234 | ir_opt/vendor_workaround_pass.cpp | ||
| 234 | ir_opt/verification_pass.cpp | 235 | ir_opt/verification_pass.cpp |
| 235 | object_pool.h | 236 | object_pool.h |
| 236 | precompiled_headers.h | 237 | precompiled_headers.h |
diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp index 928b35561..8fac6bad3 100644 --- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp | |||
| @@ -310,6 +310,7 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo | |||
| 310 | } | 310 | } |
| 311 | Optimization::CollectShaderInfoPass(env, program); | 311 | Optimization::CollectShaderInfoPass(env, program); |
| 312 | Optimization::LayerPass(program, host_info); | 312 | Optimization::LayerPass(program, host_info); |
| 313 | Optimization::VendorWorkaroundPass(program); | ||
| 313 | 314 | ||
| 314 | CollectInterpolationInfo(env, program); | 315 | CollectInterpolationInfo(env, program); |
| 315 | AddNVNStorageBuffers(program); | 316 | AddNVNStorageBuffers(program); |
diff --git a/src/shader_recompiler/ir_opt/passes.h b/src/shader_recompiler/ir_opt/passes.h index 629d18fa1..d4d5285e5 100644 --- a/src/shader_recompiler/ir_opt/passes.h +++ b/src/shader_recompiler/ir_opt/passes.h | |||
| @@ -26,6 +26,7 @@ void SsaRewritePass(IR::Program& program); | |||
| 26 | void PositionPass(Environment& env, IR::Program& program); | 26 | void PositionPass(Environment& env, IR::Program& program); |
| 27 | void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo& host_info); | 27 | void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo& host_info); |
| 28 | void LayerPass(IR::Program& program, const HostTranslateInfo& host_info); | 28 | void LayerPass(IR::Program& program, const HostTranslateInfo& host_info); |
| 29 | void VendorWorkaroundPass(IR::Program& program); | ||
| 29 | void VerificationPass(const IR::Program& program); | 30 | void VerificationPass(const IR::Program& program); |
| 30 | 31 | ||
| 31 | // Dual Vertex | 32 | // Dual Vertex |
diff --git a/src/shader_recompiler/ir_opt/vendor_workaround_pass.cpp b/src/shader_recompiler/ir_opt/vendor_workaround_pass.cpp new file mode 100644 index 000000000..08c658cb8 --- /dev/null +++ b/src/shader_recompiler/ir_opt/vendor_workaround_pass.cpp | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "shader_recompiler/frontend/ir/basic_block.h" | ||
| 5 | #include "shader_recompiler/frontend/ir/ir_emitter.h" | ||
| 6 | #include "shader_recompiler/frontend/ir/value.h" | ||
| 7 | #include "shader_recompiler/ir_opt/passes.h" | ||
| 8 | |||
| 9 | namespace Shader::Optimization { | ||
| 10 | |||
| 11 | namespace { | ||
| 12 | void AddingByteSwapsWorkaround(IR::Block& block, IR::Inst& inst) { | ||
| 13 | /* | ||
| 14 | * Workaround for an NVIDIA bug seen in Super Mario RPG | ||
| 15 | * | ||
| 16 | * We are looking for this pattern: | ||
| 17 | * %lhs_bfe = BitFieldUExtract %factor_a, #0, #16 | ||
| 18 | * %lhs_mul = IMul32 %lhs_bfe, %factor_b // potentially optional? | ||
| 19 | * %lhs_shl = ShiftLeftLogical32 %lhs_mul, #16 | ||
| 20 | * %rhs_bfe = BitFieldUExtract %factor_a, #16, #16 | ||
| 21 | * %result = IAdd32 %lhs_shl, %rhs_bfe | ||
| 22 | * | ||
| 23 | * And replacing the IAdd32 with a BitwiseOr32 | ||
| 24 | * %result = BitwiseOr32 %lhs_shl, %rhs_bfe | ||
| 25 | * | ||
| 26 | */ | ||
| 27 | IR::Inst* const lhs_shl{inst.Arg(0).TryInstRecursive()}; | ||
| 28 | IR::Inst* const rhs_bfe{inst.Arg(1).TryInstRecursive()}; | ||
| 29 | if (!lhs_shl || !rhs_bfe) { | ||
| 30 | return; | ||
| 31 | } | ||
| 32 | if (lhs_shl->GetOpcode() != IR::Opcode::ShiftLeftLogical32 || | ||
| 33 | lhs_shl->Arg(1) != IR::Value{16U}) { | ||
| 34 | return; | ||
| 35 | } | ||
| 36 | if (rhs_bfe->GetOpcode() != IR::Opcode::BitFieldUExtract || rhs_bfe->Arg(1) != IR::Value{16U} || | ||
| 37 | rhs_bfe->Arg(2) != IR::Value{16U}) { | ||
| 38 | return; | ||
| 39 | } | ||
| 40 | IR::Inst* const lhs_mul{lhs_shl->Arg(0).TryInstRecursive()}; | ||
| 41 | if (!lhs_mul) { | ||
| 42 | return; | ||
| 43 | } | ||
| 44 | const bool lhs_mul_optional{lhs_mul->GetOpcode() == IR::Opcode::BitFieldUExtract}; | ||
| 45 | if (lhs_mul->GetOpcode() != IR::Opcode::IMul32 && | ||
| 46 | lhs_mul->GetOpcode() != IR::Opcode::BitFieldUExtract) { | ||
| 47 | return; | ||
| 48 | } | ||
| 49 | IR::Inst* const lhs_bfe{lhs_mul_optional ? lhs_mul : lhs_mul->Arg(0).TryInstRecursive()}; | ||
| 50 | if (!lhs_bfe) { | ||
| 51 | return; | ||
| 52 | } | ||
| 53 | if (lhs_bfe->GetOpcode() != IR::Opcode::BitFieldUExtract) { | ||
| 54 | return; | ||
| 55 | } | ||
| 56 | if (lhs_bfe->Arg(1) != IR::Value{0U} || lhs_bfe->Arg(2) != IR::Value{16U}) { | ||
| 57 | return; | ||
| 58 | } | ||
| 59 | IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; | ||
| 60 | inst.ReplaceUsesWith(ir.BitwiseOr(IR::U32{inst.Arg(0)}, IR::U32{inst.Arg(1)})); | ||
| 61 | } | ||
| 62 | |||
| 63 | } // Anonymous namespace | ||
| 64 | |||
| 65 | void VendorWorkaroundPass(IR::Program& program) { | ||
| 66 | for (IR::Block* const block : program.post_order_blocks) { | ||
| 67 | for (IR::Inst& inst : block->Instructions()) { | ||
| 68 | switch (inst.GetOpcode()) { | ||
| 69 | case IR::Opcode::IAdd32: | ||
| 70 | AddingByteSwapsWorkaround(*block, inst); | ||
| 71 | break; | ||
| 72 | default: | ||
| 73 | break; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | } // namespace Shader::Optimization | ||