From a4f78d3eedb6a1df9e486b7b0e98f1e310be9db8 Mon Sep 17 00:00:00 2001 From: plapins Date: Mon, 20 Jun 2016 16:26:00 +0200 Subject: [PATCH] Modified rendering framework to support surface size of 0 width and 0 height (this can occur on Windows when window gets minimized). In such situation, swapchain is not created and rendering function is not called. Instead, rendering loop waits for 1/10 of a second. --- Project/Common/OperatingSystem.cpp | 47 ++++++++++++++++++++++-------- Project/Common/OperatingSystem.h | 11 +++++++ Project/Common/VulkanCommon.cpp | 19 ++++++++++-- Project/Tutorial02/Tutorial02.cpp | 9 ++++++ 4 files changed, 71 insertions(+), 15 deletions(-) diff --git a/Project/Common/OperatingSystem.cpp b/Project/Common/OperatingSystem.cpp index cae80d6..47e1991 100644 --- a/Project/Common/OperatingSystem.cpp +++ b/Project/Common/OperatingSystem.cpp @@ -8,6 +8,8 @@ // Intel does not assume any responsibility for any errors which may appear in this software // nor any responsibility to update it. +#include +#include #include "OperatingSystem.h" namespace ApiWithoutSecrets { @@ -94,6 +96,7 @@ namespace ApiWithoutSecrets { MSG message; bool loop = true; bool resize = false; + bool result = true; while( loop ) { if( PeekMessage( &message, NULL, 0, 0, PM_REMOVE ) ) { @@ -115,16 +118,22 @@ namespace ApiWithoutSecrets { if( resize ) { resize = false; if( !tutorial.OnWindowSizeChanged() ) { - loop = false; + result = false; + break; } } - if( !tutorial.Draw() ) { - loop = false; + if( tutorial.ReadyToDraw() ) { + if( !tutorial.Draw() ) { + result = false; + break; + } + } else { + std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); } } } - return true; + return result; } #elif defined(VK_USE_PLATFORM_XCB_KHR) @@ -203,6 +212,7 @@ namespace ApiWithoutSecrets { xcb_generic_event_t *event; bool loop = true; bool resize = false; + bool result = true; while( loop ) { event = xcb_poll_for_event( Parameters.Connection ); @@ -241,16 +251,22 @@ namespace ApiWithoutSecrets { if( resize ) { resize = false; if( !tutorial.OnWindowSizeChanged() ) { - loop = false; + result = false; + break; } } - if( !tutorial.Draw() ) { - loop = false; + if( tutorial.ReadyToDraw() ) { + if( !tutorial.Draw() ) { + result = false; + break; + } + } else { + std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); } } } - return true; + return result; } #elif defined(VK_USE_PLATFORM_XLIB_KHR) @@ -299,6 +315,7 @@ namespace ApiWithoutSecrets { XEvent event; bool loop = true; bool resize = false; + bool result = true; while( loop ) { if( XPending( Parameters.DisplayPtr ) ) { @@ -334,16 +351,22 @@ namespace ApiWithoutSecrets { if( resize ) { resize = false; if( !tutorial.OnWindowSizeChanged() ) { - loop = false; + result = false; + break; } } - if( !tutorial.Draw() ) { - loop = false; + if( tutorial.ReadyToDraw() ) { + if( !tutorial.Draw() ) { + result = false; + break; + } + } else { + std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); } } } - return true; + return result; } #endif diff --git a/Project/Common/OperatingSystem.h b/Project/Common/OperatingSystem.h index 0b27360..093b1f0 100644 --- a/Project/Common/OperatingSystem.h +++ b/Project/Common/OperatingSystem.h @@ -58,8 +58,19 @@ namespace ApiWithoutSecrets { virtual bool OnWindowSizeChanged() = 0; virtual bool Draw() = 0; + virtual bool ReadyToDraw() const final { + return CanRender; + } + + TutorialBase() : + CanRender( false ) { + } + virtual ~TutorialBase() { } + + protected: + bool CanRender; }; // ************************************************************ // diff --git a/Project/Common/VulkanCommon.cpp b/Project/Common/VulkanCommon.cpp index 8c34150..37229a3 100644 --- a/Project/Common/VulkanCommon.cpp +++ b/Project/Common/VulkanCommon.cpp @@ -58,10 +58,14 @@ namespace ApiWithoutSecrets { bool VulkanCommon::OnWindowSizeChanged() { ChildClear(); - if( !CreateSwapChain() ) { - return false; + if( CreateSwapChain() ) { + if( CanRender ) { + return ChildOnWindowSizeChanged(); + } + return true; } - return ChildOnWindowSizeChanged(); + + return false; } VkPhysicalDevice VulkanCommon::GetPhysicalDevice() const { @@ -434,6 +438,8 @@ namespace ApiWithoutSecrets { } bool VulkanCommon::CreateSwapChain() { + CanRender = false; + if( Vulkan.Device != VK_NULL_HANDLE ) { vkDeviceWaitIdle( Vulkan.Device ); } @@ -492,6 +498,11 @@ namespace ApiWithoutSecrets { if( static_cast(desired_present_mode) == -1 ) { return false; } + if( (desired_extent.width == 0) || (desired_extent.height == 0) ) { + // Current surface size is (0, 0) so we can't create a swap chain and render anything (CanRender == false) + // But we don't wont to kill the application as this situation may occur i.e. when window gets minimized + return true; + } VkSwapchainCreateInfoKHR swap_chain_create_info = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, // VkStructureType sType @@ -576,6 +587,8 @@ namespace ApiWithoutSecrets { } } + CanRender = true; + return true; } diff --git a/Project/Tutorial02/Tutorial02.cpp b/Project/Tutorial02/Tutorial02.cpp index 193af7d..cdefaec 100644 --- a/Project/Tutorial02/Tutorial02.cpp +++ b/Project/Tutorial02/Tutorial02.cpp @@ -430,6 +430,8 @@ namespace ApiWithoutSecrets { } bool Tutorial02::CreateSwapChain() { + CanRender = false; + if( Vulkan.Device != VK_NULL_HANDLE ) { vkDeviceWaitIdle( Vulkan.Device ); } @@ -480,6 +482,11 @@ namespace ApiWithoutSecrets { if( static_cast(desired_present_mode) == -1 ) { return false; } + if( (desired_extent.width == 0) || (desired_extent.height == 0) ) { + // Current surface size is (0, 0) so we can't create a swap chain and render anything (CanRender == false) + // But we don't wont to kill the application as this situation may occur i.e. when window gets minimized + return true; + } VkSwapchainCreateInfoKHR swap_chain_create_info = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, // VkStructureType sType @@ -510,6 +517,8 @@ namespace ApiWithoutSecrets { vkDestroySwapchainKHR( Vulkan.Device, old_swap_chain, nullptr ); } + CanRender = true; + return true; }