Well window resizing works but we have a major memory leak
This commit is contained in:
parent
a6c3d2b0f2
commit
83eebb7674
1 changed files with 91 additions and 31 deletions
122
src/main.c
122
src/main.c
|
|
@ -41,6 +41,8 @@ const char *validationLayers[] = {"VK_LAYER_KHRONOS_validation"};
|
|||
size_t validationLayerCount =
|
||||
sizeof(validationLayers) / sizeof(validationLayers[0]);
|
||||
|
||||
static bool framebufferResized; // initialised to 0
|
||||
|
||||
typedef struct Application {
|
||||
GLFWwindow *window;
|
||||
VkInstance instance;
|
||||
|
|
@ -64,9 +66,9 @@ typedef struct Application {
|
|||
uint32_t swapChainFramebufferCount;
|
||||
VkCommandPool commandPool;
|
||||
VkCommandBuffer commandBuffers[MAX_FRAMES_IN_FLIGHT];
|
||||
VkSemaphore imageAvailableSemaphore[MAX_FRAMES_IN_FLIGHT];
|
||||
VkSemaphore imageAvailableSemaphores[MAX_FRAMES_IN_FLIGHT];
|
||||
VkSemaphore renderFinishedSemaphore[MAX_FRAMES_IN_FLIGHT];
|
||||
VkFence inFlightFence[MAX_FRAMES_IN_FLIGHT];
|
||||
VkFence inFlightFences[MAX_FRAMES_IN_FLIGHT];
|
||||
uint32_t currentFrame; // initialised to 0
|
||||
} Application;
|
||||
|
||||
|
|
@ -204,11 +206,18 @@ void createInstance(Application *app) {
|
|||
}
|
||||
}
|
||||
|
||||
static void framebufferResizeCallback(GLFWwindow *window, int width,
|
||||
int height) {
|
||||
framebufferResized = true;
|
||||
}
|
||||
|
||||
void initWindow(Application *app) {
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
|
||||
app->window = glfwCreateWindow(800, 600, "Vulkan", NULL, NULL);
|
||||
|
||||
glfwSetFramebufferSizeCallback(app->window, framebufferResizeCallback);
|
||||
}
|
||||
|
||||
VkResult CreateDebugUtilsMessengerEXT(
|
||||
|
|
@ -997,10 +1006,10 @@ void createSyncObjects(Application *app) {
|
|||
|
||||
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||
if (vkCreateSemaphore(app->device, &semaphoreInfo, NULL,
|
||||
&app->imageAvailableSemaphore[i]) != VK_SUCCESS ||
|
||||
&app->imageAvailableSemaphores[i]) != VK_SUCCESS ||
|
||||
vkCreateSemaphore(app->device, &semaphoreInfo, NULL,
|
||||
&app->renderFinishedSemaphore[i]) != VK_SUCCESS ||
|
||||
vkCreateFence(app->device, &fenceInfo, NULL, &app->inFlightFence[i]) !=
|
||||
vkCreateFence(app->device, &fenceInfo, NULL, &app->inFlightFences[i]) !=
|
||||
VK_SUCCESS) {
|
||||
fprintf(stderr, "Failed to create semaphores!");
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -1008,6 +1017,37 @@ void createSyncObjects(Application *app) {
|
|||
}
|
||||
}
|
||||
|
||||
void cleanupSwapChain(Application *app) {
|
||||
for (size_t i = 0; i < app->swapChainFramebufferCount; i++) {
|
||||
vkDestroyFramebuffer(app->device, app->swapChainFramebuffers[i], NULL);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < app->swapChainImageViewCount; i++) {
|
||||
vkDestroyImageView(app->device, app->swapChainImageViews[i], NULL);
|
||||
}
|
||||
|
||||
vkDestroySwapchainKHR(app->device, app->swapChain, NULL);
|
||||
}
|
||||
|
||||
void recreateSwapChain(Application *app) {
|
||||
int width = 0, height = 0;
|
||||
glfwGetFramebufferSize(app->window, &width, &height);
|
||||
while (width == 0 || height == 0) {
|
||||
glfwGetFramebufferSize(app->window, &width, &height);
|
||||
glfwWaitEvents();
|
||||
}
|
||||
|
||||
vkDeviceWaitIdle(app->device);
|
||||
|
||||
free(app->swapChainFramebuffers);
|
||||
free(app->swapChainImageViews);
|
||||
free(app->swapChainImages);
|
||||
|
||||
createSwapChain(app);
|
||||
createImageViews(app);
|
||||
createFramebuffers(app);
|
||||
}
|
||||
|
||||
void initVulkan(Application *app) {
|
||||
createInstance(app);
|
||||
setupDebugMessenger(app);
|
||||
|
|
@ -1025,20 +1065,33 @@ void initVulkan(Application *app) {
|
|||
}
|
||||
|
||||
void drawFrame(Application *app) {
|
||||
vkWaitForFences(app->device, 1, &app->inFlightFence[app->currentFrame], VK_TRUE, UINT64_MAX);
|
||||
vkResetFences(app->device, 1, &app->inFlightFence[app->currentFrame]);
|
||||
vkWaitForFences(app->device, 1, &app->inFlightFences[app->currentFrame],
|
||||
VK_TRUE, UINT64_MAX);
|
||||
|
||||
uint32_t imageIndex;
|
||||
vkAcquireNextImageKHR(app->device, app->swapChain, UINT64_MAX,
|
||||
app->imageAvailableSemaphore[app->currentFrame], VK_NULL_HANDLE,
|
||||
&imageIndex);
|
||||
VkResult result =
|
||||
vkAcquireNextImageKHR(app->device, app->swapChain, UINT64_MAX,
|
||||
app->imageAvailableSemaphores[app->currentFrame],
|
||||
VK_NULL_HANDLE, &imageIndex);
|
||||
|
||||
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||
recreateSwapChain(app);
|
||||
return;
|
||||
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
|
||||
fprintf(stderr, "Failed to acquire swap chain image!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Only reset the fence if we are submitting work
|
||||
vkResetFences(app->device, 1, &app->inFlightFences[app->currentFrame]);
|
||||
|
||||
vkResetCommandBuffer(app->commandBuffers[app->currentFrame], 0);
|
||||
recordCommandBuffer(app, app->commandBuffers[app->currentFrame], imageIndex);
|
||||
VkSubmitInfo submitInfo = {0};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
|
||||
VkSemaphore waitSemaphores[] = {app->imageAvailableSemaphore[app->currentFrame]};
|
||||
VkSemaphore waitSemaphores[] = {
|
||||
app->imageAvailableSemaphores[app->currentFrame]};
|
||||
VkPipelineStageFlags waitStages[] = {
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
||||
submitInfo.waitSemaphoreCount = 1;
|
||||
|
|
@ -1046,12 +1099,13 @@ void drawFrame(Application *app) {
|
|||
submitInfo.pWaitDstStageMask = waitStages;
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &app->commandBuffers[app->currentFrame];
|
||||
VkSemaphore signalSemaphores[] = {app->renderFinishedSemaphore[app->currentFrame]};
|
||||
VkSemaphore signalSemaphores[] = {
|
||||
app->renderFinishedSemaphore[app->currentFrame]};
|
||||
submitInfo.signalSemaphoreCount = 1;
|
||||
submitInfo.pSignalSemaphores = signalSemaphores;
|
||||
|
||||
if (vkQueueSubmit(app->graphicsQueue, 1, &submitInfo, app->inFlightFence[app->currentFrame]) !=
|
||||
VK_SUCCESS) {
|
||||
if (vkQueueSubmit(app->graphicsQueue, 1, &submitInfo,
|
||||
app->inFlightFences[app->currentFrame]) != VK_SUCCESS) {
|
||||
fprintf(stderr, "failed to submit draw command buffer!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
@ -1066,7 +1120,15 @@ void drawFrame(Application *app) {
|
|||
presentInfo.pImageIndices = &imageIndex;
|
||||
presentInfo.pResults = NULL; // Optional
|
||||
|
||||
vkQueuePresentKHR(app->presentQueue, &presentInfo);
|
||||
result = vkQueuePresentKHR(app->presentQueue, &presentInfo);
|
||||
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR ||
|
||||
framebufferResized) {
|
||||
framebufferResized = false;
|
||||
recreateSwapChain(app);
|
||||
} else if (result != VK_SUCCESS) {
|
||||
fprintf(stderr, "failed to present swap chain image!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
app->currentFrame = (app->currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||
}
|
||||
|
|
@ -1081,25 +1143,23 @@ void mainLoop(Application *app) {
|
|||
}
|
||||
|
||||
void cleanup(Application *app) {
|
||||
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||
vkDestroySemaphore(app->device, app->imageAvailableSemaphore[i], NULL);
|
||||
vkDestroySemaphore(app->device, app->renderFinishedSemaphore[i], NULL);
|
||||
vkDestroyFence(app->device, app->inFlightFence[i], NULL);
|
||||
}
|
||||
vkDestroyCommandPool(app->device, app->commandPool, NULL);
|
||||
for (uint i = 0; i < app->swapChainFramebufferCount; i++) {
|
||||
vkDestroyFramebuffer(app->device, app->swapChainFramebuffers[i], NULL);
|
||||
}
|
||||
cleanupSwapChain(app);
|
||||
free(app->swapChainFramebuffers);
|
||||
vkDestroyPipeline(app->device, app->graphicsPipeline, NULL);
|
||||
vkDestroyPipelineLayout(app->device, app->pipelineLayout, NULL);
|
||||
vkDestroyRenderPass(app->device, app->renderPass, NULL);
|
||||
for (size_t i = 0; i < app->swapChainImageViewCount; i++) {
|
||||
vkDestroyImageView(app->device, app->swapChainImageViews[i], NULL);
|
||||
}
|
||||
free(app->swapChainImageViews);
|
||||
free(app->swapChainImages);
|
||||
vkDestroySwapchainKHR(app->device, app->swapChain, NULL);
|
||||
|
||||
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
|
||||
vkDestroySemaphore(app->device, app->imageAvailableSemaphores[i], NULL);
|
||||
vkDestroySemaphore(app->device, app->renderFinishedSemaphore[i], NULL);
|
||||
vkDestroyFence(app->device, app->inFlightFences[i], NULL);
|
||||
}
|
||||
vkDestroyCommandPool(app->device, app->commandPool, NULL);
|
||||
|
||||
vkDestroyPipeline(app->device, app->graphicsPipeline, NULL);
|
||||
vkDestroyPipelineLayout(app->device, app->pipelineLayout, NULL);
|
||||
|
||||
vkDestroyRenderPass(app->device, app->renderPass, NULL);
|
||||
|
||||
vkDestroyDevice(app->device, NULL);
|
||||
if (enableValidationLayers) {
|
||||
DestroyDebugUtilsMessengerEXT(app->instance, app->debugMessenger, NULL);
|
||||
|
|
|
|||
Loading…
Reference in a new issue