From 10ef244152bf6adfd1f34eba5e4ffc5ea32a17f3 Mon Sep 17 00:00:00 2001 From: Sebastian Gaida <gaida@ca-digit.com> Date: Tue, 11 May 2021 13:49:51 +0200 Subject: [PATCH] [#16] adjust to core class after merge-conflicts adjusted swapchain and window class after the big mess of the core class :) added temporarily utils functions to core class --- include/vkcv/Core.hpp | 27 +++++ include/vkcv/SwapChain.hpp | 15 +-- include/vkcv/Window.hpp | 2 +- projects/first_triangle/src/main.cpp | 2 +- src/vkcv/Core.cpp | 91 +++++++++++++++- src/vkcv/SwapChain.cpp | 153 ++++++++++++++------------- src/vkcv/Window.cpp | 10 +- 7 files changed, 200 insertions(+), 100 deletions(-) diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index 7a7f3be7..4fcc50b0 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -7,6 +7,7 @@ #include <vulkan/vulkan.hpp> #include "vkcv/Context.hpp" #include "vkcv/Handles.hpp" +#include <GLFW/glfw3.h> namespace vkcv { @@ -97,4 +98,30 @@ namespace vkcv PipelineHandle createPipeline(const Pipeline &pipeline); }; + + /** + * initializes glfw once and increases the counter + */ + void initGLFW(); + + /** + * terminates glfw once, if it was initialized or decreases the counter + */ + void terminateGLFW(); + + /** + * gets the window width + * @param window glfwWindow + * @return int with window width + */ + [[nodiscard]] + int getWidth(GLFWwindow *window); + + /** + * gets the window height + * @param window glfwWindow + * @return int with window height + */ + [[nodiscard]] + int getHeight(GLFWwindow *window); } diff --git a/include/vkcv/SwapChain.hpp b/include/vkcv/SwapChain.hpp index d6f24ef5..d47cb48d 100644 --- a/include/vkcv/SwapChain.hpp +++ b/include/vkcv/SwapChain.hpp @@ -1,6 +1,6 @@ #pragma once #include "vulkan/vulkan.hpp" -#include "Context.hpp" +#include "Core.hpp" #include <GLFW/glfw3.h> #include <iostream> @@ -13,15 +13,9 @@ namespace vkcv { private: vk::SurfaceKHR m_surface; - const vkcv::Context* m_context; + const vkcv::Core* m_core; - SwapChain(vk::SurfaceKHR surface, const vkcv::Context* context); - - static vk::SurfaceFormatKHR chooseSwapSurfaceFormat(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface); - - static vk::PresentModeKHR choosePresentMode(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface); - - static vk::Extent2D chooseSwapExtent(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface, GLFWwindow* window ); + SwapChain(vk::SurfaceKHR surface, const vkcv::Core* core); public: // bin mir grade unsicher wegen der Mehrfachinstanziierung der Klasse @@ -29,8 +23,7 @@ namespace vkcv { SwapChain(const SwapChain &other) = delete; SwapChain(SwapChain &&other) = default; - static SwapChain create(GLFWwindow *window, const vkcv::Context* Context); - static vk::SurfaceKHR createSurface(GLFWwindow *window, const vk::Instance& instance, const vk::PhysicalDevice& physicalDevice); + static SwapChain create(GLFWwindow *window, const vkcv::Core* core); virtual ~SwapChain(); }; diff --git a/include/vkcv/Window.hpp b/include/vkcv/Window.hpp index a1f4a2b6..43fce827 100644 --- a/include/vkcv/Window.hpp +++ b/include/vkcv/Window.hpp @@ -34,7 +34,7 @@ namespace vkcv { * @param[in] resizable resize ability of the window (optional) * @return Window class */ - static Window create(const vkcv::Context& context, const char *windowTitle, int width = -1, int height = -1, bool resizable = false); + static Window create(const vkcv::Core& core, const char *windowTitle, int width = -1, int height = -1, bool resizable = false); /** * checks if the window is still open, or the close event was called * This function should be changed/removed later on diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index 185d645d..ab111728 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -20,7 +20,7 @@ int main(int argc, const char** argv) { const vk::Device& device = context.getDevice(); vkcv::Window window = vkcv::Window::create( - context, + core, applicationName, 800, 600, diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 94f8ac4e..9f28db42 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -146,6 +146,38 @@ namespace vkcv return true; } + + std::vector<const char*> getRequiredExtensions() { + uint32_t glfwExtensionCount = 0; + const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); + std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); + +#ifndef NDEBUG + extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); +#endif + + return extensions; + } + + /** + * @brief finds an queue family index that fits with the given queue flags to create a queue handle + * @param flag The given flag that specifies as which queue type the accessed queue should be treated + * @param createInfos The createInfos of the created queues depending on the logical device + * @param device The physical with which the queue families can be accessed + * @return a fitting queue family index + */ + int findQueueFamilyIndex(vk::QueueFlagBits flag, std::vector<vk::DeviceQueueCreateInfo> &createInfos, vk::PhysicalDevice &device){ + std::vector<vk::QueueFamilyProperties> queueFamilyProperties = device.getQueueFamilyProperties(); + for (auto i = createInfos.begin(); i != createInfos.end(); ++i ) { + auto createInfo = *i; + int index = createInfo.queueFamilyIndex; + if(static_cast<uint32_t>(queueFamilyProperties[index].queueFlags & flag) != 0){ + return index; + } + } + return -1; + } + Core Core::create(const char *applicationName, uint32_t applicationVersion, uint32_t queueCount, @@ -153,7 +185,7 @@ namespace vkcv std::vector<const char *> instanceExtensions, std::vector<const char *> deviceExtensions) { - + vkcv::initGLFW(); // check for layer support const std::vector<vk::LayerProperties>& layerProperties = vk::enumerateInstanceLayerProperties(); @@ -190,9 +222,9 @@ namespace vkcv throw std::runtime_error("The requested instance extensions are not supported!"); } -#ifndef NDEBUG - instanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); -#endif + // for GLFW: get all required extensions + std::vector<const char*> requiredExtensions = getRequiredExtensions(); + instanceExtensions.insert(instanceExtensions.end(), requiredExtensions.begin(), requiredExtensions.end()); const vk::ApplicationInfo applicationInfo( applicationName, @@ -256,7 +288,23 @@ namespace vkcv vk::Device device = physicalDevice.createDevice(deviceCreateInfo); - // TODO: implement device.getQueue() to access the queues, if needed + + uint32_t graphicsQueueFamilyIndex = findQueueFamilyIndex({vk::QueueFlagBits::eGraphics}, qCreateInfos, physicalDevice); + if(graphicsQueueFamilyIndex == -1){ + throw std::runtime_error("It is not possible to access another queue as a graphics queue."); + } + uint32_t computeQueueFamilyIndex = findQueueFamilyIndex({vk::QueueFlagBits::eCompute}, qCreateInfos, physicalDevice); + if(computeQueueFamilyIndex == -1){ + throw std::runtime_error("It is not possible to access another queue as a compute queue."); + } + uint32_t transferQueueFamilyIndex = findQueueFamilyIndex({vk::QueueFlagBits::eTransfer}, qCreateInfos, physicalDevice); + if(transferQueueFamilyIndex == -1){ + throw std::runtime_error("It is not possible to access another queue as a transfer queue."); + } + vk::Queue graphicsQueue = device.getQueue( graphicsQueueFamilyIndex, 0 ); + vk::Queue computeQueue = device.getQueue(computeQueueFamilyIndex,1); + vk::Queue transferQueue = device.getQueue(transferQueueFamilyIndex,2); + Context context(instance, physicalDevice, device); return Core(std::move(context)); @@ -270,4 +318,37 @@ namespace vkcv Core::Core(Context &&context) noexcept : m_Context(std::move(context)) {} + + int glfwCounter = 0; + + void initGLFW() { + + if (glfwCounter == 0) { + int glfwSuccess = glfwInit(); + + if (glfwSuccess == GLFW_FALSE) { + throw std::runtime_error("Could not initialize GLFW"); + } + } + glfwCounter++; + } + + void terminateGLFW() { + if (glfwCounter == 1) { + glfwTerminate(); + } + glfwCounter--; + } + + int getWidth(GLFWwindow *window) { + int width; + glfwGetWindowSize(window, &width, nullptr); + return width; + } + + int getHeight(GLFWwindow *window) { + int height; + glfwGetWindowSize(window, nullptr, &height); + return height; + } } diff --git a/src/vkcv/SwapChain.cpp b/src/vkcv/SwapChain.cpp index 9a0c9ab5..04adf327 100644 --- a/src/vkcv/SwapChain.cpp +++ b/src/vkcv/SwapChain.cpp @@ -1,84 +1,27 @@ -#include "/vkcv/SwapChain.hpp" + +#include <vkcv/SwapChain.hpp> namespace vkcv { - SwapChain::SwapChain(vk::SurfaceKHR surface, const vkcv::Context* context) - : m_surface(surface), m_context(context) + SwapChain::SwapChain(vk::SurfaceKHR surface, const vkcv::Core* core) + : m_surface(surface), m_core(core) {} - SwapChain SwapChain::create(GLFWwindow* window, const vkcv::Context* context){ - - const vk::Instance& instance = context->getInstance(); - const vk::PhysicalDevice& physicalDevice = context->getPhysicalDevice(); - const vk::Device& device = context->getDevice(); - - vk::SurfaceKHR surface = createSurface(window,instance,physicalDevice); - - vk::Extent2D extent2D = chooseSwapExtent(physicalDevice, surface, window); - vk::SurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(physicalDevice, surface); - vk::PresentModeKHR presentMode = choosePresentMode(physicalDevice, surface); - - -// vk::SwapchainCreateInfoKHR swapchainCreateInfo( -// vk::SwapchainCreateFlagBitsKHR() -// VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, // VkStructureType sType -// nullptr, // const void *pNext -// 0, // VkSwapchainCreateFlagsKHR flags -// surface, // VkSurfaceKHR surface -// desired_number_of_images, // uint32_t minImageCount -// desired_format.format, // VkFormat imageFormat -// desired_format.colorSpace, // VkColorSpaceKHR imageColorSpace -// desired_extent, // VkExtent2D imageExtent -// 1, // uint32_t imageArrayLayers -// desired_usage, // VkImageUsageFlags imageUsage -// VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode imageSharingMode -// 0, // uint32_t queueFamilyIndexCount -// nullptr, // const uint32_t *pQueueFamilyIndices -// desired_transform, // VkSurfaceTransformFlagBitsKHR preTransform -// VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, // VkCompositeAlphaFlagBitsKHR compositeAlpha -// desired_present_mode, // VkPresentModeKHR presentMode -// VK_TRUE, // VkBool32 clipped -// old_swap_chain // VkSwapchainKHR oldSwapchain -// ); - -// vk::SwapchainCreateInfoKHR swapchainCreateInfo( -// vk::SwapchainCreateFlagsKHR(), //flags -// surface, // surface -// surfaceCapabilities.minImageCount, // minImageCount TODO: how many do we need for our application?? "must be less than or equal to the value returned in maxImageCount" -// vk::Format::eB8G8R8A8Unorm, // imageFormat TODO: what image format should be used? -// vk::ColorSpaceKHR::eSrgbNonlinear, // imageColorSpace TODO: which color space should be used? -// vk::Extent2D(width, height), // imageExtent -// 1, // imageArrayLayers TODO: should we only allow non-stereoscopic applications? yes -> 1, no -> ? "must be greater than 0, less or equal to maxImageArrayLayers" -// vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eDepthStencilAttachment, // imageUsage TODO: what attachments? only color? depth? -// vk::SharingMode::eExclusive, // imageSharingMode TODO: which sharing mode? "VK_SHARING_MODE_EXCLUSIV access exclusive to a single queue family, better performance", "VK_SHARING_MODE_CONCURRENT access from multiple queues" -// 0, // queueFamilyIndexCount, the number of queue families having access to the image(s) of the swapchain when imageSharingMode is VK_SHARING_MODE_CONCURRENT -// nullptr, // pQueueFamilyIndices, the pointer to an array of queue family indices having access to the images(s) of the swapchain when imageSharingMode is VK_SHARING_MODE_CONCURRENT -// vk::SurfaceTransformFlagBitsKHR::eIdentity, // preTransform, transformations applied onto the image before display -// vk::CompositeAlphaFlagBitsKHR::eOpaque, // compositeAlpha, TODO: how to handle transparent pixels? do we need transparency? If no -> opaque -// vk::PresentModeKHR::eFifo, // presentMode -// true, // clipped -// nullptr // oldSwapchain -// ); - - return SwapChain(surface, context); - - } - - vk::SurfaceKHR SwapChain::createSurface(GLFWwindow *window, const vk::Instance &instance, const vk::PhysicalDevice& physicalDevice) { - //create surface - VkSurfaceKHR surface; - // 0 means VK_SUCCESS - //std::cout << "FAIL: " << glfwCreateWindowSurface(VkInstance(instance), window, nullptr, &newSurface) << std::endl; - if(glfwCreateWindowSurface(VkInstance(instance), window, nullptr, &surface) != VK_SUCCESS) { - throw std::runtime_error("failed to create a window surface!"); - } - vk::Bool32 surfaceSupport = false; - // ToDo: hierfuer brauchen wir jetzt den queuefamiliy Index -> siehe ToDo in Context.cpp - //if(physicalDevice.getSurfaceSupportKHR()) + vk::SurfaceKHR createSurface(GLFWwindow *window, const vk::Instance &instance, const vk::PhysicalDevice& physicalDevice) { + //create surface + VkSurfaceKHR surface; + // 0 means VK_SUCCESS + //std::cout << "FAIL: " << glfwCreateWindowSurface(VkInstance(instance), window, nullptr, &newSurface) << std::endl; + if(glfwCreateWindowSurface(VkInstance(instance), window, nullptr, &surface) != VK_SUCCESS) { + throw std::runtime_error("failed to create a window surface!"); + } + vk::Bool32 surfaceSupport = false; + // ToDo: hierfuer brauchen wir jetzt den queuefamiliy Index -> siehe ToDo in Context.cpp + //if(physicalDevice.getSurfaceSupportKHR()) return vk::SurfaceKHR(surface); } - vk::Extent2D SwapChain::chooseSwapExtent(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface, GLFWwindow* window){ + vk::Extent2D chooseSwapExtent(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface, GLFWwindow* window){ vk::SurfaceCapabilitiesKHR surfaceCapabilities; if(physicalDevice.getSurfaceCapabilitiesKHR(surface,&surfaceCapabilities) != vk::Result::eSuccess){ throw std::runtime_error("cannot get surface capabilities. There is an issue with the surface."); @@ -100,7 +43,7 @@ namespace vkcv { return extent2D; } - vk::SurfaceFormatKHR SwapChain::chooseSwapSurfaceFormat(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { + vk::SurfaceFormatKHR chooseSwapSurfaceFormat(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { uint32_t formatCount; physicalDevice.getSurfaceFormatsKHR(surface, &formatCount, nullptr); std::vector<vk::SurfaceFormatKHR> availableFormats(formatCount); @@ -116,7 +59,7 @@ namespace vkcv { return availableFormats[0]; } - vk::PresentModeKHR SwapChain::choosePresentMode(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { + vk::PresentModeKHR choosePresentMode(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface) { uint32_t modeCount; physicalDevice.getSurfacePresentModesKHR( surface, &modeCount, nullptr ); std::vector<vk::PresentModeKHR> availablePresentModes(modeCount); @@ -132,9 +75,67 @@ namespace vkcv { return vk::PresentModeKHR::eFifo; } + SwapChain SwapChain::create(GLFWwindow* window, const vkcv::Core* core){ + + const vk::Instance& instance = core->getContext().getInstance(); + const vk::PhysicalDevice& physicalDevice = core->getContext().getPhysicalDevice(); + const vk::Device& device = core->getContext().getDevice(); + + vk::SurfaceKHR surface = createSurface(window,instance,physicalDevice); + + vk::Extent2D extent2D = chooseSwapExtent(physicalDevice, surface, window); + vk::SurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(physicalDevice, surface); + vk::PresentModeKHR presentMode = choosePresentMode(physicalDevice, surface); + + +// vk::SwapchainCreateInfoKHR swapchainCreateInfo( +// vk::SwapchainCreateFlagBitsKHR() +// VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, // VkStructureType sType +// nullptr, // const void *pNext +// 0, // VkSwapchainCreateFlagsKHR flags +// surface, // VkSurfaceKHR surface +// desired_number_of_images, // uint32_t minImageCount +// desired_format.format, // VkFormat imageFormat +// desired_format.colorSpace, // VkColorSpaceKHR imageColorSpace +// desired_extent, // VkExtent2D imageExtent +// 1, // uint32_t imageArrayLayers +// desired_usage, // VkImageUsageFlags imageUsage +// VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode imageSharingMode +// 0, // uint32_t queueFamilyIndexCount +// nullptr, // const uint32_t *pQueueFamilyIndices +// desired_transform, // VkSurfaceTransformFlagBitsKHR preTransform +// VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, // VkCompositeAlphaFlagBitsKHR compositeAlpha +// desired_present_mode, // VkPresentModeKHR presentMode +// VK_TRUE, // VkBool32 clipped +// old_swap_chain // VkSwapchainKHR oldSwapchain +// ); + +// vk::SwapchainCreateInfoKHR swapchainCreateInfo( +// vk::SwapchainCreateFlagsKHR(), //flags +// surface, // surface +// surfaceCapabilities.minImageCount, // minImageCount TODO: how many do we need for our application?? "must be less than or equal to the value returned in maxImageCount" +// vk::Format::eB8G8R8A8Unorm, // imageFormat TODO: what image format should be used? +// vk::ColorSpaceKHR::eSrgbNonlinear, // imageColorSpace TODO: which color space should be used? +// vk::Extent2D(width, height), // imageExtent +// 1, // imageArrayLayers TODO: should we only allow non-stereoscopic applications? yes -> 1, no -> ? "must be greater than 0, less or equal to maxImageArrayLayers" +// vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eDepthStencilAttachment, // imageUsage TODO: what attachments? only color? depth? +// vk::SharingMode::eExclusive, // imageSharingMode TODO: which sharing mode? "VK_SHARING_MODE_EXCLUSIV access exclusive to a single queue family, better performance", "VK_SHARING_MODE_CONCURRENT access from multiple queues" +// 0, // queueFamilyIndexCount, the number of queue families having access to the image(s) of the swapchain when imageSharingMode is VK_SHARING_MODE_CONCURRENT +// nullptr, // pQueueFamilyIndices, the pointer to an array of queue family indices having access to the images(s) of the swapchain when imageSharingMode is VK_SHARING_MODE_CONCURRENT +// vk::SurfaceTransformFlagBitsKHR::eIdentity, // preTransform, transformations applied onto the image before display +// vk::CompositeAlphaFlagBitsKHR::eOpaque, // compositeAlpha, TODO: how to handle transparent pixels? do we need transparency? If no -> opaque +// vk::PresentModeKHR::eFifo, // presentMode +// true, // clipped +// nullptr // oldSwapchain +// ); + + return SwapChain(surface, core); + + } + SwapChain::~SwapChain() { // m_context->getDevice().destroySwapchainKHR( m_swapChain ); - m_context->getInstance().destroySurfaceKHR( m_surface ); + m_core->getContext().getInstance().destroySurfaceKHR( m_surface ); } } diff --git a/src/vkcv/Window.cpp b/src/vkcv/Window.cpp index 96df2f5a..962e8cca 100644 --- a/src/vkcv/Window.cpp +++ b/src/vkcv/Window.cpp @@ -19,13 +19,11 @@ namespace vkcv { glfwDestroyWindow(m_window); s_WindowCount--; - if(s_WindowCount == 0) - glfwTerminate(); + terminateGLFW(); } - Window Window::create(const char *windowTitle, int width, int height, bool resizable) { - if(s_WindowCount == 0) - glfwInit(); + Window Window::create(const vkcv::Core& core, const char *windowTitle, int width, int height, bool resizable) { + initGLFW(); s_WindowCount++; @@ -39,7 +37,7 @@ namespace vkcv { const vkcv::SwapChain swapChain = vkcv::SwapChain::create( window, - &context); + &core); return Window(window, &swapChain); } -- GitLab