Browse Source

[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 <wildcard@eden-emu.dev>
pull/3101/head
JPikachu 1 month ago
committed by crueter
parent
commit
6cb690111a
  1. 16
      src/video_core/renderer_vulkan/vk_texture_cache.cpp
  2. 4
      src/video_core/renderer_vulkan/vk_texture_cache.h

16
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<StorageViews>();
}
if (image_format == Shader::ImageFormat::Typeless) {
return Handle(texture_type);
auto& view = storage_views->typeless_views[static_cast<size_t>(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<StorageViews>();
}
auto& views{is_signed ? storage_views->signeds : storage_views->unsigneds};
auto& view{views[static_cast<size_t>(texture_type)]};
if (view) {

4
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<vk::ImageView, Shader::NUM_TEXTURE_TYPES> signeds;
std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> unsigneds;
std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> typeless_views;
};
[[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask);

Loading…
Cancel
Save