From fc90f279e28c365a4eec747ba61e4976dc3a1674 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:59:23 -0700 Subject: [PATCH] vulkan: Limit multisampling to supported sample counts. (#828) --- src/video_core/renderer_vulkan/liverpool_to_vk.cpp | 12 +++++++++++- src/video_core/renderer_vulkan/liverpool_to_vk.h | 2 +- .../renderer_vulkan/vk_graphics_pipeline.cpp | 3 ++- src/video_core/renderer_vulkan/vk_instance.h | 7 +++++++ src/video_core/texture_cache/image.cpp | 11 ++++++++--- 5 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index a97c3dee9..37bd7ebc4 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -718,7 +718,7 @@ vk::ClearValue ColorBufferClearValue(const AmdGpu::Liverpool::ColorBuffer& color return {.color = color}; } -vk::SampleCountFlagBits NumSamples(u32 num_samples) { +vk::SampleCountFlagBits RawNumSamples(u32 num_samples) { switch (num_samples) { case 1: return vk::SampleCountFlagBits::e1; @@ -735,4 +735,14 @@ vk::SampleCountFlagBits NumSamples(u32 num_samples) { } } +vk::SampleCountFlagBits NumSamples(u32 num_samples, vk::SampleCountFlags supported_flags) { + vk::SampleCountFlagBits flags = RawNumSamples(num_samples); + // Half sample counts until supported, with a minimum of 1. + while (!(supported_flags & flags) && num_samples > 1) { + num_samples /= 2; + flags = RawNumSamples(num_samples); + } + return flags; +} + } // namespace Vulkan::LiverpoolToVK diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.h b/src/video_core/renderer_vulkan/liverpool_to_vk.h index 94f9073de..8432d2141 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.h +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.h @@ -51,7 +51,7 @@ vk::Format DepthFormat(Liverpool::DepthBuffer::ZFormat z_format, vk::ClearValue ColorBufferClearValue(const AmdGpu::Liverpool::ColorBuffer& color_buffer); -vk::SampleCountFlagBits NumSamples(u32 num_samples); +vk::SampleCountFlagBits NumSamples(u32 num_samples, vk::SampleCountFlags supported_flags); void EmitQuadToTriangleListIndices(u8* out_indices, u32 num_vertices); diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 2f5209eb2..283c85366 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -102,7 +102,8 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul }; const vk::PipelineMultisampleStateCreateInfo multisampling = { - .rasterizationSamples = LiverpoolToVK::NumSamples(key.num_samples), + .rasterizationSamples = + LiverpoolToVK::NumSamples(key.num_samples, instance.GetFramebufferSampleCounts()), .sampleShadingEnable = false, }; diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index a64c77a57..61687ac28 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -222,6 +222,13 @@ public: return min_imported_host_pointer_alignment; } + /// Returns the sample count flags supported by framebuffers. + vk::SampleCountFlags GetFramebufferSampleCounts() const { + return properties.limits.framebufferColorSampleCounts & + properties.limits.framebufferDepthSampleCounts & + properties.limits.framebufferStencilSampleCounts; + } + private: /// Creates the logical device opportunistically enabling extensions bool CreateDevice(); diff --git a/src/video_core/texture_cache/image.cpp b/src/video_core/texture_cache/image.cpp index d494322a9..154171bf1 100644 --- a/src/video_core/texture_cache/image.cpp +++ b/src/video_core/texture_cache/image.cpp @@ -146,10 +146,15 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, break; } + constexpr auto tiling = vk::ImageTiling::eOptimal; + const auto supported_format = instance->GetSupportedFormat(info.pixel_format); + const auto properties = instance->GetPhysicalDevice().getImageFormatProperties( + supported_format, info.type, tiling, usage, flags); + const vk::ImageCreateInfo image_ci = { .flags = flags, .imageType = info.type, - .format = instance->GetSupportedFormat(info.pixel_format), + .format = supported_format, .extent{ .width = info.size.width, .height = info.size.height, @@ -157,8 +162,8 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, }, .mipLevels = static_cast(info.resources.levels), .arrayLayers = static_cast(info.resources.layers), - .samples = LiverpoolToVK::NumSamples(info.num_samples), - .tiling = vk::ImageTiling::eOptimal, + .samples = LiverpoolToVK::NumSamples(info.num_samples, properties.sampleCounts), + .tiling = tiling, .usage = usage, .initialLayout = vk::ImageLayout::eUndefined, };