From 197929d967f587502256fd52c0c5121781fd0e47 Mon Sep 17 00:00:00 2001 From: goldislead <69987043+goldislead@users.noreply.github.com> Date: Sun, 9 Aug 2026 18:34:00 -0700 Subject: [PATCH] [D3D12] Fall back to point sampling for non-filterable formats Matches Vulkan. Co-authored-by: Herman S. <429230+has207@users.noreply.github.com> --- src/xenia/gpu/d3d12/d3d12_texture_cache.cc | 48 +++++++++++++++++++++- src/xenia/gpu/d3d12/d3d12_texture_cache.h | 4 ++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/xenia/gpu/d3d12/d3d12_texture_cache.cc b/src/xenia/gpu/d3d12/d3d12_texture_cache.cc index 94d2e038c..998a9a640 100644 --- a/src/xenia/gpu/d3d12/d3d12_texture_cache.cc +++ b/src/xenia/gpu/d3d12/d3d12_texture_cache.cc @@ -140,6 +140,32 @@ bool D3D12TextureCache::Initialize() { } scaled_resolve_heap_count_ = 0; + // GetSamplerParameters drops samplers for non-filterable formats. + for (uint32_t i = 0; i < xe::countof(host_formats_); ++i) { + const HostFormat& host_format = host_formats_[i]; + uint64_t format_bit = uint64_t(1) << i; + if (host_format.dxgi_format_unsigned != DXGI_FORMAT_UNKNOWN) { + D3D12_FEATURE_DATA_FORMAT_SUPPORT format_support = { + host_format.dxgi_format_unsigned}; + if (SUCCEEDED(device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, + &format_support, + sizeof(format_support))) && + (format_support.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE)) { + host_filterable_unsigned_ |= format_bit; + } + } + if (host_format.dxgi_format_signed != DXGI_FORMAT_UNKNOWN) { + D3D12_FEATURE_DATA_FORMAT_SUPPORT format_support = { + host_format.dxgi_format_signed}; + if (SUCCEEDED(device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, + &format_support, + sizeof(format_support))) && + (format_support.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE)) { + host_filterable_signed_ |= format_bit; + } + } + } + // Create the loading root signature. D3D12_ROOT_PARAMETER root_parameters[3]; // Parameter 0 is constants (changed multiple times when untiling). @@ -795,7 +821,6 @@ D3D12TextureCache::SamplerParameters D3D12TextureCache::GetSamplerParameters( 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 @@ -820,6 +845,27 @@ D3D12TextureCache::SamplerParameters D3D12TextureCache::GetSamplerParameters( } parameters.mip_base_map = mip_base_map; + // Fall back to point sampling if the host formats don't report + // D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE. + if (parameters.mag_linear || parameters.min_linear || parameters.mip_linear || + parameters.aniso_filter != xenos::AnisoFilter::kDisabled) { + TextureKey texture_key; + uint8_t texture_swizzled_signs; + BindingInfoFromFetchConstant(fetch, texture_key, &texture_swizzled_signs); + uint64_t format_bit = + texture_key.is_valid ? uint64_t(1) << uint32_t(texture_key.format) : 0; + if (!texture_key.is_valid || + (texture_util::IsAnySignNotSigned(texture_swizzled_signs) && + (host_filterable_unsigned_ & format_bit) == 0) || + (texture_util::IsAnySignSigned(texture_swizzled_signs) && + (host_filterable_signed_ & format_bit) == 0)) { + parameters.mag_linear = 0; + parameters.min_linear = 0; + parameters.mip_linear = 0; + parameters.aniso_filter = xenos::AnisoFilter::kDisabled; + } + } + return parameters; } diff --git a/src/xenia/gpu/d3d12/d3d12_texture_cache.h b/src/xenia/gpu/d3d12/d3d12_texture_cache.h index 599d42fb1..4e1c34bd3 100644 --- a/src/xenia/gpu/d3d12/d3d12_texture_cache.h +++ b/src/xenia/gpu/d3d12/d3d12_texture_cache.h @@ -821,6 +821,10 @@ class D3D12TextureCache final : public TextureCache { D3D12CommandProcessor& command_processor_; bool bindless_resources_used_; + // Bits per format, for checking if the host format should be point-filtered. + uint64_t host_filterable_unsigned_ = 0; + uint64_t host_filterable_signed_ = 0; + Microsoft::WRL::ComPtr load_root_signature_; std::array, kLoadShaderCount> load_pipelines_;