diff options
| author | kraibse <33869366+kraibse@users.noreply.github.com> | 2026-10-31 15:53:50 +0100 |
|---|---|---|
| committer | kraibse <33869366+kraibse@users.noreply.github.com> | 2026-11-01 17:29:56 +0100 |
| commit | a855e8373f5575fddd172ec7ffc56a8c3904c3fb (patch) | |
| tree | f486d7e29a6d72b16af773bafdf7c38394ed8047 /src | |
| parent | 139b7e5efb7c4181f14e987706eef26ca1f327c0 (diff) | |
vulkan: back large sparse images normally on AMD
Lazy Switch 2 sparse regions made the texture cache create large images
with no memory bound and sample them. AMD's drivers crash shortly after
the first such draw (builds 49+). Skip the unbacked-image paths on AMD
drivers; images get regular backing as in build 47.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 10 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_device.h | 8 |
2 files changed, 15 insertions, 3 deletions
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 5ba36feee9..3294af9c22 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -172,7 +172,10 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { // A large image over Switch 2 sparse blocks nobody has written (title 1's terrain layer pools, 2.9 // GB of R8/RG16/R16 that stay empty in the attract demo) is all zeros: it gets no device memory // until a write makes the texture cache replace it. -[[nodiscard]] bool IsUnwrittenSparse(const ImageInfo& info, GPUVAddr gpu_addr) { +[[nodiscard]] bool IsUnwrittenSparse(const Device& device, const ImageInfo& info, GPUVAddr gpu_addr) { + if (!device.CanUseUnbackedSparseImages()) { + return false; + } constexpr u32 MinSize = 32U << 20; const u32 size = VideoCommon::CalculateGuestSizeInBytes(info); return size >= MinSize && info.type != ImageType::e1D && info.type != ImageType::Buffer && @@ -184,7 +187,8 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { // Image::BindLayers. Only formats uploaded layer by layer: huge ASTC arrays (GPU decode) and // formats the host samples as they are. [[nodiscard]] bool UsesSparseLayers(const Device& device, const ImageInfo& info, GPUVAddr gpu_addr) { - if (!device.IsSparseResidencyImage2DSupported() || info.type != ImageType::e2D || + if (!device.CanUseUnbackedSparseImages() || !device.IsSparseResidencyImage2DSupported() || + info.type != ImageType::e2D || info.resources.layers <= 1 || info.num_samples != 1 || VideoCore::Surface::GetFormatType(info.format) != VideoCore::Surface::SurfaceType::ColorTexture) { return false; @@ -2089,7 +2093,7 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu : runtime->ViewFormats(info.format), AstcHostFormat(runtime_.device, info), UsesSparseLayers(runtime_.device, info, gpu_addr_) || - IsUnwrittenSparse(info, gpu_addr_))), + IsUnwrittenSparse(runtime_.device, info, gpu_addr_))), aspect_mask(ImageAspectMask(info.format)) { if (original_image.IsUnbacked()) { flags |= VideoCommon::ImageFlagBits::Unbacked; diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index d8524f6575..abd31ad904 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -326,6 +326,14 @@ public: return IsSparseBindingSupported() && features.features.sparseResidencyImage2D; } + /// Whether images with no memory bound may be sampled and used as attachments. AMD's drivers + /// fault on it (the GPU hangs shortly after the first such draw), so large images there are + /// backed normally. + bool CanUseUnbackedSparseImages() const { + const VkDriverIdKHR id = GetDriverID(); + return id != VK_DRIVER_ID_AMD_PROPRIETARY && id != VK_DRIVER_ID_AMD_OPEN_SOURCE; + } + /// Returns true for tile-based deferred renderers. bool IsTiler() const { switch (GetDriverID()) { |
