Added resizing + swap chain recreation

This commit is contained in:
Ano-sys
2025-04-03 23:00:32 +02:00
parent 811b5e0ae6
commit 5944a08abc
3 changed files with 822 additions and 765 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
#define DEBUG #define DEBUG 1
#include <iostream> #include <iostream>
#include "vulkan/vulkan_app.hpp" #include "vulkan/vulkan_app.hpp"
+81 -28
View File
@@ -5,7 +5,6 @@
#include "vulkan_app.hpp" #include "vulkan_app.hpp"
namespace vapp{ namespace vapp{
const std::vector<const char*> validationLayers = { const std::vector<const char*> validationLayers = {
"VK_LAYER_KHRONOS_validation" "VK_LAYER_KHRONOS_validation"
}; };
@@ -14,20 +13,28 @@ const std::vector<const char*> deviceExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
}; };
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData){ static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
void *pUserData){
std::cerr << "Validation Layer: " << pCallbackData->pMessage << std::endl; std::cerr << "Validation Layer: " << pCallbackData->pMessage << std::endl;
return VK_FALSE; return VK_FALSE;
} }
VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pDebugMessenger){ VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); const VkAllocationCallbacks *pAllocator,
VkDebugUtilsMessengerEXT *pDebugMessenger){
auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
instance, "vkCreateDebugUtilsMessengerEXT");
if(func == nullptr) return VK_ERROR_EXTENSION_NOT_PRESENT; if(func == nullptr) return VK_ERROR_EXTENSION_NOT_PRESENT;
if(func == nullptr) return VK_ERROR_EXTENSION_NOT_PRESENT; if(func == nullptr) return VK_ERROR_EXTENSION_NOT_PRESENT;
return func(instance, pCreateInfo, pAllocator, pDebugMessenger); return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
} }
void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks *pAllocator){ void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger,
if(auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); func != nullptr){ const VkAllocationCallbacks *pAllocator){
if(auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
instance, "vkDestroyDebugUtilsMessengerEXT"); func != nullptr){
func(instance, debugMessenger, pAllocator); func(instance, debugMessenger, pAllocator);
} }
} }
@@ -35,9 +42,11 @@ void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT
void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo){ void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo){
createInfo = {}; createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
// set which type of messages the callback is notified about // set which type of messages the callback is notified about
createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
createInfo.pfnUserCallback = debugCallback; createInfo.pfnUserCallback = debugCallback;
} }
@@ -308,7 +317,8 @@ SwapChainSupportDetails Vulkan::querySwapChainSupport(VkPhysicalDevice device){
VkSurfaceFormatKHR Vulkan::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats){ VkSurfaceFormatKHR Vulkan::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats){
for(const VkSurfaceFormatKHR availableFormat : availableFormats){ for(const VkSurfaceFormatKHR availableFormat : availableFormats){
if(availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR){ if(availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace ==
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR){
return availableFormat; return availableFormat;
} }
} }
@@ -326,7 +336,9 @@ VkPresentModeKHR Vulkan::chooseSwapPresentMode(const std::vector<VkPresentModeKH
} }
VkExtent2D Vulkan::chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities){ VkExtent2D Vulkan::chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities){
if(capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()){ return capabilities.currentExtent; } if(capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()){
return capabilities.currentExtent;
}
int width, height; int width, height;
glfwGetFramebufferSize(window, &width, &height); glfwGetFramebufferSize(window, &width, &height);
@@ -336,8 +348,10 @@ VkExtent2D Vulkan::chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities
static_cast<uint32_t>(height) static_cast<uint32_t>(height)
}; };
actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width); actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width,
actualExtent.width = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height); capabilities.maxImageExtent.width);
actualExtent.width = std::clamp(actualExtent.height, capabilities.minImageExtent.height,
capabilities.maxImageExtent.height);
return actualExtent; return actualExtent;
} }
@@ -563,7 +577,8 @@ void Vulkan::createGraphicsPipeline(){
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
*/ */
if(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS){ if(vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) !=
VK_SUCCESS){
throw std::runtime_error("Func; createGraphicsPipeline\nError: Failed to create graphics pipeline!\n"); throw std::runtime_error("Func; createGraphicsPipeline\nError: Failed to create graphics pipeline!\n");
} }
@@ -744,7 +759,10 @@ void Vulkan::drawFrame(){
vkResetFences(device, 1, &inFlightFences[currentFrame]); vkResetFences(device, 1, &inFlightFences[currentFrame]);
uint32_t imageIndex; uint32_t imageIndex;
vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
// INFO: is this right here?
// vkResetFences(device, 1, &inFlightFences[currentFrame]);
vkResetCommandBuffer(commandBuffers[currentFrame], 0); vkResetCommandBuffer(commandBuffers[currentFrame], 0);
recordCommandBuffer(commandBuffers[currentFrame], imageIndex); recordCommandBuffer(commandBuffers[currentFrame], imageIndex);
@@ -781,14 +799,55 @@ void Vulkan::drawFrame(){
vkQueuePresentKHR(presentQueue, &presentInfo); vkQueuePresentKHR(presentQueue, &presentInfo);
if(result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized){
framebufferResized = false;
recreateSwapChain();
}
else if(result != VK_SUCCESS){
throw std::runtime_error("Func: drawFrame\nError: Failed to acquire swap chain image!\n");
}
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
} }
void Vulkan::cleanupSwapChain(){
for(const auto & swapChainFramebuffer : swapChainFramebuffers)
{ vkDestroyFramebuffer(device, swapChainFramebuffer, nullptr); }
for(const auto & swapChainImageView : swapChainImageViews)
{ vkDestroyImageView(device, swapChainImageView, nullptr); }
vkDestroySwapchainKHR(device, swapChain, nullptr);
}
void Vulkan::recreateSwapChain(){
int width = 0, height = 0;
glfwGetFramebufferSize(window, &width, &height);
while(width == 0 || height == 0){
glfwGetFramebufferSize(window, &width, &height);
glfwPollEvents();
}
vkDeviceWaitIdle(device);
cleanupSwapChain();
createSwapChain();
createImageViews();
createFrameBuffers();
}
static void framebufferResizeCallback(GLFWwindow *window, int width, int height){
auto app = reinterpret_cast<Vulkan*>(glfwGetWindowUserPointer(window));
app->framebufferResized = true;
}
void Vulkan::initWindow(const char *windowName){ void Vulkan::initWindow(const char *windowName){
glfwInit(); glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); // tell glfw to not use opengl glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); // tell glfw to not use opengl
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); // disable window resize glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // disable window resize
this->window = glfwCreateWindow(static_cast<int>(_width), static_cast<int>(_height), windowName, nullptr, nullptr); this->window = glfwCreateWindow(static_cast<int>(_width), static_cast<int>(_height), windowName, nullptr, nullptr);
glfwSetWindowUserPointer(window, this);
glfwSetFramebufferSizeCallback(window, framebufferResizeCallback);
} }
void Vulkan::initVulkan(){ void Vulkan::initVulkan(){
@@ -818,6 +877,13 @@ void Vulkan::mainLoop(){
void Vulkan::cleanup(){ void Vulkan::cleanup(){
// Vulkan // Vulkan
cleanupSwapChain();
vkDestroyPipeline(device, graphicsPipeline, nullptr);
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
vkDestroyRenderPass(device, renderPass, nullptr);
for(size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++){ for(size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++){
vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr); vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr);
vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr); vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr);
@@ -826,19 +892,6 @@ void Vulkan::cleanup(){
vkDestroyCommandPool(device, commandPool, nullptr); vkDestroyCommandPool(device, commandPool, nullptr);
for(VkFramebuffer framebuffer : swapChainFramebuffers){
vkDestroyFramebuffer(device, framebuffer, nullptr);
}
vkDestroyPipeline(device, graphicsPipeline, nullptr);
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
vkDestroyRenderPass(device, renderPass, nullptr);
for(VkImageView imageView : swapChainImageViews){
vkDestroyImageView(device, imageView, nullptr);
}
vkDestroySwapchainKHR(device, swapChain, nullptr);
vkDestroyDevice(device, nullptr); vkDestroyDevice(device, nullptr);
if(enableValidationLayers){ if(enableValidationLayers){
+4
View File
@@ -109,6 +109,8 @@ private:
void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex); void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex);
void createSyncObjects(); void createSyncObjects();
void drawFrame(); void drawFrame();
void cleanupSwapChain();
void recreateSwapChain();
void initWindow(const char* windowName); void initWindow(const char* windowName);
void initVulkan(); void initVulkan();
void mainLoop(); void mainLoop();
@@ -121,6 +123,8 @@ public:
const bool enableValidationLayers = false; const bool enableValidationLayers = false;
#endif #endif
bool framebufferResized = false;
void run(const char* windowName, const uint32_t width = 800, const uint32_t height = 600); void run(const char* windowName, const uint32_t width = 800, const uint32_t height = 600);
}; };
} // vapp } // vapp