diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index 77e1f3f0..dcce629a 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -966,6 +966,23 @@ void VulkanExampleBase::handleMessages(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR mousePos.y = (float)posy; } break; + case WM_SIZE: + if ((prepared) && (wParam != SIZE_MINIMIZED)) + { + destWidth = LOWORD(lParam); + destHeight = HIWORD(lParam); + if ((wParam == SIZE_MAXIMIZED) || (wParam == SIZE_RESTORED)) + { + windowResize(); + } + } + break; + case WM_EXITSIZEMOVE: + if ((prepared) && ((destWidth != width) || (destHeight != height))) + { + windowResize(); + } + break; } } #elif defined(__ANDROID__) @@ -1182,6 +1199,11 @@ void VulkanExampleBase::keyPressed(uint32_t keyCode) // Can be overriden in derived class } +void VulkanExampleBase::buildCommandBuffers() +{ + // Can be overriden in derived class +} + VkBool32 VulkanExampleBase::getMemoryType(uint32_t typeBits, VkFlags properties, uint32_t * typeIndex) { for (uint32_t i = 0; i < 32; i++) @@ -1352,6 +1374,56 @@ void VulkanExampleBase::setupRenderPass() assert(!err); } +void VulkanExampleBase::windowResize() +{ + if (!prepared) + { + return; + } + prepared = false; + + // Recreate swap chain + width = destWidth; + height = destHeight; + createSetupCommandBuffer(); + setupSwapChain(); + + // Recreate the frame buffers + + vkDestroyImageView(device, depthStencil.view, nullptr); + vkDestroyImage(device, depthStencil.image, nullptr); + vkFreeMemory(device, depthStencil.mem, nullptr); + setupDepthStencil(); + + for (uint32_t i = 0; i < frameBuffers.size(); i++) + { + vkDestroyFramebuffer(device, frameBuffers[i], nullptr); + } + setupFrameBuffer(); + + flushSetupCommandBuffer(); + + // Command buffers need to be recreated as they may store + // references to the recreated frame buffer + destroyCommandBuffers(); + createCommandBuffers(); + buildCommandBuffers(); + + vkQueueWaitIdle(queue); + vkDeviceWaitIdle(device); + + // Notify derived class + windowResized(); + viewChanged(); + + prepared = true; +} + +void VulkanExampleBase::windowResized() +{ + // Can be overrdiden in derived class +} + void VulkanExampleBase::initSwapchain() { #if defined(_WIN32) diff --git a/base/vulkanexamplebase.h b/base/vulkanexamplebase.h index 42c24b84..23fa427b 100644 --- a/base/vulkanexamplebase.h +++ b/base/vulkanexamplebase.h @@ -53,6 +53,11 @@ private: VkResult createDevice(VkDeviceQueueCreateInfo requestedQueues, bool enableValidation); // Get window title with example name, device, et. std::string getWindowTitle(); + // Destination dimensions for resizing the window + uint32_t destWidth; + uint32_t destHeight; + // Called if the window is resized and some resources have to be recreatesd + void windowResize(); protected: // Last frame time, measured using a high performance timer (if available) float frameTimer = 1.0f; @@ -211,6 +216,13 @@ public: // Called if a key is pressed // Can be overriden in derived class to do custom key handling virtual void keyPressed(uint32_t keyCode); + // Called when the window has been resized + // Can be overriden in derived class to recreate or rebuild resources attached to the frame buffer / swapchain + virtual void windowResized(); + // Pure virtual function to be overriden by the dervice class + // Called in case of an event where e.g. the framebuffer has to be rebuild and thus + // all command buffers that may reference this + virtual void buildCommandBuffers(); // Get memory type for a given memory allocation (flags and bits) VkBool32 getMemoryType(uint32_t typeBits, VkFlags properties, uint32_t *typeIndex);