diff options
| -rw-r--r-- | assets/shaders/present.frag | 10 | ||||
| -rw-r--r-- | src/window.cpp | 164 | ||||
| -rw-r--r-- | src/window.hpp | 2 |
3 files changed, 130 insertions, 46 deletions
diff --git a/assets/shaders/present.frag b/assets/shaders/present.frag index 695f7bd..427468c 100644 --- a/assets/shaders/present.frag +++ b/assets/shaders/present.frag @@ -1,16 +1,10 @@ #version 450 -layout (binding = 0) uniform sampler2D samplerColor; - layout (location = 0) in vec2 inUV; layout (location = 0) out vec4 outFragColor; void main() { - vec4 color = texture(samplerColor, inUV); - if (color.w == 0) { - discard; - } - outFragColor = color; -}
\ No newline at end of file + outFragColor = vec4(0, 0, 0, 1); +} diff --git a/src/window.cpp b/src/window.cpp index dda6efe..4d816ca 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1,4 +1,3 @@ -#include <vulkan/vulkan_core.h> #define GLFW_INCLUDE_NONE #define GLFW_INCLUDE_VULKAN @@ -33,6 +32,7 @@ unsigned int presentFamilyIndex; /* * Instantiation */ +bool shouldRecreateSwapchain = false; unsigned int CURRENT_FRAME = 0; unsigned int selectedSurfaceIndex = -1u; unsigned int selectedPresentIndex = -1u; @@ -43,16 +43,21 @@ VkPresentModeKHR vkPresentModeKHR; VkExtent2D extent; VkImage *swapchainImages = nullptr; VkImageView *swapchainImageViews = nullptr; +VkSampler presentSampler; VkRenderPass renderPass; VkDescriptorSetLayout vkDescriptorSetLayout; +/* +VkDescriptorPool presentDescriptorPool; +VkDescriptorSet *presentDescriptorSets = nullptr; +*/ VkPipelineLayout pipelineLayout; VkPipeline graphicsPipeline; VkFramebuffer *swapchainFramebuffers = nullptr; VkCommandPool vkCommandPool; -VkCommandBuffer commandBuffer; -VkSemaphore imageAvailableSemaphore; -VkSemaphore renderFinishedSemaphore; -VkFence inFlightFence; +VkCommandBuffer presentCommandBuffers[MAX_FRAMES_IN_FLIGHT]; +VkSemaphore presentImageAvailableSemaphores[MAX_FRAMES_IN_FLIGHT]; +VkSemaphore presentRenderFinishedSemaphores[MAX_FRAMES_IN_FLIGHT]; +VkFence presentInFlightFences[MAX_FRAMES_IN_FLIGHT]; const std::vector<const char *> REQUIRED_EXTENSIONS = std::vector<const char *> { VK_KHR_SWAPCHAIN_EXTENSION_NAME @@ -350,6 +355,28 @@ void InitVulkan() { vkGetDeviceQueue(vkDevice, graphicsFamilyIndex, 0, &graphicsQueue); vkGetDeviceQueue(vkDevice, presentFamilyIndex, 0, &presentQueue); } + + // generic present sampler + VkSamplerCreateInfo samplerCreateInfo{}; + samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + samplerCreateInfo.flags = 0U; + samplerCreateInfo.magFilter = VK_FILTER_NEAREST; + samplerCreateInfo.minFilter = VK_FILTER_NEAREST; + samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCreateInfo.mipLodBias = 0.0f; + samplerCreateInfo.anisotropyEnable = VK_FALSE; + samplerCreateInfo.maxAnisotropy = 1.0f; + samplerCreateInfo.compareEnable = VK_FALSE; + samplerCreateInfo.compareOp = {}; + samplerCreateInfo.minLod = 0.0f; + samplerCreateInfo.maxLod = 1.0f; + samplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + samplerCreateInfo.unnormalizedCoordinates = {}; + + vkCreateSampler(vkDevice, &samplerCreateInfo, vkAllocator, &presentSampler); } void CreateSwapchain() { @@ -624,24 +651,55 @@ void CreateGraphicsPipeline() { * PipelineLayout + DescriptorSets */ + /* VkDescriptorSetLayoutBinding imageSamplerLayoutBinding{}; imageSamplerLayoutBinding.binding = 0; imageSamplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; imageSamplerLayoutBinding.descriptorCount = 1; imageSamplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; imageSamplerLayoutBinding.pImmutableSamplers = nullptr; + */ VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo{}; descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; descriptorSetLayoutCreateInfo.flags = 0; + descriptorSetLayoutCreateInfo.bindingCount = 0; + descriptorSetLayoutCreateInfo.pBindings = nullptr; + /* descriptorSetLayoutCreateInfo.bindingCount = 1; descriptorSetLayoutCreateInfo.pBindings = &imageSamplerLayoutBinding; + */ auto result = vkCreateDescriptorSetLayout(vkDevice, &descriptorSetLayoutCreateInfo, vkAllocator, &vkDescriptorSetLayout); if (result != VK_SUCCESS) { throw "failed to create descriptor set layout"; } + /* + VkDescriptorPoolSize vkDescriptorPoolSize{}; + vkDescriptorPoolSize.descriptorCount = swapchainLength; + vkDescriptorPoolSize.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + + VkDescriptorPoolCreateInfo descriptorPoolCreateInfo{}; + descriptorPoolCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + descriptorPoolCreateInfo.flags = 0; + descriptorPoolCreateInfo.maxSets = 1; + descriptorPoolCreateInfo.poolSizeCount = 1; + descriptorPoolCreateInfo.pPoolSizes = &vkDescriptorPoolSize; + descriptorPoolCreateInfo.pNext = nullptr; + + vkCreateDescriptorPool(vkDevice, &descriptorPoolCreateInfo, vkAllocator, &presentDescriptorPool); + + VkDescriptorSetAllocateInfo allocInfo{}; + allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + allocInfo.descriptorPool = presentDescriptorPool; + allocInfo.descriptorSetCount = 1; + allocInfo.pSetLayouts = &vkDescriptorSetLayout; + allocInfo.pNext = nullptr; + + vkAllocateDescriptorSets(vkDevice, &allocInfo, presentDescriptorSets); + */ + VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipelineLayoutInfo.setLayoutCount = 1; @@ -680,9 +738,10 @@ void CreateGraphicsPipeline() { throw "failed to create graphics pipeline."; } - VkWriteDescriptorSet writeDescriptorSets[2]; - VkDescriptorImageInfo descriptorImageInfo[2]; - for (long i = 0; i < 2; ++i) { + /* + VkWriteDescriptorSet writeDescriptorSets[3]; + VkDescriptorImageInfo descriptorImageInfo[3]; + for (long i = 0; i < 3; ++i) { writeDescriptorSets[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; // writeDescriptorSets[i].dstSet = VK_NULL_HANDLE; writeDescriptorSets[i].dstBinding = 0U; @@ -697,15 +756,16 @@ void CreateGraphicsPipeline() { descriptorImageInfo[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } - for (long i = 0; i < 2; ++i) { - descriptorImageInfo[i].sampler = nullptr; // TODO + for (long i = 0; i < 3; ++i) { + descriptorImageInfo[i].sampler = presentSampler; descriptorImageInfo[i].imageView = swapchainImageViews[i]; writeDescriptorSets[i].pImageInfo = &descriptorImageInfo[i]; - writeDescriptorSets[i].dstSet = nullptr; // TODO + writeDescriptorSets[i].dstSet = presentDescriptorSets[i]; } vkUpdateDescriptorSets(vkDevice, 2, writeDescriptorSets, 0, nullptr); + */ vkDestroyShaderModule(vkDevice, fragShader, vkAllocator); vkDestroyShaderModule(vkDevice, vertShader, vkAllocator); @@ -754,9 +814,9 @@ void CreateCommandBuffer() { allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.commandPool = vkCommandPool; allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandBufferCount = 1; + allocInfo.commandBufferCount = MAX_FRAMES_IN_FLIGHT; - auto result = vkAllocateCommandBuffers(vkDevice, &allocInfo, &commandBuffer); + auto result = vkAllocateCommandBuffers(vkDevice, &allocInfo, presentCommandBuffers); if (result != VK_SUCCESS) { throw "failed to allocate command buffer"; } @@ -770,12 +830,14 @@ void CreateSyncObjects() { fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - auto result1 = vkCreateSemaphore(vkDevice, &semaphoreInfo, vkAllocator, &imageAvailableSemaphore); - auto result2 = vkCreateSemaphore(vkDevice, &semaphoreInfo, vkAllocator, &renderFinishedSemaphore); - auto result3 = vkCreateFence(vkDevice, &fenceInfo, vkAllocator, &inFlightFence); - auto result = result1 == result2 && result2 == result3 && result3 == VK_SUCCESS; - if (!result) { - throw "failed to create sync objects"; + for (long i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { + auto result1 = vkCreateSemaphore(vkDevice, &semaphoreInfo, vkAllocator, &presentImageAvailableSemaphores[i]); + auto result2 = vkCreateSemaphore(vkDevice, &semaphoreInfo, vkAllocator, &presentRenderFinishedSemaphores[i]); + auto result3 = vkCreateFence(vkDevice, &fenceInfo, vkAllocator, &presentInFlightFences[i]); + auto result = result1 == result2 && result2 == result3 && result3 == VK_SUCCESS; + if (!result) { + throw "failed to create sync objects"; + } } } @@ -850,15 +912,26 @@ void DestroySwapchain() { swapchainFramebuffers = CAFE_BABE(VkFramebuffer); } +void RecreateSwapchain() { + int width, height = 0; + glfwGetFramebufferSize(window, &width, &height); + while (width == 0 || height == 0) { + glfwGetFramebufferSize(window, &width, &height); + glfwWaitEvents(); + } + DestroySwapchain(); + CreateSwapchain(); + CreateFramebuffers(); + shouldRecreateSwapchain = false; +} + void FramebufferResizeCallback(GLFWwindow *window, int width, int height) { if (extent.width == width && extent.height != height) { return; } - DestroySwapchain(); extent.width = width; extent.height = height; - CreateSwapchain(); - CreateFramebuffers(); + shouldRecreateSwapchain = true; } void CreateWindow(PKEWindowProperties *wp) { @@ -880,16 +953,21 @@ void CreateWindow(PKEWindowProperties *wp) { void DestroyWindow() { if (vkInstance == nullptr) return; DestroySwapchain(); - vkDestroySemaphore(vkDevice, imageAvailableSemaphore, vkAllocator); - vkDestroySemaphore(vkDevice, renderFinishedSemaphore, vkAllocator); - vkDestroyFence(vkDevice, inFlightFence, vkAllocator); + for (long i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { + vkDestroySemaphore(vkDevice, presentImageAvailableSemaphores[i], vkAllocator); + vkDestroySemaphore(vkDevice, presentRenderFinishedSemaphores[i], vkAllocator); + vkDestroyFence(vkDevice, presentInFlightFences[i], vkAllocator); + } vkDestroyCommandPool(vkDevice, vkCommandPool, vkAllocator); vkDestroyPipeline(vkDevice, graphicsPipeline, vkAllocator); vkDestroyPipelineLayout(vkDevice, pipelineLayout, vkAllocator); + /* + vkDestroyDescriptorPool(vkDevice, presentDescriptorPool, vkAllocator); + */ vkDestroyDescriptorSetLayout(vkDevice, vkDescriptorSetLayout, vkAllocator); vkDestroyRenderPass(vkDevice, renderPass, vkAllocator); - DestroySwapchain(); vkDestroySurfaceKHR(vkInstance, vkSurfaceKHR, vkAllocator); + vkDestroySampler(vkDevice, presentSampler, vkAllocator); vkDestroyDevice(vkDevice, vkAllocator); if (VULKAN_DEBUG_REPORT) { auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(vkInstance, "vkDestroyDebugReportCallbackEXT"); @@ -918,18 +996,25 @@ VkShaderModule UploadShader(AssetHandle handle) { void PreRender() {} void Render() { - vkWaitForFences(vkDevice, 1, &inFlightFence, VK_TRUE, UINT64_MAX); + vkWaitForFences(vkDevice, 1, &presentInFlightFences[CURRENT_FRAME], VK_TRUE, UINT64_MAX); uint32_t imageIndex; - vkAcquireNextImageKHR(vkDevice, vkSwapchainKHR, UINT64_MAX, imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex); + auto result = vkAcquireNextImageKHR(vkDevice, vkSwapchainKHR, UINT64_MAX, presentImageAvailableSemaphores[CURRENT_FRAME], VK_NULL_HANDLE, &imageIndex); + + if (result == VK_ERROR_OUT_OF_DATE_KHR) { + RecreateSwapchain(); + return; + } else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) { + throw "failed to acquire swapchain"; + } - vkResetFences(vkDevice, 1, &inFlightFence); + vkResetFences(vkDevice, 1, &presentInFlightFences[CURRENT_FRAME]); - vkResetCommandBuffer(commandBuffer, 0); - RecordCommandBuffer(commandBuffer, imageIndex); + vkResetCommandBuffer(presentCommandBuffers[CURRENT_FRAME], 0); + RecordCommandBuffer(presentCommandBuffers[CURRENT_FRAME], imageIndex); - VkSemaphore waitSemaphores[] = {imageAvailableSemaphore}; - VkSemaphore signalSemaphores[] = {renderFinishedSemaphore}; + VkSemaphore waitSemaphores[] = {presentImageAvailableSemaphores[CURRENT_FRAME]}; + VkSemaphore signalSemaphores[] = {presentRenderFinishedSemaphores[CURRENT_FRAME]}; VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; VkSubmitInfo submitInfo{}; @@ -938,11 +1023,11 @@ void Render() { submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitDstStageMask = waitStages; submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &commandBuffer; + submitInfo.pCommandBuffers = &presentCommandBuffers[CURRENT_FRAME]; submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = signalSemaphores; - auto result = vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFence); + result = vkQueueSubmit(graphicsQueue, 1, &submitInfo, presentInFlightFences[CURRENT_FRAME]); if (result != VK_SUCCESS) { throw "failed to submit queue"; } @@ -958,9 +1043,14 @@ void Render() { presentInfo.pImageIndices = &imageIndex; presentInfo.pResults = nullptr; - vkQueuePresentKHR(presentQueue, &presentInfo); + result = vkQueuePresentKHR(presentQueue, &presentInfo); + if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || shouldRecreateSwapchain) { + RecreateSwapchain(); + } else if (result != VK_SUCCESS) { + throw "failed to present swapchain image"; + } - CURRENT_FRAME = (CURRENT_FRAME + 1) % swapchainLength; + CURRENT_FRAME = (CURRENT_FRAME + 1) % MAX_FRAMES_IN_FLIGHT; } void PostRender() {} diff --git a/src/window.hpp b/src/window.hpp index b7a4e05..27f809c 100644 --- a/src/window.hpp +++ b/src/window.hpp @@ -7,7 +7,7 @@ #include <GLFW/glfw3.h> #include <vulkan/vulkan.h> -const unsigned int MAX_FRAMES_IN_FLIGHT = 3; +const unsigned int MAX_FRAMES_IN_FLIGHT = 2; extern GLFWwindow *window; extern VkInstance vkInstance; |
