Added resizing + swap chain recreation
This commit is contained in:
@@ -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
@@ -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){
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user