From 1a9613705db68df47ce13fa469abb032c182f247 Mon Sep 17 00:00:00 2001 From: goldislead <69987043+goldislead@users.noreply.github.com> Date: Fri, 6 Feb 2026 00:02:37 -0800 Subject: [PATCH] Rework max anisotropy override to sampler creation (D3D12/Vulkan) Revert ac6fd65 fetch additions and implement context-sensitive AF override. --- src/xenia/gpu/d3d12/d3d12_texture_cache.cc | 48 +++++++++++++------- src/xenia/gpu/dxbc_shader_translator.cc | 6 +-- src/xenia/gpu/gpu_flags.cc | 6 ++- src/xenia/gpu/spirv_shader_translator.cc | 6 +-- src/xenia/gpu/vulkan/vulkan_texture_cache.cc | 20 ++++++-- 5 files changed, 52 insertions(+), 34 deletions(-) diff --git a/src/xenia/gpu/d3d12/d3d12_texture_cache.cc b/src/xenia/gpu/d3d12/d3d12_texture_cache.cc index 9e31d8aa5..d05efb80e 100644 --- a/src/xenia/gpu/d3d12/d3d12_texture_cache.cc +++ b/src/xenia/gpu/d3d12/d3d12_texture_cache.cc @@ -696,41 +696,55 @@ D3D12TextureCache::SamplerParameters D3D12TextureCache::GetSamplerParameters( parameters.border_color = xenos::BorderColor::k_ABGR_Black; } - uint32_t mip_min_level; - texture_util::GetSubresourcesFromFetchConstant(fetch, nullptr, nullptr, - nullptr, nullptr, nullptr, - &mip_min_level, nullptr); + uint32_t mip_min_level, mip_max_level; + texture_util::GetSubresourcesFromFetchConstant( + fetch, nullptr, nullptr, nullptr, nullptr, nullptr, &mip_min_level, + &mip_max_level); parameters.mip_min_level = mip_min_level; + bool has_mips = mip_max_level > mip_min_level; + xenos::TextureFilter mag_filter = + binding.mag_filter == xenos::TextureFilter::kUseFetchConst + ? fetch.mag_filter + : binding.mag_filter; + xenos::TextureFilter min_filter = + binding.min_filter == xenos::TextureFilter::kUseFetchConst + ? fetch.min_filter + : binding.min_filter; + xenos::TextureFilter mip_filter = + binding.mip_filter == xenos::TextureFilter::kUseFetchConst + ? fetch.mip_filter + : binding.mip_filter; + bool min_mag_linear = (mag_filter == xenos::TextureFilter::kLinear) && + (min_filter == xenos::TextureFilter::kLinear); + bool mip_filter_bilinear_or_trilinear = + mip_filter == xenos::TextureFilter::kPoint || + mip_filter == xenos::TextureFilter::kLinear; + bool mip_base_map = mip_filter == xenos::TextureFilter::kBaseMap; // high cache miss count here, prefetch fetch earlier // TODO(Triang3l): Disable filtering for texture formats not supporting it. xenos::AnisoFilter aniso_filter = binding.aniso_filter == xenos::AnisoFilter::kUseFetchConst ? fetch.aniso_filter : binding.aniso_filter; + // Apply anisotropic override, but only for mipmapped textures + // that are already using bilinear/trilinear filtering. + if (cvars::anisotropic_override > -1 && cvars::anisotropic_override < 6 && + has_mips && !mip_base_map && min_mag_linear && + mip_filter_bilinear_or_trilinear) { + aniso_filter = xenos::AnisoFilter(cvars::anisotropic_override); + } aniso_filter = std::min(aniso_filter, xenos::AnisoFilter::kMax_16_1); parameters.aniso_filter = aniso_filter; - xenos::TextureFilter mip_filter = - binding.mip_filter == xenos::TextureFilter::kUseFetchConst - ? fetch.mip_filter - : binding.mip_filter; if (aniso_filter != xenos::AnisoFilter::kDisabled) { parameters.mag_linear = 1; parameters.min_linear = 1; parameters.mip_linear = 1; } else { - xenos::TextureFilter mag_filter = - binding.mag_filter == xenos::TextureFilter::kUseFetchConst - ? fetch.mag_filter - : binding.mag_filter; parameters.mag_linear = mag_filter == xenos::TextureFilter::kLinear; - xenos::TextureFilter min_filter = - binding.min_filter == xenos::TextureFilter::kUseFetchConst - ? fetch.min_filter - : binding.min_filter; parameters.min_linear = min_filter == xenos::TextureFilter::kLinear; parameters.mip_linear = mip_filter == xenos::TextureFilter::kLinear; } - parameters.mip_base_map = mip_filter == xenos::TextureFilter::kBaseMap; + parameters.mip_base_map = mip_base_map; return parameters; } diff --git a/src/xenia/gpu/dxbc_shader_translator.cc b/src/xenia/gpu/dxbc_shader_translator.cc index 42eac768c..0faa3c5bb 100644 --- a/src/xenia/gpu/dxbc_shader_translator.cc +++ b/src/xenia/gpu/dxbc_shader_translator.cc @@ -17,7 +17,6 @@ #include "xenia/base/cvar.h" #include "xenia/base/math.h" #include "xenia/gpu/dxbc_shader.h" -#include "xenia/gpu/gpu_flags.h" #include "xenia/gpu/xenos.h" #include "xenia/ui/graphics_provider.h" @@ -1379,10 +1378,7 @@ void DxbcShaderTranslator::PostTranslation() { shader_binding.mag_filter = translator_binding.mag_filter; shader_binding.min_filter = translator_binding.min_filter; shader_binding.mip_filter = translator_binding.mip_filter; - shader_binding.aniso_filter = - cvars::anisotropic_override > -1 && cvars::anisotropic_override < 6 - ? xenos::AnisoFilter(cvars::anisotropic_override) - : translator_binding.aniso_filter; + shader_binding.aniso_filter = translator_binding.aniso_filter; } } } diff --git a/src/xenia/gpu/gpu_flags.cc b/src/xenia/gpu/gpu_flags.cc index 417a8cb01..0859842af 100644 --- a/src/xenia/gpu/gpu_flags.cc +++ b/src/xenia/gpu/gpu_flags.cc @@ -72,8 +72,10 @@ DEFINE_int32( "GPU"); DEFINE_int32(anisotropic_override, -1, - "Level of anisotropic filtering enforced on all texture fetch " - "instructions.\n" + "Forces anisotropic filtering (AF) for eligible textures.\n" + "Higher values keep textures sharper at oblique angles at the " + "cost of GPU bandwidth, though most GPUs handle up to 16x fine.\n" + "In rare cases, forcing AF can introduce visual artifacts.\n" " -1 = No override\n" " 0 = Disable anisotropic filtering\n" " 1 = Force 1x anisotropic filtering\n" diff --git a/src/xenia/gpu/spirv_shader_translator.cc b/src/xenia/gpu/spirv_shader_translator.cc index 7736ca6ee..9046adb2a 100644 --- a/src/xenia/gpu/spirv_shader_translator.cc +++ b/src/xenia/gpu/spirv_shader_translator.cc @@ -17,7 +17,6 @@ #include "xenia/base/assert.h" #include "xenia/base/math.h" #include "xenia/base/string_buffer.h" -#include "xenia/gpu/gpu_flags.h" #include "xenia/gpu/spirv_shader.h" namespace xe { @@ -808,10 +807,7 @@ void SpirvShaderTranslator::PostTranslation() { shader_binding.mag_filter = translator_binding.mag_filter; shader_binding.min_filter = translator_binding.min_filter; shader_binding.mip_filter = translator_binding.mip_filter; - shader_binding.aniso_filter = - cvars::anisotropic_override > -1 && cvars::anisotropic_override < 6 - ? xenos::AnisoFilter(cvars::anisotropic_override) - : translator_binding.aniso_filter; + shader_binding.aniso_filter = translator_binding.aniso_filter; } } } diff --git a/src/xenia/gpu/vulkan/vulkan_texture_cache.cc b/src/xenia/gpu/vulkan/vulkan_texture_cache.cc index 056ccd68c..807610b6d 100644 --- a/src/xenia/gpu/vulkan/vulkan_texture_cache.cc +++ b/src/xenia/gpu/vulkan/vulkan_texture_cache.cc @@ -680,14 +680,24 @@ VulkanTextureCache::SamplerParameters VulkanTextureCache::GetSamplerParameters( binding.aniso_filter == xenos::AnisoFilter::kUseFetchConst ? fetch.aniso_filter : binding.aniso_filter; - parameters.aniso_filter = std::min(aniso_filter, max_anisotropy_); parameters.mip_base_map = mip_filter == xenos::TextureFilter::kBaseMap; - uint32_t mip_min_level; - texture_util::GetSubresourcesFromFetchConstant(fetch, nullptr, nullptr, - nullptr, nullptr, nullptr, - &mip_min_level, nullptr); + uint32_t mip_min_level, mip_max_level; + texture_util::GetSubresourcesFromFetchConstant( + fetch, nullptr, nullptr, nullptr, nullptr, nullptr, &mip_min_level, + &mip_max_level); parameters.mip_min_level = mip_min_level; + bool has_mips = mip_max_level > mip_min_level; + // Apply anisotropic override, but only for mipmapped textures + // that are already using bilinear/trilinear filtering. + if (cvars::anisotropic_override > -1 && cvars::anisotropic_override < 6 && + has_mips && !parameters.mip_base_map && parameters.mag_linear && + parameters.min_linear && + (mip_filter == xenos::TextureFilter::kPoint || + mip_filter == xenos::TextureFilter::kLinear)) { + aniso_filter = xenos::AnisoFilter(cvars::anisotropic_override); + } + parameters.aniso_filter = std::min(aniso_filter, max_anisotropy_); return parameters; }