Skip to content

Commit 4c52aeb

Browse files
[Window] Fixed maximizing and minimizing.
1 parent 3d797a9 commit 4c52aeb

6 files changed

Lines changed: 177 additions & 78 deletions

File tree

Engine/Source/VulkanRHIModule/Private/VulkanRHIModule/Graphics/VulkanSwapchain.cpp

Lines changed: 86 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ namespace Volt::RHI
7676
return 0;
7777
}
7878

79-
inline static VkSurfaceFormatKHR ChooseSwapchainFormat(const std::span<VulkanSwapchain::SurfaceFormat> swapchainFormats, bool useHDRIfAvailable)
79+
inline static VkSurfaceFormatKHR ChooseSwapchainFormat(const std::span<VulkanSwapchain::SurfaceFormat> swapchainFormats, bool useHDRIfAvailable, ColorSpace& outColorSpace)
8080
{
8181
VT_PROFILE_FUNCTION();
8282

@@ -154,51 +154,7 @@ namespace Volt::RHI
154154

155155
void VulkanSwapchain::BeginFrame()
156156
{
157-
VT_PROFILE_FUNCTION();
158-
159-
if (m_swapchainNeedsRebuild)
160-
{
161-
QuerySwapchainCapabilities();
162-
Invalidate(m_width, m_height, m_VSyncEnabled);
163-
m_swapchainNeedsRebuild = false;
164-
}
165-
166-
auto device = GraphicsContext::GetDevice();
167-
auto& frameData = m_perFrameInFlightData.at(m_currentFrameIndex);
168-
169-
vkWaitForFences(device->GetHandle<VkDevice>(), 1, &frameData.renderFence, VK_TRUE, UINT64_MAX);
170-
vkResetFences(device->GetHandle<VkDevice>(), 1, &frameData.renderFence);
171-
172-
VkResult swapchainStatus;
173-
{
174-
VT_PROFILE_SCOPE("AcquireNextImage");
175-
176-
// Reset the 'wait' of the semaphore
177-
VulkanSemaphore* vkSemaphore = ResourceCast(frameData.acquireSemaphore.GetRaw());
178-
vkSemaphore->ResetWait();
179-
180-
m_swapchainMutex.lock();
181-
swapchainStatus = vkAcquireNextImageKHR(device->GetHandle<VkDevice>(), m_swapchain, 1000000000, frameData.acquireSemaphore->GetHandle<VkSemaphore>(), nullptr, &m_currentImageIndex);
182-
m_swapchainMutex.unlock();
183-
}
184-
185-
if (swapchainStatus == VK_SUCCESS || swapchainStatus == VK_SUBOPTIMAL_KHR)
186-
{
187-
if (m_perImageData[m_currentImageIndex].imageReference == nullptr)
188-
{
189-
CreateSwapchainImage(m_currentImageIndex);
190-
}
191-
}
192-
193-
if (swapchainStatus == VK_ERROR_OUT_OF_DATE_KHR)
194-
{
195-
m_swapchainNeedsRebuild = true;
196-
return;
197-
}
198-
else if (swapchainStatus != VK_SUCCESS && swapchainStatus != VK_SUBOPTIMAL_KHR)
199-
{
200-
VT_ENSURE_NO_ENTRY();
201-
}
157+
BeginFrameInternal(true);
202158
}
203159

204160
void VulkanSwapchain::Present()
@@ -227,11 +183,6 @@ namespace Volt::RHI
227183

228184
m_commandBuffers.at(m_currentFrameIndex)->End();
229185

230-
if (m_swapchainNeedsRebuild)
231-
{
232-
return;
233-
}
234-
235186
PerFrameInFlightData& frameData = m_perFrameInFlightData.at(m_currentFrameIndex);
236187
PerImageData& imageData = m_perImageData.at(m_currentImageIndex);
237188

@@ -350,8 +301,17 @@ namespace Volt::RHI
350301

351302
QuerySwapchainCapabilities();
352303

353-
CreateSwapchain(width, height, enableVSync);
354-
CreateSyncObjects();
304+
VkSwapchainKHR oldSwapchain = CreateSwapchain(width, height, enableVSync);
305+
306+
if (oldSwapchain)
307+
{
308+
ReleasePreviousSwapchain(oldSwapchain);
309+
}
310+
311+
if (m_perFrameInFlightData.empty())
312+
{
313+
CreateSyncObjects();
314+
}
355315
CreateRenderSemaphores();
356316
}
357317

@@ -467,7 +427,8 @@ namespace Volt::RHI
467427

468428
VT_VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice->GetHandle<VkPhysicalDevice>(), m_surface, &presentModeCount, vkPresentModes.data()));
469429

470-
m_capabilities.presentModes.resize(presentModeCount);
430+
m_capabilities.presentModes.clear();
431+
m_capabilities.presentModes.reserve(presentModeCount);
471432

472433
for (VkPresentModeKHR presentMode : vkPresentModes)
473434
{
@@ -486,18 +447,12 @@ namespace Volt::RHI
486447
{
487448
VT_PROFILE_FUNCTION();
488449

489-
const VkSurfaceFormatKHR surfaceFormat = Utility::ChooseSwapchainFormat(m_capabilities.surfaceFormats, m_createInfo.useHDRIfAvailable);
450+
std::scoped_lock lock{ m_swapchainMutex };
490451

491-
if (surfaceFormat.format == VK_FORMAT_R16G16B16A16_SFLOAT ||
492-
surfaceFormat.format == VK_FORMAT_A2R10G10B10_UNORM_PACK32 ||
493-
surfaceFormat.format == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
494-
{
495-
m_isHDREnabled = true;
496-
}
497-
else
498-
{
499-
m_isHDREnabled = false;
500-
}
452+
ColorSpace selectedColorSpace;
453+
const VkSurfaceFormatKHR surfaceFormat = Utility::ChooseSwapchainFormat(m_capabilities.surfaceFormats, m_createInfo.useHDRIfAvailable, selectedColorSpace);
454+
455+
m_isHDREnabled = Utility::IsHDRColorSpace(selectedColorSpace);
501456

502457
const VkPresentModeKHR presentMode = Utility::ChooseSwapchainPresentMode(enableVSync, m_capabilities.presentModes);
503458

@@ -508,8 +463,23 @@ namespace Volt::RHI
508463
}
509464

510465
// Make sure the requested size is within the capabilities of the swapchain
511-
m_width = m_capabilities.currentExtent.width;
512-
m_height = m_capabilities.currentExtent.height;
466+
if (m_capabilities.currentExtent.width == 0 || m_capabilities.currentExtent.height == 0)
467+
{
468+
return nullptr;
469+
}
470+
471+
if (m_capabilities.currentExtent.width == 0xFFFFFFFF)
472+
{
473+
m_width = width;
474+
}
475+
476+
if (m_capabilities.currentExtent.height == 0xFFFFFFFF)
477+
{
478+
m_height = m_capabilities.currentExtent.height;
479+
}
480+
481+
m_width = std::clamp(m_width, m_capabilities.minImageExtent.width, m_capabilities.maxImageExtent.width);
482+
m_height = std::clamp(m_height, m_capabilities.minImageExtent.height, m_capabilities.maxImageExtent.height);
513483

514484
VkSwapchainKHR oldSwapchain = m_swapchain;
515485

@@ -615,7 +585,7 @@ namespace Volt::RHI
615585
auto vulkanContext = GraphicsContext::Get().As<VulkanGraphicsContext>();
616586
VkInstance instance = vulkanContext->GetHandle<VkInstance>();
617587

618-
vkCreateWin32SurfaceKHR(instance, &createInfo, VT_VULKAN_ALLOCATOR, &m_surface);
588+
VT_VK_CHECK(vkCreateWin32SurfaceKHR(instance, &createInfo, VT_VULKAN_ALLOCATOR, &m_surface));
619589
#endif
620590
}
621591

@@ -681,4 +651,52 @@ namespace Volt::RHI
681651

682652
}, nullptr);
683653
}
654+
655+
void VulkanSwapchain::BeginFrameInternal(bool waitForFences)
656+
{
657+
VT_PROFILE_FUNCTION();
658+
659+
auto device = GraphicsContext::GetDevice();
660+
auto& frameData = m_perFrameInFlightData.at(m_currentFrameIndex);
661+
662+
if (waitForFences)
663+
{
664+
vkWaitForFences(device->GetHandle<VkDevice>(), 1, &frameData.renderFence, VK_TRUE, UINT64_MAX);
665+
vkResetFences(device->GetHandle<VkDevice>(), 1, &frameData.renderFence);
666+
}
667+
668+
VkResult swapchainStatus;
669+
{
670+
VT_PROFILE_SCOPE("AcquireNextImage");
671+
672+
// Reset the 'wait' of the semaphore
673+
VulkanSemaphore* vkSemaphore = ResourceCast(frameData.acquireSemaphore.GetRaw());
674+
vkSemaphore->ResetWait();
675+
676+
m_swapchainMutex.lock();
677+
swapchainStatus = vkAcquireNextImageKHR(device->GetHandle<VkDevice>(), m_swapchain, 1000000000, frameData.acquireSemaphore->GetHandle<VkSemaphore>(), nullptr, &m_currentImageIndex);
678+
m_swapchainMutex.unlock();
679+
}
680+
681+
if (swapchainStatus == VK_SUCCESS || swapchainStatus == VK_SUBOPTIMAL_KHR)
682+
{
683+
if (m_perImageData[m_currentImageIndex].imageReference == nullptr)
684+
{
685+
CreateSwapchainImage(m_currentImageIndex);
686+
}
687+
}
688+
689+
if (swapchainStatus == VK_ERROR_OUT_OF_DATE_KHR || swapchainStatus == VK_TIMEOUT)
690+
{
691+
Invalidate(m_width, m_height, m_VSyncEnabled);
692+
693+
// Since the fence has already been reset, we should not wait on it,
694+
// or it will wait indefinetly.
695+
BeginFrameInternal(false);
696+
}
697+
else if (swapchainStatus != VK_SUCCESS && swapchainStatus != VK_SUBOPTIMAL_KHR)
698+
{
699+
VT_ENSURE_NO_ENTRY();
700+
}
701+
}
684702
}

Engine/Source/VulkanRHIModule/Public/VulkanRHIModule/Graphics/VulkanSwapchain.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ namespace Volt::RHI
5959
void Invalidate(const uint32_t width, const uint32_t height, bool enableVSync);
6060
void Release();
6161

62+
void BeginFrameInternal(bool waitForFences);
63+
6264
void QuerySwapchainCapabilities();
6365

6466
VkSwapchainKHR_T* CreateSwapchain(const uint32_t width, const uint32_t height, bool enableVSync);

Engine/Source/WindowModule/Private/WindowModule/Platform/WindowsWindow.cpp

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -353,11 +353,44 @@ namespace Volt
353353

354354
void WindowsWindow::BeginFrame()
355355
{
356+
if (m_wasMinimizedPreviousFrame)
357+
{
358+
m_wasMinimizedPreviousFrame = false;
359+
m_isMinimized = true;
360+
}
361+
362+
if (m_wasRestoredPreviousFrame)
363+
{
364+
m_wasRestoredPreviousFrame = false;
365+
m_isMinimized = false;
366+
}
367+
368+
if (m_requiresResize)
369+
{
370+
m_requiresResize = false;
371+
372+
m_width = m_requestedWidth;
373+
m_height = m_requestedHeight;
374+
375+
m_swapchain->Resize(m_width, m_height, m_enableVSync);
376+
m_onWindowResize.Broadcast(*this, m_width, m_height);
377+
}
378+
379+
if (m_isMinimized)
380+
{
381+
return;
382+
}
383+
356384
m_swapchain->BeginFrame();
357385
}
358386

359387
void WindowsWindow::Present()
360388
{
389+
if (m_isMinimized)
390+
{
391+
return;
392+
}
393+
361394
m_swapchain->Present();
362395
}
363396

@@ -368,6 +401,11 @@ namespace Volt
368401

369402
void WindowsWindow::Render()
370403
{
404+
if (m_isMinimized)
405+
{
406+
return;
407+
}
408+
371409
m_onWindowRender.Broadcast(*this);
372410
}
373411

@@ -603,20 +641,25 @@ namespace Volt
603641

604642
case WM_SIZE:
605643
{
606-
UINT x = LOWORD(lParam);
607-
UINT y = HIWORD(lParam);
608-
609-
m_width = x;
610-
m_height = y;
644+
if (wParam == SIZE_MINIMIZED)
645+
{
646+
m_wasMinimizedPreviousFrame = true;
611647

612-
// This message might be called before the swapchain has been created (inside the CreateWindowW call)
613-
// Only send an event and resize the swapchain if it exists.
614-
if (m_swapchain)
648+
// Should not resize swapchain when minimizing.
649+
break;
650+
}
651+
else if (wParam == SIZE_RESTORED)
615652
{
616-
m_swapchain->Resize(x, y, m_enableVSync);
617-
m_onWindowResize.Broadcast(*this, x, y);
653+
m_wasRestoredPreviousFrame = true;
618654
}
619655

656+
UINT x = LOWORD(lParam);
657+
UINT y = HIWORD(lParam);
658+
659+
m_requestedWidth = x;
660+
m_requestedHeight = y;
661+
m_requiresResize = true;
662+
620663
break;
621664
}
622665

Engine/Source/WindowModule/Private/WindowModule/Platform/WindowsWindow.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,14 @@ namespace Volt
106106

107107
uint32_t m_width;
108108
uint32_t m_height;
109+
uint32_t m_requestedWidth;
110+
uint32_t m_requestedHeight;
109111

110112
bool m_enableVSync : 1;
111113
bool m_isDecorated : 1;
114+
bool m_wasMinimizedPreviousFrame : 1 = false;
115+
bool m_wasRestoredPreviousFrame : 1 = false;
116+
bool m_isMinimized : 1 = false;
117+
bool m_requiresResize : 1 = false;
112118
};
113119
}

Engine/Source/WindowModule/Private/WindowModule/Window.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ namespace Volt
182182
}
183183

184184
voltWindow.m_shouldSkipDispatchResizeEvent = false;
185+
186+
if (width > 0 && height > 0)
187+
{
188+
voltWindow.m_isMinimized = false;
189+
}
185190
});
186191

187192
glfwSetWindowCloseCallback(m_window, [](GLFWwindow* window)
@@ -447,19 +452,40 @@ namespace Volt
447452

448453
void Window::BeginFrame()
449454
{
455+
if (m_wasMinimized)
456+
{
457+
m_isMinimized = true;
458+
m_wasMinimized = false;
459+
}
460+
461+
if (m_isMinimized)
462+
{
463+
return;
464+
}
465+
450466
m_swapchain->BeginFrame();
451467

452468
m_frameHasStarted = true;
453469
}
454470

455471
void Window::Render(float timestep)
456472
{
473+
if (m_isMinimized)
474+
{
475+
return;
476+
}
477+
457478
WindowRenderEvent renderEvent(*this, timestep);
458479
EventSystem::DispatchEvent(renderEvent);
459480
}
460481

461482
void Window::Present()
462483
{
484+
if (m_isMinimized)
485+
{
486+
return;
487+
}
488+
463489
if (m_frameHasStarted)
464490
{
465491
m_swapchain->Present();
@@ -515,6 +541,7 @@ namespace Volt
515541
void Window::Minimize() const
516542
{
517543
glfwIconifyWindow(m_window);
544+
m_wasMinimized = true;
518545
}
519546

520547
void Window::Restore() const

0 commit comments

Comments
 (0)