From af7b533f50fef314a5e7aaa8abec69e445b1dfdf Mon Sep 17 00:00:00 2001 From: Lillian Salehi Date: Wed, 16 Oct 2024 06:02:15 -0500 Subject: [PATCH] clean up a RIDICULOUS amount of shit code lmfao, instantiation < static calls (im dumb as hell) --- src/debug/vulkandebuglibs.cpp | 215 +++++++++++++++--------------- src/debug/vulkandebuglibs.h | 17 +-- src/devicelibrary.cpp | 33 ++--- src/devicelibrary.h | 39 +++--- src/entrypoint.cpp | 97 +++++++------- src/entrypoint.h | 5 +- src/global.cpp | 6 +- src/global.h | 21 +-- src/graphics/buffers.cpp | 44 +++--- src/graphics/buffers.h | 36 ++--- src/graphics/graphicspipeline.cpp | 59 ++++---- src/graphics/graphicspipeline.h | 28 ++-- src/graphics/model.cpp | 9 +- src/graphics/model.h | 12 +- src/graphics/render.cpp | 35 +++-- src/graphics/render.h | 12 +- src/graphics/texture.cpp | 34 ++--- src/graphics/texture.h | 21 +-- 18 files changed, 341 insertions(+), 382 deletions(-) diff --git a/src/debug/vulkandebuglibs.cpp b/src/debug/vulkandebuglibs.cpp index 3cc31d1..10ca744 100644 --- a/src/debug/vulkandebuglibs.cpp +++ b/src/debug/vulkandebuglibs.cpp @@ -1,27 +1,26 @@ #include "vulkandebuglibs.h" -using namespace Debug; // This is our messenger object! It handles passing along debug messages to the debug callback we will also set. VkDebugUtilsMessengerEXT debugMessenger; // This is the set of "layers" to hook into. Basically, layers are used to tell the messenger what data we want, its a filter. *validation* is the general blanket layer to cover incorrect usage. - -std::vector getRequiredExtensions() { - // This gets a little weird, Vulkan is platform agnostic, so you need to figure out what extensions to interface with the current system are needed - // So, to figure out what extension codes and how many to use, feed the pointer into *glfwGetRequiredInstanceExtensions*, which will get the necessary extensions! - // From there, we can send that over to our createInfo Vulkan info struct to make it fully platform agnostic! - uint32_t glfwExtensionCount = 0; - const char** glfwExtensions; - glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); +namespace debug_libs { + std::vector getRequiredExtensions() { + // This gets a little weird, Vulkan is platform agnostic, so you need to figure out what extensions to interface with the current system are needed + // So, to figure out what extension codes and how many to use, feed the pointer into *glfwGetRequiredInstanceExtensions*, which will get the necessary extensions! + // From there, we can send that over to our createInfo Vulkan info struct to make it fully platform agnostic! + uint32_t glfwExtensionCount = 0; + const char** glfwExtensions; + glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); - std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); + std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); - if(Global::enableValidationLayers) { - extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + if(Global::enableValidationLayers) { + extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + } + return extensions; } - return extensions; -} -static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( + static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, @@ -33,119 +32,119 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( std::cout << "\n"; return VK_FALSE; -} - - - -void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) { - // There is absolutely nothing about this i like, those long ass flags for messageType and Severity are just fucking hex values. Khronos should never cook again ToT - // On a serious note, this is just a struct to define the parameters of the debug messenger, nothing super special. - createInfo = {}; - 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.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.pUserData = nullptr; // Optional -} - -void vulkandebuglibs::vulkanDebugSetup(VkInstanceCreateInfo& createInfo, VkInstance& instance) { - // This function is quite useful, we first populate the debug create info structure, all the parameters dictating how the debug messenger will operate. - // The reason we populate the debug messenger so late is actually on purpose, we need to set the createInfo, which depends on the debugMessenger info, - // and if we set it before the creation of the instance, we cant debug vkCreateInstance or vkDestroyInstance! It's timed perfectly as of now. - VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{}; - auto extensions = getRequiredExtensions(); - createInfo.enabledExtensionCount = static_cast(extensions.size()); - createInfo.ppEnabledExtensionNames = extensions.data(); - - if(Global::enableValidationLayers) { - createInfo.enabledLayerCount = static_cast(Global::validationLayers.size()); - createInfo.ppEnabledLayerNames = Global::validationLayers.data(); - - populateDebugMessengerCreateInfo(debugCreateInfo); - createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debugCreateInfo; - - } else { - createInfo.enabledLayerCount = 0; - createInfo.pNext = nullptr; } - if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { - throw std::runtime_error("failed to create instance!"); + + + void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) { + // There is absolutely nothing about this i like, those long ass flags for messageType and Severity are just fucking hex values. Khronos should never cook again ToT + // On a serious note, this is just a struct to define the parameters of the debug messenger, nothing super special. + createInfo = {}; + 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.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.pUserData = nullptr; // Optional } -} -void vulkandebuglibs::checkUnavailableValidationLayers() { - // Check if we are trying to hook validation layers in without support. - if(Global::enableValidationLayers && !checkValidationLayerSupport()) { - throw std::runtime_error("Validation layers request, but not available! Are your SDK path variables set?"); + void Debug::vulkanDebugSetup(VkInstanceCreateInfo& createInfo, VkInstance& instance) { + // This function is quite useful, we first populate the debug create info structure, all the parameters dictating how the debug messenger will operate. + // The reason we populate the debug messenger so late is actually on purpose, we need to set the createInfo, which depends on the debugMessenger info, + // and if we set it before the creation of the instance, we cant debug vkCreateInstance or vkDestroyInstance! It's timed perfectly as of now. + VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{}; + auto extensions = getRequiredExtensions(); + createInfo.enabledExtensionCount = static_cast(extensions.size()); + createInfo.ppEnabledExtensionNames = extensions.data(); + + if(Global::enableValidationLayers) { + createInfo.enabledLayerCount = static_cast(Global::validationLayers.size()); + createInfo.ppEnabledLayerNames = Global::validationLayers.data(); + + populateDebugMessengerCreateInfo(debugCreateInfo); + createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debugCreateInfo; + + } else { + createInfo.enabledLayerCount = 0; + createInfo.pNext = nullptr; + } + + if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { + throw std::runtime_error("failed to create instance!"); + } } -} -bool vulkandebuglibs::checkValidationLayerSupport() { - // This function is used to check Validation Layer Support, validation layers are the debug trace tools in the Vulkan SDK. - // layerCount will be used as the var to keep track of the number of requested validation layer - // VkLayerProperties is a structure with data on the layername, desc, versions and etc. + void Debug::checkUnavailableValidationLayers() { + // Check if we are trying to hook validation layers in without support. + if(Global::enableValidationLayers && !checkValidationLayerSupport()) { + throw std::runtime_error("Validation layers request, but not available! Are your SDK path variables set?"); + } + } - uint32_t layerCount; - vkEnumerateInstanceLayerProperties(&layerCount, nullptr); + bool Debug::checkValidationLayerSupport() { + // This function is used to check Validation Layer Support, validation layers are the debug trace tools in the Vulkan SDK. + // layerCount will be used as the var to keep track of the number of requested validation layer + // VkLayerProperties is a structure with data on the layername, desc, versions and etc. - std::vector availableLayers(layerCount); - vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); + uint32_t layerCount; + vkEnumerateInstanceLayerProperties(&layerCount, nullptr); - for(const char* layerName : Global::validationLayers) { - bool layerFound = false; + std::vector availableLayers(layerCount); + vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); - for(const auto& layerProperties : availableLayers) { - if(strcmp(layerName, layerProperties.layerName) == 0) { - layerFound = true; - break; + for(const char* layerName : Global::validationLayers) { + bool layerFound = false; + + for(const auto& layerProperties : availableLayers) { + if(strcmp(layerName, layerProperties.layerName) == 0) { + layerFound = true; + break; + } + } + if(!layerFound) { + return false; } } - - if(!layerFound) { - return false; - } + return true; } - return true; -} -VkResult CreateDebugUtilsMessengerEXT( - VkInstance instance, - const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, - const VkAllocationCallbacks* pAllocator, - VkDebugUtilsMessengerEXT* pDebugMessenger) { - // This function builds out debug messenger structure! - // It's a little odd, we have to look up the address of the vkCreateDebugUtilsMessengerEXT ourselves because its an extension function, - // therefore, not auto-loaded. + VkResult CreateDebugUtilsMessengerEXT( + VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDebugUtilsMessengerEXT* pDebugMessenger) { + // This function builds out debug messenger structure! + // It's a little odd, we have to look up the address of the vkCreateDebugUtilsMessengerEXT ourselves because its an extension function, + // therefore, not auto-loaded. auto func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); + if (func != nullptr) { - return func(instance, pCreateInfo, pAllocator, pDebugMessenger); + return func(instance, pCreateInfo, pAllocator, pDebugMessenger); } else { - return VK_ERROR_EXTENSION_NOT_PRESENT; + return VK_ERROR_EXTENSION_NOT_PRESENT; } -} + } -void vulkandebuglibs::DestroyDebugUtilsMessengerEXT(VkInstance instance, - const VkAllocationCallbacks* pAllocator) { - // We are doing kind of the same thing as before in the create function, find the address of the DestroyDebugUtils function, and call it. + void Debug::DestroyDebugUtilsMessengerEXT(VkInstance instance, + const VkAllocationCallbacks* pAllocator) { + // We are doing kind of the same thing as before in the create function, find the address of the DestroyDebugUtils function, and call it. - auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); - if(func != nullptr) { - func(instance, debugMessenger, pAllocator); + auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); + if(func != nullptr) { + func(instance, debugMessenger, pAllocator); + } + } + + void Debug::setupDebugMessenger(VkInstance& vulkanInstance) { + // This is a pretty simple function! we just pass in the values to build the debug messenger, populate the structure with the data we want, + // and safely create it, covering for runtime errors as per usual, this is the first thing that will be called! + if(!Global::enableValidationLayers) return; + + VkDebugUtilsMessengerCreateInfoEXT createInfo; + populateDebugMessengerCreateInfo(createInfo); + + if(CreateDebugUtilsMessengerEXT(vulkanInstance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) { + throw std::runtime_error("Failed to set up the Debug Messenger!"); + } } } - -void vulkandebuglibs::setupDebugMessenger(VkInstance& vulkanInstance) { - // This is a pretty simple function! we just pass in the values to build the debug messenger, populate the structure with the data we want, - // and safely create it, covering for runtime errors as per usual, this is the first thing that will be called! - if(!Global::enableValidationLayers) return; - - VkDebugUtilsMessengerCreateInfoEXT createInfo; - populateDebugMessengerCreateInfo(createInfo); - - if(CreateDebugUtilsMessengerEXT(vulkanInstance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) { - throw std::runtime_error("Failed to set up the Debug Messenger!"); - } -} - diff --git a/src/debug/vulkandebuglibs.h b/src/debug/vulkandebuglibs.h index f8548c2..062ccfb 100644 --- a/src/debug/vulkandebuglibs.h +++ b/src/debug/vulkandebuglibs.h @@ -1,17 +1,14 @@ #pragma once -#include -#include #include #include "../global.h" -namespace Debug { - class vulkandebuglibs { - +namespace debug_libs { + class Debug { public: - void vulkanDebugSetup(VkInstanceCreateInfo& createInfo, VkInstance& instance); - bool checkValidationLayerSupport(); - void checkUnavailableValidationLayers(); - void setupDebugMessenger(VkInstance& vulkanInstance); - void DestroyDebugUtilsMessengerEXT(VkInstance instance, const VkAllocationCallbacks* pAllocator); + static void vulkanDebugSetup(VkInstanceCreateInfo& createInfo, VkInstance& instance); + static bool checkValidationLayerSupport(); + static void checkUnavailableValidationLayers(); + static void setupDebugMessenger(VkInstance& vulkanInstance); + static void DestroyDebugUtilsMessengerEXT(VkInstance instance, const VkAllocationCallbacks* pAllocator); }; } diff --git a/src/devicelibrary.cpp b/src/devicelibrary.cpp index f41f6a1..076e396 100644 --- a/src/devicelibrary.cpp +++ b/src/devicelibrary.cpp @@ -1,10 +1,6 @@ #include "devicelibrary.h" -#include "global.h" -#include - - -namespace DeviceControl { +namespace device_libs { VkPhysicalDeviceProperties deviceProperties; @@ -13,8 +9,6 @@ namespace DeviceControl { VkExtent2D swapChainExtent; std::vector swapChainImageViews; - - struct SwapChainSupportDetails { VkSurfaceCapabilitiesKHR capabilities; std::vector formats; @@ -143,7 +137,7 @@ namespace DeviceControl { } } // --------------------------------------- External Functions ----------------------------------------- // - void devicelibrary::pickPhysicalDevice(VkInstance& instance) { + void DeviceControl::pickPhysicalDevice(VkInstance& instance) { uint32_t deviceCount = 0; vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); @@ -165,17 +159,17 @@ namespace DeviceControl { throw std::runtime_error("Failed to find a suitable GPU!"); } } - void devicelibrary::destroySurface(VkInstance& instance) { + void DeviceControl::destroySurface(VkInstance& instance) { vkDestroySurfaceKHR(instance, Global::surface, nullptr); if(Global::enableValidationLayers) std::cout << "Destroyed surface safely\n" << std::endl; } - void devicelibrary::createSurface(VkInstance& instance, GLFWwindow* window) { + void DeviceControl::createSurface(VkInstance& instance, GLFWwindow* window) { if(glfwCreateWindowSurface(instance, window, nullptr, &Global::surface) != VK_SUCCESS) { throw std::runtime_error("Failed to create window surface!!"); } if(Global::enableValidationLayers) std::cout << "GLFW Window Surface created successfully\n" << std::endl; } - void devicelibrary::createLogicalDevice() { + void DeviceControl::createLogicalDevice() { // Describe how many queues we want for a single family (1) here, right now we are solely interested in graphics capabilites, // but Compute Shaders, transfer ops, decode and encode operations can also queued with setup! We also assign each queue a priority. // We do this by looping over all the queueFamilies and sorting them by indices to fill the queue at the end! @@ -221,7 +215,7 @@ namespace DeviceControl { vkGetDeviceQueue(Global::device, indices.graphicsFamily.value(), 0, &Global::graphicsQueue); vkGetDeviceQueue(Global::device, indices.presentFamily.value(), 0, &Global::presentQueue); } - void devicelibrary::createSwapChain(GLFWwindow* window) { + void DeviceControl::createSwapChain(GLFWwindow* window) { SwapChainSupportDetails swapChainSupport = querySwapChainSupport(Global::physicalDevice); VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats); @@ -287,11 +281,11 @@ namespace DeviceControl { swapChainImageFormat = surfaceFormat.format; swapChainExtent = extent; } - void devicelibrary::destroySwapChain() { + void DeviceControl::destroySwapChain() { vkDestroySwapchainKHR(Global::device, Global::swapChain, nullptr); if(Global::enableValidationLayers) std::cout << "Destroyed Swap Chain safely\n" << std::endl; } - VkImageView devicelibrary::createImageView(VkImage image, VkFormat format, VkImageAspectFlags flags) { + VkImageView DeviceControl::createImageView(VkImage image, VkFormat format, VkImageAspectFlags flags) { // This defines the parameters of a newly created image object! VkImageViewCreateInfo viewInfo{}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; @@ -311,28 +305,27 @@ namespace DeviceControl { return imageView; } - void devicelibrary::createImageViews() { + void DeviceControl::createImageViews() { swapChainImageViews.resize(swapChainImages.size()); for (uint32_t i = 0; i < swapChainImages.size(); i++) { swapChainImageViews[i] = createImageView(swapChainImages[i], swapChainImageFormat, VK_IMAGE_ASPECT_COLOR_BIT); } } - void devicelibrary::destroyImageViews() { + void DeviceControl::destroyImageViews() { for (auto imageView : swapChainImageViews) { vkDestroyImageView(Global::device, imageView, nullptr); } if(Global::enableValidationLayers) std::cout << "Image destroyed safely\n" << std::endl; } // --------------------------------------- Getters & Setters ------------------------------------------ // - VkFormat devicelibrary::getImageFormat() { + VkFormat DeviceControl::getImageFormat() { return swapChainImageFormat; } - std::vector devicelibrary::getSwapChainImageViews() { + std::vector DeviceControl::getSwapChainImageViews() { return swapChainImageViews; } - - VkExtent2D devicelibrary::getSwapChainExtent() { + VkExtent2D DeviceControl::getSwapChainExtent() { return swapChainExtent; } } diff --git a/src/devicelibrary.h b/src/devicelibrary.h index dce297e..37e2144 100644 --- a/src/devicelibrary.h +++ b/src/devicelibrary.h @@ -1,33 +1,30 @@ #pragma once #include "global.h" -#include -#include #include #include -#include #include #include -#include -namespace DeviceControl { -class devicelibrary { + +namespace device_libs { +class DeviceControl { public: - void pickPhysicalDevice(VkInstance& instance); - void createLogicalDevice(); - void createSurface(VkInstance& instance, GLFWwindow* window); - void destroySurface(VkInstance& instance); - void createSwapChain(GLFWwindow* window); - void destroySwapChain(); - VkImageView createImageView(VkImage image, VkFormat format, VkImageAspectFlags flags); - void createImageViews(); - void destroyImageViews(); - void createCommandPool(); - void destroyCommandPool(); + static void pickPhysicalDevice(VkInstance& instance); + static void createLogicalDevice(); + static void createSurface(VkInstance& instance, GLFWwindow* window); + static void destroySurface(VkInstance& instance); + static void createSwapChain(GLFWwindow* window); + static void destroySwapChain(); + static VkImageView createImageView(VkImage image, VkFormat format, VkImageAspectFlags flags); + static void createImageViews(); + static void destroyImageViews(); + static void createCommandPool(); + static void destroyCommandPool(); // ---------- Getters & Setters ----------- // - VkFormat getImageFormat(); - std::vector getSwapChainImageViews(); - VkExtent2D getSwapChainExtent(); - std::vector getSwapChainFramebuffers(); + static VkFormat getImageFormat(); + static std::vector getSwapChainImageViews(); + static VkExtent2D getSwapChainExtent(); + static std::vector getSwapChainFramebuffers(); }; } diff --git a/src/entrypoint.cpp b/src/entrypoint.cpp index 7d9a086..738671b 100644 --- a/src/entrypoint.cpp +++ b/src/entrypoint.cpp @@ -1,14 +1,6 @@ #include "entrypoint.h" -DeviceControl::devicelibrary deviceLibs; -Debug::vulkandebuglibs debugController; -Graphics::graphicspipeline graphicsPipeline; -RenderPresent::render renderPresentation; -BuffersLibraries::buffers buffers; -TextureLibraries::texture texture; -ModelLib::model model; -VkInstance vulkaninstance; -//TODO: add global instances? +VkInstance vulkaninstance; // Getters and Setters! void EntryApp::setFramebufferResized(bool setter) { @@ -21,8 +13,9 @@ static void framebufferResizeCallback(GLFWwindow* window, int width, int height) auto app = reinterpret_cast(glfwGetWindowUserPointer(window)); app->setFramebufferResized(true); } - // Initialize GLFW Window. First, Initialize GLFW lib, disable resizing for - // now, and create window. + +// Initialize GLFW Window. First, Initialize GLFW lib, disable resizing for +// now, and create window. void initWindow() { glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); @@ -33,7 +26,7 @@ void initWindow() { } void createInstance() { - debugController.checkUnavailableValidationLayers(); // Check if there is a mistake with our Validation Layers. + debug_libs::Debug::checkUnavailableValidationLayers(); // Check if there is a mistake with our Validation Layers. // Set application info for the vulkan instance! VkApplicationInfo appInfo{}; @@ -49,67 +42,69 @@ void createInstance() { createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; // Tell vulkan this is a info structure createInfo.pApplicationInfo = &appInfo; // We just created a new appInfo structure, so we pass the pointer to it. - debugController.vulkanDebugSetup(createInfo, vulkaninstance); // Handoff to the debug library to wrap the validation libs in! (And set the window up!) + debug_libs::Debug::vulkanDebugSetup(createInfo, vulkaninstance); // Handoff to the debug library to wrap the validation libs in! (And set the window up!) } void initVulkan() { + // Initialize vulkan and set up pipeline. createInstance(); - debugController.setupDebugMessenger(vulkaninstance); // The debug messenger is out holy grail, it gives us Vulkan related debug info when built with the -DDEBUG flag (as per the makefile) - deviceLibs.createSurface(vulkaninstance, Global::window); - deviceLibs.pickPhysicalDevice(vulkaninstance); - deviceLibs.createLogicalDevice(); - deviceLibs.createSwapChain(Global::window); - deviceLibs.createImageViews(); - graphicsPipeline.createRenderPass(); - buffers.createDescriptorSetLayout(); - graphicsPipeline.createGraphicsPipeline(); - graphicsPipeline.createCommandPool(); - texture.createDepthResources(); - graphicsPipeline.createFramebuffers(); - texture.createTextureImage(); - texture.createTextureImageView(); - texture.createTextureSampler(); - model.loadModel(); - buffers.createVertexBuffer(); - buffers.createIndexBuffer(); - buffers.createUniformBuffers(); - buffers.createDescriptorPool(); - buffers.createDescriptorSets(); - graphicsPipeline.createCommandBuffer(); - renderPresentation.createSyncObject(); + debug_libs::Debug::setupDebugMessenger(vulkaninstance); + device_libs::DeviceControl::createSurface(vulkaninstance, Global::window); + device_libs::DeviceControl::pickPhysicalDevice(vulkaninstance); + device_libs::DeviceControl::createLogicalDevice(); + device_libs::DeviceControl::createSwapChain(Global::window); + device_libs::DeviceControl::createImageViews(); + graphics_pipeline::Graphics::createRenderPass(); + buffers_libs::Buffers::createDescriptorSetLayout(); + graphics_pipeline::Graphics::createGraphicsPipeline(); + graphics_pipeline::Graphics::createCommandPool(); + texture_libs::Texture::createDepthResources(); + graphics_pipeline::Graphics::createFramebuffers(); + texture_libs::Texture::createTextureImage(); + texture_libs::Texture::createTextureImageView(); + texture_libs::Texture::createTextureSampler(); + modellib::Model::loadModel(); + buffers_libs::Buffers::createVertexBuffer(); + buffers_libs::Buffers::createIndexBuffer(); + buffers_libs::Buffers::createUniformBuffers(); + buffers_libs::Buffers::createDescriptorPool(); + buffers_libs::Buffers::createDescriptorSets(); + graphics_pipeline::Graphics::createCommandBuffer(); + render_present::Render::createSyncObject(); } -void mainLoop() { // This loop just updates the GLFW window. +void mainLoop() { while (!glfwWindowShouldClose(Global::window)) { glfwPollEvents(); - renderPresentation.drawFrame(); + render_present::Render::drawFrame(); } vkDeviceWaitIdle(Global::device); } -void cleanup() { // Similar to the last handoff, destroy the utils in a safe manner in the library! - renderPresentation.cleanupSwapChain(); - texture.createTextureSampler(); - texture.destroyTextureImage(); - buffers.destroyUniformBuffer(); - buffers.destroyDescriptorPool(); +void cleanup() { + render_present::Render::cleanupSwapChain(); + texture_libs::Texture::createTextureSampler(); + texture_libs::Texture::destroyTextureImage(); + buffers_libs::Buffers::destroyUniformBuffer(); + buffers_libs::Buffers::destroyDescriptorPool(); vkDestroyDescriptorSetLayout(Global::device, Global::descriptorSetLayout, nullptr); - graphicsPipeline.destroyGraphicsPipeline(); - graphicsPipeline.destroyRenderPass(); + graphics_pipeline::Graphics::destroyGraphicsPipeline(); + graphics_pipeline::Graphics::destroyRenderPass(); - buffers.destroyBuffers(); - renderPresentation.destroyFenceSemaphores(); - graphicsPipeline.destroyCommandPool(); + buffers_libs::Buffers::destroyBuffers(); + render_present::Render::destroyFenceSemaphores(); + graphics_pipeline::Graphics::destroyCommandPool(); vkDestroyDevice(Global::device, nullptr); if(Global::enableValidationLayers) { - debugController.DestroyDebugUtilsMessengerEXT(vulkaninstance, nullptr); + debug_libs::Debug::DestroyDebugUtilsMessengerEXT(vulkaninstance, nullptr); } - deviceLibs.destroySurface(vulkaninstance); + device_libs::DeviceControl::destroySurface(vulkaninstance); vkDestroyInstance(vulkaninstance, nullptr); glfwDestroyWindow(Global::window); glfwTerminate(); } + // External Functions EntryApp& EntryApp::getInstance() { static EntryApp instance; diff --git a/src/entrypoint.h b/src/entrypoint.h index 42bfb59..bd7f589 100644 --- a/src/entrypoint.h +++ b/src/entrypoint.h @@ -1,11 +1,10 @@ -#include -#include "devicelibrary.h" // Device Library includes global, redundant to include with it here #include "debug/vulkandebuglibs.h" #include "graphics/graphicspipeline.h" #include "graphics/render.h" -#include "graphics/texture.h" #include "global.h" #include "graphics/model.h" +#include "graphics/texture.h" + class EntryApp { public: static EntryApp& getInstance(); diff --git a/src/global.cpp b/src/global.cpp index 954617d..09fba97 100644 --- a/src/global.cpp +++ b/src/global.cpp @@ -1,6 +1,5 @@ #include "global.h" -#include "devicelibrary.h" -#include + namespace Global { const std::vector validationLayers = { @@ -33,13 +32,13 @@ namespace Global { std::vector vertices; // Index buffer definition, showing which points to reuse. std::vector indices; + Global::QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) { // First we feed in a integer we want to use to hold the number of queued items, that fills it, then we create that amount of default constructed *VkQueueFamilyProperties* structs. // These store the flags, the amount of queued items in the family, and timestamp data. Queue families are simply group collections of tasks we want to get done. // Next, we check the flags of the queueFamily item, use a bitwise and to see if they match, i.e. support graphical operations, then return that to notify that we have at least one family that supports VK_QUEUE_GRAPHICS_BIT. // Which means this device supports graphical operations! // We also do the same thing for window presentation, just check to see if its supported. - DeviceControl::devicelibrary deviceLibs; Global::QueueFamilyIndices indices; uint32_t queueFamilyCount = 0; @@ -67,5 +66,4 @@ namespace Global { } return indices; } - } diff --git a/src/global.h b/src/global.h index 8813357..a044b0c 100644 --- a/src/global.h +++ b/src/global.h @@ -1,24 +1,27 @@ #pragma once -#include "graphics/texture.h" -#include +#include + +#define GLM_FORCE_DEPTH_ZERO_TO_ONE +#include + +#include #include #include #include +#include #include + +#define GLFW_INCLUDE_VULKAN +#include + +#include #include #include #include #include -#include -#include #include -#define GLM_FORCE_DEPTH_ZERO_TO_ONE -#include -#include -#define GLFW_INCLUDE_VULKAN -#include namespace Global { // Global variables and includes we are going to use almost everywhere, validation layers hook into everything, and you need to check if they are enabled first, diff --git a/src/graphics/buffers.cpp b/src/graphics/buffers.cpp index 1770a38..b109bea 100644 --- a/src/graphics/buffers.cpp +++ b/src/graphics/buffers.cpp @@ -1,25 +1,17 @@ #include "buffers.h" -#include -#include -#include "../devicelibrary.h" VkBuffer vertexBuffer; VkDeviceMemory vertexBufferMemory; VkBuffer indexBuffer; VkDeviceMemory indexBufferMemory; VkDescriptorPool descriptorPool; -DeviceControl::devicelibrary deviceLibrary; std::vector uniformBuffers; std::vector uniformBuffersMemory; std::vector uniformBuffersMapped; - -namespace BuffersLibraries { - - - - uint32_t buffers::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) { +namespace buffers_libs { + uint32_t Buffers::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) { // Graphics cards offer different types of memory to allocate from, here we query to find the right type of memory for our needs. // Query the available types of memory to iterate over. VkPhysicalDeviceMemoryProperties memProperties; @@ -66,7 +58,7 @@ namespace BuffersLibraries { vkFreeCommandBuffers(Global::device, Global::commandPool, 1, &commandBuffer); } - void buffers::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) { + void Buffers::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) { VkBufferCreateInfo bufferInfo{}; bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferInfo.size = size; @@ -92,7 +84,7 @@ namespace BuffersLibraries { vkBindBufferMemory(Global::device, buffer, bufferMemory, 0); } - void buffers::createIndexBuffer() { + void Buffers::createIndexBuffer() { VkDeviceSize bufferSize = sizeof(Global::indices[0]) * Global::indices.size(); VkBuffer stagingBuffer; @@ -113,7 +105,7 @@ namespace BuffersLibraries { vkDestroyBuffer(Global::device, stagingBuffer, nullptr); vkFreeMemory(Global::device, stagingBufferMemory, nullptr); } - void buffers::createVertexBuffer() { + void Buffers::createVertexBuffer() { // Create a Vertex Buffer to hold the vertex information in memory so it doesn't have to be hardcoded! // Size denotes the size of the buffer in bytes, usage in this case is the buffer behaviour, using a bitwise OR. // Sharing mode denostes the same as the images in the swap chain! in this case, only the graphics queue uses this buffer, so we make it exclusive. @@ -136,22 +128,22 @@ namespace BuffersLibraries { vkFreeMemory(Global::device, stagingBufferMemory, nullptr); } - void buffers::destroyBuffers() { + void Buffers::destroyBuffers() { vkDestroyBuffer(Global::device, indexBuffer, nullptr); vkFreeMemory(Global::device, indexBufferMemory, nullptr); vkDestroyBuffer(Global::device, vertexBuffer, nullptr); vkFreeMemory(Global::device, vertexBufferMemory, nullptr); } - VkBuffer buffers::getVertexBuffer() { + VkBuffer Buffers::getVertexBuffer() { return vertexBuffer; } - VkBuffer buffers::getIndexBuffer() { + VkBuffer Buffers::getIndexBuffer() { return indexBuffer; } // ------------------------------ Uniform Buffer Setup -------------------------------- // - void buffers::createDescriptorSetLayout() { + void Buffers::createDescriptorSetLayout() { // Create a table of pointers to data, a Descriptor Set! // --------------------- UBO Layout --------------------- // VkDescriptorSetLayoutBinding uboLayoutBinding{}; @@ -182,7 +174,7 @@ namespace BuffersLibraries { throw std::runtime_error("Failed to create descriptor set layout!"); } } - void buffers::createUniformBuffers() { + void Buffers::createUniformBuffers() { // Map the uniform buffer to memory as a pointer we can use to write data to later. This stays mapped to memory for the applications lifetime. // This technique is called "persistent mapping", not having to map the buffer every time we need to update it increases performance, though not free VkDeviceSize bufferSize = sizeof(Global::UniformBufferObject); @@ -196,7 +188,7 @@ namespace BuffersLibraries { vkMapMemory(Global::device, uniformBuffersMemory[i], 0, bufferSize, 0, &uniformBuffersMapped[i]); } } - void buffers::updateUniformBuffer(uint32_t currentImage) { + void Buffers::updateUniformBuffer(uint32_t currentImage) { // Update the uniform buffer every frame to change the position, but notably, use chrono to know exactly how much to move // so we aren't locked to the framerate as the world time. @@ -208,25 +200,25 @@ namespace BuffersLibraries { Global::UniformBufferObject ubo{}; ubo.time = time; // Modify the model projection transformation to rotate around the Z over time. - ubo.model = glm::rotate(glm::mat4(1.0f), glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f)); + ubo.model = glm::rotate(glm::mat4(1.0f), glm::radians(30.0f), glm::vec3(0.0f, 0.0f, 1.0f)); // Modify the view transformation to look at the object from above at a 45 degree angle. // This takes the eye position, center position, and the up direction. - ubo.view = glm::lookAt(glm::vec3(4.0f, 4.0f, 3.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); + ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); // 45 degree field of view, set aspect ratio, and near and far clipping range. - ubo.proj = glm::perspective(glm::radians(45.0f), deviceLibrary.getSwapChainExtent().width / (float) deviceLibrary.getSwapChainExtent().height, 0.1f, 10.0f); + ubo.proj = glm::perspective(glm::radians(45.0f), device_libs::DeviceControl::getSwapChainExtent().width / (float) device_libs::DeviceControl::getSwapChainExtent().height, 0.1f, 10.0f); // GLM was created for OpenGL, where the Y coordinate was inverted. This simply flips the sign. ubo.proj[1][1] *= -1; memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); } - void buffers::destroyUniformBuffer() { + void Buffers::destroyUniformBuffer() { for(size_t i = 0; i < Global::MAX_FRAMES_IN_FLIGHT; i++) { vkDestroyBuffer(Global::device, uniformBuffers[i],nullptr); vkFreeMemory(Global::device, uniformBuffersMemory[i], nullptr); } } - void buffers::createDescriptorPool() { + void Buffers::createDescriptorPool() { // Create a pool to be used to allocate descriptor sets. std::array poolSizes{}; poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; @@ -244,7 +236,7 @@ namespace BuffersLibraries { throw std::runtime_error("failed to create descriptor pool!"); } } - void buffers::createDescriptorSets() { + void Buffers::createDescriptorSets() { std::vector layouts(Global::MAX_FRAMES_IN_FLIGHT, Global::descriptorSetLayout); VkDescriptorSetAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; @@ -289,7 +281,7 @@ namespace BuffersLibraries { vkUpdateDescriptorSets(Global::device, static_cast(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr); } } - void buffers::destroyDescriptorPool() { + void Buffers::destroyDescriptorPool() { vkDestroyDescriptorPool(Global::device, descriptorPool, nullptr); } } diff --git a/src/graphics/buffers.h b/src/graphics/buffers.h index 69f7144..c638c12 100644 --- a/src/graphics/buffers.h +++ b/src/graphics/buffers.h @@ -1,22 +1,24 @@ #pragma once -#include "../global.h" +#include +#include +#include "../devicelibrary.h" -namespace BuffersLibraries { - class buffers { +namespace buffers_libs { + class Buffers { public: - void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags props, VkBuffer& buffer, VkDeviceMemory& bufferMemory); - uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags flags); - void createIndexBuffer(); - void createVertexBuffer(); - void destroyBuffers(); - VkBuffer getVertexBuffer(); - VkBuffer getIndexBuffer(); - void createDescriptorSetLayout(); - void createUniformBuffers(); - void updateUniformBuffer(uint32_t currentImage); - void destroyUniformBuffer(); - void createDescriptorPool(); - void createDescriptorSets(); - void destroyDescriptorPool(); + static void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags props, VkBuffer& buffer, VkDeviceMemory& bufferMemory); + static uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags flags); + static void createIndexBuffer(); + static void createVertexBuffer(); + static void destroyBuffers(); + static VkBuffer getVertexBuffer(); + static VkBuffer getIndexBuffer(); + static void createDescriptorSetLayout(); + static void createUniformBuffers(); + static void updateUniformBuffer(uint32_t currentImage); + static void destroyUniformBuffer(); + static void createDescriptorPool(); + static void createDescriptorSets(); + static void destroyDescriptorPool(); }; } diff --git a/src/graphics/graphicspipeline.cpp b/src/graphics/graphicspipeline.cpp index fb4617e..72556b4 100644 --- a/src/graphics/graphicspipeline.cpp +++ b/src/graphics/graphicspipeline.cpp @@ -1,23 +1,15 @@ - #include "graphicspipeline.h" -#include "buffers.h" -#include "texture.h" -#include -#include -#include -namespace Graphics { + +namespace graphics_pipeline { + std::vector dynamicStates = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; - VkRenderPass renderPass; VkPipelineLayout pipelineLayout; VkPipeline graphicsPipeline; - DeviceControl::devicelibrary deviceLibs; - BuffersLibraries::buffers buffers; - TextureLibraries::texture textureLibs; std::vector swapChainFramebuffers; @@ -50,7 +42,7 @@ namespace Graphics { return shaderModule; } - void graphicspipeline::destroyGraphicsPipeline() { + void Graphics::destroyGraphicsPipeline() { vkDestroyPipeline(Global::device, graphicsPipeline, nullptr); if(Global::enableValidationLayers) std::cout << "Destroyed Graphics Pipeline safely\n" << std::endl; vkDestroyPipelineLayout(Global::device, pipelineLayout, nullptr); @@ -58,13 +50,12 @@ namespace Graphics { } - void graphicspipeline::createGraphicsPipeline() { + void Graphics::createGraphicsPipeline() { // Note to self, for some reason the working directory is not where a read file is called from, but the project folder! auto vertShaderCode = readFile("src/shaders/vertex.spv"); auto fragShaderCode = readFile("src/shaders/fragment.spv"); VkShaderModule vertShaderModule = createShaderModule(vertShaderCode, Global::device); VkShaderModule fragShaderModule = createShaderModule(fragShaderCode, Global::device); - // ------------------ STAGE 1 - INPUT ASSEMBLER ---------------- // // This can get a little complicated, normally, vertices are loaded in sequential order, with an element buffer however, you can specify the indices yourself! // Using an element buffer means you can reuse vertices, which can lead to optimizations. If you set PrimRestart to TRUE, you can utilize the _STRIP modes with special indices @@ -191,9 +182,9 @@ namespace Graphics { if(Global::enableValidationLayers) std::cout << "Pipeline Layout created successfully\n" << std::endl; } - void graphicspipeline::createRenderPass() { + void Graphics::createRenderPass() { VkAttachmentDescription colorAttachment{}; - colorAttachment.format = deviceLibs.getImageFormat(); + colorAttachment.format = device_libs::DeviceControl::getImageFormat(); colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; @@ -207,7 +198,7 @@ namespace Graphics { colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; VkAttachmentDescription depthAttachment{}; - depthAttachment.format = textureLibs.findDepthFormat(); + depthAttachment.format = texture_libs::Texture::findDepthFormat(); depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT; depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; @@ -250,18 +241,18 @@ namespace Graphics { } if(Global::enableValidationLayers) std::cout << "Render pass created successfully\n" << std::endl; } - void graphicspipeline::destroyRenderPass() { + void Graphics::destroyRenderPass() { vkDestroyRenderPass(Global::device, renderPass, nullptr); if(Global::enableValidationLayers) std::cout << "Destroyed Render Pass Safely\n" << std::endl; } - void graphicspipeline::createFramebuffers() { + void Graphics::createFramebuffers() { // Resize the container to hold all the framebuffers. - int framebuffersSize = deviceLibs.getSwapChainImageViews().size(); + int framebuffersSize = device_libs::DeviceControl::getSwapChainImageViews().size(); swapChainFramebuffers.resize(framebuffersSize); for(size_t i = 0; i < framebuffersSize; i++) { std::array attachments = { - deviceLibs.getSwapChainImageViews()[i], + device_libs::DeviceControl::getSwapChainImageViews()[i], Global::depthImageView }; @@ -270,8 +261,8 @@ namespace Graphics { framebufferInfo.renderPass = renderPass; framebufferInfo.attachmentCount = static_cast(attachments.size()); framebufferInfo.pAttachments = attachments.data(); - framebufferInfo.width = deviceLibs.getSwapChainExtent().width; - framebufferInfo.height = deviceLibs.getSwapChainExtent().height; + framebufferInfo.width = device_libs::DeviceControl::getSwapChainExtent().width; + framebufferInfo.height = device_libs::DeviceControl::getSwapChainExtent().height; framebufferInfo.layers = 1; if(vkCreateFramebuffer(Global::device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) { @@ -279,7 +270,7 @@ namespace Graphics { } } } - void graphicspipeline::createCommandPool() { + void Graphics::createCommandPool() { // Commands in Vulkan are not executed using function calls, you have to record the ops you wish to perform // to command buffers, pools manage the memory used by the buffer! Global::QueueFamilyIndices queueFamilyIndices = Global::findQueueFamilies(Global::physicalDevice); @@ -294,10 +285,10 @@ namespace Graphics { } if(Global::enableValidationLayers) std::cout << "Command pool created successfully\n" << std::endl; } - void graphicspipeline::destroyCommandPool() { + void Graphics::destroyCommandPool() { vkDestroyCommandPool(Global::device, Global::commandPool, nullptr); } - void graphicspipeline::createCommandBuffer() { + void Graphics::createCommandBuffer() { Global::commandBuffers.resize(Global::MAX_FRAMES_IN_FLIGHT); VkCommandBufferAllocateInfo allocInfo{}; @@ -312,7 +303,7 @@ namespace Graphics { if(Global::enableValidationLayers) std::cout << "Allocated command buffers successfully\n" << std::endl; } - void graphicspipeline::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) { + void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) { VkCommandBufferBeginInfo beginInfo{}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -325,7 +316,7 @@ namespace Graphics { renderPassInfo.renderPass = renderPass; renderPassInfo.framebuffer = swapChainFramebuffers[imageIndex]; renderPassInfo.renderArea.offset = {0, 0}; - renderPassInfo.renderArea.extent = deviceLibs.getSwapChainExtent(); + renderPassInfo.renderArea.extent = device_libs::DeviceControl::getSwapChainExtent(); std::array clearValues{}; clearValues[0].color = {{0.0f, 0.0f, 0.0f, 1.0f}}; @@ -340,21 +331,21 @@ namespace Graphics { VkViewport viewport{}; viewport.x = 0.0f; viewport.y = 0.0f; - viewport.width = (float) deviceLibs.getSwapChainExtent().width; - viewport.height = (float) deviceLibs.getSwapChainExtent().height; + viewport.width = (float) device_libs::DeviceControl::getSwapChainExtent().width; + viewport.height = (float) device_libs::DeviceControl::getSwapChainExtent().height; viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; vkCmdSetViewport(commandBuffer, 0, 1, &viewport); VkRect2D scissor{}; scissor.offset = {0, 0}; - scissor.extent = deviceLibs.getSwapChainExtent(); + scissor.extent = device_libs::DeviceControl::getSwapChainExtent(); vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - VkBuffer vertexBuffers[] = {buffers.getVertexBuffer()}; + VkBuffer vertexBuffers[] = {buffers_libs::Buffers::getVertexBuffer()}; VkDeviceSize offsets[] = {0}; vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); - vkCmdBindIndexBuffer(commandBuffer, buffers.getIndexBuffer(), 0, VK_INDEX_TYPE_UINT32); + vkCmdBindIndexBuffer(commandBuffer, buffers_libs::Buffers::getIndexBuffer(), 0, VK_INDEX_TYPE_UINT32); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &Global::descriptorSets[Global::currentFrame], 0, nullptr); @@ -365,7 +356,7 @@ namespace Graphics { throw std::runtime_error("failed to record command buffer!"); } } - std::vector graphicspipeline::getSwapChainFramebuffers() { + std::vector Graphics::getSwapChainFramebuffers() { return swapChainFramebuffers; } } diff --git a/src/graphics/graphicspipeline.h b/src/graphics/graphicspipeline.h index b5d74a3..5f263e8 100644 --- a/src/graphics/graphicspipeline.h +++ b/src/graphics/graphicspipeline.h @@ -2,20 +2,22 @@ #include "../global.h" #include "../devicelibrary.h" #include "buffers.h" +#include "texture.h" #include -namespace Graphics { - class graphicspipeline { + +namespace graphics_pipeline { + class Graphics { public: - void createGraphicsPipeline(); - void destroyGraphicsPipeline(); - void createRenderPass(); - void destroyRenderPass(); - void createFramebuffers(); - void destroyFramebuffers(); - void createCommandPool(); - void destroyCommandPool(); - void createCommandBuffer(); - void recordCommandBuffer(VkCommandBuffer cmndBuffer, uint32_t imageIndex); - std::vector getSwapChainFramebuffers(); + static void createGraphicsPipeline(); + static void destroyGraphicsPipeline(); + static void createRenderPass(); + static void destroyRenderPass(); + static void createFramebuffers(); + static void destroyFramebuffers(); + static void createCommandPool(); + static void destroyCommandPool(); + static void createCommandBuffer(); + static void recordCommandBuffer(VkCommandBuffer cmndBuffer, uint32_t imageIndex); + static std::vector getSwapChainFramebuffers(); }; } diff --git a/src/graphics/model.cpp b/src/graphics/model.cpp index 2c6136c..c35b1a2 100644 --- a/src/graphics/model.cpp +++ b/src/graphics/model.cpp @@ -1,9 +1,4 @@ -#define TINY_OBJ_IMPLEMENTATION -#include #include "model.h" -#include -#define GLM_ENABLE_EXPERIMENTAL -#include namespace std { template<> struct hash { @@ -15,11 +10,11 @@ namespace std { }; } -namespace ModelLib { +namespace modellib { std::unordered_map uniqueVertices{}; - void model::loadModel() { + void Model::loadModel() { tinyobj::ObjReaderConfig readerConfig; tinyobj::ObjReader reader; diff --git a/src/graphics/model.h b/src/graphics/model.h index 23e6014..7714442 100644 --- a/src/graphics/model.h +++ b/src/graphics/model.h @@ -1,8 +1,14 @@ #include "../global.h" -namespace ModelLib { - class model { +#define TINY_OBJ_IMPLEMENTATION +#include + +#define GLM_ENABLE_EXPERIMENTAL +#include + +namespace modellib { + class Model { public: - void loadModel(); + static void loadModel(); }; } diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index 36f77d2..d3e05fe 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -3,16 +3,11 @@ #include "../devicelibrary.h" #include "../entrypoint.h" #include "texture.h" -#include -namespace RenderPresent { +namespace render_present { std::vector imageAvailableSemaphores; std::vector renderFinishedSemaphores; std::vector inFlightFences; - Graphics::graphicspipeline pipeline; - DeviceControl::devicelibrary deviceLibs; - BuffersLibraries::buffers buffers; - TextureLibraries::texture tex; void recreateSwapChain() { int width = 0, height = 0; @@ -23,24 +18,24 @@ namespace RenderPresent { } vkDeviceWaitIdle(Global::device); // Don't really wanna do this but I also don't want to create an extra class instance just to call the cleanup function. - for(auto framebuffer : pipeline.getSwapChainFramebuffers()) { + for(auto framebuffer : graphics_pipeline::Graphics::getSwapChainFramebuffers()) { vkDestroyFramebuffer(Global::device, framebuffer, nullptr); } - for(auto imageView : deviceLibs.getSwapChainImageViews()) { + for(auto imageView : device_libs::DeviceControl::getSwapChainImageViews()) { vkDestroyImageView(Global::device, imageView, nullptr); } vkDestroySwapchainKHR(Global::device, Global::swapChain, nullptr); - deviceLibs.createSwapChain(Global::window); - deviceLibs.createImageViews(); - tex.createDepthResources(); - pipeline.createFramebuffers(); + device_libs::DeviceControl::createSwapChain(Global::window); + device_libs::DeviceControl::createImageViews(); + texture_libs::Texture::createDepthResources(); + graphics_pipeline::Graphics::createFramebuffers(); } // At a high level, rendering in Vulkan consists of 5 steps: // Wait for the previous frame, acquire a image from the swap chain // record a comman d buffer which draws the scene onto that image // submit the recorded command buffer and present the image! - void render::drawFrame() { + void Render::drawFrame() { vkWaitForFences(Global::device, 1, &inFlightFences[Global::currentFrame], VK_TRUE, UINT64_MAX); vkResetFences(Global::device, 1, &inFlightFences[Global::currentFrame]); @@ -54,12 +49,12 @@ namespace RenderPresent { throw std::runtime_error("failed to acquire swap chain image!"); } - buffers.updateUniformBuffer(Global::currentFrame); + buffers_libs::Buffers::updateUniformBuffer(Global::currentFrame); vkResetFences(Global::device, 1, &inFlightFences[Global::currentFrame]); vkResetCommandBuffer(Global::commandBuffers[Global::currentFrame], /*VkCommandBufferResetFlagBits*/ 0); - pipeline.recordCommandBuffer(Global::commandBuffers[Global::currentFrame], imageIndex); + graphics_pipeline::Graphics::recordCommandBuffer(Global::commandBuffers[Global::currentFrame], imageIndex); VkSubmitInfo submitInfo{}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; @@ -127,7 +122,7 @@ namespace RenderPresent { // doStuffOnceFenceDone() #pragma endinfo - void render::createSyncObject() { + void Render::createSyncObject() { imageAvailableSemaphores.resize(Global::MAX_FRAMES_IN_FLIGHT); renderFinishedSemaphores.resize(Global::MAX_FRAMES_IN_FLIGHT); inFlightFences.resize(Global::MAX_FRAMES_IN_FLIGHT); @@ -149,21 +144,21 @@ namespace RenderPresent { } - void render::destroyFenceSemaphores() { + void Render::destroyFenceSemaphores() { for (size_t i = 0; i < Global::MAX_FRAMES_IN_FLIGHT; i++) { vkDestroySemaphore(Global::device, renderFinishedSemaphores[i], nullptr); vkDestroySemaphore(Global::device, imageAvailableSemaphores[i], nullptr); vkDestroyFence(Global::device, inFlightFences[i], nullptr); } } - void render::cleanupSwapChain() { + void Render::cleanupSwapChain() { vkDestroyImageView(Global::device, Global::depthImageView, nullptr); vkDestroyImage(Global::device, Global::depthImage, nullptr); vkFreeMemory(Global::device, Global::depthImageMemory, nullptr); - for(auto framebuffer : pipeline.getSwapChainFramebuffers()) { + for(auto framebuffer : graphics_pipeline::Graphics::getSwapChainFramebuffers()) { vkDestroyFramebuffer(Global::device, framebuffer, nullptr); } - for(auto imageView : deviceLibs.getSwapChainImageViews()) { + for(auto imageView : device_libs::DeviceControl::getSwapChainImageViews()) { vkDestroyImageView(Global::device, imageView, nullptr); } vkDestroySwapchainKHR(Global::device, Global::swapChain, nullptr); diff --git a/src/graphics/render.h b/src/graphics/render.h index fa5adfc..ffd7112 100644 --- a/src/graphics/render.h +++ b/src/graphics/render.h @@ -2,12 +2,12 @@ #include "../global.h" -namespace RenderPresent { -class render { +namespace render_present { +class Render { public: - void drawFrame(); - void createSyncObject(); - void destroyFenceSemaphores(); - void cleanupSwapChain(); + static void drawFrame(); + static void createSyncObject(); + static void destroyFenceSemaphores(); + static void cleanupSwapChain(); }; } diff --git a/src/graphics/texture.cpp b/src/graphics/texture.cpp index 86f757e..92c5d50 100644 --- a/src/graphics/texture.cpp +++ b/src/graphics/texture.cpp @@ -1,20 +1,14 @@ -#include #define STB_IMAGE_IMPLEMENTATION #include #include "texture.h" -#include "buffers.h" -#include "../devicelibrary.h" -BuffersLibraries::buffers buffer; -DeviceControl::devicelibrary deviceLibraries; + VkImage textureImage; VkDeviceMemory textureImageMemory; VkPipelineStageFlags sourceStage; VkPipelineStageFlags destinationStage; - - -namespace TextureLibraries { +namespace texture_libs { void createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory) { // This function specifies all the data in an image object, this is called directly after the creation of an image object. VkImageCreateInfo imageInfo{}; @@ -42,7 +36,7 @@ namespace TextureLibraries { VkMemoryAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocInfo.allocationSize = memRequirements.size; - allocInfo.memoryTypeIndex = buffer.findMemoryType(memRequirements.memoryTypeBits, properties); + allocInfo.memoryTypeIndex = buffers_libs::Buffers::findMemoryType(memRequirements.memoryTypeBits, properties); if (vkAllocateMemory(Global::device, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS) { throw std::runtime_error("failed to allocate image memory!"); @@ -186,7 +180,7 @@ void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT; } // -------------------------------- Image Libraries ------------------------------- // - void texture::createTextureImage() { + void Texture::createTextureImage() { // Import pixels from image with data on color channels, width and height, and colorspace! // Its a lot of kind of complicated memory calls to bring it from a file -> to a buffer -> to a image object. int textureWidth, textureHeight, textureChannels; @@ -199,7 +193,7 @@ void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t } VkBuffer stagingBuffer; VkDeviceMemory stagingBufferMemory; - buffer.createBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory); + buffers_libs::Buffers::createBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory); void* data; vkMapMemory(Global::device, stagingBufferMemory, 0, imageSize, 0, &data); @@ -217,11 +211,11 @@ void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t vkDestroyBuffer(Global::device, stagingBuffer, nullptr); vkFreeMemory(Global::device, stagingBufferMemory, nullptr); } - void texture::createTextureImageView() { + void Texture::createTextureImageView() { // Create a texture image view, which is a struct of information about the image. - Global::textureImageView = deviceLibraries.createImageView(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT); + Global::textureImageView = device_libs::DeviceControl::createImageView(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT); } - void texture::createTextureSampler() { + void Texture::createTextureSampler() { // Create a sampler to access and parse the texture object. VkSamplerCreateInfo samplerInfo{}; samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; @@ -263,26 +257,26 @@ void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t throw std::runtime_error("failed to create texture sampler!"); } } - void texture::destroyTextureSampler() { + void Texture::destroyTextureSampler() { vkDestroySampler(Global::device, Global::textureSampler, nullptr); vkDestroyImageView(Global::device, Global::textureImageView, nullptr); } - void texture::destroyTextureImage() { + void Texture::destroyTextureImage() { vkDestroyImage(Global::device, textureImage, nullptr); vkFreeMemory(Global::device, textureImageMemory, nullptr); } - VkFormat texture::findDepthFormat() { + VkFormat Texture::findDepthFormat() { return findSupportedFormat( {VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT}, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT ); } - void texture::createDepthResources() { + void Texture::createDepthResources() { VkFormat depthFormat = findDepthFormat(); - VkExtent2D swapChainExtent = deviceLibraries.getSwapChainExtent(); + VkExtent2D swapChainExtent = device_libs::DeviceControl::getSwapChainExtent(); createImage(swapChainExtent.width, swapChainExtent.height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, Global::depthImage, Global::depthImageMemory); - Global::depthImageView = deviceLibraries.createImageView(Global::depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT); + Global::depthImageView = device_libs::DeviceControl::createImageView(Global::depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT); // Explicit transition from the layout of the image to the depth attachment is unnecessary here, since that will be handled in the render pass! diff --git a/src/graphics/texture.h b/src/graphics/texture.h index b928b03..944f8ed 100644 --- a/src/graphics/texture.h +++ b/src/graphics/texture.h @@ -1,16 +1,17 @@ #pragma once #include "../global.h" -#include +#include "buffers.h" +#include "../devicelibrary.h" -namespace TextureLibraries { - class texture { +namespace texture_libs { + class Texture { public: - void createTextureImage(); - void createTextureImageView(); - void createTextureSampler(); - void destroyTextureImage(); - void destroyTextureSampler(); - VkFormat findDepthFormat(); - void createDepthResources(); + static void createTextureImage(); + static void createTextureImageView(); + static void createTextureSampler(); + static void destroyTextureImage(); + static void destroyTextureSampler(); + static VkFormat findDepthFormat(); + static void createDepthResources(); }; }