From 6cb690111a3f42a20be7149a69e6d6b3126f35c6 Mon Sep 17 00:00:00 2001 From: JPikachu Date: Sun, 23 Nov 2025 17:36:27 +0000 Subject: [PATCH] [vk] Fix storage image views to use identity swizzle per Vulkan spec Vulkan specs descriptorType-00336 requires that imageView members bound as VK_DESCRIPTOR_TYPE_STORAGE_IMAGE must have been created With the identity swizzle (https://docs.vulkan.org/spec/latest/chapters/descriptorsets.html#VUID-VkWriteDescriptorSet-descriptorType-00336). Identity swizzle means components.r/g/b/a are set to VK_COMPONENT_SWIZZLE_R/G/B/A (see "Table 2: Component Mappings Equivalent To VK_COMPONENT_SWIZZLE_IDENTITY") (https://docs.vulkan.org/spec/latest/chapters/resources.html#resources-image-views-identity-mappings). Previously Handle() was returned for typeless storage images, which could have non-identity swizzles like (r=R, g=ZERO, b=ZERO, a=ONE) as shown in validation error logs, violating this requirement. Based on reverted PR#321, with fixes to prevent regressions with incorrect colors in 'Sonic X Shadow Generations'. Aims to improve flickering in 'Pokemon Legends: ZA' and rendering issues in 'Trident's Tale' Co-authored-by: wildcard --- .../renderer_vulkan/vk_texture_cache.cpp | 16 ++++++++++++---- .../renderer_vulkan/vk_texture_cache.h | 4 ++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 136a11f78d..013b60569b 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -2165,14 +2165,22 @@ VkImageView ImageView::StorageView(Shader::TextureType texture_type, if (!image_handle) { return VK_NULL_HANDLE; } + if (!storage_views) { + storage_views = std::make_unique(); + } if (image_format == Shader::ImageFormat::Typeless) { - return Handle(texture_type); + auto& view = storage_views->typeless_views[static_cast(texture_type)]; + if (view) { + return *view; + } + const auto fmt_info = + MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, /*is_image=*/true, format); + const VkFormat vk_format = fmt_info.format; + view = MakeView(vk_format, VK_IMAGE_ASPECT_COLOR_BIT); + return *view; } const bool is_signed{image_format == Shader::ImageFormat::R8_SINT || image_format == Shader::ImageFormat::R16_SINT}; - if (!storage_views) { - storage_views = std::make_unique(); - } auto& views{is_signed ? storage_views->signeds : storage_views->unsigneds}; auto& view{views[static_cast(texture_type)]}; if (view) { diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index cd11cc8fc7..accf9330b9 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -266,6 +269,7 @@ private: struct StorageViews { std::array signeds; std::array unsigneds; + std::array typeless_views; }; [[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask);