|
@@ -5,11 +5,13 @@
|
|
|
|
|
|
#include "GLFW.hpp"
|
|
|
#include "core/VulkanBase.hpp"
|
|
|
+#include "core/WindowManager.hpp"
|
|
|
|
|
|
namespace Vulkan = Core::Vulkan;
|
|
|
using Vulkan::CommandBuffer;
|
|
|
using Vulkan::Queue;
|
|
|
using Vulkan::SwapchainImages;
|
|
|
+using Vulkan::SwapchainResult;
|
|
|
|
|
|
#define WRAPPER_DESTRUCT(Type, ...) \
|
|
|
using Core::Vulkan::Type; \
|
|
@@ -17,6 +19,8 @@ using Vulkan::SwapchainImages;
|
|
|
if(device != VK_NULL_HANDLE) { \
|
|
|
vkDestroy##Type##__VA_ARGS__(device, handle, nullptr); \
|
|
|
} \
|
|
|
+ device = VK_NULL_HANDLE; \
|
|
|
+ handle = VK_NULL_HANDLE; \
|
|
|
}
|
|
|
|
|
|
WRAPPER_DESTRUCT(ImageView)
|
|
@@ -31,6 +35,7 @@ WRAPPER_DESTRUCT(CommandPool)
|
|
|
WRAPPER_DESTRUCT(RenderPass)
|
|
|
|
|
|
bool ImageView::init(VkDevice d, VkImage image, VkFormat format) {
|
|
|
+ ImageView::~ImageView();
|
|
|
VkImageViewCreateInfo info = {
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
|
|
.image = image,
|
|
@@ -49,6 +54,7 @@ bool ImageView::init(VkDevice d, VkImage image, VkFormat format) {
|
|
|
|
|
|
bool Framebuffer::init(
|
|
|
const ImageView& iv, VkRenderPass rp, u32 width, u32 height) {
|
|
|
+ Framebuffer::~Framebuffer();
|
|
|
VkFramebufferCreateInfo info = {
|
|
|
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
|
|
.renderPass = rp,
|
|
@@ -63,6 +69,7 @@ bool Framebuffer::init(
|
|
|
}
|
|
|
|
|
|
bool Semaphore::init(VkDevice d) {
|
|
|
+ Semaphore::~Semaphore();
|
|
|
VkSemaphoreCreateInfo info = {
|
|
|
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
|
|
|
VK_CHECK_TRUE(vkCreateSemaphore(d, &info, nullptr, &handle));
|
|
@@ -71,6 +78,7 @@ bool Semaphore::init(VkDevice d) {
|
|
|
}
|
|
|
|
|
|
bool Fence::init(VkDevice d) {
|
|
|
+ Fence::~Fence();
|
|
|
VkFenceCreateInfo info = {
|
|
|
.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
|
|
|
.flags = VK_FENCE_CREATE_SIGNALED_BIT};
|
|
@@ -98,6 +106,7 @@ static u32 getSwapImageCount(const VkSurfaceCapabilitiesKHR* caps) {
|
|
|
}
|
|
|
|
|
|
bool Swapchain::init(Data& d) {
|
|
|
+ Swapchain::~Swapchain();
|
|
|
VkSurfaceCapabilitiesKHR caps = {0};
|
|
|
if(d.base.getSurfaceCapabilities(caps)) {
|
|
|
return true;
|
|
@@ -124,13 +133,21 @@ bool Swapchain::init(Data& d) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-bool Swapchain::nextImage(u32& imageIndex, Semaphore& s, u64 timeout) {
|
|
|
- VK_CHECK_TRUE(vkAcquireNextImageKHR(
|
|
|
- device, handle, timeout, s, VK_NULL_HANDLE, &imageIndex));
|
|
|
- return false;
|
|
|
+SwapchainResult Swapchain::nextImage(
|
|
|
+ u32& imageIndex, Semaphore& s, u64 timeout) {
|
|
|
+ VkResult r = vkAcquireNextImageKHR(
|
|
|
+ device, handle, timeout, s, VK_NULL_HANDLE, &imageIndex);
|
|
|
+ if(r == VK_SUBOPTIMAL_KHR) {
|
|
|
+ return SwapchainResult::RECREATE;
|
|
|
+ } else if(r == VK_ERROR_OUT_OF_DATE_KHR) {
|
|
|
+ return SwapchainResult::ERROR_RECREATE;
|
|
|
+ }
|
|
|
+ VK_CHECK(SwapchainResult::ERROR, r);
|
|
|
+ return SwapchainResult::SUCCESS;
|
|
|
}
|
|
|
|
|
|
bool ShaderModule::init(VkDevice d, const char* path) {
|
|
|
+ ShaderModule::~ShaderModule();
|
|
|
List<char> f;
|
|
|
if(Core::readFile(f, path)) {
|
|
|
return true;
|
|
@@ -150,6 +167,7 @@ bool ShaderModule::init(VkDevice d, const char* path) {
|
|
|
}
|
|
|
|
|
|
bool PipelineLayout::init(VkDevice d) {
|
|
|
+ PipelineLayout::~PipelineLayout();
|
|
|
VkPipelineLayoutCreateInfo info = {
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO};
|
|
|
VK_CHECK_TRUE(vkCreatePipelineLayout(d, &info, nullptr, &handle));
|
|
@@ -172,6 +190,7 @@ bool SwapchainImages::init(const Swapchain& s, VkFormat format) {
|
|
|
}
|
|
|
|
|
|
bool RenderPass::init(VkDevice d, VkFormat format) {
|
|
|
+ RenderPass::~RenderPass();
|
|
|
VkAttachmentDescription c = {
|
|
|
.format = format,
|
|
|
.samples = VK_SAMPLE_COUNT_1_BIT,
|
|
@@ -219,6 +238,7 @@ void Pipeline::updateSize(u32 width, u32 height) {
|
|
|
}
|
|
|
|
|
|
bool Pipeline::init(PipelineLayout& pl, RenderPass& rp) {
|
|
|
+ Pipeline::~Pipeline();
|
|
|
ShaderModule vertexShaderModule;
|
|
|
ShaderModule fragmentShaderModule;
|
|
|
if(vertexShaderModule.init(pl.device, "shaders/vertex.spv") ||
|
|
@@ -325,6 +345,7 @@ bool Pipeline::init(PipelineLayout& pl, RenderPass& rp) {
|
|
|
}
|
|
|
|
|
|
bool CommandPool::init(VkDevice d, u32 queueFamily) {
|
|
|
+ CommandPool::~CommandPool();
|
|
|
VkCommandPoolCreateInfo info = {
|
|
|
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
|
|
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
|
|
@@ -335,6 +356,7 @@ bool CommandPool::init(VkDevice d, u32 queueFamily) {
|
|
|
}
|
|
|
|
|
|
bool CommandBuffer::init(CommandPool& cp) {
|
|
|
+ CommandBuffer::~CommandBuffer();
|
|
|
VkCommandBufferAllocateInfo info = {
|
|
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
|
|
.commandPool = cp,
|
|
@@ -406,7 +428,7 @@ void Queue::submit(
|
|
|
VK_CHECK_VOID(vkQueueSubmit(handle, 1, &info, f));
|
|
|
}
|
|
|
|
|
|
-void Queue::present(Semaphore& signal, Swapchain& s, u32 index) {
|
|
|
+SwapchainResult Queue::present(Semaphore& signal, Swapchain& s, u32 index) {
|
|
|
VkPresentInfoKHR info = {
|
|
|
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
|
|
.waitSemaphoreCount = 1,
|
|
@@ -414,7 +436,14 @@ void Queue::present(Semaphore& signal, Swapchain& s, u32 index) {
|
|
|
.swapchainCount = 1,
|
|
|
.pSwapchains = s,
|
|
|
.pImageIndices = &index};
|
|
|
- VK_CHECK_VOID(vkQueuePresentKHR(handle, &info));
|
|
|
+ VkResult r = vkQueuePresentKHR(handle, &info);
|
|
|
+ if(r == VK_SUBOPTIMAL_KHR) {
|
|
|
+ return SwapchainResult::RECREATE;
|
|
|
+ } else if(r == VK_ERROR_OUT_OF_DATE_KHR) {
|
|
|
+ return SwapchainResult::ERROR_RECREATE;
|
|
|
+ }
|
|
|
+ VK_CHECK(SwapchainResult::ERROR, r);
|
|
|
+ return SwapchainResult::SUCCESS;
|
|
|
}
|
|
|
|
|
|
struct VulkanDummy {
|
|
@@ -439,7 +468,6 @@ struct VulkanDummy {
|
|
|
Core::List<Vulkan::Framebuffer> framebuffers{};
|
|
|
CommandPool commandPool{};
|
|
|
size_t currentFrame = 0;
|
|
|
- bool shouldWait = false;
|
|
|
|
|
|
struct Frame {
|
|
|
CommandBuffer commandBuffer{};
|
|
@@ -648,18 +676,28 @@ struct VulkanDummy {
|
|
|
commandPool.init(base, baseData.graphicsFamily) || initFrames();
|
|
|
}
|
|
|
|
|
|
- bool render() {
|
|
|
- if(shouldWait) {
|
|
|
- return false;
|
|
|
+ bool recreateSwapchain() {
|
|
|
+ LOG_INFO("Recreate swapchain");
|
|
|
+ base.waitForIdle();
|
|
|
+ if(initSwapchain() || initSwapchainImages() || initFramebuffers()) {
|
|
|
+ return true;
|
|
|
}
|
|
|
+ pipeline.updateSize(swapchainSize.width, swapchainSize.height);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool render() {
|
|
|
Frame& f = frames[currentFrame];
|
|
|
f.inFlightFence.waitFor();
|
|
|
- f.inFlightFence.reset();
|
|
|
|
|
|
u32 imageIndex = 0;
|
|
|
- if(swapchain.nextImage(imageIndex, f.imageAvailableSemaphore)) {
|
|
|
- return true;
|
|
|
+ switch(swapchain.nextImage(imageIndex, f.imageAvailableSemaphore)) {
|
|
|
+ case SwapchainResult::SUCCESS: break;
|
|
|
+ case SwapchainResult::RECREATE: break;
|
|
|
+ case SwapchainResult::ERROR_RECREATE: return recreateSwapchain();
|
|
|
+ case SwapchainResult::ERROR: return true;
|
|
|
}
|
|
|
+ f.inFlightFence.reset();
|
|
|
f.commandBuffer.reset();
|
|
|
fillCommandBuffer(f.commandBuffer, imageIndex);
|
|
|
|
|
@@ -668,8 +706,18 @@ struct VulkanDummy {
|
|
|
f.renderFinishedSemaphore,
|
|
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
|
|
|
|
|
- presentQueue.present(f.renderFinishedSemaphore, swapchain, imageIndex);
|
|
|
+ bool recreate = false;
|
|
|
+ switch(presentQueue.present(
|
|
|
+ f.renderFinishedSemaphore, swapchain, imageIndex)) {
|
|
|
+ case SwapchainResult::SUCCESS: break;
|
|
|
+ case SwapchainResult::RECREATE:
|
|
|
+ case SwapchainResult::ERROR_RECREATE: recreate = true;
|
|
|
+ case SwapchainResult::ERROR: break;
|
|
|
+ }
|
|
|
currentFrame = (currentFrame + 1) % frames.getLength();
|
|
|
+ if(recreate || Core::Window::hasSizeChanged()) {
|
|
|
+ recreateSwapchain();
|
|
|
+ }
|
|
|
return false;
|
|
|
}
|
|
|
};
|
|
@@ -682,9 +730,7 @@ bool Vulkan::init() {
|
|
|
}
|
|
|
|
|
|
void Vulkan::render() {
|
|
|
- if(dummy->render()) {
|
|
|
- dummy->shouldWait = true;
|
|
|
- }
|
|
|
+ dummy->render();
|
|
|
}
|
|
|
|
|
|
void Vulkan::destroy() {
|