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