@@ -18,6 +18,12 @@ const char* WIN_TITLE = "SeEngine";
18
18
const u32 WIN_WIDTH = 800 ;
19
19
const u32 WIN_HEIGHT = 600 ;
20
20
21
+ const int MAX_FRAMES_IN_FLIGHT = 2 ;
22
+
23
+ u32 currentFrame = 0 ;
24
+ bool framebufferResized = false;
25
+
26
+
21
27
const u32 validationLayerCount = 1 ;
22
28
const char * validationLayers [] = { "VK_LAYER_KHRONOS_validation" };
23
29
const u32 deviceExtensionCount = 1 ;
@@ -65,10 +71,10 @@ typedef struct App {
65
71
VkPipeline graphicsPipeline ;
66
72
VkFramebuffer * swapChainFramebuffers ;
67
73
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 ;
72
78
} App ;
73
79
74
80
void initWindow (App * pApp );
@@ -116,7 +122,9 @@ VkPresentModeKHR chooseSwapPresentMode(u32 presentModeCount, VkPresentModeKHR *a
116
122
VkSurfaceFormatKHR chooseSwapSurfaceFormat (u32 formatCount , VkSurfaceFormatKHR * availableFormats );
117
123
VkExtent2D chooseSwapExtent (GLFWwindow * window , VkSurfaceCapabilitiesKHR capabilities );
118
124
125
+ void cleanupSwapChain (App * pApp );
119
126
void createSwapChain (App * pApp );
127
+ void recreateSwapChain (App * pApp );
120
128
121
129
void createImageViews (App * pApp );
122
130
@@ -127,7 +135,7 @@ void createGraphicsPipeline(App *pApp);
127
135
void createFramebuffers (App * pApp );
128
136
129
137
void createCommandPool (App * pApp );
130
- void createCommandBuffer (App * pApp );
138
+ void createCommandBuffers (App * pApp );
131
139
132
140
void createSyncObjects (App * pApp );
133
141
@@ -146,13 +154,19 @@ int main(void) {
146
154
return 0 ;
147
155
}
148
156
157
+ void framebufferResizeCallback (GLFWwindow * window , int width , int height ) {
158
+ // App *app = glfwGetWindowUserPointer(window);
159
+ framebufferResized = true;
160
+ }
161
+
149
162
void initWindow (App * pApp ) {
150
163
glfwInit ();
151
164
152
165
glfwWindowHint (GLFW_CLIENT_API , GLFW_NO_API );
153
- glfwWindowHint (GLFW_RESIZABLE , GLFW_FALSE );
154
166
155
167
pApp -> window = glfwCreateWindow (WIN_WIDTH , WIN_HEIGHT , WIN_TITLE , NULL , NULL );
168
+ // glfwSetWindowUserPointer(pApp->window, pApp);
169
+ glfwSetFramebufferSizeCallback (pApp -> window , framebufferResizeCallback );
156
170
}
157
171
158
172
void initVulkan (App * pApp ) {
@@ -167,7 +181,7 @@ void initVulkan(App *pApp) {
167
181
createGraphicsPipeline (pApp );
168
182
createFramebuffers (pApp );
169
183
createCommandPool (pApp );
170
- createCommandBuffer (pApp );
184
+ createCommandBuffers (pApp );
171
185
createSyncObjects (pApp );
172
186
}
173
187
@@ -181,26 +195,20 @@ void mainLoop(App *pApp) {
181
195
}
182
196
183
197
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 );
189
199
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 );
192
204
}
193
205
206
+ vkDestroyCommandPool (pApp -> device , pApp -> commandPool , NULL );
207
+
194
208
vkDestroyPipeline (pApp -> device , pApp -> graphicsPipeline , NULL );
195
209
vkDestroyPipelineLayout (pApp -> device , pApp -> pipelineLayout , NULL );
196
210
vkDestroyRenderPass (pApp -> device , pApp -> renderPass , NULL );
197
211
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
-
204
212
if (enableValidationLayers ) {
205
213
DestroyDebugUtilsMessengerEXT (pApp -> instance , pApp -> debugMessenger , NULL );
206
214
}
@@ -463,7 +471,36 @@ void createSwapChain(App *pApp) {
463
471
pApp -> swapChainExtent = extent ;
464
472
}
465
473
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 ) {
467
504
pApp -> swapChainImageViews = (VkImageView * )malloc (sizeof (VkImageView ) * pApp -> swapChainImageCount );
468
505
469
506
for (u32 i = 0 ; i < pApp -> swapChainImageCount ; i ++ ) {
@@ -825,69 +862,88 @@ void createCommandPool(App *pApp) {
825
862
}
826
863
}
827
864
828
- void createCommandBuffer (App * pApp ) {
865
+ void createCommandBuffers (App * pApp ) {
866
+ pApp -> commandBuffers = (VkCommandBuffer * )malloc (sizeof (VkCommandBuffer ) * MAX_FRAMES_IN_FLIGHT );
867
+
829
868
VkCommandBufferAllocateInfo allocInfo = {};
830
869
allocInfo .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO ;
831
870
allocInfo .commandPool = pApp -> commandPool ;
832
871
allocInfo .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY ;
833
- allocInfo .commandBufferCount = 1 ;
872
+ allocInfo .commandBufferCount = MAX_FRAMES_IN_FLIGHT ;
834
873
835
- if (vkAllocateCommandBuffers (pApp -> device , & allocInfo , & pApp -> commandBuffer ) != VK_SUCCESS ) {
874
+ if (vkAllocateCommandBuffers (pApp -> device , & allocInfo , pApp -> commandBuffers ) != VK_SUCCESS ) {
836
875
printf ("failed to allocate command buffers!\n" );
837
876
exit (12 );
838
877
}
839
878
}
840
879
841
880
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
+
842
885
VkSemaphoreCreateInfo semaphoreInfo = {};
843
886
semaphoreInfo .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO ;
844
887
845
888
VkFenceCreateInfo fenceInfo = {};
846
889
fenceInfo .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO ;
847
890
fenceInfo .flags = VK_FENCE_CREATE_SIGNALED_BIT ;
848
891
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
+ }
860
905
}
861
906
}
862
907
863
908
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 );
865
910
866
- vkResetFences (pApp -> device , 1 , & pApp -> inFlightFence );
911
+ vkResetFences (pApp -> device , 1 , & pApp -> inFlightFences [ currentFrame ] );
867
912
868
913
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 ]);
870
926
871
- vkResetCommandBuffer (pApp -> commandBuffer , 0 );
872
- recordCommandBuffer (pApp , pApp -> commandBuffer , imageIndex );
927
+ vkResetCommandBuffer (pApp -> commandBuffers [ currentFrame ] , 0 );
928
+ recordCommandBuffer (pApp , pApp -> commandBuffers [ currentFrame ] , imageIndex );
873
929
874
930
VkSubmitInfo submitInfo = {};
875
931
submitInfo .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO ;
876
932
877
- VkSemaphore waitSemaphores [] = { pApp -> imageAvailableSemaphore };
933
+ VkSemaphore waitSemaphores [] = { pApp -> imageAvailableSemaphores [ currentFrame ] };
878
934
VkPipelineStageFlags waitStages [] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
879
935
submitInfo .waitSemaphoreCount = 1 ;
880
936
submitInfo .pWaitSemaphores = waitSemaphores ;
881
937
submitInfo .pWaitDstStageMask = waitStages ;
882
938
883
939
submitInfo .commandBufferCount = 1 ;
884
- submitInfo .pCommandBuffers = & pApp -> commandBuffer ;
940
+ submitInfo .pCommandBuffers = & pApp -> commandBuffers [ currentFrame ] ;
885
941
886
- VkSemaphore signalSemaphores [] = { pApp -> renderFinishedSemaphore };
942
+ VkSemaphore signalSemaphores [] = { pApp -> renderFinishedSemaphores [ currentFrame ] };
887
943
submitInfo .signalSemaphoreCount = 1 ;
888
944
submitInfo .pSignalSemaphores = signalSemaphores ;
889
945
890
- if (vkQueueSubmit (pApp -> graphicsQueue , 1 , & submitInfo , pApp -> inFlightFence ) != VK_SUCCESS ) {
946
+ if (vkQueueSubmit (pApp -> graphicsQueue , 1 , & submitInfo , pApp -> inFlightFences [ currentFrame ] ) != VK_SUCCESS ) {
891
947
printf ("Failed to submit draw command buffer!\n" );
892
948
exit (16 );
893
949
}
@@ -905,7 +961,17 @@ void drawFrame(App *pApp) {
905
961
906
962
presentInfo .pResults = NULL ; // Optional
907
963
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 ;
909
975
}
910
976
911
977
bool checkDeviceExtensionSupport (VkPhysicalDevice device ) {
0 commit comments