diff --git a/src/main.cpp b/src/main.cpp index 6e6249c..ada3ed1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,40 +41,40 @@ class VulkanApp { initWindow(); initVulkan(); mainLoop(); + cleanup(); } private: - vkfw::UniqueInstance mGLFWInstance; - vkfw::UniqueWindow mWindow; + vkfw::Window mWindow; - vk::UniqueInstance mInstance; + vk::Instance mInstance; - vk::UniqueDebugUtilsMessengerEXT mDebugMessenger; - vk::UniqueSurfaceKHR mSurface; + vk::DebugUtilsMessengerEXT mDebugMessenger; + vk::SurfaceKHR mSurface; vk::PhysicalDevice mPhysicalDevice; - vk::UniqueDevice mDevice; + vk::Device mDevice; vk::Queue mGraphicsQueue; vk::Queue mPresentQueue; - vk::UniqueSwapchainKHR mSwapChain; - std::vector mSwapChainImages; - vk::Format mSwapChainImageFormat; - vk::Extent2D mSwapChainExtent; - std::vector mSwapChainImageViews; - std::vector mSwapChainFramebuffers; + vk::SwapchainKHR mSwapChain; + std::vector mSwapChainImages; + vk::Format mSwapChainImageFormat; + vk::Extent2D mSwapChainExtent; + std::vector mSwapChainImageViews; + std::vector mSwapChainFramebuffers; - vk::UniqueRenderPass mRenderPass; - vk::UniquePipelineLayout mPipelineLayout; - vk::UniquePipeline mGraphicsPipeline; + vk::RenderPass mRenderPass; + vk::PipelineLayout mPipelineLayout; + vk::Pipeline mGraphicsPipeline; - vk::UniqueCommandPool mCommandPool; - std::vector mCommandBuffers; + vk::CommandPool mCommandPool; + std::vector mCommandBuffers; - std::vector mImageAvailableSemaphores; - std::vector mRenderFinishedSemaphores; - std::vector mInFlightFences; + std::vector mImageAvailableSemaphores; + std::vector mRenderFinishedSemaphores; + std::vector mInFlightFences; bool mFramebufferResized = false; u32 mCurrentFrame = 0; @@ -110,16 +110,16 @@ class VulkanApp { } fn initWindow() -> void { - mGLFWInstance = vkfw::initUnique(); + vkfw::init(); vkfw::WindowHints hints; hints.clientAPI = vkfw::ClientAPI::eNone; // hints.resizable = false; - mWindow = vkfw::createWindowUnique(WIDTH, HEIGHT, "Vulkan", hints); - mWindow->setUserPointer(this); - mWindow->setFramebufferSizeCallback(framebufferResizeCallback); + mWindow = vkfw::createWindow(WIDTH, HEIGHT, "Vulkan", hints); + mWindow.setUserPointer(this); + mWindow.setFramebufferSizeCallback(framebufferResizeCallback); } static fn framebufferResizeCallback(GLFWwindow* window, int /*width*/, int /*height*/) -> void { @@ -145,33 +145,67 @@ class VulkanApp { } fn mainLoop() -> void { - while (!mWindow->shouldClose()) { + while (!mWindow.shouldClose()) { vkfw::waitEvents(); drawFrame(); } - mDevice->waitIdle(); + mDevice.waitIdle(); } fn cleanupSwapChain() -> void { - for (vk::UniqueFramebuffer& mSwapChainFramebuffer : mSwapChainFramebuffers) { - mSwapChainFramebuffer.reset(); + for (vk::Framebuffer& mSwapChainFramebuffer : mSwapChainFramebuffers) { + mDevice.destroyFramebuffer(mSwapChainFramebuffer); + } + for (vk::ImageView& mSwapChainImageView : mSwapChainImageViews) { + mDevice.destroyImageView(mSwapChainImageView); } - for (vk::UniqueImageView& mSwapChainImageView : mSwapChainImageViews) { mSwapChainImageView.reset(); } - mSwapChain.reset(); + mDevice.destroySwapchainKHR(mSwapChain); + } + + fn cleanup() -> void { + cleanupSwapChain(); + + mDevice.destroyPipeline(mGraphicsPipeline); + mDevice.destroyPipelineLayout(mPipelineLayout); + + mDevice.destroyRenderPass(mRenderPass); + + for (vk::Semaphore& mRenderFinishedSemaphore : mRenderFinishedSemaphores) + mDevice.destroySemaphore(mRenderFinishedSemaphore); + + for (vk::Semaphore& mImageAvailableSemaphore : mImageAvailableSemaphores) + mDevice.destroySemaphore(mImageAvailableSemaphore); + + for (vk::Fence& mInFlightFence : mInFlightFences) mDevice.destroyFence(mInFlightFence); + + mDevice.destroyCommandPool(mCommandPool); + + mDevice.destroy(); + + if (enableValidationLayers) + mInstance.destroyDebugUtilsMessengerEXT(mDebugMessenger, nullptr); + + mInstance.destroySurfaceKHR(mSurface); + + vkDestroyInstance(mInstance, nullptr); + + mWindow.destroy(); + + glfwTerminate(); } fn recreateSwapChain() -> void { u32 width = 0, height = 0; - std::tie(width, height) = mWindow->getFramebufferSize(); + std::tie(width, height) = mWindow.getFramebufferSize(); while (width == 0 || height == 0) { - std::tie(width, height) = mWindow->getFramebufferSize(); + std::tie(width, height) = mWindow.getFramebufferSize(); vkfw::waitEvents(); } - mDevice->waitIdle(); + mDevice.waitIdle(); cleanupSwapChain(); @@ -219,9 +253,9 @@ class VulkanApp { for (const char* extension : extensions) fmt::println("\t{}", extension); #endif - mInstance = vk::createInstanceUnique(createInfo); + mInstance = vk::createInstance(createInfo); - VULKAN_HPP_DEFAULT_DISPATCHER.init(mInstance.get()); + VULKAN_HPP_DEFAULT_DISPATCHER.init(mInstance); } fn setupDebugMessenger() -> void { @@ -238,13 +272,13 @@ class VulkanApp { .pfnUserCallback = debugCallback, }; - mDebugMessenger = mInstance->createDebugUtilsMessengerEXTUnique(messengerCreateInfo, nullptr); + mDebugMessenger = mInstance.createDebugUtilsMessengerEXT(messengerCreateInfo, nullptr); } - fn createSurface() -> void { mSurface = vkfw::createWindowSurfaceUnique(mInstance.get(), mWindow.get()); } + fn createSurface() -> void { mSurface = vkfw::createWindowSurface(mInstance, mWindow); } fn pickPhysicalDevice() -> void { - std::vector devices = mInstance->enumeratePhysicalDevices(); + std::vector devices = mInstance.enumeratePhysicalDevices(); if (devices.empty()) throw std::runtime_error("Failed to find GPUs with Vulkan support!"); @@ -293,9 +327,9 @@ class VulkanApp { .ppEnabledExtensionNames = deviceExtensions.data(), .pEnabledFeatures = &deviceFeatures }; - mDevice = mPhysicalDevice.createDeviceUnique(createInfo); - mGraphicsQueue = mDevice->getQueue(indices.graphics_family.value(), 0); - mPresentQueue = mDevice->getQueue(indices.present_family.value(), 0); + mDevice = mPhysicalDevice.createDevice(createInfo); + mGraphicsQueue = mDevice.getQueue(indices.graphics_family.value(), 0); + mPresentQueue = mDevice.getQueue(indices.present_family.value(), 0); } fn createSwapChain() -> void { @@ -316,7 +350,7 @@ class VulkanApp { indices.present_family.value() }; vk::SwapchainCreateInfoKHR createInfo { - .surface = mSurface.get(), + .surface = mSurface, .minImageCount = imageCount, .imageFormat = surfaceFormat.format, .imageColorSpace = surfaceFormat.colorSpace, @@ -335,9 +369,9 @@ class VulkanApp { .oldSwapchain = nullptr, }; - mSwapChain = mDevice->createSwapchainKHRUnique(createInfo); + mSwapChain = mDevice.createSwapchainKHR(createInfo); - mSwapChainImages = mDevice->getSwapchainImagesKHR(mSwapChain.get()); + mSwapChainImages = mDevice.getSwapchainImagesKHR(mSwapChain); mSwapChainImageFormat = surfaceFormat.format; mSwapChainExtent = extent; } @@ -363,7 +397,7 @@ class VulkanApp { // clang-format on }; - mSwapChainImageViews[i] = mDevice->createImageViewUnique(createInfo); + mSwapChainImageViews[i] = mDevice.createImageView(createInfo); } } @@ -397,25 +431,25 @@ class VulkanApp { .pSubpasses = &subpass, }; - mRenderPass = mDevice->createRenderPassUnique(renderPassInfo); + mRenderPass = mDevice.createRenderPass(renderPassInfo); } fn createGraphicsPipeline() -> void { std::vector vertShaderCode = readFile("src/shaders/vert.spv"); std::vector fragShaderCode = readFile("src/shaders/frag.spv"); - vk::UniqueShaderModule vertShaderModule = createShaderModule(vertShaderCode); - vk::UniqueShaderModule fragShaderModule = createShaderModule(fragShaderCode); + vk::ShaderModule vertShaderModule = createShaderModule(vertShaderCode); + vk::ShaderModule fragShaderModule = createShaderModule(fragShaderCode); vk::PipelineShaderStageCreateInfo vertShaderStageInfo { .stage = vk::ShaderStageFlagBits::eVertex, - .module = vertShaderModule.get(), + .module = vertShaderModule, .pName = "main", }; vk::PipelineShaderStageCreateInfo fragShaderStageInfo { .stage = vk::ShaderStageFlagBits::eFragment, - .module = fragShaderModule.get(), + .module = fragShaderModule, .pName = "main", }; @@ -479,7 +513,7 @@ class VulkanApp { .pushConstantRangeCount = 0, }; - mPipelineLayout = mDevice->createPipelineLayoutUnique(pipelineLayoutInfo); + mPipelineLayout = mDevice.createPipelineLayout(pipelineLayoutInfo); vk::GraphicsPipelineCreateInfo pipelineInfo { .stageCount = static_cast(shaderStages.size()), @@ -491,21 +525,24 @@ class VulkanApp { .pMultisampleState = &multisampling, .pColorBlendState = &colorBlending, .pDynamicState = &dynamicState, - .layout = mPipelineLayout.get(), - .renderPass = mRenderPass.get(), + .layout = mPipelineLayout, + .renderPass = mRenderPass, .subpass = 0, }; - vk::Result graphicsPipelineResult = vk::Result::eSuccess; - vk::UniquePipeline graphicsPipelineValue; + vk::Result graphicsPipelineResult = vk::Result::eSuccess; + vk::Pipeline graphicsPipelineValue; std::tie(graphicsPipelineResult, graphicsPipelineValue) = - mDevice->createGraphicsPipelineUnique(nullptr, pipelineInfo).asTuple(); + mDevice.createGraphicsPipeline(nullptr, pipelineInfo); if (graphicsPipelineResult != vk::Result::eSuccess) throw std::runtime_error("Failed to create graphics pipeline!"); - mGraphicsPipeline = std::move(graphicsPipelineValue); + mGraphicsPipeline = graphicsPipelineValue; + + mDevice.destroyShaderModule(vertShaderModule); + mDevice.destroyShaderModule(fragShaderModule); } fn createFramebuffers() -> void { @@ -513,15 +550,15 @@ class VulkanApp { for (usize i = 0; i < mSwapChainImageViews.size(); i++) { vk::FramebufferCreateInfo framebufferInfo { - .renderPass = mRenderPass.get(), + .renderPass = mRenderPass, .attachmentCount = 1, - .pAttachments = &mSwapChainImageViews[i].get(), + .pAttachments = &mSwapChainImageViews[i], .width = mSwapChainExtent.width, .height = mSwapChainExtent.height, .layers = 1, }; - mSwapChainFramebuffers[i] = mDevice->createFramebufferUnique(framebufferInfo); + mSwapChainFramebuffers[i] = mDevice.createFramebuffer(framebufferInfo); } } @@ -533,18 +570,18 @@ class VulkanApp { .queueFamilyIndex = queueFamilyIndices.graphics_family.value(), }; - mCommandPool = mDevice->createCommandPoolUnique(poolInfo); + mCommandPool = mDevice.createCommandPool(poolInfo); } fn createCommandBuffers() -> void { mCommandBuffers.resize(MAX_FRAMES_IN_FLIGHT); - vk::CommandBufferAllocateInfo allocInfo { .commandPool = mCommandPool.get(), + vk::CommandBufferAllocateInfo allocInfo { .commandPool = mCommandPool, .level = vk::CommandBufferLevel::ePrimary, .commandBufferCount = static_cast(mCommandBuffers.size()) }; - mCommandBuffers = mDevice->allocateCommandBuffersUnique(allocInfo); + mCommandBuffers = mDevice.allocateCommandBuffers(allocInfo); } fn recordCommandBuffer(vk::CommandBuffer commandBuffer, u32 imageIndex) -> void { @@ -555,15 +592,15 @@ class VulkanApp { vk::ClearValue clearColor { .color = { .float32 = std::array { 0.0F, 0.0F, 0.0F, 1.0F } } }; vk::RenderPassBeginInfo renderPassInfo { - .renderPass = mRenderPass.get(), - .framebuffer = mSwapChainFramebuffers[imageIndex].get(), + .renderPass = mRenderPass, + .framebuffer = mSwapChainFramebuffers[imageIndex], .renderArea = { .offset = { .x = 0, .y = 0 }, .extent = mSwapChainExtent }, .clearValueCount = 1, .pClearValues = &clearColor, }; commandBuffer.beginRenderPass(renderPassInfo, vk::SubpassContents::eInline); - commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, mGraphicsPipeline.get()); + commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, mGraphicsPipeline); vk::Viewport viewport { .x = 0.0F, @@ -597,16 +634,16 @@ class VulkanApp { vk::FenceCreateInfo fenceInfo { .flags = vk::FenceCreateFlagBits::eSignaled }; for (usize idx = 0; idx < MAX_FRAMES_IN_FLIGHT; idx++) { - mImageAvailableSemaphores[idx] = mDevice->createSemaphoreUnique(semaphoreInfo); - mRenderFinishedSemaphores[idx] = mDevice->createSemaphoreUnique(semaphoreInfo); - mInFlightFences[idx] = mDevice->createFenceUnique(fenceInfo); + mImageAvailableSemaphores[idx] = mDevice.createSemaphore(semaphoreInfo); + mRenderFinishedSemaphores[idx] = mDevice.createSemaphore(semaphoreInfo); + mInFlightFences[idx] = mDevice.createFence(fenceInfo); } } fn drawFrame() -> void { try { vk::Result result = - mDevice->waitForFences(mInFlightFences[mCurrentFrame].get(), vk::Bool32(vk::True), UINT64_MAX); + mDevice.waitForFences(mInFlightFences[mCurrentFrame], vk::Bool32(vk::True), UINT64_MAX); if (result != vk::Result::eSuccess) throw std::runtime_error("Failed to wait for fences!"); @@ -614,8 +651,8 @@ class VulkanApp { vk::Result imageIndexResult = vk::Result::eSuccess; u32 imageIndexValue = 0; - std::tie(imageIndexResult, imageIndexValue) = mDevice->acquireNextImageKHR( - mSwapChain.get(), UINT64_MAX, mImageAvailableSemaphores[mCurrentFrame].get(), nullptr + std::tie(imageIndexResult, imageIndexValue) = mDevice.acquireNextImageKHR( + mSwapChain, UINT64_MAX, mImageAvailableSemaphores[mCurrentFrame], nullptr ); if (imageIndexResult == vk::Result::eErrorOutOfDateKHR) { @@ -626,10 +663,10 @@ class VulkanApp { if (imageIndexResult != vk::Result::eSuccess && imageIndexResult != vk::Result::eSuboptimalKHR) throw std::runtime_error("Failed to acquire swap chain image!"); - mDevice->resetFences(mInFlightFences[mCurrentFrame].get()); + mDevice.resetFences(mInFlightFences[mCurrentFrame]); - mCommandBuffers[mCurrentFrame]->reset(vk::CommandBufferResetFlagBits::eReleaseResources); - recordCommandBuffer(mCommandBuffers[mCurrentFrame].get(), imageIndexValue); + mCommandBuffers[mCurrentFrame].reset(vk::CommandBufferResetFlagBits::eReleaseResources); + recordCommandBuffer(mCommandBuffers[mCurrentFrame], imageIndexValue); std::array waitStages = { vk::PipelineStageFlagBits::eColorAttachmentOutput @@ -637,21 +674,21 @@ class VulkanApp { vk::SubmitInfo submitInfo { .waitSemaphoreCount = 1, - .pWaitSemaphores = &mImageAvailableSemaphores[mCurrentFrame].get(), + .pWaitSemaphores = &mImageAvailableSemaphores[mCurrentFrame], .pWaitDstStageMask = waitStages.data(), .commandBufferCount = 1, - .pCommandBuffers = &mCommandBuffers[mCurrentFrame].get(), + .pCommandBuffers = &mCommandBuffers[mCurrentFrame], .signalSemaphoreCount = 1, - .pSignalSemaphores = &mRenderFinishedSemaphores[mCurrentFrame].get(), + .pSignalSemaphores = &mRenderFinishedSemaphores[mCurrentFrame], }; - mGraphicsQueue.submit(submitInfo, mInFlightFences[mCurrentFrame].get()); + mGraphicsQueue.submit(submitInfo, mInFlightFences[mCurrentFrame]); vk::PresentInfoKHR presentInfo { .waitSemaphoreCount = 1, - .pWaitSemaphores = &mRenderFinishedSemaphores[mCurrentFrame].get(), + .pWaitSemaphores = &mRenderFinishedSemaphores[mCurrentFrame], .swapchainCount = 1, - .pSwapchains = &mSwapChain.get(), + .pSwapchains = &mSwapChain, .pImageIndices = &imageIndexValue, }; @@ -674,11 +711,11 @@ class VulkanApp { } } - fn createShaderModule(const std::vector& code) -> vk::UniqueShaderModule { + fn createShaderModule(const std::vector& code) -> vk::ShaderModule { vk::ShaderModuleCreateInfo createInfo { .codeSize = code.size(), .pCode = std::bit_cast(code.data()) }; - return mDevice->createShaderModuleUnique(createInfo); + return mDevice.createShaderModule(createInfo); } static fn chooseSwapSurfaceFormat(const std::vector& availableFormats @@ -705,7 +742,7 @@ class VulkanApp { return capabilities.currentExtent; u32 width = 0, height = 0; - std::tie(width, height) = mWindow->getFramebufferSize(); + std::tie(width, height) = mWindow.getFramebufferSize(); vk::Extent2D actualExtent = { width, height }; @@ -720,9 +757,9 @@ class VulkanApp { fn querySwapChainSupport(vk::PhysicalDevice device) -> SwapChainSupportDetails { SwapChainSupportDetails details; - details.capabilities = device.getSurfaceCapabilitiesKHR(mSurface.get()); - details.formats = device.getSurfaceFormatsKHR(mSurface.get()); - details.present_modes = device.getSurfacePresentModesKHR(mSurface.get()); + details.capabilities = device.getSurfaceCapabilitiesKHR(mSurface); + details.formats = device.getSurfaceFormatsKHR(mSurface); + details.present_modes = device.getSurfacePresentModesKHR(mSurface); return details; } @@ -762,7 +799,7 @@ class VulkanApp { if (queueFamilies[i].queueFlags & vk::QueueFlagBits::eGraphics) indices.graphics_family = i; - vk::Bool32 queuePresentSupport = device.getSurfaceSupportKHR(i, mSurface.get()); + vk::Bool32 queuePresentSupport = device.getSurfaceSupportKHR(i, mSurface); if (queuePresentSupport) indices.present_family = i;