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 "util/types.h"
#define VKFW_NO_STD_FUNCTION_CALLBACKS
#include "vkfw.hpp"
namespace vk {
@ -17,6 +19,8 @@ namespace vk {
constexpr i32 WIDTH = 800;
constexpr i32 HEIGHT = 600;
constexpr i32 MAX_FRAMES_IN_FLIGHT = 2;
constexpr std::array<const char*, 1> validationLayers = { "VK_LAYER_KHRONOS_validation" };
#ifdef __APPLE__
@ -67,12 +71,15 @@ class VulkanApp {
vk::UniquePipelineLayout mPipelineLayout;
vk::UniquePipeline mGraphicsPipeline;
vk::UniqueCommandPool mCommandPool;
vk::UniqueCommandBuffer mCommandBuffer;
vk::UniqueCommandPool mCommandPool;
std::vector<vk::UniqueCommandBuffer> mCommandBuffers;
vk::UniqueSemaphore mImageAvailableSemaphore;
vk::UniqueSemaphore mRenderFinishedSemaphore;
vk::UniqueFence mInFlightFence;
std::vector<vk::UniqueSemaphore> mImageAvailableSemaphores;
std::vector<vk::UniqueSemaphore> mRenderFinishedSemaphores;
std::vector<vk::UniqueFence> mInFlightFences;
bool mFramebufferResized = false;
u32 mCurrentFrame = 0;
struct QueueFamilyIndices {
std::optional<u32> graphics_family;
@ -110,9 +117,17 @@ class VulkanApp {
vkfw::WindowHints hints;
hints.clientAPI = vkfw::ClientAPI::eNone;
hints.resizable = false;
// hints.resizable = false;
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 {
@ -127,7 +142,7 @@ class VulkanApp {
createGraphicsPipeline();
createFramebuffers();
createCommandPool();
createCommandBuffer();
createCommandBuffers();
createSyncObjects();
}
@ -140,6 +155,37 @@ class VulkanApp {
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 {
if (enableValidationLayers && !checkValidationLayerSupport())
throw std::runtime_error("Validation layers requested, but not available!");
@ -489,14 +535,15 @@ class VulkanApp {
mCommandPool = mDevice->createCommandPoolUnique(poolInfo);
}
fn createCommandBuffer() -> void {
vk::CommandBufferAllocateInfo allocInfo {
.commandPool = mCommandPool.get(),
.level = vk::CommandBufferLevel::ePrimary,
.commandBufferCount = 1,
};
fn createCommandBuffers() -> void {
mCommandBuffers.resize(MAX_FRAMES_IN_FLIGHT);
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 {
@ -540,55 +587,77 @@ class VulkanApp {
}
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::FenceCreateInfo fenceInfo { .flags = vk::FenceCreateFlagBits::eSignaled };
mImageAvailableSemaphore = mDevice->createSemaphoreUnique(semaphoreInfo);
mRenderFinishedSemaphore = mDevice->createSemaphoreUnique(semaphoreInfo);
mInFlightFence = mDevice->createFenceUnique(fenceInfo);
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);
}
}
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)
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 =
mDevice->acquireNextImageKHR(mSwapChain.get(), UINT64_MAX, mImageAvailableSemaphore.get(), nullptr)
.value;
if (imageIndex.result == vk::Result::eErrorOutOfDateKHR) {
recreateSwapChain();
return;
}
mCommandBuffer->reset(vk::CommandBufferResetFlagBits::eReleaseResources);
recordCommandBuffer(mCommandBuffer.get(), imageIndex);
if (imageIndex.result != vk::Result::eSuccess && imageIndex.result != vk::Result::eSuboptimalKHR)
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 };
vk::SubmitInfo submitInfo {
.waitSemaphoreCount = 1,
.pWaitSemaphores = &mImageAvailableSemaphore.get(),
.pWaitSemaphores = &mImageAvailableSemaphores[mCurrentFrame].get(),
.pWaitDstStageMask = waitStages.data(),
.commandBufferCount = 1,
.pCommandBuffers = &mCommandBuffer.get(),
.pCommandBuffers = &mCommandBuffers[mCurrentFrame].get(),
.signalSemaphoreCount = 1,
.pSignalSemaphores = &mRenderFinishedSemaphore.get(),
.pSignalSemaphores = &mRenderFinishedSemaphores[mCurrentFrame].get(),
};
mGraphicsQueue.submit(submitInfo, mInFlightFence.get());
mGraphicsQueue.submit(submitInfo, mInFlightFences[mCurrentFrame].get());
vk::PresentInfoKHR presentInfo {
.waitSemaphoreCount = 1,
.pWaitSemaphores = &mRenderFinishedSemaphore.get(),
.pWaitSemaphores = &mRenderFinishedSemaphores[mCurrentFrame].get(),
.swapchainCount = 1,
.pSwapchains = &mSwapChain.get(),
.pImageIndices = &imageIndex,
.pImageIndices = &imageIndex.value,
};
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!");
}
mCurrentFrame = (mCurrentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
}
fn createShaderModule(const std::vector<char>& code) -> vk::UniqueShaderModule {
@ -598,8 +667,8 @@ class VulkanApp {
return mDevice->createShaderModuleUnique(createInfo);
}
static fn chooseSwapSurfaceFormat(const std::vector<vk::SurfaceFormatKHR>& availableFormats)
-> vk::SurfaceFormatKHR {
static fn chooseSwapSurfaceFormat(const std::vector<vk::SurfaceFormatKHR>& availableFormats
) -> vk::SurfaceFormatKHR {
for (const auto& availableFormat : availableFormats)
if (availableFormat.format == vk::Format::eB8G8R8A8Srgb &&
availableFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear)
@ -608,8 +677,8 @@ class VulkanApp {
return availableFormats[0];
}
static fn chooseSwapPresentMode(const std::vector<vk::PresentModeKHR>& availablePresentModes)
-> vk::PresentModeKHR {
static fn chooseSwapPresentMode(const std::vector<vk::PresentModeKHR>& availablePresentModes
) -> vk::PresentModeKHR {
for (const auto& availablePresentMode : availablePresentModes)
if (availablePresentMode == vk::PresentModeKHR::eMailbox)
return availablePresentMode;
@ -738,7 +807,7 @@ fn main() -> i32 {
try {
app.run();
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
fmt::println("{}", e.what());
return EXIT_FAILURE;
}