forked from pupbrained/vulkan-test
resizing works now yay
This commit is contained in:
parent
14ca81b3cb
commit
83631f940e
139
src/main.cpp
139
src/main.cpp
|
@ -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__
|
||||
|
@ -68,11 +72,14 @@ class VulkanApp {
|
|||
vk::UniquePipeline mGraphicsPipeline;
|
||||
|
||||
vk::UniqueCommandPool mCommandPool;
|
||||
vk::UniqueCommandBuffer mCommandBuffer;
|
||||
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,57 +587,79 @@ 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 {
|
||||
vk::ShaderModuleCreateInfo createInfo { .codeSize = code.size(),
|
||||
.pCode = std::bit_cast<const u32*>(code.data()) };
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue