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.
This commit is contained in:
parent
d49ed4a421
commit
f632d00eb1
2 changed files with 31 additions and 24 deletions
|
@ -19,12 +19,18 @@
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
vk::SurfaceFormatKHR ChooseSwapSurfaceFormat(const std::vector<vk::SurfaceFormatKHR>& formats) {
|
|
||||||
|
vk::SurfaceFormatKHR ChooseSwapSurfaceFormat(const std::vector<vk::SurfaceFormatKHR>& formats,
|
||||||
|
bool srgb) {
|
||||||
if (formats.size() == 1 && formats[0].format == vk::Format::eUndefined) {
|
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) {
|
const auto& found = std::find_if(formats.begin(), formats.end(), [srgb](const auto& format) {
|
||||||
return format.format == vk::Format::eB8G8R8A8Unorm &&
|
const auto request_format = srgb ? vk::Format::eB8G8R8A8Srgb : vk::Format::eB8G8R8A8Unorm;
|
||||||
|
return format.format == request_format &&
|
||||||
format.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear;
|
format.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear;
|
||||||
});
|
});
|
||||||
return found != formats.end() ? *found : formats[0];
|
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));
|
std::min(capabilities.maxImageExtent.height, extent.height));
|
||||||
return extent;
|
return extent;
|
||||||
}
|
}
|
||||||
} // namespace
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
VKSwapchain::VKSwapchain(vk::SurfaceKHR surface, const VKDevice& device)
|
VKSwapchain::VKSwapchain(vk::SurfaceKHR surface, const VKDevice& device)
|
||||||
: surface{surface}, device{device} {}
|
: surface{surface}, device{device} {}
|
||||||
|
|
||||||
VKSwapchain::~VKSwapchain() = default;
|
VKSwapchain::~VKSwapchain() = default;
|
||||||
|
|
||||||
void VKSwapchain::Create(u32 width, u32 height) {
|
void VKSwapchain::Create(u32 width, u32 height, bool srgb) {
|
||||||
const auto dev = device.GetLogical();
|
|
||||||
const auto& dld = device.GetDispatchLoader();
|
const auto& dld = device.GetDispatchLoader();
|
||||||
const auto physical_device = device.GetPhysical();
|
const auto physical_device = device.GetPhysical();
|
||||||
|
const auto capabilities{physical_device.getSurfaceCapabilitiesKHR(surface, dld)};
|
||||||
const vk::SurfaceCapabilitiesKHR capabilities{
|
|
||||||
physical_device.getSurfaceCapabilitiesKHR(surface, dld)};
|
|
||||||
if (capabilities.maxImageExtent.width == 0 || capabilities.maxImageExtent.height == 0) {
|
if (capabilities.maxImageExtent.width == 0 || capabilities.maxImageExtent.height == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev.waitIdle(dld);
|
device.GetLogical().waitIdle(dld);
|
||||||
Destroy();
|
Destroy();
|
||||||
|
|
||||||
CreateSwapchain(capabilities, width, height);
|
CreateSwapchain(capabilities, width, height, srgb);
|
||||||
CreateSemaphores();
|
CreateSemaphores();
|
||||||
CreateImageViews();
|
CreateImageViews();
|
||||||
|
|
||||||
|
@ -107,7 +111,7 @@ bool VKSwapchain::Present(vk::Semaphore render_semaphore, VKFence& fence) {
|
||||||
break;
|
break;
|
||||||
case vk::Result::eErrorOutOfDateKHR:
|
case vk::Result::eErrorOutOfDateKHR:
|
||||||
if (current_width > 0 && current_height > 0) {
|
if (current_width > 0 && current_height > 0) {
|
||||||
Create(current_width, current_height);
|
Create(current_width, current_height, current_srgb);
|
||||||
recreated = true;
|
recreated = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -129,23 +133,19 @@ bool VKSwapchain::HasFramebufferChanged(const Layout::FramebufferLayout& framebu
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKSwapchain::CreateSwapchain(const vk::SurfaceCapabilitiesKHR& capabilities, u32 width,
|
void VKSwapchain::CreateSwapchain(const vk::SurfaceCapabilitiesKHR& capabilities, u32 width,
|
||||||
u32 height) {
|
u32 height, bool srgb) {
|
||||||
const auto dev{device.GetLogical()};
|
|
||||||
const auto& dld{device.GetDispatchLoader()};
|
const auto& dld{device.GetDispatchLoader()};
|
||||||
const auto physical_device{device.GetPhysical()};
|
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<vk::SurfaceFormatKHR> formats{
|
const vk::SurfaceFormatKHR surface_format{ChooseSwapSurfaceFormat(formats, srgb)};
|
||||||
physical_device.getSurfaceFormatsKHR(surface, dld)};
|
|
||||||
|
|
||||||
const std::vector<vk::PresentModeKHR> present_modes{
|
|
||||||
physical_device.getSurfacePresentModesKHR(surface, dld)};
|
|
||||||
|
|
||||||
const vk::SurfaceFormatKHR surface_format{ChooseSwapSurfaceFormat(formats)};
|
|
||||||
const vk::PresentModeKHR present_mode{ChooseSwapPresentMode(present_modes)};
|
const vk::PresentModeKHR present_mode{ChooseSwapPresentMode(present_modes)};
|
||||||
extent = ChooseSwapExtent(capabilities, width, height);
|
extent = ChooseSwapExtent(capabilities, width, height);
|
||||||
|
|
||||||
current_width = extent.width;
|
current_width = extent.width;
|
||||||
current_height = extent.height;
|
current_height = extent.height;
|
||||||
|
current_srgb = srgb;
|
||||||
|
|
||||||
u32 requested_image_count{capabilities.minImageCount + 1};
|
u32 requested_image_count{capabilities.minImageCount + 1};
|
||||||
if (capabilities.maxImageCount > 0 && requested_image_count > capabilities.maxImageCount) {
|
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;
|
swapchain_ci.imageSharingMode = vk::SharingMode::eExclusive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto dev{device.GetLogical()};
|
||||||
swapchain = dev.createSwapchainKHRUnique(swapchain_ci, nullptr, dld);
|
swapchain = dev.createSwapchainKHRUnique(swapchain_ci, nullptr, dld);
|
||||||
|
|
||||||
images = dev.getSwapchainImagesKHR(*swapchain, dld);
|
images = dev.getSwapchainImagesKHR(*swapchain, dld);
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
~VKSwapchain();
|
~VKSwapchain();
|
||||||
|
|
||||||
/// Creates (or recreates) the swapchain with a given size.
|
/// 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.
|
/// Acquires the next image in the swapchain, waits as needed.
|
||||||
void AcquireNextImage();
|
void AcquireNextImage();
|
||||||
|
@ -60,8 +60,13 @@ public:
|
||||||
return image_format;
|
return image_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GetSrgbState() const {
|
||||||
|
return current_srgb;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
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 CreateSemaphores();
|
||||||
void CreateImageViews();
|
void CreateImageViews();
|
||||||
|
|
||||||
|
@ -87,6 +92,7 @@ private:
|
||||||
|
|
||||||
u32 current_width{};
|
u32 current_width{};
|
||||||
u32 current_height{};
|
u32 current_height{};
|
||||||
|
bool current_srgb{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
Loading…
Reference in a new issue