diff --git a/main.cpp b/main.cpp index 726eb58..2f4b354 100644 --- a/main.cpp +++ b/main.cpp @@ -30,7 +30,7 @@ int main() return -1; /* Runs Vulkan initialisation functions */ - if (!VulkanManager::InitAll(window)) + if (!VulkanManager::Init(window)) CleanupAllAndExit(EXIT_FAILURE); /* Polls window events whilst it is still open */ diff --git a/src/managers/VulkanManager.h b/src/managers/VulkanManager.h index 7f26791..bbb27ba 100644 --- a/src/managers/VulkanManager.h +++ b/src/managers/VulkanManager.h @@ -6,12 +6,16 @@ namespace PB::Renderer { struct QueueFamilyIndices { - std::optional graphicsFamily = std::nullopt; - std::optional presentFamily = std::nullopt; + static constexpr uint32_t UNDEFINED_UINT32_VALUE = 0xFFFFFFFF; + + uint32_t graphicsFamily = UNDEFINED_UINT32_VALUE; + uint32_t presentFamily = UNDEFINED_UINT32_VALUE; [[nodiscard]] bool Complete() const { - return graphicsFamily && presentFamily; + return + graphicsFamily != UNDEFINED_UINT32_VALUE && + presentFamily != UNDEFINED_UINT32_VALUE; } }; @@ -25,14 +29,15 @@ namespace PB::Renderer class VulkanManager { public: + /* Static class so (de)constructors have been deleted to stop accidental creation */ VulkanManager() = delete; ~VulkanManager() = delete; - static bool InitAll(GLFWwindow* window); - static std::optional Init(); + static bool Init(GLFWwindow* window); static bool Cleanup(); - static std::optional CreateSurface(GLFWwindow* window); + static bool CreateInstance(); + static bool CreateSurface(GLFWwindow* window); static bool PickPhysicalDevice(); static bool CreateLogicalDevice(); static bool CreateSwapChain(GLFWwindow* window); @@ -41,7 +46,7 @@ namespace PB::Renderer static bool CreateFramebuffer(); static bool CreateGraphicsPipeline(); static bool CreateCommandBuffers(); - static void CreateSemaphores(); + static bool CreateSemaphores(); static bool RenderPass(); @@ -57,8 +62,8 @@ namespace PB::Renderer static VkShaderModule CreateShaderModule(const std::string& filename); - static std::optional s_Instance; - static std::optional s_Surface; + static VkInstance s_Instance; + static VkSurfaceKHR s_Surface; static VkPhysicalDevice s_PhysicalDevice; static QueueFamilyIndices s_QueueIndices; diff --git a/src/managers/VulkanManagerInit.cpp b/src/managers/VulkanManagerInit.cpp index c6eb745..cfd27cc 100644 --- a/src/managers/VulkanManagerInit.cpp +++ b/src/managers/VulkanManagerInit.cpp @@ -2,8 +2,8 @@ namespace PB::Renderer { - std::optional VulkanManager::s_Instance = std::nullopt; - std::optional VulkanManager::s_Surface = std::nullopt; + VkInstance VulkanManager::s_Instance = VK_NULL_HANDLE; + VkSurfaceKHR VulkanManager::s_Surface = VK_NULL_HANDLE; VkPhysicalDevice VulkanManager::s_PhysicalDevice = VK_NULL_HANDLE; QueueFamilyIndices VulkanManager::s_QueueIndices; @@ -31,15 +31,11 @@ namespace PB::Renderer VkSemaphore VulkanManager::s_ImageAvailableSemaphore = VK_NULL_HANDLE; VkSemaphore VulkanManager::s_RenderFinishedSemaphore = VK_NULL_HANDLE; - bool VulkanManager::InitAll(GLFWwindow* window) + bool VulkanManager::Init(GLFWwindow* window) { - if (const std::optional instance = Init(); !instance) - return false; - - if (const std::optional surface = CreateSurface(window); !surface) - return false; - - if (!( + return + CreateInstance() && + CreateSurface(window) && PickPhysicalDevice() && CreateLogicalDevice() && CreateSwapChain(window) && @@ -47,21 +43,56 @@ namespace PB::Renderer CreateRenderPass() && CreateFramebuffer() && CreateGraphicsPipeline() && - CreateCommandBuffers() - )) { - return false; - } + CreateCommandBuffers() && + CreateSemaphores(); + } + + bool VulkanManager::Cleanup() + { + if (s_Device != VK_NULL_HANDLE) + vkDeviceWaitIdle(s_Device); + + if (s_ImageAvailableSemaphore != VK_NULL_HANDLE) + vkDestroySemaphore(s_Device, s_ImageAvailableSemaphore, nullptr); + + if (s_RenderFinishedSemaphore != VK_NULL_HANDLE) + vkDestroySemaphore(s_Device, s_RenderFinishedSemaphore, nullptr); + + if (s_CommandPool != VK_NULL_HANDLE) + vkDestroyCommandPool(s_Device, s_CommandPool, nullptr); + + for (const VkFramebuffer& fb : s_Framebuffers) + vkDestroyFramebuffer(s_Device, fb, nullptr); + + if (s_RenderPipeline != VK_NULL_HANDLE) + vkDestroyPipeline(s_Device, s_RenderPipeline, nullptr); + + if (s_PipelineLayout != VK_NULL_HANDLE) + vkDestroyPipelineLayout(s_Device, s_PipelineLayout, nullptr); + + if (s_RenderPass != VK_NULL_HANDLE) + vkDestroyRenderPass(s_Device, s_RenderPass, nullptr); + + for (const VkImageView& view : s_SwapChainImageViews) + vkDestroyImageView(s_Device, view, nullptr); + + if (s_SwapChain != VK_NULL_HANDLE) + vkDestroySwapchainKHR(s_Device, s_SwapChain, nullptr); + + if (s_Device != VK_NULL_HANDLE) + vkDestroyDevice(s_Device, nullptr); + + if (s_Surface != VK_NULL_HANDLE) + vkDestroySurfaceKHR(s_Instance, s_Surface, nullptr); + + if (s_Instance != VK_NULL_HANDLE) + vkDestroyInstance(s_Instance, nullptr); - CreateSemaphores(); return true; } - std::optional VulkanManager::Init() + bool VulkanManager::CreateInstance() { - /* Stops multi initialisation */ - if (s_Instance != std::nullopt) - return s_Instance; - VkApplicationInfo appInfo; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pNext = nullptr; @@ -89,56 +120,30 @@ namespace PB::Renderer if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { std::cout << "PB::Renderer::VulkanManager::Init(): Could not create Vulkan instance" << std::endl; - return std::nullopt; + return false; } s_Instance = instance; - return instance; - } - - bool VulkanManager::Cleanup() - { - if (s_Surface != std::nullopt) - vkDestroySurfaceKHR(s_Instance.value(), s_Surface.value(), nullptr); - - if (s_Instance != std::nullopt) - vkDestroyInstance(s_Instance.value(), nullptr); - - s_Instance = std::nullopt; return true; } - std::optional VulkanManager::CreateSurface(GLFWwindow* window) + bool VulkanManager::CreateSurface(GLFWwindow* window) { - if (s_Instance == std::nullopt) - { - std::cout << "PB::Renderer::VulkanManager::CreateSurface(): No Vulkan instance" << std::endl; - return std::nullopt; - } - VkSurfaceKHR surface; - if (glfwCreateWindowSurface(s_Instance.value(), window, nullptr, &surface) != VK_SUCCESS) + if (glfwCreateWindowSurface(s_Instance, window, nullptr, &surface) != VK_SUCCESS) { std::cout << "PB::Renderer::VulkanManager::CreateSurface(): Failed to create Vulkan Surface" << std::endl; - return std::nullopt; + return false; } s_Surface = surface; - return surface; + return true; } bool VulkanManager::PickPhysicalDevice() { - if (s_Instance == std::nullopt || s_Surface == std::nullopt) - { - std::cout << "PB::Renderer::VulkanManager::PickPhysicalDevice(): No Vulkan instance or surface" << std::endl; - return false; - } - - const VkInstance& instance = s_Instance.value(); - uint32_t deviceCount = 0; - vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); + vkEnumeratePhysicalDevices(s_Instance, &deviceCount, nullptr); if (deviceCount == 0) { std::cout << "PB::Renderer::VulkanManager::PickPhysicalDevice(): No GPU with Vulkan support" << std::endl; @@ -146,7 +151,7 @@ namespace PB::Renderer } std::vector devices(deviceCount); - vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); + vkEnumeratePhysicalDevices(s_Instance, &deviceCount, devices.data()); for (const auto& device : devices) { @@ -170,7 +175,6 @@ namespace PB::Renderer bool VulkanManager::IsDeviceSuitable(const VkPhysicalDevice& device) { - const VkSurfaceKHR& surface = s_Surface.value(); const QueueFamilyIndices indices = FindQueueFamilies(device); if (const bool extensionsSupported = CheckDeviceExtensionSupport(device); !extensionsSupported) @@ -179,9 +183,9 @@ namespace PB::Renderer VkSurfaceCapabilitiesKHR capabilities; uint32_t formatCount, presentCount; - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &capabilities); - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr); - vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentCount, nullptr); + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, s_Surface, &capabilities); + vkGetPhysicalDeviceSurfaceFormatsKHR(device, s_Surface, &formatCount, nullptr); + vkGetPhysicalDeviceSurfacePresentModesKHR(device, s_Surface, &presentCount, nullptr); const bool swapChainAdequate = formatCount > 0 && presentCount > 0; VkPhysicalDeviceProperties deviceProperties; @@ -193,7 +197,6 @@ namespace PB::Renderer QueueFamilyIndices VulkanManager::FindQueueFamilies(const VkPhysicalDevice& device) { - const VkSurfaceKHR& surface = s_Surface.value(); QueueFamilyIndices indices; uint32_t queueFamilyCount; @@ -210,7 +213,7 @@ namespace PB::Renderer } VkBool32 presentSupport = false; - vkGetPhysicalDeviceSurfaceSupportKHR(device, index, surface, &presentSupport); + vkGetPhysicalDeviceSurfaceSupportKHR(device, index, s_Surface, &presentSupport); if (presentSupport) { indices.presentFamily = index; @@ -251,8 +254,8 @@ namespace PB::Renderer { std::set uniqueQueueFamilies = { - s_QueueIndices.graphicsFamily.value(), - s_QueueIndices.presentFamily.value() + s_QueueIndices.graphicsFamily, + s_QueueIndices.presentFamily }; std::vector queueCreateInfos; @@ -288,8 +291,8 @@ namespace PB::Renderer return false; } - vkGetDeviceQueue(s_Device, s_QueueIndices.graphicsFamily.value(), 0, &s_GraphicsQueue); - vkGetDeviceQueue(s_Device, s_QueueIndices.presentFamily.value(), 0, &s_PresentQueue); + vkGetDeviceQueue(s_Device, s_QueueIndices.graphicsFamily, 0, &s_GraphicsQueue); + vkGetDeviceQueue(s_Device, s_QueueIndices.presentFamily, 0, &s_PresentQueue); return true; } @@ -308,7 +311,7 @@ namespace PB::Renderer VkSwapchainCreateInfoKHR createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - createInfo.surface = s_Surface.value(); + createInfo.surface = s_Surface; createInfo.minImageCount = imageCount; createInfo.imageFormat = format; @@ -319,11 +322,11 @@ namespace PB::Renderer const uint32_t queueFamilyIndices[] = { - s_QueueIndices.graphicsFamily.value(), - s_QueueIndices.presentFamily.value() + s_QueueIndices.graphicsFamily, + s_QueueIndices.presentFamily }; - if (s_QueueIndices.graphicsFamily.value() != s_QueueIndices.presentFamily.value()) + if (s_QueueIndices.graphicsFamily != s_QueueIndices.presentFamily) { createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; createInfo.queueFamilyIndexCount = 2; @@ -361,18 +364,17 @@ namespace PB::Renderer SwapChainSupportDetails VulkanManager::QuerySwapChainSupport() { SwapChainSupportDetails details; - const VkSurfaceKHR& surface = s_Surface.value(); - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(s_PhysicalDevice, surface, &details.capabilities); + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(s_PhysicalDevice, s_Surface, &details.capabilities); uint32_t formatCount; - vkGetPhysicalDeviceSurfaceFormatsKHR(s_PhysicalDevice, surface, &formatCount, nullptr); + vkGetPhysicalDeviceSurfaceFormatsKHR(s_PhysicalDevice, s_Surface, &formatCount, nullptr); details.formats.resize(formatCount); - vkGetPhysicalDeviceSurfaceFormatsKHR(s_PhysicalDevice, surface, &formatCount, details.formats.data()); + vkGetPhysicalDeviceSurfaceFormatsKHR(s_PhysicalDevice, s_Surface, &formatCount, details.formats.data()); uint32_t presentModeCount; - vkGetPhysicalDeviceSurfacePresentModesKHR(s_PhysicalDevice, surface, &presentModeCount, nullptr); + vkGetPhysicalDeviceSurfacePresentModesKHR(s_PhysicalDevice, s_Surface, &presentModeCount, nullptr); details.presentModes.resize(presentModeCount); - vkGetPhysicalDeviceSurfacePresentModesKHR(s_PhysicalDevice, surface, &presentModeCount, details.presentModes.data()); + vkGetPhysicalDeviceSurfacePresentModesKHR(s_PhysicalDevice, s_Surface, &presentModeCount, details.presentModes.data()); return details; } @@ -679,7 +681,7 @@ namespace PB::Renderer VkCommandPoolCreateInfo poolInfo{}; poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - poolInfo.queueFamilyIndex = s_QueueIndices.graphicsFamily.value(); + poolInfo.queueFamilyIndex = s_QueueIndices.graphicsFamily; if (vkCreateCommandPool(s_Device, &poolInfo, nullptr, &s_CommandPool) != VK_SUCCESS) { @@ -737,12 +739,23 @@ namespace PB::Renderer return true; } - void VulkanManager::CreateSemaphores() + bool VulkanManager::CreateSemaphores() { VkSemaphoreCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - vkCreateSemaphore(s_Device, &createInfo, nullptr, &s_ImageAvailableSemaphore); - vkCreateSemaphore(s_Device, &createInfo, nullptr, &s_RenderFinishedSemaphore); + if (vkCreateSemaphore(s_Device, &createInfo, nullptr, &s_ImageAvailableSemaphore) != VK_SUCCESS) + { + std::cout << "PB::Renderer::VulkanManager::CreateSemaphores(): Could not create semaphore" << std::endl; + return false; + } + + if (vkCreateSemaphore(s_Device, &createInfo, nullptr, &s_RenderFinishedSemaphore) != VK_SUCCESS) + { + std::cout << "PB::Renderer::VulkanManager::CreateSemaphores(): Could not create semaphore" << std::endl; + return false; + } + + return true; } }