diff --git a/src/common/settings.h b/src/common/settings.h index d6d3b5e26d..58ce0b5f11 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -69,6 +69,7 @@ SWITCHABLE(AstcRecompression, true); SWITCHABLE(AudioMode, true); SWITCHABLE(CpuBackend, true); SWITCHABLE(CpuAccuracy, true); +SWITCHABLE(FormatReinterpretation, true); SWITCHABLE(FullscreenMode, true); SWITCHABLE(GpuAccuracy, true); SWITCHABLE(Language, true); @@ -451,6 +452,11 @@ struct Values { AstcRecompression::Uncompressed, "astc_recompression", Category::RendererAdvanced}; + SwitchableSetting format_reinterpretation{ + linkage, + FormatReinterpretation::Disabled, + "format_reinterpretation", + Category::RendererAdvanced}; SwitchableSetting vram_usage_mode{linkage, VramUsageMode::Conservative, "vram_usage_mode", diff --git a/src/common/settings_common.h b/src/common/settings_common.h index af16ec692b..a33f97d04e 100644 --- a/src/common/settings_common.h +++ b/src/common/settings_common.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index 33daa55519..761f73913c 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h @@ -151,6 +151,7 @@ ENUM(AppletMode, HLE, LLE); ENUM(SpirvOptimizeMode, Never, OnLoad, Always); ENUM(GpuOverclock, Low, Medium, High) ENUM(TemperatureUnits, Celsius, Fahrenheit) +ENUM(FormatReinterpretation, Disabled, R32UintToR32Sfloat, R32SintToR32Uint, R32SfloatToR32Sint) // Shader Float Controls behavior modes // These control how floating-point denormals and special values are handled in shaders diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 111ca62fd2..03603f1ee3 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -2122,11 +2122,34 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI const auto format_info = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format); VkFormat view_format = format_info.format; - // TODO: Format reinterpretation toggles (per-game settings) - // Some games incorrectly use integer formats with float samplers: - // - R32_UINT with texture() instead of texelFetch() causes flickering - // - R8_UINT with LINEAR filter causes validation errors - // Cannot auto-detect: need user toggles to force format reinterpretation + // Format reinterpretation for games with incorrect format usage + // Some games declare render targets as R32_UINT but sample them + // as float textures. + const auto reinterpretation_mode = Settings::values.format_reinterpretation.GetValue(); + if (reinterpretation_mode != Settings::FormatReinterpretation::Disabled) { + switch (reinterpretation_mode) { + case Settings::FormatReinterpretation::R32UintToR32Sfloat: + if (view_format == VK_FORMAT_R32_UINT) { + view_format = VK_FORMAT_R32_SFLOAT; + LOG_DEBUG(Render_Vulkan, "Reinterpreting R32_UINT -> R32_SFLOAT for texture view"); + } + break; + case Settings::FormatReinterpretation::R32SintToR32Uint: + if (view_format == VK_FORMAT_R32_SINT) { + view_format = VK_FORMAT_R32_UINT; + LOG_DEBUG(Render_Vulkan, "Reinterpreting R32_SINT -> R32_UINT for texture view"); + } + break; + case Settings::FormatReinterpretation::R32SfloatToR32Sint: + if (view_format == VK_FORMAT_R32_SFLOAT) { + view_format = VK_FORMAT_R32_SINT; + LOG_DEBUG(Render_Vulkan, "Reinterpreting R32_SFLOAT -> R32_SINT for texture view"); + } + break; + default: + break; + } + } if (ImageUsageFlags(format_info, format) != image.UsageFlags()) { LOG_WARNING(Render_Vulkan,