mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-01 04:24:21 +00:00
[vulkan] Sampled linear images fallback to nearest
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
#include "shader_recompiler/shader_info.h"
|
#include "shader_recompiler/shader_info.h"
|
||||||
#include "video_core/renderer_vulkan/vk_texture_cache.h"
|
#include "video_core/renderer_vulkan/vk_texture_cache.h"
|
||||||
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
|
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
|
||||||
|
#include "video_core/surface.h"
|
||||||
#include "video_core/texture_cache/types.h"
|
#include "video_core/texture_cache/types.h"
|
||||||
#include "video_core/vulkan_common/vulkan_device.h"
|
#include "video_core/vulkan_common/vulkan_device.h"
|
||||||
|
|
||||||
@@ -235,8 +236,12 @@ inline void PushImageDescriptors(TextureCache& texture_cache,
|
|||||||
const Sampler& sampler{texture_cache.GetSampler(sampler_id)};
|
const Sampler& sampler{texture_cache.GetSampler(sampler_id)};
|
||||||
const bool use_fallback_sampler{sampler.HasAddedAnisotropy() &&
|
const bool use_fallback_sampler{sampler.HasAddedAnisotropy() &&
|
||||||
!image_view.SupportsAnisotropy()};
|
!image_view.SupportsAnisotropy()};
|
||||||
const VkSampler vk_sampler{use_fallback_sampler ? sampler.HandleWithDefaultAnisotropy()
|
VkSampler vk_sampler{use_fallback_sampler ? sampler.HandleWithDefaultAnisotropy()
|
||||||
: sampler.Handle()};
|
: sampler.Handle()};
|
||||||
|
if (sampler.HasLinearFiltering() &&
|
||||||
|
VideoCore::Surface::IsPixelFormatInteger(image_view.format)) {
|
||||||
|
vk_sampler = sampler.HandleWithNearestFilter();
|
||||||
|
}
|
||||||
guest_descriptor_queue.AddSampledImage(vk_image_view, vk_sampler);
|
guest_descriptor_queue.AddSampledImage(vk_image_view, vk_sampler);
|
||||||
const bool element_rescaled{texture_cache.IsRescaling(image_view)};
|
const bool element_rescaled{texture_cache.IsRescaling(image_view)};
|
||||||
is_rescaled |= element_rescaled;
|
is_rescaled |= element_rescaled;
|
||||||
|
|||||||
@@ -2326,20 +2326,28 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t
|
|||||||
// Some games have samplers with garbage. Sanitize them here.
|
// Some games have samplers with garbage. Sanitize them here.
|
||||||
const f32 max_anisotropy = std::clamp(tsc.MaxAnisotropy(), 1.0f, 16.0f);
|
const f32 max_anisotropy = std::clamp(tsc.MaxAnisotropy(), 1.0f, 16.0f);
|
||||||
|
|
||||||
const auto create_sampler = [&](const f32 anisotropy) {
|
const VkFilter mag_filter{MaxwellToVK::Sampler::Filter(tsc.mag_filter)};
|
||||||
|
const VkFilter min_filter{MaxwellToVK::Sampler::Filter(tsc.min_filter)};
|
||||||
|
const VkSamplerMipmapMode mipmap_mode{MaxwellToVK::Sampler::MipmapMode(tsc.mipmap_filter)};
|
||||||
|
const bool has_linear_filtering{mag_filter == VK_FILTER_LINEAR ||
|
||||||
|
min_filter == VK_FILTER_LINEAR ||
|
||||||
|
mipmap_mode == VK_SAMPLER_MIPMAP_MODE_LINEAR};
|
||||||
|
|
||||||
|
const auto create_sampler = [&](const f32 anisotropy, bool force_nearest) {
|
||||||
return device.GetLogical().CreateSampler(VkSamplerCreateInfo{
|
return device.GetLogical().CreateSampler(VkSamplerCreateInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||||
.pNext = pnext,
|
.pNext = pnext,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.magFilter = MaxwellToVK::Sampler::Filter(tsc.mag_filter),
|
.magFilter = force_nearest ? VK_FILTER_NEAREST : mag_filter,
|
||||||
.minFilter = MaxwellToVK::Sampler::Filter(tsc.min_filter),
|
.minFilter = force_nearest ? VK_FILTER_NEAREST : min_filter,
|
||||||
.mipmapMode = MaxwellToVK::Sampler::MipmapMode(tsc.mipmap_filter),
|
.mipmapMode = force_nearest ? VK_SAMPLER_MIPMAP_MODE_NEAREST : mipmap_mode,
|
||||||
.addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, tsc.mag_filter),
|
.addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, tsc.mag_filter),
|
||||||
.addressModeV = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_v, tsc.mag_filter),
|
.addressModeV = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_v, tsc.mag_filter),
|
||||||
.addressModeW = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_p, tsc.mag_filter),
|
.addressModeW = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_p, tsc.mag_filter),
|
||||||
.mipLodBias = tsc.LodBias(),
|
.mipLodBias = tsc.LodBias(),
|
||||||
.anisotropyEnable = static_cast<VkBool32>(anisotropy > 1.0f ? VK_TRUE : VK_FALSE),
|
.anisotropyEnable =
|
||||||
.maxAnisotropy = anisotropy,
|
static_cast<VkBool32>(!force_nearest && anisotropy > 1.0f ? VK_TRUE : VK_FALSE),
|
||||||
|
.maxAnisotropy = force_nearest ? 1.0f : anisotropy,
|
||||||
.compareEnable = tsc.depth_compare_enabled,
|
.compareEnable = tsc.depth_compare_enabled,
|
||||||
.compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func),
|
.compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func),
|
||||||
.minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.MinLod(),
|
.minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.MinLod(),
|
||||||
@@ -2350,11 +2358,18 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
sampler = create_sampler(max_anisotropy);
|
sampler = create_sampler(max_anisotropy, false);
|
||||||
|
|
||||||
const f32 max_anisotropy_default = static_cast<f32>(1U << tsc.max_anisotropy);
|
const f32 max_anisotropy_default = static_cast<f32>(1U << tsc.max_anisotropy);
|
||||||
if (max_anisotropy > max_anisotropy_default) {
|
if (max_anisotropy > max_anisotropy_default) {
|
||||||
sampler_default_anisotropy = create_sampler(max_anisotropy_default);
|
sampler_default_anisotropy = create_sampler(max_anisotropy_default, false);
|
||||||
|
}
|
||||||
|
if (has_linear_filtering) {
|
||||||
|
// Integer-format image views can never be linearly filtered
|
||||||
|
// (VUID-vkCmdDraw*-magFilter-04553); this sampler is cached purely from the guest's TSC,
|
||||||
|
// decoupled from whichever ImageView it ends up paired with, so build a nearest-forced
|
||||||
|
// fallback here for callers to swap to when the paired view turns out to be integer.
|
||||||
|
sampler_nearest = create_sampler(1.0f, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -406,9 +406,18 @@ public:
|
|||||||
return static_cast<bool>(sampler_default_anisotropy);
|
return static_cast<bool>(sampler_default_anisotropy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] VkSampler HandleWithNearestFilter() const noexcept {
|
||||||
|
return *sampler_nearest;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool HasLinearFiltering() const noexcept {
|
||||||
|
return static_cast<bool>(sampler_nearest);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vk::Sampler sampler;
|
vk::Sampler sampler;
|
||||||
vk::Sampler sampler_default_anisotropy;
|
vk::Sampler sampler_default_anisotropy;
|
||||||
|
vk::Sampler sampler_nearest;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextureCacheParams {
|
struct TextureCacheParams {
|
||||||
|
|||||||
Reference in New Issue
Block a user