|
|
@ -64,15 +64,15 @@ VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, u32 wi
|
|
|
|
|
|
|
|
|
|
|
|
} // Anonymous namespace
|
|
|
|
} // Anonymous namespace
|
|
|
|
|
|
|
|
|
|
|
|
VKSwapchain::VKSwapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_,
|
|
|
|
Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_, u32 width,
|
|
|
|
u32 width, u32 height, bool srgb)
|
|
|
|
u32 height, bool srgb)
|
|
|
|
: surface{surface_}, device{device_}, scheduler{scheduler_} {
|
|
|
|
: surface{surface_}, device{device_}, scheduler{scheduler_} {
|
|
|
|
Create(width, height, srgb);
|
|
|
|
Create(width, height, srgb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VKSwapchain::~VKSwapchain() = default;
|
|
|
|
Swapchain::~Swapchain() = default;
|
|
|
|
|
|
|
|
|
|
|
|
void VKSwapchain::Create(u32 width, u32 height, bool srgb) {
|
|
|
|
void Swapchain::Create(u32 width, u32 height, bool srgb) {
|
|
|
|
is_outdated = false;
|
|
|
|
is_outdated = false;
|
|
|
|
is_suboptimal = false;
|
|
|
|
is_suboptimal = false;
|
|
|
|
|
|
|
|
|
|
|
@ -93,7 +93,7 @@ void VKSwapchain::Create(u32 width, u32 height, bool srgb) {
|
|
|
|
resource_ticks.resize(image_count);
|
|
|
|
resource_ticks.resize(image_count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void VKSwapchain::AcquireNextImage() {
|
|
|
|
void Swapchain::AcquireNextImage() {
|
|
|
|
const VkResult result = device.GetLogical().AcquireNextImageKHR(
|
|
|
|
const VkResult result = device.GetLogical().AcquireNextImageKHR(
|
|
|
|
*swapchain, std::numeric_limits<u64>::max(), *present_semaphores[frame_index],
|
|
|
|
*swapchain, std::numeric_limits<u64>::max(), *present_semaphores[frame_index],
|
|
|
|
VK_NULL_HANDLE, &image_index);
|
|
|
|
VK_NULL_HANDLE, &image_index);
|
|
|
@ -114,7 +114,7 @@ void VKSwapchain::AcquireNextImage() {
|
|
|
|
resource_ticks[image_index] = scheduler.CurrentTick();
|
|
|
|
resource_ticks[image_index] = scheduler.CurrentTick();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void VKSwapchain::Present(VkSemaphore render_semaphore) {
|
|
|
|
void Swapchain::Present(VkSemaphore render_semaphore) {
|
|
|
|
const auto present_queue{device.GetPresentQueue()};
|
|
|
|
const auto present_queue{device.GetPresentQueue()};
|
|
|
|
const VkPresentInfoKHR present_info{
|
|
|
|
const VkPresentInfoKHR present_info{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
|
|
@ -145,8 +145,8 @@ void VKSwapchain::Present(VkSemaphore render_semaphore) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, u32 width,
|
|
|
|
void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, u32 width, u32 height,
|
|
|
|
u32 height, bool srgb) {
|
|
|
|
bool srgb) {
|
|
|
|
const auto physical_device{device.GetPhysical()};
|
|
|
|
const auto physical_device{device.GetPhysical()};
|
|
|
|
const auto formats{physical_device.GetSurfaceFormatsKHR(surface)};
|
|
|
|
const auto formats{physical_device.GetSurfaceFormatsKHR(surface)};
|
|
|
|
const auto present_modes{physical_device.GetSurfacePresentModesKHR(surface)};
|
|
|
|
const auto present_modes{physical_device.GetSurfacePresentModesKHR(surface)};
|
|
|
@ -212,13 +212,13 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities,
|
|
|
|
image_view_format = srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM;
|
|
|
|
image_view_format = srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void VKSwapchain::CreateSemaphores() {
|
|
|
|
void Swapchain::CreateSemaphores() {
|
|
|
|
present_semaphores.resize(image_count);
|
|
|
|
present_semaphores.resize(image_count);
|
|
|
|
std::ranges::generate(present_semaphores,
|
|
|
|
std::ranges::generate(present_semaphores,
|
|
|
|
[this] { return device.GetLogical().CreateSemaphore(); });
|
|
|
|
[this] { return device.GetLogical().CreateSemaphore(); });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void VKSwapchain::CreateImageViews() {
|
|
|
|
void Swapchain::CreateImageViews() {
|
|
|
|
VkImageViewCreateInfo ci{
|
|
|
|
VkImageViewCreateInfo ci{
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
|
|
|
.pNext = nullptr,
|
|
|
|
.pNext = nullptr,
|
|
|
@ -250,7 +250,7 @@ void VKSwapchain::CreateImageViews() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void VKSwapchain::Destroy() {
|
|
|
|
void Swapchain::Destroy() {
|
|
|
|
frame_index = 0;
|
|
|
|
frame_index = 0;
|
|
|
|
present_semaphores.clear();
|
|
|
|
present_semaphores.clear();
|
|
|
|
framebuffers.clear();
|
|
|
|
framebuffers.clear();
|
|
|
@ -258,11 +258,11 @@ void VKSwapchain::Destroy() {
|
|
|
|
swapchain.reset();
|
|
|
|
swapchain.reset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool VKSwapchain::HasFpsUnlockChanged() const {
|
|
|
|
bool Swapchain::HasFpsUnlockChanged() const {
|
|
|
|
return current_fps_unlocked != Settings::values.disable_fps_limit.GetValue();
|
|
|
|
return current_fps_unlocked != Settings::values.disable_fps_limit.GetValue();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool VKSwapchain::NeedsPresentModeUpdate() const {
|
|
|
|
bool Swapchain::NeedsPresentModeUpdate() const {
|
|
|
|
// Mailbox present mode is the ideal for all scenarios. If it is not available,
|
|
|
|
// Mailbox present mode is the ideal for all scenarios. If it is not available,
|
|
|
|
// A different present mode is needed to support unlocked FPS above the monitor's refresh rate.
|
|
|
|
// A different present mode is needed to support unlocked FPS above the monitor's refresh rate.
|
|
|
|
return present_mode != VK_PRESENT_MODE_MAILBOX_KHR && HasFpsUnlockChanged();
|
|
|
|
return present_mode != VK_PRESENT_MODE_MAILBOX_KHR && HasFpsUnlockChanged();
|
|
|
|