From 8315f15cc1fe547e1d8f1430f80a090977deadab Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Mon, 24 Nov 2025 19:53:02 -0400 Subject: [PATCH] [surface, vk, pipeline, texture_cache] Texture Sampling Fix --- .../renderer_vulkan/pipeline_helper.h | 2 +- .../renderer_vulkan/vk_texture_cache.cpp | 35 ++++++++++++++----- .../renderer_vulkan/vk_texture_cache.h | 4 ++- src/video_core/surface.cpp | 33 +++++++++++++++++ src/video_core/surface.h | 1 + 5 files changed, 65 insertions(+), 10 deletions(-) diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h index b444307dcd..e97eeabf9a 100644 --- a/src/video_core/renderer_vulkan/pipeline_helper.h +++ b/src/video_core/renderer_vulkan/pipeline_helper.h @@ -192,7 +192,7 @@ inline void PushImageDescriptors(TextureCache& texture_cache, const VideoCommon::ImageViewId image_view_id{(views++)->id}; const VideoCommon::SamplerId sampler_id{*(samplers++)}; ImageView& image_view{texture_cache.GetImageView(image_view_id)}; - const VkImageView vk_image_view{image_view.SampledHandle(desc.type)}; + const VkImageView vk_image_view{image_view.SampledHandle(desc.type, desc.is_integer)}; const Sampler& sampler{texture_cache.GetSampler(sampler_id)}; const bool use_fallback_sampler{sampler.HasAddedAnisotropy() && !image_view.SupportsAnisotropy()}; diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 01090d3ce6..d7f1c84a7f 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -45,6 +45,7 @@ using VideoCore::Surface::BytesPerBlock; using VideoCore::Surface::HasAlpha; using VideoCore::Surface::IsPixelFormatASTC; using VideoCore::Surface::IsPixelFormatInteger; +using VideoCore::Surface::IntegerCompatibleFormat; using VideoCore::Surface::NormalizedCompatibleFormat; using VideoCore::Surface::SurfaceType; @@ -2223,22 +2224,40 @@ VkImageView ImageView::StorageView(Shader::TextureType texture_type, return *view; } -VkImageView ImageView::SampledHandle(Shader::TextureType texture_type) { - if (!IsPixelFormatInteger(format)) { - return Handle(texture_type); +VkImageView ImageView::SampledHandle(Shader::TextureType texture_type, bool use_integer_view) { + const auto type_index = static_cast(texture_type); + + if (use_integer_view || !IsPixelFormatInteger(format)) { + if (!use_integer_view || IsPixelFormatInteger(format)) { + return Handle(texture_type); + } + + const auto compatible_integer = IntegerCompatibleFormat(format); + if (!compatible_integer) { + return Handle(texture_type); + } + auto& int_view = sampled_integer_views[type_index]; + if (int_view) { + return *int_view; + } + const auto format_info = + MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, *compatible_integer); + int_view = CreateSampledView(texture_type, format_info.format); + return *int_view; } + const auto compatible_format = NormalizedCompatibleFormat(format); if (!compatible_format) { return Handle(texture_type); } - auto& view = sampled_float_views[static_cast(texture_type)]; - if (view) { - return *view; + auto& float_view = sampled_float_views[type_index]; + if (float_view) { + return *float_view; } const auto format_info = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, *compatible_format); - view = CreateSampledView(texture_type, format_info.format); - return *view; + float_view = CreateSampledView(texture_type, format_info.format); + return *float_view; } bool ImageView::IsRescaled() const noexcept { diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 010c72964d..e9209ff427 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -247,7 +247,8 @@ public: return *image_views[static_cast(texture_type)]; } - [[nodiscard]] VkImageView SampledHandle(Shader::TextureType texture_type); + [[nodiscard]] VkImageView SampledHandle(Shader::TextureType texture_type, + bool use_integer_view); [[nodiscard]] VkImage ImageHandle() const noexcept { return image_handle; @@ -284,6 +285,7 @@ private: std::array image_views; std::array sampled_float_views; + std::array sampled_integer_views; std::array, Shader::NUM_TEXTURE_TYPES> view_layer_counts{}; std::unique_ptr storage_views; vk::ImageView depth_view; diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp index 3590ed0226..63c9980391 100644 --- a/src/video_core/surface.cpp +++ b/src/video_core/surface.cpp @@ -443,6 +443,39 @@ std::optional NormalizedCompatibleFormat(PixelFormat format) { } } +std::optional IntegerCompatibleFormat(PixelFormat format) { + switch (format) { + case PixelFormat::A8B8G8R8_UNORM: + return PixelFormat::A8B8G8R8_UINT; + case PixelFormat::A8B8G8R8_SNORM: + return PixelFormat::A8B8G8R8_SINT; + case PixelFormat::A2B10G10R10_UNORM: + return PixelFormat::A2B10G10R10_UINT; + case PixelFormat::R8_UNORM: + return PixelFormat::R8_UINT; + case PixelFormat::R8_SNORM: + return PixelFormat::R8_SINT; + case PixelFormat::R8G8_UNORM: + return PixelFormat::R8G8_UINT; + case PixelFormat::R8G8_SNORM: + return PixelFormat::R8G8_SINT; + case PixelFormat::R16_UNORM: + return PixelFormat::R16_UINT; + case PixelFormat::R16_SNORM: + return PixelFormat::R16_SINT; + case PixelFormat::R16G16_UNORM: + return PixelFormat::R16G16_UINT; + case PixelFormat::R16G16_SNORM: + return PixelFormat::R16G16_SINT; + case PixelFormat::R16G16B16A16_UNORM: + return PixelFormat::R16G16B16A16_UINT; + case PixelFormat::R16G16B16A16_SNORM: + return PixelFormat::R16G16B16A16_SINT; + default: + return std::nullopt; + } +} + size_t PixelComponentSizeBitsInteger(PixelFormat format) { switch (format) { case PixelFormat::A8B8G8R8_SINT: diff --git a/src/video_core/surface.h b/src/video_core/surface.h index b613b0d9cc..b619f529d1 100644 --- a/src/video_core/surface.h +++ b/src/video_core/surface.h @@ -520,6 +520,7 @@ bool IsPixelFormatInteger(PixelFormat format); bool IsPixelFormatSignedInteger(PixelFormat format); std::optional NormalizedCompatibleFormat(PixelFormat format); +std::optional IntegerCompatibleFormat(PixelFormat format); size_t PixelComponentSizeBitsInteger(PixelFormat format);