@@ -189,7 +189,7 @@ class MultithreadedApplication {
189189
190190 double lastFrameTime = 0.0 ;
191191
192- // Removed resize-related variables and FSM state management as per simplification request
192+ bool framebufferResized = false ;
193193
194194 double lastTime = 0 .0f ;
195195
@@ -240,7 +240,7 @@ class MultithreadedApplication {
240240 []( const auto & format ) { return format.format == vk::Format::eB8G8R8A8Srgb && format.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear; } );
241241 return formatIt != availableFormats.end () ? *formatIt : availableFormats[0 ];
242242 }
243-
243+
244244 static vk::PresentModeKHR chooseSwapPresentMode (const std::vector<vk::PresentModeKHR>& availablePresentModes) {
245245 assert (std::ranges::any_of (availablePresentModes, [](auto presentMode){ return presentMode == vk::PresentModeKHR::eFifo; }));
246246 return std::ranges::any_of (availablePresentModes,
@@ -282,14 +282,22 @@ class MultithreadedApplication {
282282 glfwInit ();
283283
284284 glfwWindowHint (GLFW_CLIENT_API, GLFW_NO_API);
285- glfwWindowHint (GLFW_RESIZABLE, GLFW_FALSE );
285+ glfwWindowHint (GLFW_RESIZABLE, GLFW_TRUE );
286286
287287 window = glfwCreateWindow (WIDTH, HEIGHT, " Vulkan Multithreading" , nullptr , nullptr );
288288 glfwSetWindowUserPointer (window, this );
289+ glfwSetFramebufferSizeCallback (window, framebufferResizeCallback);
289290
290291 lastTime = glfwGetTime ();
291292 }
292293
294+ static void framebufferResizeCallback (GLFWwindow* window, int , int ) {
295+ auto app = reinterpret_cast <MultithreadedApplication*>(glfwGetWindowUserPointer (window));
296+ if (app) {
297+ app->framebufferResized = true ;
298+ }
299+ }
300+
293301 void initVulkan () {
294302 createInstance ();
295303 createSurface ();
@@ -439,6 +447,28 @@ class MultithreadedApplication {
439447 swapChain = nullptr ;
440448 }
441449
450+ void recreateSwapChain () {
451+ int width = 0 , height = 0 ;
452+ glfwGetFramebufferSize (window, &width, &height);
453+ while (width == 0 || height == 0 ) {
454+ glfwGetFramebufferSize (window, &width, &height);
455+ glfwWaitEvents ();
456+ }
457+ device.waitIdle ();
458+
459+ cleanupSwapChain ();
460+
461+ createSwapChain ();
462+ createImageViews ();
463+ createComputeDescriptorSetLayout ();
464+ createGraphicsPipeline ();
465+ createComputePipeline ();
466+ createShaderStorageBuffers ();
467+ createUniformBuffers ();
468+ createDescriptorPool ();
469+ createComputeDescriptorSets ();
470+ }
471+
442472 void stopThreads () {
443473 shouldExit.store (true , std::memory_order_release);
444474
@@ -1075,10 +1105,22 @@ class MultithreadedApplication {
10751105 // Wait for the previous frame to finish
10761106 while (vk::Result::eTimeout == device.waitForFences (*inFlightFences[currentFrame], vk::True, UINT64_MAX))
10771107 ;
1078- device.resetFences (*inFlightFences[currentFrame]);
1108+
1109+ // If the framebuffer was resized, rebuild the swap chain before acquiring a new image
1110+ if (framebufferResized) {
1111+ recreateSwapChain ();
1112+ framebufferResized = false ;
1113+ return ;
1114+ }
10791115
10801116 // Acquire the next image
10811117 auto [result, imageIndex] = swapChain.acquireNextImage (UINT64_MAX, *imageAvailableSemaphores[currentFrame], nullptr );
1118+ if (result == vk::Result::eErrorOutOfDateKHR) {
1119+ recreateSwapChain ();
1120+ return ;
1121+ } else if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) {
1122+ throw std::runtime_error (" failed to acquire swap chain image!" );
1123+ }
10821124
10831125 // Update timeline values for synchronization
10841126 uint64_t computeWaitValue = timelineValue;
@@ -1168,6 +1210,7 @@ class MultithreadedApplication {
11681210 // Submit graphics work
11691211 {
11701212 std::lock_guard<std::mutex> lock (queueSubmitMutex);
1213+ device.resetFences (*inFlightFences[currentFrame]);
11711214 queue.submit (graphicsSubmitInfo, *inFlightFences[currentFrame]);
11721215 }
11731216
@@ -1194,6 +1237,13 @@ class MultithreadedApplication {
11941237 };
11951238
11961239 result = queue.presentKHR (presentInfo);
1240+ if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized) {
1241+ framebufferResized = false ;
1242+ recreateSwapChain ();
1243+ return ;
1244+ } else if (result != vk::Result::eSuccess) {
1245+ throw std::runtime_error (" failed to present swap chain image!" );
1246+ }
11971247
11981248 // Move to the next frame
11991249 currentFrame = (currentFrame + 1 ) % MAX_FRAMES_IN_FLIGHT;
0 commit comments