resizing works now yay

This commit is contained in:
Mars 2024-10-05 23:08:12 -04:00
parent 14ca81b3cb
commit 83631f940e
Signed by untrusted user: pupbrained
GPG key ID: 874E22DF2F9DFCB5

View file

@ -8,6 +8,8 @@
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#include "util/types.h" #include "util/types.h"
#define VKFW_NO_STD_FUNCTION_CALLBACKS
#include "vkfw.hpp" #include "vkfw.hpp"
namespace vk { namespace vk {
@ -17,6 +19,8 @@ namespace vk {
constexpr i32 WIDTH = 800; constexpr i32 WIDTH = 800;
constexpr i32 HEIGHT = 600; constexpr i32 HEIGHT = 600;
constexpr i32 MAX_FRAMES_IN_FLIGHT = 2;
constexpr std::array<const char*, 1> validationLayers = { "VK_LAYER_KHRONOS_validation" }; constexpr std::array<const char*, 1> validationLayers = { "VK_LAYER_KHRONOS_validation" };
#ifdef __APPLE__ #ifdef __APPLE__
@ -67,12 +71,15 @@ class VulkanApp {
vk::UniquePipelineLayout mPipelineLayout; vk::UniquePipelineLayout mPipelineLayout;
vk::UniquePipeline mGraphicsPipeline; vk::UniquePipeline mGraphicsPipeline;
vk::UniqueCommandPool mCommandPool; vk::UniqueCommandPool mCommandPool;
vk::UniqueCommandBuffer mCommandBuffer; std::vector<vk::UniqueCommandBuffer> mCommandBuffers;
vk::UniqueSemaphore mImageAvailableSemaphore; std::vector<vk::UniqueSemaphore> mImageAvailableSemaphores;
vk::UniqueSemaphore mRenderFinishedSemaphore; std::vector<vk::UniqueSemaphore> mRenderFinishedSemaphores;
vk::UniqueFence mInFlightFence; std::vector<vk::UniqueFence> mInFlightFences;
bool mFramebufferResized = false;
u32 mCurrentFrame = 0;
struct QueueFamilyIndices { struct QueueFamilyIndices {
std::optional<u32> graphics_family; std::optional<u32> graphics_family;
@ -110,9 +117,17 @@ class VulkanApp {
vkfw::WindowHints hints; vkfw::WindowHints hints;
hints.clientAPI = vkfw::ClientAPI::eNone; hints.clientAPI = vkfw::ClientAPI::eNone;
hints.resizable = false; // hints.resizable = false;
mWindow = vkfw::createWindowUnique(WIDTH, HEIGHT, "Vulkan", hints); mWindow = vkfw::createWindowUnique(WIDTH, HEIGHT, "Vulkan", hints);
mWindow->setUserPointer(this);
mWindow->setFramebufferSizeCallback(framebufferResizeCallback);
}
static fn framebufferResizeCallback(GLFWwindow* window, int /*width*/, int /*height*/) -> void {
auto* app = std::bit_cast<VulkanApp*>(glfwGetWindowUserPointer(window));
app->mFramebufferResized = true;
} }
fn initVulkan() -> void { fn initVulkan() -> void {
@ -127,7 +142,7 @@ class VulkanApp {
createGraphicsPipeline(); createGraphicsPipeline();
createFramebuffers(); createFramebuffers();
createCommandPool(); createCommandPool();
createCommandBuffer(); createCommandBuffers();
createSyncObjects(); createSyncObjects();
} }
@ -140,6 +155,37 @@ class VulkanApp {
mDevice->waitIdle(); mDevice->waitIdle();
} }
fn cleanupSwapChain() -> void {
for (vk::UniqueHandle<vk::Framebuffer, vk::DispatchLoaderStatic>& mSwapChainFramebuffer :
mSwapChainFramebuffers) {
mSwapChainFramebuffer.reset();
}
for (vk::UniqueHandle<vk::ImageView, vk::DispatchLoaderStatic>& mSwapChainImageView :
mSwapChainImageViews) {
mSwapChainImageView.reset();
}
mSwapChain.reset();
}
fn recreateSwapChain() -> void {
u32 width = 0, height = 0;
std::tie(width, height) = mWindow->getFramebufferSize();
while (width == 0 || height == 0) {
std::tie(width, height) = mWindow->getFramebufferSize();
vkfw::waitEvents();
}
mDevice->waitIdle();
cleanupSwapChain();
createSwapChain();
createImageViews();
createFramebuffers();
}
fn createInstance() -> void { fn createInstance() -> void {
if (enableValidationLayers && !checkValidationLayerSupport()) if (enableValidationLayers && !checkValidationLayerSupport())
throw std::runtime_error("Validation layers requested, but not available!"); throw std::runtime_error("Validation layers requested, but not available!");
@ -489,14 +535,15 @@ class VulkanApp {
mCommandPool = mDevice->createCommandPoolUnique(poolInfo); mCommandPool = mDevice->createCommandPoolUnique(poolInfo);
} }
fn createCommandBuffer() -> void { fn createCommandBuffers() -> void {
vk::CommandBufferAllocateInfo allocInfo { mCommandBuffers.resize(MAX_FRAMES_IN_FLIGHT);
.commandPool = mCommandPool.get(),
.level = vk::CommandBufferLevel::ePrimary,
.commandBufferCount = 1,
};
mCommandBuffer = std::move(mDevice->allocateCommandBuffersUnique(allocInfo)[0]); vk::CommandBufferAllocateInfo allocInfo { .commandPool = mCommandPool.get(),
.level = vk::CommandBufferLevel::ePrimary,
.commandBufferCount =
static_cast<u32>(mCommandBuffers.size()) };
mCommandBuffers = mDevice->allocateCommandBuffersUnique(allocInfo);
} }
fn recordCommandBuffer(vk::CommandBuffer commandBuffer, u32 imageIndex) -> void { fn recordCommandBuffer(vk::CommandBuffer commandBuffer, u32 imageIndex) -> void {
@ -540,55 +587,77 @@ class VulkanApp {
} }
fn createSyncObjects() -> void { fn createSyncObjects() -> void {
mImageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
mRenderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
mInFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
vk::SemaphoreCreateInfo semaphoreInfo {}; vk::SemaphoreCreateInfo semaphoreInfo {};
vk::FenceCreateInfo fenceInfo { .flags = vk::FenceCreateFlagBits::eSignaled }; vk::FenceCreateInfo fenceInfo { .flags = vk::FenceCreateFlagBits::eSignaled };
mImageAvailableSemaphore = mDevice->createSemaphoreUnique(semaphoreInfo); for (usize idx = 0; idx < MAX_FRAMES_IN_FLIGHT; idx++) {
mRenderFinishedSemaphore = mDevice->createSemaphoreUnique(semaphoreInfo); mImageAvailableSemaphores[idx] = mDevice->createSemaphoreUnique(semaphoreInfo);
mInFlightFence = mDevice->createFenceUnique(fenceInfo); mRenderFinishedSemaphores[idx] = mDevice->createSemaphoreUnique(semaphoreInfo);
mInFlightFences[idx] = mDevice->createFenceUnique(fenceInfo);
}
} }
fn drawFrame() -> void { fn drawFrame() -> void {
vk::Result result = mDevice->waitForFences(mInFlightFence.get(), vk::Bool32(vk::True), UINT64_MAX); vk::Result result =
mDevice->waitForFences(mInFlightFences[mCurrentFrame].get(), vk::Bool32(vk::True), UINT64_MAX);
if (result != vk::Result::eSuccess) if (result != vk::Result::eSuccess)
throw std::runtime_error("Failed to wait for fences!"); throw std::runtime_error("Failed to wait for fences!");
mDevice->resetFences(mInFlightFence.get()); vk::ResultValue<uint32_t> imageIndex = mDevice->acquireNextImageKHR(
mSwapChain.get(), UINT64_MAX, mImageAvailableSemaphores[mCurrentFrame].get(), nullptr
);
u32 imageIndex = if (imageIndex.result == vk::Result::eErrorOutOfDateKHR) {
mDevice->acquireNextImageKHR(mSwapChain.get(), UINT64_MAX, mImageAvailableSemaphore.get(), nullptr) recreateSwapChain();
.value; return;
}
mCommandBuffer->reset(vk::CommandBufferResetFlagBits::eReleaseResources); if (imageIndex.result != vk::Result::eSuccess && imageIndex.result != vk::Result::eSuboptimalKHR)
recordCommandBuffer(mCommandBuffer.get(), imageIndex); throw std::runtime_error("Failed to acquire swap chain image!");
mDevice->resetFences(mInFlightFences[mCurrentFrame].get());
mCommandBuffers[mCurrentFrame]->reset(vk::CommandBufferResetFlagBits::eReleaseResources);
recordCommandBuffer(mCommandBuffers[mCurrentFrame].get(), imageIndex.value);
std::array<vk::PipelineStageFlags, 1> waitStages = { vk::PipelineStageFlagBits::eColorAttachmentOutput }; std::array<vk::PipelineStageFlags, 1> waitStages = { vk::PipelineStageFlagBits::eColorAttachmentOutput };
vk::SubmitInfo submitInfo { vk::SubmitInfo submitInfo {
.waitSemaphoreCount = 1, .waitSemaphoreCount = 1,
.pWaitSemaphores = &mImageAvailableSemaphore.get(), .pWaitSemaphores = &mImageAvailableSemaphores[mCurrentFrame].get(),
.pWaitDstStageMask = waitStages.data(), .pWaitDstStageMask = waitStages.data(),
.commandBufferCount = 1, .commandBufferCount = 1,
.pCommandBuffers = &mCommandBuffer.get(), .pCommandBuffers = &mCommandBuffers[mCurrentFrame].get(),
.signalSemaphoreCount = 1, .signalSemaphoreCount = 1,
.pSignalSemaphores = &mRenderFinishedSemaphore.get(), .pSignalSemaphores = &mRenderFinishedSemaphores[mCurrentFrame].get(),
}; };
mGraphicsQueue.submit(submitInfo, mInFlightFence.get()); mGraphicsQueue.submit(submitInfo, mInFlightFences[mCurrentFrame].get());
vk::PresentInfoKHR presentInfo { vk::PresentInfoKHR presentInfo {
.waitSemaphoreCount = 1, .waitSemaphoreCount = 1,
.pWaitSemaphores = &mRenderFinishedSemaphore.get(), .pWaitSemaphores = &mRenderFinishedSemaphores[mCurrentFrame].get(),
.swapchainCount = 1, .swapchainCount = 1,
.pSwapchains = &mSwapChain.get(), .pSwapchains = &mSwapChain.get(),
.pImageIndices = &imageIndex, .pImageIndices = &imageIndex.value,
}; };
vk::Result presentResult = mPresentQueue.presentKHR(presentInfo); vk::Result presentResult = mPresentQueue.presentKHR(presentInfo);
if (presentResult != vk::Result::eSuccess) if (presentResult == vk::Result::eErrorOutOfDateKHR || presentResult == vk::Result::eSuboptimalKHR || mFramebufferResized) {
mFramebufferResized = false;
recreateSwapChain();
} else if (presentResult != vk::Result::eSuccess){
std::cout << presentResult << '\n';
throw std::runtime_error("Failed to present swap chain image!"); throw std::runtime_error("Failed to present swap chain image!");
}
mCurrentFrame = (mCurrentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
} }
fn createShaderModule(const std::vector<char>& code) -> vk::UniqueShaderModule { fn createShaderModule(const std::vector<char>& code) -> vk::UniqueShaderModule {
@ -598,8 +667,8 @@ class VulkanApp {
return mDevice->createShaderModuleUnique(createInfo); return mDevice->createShaderModuleUnique(createInfo);
} }
static fn chooseSwapSurfaceFormat(const std::vector<vk::SurfaceFormatKHR>& availableFormats) static fn chooseSwapSurfaceFormat(const std::vector<vk::SurfaceFormatKHR>& availableFormats
-> vk::SurfaceFormatKHR { ) -> vk::SurfaceFormatKHR {
for (const auto& availableFormat : availableFormats) for (const auto& availableFormat : availableFormats)
if (availableFormat.format == vk::Format::eB8G8R8A8Srgb && if (availableFormat.format == vk::Format::eB8G8R8A8Srgb &&
availableFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) availableFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear)
@ -608,8 +677,8 @@ class VulkanApp {
return availableFormats[0]; return availableFormats[0];
} }
static fn chooseSwapPresentMode(const std::vector<vk::PresentModeKHR>& availablePresentModes) static fn chooseSwapPresentMode(const std::vector<vk::PresentModeKHR>& availablePresentModes
-> vk::PresentModeKHR { ) -> vk::PresentModeKHR {
for (const auto& availablePresentMode : availablePresentModes) for (const auto& availablePresentMode : availablePresentModes)
if (availablePresentMode == vk::PresentModeKHR::eMailbox) if (availablePresentMode == vk::PresentModeKHR::eMailbox)
return availablePresentMode; return availablePresentMode;
@ -738,7 +807,7 @@ fn main() -> i32 {
try { try {
app.run(); app.run();
} catch (const std::exception& e) { } catch (const std::exception& e) {
std::cerr << e.what() << std::endl; fmt::println("{}", e.what());
return EXIT_FAILURE; return EXIT_FAILURE;
} }