Skip to content

Commit 7493e71

Browse files
committed
Handled resize and minimization
1 parent 188dcb1 commit 7493e71

File tree

1 file changed

+111
-45
lines changed

1 file changed

+111
-45
lines changed

main.c

+111-45
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ const char* WIN_TITLE = "SeEngine";
1818
const u32 WIN_WIDTH = 800;
1919
const u32 WIN_HEIGHT = 600;
2020

21+
const int MAX_FRAMES_IN_FLIGHT = 2;
22+
23+
u32 currentFrame = 0;
24+
bool framebufferResized = false;
25+
26+
2127
const u32 validationLayerCount = 1;
2228
const char *validationLayers[] = { "VK_LAYER_KHRONOS_validation" };
2329
const u32 deviceExtensionCount = 1;
@@ -65,10 +71,10 @@ typedef struct App {
6571
VkPipeline graphicsPipeline;
6672
VkFramebuffer *swapChainFramebuffers;
6773
VkCommandPool commandPool;
68-
VkCommandBuffer commandBuffer;
69-
VkSemaphore imageAvailableSemaphore;
70-
VkSemaphore renderFinishedSemaphore;
71-
VkFence inFlightFence;
74+
VkCommandBuffer *commandBuffers;
75+
VkSemaphore *imageAvailableSemaphores;
76+
VkSemaphore *renderFinishedSemaphores;
77+
VkFence *inFlightFences;
7278
} App;
7379

7480
void initWindow(App *pApp);
@@ -116,7 +122,9 @@ VkPresentModeKHR chooseSwapPresentMode(u32 presentModeCount, VkPresentModeKHR *a
116122
VkSurfaceFormatKHR chooseSwapSurfaceFormat(u32 formatCount, VkSurfaceFormatKHR *availableFormats);
117123
VkExtent2D chooseSwapExtent(GLFWwindow *window, VkSurfaceCapabilitiesKHR capabilities);
118124

125+
void cleanupSwapChain(App *pApp);
119126
void createSwapChain(App *pApp);
127+
void recreateSwapChain(App *pApp);
120128

121129
void createImageViews(App *pApp);
122130

@@ -127,7 +135,7 @@ void createGraphicsPipeline(App *pApp);
127135
void createFramebuffers(App *pApp);
128136

129137
void createCommandPool(App *pApp);
130-
void createCommandBuffer(App *pApp);
138+
void createCommandBuffers(App *pApp);
131139

132140
void createSyncObjects(App *pApp);
133141

@@ -146,13 +154,19 @@ int main(void) {
146154
return 0;
147155
}
148156

157+
void framebufferResizeCallback(GLFWwindow *window, int width, int height) {
158+
// App *app = glfwGetWindowUserPointer(window);
159+
framebufferResized = true;
160+
}
161+
149162
void initWindow(App *pApp) {
150163
glfwInit();
151164

152165
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
153-
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
154166

155167
pApp->window = glfwCreateWindow(WIN_WIDTH, WIN_HEIGHT, WIN_TITLE, NULL, NULL);
168+
// glfwSetWindowUserPointer(pApp->window, pApp);
169+
glfwSetFramebufferSizeCallback(pApp->window, framebufferResizeCallback);
156170
}
157171

158172
void initVulkan(App *pApp) {
@@ -167,7 +181,7 @@ void initVulkan(App *pApp) {
167181
createGraphicsPipeline(pApp);
168182
createFramebuffers(pApp);
169183
createCommandPool(pApp);
170-
createCommandBuffer(pApp);
184+
createCommandBuffers(pApp);
171185
createSyncObjects(pApp);
172186
}
173187

@@ -181,26 +195,20 @@ void mainLoop(App *pApp) {
181195
}
182196

183197
void cleanup(App *pApp) {
184-
vkDestroySemaphore(pApp->device, pApp->imageAvailableSemaphore, NULL);
185-
vkDestroySemaphore(pApp->device, pApp->renderFinishedSemaphore, NULL);
186-
vkDestroyFence(pApp->device, pApp->inFlightFence, NULL);
187-
188-
vkDestroyCommandPool(pApp->device, pApp->commandPool, NULL);
198+
cleanupSwapChain(pApp);
189199

190-
for (u32 i = 0; i < pApp->swapChainImageCount; i++) {
191-
vkDestroyFramebuffer(pApp->device, pApp->swapChainFramebuffers[i], NULL);
200+
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
201+
vkDestroySemaphore(pApp->device, pApp->imageAvailableSemaphores[i], NULL);
202+
vkDestroySemaphore(pApp->device, pApp->renderFinishedSemaphores[i], NULL);
203+
vkDestroyFence(pApp->device, pApp->inFlightFences[i], NULL);
192204
}
193205

206+
vkDestroyCommandPool(pApp->device, pApp->commandPool, NULL);
207+
194208
vkDestroyPipeline(pApp->device, pApp->graphicsPipeline, NULL);
195209
vkDestroyPipelineLayout(pApp->device, pApp->pipelineLayout, NULL);
196210
vkDestroyRenderPass(pApp->device, pApp->renderPass, NULL);
197211

198-
for (u32 i = 0; i < pApp->swapChainImageCount; i++) {
199-
vkDestroyImageView(pApp->device, pApp->swapChainImageViews[i], NULL);
200-
}
201-
202-
vkDestroySwapchainKHR(pApp->device, pApp->swapChain, NULL);
203-
204212
if (enableValidationLayers) {
205213
DestroyDebugUtilsMessengerEXT(pApp->instance, pApp->debugMessenger, NULL);
206214
}
@@ -463,7 +471,36 @@ void createSwapChain(App *pApp) {
463471
pApp->swapChainExtent = extent;
464472
}
465473

466-
void createImageViews(App *pApp) {
474+
void cleanupSwapChain(App *pApp) {
475+
for (u32 i = 0; i < pApp->swapChainImageCount; i++) {
476+
vkDestroyFramebuffer(pApp->device, pApp->swapChainFramebuffers[i], NULL);
477+
}
478+
479+
for (u32 i = 0; i < pApp->swapChainImageCount; i++) {
480+
vkDestroyImageView(pApp->device, pApp->swapChainImageViews[i], NULL);
481+
}
482+
483+
vkDestroySwapchainKHR(pApp->device, pApp->swapChain, NULL);
484+
}
485+
486+
void recreateSwapChain(App *pApp) {
487+
int width = 0, height = 0;
488+
glfwGetFramebufferSize(pApp->window, &width, &height);
489+
while (width == 0 || height == 0) {
490+
glfwGetFramebufferSize(pApp->window, &width, &height);
491+
glfwWaitEvents();
492+
}
493+
494+
vkDeviceWaitIdle(pApp->device);
495+
496+
cleanupSwapChain(pApp);
497+
498+
createSwapChain(pApp);
499+
createImageViews(pApp);
500+
createFramebuffers(pApp);
501+
}
502+
503+
void createImageViews(App *pApp) {
467504
pApp->swapChainImageViews = (VkImageView*)malloc(sizeof(VkImageView) * pApp->swapChainImageCount);
468505

469506
for (u32 i = 0; i < pApp->swapChainImageCount; i++) {
@@ -825,69 +862,88 @@ void createCommandPool(App *pApp) {
825862
}
826863
}
827864

828-
void createCommandBuffer(App *pApp) {
865+
void createCommandBuffers(App *pApp) {
866+
pApp->commandBuffers = (VkCommandBuffer*)malloc(sizeof(VkCommandBuffer) * MAX_FRAMES_IN_FLIGHT);
867+
829868
VkCommandBufferAllocateInfo allocInfo = {};
830869
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
831870
allocInfo.commandPool = pApp->commandPool;
832871
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
833-
allocInfo.commandBufferCount = 1;
872+
allocInfo.commandBufferCount = MAX_FRAMES_IN_FLIGHT;
834873

835-
if (vkAllocateCommandBuffers(pApp->device, &allocInfo, &pApp->commandBuffer) != VK_SUCCESS) {
874+
if (vkAllocateCommandBuffers(pApp->device, &allocInfo, pApp->commandBuffers) != VK_SUCCESS) {
836875
printf("failed to allocate command buffers!\n");
837876
exit(12);
838877
}
839878
}
840879

841880
void createSyncObjects(App *pApp) {
881+
pApp->imageAvailableSemaphores = (VkSemaphore*)malloc(sizeof(VkSemaphore) * MAX_FRAMES_IN_FLIGHT);
882+
pApp->renderFinishedSemaphores = (VkSemaphore*)malloc(sizeof(VkSemaphore) * MAX_FRAMES_IN_FLIGHT);
883+
pApp->inFlightFences = (VkFence*)malloc(sizeof(VkFence) * MAX_FRAMES_IN_FLIGHT);
884+
842885
VkSemaphoreCreateInfo semaphoreInfo = {};
843886
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
844887

845888
VkFenceCreateInfo fenceInfo = {};
846889
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
847890
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
848891

849-
if (vkCreateSemaphore(pApp->device, &semaphoreInfo, NULL, &pApp->imageAvailableSemaphore) != VK_SUCCESS) {
850-
printf("Failed to create imageAvailableSemaphore!\n");
851-
exit(15);
852-
}
853-
if (vkCreateSemaphore(pApp->device, &semaphoreInfo, NULL, &pApp->renderFinishedSemaphore) != VK_SUCCESS) {
854-
printf("Failed to create renderFinishedSemaphore!\n");
855-
exit(15);
856-
}
857-
if (vkCreateFence(pApp->device, &fenceInfo, NULL, &pApp->inFlightFence) != VK_SUCCESS) {
858-
printf("Failed to create fence!\n");
859-
exit(15);
892+
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
893+
if (vkCreateSemaphore(pApp->device, &semaphoreInfo, NULL, &pApp->imageAvailableSemaphores[i]) != VK_SUCCESS) {
894+
printf("Failed to create imageAvailableSemaphore!\n");
895+
exit(15);
896+
}
897+
if (vkCreateSemaphore(pApp->device, &semaphoreInfo, NULL, &pApp->renderFinishedSemaphores[i]) != VK_SUCCESS) {
898+
printf("Failed to create renderFinishedSemaphore!\n");
899+
exit(15);
900+
}
901+
if (vkCreateFence(pApp->device, &fenceInfo, NULL, &pApp->inFlightFences[i]) != VK_SUCCESS) {
902+
printf("Failed to create fence!\n");
903+
exit(15);
904+
}
860905
}
861906
}
862907

863908
void drawFrame(App *pApp) {
864-
vkWaitForFences(pApp->device, 1, &pApp->inFlightFence, VK_TRUE, UINT64_MAX);
909+
vkWaitForFences(pApp->device, 1, &pApp->inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
865910

866-
vkResetFences(pApp->device, 1, &pApp->inFlightFence);
911+
vkResetFences(pApp->device, 1, &pApp->inFlightFences[currentFrame]);
867912

868913
uint32_t imageIndex;
869-
vkAcquireNextImageKHR(pApp->device, pApp->swapChain, UINT64_MAX, pApp->imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
914+
VkResult result = vkAcquireNextImageKHR(pApp->device, pApp->swapChain, UINT64_MAX, pApp->imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
915+
916+
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
917+
recreateSwapChain(pApp);
918+
return;
919+
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
920+
printf("Failed to acquire swap chain image!\n");
921+
exit(17);
922+
}
923+
924+
// Only reset the fence if we are submitting work
925+
vkResetFences(pApp->device, 1, &pApp->inFlightFences[currentFrame]);
870926

871-
vkResetCommandBuffer(pApp->commandBuffer, 0);
872-
recordCommandBuffer(pApp, pApp->commandBuffer, imageIndex);
927+
vkResetCommandBuffer(pApp->commandBuffers[currentFrame], 0);
928+
recordCommandBuffer(pApp, pApp->commandBuffers[currentFrame], imageIndex);
873929

874930
VkSubmitInfo submitInfo = {};
875931
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
876932

877-
VkSemaphore waitSemaphores[] = { pApp->imageAvailableSemaphore };
933+
VkSemaphore waitSemaphores[] = { pApp->imageAvailableSemaphores[currentFrame] };
878934
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
879935
submitInfo.waitSemaphoreCount = 1;
880936
submitInfo.pWaitSemaphores = waitSemaphores;
881937
submitInfo.pWaitDstStageMask = waitStages;
882938

883939
submitInfo.commandBufferCount = 1;
884-
submitInfo.pCommandBuffers = &pApp->commandBuffer;
940+
submitInfo.pCommandBuffers = &pApp->commandBuffers[currentFrame];
885941

886-
VkSemaphore signalSemaphores[] = { pApp->renderFinishedSemaphore };
942+
VkSemaphore signalSemaphores[] = { pApp->renderFinishedSemaphores[currentFrame] };
887943
submitInfo.signalSemaphoreCount = 1;
888944
submitInfo.pSignalSemaphores = signalSemaphores;
889945

890-
if (vkQueueSubmit(pApp->graphicsQueue, 1, &submitInfo, pApp->inFlightFence) != VK_SUCCESS) {
946+
if (vkQueueSubmit(pApp->graphicsQueue, 1, &submitInfo, pApp->inFlightFences[currentFrame]) != VK_SUCCESS) {
891947
printf("Failed to submit draw command buffer!\n");
892948
exit(16);
893949
}
@@ -905,7 +961,17 @@ void drawFrame(App *pApp) {
905961

906962
presentInfo.pResults = NULL; // Optional
907963

908-
vkQueuePresentKHR(pApp->presentQueue, &presentInfo);
964+
VkResult queueResult = vkQueuePresentKHR(pApp->presentQueue, &presentInfo);
965+
966+
if (queueResult == VK_ERROR_OUT_OF_DATE_KHR || queueResult == VK_SUBOPTIMAL_KHR || framebufferResized) {
967+
framebufferResized = false;
968+
recreateSwapChain(pApp);
969+
} else if (queueResult != VK_SUCCESS) {
970+
printf("Failed to present swap chain image!\n");
971+
exit(17);
972+
}
973+
974+
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
909975
}
910976

911977
bool checkDeviceExtensionSupport(VkPhysicalDevice device) {

0 commit comments

Comments
 (0)