From ce1d58b086a87a0098d25b7ae68a00ef4451210e Mon Sep 17 00:00:00 2001 From: Warwick Date: Thu, 2 May 2024 15:54:48 +0100 Subject: [PATCH] Boy this is messy, but for the love of god let surface config from the vulkan tutorial be over. --- src/application.cpp | 4 +-- src/yave_vulkan_instance.cpp | 52 +++++++++++++++++++++++------------- src/yave_vulkan_instance.hpp | 14 +++++++--- src/yave_vulkan_surface.cpp | 12 +++++---- src/yave_vulkan_surface.hpp | 12 +++++---- 5 files changed, 60 insertions(+), 34 deletions(-) diff --git a/src/application.cpp b/src/application.cpp index 0dca228..1c64435 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -1,12 +1,10 @@ #include "application.hpp" #include "yave_vulkan_instance.hpp" -#include "yave_vulkan_surface.hpp" namespace yave { void Application::run() { - YaveVulkanInstance VI = YaveVulkanInstance(); - YaveVulkanSurface VS = YaveVulkanSurface(VI, yaveWindow); + YaveVulkanInstance VI = YaveVulkanInstance(&yaveWindow); while (!yaveWindow.shouldClose()) { glfwPollEvents(); diff --git a/src/yave_vulkan_instance.cpp b/src/yave_vulkan_instance.cpp index e3d0128..5b2eb83 100644 --- a/src/yave_vulkan_instance.cpp +++ b/src/yave_vulkan_instance.cpp @@ -1,16 +1,19 @@ #include "yave_vulkan_instance.hpp" #include +#include #include namespace yave { -YaveVulkanInstance::YaveVulkanInstance() { +YaveVulkanInstance::YaveVulkanInstance(YaveWindow *window) : window(window) { createInstance(); + surface = new YaveVulkanSurface(*this, window); pickPhysicalDevice(); createLogicalDevice(); } YaveVulkanInstance::~YaveVulkanInstance() { destroyLogicalDevice(); + delete surface; destroyInstance(); } @@ -142,41 +145,55 @@ YaveVulkanInstance::findQueueFamilies(VkPhysicalDevice device) { if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { indices.graphicsFamily = i; } + + VkBool32 presentSupport = false; + vkGetPhysicalDeviceSurfaceSupportKHR(device, i, *surface->getVkSurface(), + &presentSupport); + + if (presentSupport) { + indices.presentFamily = i; + } + // If we know we have support we don't need to look for anything more if (indices.isComplete()) { break; } i++; } + return indices; } void YaveVulkanInstance::createLogicalDevice() { QueueFamilyIndices indices = findQueueFamilies(physicalDevice); - // Only need a single queue as we can feed it with multiple threads and - // trigger it from the main thread to start off with. - VkDeviceQueueCreateInfo queueCreateInfo{}; - queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queueCreateInfo.queueFamilyIndex = indices.graphicsFamily.value(); - queueCreateInfo.queueCount = 1; - // Since we only have one queue it has all the priority. - float queuePriority = 1.0f; - queueCreateInfo.pQueuePriorities = &queuePriority; + std::vector queueCreateInfos; + std::set uniqueQueueFamilies = {indices.graphicsFamily.value(), + indices.presentFamily.value()}; + + float queuePriority = 1.0f; + for (uint32_t queueFamily : uniqueQueueFamilies) { + VkDeviceQueueCreateInfo queueCreateInfo{}; + queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queueCreateInfo.queueFamilyIndex = queueFamily; + queueCreateInfo.queueCount = 1; + queueCreateInfo.pQueuePriorities = &queuePriority; + queueCreateInfos.push_back(queueCreateInfo); + } - // TODO: set up device with interesting features as we use them VkPhysicalDeviceFeatures deviceFeatures{}; - // Create logical device. VkDeviceCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - createInfo.pQueueCreateInfos = &queueCreateInfo; - createInfo.queueCreateInfoCount = 1; + + createInfo.queueCreateInfoCount = + static_cast(queueCreateInfos.size()); + createInfo.pQueueCreateInfos = queueCreateInfos.data(); + createInfo.pEnabledFeatures = &deviceFeatures; - // TODO: Require specific features when we need some - // Device specific create information createInfo.enabledExtensionCount = 0; + if (enableValidationLayers) { createInfo.enabledLayerCount = static_cast(validationLayers.size()); @@ -185,14 +202,13 @@ void YaveVulkanInstance::createLogicalDevice() { createInfo.enabledLayerCount = 0; } - // Create logical device if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) { throw std::runtime_error("failed to create logical device!"); } - // Whilst we're here we might as well set up our queue vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue); + vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue); } void YaveVulkanInstance::destroyLogicalDevice() { diff --git a/src/yave_vulkan_instance.hpp b/src/yave_vulkan_instance.hpp index 1ac1054..59b3e46 100644 --- a/src/yave_vulkan_instance.hpp +++ b/src/yave_vulkan_instance.hpp @@ -1,5 +1,7 @@ #pragma once +#include "yave_vulkan_surface.hpp" +#include "yave_window.hpp" #include #include #include @@ -13,8 +15,11 @@ namespace yave { struct QueueFamilyIndices { std::optional graphicsFamily; + std::optional presentFamily; - bool isComplete() { return graphicsFamily.has_value(); } + bool isComplete() { + return graphicsFamily.has_value() && presentFamily.has_value(); + } }; class YaveVulkanInstance { @@ -24,6 +29,9 @@ private: VkPhysicalDevice physicalDevice; VkDevice device; VkQueue graphicsQueue; + YaveVulkanSurface *surface; + YaveWindow *window; + VkQueue presentQueue; // Vulkan instance void createInstance(); @@ -56,8 +64,8 @@ public: YaveVulkanInstance(const YaveVulkanInstance &) = delete; YaveVulkanInstance &operator=(const YaveVulkanInstance &) = delete; - VkInstance *getVkInstance(){return &instance;} - YaveVulkanInstance(); + VkInstance *getVkInstance() { return &instance; } + YaveVulkanInstance(YaveWindow *window); ~YaveVulkanInstance(); }; } // namespace yave diff --git a/src/yave_vulkan_surface.cpp b/src/yave_vulkan_surface.cpp index 0b7935d..838e602 100644 --- a/src/yave_vulkan_surface.cpp +++ b/src/yave_vulkan_surface.cpp @@ -7,16 +7,18 @@ namespace yave { YaveVulkanSurface::YaveVulkanSurface(YaveVulkanInstance &yaveVulkanInstance, - YaveWindow &window) { - this->instance = yaveVulkanInstance.getVkInstance(); - if (glfwCreateWindowSurface(*instance, window.getGLFWWindow(), nullptr, - &surface)) { + YaveWindow *window) + : instance(yaveVulkanInstance) { + if (glfwCreateWindowSurface(*instance.getVkInstance(), + window->getGLFWWindow(), nullptr, &surface)) { throw std::runtime_error("failed to create window surface!"); } } +VkSurfaceKHR *YaveVulkanSurface::getVkSurface() { return &this->surface; } + YaveVulkanSurface::~YaveVulkanSurface() { - vkDestroySurfaceKHR(*instance, surface, nullptr); + vkDestroySurfaceKHR(*instance.getVkInstance(), surface, nullptr); } } // namespace yave diff --git a/src/yave_vulkan_surface.hpp b/src/yave_vulkan_surface.hpp index e46fbfb..e245b56 100644 --- a/src/yave_vulkan_surface.hpp +++ b/src/yave_vulkan_surface.hpp @@ -1,26 +1,28 @@ #pragma once -#include "yave_vulkan_instance.hpp" #include "yave_window.hpp" -#include +#include #define GLFW_INCLUDE_VULKAN #include namespace yave { +class YaveVulkanInstance; class YaveVulkanSurface { private: // Keep reference to instance this surface is attached to - VkInstance *instance; + YaveVulkanInstance &instance; VkSurfaceKHR surface; public: - YaveVulkanSurface(YaveVulkanInstance &yaveVulkanInstance, YaveWindow &window); + YaveVulkanSurface(YaveVulkanInstance &yaveVulkanInstance, YaveWindow *window); ~YaveVulkanSurface(); - // + + VkSurfaceKHR *getVkSurface(); + // Delete Copy constructors // This class should match one to one with vulkan instances YaveVulkanSurface(const YaveVulkanSurface &) = delete;