diff --git a/src/shader_recompiler/frontend/ir/attribute.h b/src/shader_recompiler/frontend/ir/attribute.h index 943c8d673f..4adf980949 100644 --- a/src/shader_recompiler/frontend/ir/attribute.h +++ b/src/shader_recompiler/frontend/ir/attribute.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -240,6 +240,14 @@ constexpr size_t NUM_FIXEDFNCTEXTURE = 10; return attribute >= Attribute::Generic0X && attribute <= Attribute::Generic31X; } +[[nodiscard]] inline bool IsLegacyAttribute(Attribute attribute) noexcept { + return (attribute >= Attribute::ColorFrontDiffuseR && + attribute <= Attribute::ColorBackSpecularA) || + attribute == Attribute::FogCoordinate || + (attribute >= Attribute::FixedFncTexture0S && + attribute <= Attribute::FixedFncTexture9Q); +} + [[nodiscard]] inline u32 GenericAttributeIndex(Attribute attribute) { if (!IsGeneric(attribute)) throw InvalidArgument("Attribute is not generic {}", attribute); diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp index e3745ce084..d4990af7a6 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/load_store_attribute.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -163,12 +166,24 @@ void TranslatorVisitor::IPA(u64 insn) { const IR::Attribute attribute{ipa.attribute}; IR::F32 value{is_indexed ? ir.GetAttributeIndexed(X(ipa.index_reg)) : ir.GetAttribute(attribute)}; - if (IR::IsGeneric(attribute)) { - const ProgramHeader& sph{env.SPH()}; - const u32 attr_index{IR::GenericAttributeIndex(attribute)}; - const u32 element{static_cast(attribute) % 4}; - const std::array input_map{sph.ps.GenericInputMap(attr_index)}; - const bool is_perspective{input_map[element] == Shader::PixelImap::Perspective}; + const bool is_legacy{IR::IsLegacyAttribute(attribute)}; + if (IR::IsGeneric(attribute) || is_legacy) { + bool is_perspective{is_legacy && + ipa.interpolation_mode != InterpolationMode::Sc}; + if (!is_legacy) { + const ProgramHeader& sph{env.SPH()}; + const u32 attr_index{IR::GenericAttributeIndex(attribute)}; + const std::array input_map{sph.ps.GenericInputMap(attr_index)}; + Shader::PixelImap effective_imap{Shader::PixelImap::Unused}; + for (const Shader::PixelImap component : input_map) { + if (component != Shader::PixelImap::Unused) { + effective_imap = component; + break; + } + } + is_perspective = effective_imap == Shader::PixelImap::Perspective || + effective_imap == Shader::PixelImap::Unused; + } if (is_perspective) { const IR::F32 position_w{ir.GetAttribute(IR::Attribute::PositionW)}; value = ir.FPMul(value, position_w); diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp index f156192c13..705f20850a 100644 --- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp @@ -132,13 +132,7 @@ void AddNVNStorageBuffers(IR::Program& program) { } } -bool IsLegacyAttribute(IR::Attribute attribute) { - return (attribute >= IR::Attribute::ColorFrontDiffuseR && - attribute <= IR::Attribute::ColorBackSpecularA) || - attribute == IR::Attribute::FogCoordinate || - (attribute >= IR::Attribute::FixedFncTexture0S && - attribute <= IR::Attribute::FixedFncTexture9Q); -} +using IR::IsLegacyAttribute; //rescoped to attribute.h to make it visible in load_store_attribute.cpp IPA std::map GenerateLegacyToGenericMappings( const VaryingState& state, std::queue unused_generics,