diff --git a/src/main.c b/src/main.c index 5cbc30a..014847b 100644 --- a/src/main.c +++ b/src/main.c @@ -62,6 +62,10 @@ typedef struct Application { uint32_t swapChainFramebufferCount; VkCommandPool commandPool; VkCommandBuffer commandBuffer; + VkSemaphore imageAvailableSemaphore; + VkSemaphore renderFinishedSemaphore; + VkFence inFlightFence; + } Application; typedef struct SwapChainSupportDetails { @@ -846,12 +850,22 @@ void createRenderPass(Application *app) { subpass.colorAttachmentCount = 1; subpass.pColorAttachments = &colorAttachmentRef; + VkSubpassDependency dependency = {0}; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.srcAccessMask = 0; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + VkRenderPassCreateInfo renderPassInfo = {0}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; renderPassInfo.attachmentCount = 1; renderPassInfo.pAttachments = &colorAttachment; renderPassInfo.subpassCount = 1; renderPassInfo.pSubpasses = &subpass; + renderPassInfo.dependencyCount = 1; + renderPassInfo.pDependencies = &dependency; if (vkCreateRenderPass(app->device, &renderPassInfo, NULL, &app->renderPass) != VK_SUCCESS) { @@ -971,6 +985,25 @@ void createCommandBuffer(Application *app) { } } +void createSyncObjects(Application *app) { + VkSemaphoreCreateInfo semaphoreInfo = {0}; + semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + VkFenceCreateInfo fenceInfo = {0}; + fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; + + if (vkCreateSemaphore(app->device, &semaphoreInfo, NULL, + &app->imageAvailableSemaphore) != VK_SUCCESS || + vkCreateSemaphore(app->device, &semaphoreInfo, NULL, + &app->renderFinishedSemaphore) != VK_SUCCESS || + vkCreateFence(app->device, &fenceInfo, NULL, &app->inFlightFence) != + VK_SUCCESS) { + fprintf(stderr, "Failed to create semaphores!"); + exit(EXIT_FAILURE); + } +} + void initVulkan(Application *app) { createInstance(app); setupDebugMessenger(app); @@ -984,15 +1017,67 @@ void initVulkan(Application *app) { createFramebuffers(app); CreateCommandPool(app); createCommandBuffer(app); + createSyncObjects(app); +} + +void drawFrame(Application *app) { + vkWaitForFences(app->device, 1, &app->inFlightFence, VK_TRUE, UINT64_MAX); + vkResetFences(app->device, 1, &app->inFlightFence); + + uint32_t imageIndex; + vkAcquireNextImageKHR(app->device, app->swapChain, UINT64_MAX, + app->imageAvailableSemaphore, VK_NULL_HANDLE, + &imageIndex); + + vkResetCommandBuffer(app->commandBuffer, 0); + recordCommandBuffer(app, app->commandBuffer, imageIndex); + VkSubmitInfo submitInfo = {0}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + + VkSemaphore waitSemaphores[] = {app->imageAvailableSemaphore}; + VkPipelineStageFlags waitStages[] = { + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; + submitInfo.waitSemaphoreCount = 1; + submitInfo.pWaitSemaphores = waitSemaphores; + submitInfo.pWaitDstStageMask = waitStages; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &app->commandBuffer; + VkSemaphore signalSemaphores[] = {app->renderFinishedSemaphore}; + submitInfo.signalSemaphoreCount = 1; + submitInfo.pSignalSemaphores = signalSemaphores; + + if (vkQueueSubmit(app->graphicsQueue, 1, &submitInfo, app->inFlightFence) != + VK_SUCCESS) { + fprintf(stderr, "failed to submit draw command buffer!"); + exit(EXIT_FAILURE); + } + + VkPresentInfoKHR presentInfo = {0}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.waitSemaphoreCount = 1; + presentInfo.pWaitSemaphores = signalSemaphores; + VkSwapchainKHR swapChains[] = {app->swapChain}; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = swapChains; + presentInfo.pImageIndices = &imageIndex; + presentInfo.pResults = NULL; // Optional + + vkQueuePresentKHR(app->presentQueue, &presentInfo); } void mainLoop(Application *app) { while (!glfwWindowShouldClose(app->window)) { glfwPollEvents(); + drawFrame(app); } + + vkDeviceWaitIdle(app->device); } void cleanup(Application *app) { + vkDestroySemaphore(app->device, app->imageAvailableSemaphore, NULL); + vkDestroySemaphore(app->device, app->renderFinishedSemaphore, NULL); + vkDestroyFence(app->device, app->inFlightFence, NULL); vkDestroyCommandPool(app->device, app->commandPool, NULL); for (uint i = 0; i < app->swapChainFramebufferCount; i++) { vkDestroyFramebuffer(app->device, app->swapChainFramebuffers[i], NULL);