[TEST] Adjustments to compareEnable detection for depth samplers

This commit is contained in:
CamilleLaVey
2026-04-24 23:18:59 -04:00
parent 5f3d0d3a9c
commit 865ff42a32
4 changed files with 101 additions and 10 deletions

View File

@@ -14,6 +14,7 @@
#include "shader_recompiler/backend/spirv/emit_spirv.h"
#include "shader_recompiler/shader_info.h"
#include "video_core/renderer_vulkan/vk_texture_cache.h"
#include "video_core/renderer_vulkan/maxwell_to_vk.h"
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
#include "video_core/texture_cache/types.h"
#include "video_core/vulkan_common/vulkan_device.h"
@@ -197,8 +198,29 @@ inline void PushImageDescriptors(TextureCache& texture_cache,
const Sampler& sampler{texture_cache.GetSampler(sampler_id)};
const bool use_fallback_sampler{sampler.HasAddedAnisotropy() &&
!image_view.SupportsAnisotropy()};
const VkSampler vk_sampler{use_fallback_sampler ? sampler.HandleWithDefaultAnisotropy()
: sampler.Handle()};
// In case sampler requires depth comparison but the format doesn't support it.
bool need_no_compare = false;
if (sampler.HasCompareEnabled()) {
const auto& device = texture_cache.runtime.device;
const auto fmt_info = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true,
image_view.format);
if (!device.IsFormatSupported(fmt_info.format,
VK_FORMAT_FEATURE_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT,
FormatType::Optimal)) {
need_no_compare = true;
}
}
VkSampler vk_sampler;
if (need_no_compare) {
vk_sampler = use_fallback_sampler ?
sampler.HandleNoCompareWithDefaultAnisotropy()
: sampler.HandleNoCompare();
} else {
vk_sampler = use_fallback_sampler ? sampler.HandleWithDefaultAnisotropy()
: sampler.Handle();
}
guest_descriptor_queue.AddSampledImage(vk_image_view, vk_sampler);
rescaling.PushTexture(texture_cache.IsRescaling(image_view));
}

View File

@@ -2284,8 +2284,28 @@ VkImageView ImageView::StorageView(Shader::TextureType texture_type,
storage_views.emplace();
auto& views{is_signed ? storage_views->signeds : storage_views->unsigneds};
auto& view{views[size_t(texture_type)]};
if (!view)
view = MakeView(Format(image_format), VK_IMAGE_ASPECT_COLOR_BIT);
if (!view) {
static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
.pNext = nullptr,
.usage = VK_IMAGE_USAGE_STORAGE_BIT,
};
view = device->GetLogical().CreateImageView({
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.pNext = &storage_image_view_usage_create_info,
.flags = 0,
.image = image_handle,
.viewType = ImageViewType(type),
.format = Format(image_format),
.components{
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
.g = VK_COMPONENT_SWIZZLE_IDENTITY,
.b = VK_COMPONENT_SWIZZLE_IDENTITY,
.a = VK_COMPONENT_SWIZZLE_IDENTITY,
},
.subresourceRange = MakeSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, range),
});
}
return *view;
}
return VK_NULL_HANDLE;
@@ -2350,7 +2370,7 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t
// Some games have samplers with garbage. Sanitize them here.
const f32 max_anisotropy = std::clamp(tsc.MaxAnisotropy(), 1.0f, 16.0f);
const auto create_sampler = [&](const f32 anisotropy) {
const auto create_sampler = [&](const f32 anisotropy, bool compare_enable) {
return device.GetLogical().CreateSampler(VkSamplerCreateInfo{
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
.pNext = pnext,
@@ -2364,7 +2384,7 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t
.mipLodBias = tsc.LodBias(),
.anisotropyEnable = static_cast<VkBool32>(anisotropy > 1.0f ? VK_TRUE : VK_FALSE),
.maxAnisotropy = anisotropy,
.compareEnable = tsc.depth_compare_enabled,
.compareEnable = compare_enable ? VK_TRUE : VK_FALSE,
.compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func),
.minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.MinLod(),
.maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.MaxLod(),
@@ -2374,11 +2394,23 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t
});
};
sampler = create_sampler(max_anisotropy);
compare_enable = static_cast<bool>(tsc.depth_compare_enabled);
sampler = create_sampler(max_anisotropy, compare_enable);
if (compare_enable) {
sampler_no_compare = create_sampler(max_anisotropy, false);
} else {
sampler_no_compare = sampler;
}
const f32 max_anisotropy_default = static_cast<f32>(1U << tsc.max_anisotropy);
if (max_anisotropy > max_anisotropy_default) {
sampler_default_anisotropy = create_sampler(max_anisotropy_default);
sampler_default_anisotropy = create_sampler(max_anisotropy_default, compare_enable);
if (compare_enable) {
sampler_no_compare_default_anisotropy = create_sampler(max_anisotropy_default, false);
} else {
sampler_no_compare_default_anisotropy = sampler_default_anisotropy;
}
}
}

View File

@@ -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 2019 yuzu Emulator Project
@@ -408,9 +408,28 @@ public:
return static_cast<bool>(sampler_default_anisotropy);
}
[[nodiscard]] bool HasCompareEnabled() const noexcept {
return compare_enable;
}
[[nodiscard]] VkSampler HandleNoCompare() const noexcept {
return sampler_no_compare ? *sampler_no_compare : *sampler;
}
[[nodiscard]] VkSampler HandleNoCompareWithDefaultAnisotropy() const noexcept {
if (sampler_no_compare_default_anisotropy)
return *sampler_no_compare_default_anisotropy;
if (sampler_default_anisotropy)
return *sampler_default_anisotropy;
return *sampler;
}
private:
vk::Sampler sampler;
vk::Sampler sampler_default_anisotropy;
vk::Sampler sampler_no_compare;
vk::Sampler sampler_no_compare_default_anisotropy;
bool compare_enable = false;
};
struct TextureCacheParams {

View File

@@ -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 2020 yuzu Emulator Project
@@ -7,6 +7,7 @@
#include <fmt/ranges.h>
#include "common/assert.h"
#include "common/logging.h"
#include "common/settings.h"
#include "video_core/surface.h"
#include "video_core/texture_cache/format_lookup_table.h"
@@ -130,6 +131,23 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept {
size.width *= NumSamplesX(config.msaa_mode);
size.height *= NumSamplesY(config.msaa_mode);
}
{
u32 max_dim = std::max({size.width, size.height, size.depth});
if (max_dim == 0) {
max_dim = 1;
}
u32 max_mip_levels = 1;
while (max_dim > 1) {
max_dim >>= 1;
++max_mip_levels;
}
if (resources.levels > static_cast<s32>(max_mip_levels)) {
LOG_WARNING(HW_GPU, "Clamping mip levels from {} to {} for size {}x{}x{}",
resources.levels, max_mip_levels, size.width, size.height, size.depth);
resources.levels = static_cast<s32>(max_mip_levels);
}
}
if (type != ImageType::Linear) {
// FIXME: Call this without passing *this
layer_stride = CalculateLayerStride(*this);