@@ -30,17 +30,14 @@ bool handleMessage() {
3030 return true ;
3131}
3232
33- void initApplication (SDL_Window* window) {
34- uint32_t instanceExtensionCount;
35- SDL_Vulkan_GetInstanceExtensions (window, &instanceExtensionCount, 0 );
36- const char ** enabledInstanceExtensions = new const char * [instanceExtensionCount];
37- SDL_Vulkan_GetInstanceExtensions (window, &instanceExtensionCount, enabledInstanceExtensions);
38-
39- const char * enabledDeviceExtensions[]{ VK_KHR_SWAPCHAIN_EXTENSION_NAME };
40- context = initVulkan (instanceExtensionCount, enabledInstanceExtensions, ARRAY_COUNT (enabledDeviceExtensions), enabledDeviceExtensions);
41-
42- SDL_Vulkan_CreateSurface (window, context->instance , &surface);
43- swapchain = createSwapchain (context, surface, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
33+ void recreateRenderPass () {
34+ if (renderPass) {
35+ for (uint32_t i = 0 ; i < framebuffers.size (); ++i) {
36+ VK (vkDestroyFramebuffer (context->device , framebuffers[i], 0 ));
37+ }
38+ destroyRenderpass (context, renderPass);
39+ }
40+ framebuffers.clear ();
4441
4542 renderPass = createRenderPass (context, swapchain.format );
4643 framebuffers.resize (swapchain.images .size ());
@@ -54,6 +51,21 @@ void initApplication(SDL_Window* window) {
5451 createInfo.layers = 1 ;
5552 VKA (vkCreateFramebuffer (context->device , &createInfo, 0 , &framebuffers[i]));
5653 }
54+ }
55+
56+ void initApplication (SDL_Window* window) {
57+ uint32_t instanceExtensionCount;
58+ SDL_Vulkan_GetInstanceExtensions (window, &instanceExtensionCount, 0 );
59+ const char ** enabledInstanceExtensions = new const char * [instanceExtensionCount];
60+ SDL_Vulkan_GetInstanceExtensions (window, &instanceExtensionCount, enabledInstanceExtensions);
61+
62+ const char * enabledDeviceExtensions[]{ VK_KHR_SWAPCHAIN_EXTENSION_NAME };
63+ context = initVulkan (instanceExtensionCount, enabledInstanceExtensions, ARRAY_COUNT (enabledDeviceExtensions), enabledDeviceExtensions);
64+
65+ SDL_Vulkan_CreateSurface (window, context->instance , &surface);
66+ swapchain = createSwapchain (context, surface, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
67+
68+ recreateRenderPass ();
5769
5870 pipeline = createPipeline (context, " ../shaders/triangle_vert.spv" , " ../shaders/triangle_frag.spv" , renderPass, swapchain.width , swapchain.height );
5971
@@ -83,6 +95,23 @@ void initApplication(SDL_Window* window) {
8395 }
8496}
8597
98+ void recreateSwapchain () {
99+ VulkanSwapchain oldSwapchain = swapchain;
100+
101+ VkSurfaceCapabilitiesKHR surfaceCapabilities;
102+ VKA (vkGetPhysicalDeviceSurfaceCapabilitiesKHR (context->physicalDevice , surface, &surfaceCapabilities));
103+ if (surfaceCapabilities.currentExtent .width == 0 || surfaceCapabilities.currentExtent .height == 0 ) {
104+ return ;
105+ }
106+
107+
108+ VKA (vkDeviceWaitIdle (context->device ));
109+ swapchain = createSwapchain (context, surface, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, &oldSwapchain);
110+
111+ destroySwapchain (context, &oldSwapchain);
112+ recreateRenderPass ();
113+ }
114+
86115void renderApplication () {
87116 static float greenChannel = 0 .0f ;
88117 greenChannel += 0 .01f ;
@@ -94,7 +123,14 @@ void renderApplication() {
94123 VKA (vkWaitForFences (context->device , 1 , &fences[frameIndex], VK_TRUE, UINT64_MAX));
95124 VKA (vkResetFences (context->device , 1 , &fences[frameIndex]));
96125
97- VK (vkAcquireNextImageKHR (context->device , swapchain.swapchain , UINT64_MAX, acquireSemaphores[frameIndex], 0 , &imageIndex));
126+ VkResult result = VK (vkAcquireNextImageKHR (context->device , swapchain.swapchain , UINT64_MAX, acquireSemaphores[frameIndex], 0 , &imageIndex));
127+ if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
128+ // Swapchain is out of date
129+ recreateSwapchain ();
130+ return ;
131+ } else {
132+ ASSERT_VULKAN (result);
133+ }
98134
99135 VKA (vkResetCommandPool (context->device , commandPools[frameIndex], 0 ));
100136
@@ -104,6 +140,11 @@ void renderApplication() {
104140 VkCommandBuffer commandBuffer = commandBuffers[frameIndex];
105141 VKA (vkBeginCommandBuffer (commandBuffer, &beginInfo));
106142
143+ VkViewport viewport = { 0 .0f , 0 .0f , (float )swapchain.width , (float )swapchain.height };
144+ VkRect2D scissor = { {0 , 0 }, {swapchain.width , swapchain.height } };
145+ vkCmdSetViewport (commandBuffer, 0 , 1 , &viewport);
146+ vkCmdSetScissor (commandBuffer, 0 , 1 , &scissor);
147+
107148 VkClearValue clearValue = {0 .0f , greenChannel, 1 .0f , 1 .0f };
108149 VkRenderPassBeginInfo beginInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO };
109150 beginInfo.renderPass = renderPass;
@@ -114,6 +155,7 @@ void renderApplication() {
114155 vkCmdBeginRenderPass (commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
115156
116157 vkCmdBindPipeline (commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline );
158+
117159 vkCmdDraw (commandBuffer, 3 , 1 , 0 , 0 );
118160
119161 vkCmdEndRenderPass (commandBuffer);
@@ -138,7 +180,13 @@ void renderApplication() {
138180 presentInfo.pImageIndices = &imageIndex;
139181 presentInfo.waitSemaphoreCount = 1 ;
140182 presentInfo.pWaitSemaphores = &releaseSemaphores[frameIndex];
141- VK (vkQueuePresentKHR (context->graphicsQueue .queue , &presentInfo));
183+ result = VK (vkQueuePresentKHR (context->graphicsQueue .queue , &presentInfo));
184+ if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
185+ // Swapchain is out of date
186+ recreateSwapchain ();
187+ } else {
188+ ASSERT_VULKAN (result);
189+ }
142190
143191 frameIndex = (frameIndex + 1 ) % FRAMES_IN_FLIGHT;
144192}
@@ -173,7 +221,7 @@ int main() {
173221 return 1 ;
174222 }
175223
176- SDL_Window* window = SDL_CreateWindow (" Vulkan Tutorial" , SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1240 , 720 , SDL_WINDOW_VULKAN);
224+ SDL_Window* window = SDL_CreateWindow (" Vulkan Tutorial" , SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1240 , 720 , SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE );
177225 if (!window) {
178226 LOG_ERROR (" Error creating SDL window" );
179227 return 1 ;
0 commit comments