From f632d00eb1add39f43617d147466bb310ce646fd Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 6 Dec 2019 22:41:42 -0300 Subject: vk_swapchain: Add support for swapping sRGB We don't know until the game is running if it's using an sRGB color space or not. Add support for hot-swapping swapchain surface formats. --- src/video_core/renderer_vulkan/vk_swapchain.cpp | 45 +++++++++++++------------ src/video_core/renderer_vulkan/vk_swapchain.h | 10 ++++-- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 08279e562..ebc68f030 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -19,12 +19,18 @@ namespace Vulkan { namespace { -vk::SurfaceFormatKHR ChooseSwapSurfaceFormat(const std::vector& formats) { + +vk::SurfaceFormatKHR ChooseSwapSurfaceFormat(const std::vector& formats, + bool srgb) { if (formats.size() == 1 && formats[0].format == vk::Format::eUndefined) { - return {vk::Format::eB8G8R8A8Unorm, vk::ColorSpaceKHR::eSrgbNonlinear}; + vk::SurfaceFormatKHR format; + format.format = vk::Format::eB8G8R8A8Unorm; + format.colorSpace = vk::ColorSpaceKHR::eSrgbNonlinear; + return format; } - const auto& found = std::find_if(formats.begin(), formats.end(), [](const auto& format) { - return format.format == vk::Format::eB8G8R8A8Unorm && + const auto& found = std::find_if(formats.begin(), formats.end(), [srgb](const auto& format) { + const auto request_format = srgb ? vk::Format::eB8G8R8A8Srgb : vk::Format::eB8G8R8A8Unorm; + return format.format == request_format && format.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear; }); return found != formats.end() ? *found : formats[0]; @@ -51,28 +57,26 @@ vk::Extent2D ChooseSwapExtent(const vk::SurfaceCapabilitiesKHR& capabilities, u3 std::min(capabilities.maxImageExtent.height, extent.height)); return extent; } -} // namespace + +} // Anonymous namespace VKSwapchain::VKSwapchain(vk::SurfaceKHR surface, const VKDevice& device) : surface{surface}, device{device} {} VKSwapchain::~VKSwapchain() = default; -void VKSwapchain::Create(u32 width, u32 height) { - const auto dev = device.GetLogical(); +void VKSwapchain::Create(u32 width, u32 height, bool srgb) { const auto& dld = device.GetDispatchLoader(); const auto physical_device = device.GetPhysical(); - - const vk::SurfaceCapabilitiesKHR capabilities{ - physical_device.getSurfaceCapabilitiesKHR(surface, dld)}; + const auto capabilities{physical_device.getSurfaceCapabilitiesKHR(surface, dld)}; if (capabilities.maxImageExtent.width == 0 || capabilities.maxImageExtent.height == 0) { return; } - dev.waitIdle(dld); + device.GetLogical().waitIdle(dld); Destroy(); - CreateSwapchain(capabilities, width, height); + CreateSwapchain(capabilities, width, height, srgb); CreateSemaphores(); CreateImageViews(); @@ -107,7 +111,7 @@ bool VKSwapchain::Present(vk::Semaphore render_semaphore, VKFence& fence) { break; case vk::Result::eErrorOutOfDateKHR: if (current_width > 0 && current_height > 0) { - Create(current_width, current_height); + Create(current_width, current_height, current_srgb); recreated = true; } break; @@ -129,23 +133,19 @@ bool VKSwapchain::HasFramebufferChanged(const Layout::FramebufferLayout& framebu } void VKSwapchain::CreateSwapchain(const vk::SurfaceCapabilitiesKHR& capabilities, u32 width, - u32 height) { - const auto dev{device.GetLogical()}; + u32 height, bool srgb) { const auto& dld{device.GetDispatchLoader()}; const auto physical_device{device.GetPhysical()}; + const auto formats{physical_device.getSurfaceFormatsKHR(surface, dld)}; + const auto present_modes{physical_device.getSurfacePresentModesKHR(surface, dld)}; - const std::vector formats{ - physical_device.getSurfaceFormatsKHR(surface, dld)}; - - const std::vector present_modes{ - physical_device.getSurfacePresentModesKHR(surface, dld)}; - - const vk::SurfaceFormatKHR surface_format{ChooseSwapSurfaceFormat(formats)}; + const vk::SurfaceFormatKHR surface_format{ChooseSwapSurfaceFormat(formats, srgb)}; const vk::PresentModeKHR present_mode{ChooseSwapPresentMode(present_modes)}; extent = ChooseSwapExtent(capabilities, width, height); current_width = extent.width; current_height = extent.height; + current_srgb = srgb; u32 requested_image_count{capabilities.minImageCount + 1}; if (capabilities.maxImageCount > 0 && requested_image_count > capabilities.maxImageCount) { @@ -169,6 +169,7 @@ void VKSwapchain::CreateSwapchain(const vk::SurfaceCapabilitiesKHR& capabilities swapchain_ci.imageSharingMode = vk::SharingMode::eExclusive; } + const auto dev{device.GetLogical()}; swapchain = dev.createSwapchainKHRUnique(swapchain_ci, nullptr, dld); images = dev.getSwapchainImagesKHR(*swapchain, dld); diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h index 2ad84f185..a1e7938d2 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.h +++ b/src/video_core/renderer_vulkan/vk_swapchain.h @@ -24,7 +24,7 @@ public: ~VKSwapchain(); /// Creates (or recreates) the swapchain with a given size. - void Create(u32 width, u32 height); + void Create(u32 width, u32 height, bool srgb); /// Acquires the next image in the swapchain, waits as needed. void AcquireNextImage(); @@ -60,8 +60,13 @@ public: return image_format; } + bool GetSrgbState() const { + return current_srgb; + } + private: - void CreateSwapchain(const vk::SurfaceCapabilitiesKHR& capabilities, u32 width, u32 height); + void CreateSwapchain(const vk::SurfaceCapabilitiesKHR& capabilities, u32 width, u32 height, + bool srgb); void CreateSemaphores(); void CreateImageViews(); @@ -87,6 +92,7 @@ private: u32 current_width{}; u32 current_height{}; + bool current_srgb{}; }; } // namespace Vulkan -- cgit v1.2.3