diff --git a/.cache/clangd/index/devicelibrary.cpp.A6A50BF3BD186A09.idx b/.cache/clangd/index/devicelibrary.cpp.A6A50BF3BD186A09.idx index 00755c3..26769df 100644 Binary files a/.cache/clangd/index/devicelibrary.cpp.A6A50BF3BD186A09.idx and b/.cache/clangd/index/devicelibrary.cpp.A6A50BF3BD186A09.idx differ diff --git a/.cache/clangd/index/devicelibrary.h.D7B097F0839961AC.idx b/.cache/clangd/index/devicelibrary.h.D7B097F0839961AC.idx index 6df7dac..a4f05b4 100644 Binary files a/.cache/clangd/index/devicelibrary.h.D7B097F0839961AC.idx and b/.cache/clangd/index/devicelibrary.h.D7B097F0839961AC.idx differ diff --git a/imgui.ini b/imgui.ini index 22bd0f8..7e47892 100644 --- a/imgui.ini +++ b/imgui.ini @@ -3,6 +3,6 @@ Pos=60,60 Size=400,400 [Window][Agnosia Debug] -Pos=124,277 +Pos=194,438 Size=583,225 diff --git a/src/agnosiaimgui.cpp b/src/agnosiaimgui.cpp index 8194690..4404aa5 100644 --- a/src/agnosiaimgui.cpp +++ b/src/agnosiaimgui.cpp @@ -1,26 +1,30 @@ #include "agnosiaimgui.h" +#include "devicelibrary.h" +#include "entrypoint.h" #include "graphics/buffers.h" - -namespace agnosia_imgui { +#include "graphics/texture.h" +#include "imgui.h" +#include "imgui_impl_glfw.h" +#include "imgui_impl_vulkan.h" +#include VkDescriptorPool imGuiDescriptorPool; -void initWindow() { +void initImGuiWindow() { - ImGui::DragFloat3("Object Position", buffers_libs::Buffers::getObjPos()); - ImGui::DragFloat3("Camera Position", buffers_libs::Buffers::getCamPos()); - ImGui::DragFloat3("Center Position", buffers_libs::Buffers::getCenterPos()); - ImGui::DragFloat3("Up Direction", buffers_libs::Buffers::getUpDir()); - ImGui::DragFloat("Depth of Field", buffers_libs::Buffers::getDepthField(), - 0.1f, 1.0f, 180.0f, NULL, ImGuiSliderFlags_AlwaysClamp); - ImGui::DragFloat2("Near and Far fields", - buffers_libs::Buffers::getDistanceField()); + ImGui::DragFloat3("Object Position", Buffers::getObjPos()); + ImGui::DragFloat3("Camera Position", Buffers::getCamPos()); + ImGui::DragFloat3("Center Position", Buffers::getCenterPos()); + ImGui::DragFloat3("Up Direction", Buffers::getUpDir()); + ImGui::DragFloat("Depth of Field", &Buffers::getDepthField(), 0.1f, 1.0f, + 180.0f, NULL, ImGuiSliderFlags_AlwaysClamp); + ImGui::DragFloat2("Near and Far fields", Buffers::getDistanceField()); } void drawTabs() { if (ImGui::BeginTabBar("MainTabBar", ImGuiTabBarFlags_Reorderable)) { if (ImGui::BeginTabItem("Transforms Control")) { - initWindow(); + initImGuiWindow(); ImGui::EndTabItem(); } @@ -50,7 +54,7 @@ void Gui::drawImGui() { void Gui::initImgui(VkInstance instance) { auto load_vk_func = [&](const char *fn) { - if (auto proc = vkGetDeviceProcAddr(Global::device, fn)) + if (auto proc = vkGetDeviceProcAddr(DeviceControl::getDevice(), fn)) return proc; return vkGetInstanceProcAddr(instance, fn); }; @@ -69,7 +73,7 @@ void Gui::initImgui(VkInstance instance) { ImGui::StyleColorsDark(); - ImGui_ImplGlfw_InitForVulkan(Global::window, true); + ImGui_ImplGlfw_InitForVulkan(EntryApp::getWindow(), true); VkDescriptorPoolSize ImGuiPoolSizes[]{ {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1}, @@ -81,33 +85,33 @@ void Gui::initImgui(VkInstance instance) { .poolSizeCount = 1, .pPoolSizes = ImGuiPoolSizes, }; - if (vkCreateDescriptorPool(Global::device, &ImGuiPoolInfo, nullptr, - &imGuiDescriptorPool) != VK_SUCCESS) { + if (vkCreateDescriptorPool(DeviceControl::getDevice(), &ImGuiPoolInfo, + nullptr, &imGuiDescriptorPool) != VK_SUCCESS) { throw std::runtime_error("Failed to create ImGui descriptor pool!"); } VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo{ .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, .colorAttachmentCount = 1, - .pColorAttachmentFormats = device_libs::DeviceControl::getImageFormat(), - .depthAttachmentFormat = texture_libs::Texture::findDepthFormat(), + .pColorAttachmentFormats = &DeviceControl::getImageFormat(), + .depthAttachmentFormat = Texture::findDepthFormat(), }; ImGui_ImplVulkan_InitInfo initInfo{ .Instance = instance, - .PhysicalDevice = Global::physicalDevice, - .Device = Global::device, - .QueueFamily = Global::findQueueFamilies(Global::physicalDevice) - .graphicsFamily.value(), - .Queue = Global::graphicsQueue, + .PhysicalDevice = DeviceControl::getPhysicalDevice(), + .Device = DeviceControl::getDevice(), + .QueueFamily = + DeviceControl::findQueueFamilies(DeviceControl::getPhysicalDevice()) + .graphicsFamily.value(), + .Queue = DeviceControl::getGraphicsQueue(), .DescriptorPool = imGuiDescriptorPool, - .MinImageCount = Global::MAX_FRAMES_IN_FLIGHT, - .ImageCount = Global::MAX_FRAMES_IN_FLIGHT, - .MSAASamples = Global::perPixelSampleCount, + .MinImageCount = Buffers::getMaxFramesInFlight(), + .ImageCount = Buffers::getMaxFramesInFlight(), + .MSAASamples = DeviceControl::getPerPixelSampleCount(), .UseDynamicRendering = true, .PipelineRenderingCreateInfo = pipelineRenderingCreateInfo, }; ImGui_ImplVulkan_Init(&initInfo); } -} // namespace agnosia_imgui diff --git a/src/agnosiaimgui.h b/src/agnosiaimgui.h index 2ad392d..8750031 100644 --- a/src/agnosiaimgui.h +++ b/src/agnosiaimgui.h @@ -1,15 +1,8 @@ #pragma once -#include "global.h" -#include "graphics/texture.h" -#include "imgui.h" -#include "imgui_impl_glfw.h" -#include "imgui_impl_vulkan.h" -#include +#include "volk.h" -namespace agnosia_imgui { class Gui { public: static void drawImGui(); static void initImgui(VkInstance instance); }; -} // namespace agnosia_imgui diff --git a/src/devicelibrary.cpp b/src/devicelibrary.cpp index d10a422..8fbeb86 100644 --- a/src/devicelibrary.cpp +++ b/src/devicelibrary.cpp @@ -1,11 +1,22 @@ #include "devicelibrary.h" -#include "global.h" - -namespace device_libs { +#include +#include +#include +#include +#include +#include VkPhysicalDeviceProperties deviceProperties; +VkDevice device; +VkSurfaceKHR surface; +VkQueue graphicsQueue; +VkQueue presentQueue; +VkPhysicalDevice physicalDevice; +VkSampleCountFlagBits perPixelSampleCount; +VkSwapchainKHR swapChain; std::vector swapChainImages; +std::vector swapChainImageViews; VkFormat swapChainImageFormat; VkExtent2D swapChainExtent; @@ -18,6 +29,47 @@ const std::vector deviceExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME, }; + +DeviceControl::QueueFamilyIndices +DeviceControl::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::QueueFamilyIndices indices; + uint32_t queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr); + + std::vector queueFamilies(queueFamilyCount); + vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, + queueFamilies.data()); + + int i = 0; + for (const auto &queueFamily : queueFamilies) { + if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { + indices.graphicsFamily = i; + } + + VkBool32 presentSupport = false; + vkGetPhysicalDeviceSurfaceSupportKHR(device, i, DeviceControl::getSurface(), + &presentSupport); + if (presentSupport) { + indices.presentFamily = i; + } + + if (indices.isComplete()) { + break; + } + i++; + } + return indices; +} SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device) { /* Swap chains are weird ngl, it's another one of those Vulkan platform @@ -28,28 +80,26 @@ SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device) { no fucking clue how it works though) */ SwapChainSupportDetails details; - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, Global::surface, + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities); uint32_t formatCount; - vkGetPhysicalDeviceSurfaceFormatsKHR(device, Global::surface, &formatCount, - nullptr); + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr); if (formatCount != 0) { details.formats.resize(formatCount); - vkGetPhysicalDeviceSurfaceFormatsKHR(device, Global::surface, &formatCount, + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data()); } uint32_t presentModeCount; - vkGetPhysicalDeviceSurfacePresentModesKHR( - device, Global::surface, &presentModeCount, details.presentModes.data()); + vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, + details.presentModes.data()); if (presentModeCount != 0) { details.presentModes.resize(presentModeCount); - vkGetPhysicalDeviceSurfacePresentModesKHR(device, Global::surface, - &presentModeCount, - details.presentModes.data()); + vkGetPhysicalDeviceSurfacePresentModesKHR( + device, surface, &presentModeCount, details.presentModes.data()); } return details; @@ -88,7 +138,8 @@ bool isDeviceSuitable(VkPhysicalDevice device) { // We need to find a device that supports graphical operations, or else we // cant do much with it! This function just runs over all the queueFamilies // and sees if there is a queue family with the VK_QUEUE_GRAPHICS_BIT flipped! - Global::QueueFamilyIndices indices = Global::findQueueFamilies(device); + DeviceControl::QueueFamilyIndices indices = + DeviceControl::findQueueFamilies(device); bool extensionSupported = checkDeviceExtensionSupport(device); bool swapChainAdequate = false; @@ -167,7 +218,7 @@ VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities, VkSampleCountFlagBits getMaxUsableSampleCount() { VkPhysicalDeviceProperties physicalDeviceProps; VkSampleCountFlags maxCounts; - vkGetPhysicalDeviceProperties(Global::physicalDevice, &physicalDeviceProps); + vkGetPhysicalDeviceProperties(physicalDevice, &physicalDeviceProps); VkSampleCountFlags counts = physicalDeviceProps.limits.framebufferColorSampleCounts & @@ -210,20 +261,20 @@ void DeviceControl::pickPhysicalDevice(VkInstance &instance) { if (isDeviceSuitable(device)) { // Once we have buttons or such, maybe ask the user or write a config file // for which GPU to use? - Global::physicalDevice = device; - Global::perPixelSampleCount = getMaxUsableSampleCount(); + physicalDevice = device; + perPixelSampleCount = getMaxUsableSampleCount(); break; } } - if (Global::physicalDevice == VK_NULL_HANDLE) { + if (physicalDevice == VK_NULL_HANDLE) { throw std::runtime_error("Failed to find a suitable GPU!"); } } void DeviceControl::destroySurface(VkInstance &instance) { - vkDestroySurfaceKHR(instance, Global::surface, nullptr); + vkDestroySurfaceKHR(instance, surface, nullptr); } void DeviceControl::createSurface(VkInstance &instance, GLFWwindow *window) { - if (glfwCreateWindowSurface(instance, window, nullptr, &Global::surface) != + if (glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS) { throw std::runtime_error("Failed to create window surface!!"); } @@ -234,8 +285,7 @@ void DeviceControl::createLogicalDevice() { // 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! - Global::QueueFamilyIndices indices = - Global::findQueueFamilies(Global::physicalDevice); + QueueFamilyIndices indices = findQueueFamilies(physicalDevice); std::vector queueCreateInfos; std::set uniqueQueueFamilies = {indices.graphicsFamily.value(), @@ -278,18 +328,16 @@ void DeviceControl::createLogicalDevice() { static_cast(deviceExtensions.size()); createDeviceInfo.ppEnabledExtensionNames = deviceExtensions.data(); - if (vkCreateDevice(Global::physicalDevice, &createDeviceInfo, nullptr, - &Global::device) != VK_SUCCESS) { + if (vkCreateDevice(physicalDevice, &createDeviceInfo, nullptr, &device) != + VK_SUCCESS) { throw std::runtime_error("Failed to create logical device"); } - vkGetDeviceQueue(Global::device, indices.graphicsFamily.value(), 0, - &Global::graphicsQueue); - vkGetDeviceQueue(Global::device, indices.presentFamily.value(), 0, - &Global::presentQueue); + vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue); + vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue); } void DeviceControl::createSwapChain(GLFWwindow *window) { SwapChainSupportDetails swapChainSupport = - querySwapChainSupport(Global::physicalDevice); + querySwapChainSupport(physicalDevice); VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats); @@ -311,7 +359,7 @@ void DeviceControl::createSwapChain(GLFWwindow *window) { VkSwapchainCreateInfoKHR createSwapChainInfo{}; createSwapChainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - createSwapChainInfo.surface = Global::surface; + createSwapChainInfo.surface = surface; createSwapChainInfo.minImageCount = imageCount; createSwapChainInfo.imageFormat = surfaceFormat.format; createSwapChainInfo.imageColorSpace = surfaceFormat.colorSpace; @@ -327,8 +375,7 @@ void DeviceControl::createSwapChain(GLFWwindow *window) { // This handles swap chain images across multiple queue families, ie, if the // graphics queue family is different from the present queue - Global::QueueFamilyIndices indices = - Global::findQueueFamilies(Global::physicalDevice); + QueueFamilyIndices indices = findQueueFamilies(physicalDevice); uint32_t queueFamilyIndices[] = {indices.graphicsFamily.value(), indices.presentFamily.value()}; // Usage across multiple queue families without explicit transfer of ownership @@ -357,22 +404,21 @@ void DeviceControl::createSwapChain(GLFWwindow *window) { // it and reference the old one specified here, will revisit in a few days. // createSwapChainInfo.oldSwapchain = VK_NULL_HANDLE; - if (vkCreateSwapchainKHR(Global::device, &createSwapChainInfo, nullptr, - &Global::swapChain) != VK_SUCCESS) { + if (vkCreateSwapchainKHR(device, &createSwapChainInfo, nullptr, &swapChain) != + VK_SUCCESS) { throw std::runtime_error("Failed to create the swap chain!!"); } - vkGetSwapchainImagesKHR(Global::device, Global::swapChain, &imageCount, - nullptr); + vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr); swapChainImages.resize(imageCount); - vkGetSwapchainImagesKHR(Global::device, Global::swapChain, &imageCount, + vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImages.data()); swapChainImageFormat = surfaceFormat.format; swapChainExtent = extent; } void DeviceControl::destroySwapChain() { - vkDestroySwapchainKHR(Global::device, Global::swapChain, nullptr); + vkDestroySwapchainKHR(device, swapChain, nullptr); } VkImageView DeviceControl::createImageView(VkImage image, VkFormat format, VkImageAspectFlags flags, @@ -391,33 +437,43 @@ VkImageView DeviceControl::createImageView(VkImage image, VkFormat format, viewInfo.subresourceRange.levelCount = mipLevels; VkImageView imageView; - if (vkCreateImageView(Global::device, &viewInfo, nullptr, &imageView) != - VK_SUCCESS) { + if (vkCreateImageView(device, &viewInfo, nullptr, &imageView) != VK_SUCCESS) { throw std::runtime_error("failed to create image view!"); } return imageView; } void DeviceControl::createImageViews() { - Global::swapChainImageViews.resize(swapChainImages.size()); + swapChainImageViews.resize(swapChainImages.size()); for (uint32_t i = 0; i < swapChainImages.size(); i++) { - Global::swapChainImageViews[i] = createImageView( + swapChainImageViews[i] = createImageView( swapChainImages[i], swapChainImageFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1); } } void DeviceControl::destroyImageViews() { - for (auto imageView : Global::swapChainImageViews) { - vkDestroyImageView(Global::device, imageView, nullptr); + for (auto imageView : swapChainImageViews) { + vkDestroyImageView(device, imageView, nullptr); } } // --------------------------------------- Getters & Setters // ------------------------------------------ // -VkFormat *DeviceControl::getImageFormat() { return &swapChainImageFormat; } -VkExtent2D DeviceControl::getSwapChainExtent() { return swapChainExtent; } -std::vector DeviceControl::getSwapChainImages() { +VkFormat &DeviceControl::getImageFormat() { return swapChainImageFormat; } +VkSwapchainKHR &DeviceControl::getSwapChain() { return swapChain; } +VkExtent2D &DeviceControl::getSwapChainExtent() { return swapChainExtent; } +std::vector &DeviceControl::getSwapChainImages() { return swapChainImages; } -} // namespace device_libs +std::vector &DeviceControl::getSwapChainImageViews() { + return swapChainImageViews; +} +VkDevice &DeviceControl::getDevice() { return device; } +VkPhysicalDevice &DeviceControl::getPhysicalDevice() { return physicalDevice; } +VkSampleCountFlagBits &DeviceControl::getPerPixelSampleCount() { + return perPixelSampleCount; +} +VkQueue &DeviceControl::getGraphicsQueue() { return graphicsQueue; } +VkQueue &DeviceControl::getPresentQueue() { return presentQueue; } +VkSurfaceKHR &DeviceControl::getSurface() { return surface; } diff --git a/src/devicelibrary.h b/src/devicelibrary.h index a32e6d2..e1aee7d 100644 --- a/src/devicelibrary.h +++ b/src/devicelibrary.h @@ -1,31 +1,50 @@ #pragma once -#include "global.h" -#include -#include -#include -#include +#define VK_NO_PROTOTYPES +#include "volk.h" +#include +#define GLFW_INCLUDE_VULKAN +#include +#include -namespace device_libs { class DeviceControl { - public: - 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, uint32_t mipLevels); - static void createImageViews(); - static void destroyImageViews(); - static void createCommandPool(); - static void destroyCommandPool(); +public: + struct QueueFamilyIndices { + // We need to check that the Queue families support graphics operations and + // window presentation, sometimes they can support one or the other, + // therefore, we take into account both for completion. + std::optional graphicsFamily; + std::optional presentFamily; - // ---------- Getters & Setters ----------- // - static VkFormat* getImageFormat(); - static VkExtent2D getSwapChainExtent(); - static std::vector getSwapChainImages(); - static std::vector getSwapChainFramebuffers(); + bool isComplete() { + return graphicsFamily.has_value() && presentFamily.has_value(); + } }; -} - + 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, + uint32_t mipLevels); + static void createImageViews(); + static void destroyImageViews(); + static void createCommandPool(); + static void destroyCommandPool(); + static QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device); + // ---------- Getters & Setters ----------- // + static VkFormat &getImageFormat(); + static VkExtent2D &getSwapChainExtent(); + static std::vector &getSwapChainImages(); + static std::vector &getSwapChainFramebuffers(); + static VkDevice &getDevice(); + static VkSurfaceKHR &getSurface(); + static VkQueue &getGraphicsQueue(); + static VkQueue &getPresentQueue(); + static VkPhysicalDevice &getPhysicalDevice(); + static VkSampleCountFlagBits &getPerPixelSampleCount(); + static std::vector &getSwapChainImageViews(); + static VkSwapchainKHR &getSwapChain(); +}; diff --git a/src/entrypoint.cpp b/src/entrypoint.cpp index e4c53d2..e511a18 100644 --- a/src/entrypoint.cpp +++ b/src/entrypoint.cpp @@ -1,13 +1,26 @@ #include "agnosiaimgui.h" +#include "devicelibrary.h" #include "entrypoint.h" -#include "global.h" +#include "graphics/buffers.h" +#include "graphics/graphicspipeline.h" +#include "graphics/model.h" +#include "graphics/render.h" #include "graphics/texture.h" + +#define VK_NO_PROTOTYPES +#include "volk.h" +#define GLFW_INCLUDE_VULKAN +#include + #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_vulkan.h" +#include VkInstance vulkaninstance; - +GLFWwindow *window; +const uint32_t WIDTH = 800; +const uint32_t HEIGHT = 600; // Getters and Setters! void EntryApp::setFramebufferResized(bool setter) { framebufferResized = setter; @@ -25,10 +38,9 @@ void initWindow() { glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); // Settings for the window are set, create window reference. - Global::window = glfwCreateWindow(Global::WIDTH, Global::HEIGHT, - "Trimgles :o", nullptr, nullptr); - glfwSetWindowUserPointer(Global::window, &EntryApp::getInstance()); - glfwSetFramebufferSizeCallback(Global::window, framebufferResizeCallback); + window = glfwCreateWindow(WIDTH, HEIGHT, "Trimgles :o", nullptr, nullptr); + glfwSetWindowUserPointer(window, &EntryApp::getInstance()); + glfwSetFramebufferSizeCallback(window, framebufferResizeCallback); } void createInstance() { @@ -84,62 +96,62 @@ void initVulkan() { // Initialize vulkan and set up pipeline. createInstance(); volkLoadInstance(vulkaninstance); - device_libs::DeviceControl::createSurface(vulkaninstance, Global::window); - device_libs::DeviceControl::pickPhysicalDevice(vulkaninstance); - device_libs::DeviceControl::createLogicalDevice(); - volkLoadDevice(Global::device); - device_libs::DeviceControl::createSwapChain(Global::window); - device_libs::DeviceControl::createImageViews(); - buffers_libs::Buffers::createDescriptorSetLayout(); - graphics_pipeline::Graphics::createGraphicsPipeline(); - graphics_pipeline::Graphics::createCommandPool(); - texture_libs::Texture::createColorResources(); - texture_libs::Texture::createDepthResources(); - 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(); - agnosia_imgui::Gui::initImgui(vulkaninstance); + DeviceControl::createSurface(vulkaninstance, window); + DeviceControl::pickPhysicalDevice(vulkaninstance); + DeviceControl::createLogicalDevice(); + volkLoadDevice(DeviceControl::getDevice()); + DeviceControl::createSwapChain(window); + DeviceControl::createImageViews(); + Buffers::createDescriptorSetLayout(); + Graphics::createGraphicsPipeline(); + Graphics::createCommandPool(); + Texture::createColorResources(); + Texture::createDepthResources(); + Texture::createTextureImage(); + Texture::createTextureImageView(); + Texture::createTextureSampler(); + Model::loadModel(); + Buffers::createVertexBuffer(); + Buffers::createIndexBuffer(); + Buffers::createUniformBuffers(); + Buffers::createDescriptorPool(); + Buffers::createDescriptorSets(); + Graphics::createCommandBuffer(); + Render::createSyncObject(); + Gui::initImgui(vulkaninstance); } void mainLoop() { - while (!glfwWindowShouldClose(Global::window)) { + while (!glfwWindowShouldClose(window)) { glfwPollEvents(); - agnosia_imgui::Gui::drawImGui(); - render_present::Render::drawFrame(); + Gui::drawImGui(); + Render::drawFrame(); } - vkDeviceWaitIdle(Global::device); + vkDeviceWaitIdle(DeviceControl::getDevice()); } void cleanup() { - render_present::Render::cleanupSwapChain(); - graphics_pipeline::Graphics::destroyGraphicsPipeline(); - buffers_libs::Buffers::destroyUniformBuffer(); - buffers_libs::Buffers::destroyDescriptorPool(); - texture_libs::Texture::destroyTextureSampler(); - texture_libs::Texture::destroyTextureImage(); - vkDestroyDescriptorSetLayout(Global::device, Global::descriptorSetLayout, - nullptr); - buffers_libs::Buffers::destroyBuffers(); - render_present::Render::destroyFenceSemaphores(); - graphics_pipeline::Graphics::destroyCommandPool(); + Render::cleanupSwapChain(); + Graphics::destroyGraphicsPipeline(); + Buffers::destroyUniformBuffer(); + Buffers::destroyDescriptorPool(); + Texture::destroyTextureSampler(); + Texture::destroyTextureImage(); + vkDestroyDescriptorSetLayout(DeviceControl::getDevice(), + Buffers::getDescriptorSetLayout(), nullptr); + Buffers::destroyBuffers(); + Render::destroyFenceSemaphores(); + Graphics::destroyCommandPool(); ImGui_ImplVulkan_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); - vkDestroyDevice(Global::device, nullptr); - device_libs::DeviceControl::destroySurface(vulkaninstance); + vkDestroyDevice(DeviceControl::getDevice(), nullptr); + DeviceControl::destroySurface(vulkaninstance); vkDestroyInstance(vulkaninstance, nullptr); - glfwDestroyWindow(Global::window); + glfwDestroyWindow(window); glfwTerminate(); } @@ -152,7 +164,7 @@ EntryApp::EntryApp() : initialized(false), framebufferResized(false) {} void EntryApp::initialize() { initialized = true; } bool EntryApp::isInitialized() const { return initialized; } - +GLFWwindow *EntryApp::getWindow() { return window; } void EntryApp::run() { initWindow(); initVulkan(); diff --git a/src/entrypoint.h b/src/entrypoint.h index bcad76a..91c638e 100644 --- a/src/entrypoint.h +++ b/src/entrypoint.h @@ -1,10 +1,6 @@ #pragma once -#include "global.h" -#include "graphics/graphicspipeline.h" -#include "graphics/model.h" -#include "graphics/render.h" -#include "graphics/texture.h" +#include class EntryApp { public: static EntryApp &getInstance(); @@ -13,6 +9,7 @@ public: void run(); void setFramebufferResized(bool frame); bool getFramebufferResized() const; + static GLFWwindow *getWindow(); private: EntryApp(); diff --git a/src/global.cpp b/src/global.cpp deleted file mode 100644 index 1802144..0000000 --- a/src/global.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "global.h" - -namespace Global { - -VkSurfaceKHR surface; -VkDevice device; -VkPhysicalDevice physicalDevice; -VkSampleCountFlagBits perPixelSampleCount; -VkSwapchainKHR swapChain; -VkCommandPool commandPool; -std::vector commandBuffers; -VkQueue graphicsQueue; -VkQueue presentQueue; -GLFWwindow *window; -VkDescriptorSetLayout descriptorSetLayout; -std::vector descriptorSets; -uint32_t currentFrame = 0; -VkImageView textureImageView; -VkSampler textureSampler; -VkImageView colorImageView; -VkImage colorImage; -VkDeviceMemory colorImageMemory; -VkImageView depthImageView; -VkImage depthImage; -VkDeviceMemory depthImageMemory; - -std::vector swapChainImageViews; -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. - Global::QueueFamilyIndices indices; - uint32_t queueFamilyCount = 0; - vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr); - - std::vector queueFamilies(queueFamilyCount); - vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, - queueFamilies.data()); - - int i = 0; - for (const auto &queueFamily : queueFamilies) { - if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { - indices.graphicsFamily = i; - } - - VkBool32 presentSupport = false; - vkGetPhysicalDeviceSurfaceSupportKHR(device, i, Global::surface, - &presentSupport); - if (presentSupport) { - indices.presentFamily = i; - } - - if (indices.isComplete()) { - break; - } - i++; - } - return indices; -} -} // namespace Global diff --git a/src/global.h b/src/global.h deleted file mode 100644 index a829121..0000000 --- a/src/global.h +++ /dev/null @@ -1,129 +0,0 @@ -#pragma once - -#define VK_NO_PROTOTYPES -#include "volk.h" - -#define GLM_FORCE_DEPTH_ZERO_TO_ONE -#include - -#include -#include -#include -#include -#include - -#define GLFW_INCLUDE_VULKAN -#include - -#include -#include -#include -#include -#include -#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, so that's one obvious global, as well as the glfw includes! - -extern VkPhysicalDevice physicalDevice; -extern VkSampleCountFlagBits perPixelSampleCount; -extern VkDevice device; - -extern VkCommandPool commandPool; -extern std::vector commandBuffers; - -extern VkQueue graphicsQueue; -extern VkQueue presentQueue; - -extern GLFWwindow *window; -extern VkSurfaceKHR surface; -extern uint32_t currentFrame; - -extern std::vector descriptorSets; -extern VkDescriptorSetLayout descriptorSetLayout; - -extern VkImageView textureImageView; -extern VkSampler textureSampler; - -extern VkImage colorImage; -extern VkImageView colorImageView; -extern VkDeviceMemory colorImageMemory; - -extern VkImage depthImage; -extern VkImageView depthImageView; -extern VkDeviceMemory depthImageMemory; - -extern VkSwapchainKHR swapChain; -extern std::vector swapChainImageViews; - -const std::string MODEL_PATH = "assets/models/viking_room.obj"; -const std::string TEXTURE_PATH = "assets/textures/viking_room.png"; -const uint32_t WIDTH = 800; -const uint32_t HEIGHT = 600; -const int MAX_FRAMES_IN_FLIGHT = 2; - -struct UniformBufferObject { - float time; - alignas(16) glm::mat4 model; - alignas(16) glm::mat4 view; - alignas(16) glm::mat4 proj; -}; -struct Vertex { - // This defines what a vertex is! - // We control the position, color and texture coordinate here! - glm::vec3 pos; - glm::vec3 color; - glm::vec2 texCoord; - - static VkVertexInputBindingDescription getBindingDescription() { - VkVertexInputBindingDescription bindingDescription{}; - bindingDescription.binding = 0; - bindingDescription.stride = sizeof(Vertex); - bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - - return bindingDescription; - } - static std::array - getAttributeDescriptions() { - std::array attributeDescriptions{}; - - attributeDescriptions[0].binding = 0; - attributeDescriptions[0].location = 0; - attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT; - attributeDescriptions[0].offset = offsetof(Vertex, pos); - - attributeDescriptions[1].binding = 0; - attributeDescriptions[1].location = 1; - attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT; - attributeDescriptions[1].offset = offsetof(Vertex, color); - - attributeDescriptions[2].binding = 0; - attributeDescriptions[2].location = 2; - attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT; - attributeDescriptions[2].offset = offsetof(Vertex, texCoord); - return attributeDescriptions; - } - bool operator==(const Vertex &other) const { - return pos == other.pos && color == other.color && - texCoord == other.texCoord; - } -}; - -extern std::vector vertices; -// Index buffer definition, showing which points to reuse. -extern std::vector indices; -struct QueueFamilyIndices { - // We need to check that the Queue families support graphics operations and - // window presentation, sometimes they can support one or the other, - // therefore, we take into account both for completion. - std::optional graphicsFamily; - std::optional presentFamily; - - bool isComplete() { - return graphicsFamily.has_value() && presentFamily.has_value(); - } -}; -Global::QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device); -} // namespace Global diff --git a/src/graphics/buffers.cpp b/src/graphics/buffers.cpp index 431b198..f7713b6 100644 --- a/src/graphics/buffers.cpp +++ b/src/graphics/buffers.cpp @@ -1,12 +1,27 @@ +#include "../devicelibrary.h" #include "buffers.h" -#include +#include "texture.h" +#include +#include +#include +#include +#include VkBuffer vertexBuffer; VkDeviceMemory vertexBufferMemory; VkBuffer indexBuffer; VkDeviceMemory indexBufferMemory; -VkDescriptorPool descriptorPool; +std::vector vertices; +// Index buffer definition, showing which points to reuse. +std::vector indices; + +VkDescriptorPool descriptorPool; +VkDescriptorSetLayout descriptorSetLayout; +std::vector descriptorSets; + +VkCommandPool commandPool; +std::vector commandBuffers; std::vector uniformBuffers; std::vector uniformBuffersMemory; std::vector uniformBuffersMapped; @@ -18,14 +33,22 @@ float upDir[4] = {0.0f, 0.0f, 1.0f, 0.44f}; float depthField = 45.0f; float distanceField[2] = {0.1f, 100.0f}; -namespace buffers_libs { +const int MAX_FRAMES_IN_FLIGHT = 2; +struct UniformBufferObject { + float time; + alignas(16) glm::mat4 model; + alignas(16) glm::mat4 view; + alignas(16) glm::mat4 proj; +}; + 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; - vkGetPhysicalDeviceMemoryProperties(Global::physicalDevice, &memProperties); + vkGetPhysicalDeviceMemoryProperties(DeviceControl::getPhysicalDevice(), + &memProperties); // iterate over and see if any of the memory types match our needs, in this // case, HOST_VISIBLE and HOST_COHERENT. These will be explained shortly. for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) { @@ -41,11 +64,12 @@ void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) { VkCommandBufferAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandPool = Global::commandPool; + allocInfo.commandPool = commandPool; allocInfo.commandBufferCount = 1; VkCommandBuffer commandBuffer; - vkAllocateCommandBuffers(Global::device, &allocInfo, &commandBuffer); + vkAllocateCommandBuffers(DeviceControl::getDevice(), &allocInfo, + &commandBuffer); VkCommandBufferBeginInfo beginInfo{}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -64,10 +88,12 @@ void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) { submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &commandBuffer; - vkQueueSubmit(Global::graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); - vkQueueWaitIdle(Global::graphicsQueue); + vkQueueSubmit(DeviceControl::getGraphicsQueue(), 1, &submitInfo, + VK_NULL_HANDLE); + vkQueueWaitIdle(DeviceControl::getGraphicsQueue()); - vkFreeCommandBuffers(Global::device, Global::commandPool, 1, &commandBuffer); + vkFreeCommandBuffers(DeviceControl::getDevice(), commandPool, 1, + &commandBuffer); } void Buffers::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, @@ -79,13 +105,14 @@ void Buffers::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, bufferInfo.usage = usage; bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - if (vkCreateBuffer(Global::device, &bufferInfo, nullptr, &buffer) != - VK_SUCCESS) { + if (vkCreateBuffer(DeviceControl::getDevice(), &bufferInfo, nullptr, + &buffer) != VK_SUCCESS) { throw std::runtime_error("failed to create buffer!"); } VkMemoryRequirements memRequirements; - vkGetBufferMemoryRequirements(Global::device, buffer, &memRequirements); + vkGetBufferMemoryRequirements(DeviceControl::getDevice(), buffer, + &memRequirements); VkMemoryAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; @@ -93,16 +120,16 @@ void Buffers::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties); - if (vkAllocateMemory(Global::device, &allocInfo, nullptr, &bufferMemory) != - VK_SUCCESS) { + if (vkAllocateMemory(DeviceControl::getDevice(), &allocInfo, nullptr, + &bufferMemory) != VK_SUCCESS) { throw std::runtime_error("failed to allocate buffer memory!"); } - vkBindBufferMemory(Global::device, buffer, bufferMemory, 0); + vkBindBufferMemory(DeviceControl::getDevice(), buffer, bufferMemory, 0); } void Buffers::createIndexBuffer() { - VkDeviceSize bufferSize = sizeof(Global::indices[0]) * Global::indices.size(); + VkDeviceSize bufferSize = sizeof(indices[0]) * indices.size(); VkBuffer stagingBuffer; VkDeviceMemory stagingBufferMemory; @@ -113,10 +140,11 @@ void Buffers::createIndexBuffer() { stagingBuffer, stagingBufferMemory); void *data; - vkMapMemory(Global::device, stagingBufferMemory, 0, bufferSize, 0, &data); - memcpy(data, Global::indices.data(), (size_t)bufferSize); + vkMapMemory(DeviceControl::getDevice(), stagingBufferMemory, 0, bufferSize, 0, + &data); + memcpy(data, indices.data(), (size_t)bufferSize); - vkUnmapMemory(Global::device, stagingBufferMemory); + vkUnmapMemory(DeviceControl::getDevice(), stagingBufferMemory); createBuffer( bufferSize, @@ -125,8 +153,8 @@ void Buffers::createIndexBuffer() { copyBuffer(stagingBuffer, indexBuffer, bufferSize); - vkDestroyBuffer(Global::device, stagingBuffer, nullptr); - vkFreeMemory(Global::device, stagingBufferMemory, nullptr); + vkDestroyBuffer(DeviceControl::getDevice(), stagingBuffer, nullptr); + vkFreeMemory(DeviceControl::getDevice(), stagingBufferMemory, nullptr); } void Buffers::createVertexBuffer() { // Create a Vertex Buffer to hold the vertex information in memory so it @@ -134,8 +162,7 @@ void Buffers::createVertexBuffer() { // 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. - VkDeviceSize bufferSize = - sizeof(Global::vertices[0]) * Global::vertices.size(); + VkDeviceSize bufferSize = sizeof(vertices[0]) * vertices.size(); VkBuffer stagingBuffer; VkDeviceMemory stagingBufferMemory; @@ -147,9 +174,10 @@ void Buffers::createVertexBuffer() { stagingBuffer, stagingBufferMemory); void *data; - vkMapMemory(Global::device, stagingBufferMemory, 0, bufferSize, 0, &data); - memcpy(data, Global::vertices.data(), (size_t)bufferSize); - vkUnmapMemory(Global::device, stagingBufferMemory); + vkMapMemory(DeviceControl::getDevice(), stagingBufferMemory, 0, bufferSize, 0, + &data); + memcpy(data, vertices.data(), (size_t)bufferSize); + vkUnmapMemory(DeviceControl::getDevice(), stagingBufferMemory); createBuffer( bufferSize, @@ -158,19 +186,17 @@ void Buffers::createVertexBuffer() { copyBuffer(stagingBuffer, vertexBuffer, bufferSize); - vkDestroyBuffer(Global::device, stagingBuffer, nullptr); - vkFreeMemory(Global::device, stagingBufferMemory, nullptr); + vkDestroyBuffer(DeviceControl::getDevice(), stagingBuffer, nullptr); + vkFreeMemory(DeviceControl::getDevice(), stagingBufferMemory, nullptr); } void Buffers::destroyBuffers() { - vkDestroyBuffer(Global::device, indexBuffer, nullptr); - vkFreeMemory(Global::device, indexBufferMemory, nullptr); + vkDestroyBuffer(DeviceControl::getDevice(), indexBuffer, nullptr); + vkFreeMemory(DeviceControl::getDevice(), indexBufferMemory, nullptr); - vkDestroyBuffer(Global::device, vertexBuffer, nullptr); - vkFreeMemory(Global::device, vertexBufferMemory, nullptr); + vkDestroyBuffer(DeviceControl::getDevice(), vertexBuffer, nullptr); + vkFreeMemory(DeviceControl::getDevice(), vertexBufferMemory, nullptr); } -VkBuffer Buffers::getVertexBuffer() { return vertexBuffer; } -VkBuffer Buffers::getIndexBuffer() { return indexBuffer; } // ------------------------------ Uniform Buffer Setup // -------------------------------- // @@ -204,8 +230,9 @@ void Buffers::createDescriptorSetLayout() { layoutInfo.bindingCount = static_cast(bindings.size()); layoutInfo.pBindings = bindings.data(); - if (vkCreateDescriptorSetLayout(Global::device, &layoutInfo, nullptr, - &Global::descriptorSetLayout) != VK_SUCCESS) { + if (vkCreateDescriptorSetLayout(DeviceControl::getDevice(), &layoutInfo, + nullptr, + &descriptorSetLayout) != VK_SUCCESS) { throw std::runtime_error("Failed to create descriptor set layout!"); } } @@ -214,19 +241,18 @@ void Buffers::createUniformBuffers() { // 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); + VkDeviceSize bufferSize = sizeof(UniformBufferObject); - uniformBuffers.resize(Global::MAX_FRAMES_IN_FLIGHT); - uniformBuffersMemory.resize(Global::MAX_FRAMES_IN_FLIGHT); - uniformBuffersMapped.resize(Global::MAX_FRAMES_IN_FLIGHT); - - for (size_t i = 0; i < Global::MAX_FRAMES_IN_FLIGHT; i++) { + uniformBuffers.resize(MAX_FRAMES_IN_FLIGHT); + uniformBuffersMemory.resize(MAX_FRAMES_IN_FLIGHT); + uniformBuffersMapped.resize(MAX_FRAMES_IN_FLIGHT); + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, uniformBuffers[i], uniformBuffersMemory[i]); - vkMapMemory(Global::device, uniformBuffersMemory[i], 0, bufferSize, 0, - &uniformBuffersMapped[i]); + vkMapMemory(DeviceControl::getDevice(), uniformBuffersMemory[i], 0, + bufferSize, 0, &uniformBuffersMapped[i]); } } void Buffers::updateUniformBuffer(uint32_t currentImage) { @@ -242,7 +268,7 @@ void Buffers::updateUniformBuffer(uint32_t currentImage) { currentTime - startTime) .count(); - Global::UniformBufferObject ubo{}; + UniformBufferObject ubo{}; ubo.time = time; // Modify the model projection transformation to rotate around the Z over // time. @@ -257,11 +283,11 @@ void Buffers::updateUniformBuffer(uint32_t currentImage) { glm::vec3(centerPos[0], centerPos[1], centerPos[2]), glm::vec3(upDir[0], upDir[1], upDir[2])); // 45 degree field of view, set aspect ratio, and near and far clipping range. - ubo.proj = glm::perspective( - glm::radians(depthField), - device_libs::DeviceControl::getSwapChainExtent().width / - (float)device_libs::DeviceControl::getSwapChainExtent().height, - distanceField[0], distanceField[1]); + ubo.proj = + glm::perspective(glm::radians(depthField), + DeviceControl::getSwapChainExtent().width / + (float)DeviceControl::getSwapChainExtent().height, + distanceField[0], distanceField[1]); // GLM was created for OpenGL, where the Y coordinate was inverted. This // simply flips the sign. @@ -270,63 +296,60 @@ void Buffers::updateUniformBuffer(uint32_t currentImage) { memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); } 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); + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + vkDestroyBuffer(DeviceControl::getDevice(), uniformBuffers[i], nullptr); + vkFreeMemory(DeviceControl::getDevice(), uniformBuffersMemory[i], nullptr); } } void Buffers::createDescriptorPool() { // Create a pool to be used to allocate descriptor sets. std::array poolSizes{}; poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - poolSizes[0].descriptorCount = - static_cast(Global::MAX_FRAMES_IN_FLIGHT); + poolSizes[0].descriptorCount = static_cast(MAX_FRAMES_IN_FLIGHT); poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - poolSizes[1].descriptorCount = - static_cast(Global::MAX_FRAMES_IN_FLIGHT); + poolSizes[1].descriptorCount = static_cast(MAX_FRAMES_IN_FLIGHT); VkDescriptorPoolCreateInfo poolInfo{}; poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; poolInfo.poolSizeCount = static_cast(poolSizes.size()); poolInfo.pPoolSizes = poolSizes.data(); - poolInfo.maxSets = static_cast(Global::MAX_FRAMES_IN_FLIGHT); + poolInfo.maxSets = static_cast(MAX_FRAMES_IN_FLIGHT); - if (vkCreateDescriptorPool(Global::device, &poolInfo, nullptr, + if (vkCreateDescriptorPool(DeviceControl::getDevice(), &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) { throw std::runtime_error("failed to create descriptor pool!"); } } void Buffers::createDescriptorSets() { - std::vector layouts(Global::MAX_FRAMES_IN_FLIGHT, - Global::descriptorSetLayout); + std::vector layouts(MAX_FRAMES_IN_FLIGHT, + descriptorSetLayout); VkDescriptorSetAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; allocInfo.descriptorPool = descriptorPool; - allocInfo.descriptorSetCount = - static_cast(Global::MAX_FRAMES_IN_FLIGHT); + allocInfo.descriptorSetCount = static_cast(MAX_FRAMES_IN_FLIGHT); allocInfo.pSetLayouts = layouts.data(); - Global::descriptorSets.resize(Global::MAX_FRAMES_IN_FLIGHT); - if (vkAllocateDescriptorSets(Global::device, &allocInfo, - Global::descriptorSets.data()) != VK_SUCCESS) { + descriptorSets.resize(MAX_FRAMES_IN_FLIGHT); + if (vkAllocateDescriptorSets(DeviceControl::getDevice(), &allocInfo, + descriptorSets.data()) != VK_SUCCESS) { throw std::runtime_error("failed to allocate descriptor sets!"); } - for (size_t i = 0; i < Global::MAX_FRAMES_IN_FLIGHT; i++) { + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { VkDescriptorBufferInfo bufferInfo{}; bufferInfo.buffer = uniformBuffers[i]; bufferInfo.offset = 0; - bufferInfo.range = sizeof(Global::UniformBufferObject); + bufferInfo.range = sizeof(UniformBufferObject); VkDescriptorImageInfo imageInfo{}; imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageInfo.imageView = Global::textureImageView; - imageInfo.sampler = Global::textureSampler; + imageInfo.imageView = Texture::getTextureImageView(); + imageInfo.sampler = Texture::getTextureSampler(); std::array descriptorWrites{}; descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrites[0].dstSet = Global::descriptorSets[i]; + descriptorWrites[0].dstSet = descriptorSets[i]; descriptorWrites[0].dstBinding = 0; descriptorWrites[0].dstArrayElement = 0; descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; @@ -334,7 +357,7 @@ void Buffers::createDescriptorSets() { descriptorWrites[0].pBufferInfo = &bufferInfo; descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrites[1].dstSet = Global::descriptorSets[i]; + descriptorWrites[1].dstSet = descriptorSets[i]; descriptorWrites[1].dstBinding = 1; descriptorWrites[1].dstArrayElement = 0; descriptorWrites[1].descriptorType = @@ -342,19 +365,37 @@ void Buffers::createDescriptorSets() { descriptorWrites[1].descriptorCount = 1; descriptorWrites[1].pImageInfo = &imageInfo; - vkUpdateDescriptorSets(Global::device, + vkUpdateDescriptorSets(DeviceControl::getDevice(), static_cast(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr); } } void Buffers::destroyDescriptorPool() { - vkDestroyDescriptorPool(Global::device, descriptorPool, nullptr); + vkDestroyDescriptorPool(DeviceControl::getDevice(), descriptorPool, nullptr); +} +VkBuffer &Buffers::getVertexBuffer() { return vertexBuffer; } +VkBuffer &Buffers::getIndexBuffer() { return indexBuffer; } +VkDescriptorPool &Buffers::getDescriptorPool() { return descriptorPool; } +std::vector &Buffers::getDescriptorSets() { + return descriptorSets; } -VkDescriptorPool Buffers::getDescriptorPool() { return descriptorPool; } float *Buffers::getObjPos() { return objPos; } float *Buffers::getCamPos() { return camPos; } float *Buffers::getCenterPos() { return centerPos; } float *Buffers::getUpDir() { return upDir; } -float *Buffers::getDepthField() { return &depthField; } +float &Buffers::getDepthField() { return depthField; } float *Buffers::getDistanceField() { return distanceField; } -} // namespace buffers_libs +uint32_t Buffers::getMaxFramesInFlight() { return MAX_FRAMES_IN_FLIGHT; } +std::vector &Buffers::getCommandBuffers() { + return commandBuffers; +} +std::vector &Buffers::getUniformBuffers() { return uniformBuffers; } +std::vector &Buffers::getUniformBuffersMemory() { + return uniformBuffersMemory; +} +VkCommandPool &Buffers::getCommandPool() { return commandPool; } +VkDescriptorSetLayout &Buffers::getDescriptorSetLayout() { + return descriptorSetLayout; +} +std::vector &Buffers::getVertices() { return vertices; } +std::vector &Buffers::getIndices() { return indices; } diff --git a/src/graphics/buffers.h b/src/graphics/buffers.h index 3c9d59b..6a26a14 100644 --- a/src/graphics/buffers.h +++ b/src/graphics/buffers.h @@ -1,11 +1,58 @@ #pragma once -#include "../devicelibrary.h" -#include -#include -namespace buffers_libs { +#define VK_NO_PROTOTYPES +#include "volk.h" +#include +#define GLM_FORCE_DEPTH_ZERO_TO_ONE +#include + +#define GLFW_INCLUDE_VULKAN +#include +#include + class Buffers { + public: + struct Vertex { + // This defines what a vertex is! + // We control the position, color and texture coordinate here! + glm::vec3 pos; + glm::vec3 color; + glm::vec2 texCoord; + + static VkVertexInputBindingDescription getBindingDescription() { + VkVertexInputBindingDescription bindingDescription{}; + bindingDescription.binding = 0; + bindingDescription.stride = sizeof(Vertex); + bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + + return bindingDescription; + } + static std::array + getAttributeDescriptions() { + std::array attributeDescriptions{}; + + attributeDescriptions[0].binding = 0; + attributeDescriptions[0].location = 0; + attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT; + attributeDescriptions[0].offset = offsetof(Vertex, pos); + + attributeDescriptions[1].binding = 0; + attributeDescriptions[1].location = 1; + attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT; + attributeDescriptions[1].offset = offsetof(Vertex, color); + + attributeDescriptions[2].binding = 0; + attributeDescriptions[2].location = 2; + attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT; + attributeDescriptions[2].offset = offsetof(Vertex, texCoord); + return attributeDescriptions; + } + bool operator==(const Vertex &other) const { + return pos == other.pos && color == other.color && + texCoord == other.texCoord; + } + }; static void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags props, VkBuffer &buffer, VkDeviceMemory &bufferMemory); @@ -14,8 +61,8 @@ public: static void createIndexBuffer(); static void createVertexBuffer(); static void destroyBuffers(); - static VkBuffer getVertexBuffer(); - static VkBuffer getIndexBuffer(); + static VkBuffer &getVertexBuffer(); + static VkBuffer &getIndexBuffer(); static void createDescriptorSetLayout(); static void createUniformBuffers(); static void updateUniformBuffer(uint32_t currentImage); @@ -23,13 +70,21 @@ public: static void createDescriptorPool(); static void createDescriptorSets(); static void destroyDescriptorPool(); - static VkDescriptorPool getDescriptorPool(); + static VkDescriptorPool &getDescriptorPool(); + static VkDescriptorSetLayout &getDescriptorSetLayout(); + static std::vector &getDescriptorSets(); static float *getObjPos(); static float *getCamPos(); static float *getCenterPos(); static float *getUpDir(); - static float *getDepthField(); + static float &getDepthField(); static float *getDistanceField(); + static uint32_t getMaxFramesInFlight(); + static std::vector &getCommandBuffers(); + static std::vector &getUniformBuffers(); + static std::vector &getUniformBuffersMemory(); + static VkCommandPool &getCommandPool(); + static std::vector &getVertices(); + static std::vector &getIndices(); }; -} // namespace buffers_libs diff --git a/src/graphics/graphicspipeline.cpp b/src/graphics/graphicspipeline.cpp index e9a15e2..99d32b1 100644 --- a/src/graphics/graphicspipeline.cpp +++ b/src/graphics/graphicspipeline.cpp @@ -1,9 +1,11 @@ +#include "../devicelibrary.h" +#include "buffers.h" #include "graphicspipeline.h" #include "imgui.h" #include "imgui_impl_vulkan.h" +#include "render.h" #include "texture.h" - -namespace graphics_pipeline { +#include std::vector dynamicStates = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; @@ -43,8 +45,8 @@ VkShaderModule createShaderModule(const std::vector &code, } void Graphics::destroyGraphicsPipeline() { - vkDestroyPipeline(Global::device, graphicsPipeline, nullptr); - vkDestroyPipelineLayout(Global::device, pipelineLayout, nullptr); + vkDestroyPipeline(DeviceControl::getDevice(), graphicsPipeline, nullptr); + vkDestroyPipelineLayout(DeviceControl::getDevice(), pipelineLayout, nullptr); } void Graphics::createGraphicsPipeline() { @@ -53,9 +55,9 @@ void Graphics::createGraphicsPipeline() { auto vertShaderCode = readFile("src/shaders/vertex.spv"); auto fragShaderCode = readFile("src/shaders/fragment.spv"); VkShaderModule vertShaderModule = - createShaderModule(vertShaderCode, Global::device); + createShaderModule(vertShaderCode, DeviceControl::getDevice()); VkShaderModule fragShaderModule = - createShaderModule(fragShaderCode, Global::device); + createShaderModule(fragShaderCode, DeviceControl::getDevice()); // ------------------ 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 @@ -81,8 +83,8 @@ void Graphics::createGraphicsPipeline() { vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - auto bindingDescription = Global::Vertex::getBindingDescription(); - auto attributeDescriptions = Global::Vertex::getAttributeDescriptions(); + auto bindingDescription = Buffers::Vertex::getBindingDescription(); + auto attributeDescriptions = Buffers::Vertex::getAttributeDescriptions(); vertexInputInfo.vertexBindingDescriptionCount = 1; vertexInputInfo.pVertexBindingDescriptions = &bindingDescription; @@ -149,7 +151,7 @@ void Graphics::createGraphicsPipeline() { multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; multisampling.sampleShadingEnable = VK_TRUE; - multisampling.rasterizationSamples = Global::perPixelSampleCount; + multisampling.rasterizationSamples = DeviceControl::getPerPixelSampleCount(); // TODO: Document! VkPipelineDepthStencilStateCreateInfo depthStencil{}; depthStencil.sType = @@ -175,18 +177,18 @@ void Graphics::createGraphicsPipeline() { VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipelineLayoutInfo.setLayoutCount = 1; - pipelineLayoutInfo.pSetLayouts = &Global::descriptorSetLayout; + pipelineLayoutInfo.pSetLayouts = &Buffers::getDescriptorSetLayout(); - if (vkCreatePipelineLayout(Global::device, &pipelineLayoutInfo, nullptr, - &pipelineLayout) != VK_SUCCESS) { + if (vkCreatePipelineLayout(DeviceControl::getDevice(), &pipelineLayoutInfo, + nullptr, &pipelineLayout) != VK_SUCCESS) { throw std::runtime_error("failed to create pipeline layout!"); } VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo{ .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, .colorAttachmentCount = 1, - .pColorAttachmentFormats = device_libs::DeviceControl::getImageFormat(), - .depthAttachmentFormat = texture_libs::Texture::findDepthFormat(), + .pColorAttachmentFormats = &DeviceControl::getImageFormat(), + .depthAttachmentFormat = Texture::findDepthFormat(), }; // Here we combine all of the structures we created to make the final @@ -209,46 +211,48 @@ void Graphics::createGraphicsPipeline() { .subpass = 0, }; - if (vkCreateGraphicsPipelines(Global::device, VK_NULL_HANDLE, 1, + if (vkCreateGraphicsPipelines(DeviceControl::getDevice(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) { throw std::runtime_error("failed to create graphics pipeline!"); } - vkDestroyShaderModule(Global::device, fragShaderModule, nullptr); - vkDestroyShaderModule(Global::device, vertShaderModule, nullptr); + vkDestroyShaderModule(DeviceControl::getDevice(), fragShaderModule, nullptr); + vkDestroyShaderModule(DeviceControl::getDevice(), vertShaderModule, nullptr); } 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); + DeviceControl::QueueFamilyIndices queueFamilyIndices = + DeviceControl::findQueueFamilies(DeviceControl::getPhysicalDevice()); VkCommandPoolCreateInfo poolInfo{}; poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value(); - if (vkCreateCommandPool(Global::device, &poolInfo, nullptr, - &Global::commandPool) != VK_SUCCESS) { + if (vkCreateCommandPool(DeviceControl::getDevice(), &poolInfo, nullptr, + &Buffers::getCommandPool()) != VK_SUCCESS) { throw std::runtime_error("Failed to create command pool!"); } } void Graphics::destroyCommandPool() { - vkDestroyCommandPool(Global::device, Global::commandPool, nullptr); + vkDestroyCommandPool(DeviceControl::getDevice(), Buffers::getCommandPool(), + nullptr); } void Graphics::createCommandBuffer() { - Global::commandBuffers.resize(Global::MAX_FRAMES_IN_FLIGHT); + Buffers::getCommandBuffers().resize(Buffers::getMaxFramesInFlight()); VkCommandBufferAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocInfo.commandPool = Global::commandPool; + allocInfo.commandPool = Buffers::getCommandPool(); allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandBufferCount = (uint32_t)Global::commandBuffers.size(); + allocInfo.commandBufferCount = (uint32_t)Buffers::getCommandBuffers().size(); - if (vkAllocateCommandBuffers(Global::device, &allocInfo, - Global::commandBuffers.data()) != VK_SUCCESS) { + if (vkAllocateCommandBuffers(DeviceControl::getDevice(), &allocInfo, + Buffers::getCommandBuffers().data()) != + VK_SUCCESS) { throw std::runtime_error("Failed to allocate command buffers"); } } @@ -272,7 +276,7 @@ void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer, .newLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = device_libs::DeviceControl::getSwapChainImages()[imageIndex], + .image = DeviceControl::getSwapChainImages()[imageIndex], .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, @@ -294,10 +298,10 @@ void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer, const VkRenderingAttachmentInfo colorAttachmentInfo{ .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, - .imageView = Global::colorImageView, + .imageView = Texture::getColorImageView(), .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, .resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT, - .resolveImageView = Global::swapChainImageViews[imageIndex], + .resolveImageView = DeviceControl::getSwapChainImageViews()[imageIndex], .resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, .storeOp = VK_ATTACHMENT_STORE_OP_STORE, @@ -305,7 +309,7 @@ void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer, }; const VkRenderingAttachmentInfo depthAttachmentInfo{ .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, - .imageView = Global::depthImageView, + .imageView = Texture::getDepthImageView(), .imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, @@ -315,8 +319,7 @@ void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer, const VkRenderingInfo renderInfo{ .sType = VK_STRUCTURE_TYPE_RENDERING_INFO, .renderArea = {.offset = {0, 0}, - .extent = - device_libs::DeviceControl::getSwapChainExtent()}, + .extent = DeviceControl::getSwapChainExtent()}, .layerCount = 1, .colorAttachmentCount = 1, .pColorAttachments = &colorAttachmentInfo, @@ -330,31 +333,30 @@ void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer, VkViewport viewport{}; viewport.x = 0.0f; viewport.y = 0.0f; - viewport.width = - (float)device_libs::DeviceControl::getSwapChainExtent().width; - viewport.height = - (float)device_libs::DeviceControl::getSwapChainExtent().height; + viewport.width = (float)DeviceControl::getSwapChainExtent().width; + viewport.height = (float)DeviceControl::getSwapChainExtent().height; viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; vkCmdSetViewport(commandBuffer, 0, 1, &viewport); VkRect2D scissor{}; scissor.offset = {0, 0}; - scissor.extent = device_libs::DeviceControl::getSwapChainExtent(); + scissor.extent = DeviceControl::getSwapChainExtent(); vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - VkBuffer vertexBuffers[] = {buffers_libs::Buffers::getVertexBuffer()}; + VkBuffer vertexBuffers[] = {Buffers::getVertexBuffer()}; VkDeviceSize offsets[] = {0}; vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); - vkCmdBindIndexBuffer(commandBuffer, buffers_libs::Buffers::getIndexBuffer(), - 0, VK_INDEX_TYPE_UINT32); + vkCmdBindIndexBuffer(commandBuffer, Buffers::getIndexBuffer(), 0, + VK_INDEX_TYPE_UINT32); vkCmdBindDescriptorSets( commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, - &Global::descriptorSets[Global::currentFrame], 0, nullptr); + &Buffers::getDescriptorSets()[Render::getCurrentFrame()], 0, nullptr); - vkCmdDrawIndexed(commandBuffer, static_cast(Global::indices.size()), - 1, 0, 0, 0); + vkCmdDrawIndexed(commandBuffer, + static_cast(Buffers::getIndices().size()), 1, 0, 0, + 0); ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), commandBuffer); @@ -371,7 +373,7 @@ void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer, .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = device_libs::DeviceControl::getSwapChainImages()[imageIndex], + .image = DeviceControl::getSwapChainImages()[imageIndex], .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, @@ -388,11 +390,10 @@ void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer, .pImageMemoryBarriers = &prePresentImageBarrier, }; - vkCmdPipelineBarrier2(Global::commandBuffers[Global::currentFrame], &depInfo); + vkCmdPipelineBarrier2( + Buffers ::getCommandBuffers()[Render::getCurrentFrame()], &depInfo); if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) { throw std::runtime_error("failed to record command buffer!"); } } - -} // namespace graphics_pipeline diff --git a/src/graphics/graphicspipeline.h b/src/graphics/graphicspipeline.h index 16c9a4a..e177a45 100644 --- a/src/graphics/graphicspipeline.h +++ b/src/graphics/graphicspipeline.h @@ -1,20 +1,16 @@ #pragma once -#include "../global.h" -#include "../devicelibrary.h" -#include "buffers.h" -#include "texture.h" -#include +#define VK_NO_PROTOTYPES +#include "volk.h" -namespace graphics_pipeline { - class Graphics { - public: - static void createGraphicsPipeline(); - static void destroyGraphicsPipeline(); - static void createFramebuffers(); - static void destroyFramebuffers(); - static void createCommandPool(); - static void destroyCommandPool(); - static void createCommandBuffer(); - static void recordCommandBuffer(VkCommandBuffer cmndBuffer, uint32_t imageIndex); - }; -} +class Graphics { +public: + static void createGraphicsPipeline(); + static void destroyGraphicsPipeline(); + static void createFramebuffers(); + static void destroyFramebuffers(); + static void createCommandPool(); + static void destroyCommandPool(); + static void createCommandBuffer(); + static void recordCommandBuffer(VkCommandBuffer cmndBuffer, + uint32_t imageIndex); +}; diff --git a/src/graphics/model.cpp b/src/graphics/model.cpp index 72693f8..17ce4de 100644 --- a/src/graphics/model.cpp +++ b/src/graphics/model.cpp @@ -1,64 +1,68 @@ +#include "buffers.h" #include "model.h" +#include + +#define TINY_OBJ_IMPLEMENTATION +#include + +#define GLM_ENABLE_EXPERIMENTAL +#include namespace std { - template<> struct hash { - size_t operator()(Global::Vertex const& vertex) const { - return ((hash()(vertex.pos) ^ - (hash()(vertex.color) << 1)) >> 1) ^ - (hash()(vertex.texCoord) << 1); +template <> struct hash { + size_t operator()(Buffers::Vertex const &vertex) const { + return ((hash()(vertex.pos) ^ + (hash()(vertex.color) << 1)) >> + 1) ^ + (hash()(vertex.texCoord) << 1); + } +}; +} // namespace std + +const std::string MODEL_PATH = "assets/models/viking_room.obj"; + +void Model::loadModel() { + tinyobj::ObjReaderConfig readerConfig; + + tinyobj::ObjReader reader; + + if (!reader.ParseFromFile(MODEL_PATH, readerConfig)) { + if (!reader.Error().empty()) { + throw std::runtime_error(reader.Error()); } - }; -} - -namespace modellib { - - std::unordered_map uniqueVertices{}; - - void Model::loadModel() { - tinyobj::ObjReaderConfig readerConfig; - - tinyobj::ObjReader reader; - - if(!reader.ParseFromFile(Global::MODEL_PATH, readerConfig)) { - if(!reader.Error().empty()) { - throw std::runtime_error(reader.Error()); - } - if(!reader.Warning().empty()) { - throw std::runtime_error(reader.Warning()); - } + if (!reader.Warning().empty()) { + throw std::runtime_error(reader.Warning()); } - - auto& attrib = reader.GetAttrib(); - auto& shapes = reader.GetShapes(); - auto& materials = reader.GetMaterials(); + } - for (const auto& shape : shapes) { - for (const auto& index : shape.mesh.indices) { - Global::Vertex vertex{}; + auto &attrib = reader.GetAttrib(); + auto &shapes = reader.GetShapes(); + auto &materials = reader.GetMaterials(); + std::unordered_map uniqueVertices{}; - vertex.pos = { - attrib.vertices[3 * index.vertex_index + 0], - attrib.vertices[3 * index.vertex_index + 1], - attrib.vertices[3 * index.vertex_index + 2] - }; - - //TODO: Small fix here, handle if there are no UV's unwrapped for the model. - // As of now, if it is not unwrapped, it segfaults on texCoord assignment. - // Obviously we should always have UV's, but it shouldn't crash, just unwrap - // in a default method. - vertex.texCoord = { - attrib.texcoords[2 * index.texcoord_index + 0], - 1.0f - attrib.texcoords[2 * index.texcoord_index + 1] - }; - vertex.color = {1.0f, 1.0f, 1.0f}; + for (const auto &shape : shapes) { + for (const auto &index : shape.mesh.indices) { + Buffers::Vertex vertex{}; - if (uniqueVertices.count(vertex) == 0) { - uniqueVertices[vertex] = static_cast(Global::vertices.size()); - Global::vertices.push_back(vertex); - } - - Global::indices.push_back(uniqueVertices[vertex]); + vertex.pos = {attrib.vertices[3 * index.vertex_index + 0], + attrib.vertices[3 * index.vertex_index + 1], + attrib.vertices[3 * index.vertex_index + 2]}; + + // TODO: Small fix here, handle if there are no UV's unwrapped for the + // model. + // As of now, if it is not unwrapped, it segfaults on texCoord + // assignment. Obviously we should always have UV's, but it + // shouldn't crash, just unwrap in a default method. + vertex.texCoord = {attrib.texcoords[2 * index.texcoord_index + 0], + 1.0f - attrib.texcoords[2 * index.texcoord_index + 1]}; + vertex.color = {1.0f, 1.0f, 1.0f}; + + if (uniqueVertices.count(vertex) == 0) { + uniqueVertices[vertex] = + static_cast(Buffers::getVertices().size()); + Buffers::getVertices().push_back(vertex); } + Buffers::getIndices().push_back(uniqueVertices[vertex]); } } } diff --git a/src/graphics/model.h b/src/graphics/model.h index 41dcd89..aa75d59 100644 --- a/src/graphics/model.h +++ b/src/graphics/model.h @@ -1,15 +1,6 @@ #pragma once -#include "../global.h" -#define TINY_OBJ_IMPLEMENTATION -#include - -#define GLM_ENABLE_EXPERIMENTAL -#include - -namespace modellib { class Model { public: static void loadModel(); }; -} // namespace modellib diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index e71cdb4..be5544f 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -1,55 +1,56 @@ + +#include + +#include "imgui.h" +#include "imgui_impl_vulkan.h" + #include "../devicelibrary.h" #include "../entrypoint.h" #include "buffers.h" #include "graphicspipeline.h" #include "render.h" #include "texture.h" -#include - -#include "imgui.h" -#include "imgui_impl_vulkan.h" - -namespace render_present { +uint32_t currentFrame; std::vector imageAvailableSemaphores; std::vector renderFinishedSemaphores; std::vector inFlightFences; void recreateSwapChain() { int width = 0, height = 0; - glfwGetFramebufferSize(Global::window, &width, &height); + glfwGetFramebufferSize(EntryApp::getWindow(), &width, &height); while (width == 0 || height == 0) { - glfwGetFramebufferSize(Global::window, &width, &height); + glfwGetFramebufferSize(EntryApp::getWindow(), &width, &height); glfwWaitEvents(); } - vkDeviceWaitIdle(Global::device); + vkDeviceWaitIdle(DeviceControl::getDevice()); // 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 imageView : Global::swapChainImageViews) { - vkDestroyImageView(Global::device, imageView, nullptr); + for (auto imageView : DeviceControl::getSwapChainImageViews()) { + vkDestroyImageView(DeviceControl::getDevice(), imageView, nullptr); } - vkDestroySwapchainKHR(Global::device, Global::swapChain, nullptr); + vkDestroySwapchainKHR(DeviceControl::getDevice(), + DeviceControl::getSwapChain(), nullptr); - device_libs::DeviceControl::createSwapChain(Global::window); - device_libs::DeviceControl::createImageViews(); - texture_libs::Texture::createColorResources(); - texture_libs::Texture::createDepthResources(); + DeviceControl::createSwapChain(EntryApp::getWindow()); + DeviceControl::createImageViews(); + Texture::createColorResources(); + Texture::createDepthResources(); } // 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() { - vkWaitForFences(Global::device, 1, &inFlightFences[Global::currentFrame], + vkWaitForFences(DeviceControl::getDevice(), 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); - vkResetFences(Global::device, 1, &inFlightFences[Global::currentFrame]); + vkResetFences(DeviceControl::getDevice(), 1, &inFlightFences[currentFrame]); uint32_t imageIndex; - VkResult result = - vkAcquireNextImageKHR(Global::device, Global::swapChain, UINT64_MAX, - imageAvailableSemaphores[Global::currentFrame], - VK_NULL_HANDLE, &imageIndex); + VkResult result = vkAcquireNextImageKHR( + DeviceControl::getDevice(), DeviceControl::getSwapChain(), UINT64_MAX, + imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); if (result == VK_ERROR_OUT_OF_DATE_KHR) { recreateSwapChain(); return; @@ -57,36 +58,34 @@ void Render::drawFrame() { throw std::runtime_error("failed to acquire swap chain image!"); } - buffers_libs::Buffers::updateUniformBuffer(Global::currentFrame); + Buffers::updateUniformBuffer(currentFrame); - vkResetFences(Global::device, 1, &inFlightFences[Global::currentFrame]); + vkResetFences(DeviceControl::getDevice(), 1, &inFlightFences[currentFrame]); - vkResetCommandBuffer(Global::commandBuffers[Global::currentFrame], + vkResetCommandBuffer(Buffers::getCommandBuffers()[currentFrame], /*VkCommandBufferResetFlagBits*/ 0); - graphics_pipeline::Graphics::recordCommandBuffer( - Global::commandBuffers[Global::currentFrame], imageIndex); + Graphics::recordCommandBuffer(Buffers::getCommandBuffers()[currentFrame], + imageIndex); ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), - Global::commandBuffers[Global::currentFrame]); + Buffers::getCommandBuffers()[currentFrame]); VkSubmitInfo submitInfo{}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - VkSemaphore waitSemaphores[] = { - imageAvailableSemaphores[Global::currentFrame]}; + VkSemaphore waitSemaphores[] = {imageAvailableSemaphores[currentFrame]}; VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitDstStageMask = waitStages; submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &Global::commandBuffers[Global::currentFrame]; + submitInfo.pCommandBuffers = &Buffers::getCommandBuffers()[currentFrame]; - VkSemaphore signalSemaphores[] = { - renderFinishedSemaphores[Global::currentFrame]}; + VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[currentFrame]}; submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = signalSemaphores; - if (vkQueueSubmit(Global::graphicsQueue, 1, &submitInfo, - inFlightFences[Global::currentFrame]) != VK_SUCCESS) { + if (vkQueueSubmit(DeviceControl::getGraphicsQueue(), 1, &submitInfo, + inFlightFences[currentFrame]) != VK_SUCCESS) { throw std::runtime_error("failed to submit draw command buffer!"); } @@ -96,12 +95,12 @@ void Render::drawFrame() { presentInfo.waitSemaphoreCount = 1; presentInfo.pWaitSemaphores = signalSemaphores; - VkSwapchainKHR swapChains[] = {Global::swapChain}; + VkSwapchainKHR swapChains[] = {DeviceControl::getSwapChain()}; presentInfo.swapchainCount = 1; presentInfo.pSwapchains = swapChains; presentInfo.pImageIndices = &imageIndex; - result = vkQueuePresentKHR(Global::presentQueue, &presentInfo); + result = vkQueuePresentKHR(DeviceControl::getPresentQueue(), &presentInfo); if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || EntryApp::getInstance().getFramebufferResized()) { @@ -110,8 +109,7 @@ void Render::drawFrame() { } else if (result != VK_SUCCESS) { throw std::runtime_error("failed to present swap chain image!"); } - Global::currentFrame = - (Global::currentFrame + 1) % Global::MAX_FRAMES_IN_FLIGHT; + currentFrame = (currentFrame + 1) % Buffers::getMaxFramesInFlight(); } #pragma info @@ -139,9 +137,9 @@ void Render::drawFrame() { #pragma endinfo void Render::createSyncObject() { - imageAvailableSemaphores.resize(Global::MAX_FRAMES_IN_FLIGHT); - renderFinishedSemaphores.resize(Global::MAX_FRAMES_IN_FLIGHT); - inFlightFences.resize(Global::MAX_FRAMES_IN_FLIGHT); + imageAvailableSemaphores.resize(Buffers::getMaxFramesInFlight()); + renderFinishedSemaphores.resize(Buffers::getMaxFramesInFlight()); + inFlightFences.resize(Buffers::getMaxFramesInFlight()); VkSemaphoreCreateInfo semaphoreInfo{}; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; @@ -150,36 +148,42 @@ void Render::createSyncObject() { fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - for (size_t i = 0; i < Global::MAX_FRAMES_IN_FLIGHT; i++) { - if (vkCreateSemaphore(Global::device, &semaphoreInfo, nullptr, + for (size_t i = 0; i < Buffers::getMaxFramesInFlight(); i++) { + if (vkCreateSemaphore(DeviceControl::getDevice(), &semaphoreInfo, nullptr, &imageAvailableSemaphores[i]) != VK_SUCCESS || - vkCreateSemaphore(Global::device, &semaphoreInfo, nullptr, + vkCreateSemaphore(DeviceControl::getDevice(), &semaphoreInfo, nullptr, &renderFinishedSemaphores[i]) != VK_SUCCESS || - vkCreateFence(Global::device, &fenceInfo, nullptr, + vkCreateFence(DeviceControl::getDevice(), &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS) { throw std::runtime_error("Failed to create semaphores!"); } } } 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); + for (size_t i = 0; i < Buffers::getMaxFramesInFlight(); i++) { + vkDestroySemaphore(DeviceControl::getDevice(), renderFinishedSemaphores[i], + nullptr); + vkDestroySemaphore(DeviceControl::getDevice(), imageAvailableSemaphores[i], + nullptr); + vkDestroyFence(DeviceControl::getDevice(), inFlightFences[i], nullptr); } } void Render::cleanupSwapChain() { - vkDestroyImageView(Global::device, Global::colorImageView, nullptr); - vkDestroyImage(Global::device, Global::colorImage, nullptr); - vkFreeMemory(Global::device, Global::colorImageMemory, nullptr); - vkDestroyImageView(Global::device, Global::depthImageView, nullptr); - vkDestroyImage(Global::device, Global::depthImage, nullptr); - vkFreeMemory(Global::device, Global::depthImageMemory, nullptr); + vkDestroyImageView(DeviceControl::getDevice(), Texture::getColorImageView(), + nullptr); + vkDestroyImage(DeviceControl::getDevice(), Texture::getColorImage(), nullptr); + vkFreeMemory(DeviceControl::getDevice(), Texture::getColorImageMemory(), + nullptr); + vkDestroyImageView(DeviceControl::getDevice(), Texture::getDepthImageView(), + nullptr); + vkDestroyImage(DeviceControl::getDevice(), Texture::getDepthImage(), nullptr); + vkFreeMemory(DeviceControl::getDevice(), Texture::getDepthImageMemory(), + nullptr); - for (auto imageView : Global::swapChainImageViews) { - vkDestroyImageView(Global::device, imageView, nullptr); + for (auto imageView : DeviceControl::getSwapChainImageViews()) { + vkDestroyImageView(DeviceControl::getDevice(), imageView, nullptr); } - vkDestroySwapchainKHR(Global::device, Global::swapChain, nullptr); + vkDestroySwapchainKHR(DeviceControl::getDevice(), + DeviceControl::getSwapChain(), nullptr); } - -} // namespace render_present +uint32_t Render::getCurrentFrame() { return currentFrame; } diff --git a/src/graphics/render.h b/src/graphics/render.h index 9a13585..8cecdd8 100644 --- a/src/graphics/render.h +++ b/src/graphics/render.h @@ -1,7 +1,6 @@ #pragma once -#include "../global.h" -namespace render_present { +#include class Render { public: static void drawFrame(); @@ -9,5 +8,5 @@ public: static void destroyFenceSemaphores(); static void cleanupSwapChain(); static float getFloatBar(); + static uint32_t getCurrentFrame(); }; -} // namespace render_present diff --git a/src/graphics/texture.cpp b/src/graphics/texture.cpp index a18d53c..04027c3 100644 --- a/src/graphics/texture.cpp +++ b/src/graphics/texture.cpp @@ -1,5 +1,9 @@ -#define STB_IMAGE_IMPLEMENTATION +#include "../devicelibrary.h" +#include "buffers.h" #include "texture.h" +#include +#include +#define STB_IMAGE_IMPLEMENTATION #include uint32_t mipLevels; @@ -9,7 +13,19 @@ VkDeviceMemory textureImageMemory; VkPipelineStageFlags sourceStage; VkPipelineStageFlags destinationStage; -namespace texture_libs { +VkImageView textureImageView; +VkSampler textureSampler; + +VkImage colorImage; +VkImageView colorImageView; +VkDeviceMemory colorImageMemory; + +VkImage depthImage; +VkImageView depthImageView; +VkDeviceMemory depthImageMemory; + +std::string TEXTURE_PATH = "assets/textures/viking_room.png"; + void createImage(uint32_t width, uint32_t height, uint32_t mipLevels, VkSampleCountFlagBits sampleNum, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, @@ -33,26 +49,27 @@ void createImage(uint32_t width, uint32_t height, uint32_t mipLevels, imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; imageInfo.mipLevels = mipLevels; - if (vkCreateImage(Global::device, &imageInfo, nullptr, &image) != + if (vkCreateImage(DeviceControl::getDevice(), &imageInfo, nullptr, &image) != VK_SUCCESS) { throw std::runtime_error("failed to create image!"); } VkMemoryRequirements memRequirements; - vkGetImageMemoryRequirements(Global::device, image, &memRequirements); + vkGetImageMemoryRequirements(DeviceControl::getDevice(), image, + &memRequirements); VkMemoryAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocInfo.allocationSize = memRequirements.size; - allocInfo.memoryTypeIndex = buffers_libs::Buffers::findMemoryType( - memRequirements.memoryTypeBits, properties); + allocInfo.memoryTypeIndex = + Buffers::findMemoryType(memRequirements.memoryTypeBits, properties); - if (vkAllocateMemory(Global::device, &allocInfo, nullptr, &imageMemory) != - VK_SUCCESS) { + if (vkAllocateMemory(DeviceControl::getDevice(), &allocInfo, nullptr, + &imageMemory) != VK_SUCCESS) { throw std::runtime_error("failed to allocate image memory!"); } - vkBindImageMemory(Global::device, image, imageMemory, 0); + vkBindImageMemory(DeviceControl::getDevice(), image, imageMemory, 0); } VkCommandBuffer beginSingleTimeCommands() { @@ -61,11 +78,12 @@ VkCommandBuffer beginSingleTimeCommands() { VkCommandBufferAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandPool = Global::commandPool; + allocInfo.commandPool = Buffers::getCommandPool(); allocInfo.commandBufferCount = 1; VkCommandBuffer commandBuffer; - vkAllocateCommandBuffers(Global::device, &allocInfo, &commandBuffer); + vkAllocateCommandBuffers(DeviceControl::getDevice(), &allocInfo, + &commandBuffer); VkCommandBufferBeginInfo beginInfo{}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -85,21 +103,14 @@ void endSingleTimeCommands(VkCommandBuffer commandBuffer) { submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &commandBuffer; - vkQueueSubmit(Global::graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); - vkQueueWaitIdle(Global::graphicsQueue); + vkQueueSubmit(DeviceControl::getGraphicsQueue(), 1, &submitInfo, + VK_NULL_HANDLE); + vkQueueWaitIdle(DeviceControl::getGraphicsQueue()); - vkFreeCommandBuffers(Global::device, Global::commandPool, 1, &commandBuffer); + vkFreeCommandBuffers(DeviceControl::getDevice(), Buffers::getCommandPool(), 1, + &commandBuffer); } -void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) { - // Copy 1 buffer to another. - VkCommandBuffer commandBuffer = beginSingleTimeCommands(); - VkBufferCopy copyRegion{}; - copyRegion.size = size; - vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region); - - endSingleTimeCommands(commandBuffer); -} void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels) { @@ -173,7 +184,8 @@ VkFormat findSupportedFormat(const std::vector &candidates, VkFormatFeatureFlags features) { for (VkFormat format : candidates) { VkFormatProperties props; - vkGetPhysicalDeviceFormatProperties(Global::physicalDevice, format, &props); + vkGetPhysicalDeviceFormatProperties(DeviceControl::getPhysicalDevice(), + format, &props); // Do we support linear tiling? if (tiling == VK_IMAGE_TILING_LINEAR && @@ -195,8 +207,8 @@ void generateMipmaps(VkImage image, VkFormat imageFormat, int32_t textureWidth, int32_t textureHeight, uint32_t mipLevels) { // Check if image format supports linear blitting VkFormatProperties formatProperties; - vkGetPhysicalDeviceFormatProperties(Global::physicalDevice, imageFormat, - &formatProperties); + vkGetPhysicalDeviceFormatProperties(DeviceControl::getPhysicalDevice(), + imageFormat, &formatProperties); if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) { @@ -283,7 +295,7 @@ void Texture::createTextureImage() { // 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; - stbi_uc *pixels = stbi_load(Global::TEXTURE_PATH.c_str(), &textureWidth, + stbi_uc *pixels = stbi_load(TEXTURE_PATH.c_str(), &textureWidth, &textureHeight, &textureChannels, STBI_rgb_alpha); mipLevels = static_cast(std::floor( std::log2(std::max(textureWidth, textureHeight)))) + @@ -296,16 +308,16 @@ void Texture::createTextureImage() { } VkBuffer stagingBuffer; VkDeviceMemory 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); + 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); + vkMapMemory(DeviceControl::getDevice(), stagingBufferMemory, 0, imageSize, 0, + &data); memcpy(data, pixels, static_cast(imageSize)); - vkUnmapMemory(Global::device, stagingBufferMemory); + vkUnmapMemory(DeviceControl::getDevice(), stagingBufferMemory); stbi_image_free(pixels); @@ -323,8 +335,8 @@ void Texture::createTextureImage() { static_cast(textureWidth), static_cast(textureHeight)); - vkDestroyBuffer(Global::device, stagingBuffer, nullptr); - vkFreeMemory(Global::device, stagingBufferMemory, nullptr); + vkDestroyBuffer(DeviceControl::getDevice(), stagingBuffer, nullptr); + vkFreeMemory(DeviceControl::getDevice(), stagingBufferMemory, nullptr); generateMipmaps(textureImage, VK_FORMAT_R8G8B8A8_SRGB, textureWidth, textureHeight, mipLevels); @@ -332,9 +344,9 @@ void Texture::createTextureImage() { void Texture::createTextureImageView() { // Create a texture image view, which is a struct of information about the // image. - Global::textureImageView = device_libs::DeviceControl::createImageView( - textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT, - mipLevels); + textureImageView = + DeviceControl::createImageView(textureImage, VK_FORMAT_R8G8B8A8_SRGB, + VK_IMAGE_ASPECT_COLOR_BIT, mipLevels); } void Texture::createTextureSampler() { // Create a sampler to access and parse the texture object. @@ -352,7 +364,8 @@ void Texture::createTextureSampler() { samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; VkPhysicalDeviceProperties properties{}; - vkGetPhysicalDeviceProperties(Global::physicalDevice, &properties); + vkGetPhysicalDeviceProperties(DeviceControl::getPhysicalDevice(), + &properties); // Enable or Disable Anisotropy, and set the amount. samplerInfo.anisotropyEnable = VK_TRUE; samplerInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy; @@ -376,18 +389,18 @@ void Texture::createTextureSampler() { samplerInfo.minLod = 0.0f; samplerInfo.maxLod = VK_LOD_CLAMP_NONE; - if (vkCreateSampler(Global::device, &samplerInfo, nullptr, - &Global::textureSampler) != VK_SUCCESS) { + if (vkCreateSampler(DeviceControl::getDevice(), &samplerInfo, nullptr, + &textureSampler) != VK_SUCCESS) { throw std::runtime_error("failed to create texture sampler!"); } } void Texture::destroyTextureSampler() { - vkDestroySampler(Global::device, Global::textureSampler, nullptr); - vkDestroyImageView(Global::device, Global::textureImageView, nullptr); + vkDestroySampler(DeviceControl::getDevice(), textureSampler, nullptr); + vkDestroyImageView(DeviceControl::getDevice(), textureImageView, nullptr); } void Texture::destroyTextureImage() { - vkDestroyImage(Global::device, textureImage, nullptr); - vkFreeMemory(Global::device, textureImageMemory, nullptr); + vkDestroyImage(DeviceControl::getDevice(), textureImage, nullptr); + vkFreeMemory(DeviceControl::getDevice(), textureImageMemory, nullptr); } VkFormat Texture::findDepthFormat() { return findSupportedFormat( @@ -396,32 +409,42 @@ VkFormat Texture::findDepthFormat() { VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); } void Texture::createColorResources() { - VkFormat colorFormat = *device_libs::DeviceControl::getImageFormat(); - VkExtent2D swapChainExtent = device_libs::DeviceControl::getSwapChainExtent(); + VkFormat colorFormat = DeviceControl::getImageFormat(); + VkExtent2D swapChainExtent = DeviceControl::getSwapChainExtent(); createImage(swapChainExtent.width, swapChainExtent.height, 1, - Global::perPixelSampleCount, colorFormat, VK_IMAGE_TILING_OPTIMAL, + DeviceControl::getPerPixelSampleCount(), colorFormat, + VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, Global::colorImage, - Global::colorImageMemory); - Global::colorImageView = device_libs::DeviceControl::createImageView( - Global::colorImage, colorFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1); + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, colorImage, + colorImageMemory); + colorImageView = DeviceControl::createImageView(colorImage, colorFormat, + VK_IMAGE_ASPECT_COLOR_BIT, 1); } void Texture::createDepthResources() { VkFormat depthFormat = findDepthFormat(); - VkExtent2D swapChainExtent = device_libs::DeviceControl::getSwapChainExtent(); - createImage(swapChainExtent.width, swapChainExtent.height, 1, - Global::perPixelSampleCount, depthFormat, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, Global::depthImage, - Global::depthImageMemory); - Global::depthImageView = device_libs::DeviceControl::createImageView( - Global::depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1); + VkExtent2D swapChainExtent = DeviceControl::getSwapChainExtent(); + createImage( + swapChainExtent.width, swapChainExtent.height, 1, + DeviceControl::getPerPixelSampleCount(), depthFormat, + VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImage, depthImageMemory); + depthImageView = DeviceControl::createImageView(depthImage, depthFormat, + VK_IMAGE_ASPECT_DEPTH_BIT, 1); // Explicit transition from the layout of the image to the depth attachment is // unnecessary here, since that will be handled in the render pass! } // ---------------------------- Getters & Setters // ---------------------------------// uint32_t Texture::getMipLevels() { return mipLevels; } -} // namespace texture_libs +VkImageView &Texture::getTextureImageView() { return textureImageView; } +VkSampler &Texture::getTextureSampler() { return textureSampler; } + +VkImage &Texture::getColorImage() { return colorImage; } +VkImageView &Texture::getColorImageView() { return colorImageView; } +VkDeviceMemory &Texture::getColorImageMemory() { return colorImageMemory; } + +VkImage &Texture::getDepthImage() { return depthImage; } +VkImageView &Texture::getDepthImageView() { return depthImageView; } +VkDeviceMemory &Texture::getDepthImageMemory() { return depthImageMemory; } diff --git a/src/graphics/texture.h b/src/graphics/texture.h index 615fdde..940bc2e 100644 --- a/src/graphics/texture.h +++ b/src/graphics/texture.h @@ -1,10 +1,7 @@ #pragma once -#include "../devicelibrary.h" -#include "../global.h" -#include "buffers.h" +#define VK_NO_PROTOTYPES +#include "volk.h" #include - -namespace texture_libs { class Texture { public: static void createTextureImage(); @@ -17,5 +14,14 @@ public: static void createColorResources(); // ------------ Getters & Setters ------------ // static uint32_t getMipLevels(); + static VkImageView &getTextureImageView(); + static VkSampler &getTextureSampler(); + + static VkImage &getColorImage(); + static VkImageView &getColorImageView(); + static VkDeviceMemory &getColorImageMemory(); + + static VkImage &getDepthImage(); + static VkImageView &getDepthImageView(); + static VkDeviceMemory &getDepthImageMemory(); }; -} // namespace texture_libs diff --git a/src/main.cpp b/src/main.cpp index dc5daf4..d23a5f5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,5 @@ #include "entrypoint.h" +#include #define VOLK_IMPLEMENTATION int main() {