Added resizing + swap chain recreation
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
#define DEBUG
|
||||
#define DEBUG 1
|
||||
|
||||
#include <iostream>
|
||||
#include "vulkan/vulkan_app.hpp"
|
||||
|
||||
+81
-28
@@ -5,7 +5,6 @@
|
||||
#include "vulkan_app.hpp"
|
||||
|
||||
namespace vapp{
|
||||
|
||||
const std::vector<const char*> validationLayers = {
|
||||
"VK_LAYER_KHRONOS_validation"
|
||||
};
|
||||
@@ -14,20 +13,28 @@ const std::vector<const char*> deviceExtensions = {
|
||||
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;
|
||||
return VK_FALSE;
|
||||
}
|
||||
|
||||
VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pDebugMessenger){
|
||||
auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
|
||||
VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
|
||||
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;
|
||||
return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
|
||||
}
|
||||
|
||||
void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks *pAllocator){
|
||||
if(auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); func != nullptr){
|
||||
void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger,
|
||||
const VkAllocationCallbacks *pAllocator){
|
||||
if(auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
|
||||
instance, "vkDestroyDebugUtilsMessengerEXT"); func != nullptr){
|
||||
func(instance, debugMessenger, pAllocator);
|
||||
}
|
||||
}
|
||||
@@ -35,9 +42,11 @@ void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT
|
||||
void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo){
|
||||
createInfo = {};
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -308,7 +317,8 @@ SwapChainSupportDetails Vulkan::querySwapChainSupport(VkPhysicalDevice device){
|
||||
|
||||
VkSurfaceFormatKHR Vulkan::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& 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;
|
||||
}
|
||||
}
|
||||
@@ -326,7 +336,9 @@ VkPresentModeKHR Vulkan::chooseSwapPresentMode(const std::vector<VkPresentModeKH
|
||||
}
|
||||
|
||||
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;
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
@@ -336,8 +348,10 @@ VkExtent2D Vulkan::chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities
|
||||
static_cast<uint32_t>(height)
|
||||
};
|
||||
|
||||
actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
|
||||
actualExtent.width = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
|
||||
actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width,
|
||||
capabilities.maxImageExtent.width);
|
||||
actualExtent.width = std::clamp(actualExtent.height, capabilities.minImageExtent.height,
|
||||
capabilities.maxImageExtent.height);
|
||||
|
||||
return actualExtent;
|
||||
}
|
||||
@@ -563,7 +577,8 @@ void Vulkan::createGraphicsPipeline(){
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -744,7 +759,10 @@ void Vulkan::drawFrame(){
|
||||
vkResetFences(device, 1, &inFlightFences[currentFrame]);
|
||||
|
||||
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);
|
||||
recordCommandBuffer(commandBuffers[currentFrame], imageIndex);
|
||||
@@ -781,14 +799,55 @@ void Vulkan::drawFrame(){
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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){
|
||||
glfwInit();
|
||||
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);
|
||||
glfwSetWindowUserPointer(window, this);
|
||||
glfwSetFramebufferSizeCallback(window, framebufferResizeCallback);
|
||||
}
|
||||
|
||||
void Vulkan::initVulkan(){
|
||||
@@ -818,6 +877,13 @@ void Vulkan::mainLoop(){
|
||||
|
||||
void Vulkan::cleanup(){
|
||||
// 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++){
|
||||
vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr);
|
||||
vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr);
|
||||
@@ -826,19 +892,6 @@ void Vulkan::cleanup(){
|
||||
|
||||
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);
|
||||
|
||||
if(enableValidationLayers){
|
||||
|
||||
@@ -109,6 +109,8 @@ private:
|
||||
void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex);
|
||||
void createSyncObjects();
|
||||
void drawFrame();
|
||||
void cleanupSwapChain();
|
||||
void recreateSwapChain();
|
||||
void initWindow(const char* windowName);
|
||||
void initVulkan();
|
||||
void mainLoop();
|
||||
@@ -121,6 +123,8 @@ public:
|
||||
const bool enableValidationLayers = false;
|
||||
#endif
|
||||
|
||||
bool framebufferResized = false;
|
||||
|
||||
void run(const char* windowName, const uint32_t width = 800, const uint32_t height = 600);
|
||||
};
|
||||
} // vapp
|
||||
|
||||
Reference in New Issue
Block a user