Major refactoring, removed the usage of the global header and replaced with getters and setters. Cleaned up headers and what is included.

This commit is contained in:
Lillian Salehi 2024-11-24 18:12:29 -06:00
parent d8c82d3351
commit f8bd7fdf3b
22 changed files with 708 additions and 706 deletions

View File

@ -3,6 +3,6 @@ Pos=60,60
Size=400,400 Size=400,400
[Window][Agnosia Debug] [Window][Agnosia Debug]
Pos=124,277 Pos=194,438
Size=583,225 Size=583,225

View File

@ -1,26 +1,30 @@
#include "agnosiaimgui.h" #include "agnosiaimgui.h"
#include "devicelibrary.h"
#include "entrypoint.h"
#include "graphics/buffers.h" #include "graphics/buffers.h"
#include "graphics/texture.h"
namespace agnosia_imgui { #include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_vulkan.h"
#include <stdexcept>
VkDescriptorPool imGuiDescriptorPool; VkDescriptorPool imGuiDescriptorPool;
void initWindow() { void initImGuiWindow() {
ImGui::DragFloat3("Object Position", buffers_libs::Buffers::getObjPos()); ImGui::DragFloat3("Object Position", Buffers::getObjPos());
ImGui::DragFloat3("Camera Position", buffers_libs::Buffers::getCamPos()); ImGui::DragFloat3("Camera Position", Buffers::getCamPos());
ImGui::DragFloat3("Center Position", buffers_libs::Buffers::getCenterPos()); ImGui::DragFloat3("Center Position", Buffers::getCenterPos());
ImGui::DragFloat3("Up Direction", buffers_libs::Buffers::getUpDir()); ImGui::DragFloat3("Up Direction", Buffers::getUpDir());
ImGui::DragFloat("Depth of Field", buffers_libs::Buffers::getDepthField(), ImGui::DragFloat("Depth of Field", &Buffers::getDepthField(), 0.1f, 1.0f,
0.1f, 1.0f, 180.0f, NULL, ImGuiSliderFlags_AlwaysClamp); 180.0f, NULL, ImGuiSliderFlags_AlwaysClamp);
ImGui::DragFloat2("Near and Far fields", ImGui::DragFloat2("Near and Far fields", Buffers::getDistanceField());
buffers_libs::Buffers::getDistanceField());
} }
void drawTabs() { void drawTabs() {
if (ImGui::BeginTabBar("MainTabBar", ImGuiTabBarFlags_Reorderable)) { if (ImGui::BeginTabBar("MainTabBar", ImGuiTabBarFlags_Reorderable)) {
if (ImGui::BeginTabItem("Transforms Control")) { if (ImGui::BeginTabItem("Transforms Control")) {
initWindow(); initImGuiWindow();
ImGui::EndTabItem(); ImGui::EndTabItem();
} }
@ -50,7 +54,7 @@ void Gui::drawImGui() {
void Gui::initImgui(VkInstance instance) { void Gui::initImgui(VkInstance instance) {
auto load_vk_func = [&](const char *fn) { auto load_vk_func = [&](const char *fn) {
if (auto proc = vkGetDeviceProcAddr(Global::device, fn)) if (auto proc = vkGetDeviceProcAddr(DeviceControl::getDevice(), fn))
return proc; return proc;
return vkGetInstanceProcAddr(instance, fn); return vkGetInstanceProcAddr(instance, fn);
}; };
@ -69,7 +73,7 @@ void Gui::initImgui(VkInstance instance) {
ImGui::StyleColorsDark(); ImGui::StyleColorsDark();
ImGui_ImplGlfw_InitForVulkan(Global::window, true); ImGui_ImplGlfw_InitForVulkan(EntryApp::getWindow(), true);
VkDescriptorPoolSize ImGuiPoolSizes[]{ VkDescriptorPoolSize ImGuiPoolSizes[]{
{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1}, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1},
@ -81,33 +85,33 @@ void Gui::initImgui(VkInstance instance) {
.poolSizeCount = 1, .poolSizeCount = 1,
.pPoolSizes = ImGuiPoolSizes, .pPoolSizes = ImGuiPoolSizes,
}; };
if (vkCreateDescriptorPool(Global::device, &ImGuiPoolInfo, nullptr, if (vkCreateDescriptorPool(DeviceControl::getDevice(), &ImGuiPoolInfo,
&imGuiDescriptorPool) != VK_SUCCESS) { nullptr, &imGuiDescriptorPool) != VK_SUCCESS) {
throw std::runtime_error("Failed to create ImGui descriptor pool!"); throw std::runtime_error("Failed to create ImGui descriptor pool!");
} }
VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo{ VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
.colorAttachmentCount = 1, .colorAttachmentCount = 1,
.pColorAttachmentFormats = device_libs::DeviceControl::getImageFormat(), .pColorAttachmentFormats = &DeviceControl::getImageFormat(),
.depthAttachmentFormat = texture_libs::Texture::findDepthFormat(), .depthAttachmentFormat = Texture::findDepthFormat(),
}; };
ImGui_ImplVulkan_InitInfo initInfo{ ImGui_ImplVulkan_InitInfo initInfo{
.Instance = instance, .Instance = instance,
.PhysicalDevice = Global::physicalDevice, .PhysicalDevice = DeviceControl::getPhysicalDevice(),
.Device = Global::device, .Device = DeviceControl::getDevice(),
.QueueFamily = Global::findQueueFamilies(Global::physicalDevice) .QueueFamily =
DeviceControl::findQueueFamilies(DeviceControl::getPhysicalDevice())
.graphicsFamily.value(), .graphicsFamily.value(),
.Queue = Global::graphicsQueue, .Queue = DeviceControl::getGraphicsQueue(),
.DescriptorPool = imGuiDescriptorPool, .DescriptorPool = imGuiDescriptorPool,
.MinImageCount = Global::MAX_FRAMES_IN_FLIGHT, .MinImageCount = Buffers::getMaxFramesInFlight(),
.ImageCount = Global::MAX_FRAMES_IN_FLIGHT, .ImageCount = Buffers::getMaxFramesInFlight(),
.MSAASamples = Global::perPixelSampleCount, .MSAASamples = DeviceControl::getPerPixelSampleCount(),
.UseDynamicRendering = true, .UseDynamicRendering = true,
.PipelineRenderingCreateInfo = pipelineRenderingCreateInfo, .PipelineRenderingCreateInfo = pipelineRenderingCreateInfo,
}; };
ImGui_ImplVulkan_Init(&initInfo); ImGui_ImplVulkan_Init(&initInfo);
} }
} // namespace agnosia_imgui

View File

@ -1,15 +1,8 @@
#pragma once #pragma once
#include "global.h" #include "volk.h"
#include "graphics/texture.h"
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_vulkan.h"
#include <map>
namespace agnosia_imgui {
class Gui { class Gui {
public: public:
static void drawImGui(); static void drawImGui();
static void initImgui(VkInstance instance); static void initImgui(VkInstance instance);
}; };
} // namespace agnosia_imgui

View File

@ -1,11 +1,22 @@
#include "devicelibrary.h" #include "devicelibrary.h"
#include "global.h" #include <algorithm>
#include <limits>
namespace device_libs { #include <set>
#include <stdexcept>
#include <string>
#include <vulkan/vulkan_core.h>
VkPhysicalDeviceProperties deviceProperties; VkPhysicalDeviceProperties deviceProperties;
VkDevice device;
VkSurfaceKHR surface;
VkQueue graphicsQueue;
VkQueue presentQueue;
VkPhysicalDevice physicalDevice;
VkSampleCountFlagBits perPixelSampleCount;
VkSwapchainKHR swapChain;
std::vector<VkImage> swapChainImages; std::vector<VkImage> swapChainImages;
std::vector<VkImageView> swapChainImageViews;
VkFormat swapChainImageFormat; VkFormat swapChainImageFormat;
VkExtent2D swapChainExtent; VkExtent2D swapChainExtent;
@ -18,6 +29,47 @@ const std::vector<const char *> deviceExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_KHR_DYNAMIC_RENDERING_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<VkQueueFamilyProperties> 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) { SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device) {
/* Swap chains are weird ngl, it's another one of those Vulkan platform /* 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) */ no fucking clue how it works though) */
SwapChainSupportDetails details; SwapChainSupportDetails details;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, Global::surface, vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface,
&details.capabilities); &details.capabilities);
uint32_t formatCount; uint32_t formatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(device, Global::surface, &formatCount, vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
nullptr);
if (formatCount != 0) { if (formatCount != 0) {
details.formats.resize(formatCount); details.formats.resize(formatCount);
vkGetPhysicalDeviceSurfaceFormatsKHR(device, Global::surface, &formatCount, vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount,
details.formats.data()); details.formats.data());
} }
uint32_t presentModeCount; uint32_t presentModeCount;
vkGetPhysicalDeviceSurfacePresentModesKHR( vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount,
device, Global::surface, &presentModeCount, details.presentModes.data()); details.presentModes.data());
if (presentModeCount != 0) { if (presentModeCount != 0) {
details.presentModes.resize(presentModeCount); details.presentModes.resize(presentModeCount);
vkGetPhysicalDeviceSurfacePresentModesKHR(device, Global::surface, vkGetPhysicalDeviceSurfacePresentModesKHR(
&presentModeCount, device, surface, &presentModeCount, details.presentModes.data());
details.presentModes.data());
} }
return details; return details;
@ -88,7 +138,8 @@ bool isDeviceSuitable(VkPhysicalDevice device) {
// We need to find a device that supports graphical operations, or else we // 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 // 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! // 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 extensionSupported = checkDeviceExtensionSupport(device);
bool swapChainAdequate = false; bool swapChainAdequate = false;
@ -167,7 +218,7 @@ VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities,
VkSampleCountFlagBits getMaxUsableSampleCount() { VkSampleCountFlagBits getMaxUsableSampleCount() {
VkPhysicalDeviceProperties physicalDeviceProps; VkPhysicalDeviceProperties physicalDeviceProps;
VkSampleCountFlags maxCounts; VkSampleCountFlags maxCounts;
vkGetPhysicalDeviceProperties(Global::physicalDevice, &physicalDeviceProps); vkGetPhysicalDeviceProperties(physicalDevice, &physicalDeviceProps);
VkSampleCountFlags counts = VkSampleCountFlags counts =
physicalDeviceProps.limits.framebufferColorSampleCounts & physicalDeviceProps.limits.framebufferColorSampleCounts &
@ -210,20 +261,20 @@ void DeviceControl::pickPhysicalDevice(VkInstance &instance) {
if (isDeviceSuitable(device)) { if (isDeviceSuitable(device)) {
// Once we have buttons or such, maybe ask the user or write a config file // Once we have buttons or such, maybe ask the user or write a config file
// for which GPU to use? // for which GPU to use?
Global::physicalDevice = device; physicalDevice = device;
Global::perPixelSampleCount = getMaxUsableSampleCount(); perPixelSampleCount = getMaxUsableSampleCount();
break; break;
} }
} }
if (Global::physicalDevice == VK_NULL_HANDLE) { if (physicalDevice == VK_NULL_HANDLE) {
throw std::runtime_error("Failed to find a suitable GPU!"); throw std::runtime_error("Failed to find a suitable GPU!");
} }
} }
void DeviceControl::destroySurface(VkInstance &instance) { void DeviceControl::destroySurface(VkInstance &instance) {
vkDestroySurfaceKHR(instance, Global::surface, nullptr); vkDestroySurfaceKHR(instance, surface, nullptr);
} }
void DeviceControl::createSurface(VkInstance &instance, GLFWwindow *window) { void DeviceControl::createSurface(VkInstance &instance, GLFWwindow *window) {
if (glfwCreateWindowSurface(instance, window, nullptr, &Global::surface) != if (glfwCreateWindowSurface(instance, window, nullptr, &surface) !=
VK_SUCCESS) { VK_SUCCESS) {
throw std::runtime_error("Failed to create window surface!!"); 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 // 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 // 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! // queueFamilies and sorting them by indices to fill the queue at the end!
Global::QueueFamilyIndices indices = QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
Global::findQueueFamilies(Global::physicalDevice);
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos; std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
std::set<uint32_t> uniqueQueueFamilies = {indices.graphicsFamily.value(), std::set<uint32_t> uniqueQueueFamilies = {indices.graphicsFamily.value(),
@ -278,18 +328,16 @@ void DeviceControl::createLogicalDevice() {
static_cast<uint32_t>(deviceExtensions.size()); static_cast<uint32_t>(deviceExtensions.size());
createDeviceInfo.ppEnabledExtensionNames = deviceExtensions.data(); createDeviceInfo.ppEnabledExtensionNames = deviceExtensions.data();
if (vkCreateDevice(Global::physicalDevice, &createDeviceInfo, nullptr, if (vkCreateDevice(physicalDevice, &createDeviceInfo, nullptr, &device) !=
&Global::device) != VK_SUCCESS) { VK_SUCCESS) {
throw std::runtime_error("Failed to create logical device"); throw std::runtime_error("Failed to create logical device");
} }
vkGetDeviceQueue(Global::device, indices.graphicsFamily.value(), 0, vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue);
&Global::graphicsQueue); vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue);
vkGetDeviceQueue(Global::device, indices.presentFamily.value(), 0,
&Global::presentQueue);
} }
void DeviceControl::createSwapChain(GLFWwindow *window) { void DeviceControl::createSwapChain(GLFWwindow *window) {
SwapChainSupportDetails swapChainSupport = SwapChainSupportDetails swapChainSupport =
querySwapChainSupport(Global::physicalDevice); querySwapChainSupport(physicalDevice);
VkSurfaceFormatKHR surfaceFormat = VkSurfaceFormatKHR surfaceFormat =
chooseSwapSurfaceFormat(swapChainSupport.formats); chooseSwapSurfaceFormat(swapChainSupport.formats);
@ -311,7 +359,7 @@ void DeviceControl::createSwapChain(GLFWwindow *window) {
VkSwapchainCreateInfoKHR createSwapChainInfo{}; VkSwapchainCreateInfoKHR createSwapChainInfo{};
createSwapChainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; createSwapChainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
createSwapChainInfo.surface = Global::surface; createSwapChainInfo.surface = surface;
createSwapChainInfo.minImageCount = imageCount; createSwapChainInfo.minImageCount = imageCount;
createSwapChainInfo.imageFormat = surfaceFormat.format; createSwapChainInfo.imageFormat = surfaceFormat.format;
createSwapChainInfo.imageColorSpace = surfaceFormat.colorSpace; 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 // This handles swap chain images across multiple queue families, ie, if the
// graphics queue family is different from the present queue // graphics queue family is different from the present queue
Global::QueueFamilyIndices indices = QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
Global::findQueueFamilies(Global::physicalDevice);
uint32_t queueFamilyIndices[] = {indices.graphicsFamily.value(), uint32_t queueFamilyIndices[] = {indices.graphicsFamily.value(),
indices.presentFamily.value()}; indices.presentFamily.value()};
// Usage across multiple queue families without explicit transfer of ownership // 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. // it and reference the old one specified here, will revisit in a few days.
// createSwapChainInfo.oldSwapchain = VK_NULL_HANDLE; // createSwapChainInfo.oldSwapchain = VK_NULL_HANDLE;
if (vkCreateSwapchainKHR(Global::device, &createSwapChainInfo, nullptr, if (vkCreateSwapchainKHR(device, &createSwapChainInfo, nullptr, &swapChain) !=
&Global::swapChain) != VK_SUCCESS) { VK_SUCCESS) {
throw std::runtime_error("Failed to create the swap chain!!"); throw std::runtime_error("Failed to create the swap chain!!");
} }
vkGetSwapchainImagesKHR(Global::device, Global::swapChain, &imageCount, vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr);
nullptr);
swapChainImages.resize(imageCount); swapChainImages.resize(imageCount);
vkGetSwapchainImagesKHR(Global::device, Global::swapChain, &imageCount, vkGetSwapchainImagesKHR(device, swapChain, &imageCount,
swapChainImages.data()); swapChainImages.data());
swapChainImageFormat = surfaceFormat.format; swapChainImageFormat = surfaceFormat.format;
swapChainExtent = extent; swapChainExtent = extent;
} }
void DeviceControl::destroySwapChain() { void DeviceControl::destroySwapChain() {
vkDestroySwapchainKHR(Global::device, Global::swapChain, nullptr); vkDestroySwapchainKHR(device, swapChain, nullptr);
} }
VkImageView DeviceControl::createImageView(VkImage image, VkFormat format, VkImageView DeviceControl::createImageView(VkImage image, VkFormat format,
VkImageAspectFlags flags, VkImageAspectFlags flags,
@ -391,33 +437,43 @@ VkImageView DeviceControl::createImageView(VkImage image, VkFormat format,
viewInfo.subresourceRange.levelCount = mipLevels; viewInfo.subresourceRange.levelCount = mipLevels;
VkImageView imageView; VkImageView imageView;
if (vkCreateImageView(Global::device, &viewInfo, nullptr, &imageView) != if (vkCreateImageView(device, &viewInfo, nullptr, &imageView) != VK_SUCCESS) {
VK_SUCCESS) {
throw std::runtime_error("failed to create image view!"); throw std::runtime_error("failed to create image view!");
} }
return imageView; return imageView;
} }
void DeviceControl::createImageViews() { void DeviceControl::createImageViews() {
Global::swapChainImageViews.resize(swapChainImages.size()); swapChainImageViews.resize(swapChainImages.size());
for (uint32_t i = 0; i < swapChainImages.size(); i++) { 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); swapChainImages[i], swapChainImageFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1);
} }
} }
void DeviceControl::destroyImageViews() { void DeviceControl::destroyImageViews() {
for (auto imageView : Global::swapChainImageViews) { for (auto imageView : swapChainImageViews) {
vkDestroyImageView(Global::device, imageView, nullptr); vkDestroyImageView(device, imageView, nullptr);
} }
} }
// --------------------------------------- Getters & Setters // --------------------------------------- Getters & Setters
// ------------------------------------------ // // ------------------------------------------ //
VkFormat *DeviceControl::getImageFormat() { return &swapChainImageFormat; } VkFormat &DeviceControl::getImageFormat() { return swapChainImageFormat; }
VkExtent2D DeviceControl::getSwapChainExtent() { return swapChainExtent; } VkSwapchainKHR &DeviceControl::getSwapChain() { return swapChain; }
std::vector<VkImage> DeviceControl::getSwapChainImages() { VkExtent2D &DeviceControl::getSwapChainExtent() { return swapChainExtent; }
std::vector<VkImage> &DeviceControl::getSwapChainImages() {
return swapChainImages; return swapChainImages;
} }
} // namespace device_libs std::vector<VkImageView> &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; }

View File

@ -1,31 +1,50 @@
#pragma once #pragma once
#include "global.h" #define VK_NO_PROTOTYPES
#include <algorithm> #include "volk.h"
#include <limits> #include <optional>
#include <set> #define GLFW_INCLUDE_VULKAN
#include <string> #include <GLFW/glfw3.h>
#include <vector>
namespace device_libs {
class DeviceControl { class DeviceControl {
public: 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<uint32_t> graphicsFamily;
std::optional<uint32_t> presentFamily;
bool isComplete() {
return graphicsFamily.has_value() && presentFamily.has_value();
}
};
static void pickPhysicalDevice(VkInstance &instance); static void pickPhysicalDevice(VkInstance &instance);
static void createLogicalDevice(); static void createLogicalDevice();
static void createSurface(VkInstance &instance, GLFWwindow *window); static void createSurface(VkInstance &instance, GLFWwindow *window);
static void destroySurface(VkInstance &instance); static void destroySurface(VkInstance &instance);
static void createSwapChain(GLFWwindow *window); static void createSwapChain(GLFWwindow *window);
static void destroySwapChain(); static void destroySwapChain();
static VkImageView createImageView(VkImage image, VkFormat format, VkImageAspectFlags flags, uint32_t mipLevels); static VkImageView createImageView(VkImage image, VkFormat format,
VkImageAspectFlags flags,
uint32_t mipLevels);
static void createImageViews(); static void createImageViews();
static void destroyImageViews(); static void destroyImageViews();
static void createCommandPool(); static void createCommandPool();
static void destroyCommandPool(); static void destroyCommandPool();
static QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device);
// ---------- Getters & Setters ----------- // // ---------- Getters & Setters ----------- //
static VkFormat* getImageFormat(); static VkFormat &getImageFormat();
static VkExtent2D getSwapChainExtent(); static VkExtent2D &getSwapChainExtent();
static std::vector<VkImage> getSwapChainImages(); static std::vector<VkImage> &getSwapChainImages();
static std::vector<VkFramebuffer> getSwapChainFramebuffers(); static std::vector<VkFramebuffer> &getSwapChainFramebuffers();
static VkDevice &getDevice();
static VkSurfaceKHR &getSurface();
static VkQueue &getGraphicsQueue();
static VkQueue &getPresentQueue();
static VkPhysicalDevice &getPhysicalDevice();
static VkSampleCountFlagBits &getPerPixelSampleCount();
static std::vector<VkImageView> &getSwapChainImageViews();
static VkSwapchainKHR &getSwapChain();
}; };
}

View File

@ -1,13 +1,26 @@
#include "agnosiaimgui.h" #include "agnosiaimgui.h"
#include "devicelibrary.h"
#include "entrypoint.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" #include "graphics/texture.h"
#define VK_NO_PROTOTYPES
#include "volk.h"
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#include "imgui.h" #include "imgui.h"
#include "imgui_impl_glfw.h" #include "imgui_impl_glfw.h"
#include "imgui_impl_vulkan.h" #include "imgui_impl_vulkan.h"
#include <stdexcept>
VkInstance vulkaninstance; VkInstance vulkaninstance;
GLFWwindow *window;
const uint32_t WIDTH = 800;
const uint32_t HEIGHT = 600;
// Getters and Setters! // Getters and Setters!
void EntryApp::setFramebufferResized(bool setter) { void EntryApp::setFramebufferResized(bool setter) {
framebufferResized = setter; framebufferResized = setter;
@ -25,10 +38,9 @@ void initWindow() {
glfwInit(); glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
// Settings for the window are set, create window reference. // Settings for the window are set, create window reference.
Global::window = glfwCreateWindow(Global::WIDTH, Global::HEIGHT, window = glfwCreateWindow(WIDTH, HEIGHT, "Trimgles :o", nullptr, nullptr);
"Trimgles :o", nullptr, nullptr); glfwSetWindowUserPointer(window, &EntryApp::getInstance());
glfwSetWindowUserPointer(Global::window, &EntryApp::getInstance()); glfwSetFramebufferSizeCallback(window, framebufferResizeCallback);
glfwSetFramebufferSizeCallback(Global::window, framebufferResizeCallback);
} }
void createInstance() { void createInstance() {
@ -84,62 +96,62 @@ void initVulkan() {
// Initialize vulkan and set up pipeline. // Initialize vulkan and set up pipeline.
createInstance(); createInstance();
volkLoadInstance(vulkaninstance); volkLoadInstance(vulkaninstance);
device_libs::DeviceControl::createSurface(vulkaninstance, Global::window); DeviceControl::createSurface(vulkaninstance, window);
device_libs::DeviceControl::pickPhysicalDevice(vulkaninstance); DeviceControl::pickPhysicalDevice(vulkaninstance);
device_libs::DeviceControl::createLogicalDevice(); DeviceControl::createLogicalDevice();
volkLoadDevice(Global::device); volkLoadDevice(DeviceControl::getDevice());
device_libs::DeviceControl::createSwapChain(Global::window); DeviceControl::createSwapChain(window);
device_libs::DeviceControl::createImageViews(); DeviceControl::createImageViews();
buffers_libs::Buffers::createDescriptorSetLayout(); Buffers::createDescriptorSetLayout();
graphics_pipeline::Graphics::createGraphicsPipeline(); Graphics::createGraphicsPipeline();
graphics_pipeline::Graphics::createCommandPool(); Graphics::createCommandPool();
texture_libs::Texture::createColorResources(); Texture::createColorResources();
texture_libs::Texture::createDepthResources(); Texture::createDepthResources();
texture_libs::Texture::createTextureImage(); Texture::createTextureImage();
texture_libs::Texture::createTextureImageView(); Texture::createTextureImageView();
texture_libs::Texture::createTextureSampler(); Texture::createTextureSampler();
modellib::Model::loadModel(); Model::loadModel();
buffers_libs::Buffers::createVertexBuffer(); Buffers::createVertexBuffer();
buffers_libs::Buffers::createIndexBuffer(); Buffers::createIndexBuffer();
buffers_libs::Buffers::createUniformBuffers(); Buffers::createUniformBuffers();
buffers_libs::Buffers::createDescriptorPool(); Buffers::createDescriptorPool();
buffers_libs::Buffers::createDescriptorSets(); Buffers::createDescriptorSets();
graphics_pipeline::Graphics::createCommandBuffer(); Graphics::createCommandBuffer();
render_present::Render::createSyncObject(); Render::createSyncObject();
agnosia_imgui::Gui::initImgui(vulkaninstance); Gui::initImgui(vulkaninstance);
} }
void mainLoop() { void mainLoop() {
while (!glfwWindowShouldClose(Global::window)) { while (!glfwWindowShouldClose(window)) {
glfwPollEvents(); glfwPollEvents();
agnosia_imgui::Gui::drawImGui(); Gui::drawImGui();
render_present::Render::drawFrame(); Render::drawFrame();
} }
vkDeviceWaitIdle(Global::device); vkDeviceWaitIdle(DeviceControl::getDevice());
} }
void cleanup() { void cleanup() {
render_present::Render::cleanupSwapChain(); Render::cleanupSwapChain();
graphics_pipeline::Graphics::destroyGraphicsPipeline(); Graphics::destroyGraphicsPipeline();
buffers_libs::Buffers::destroyUniformBuffer(); Buffers::destroyUniformBuffer();
buffers_libs::Buffers::destroyDescriptorPool(); Buffers::destroyDescriptorPool();
texture_libs::Texture::destroyTextureSampler(); Texture::destroyTextureSampler();
texture_libs::Texture::destroyTextureImage(); Texture::destroyTextureImage();
vkDestroyDescriptorSetLayout(Global::device, Global::descriptorSetLayout, vkDestroyDescriptorSetLayout(DeviceControl::getDevice(),
nullptr); Buffers::getDescriptorSetLayout(), nullptr);
buffers_libs::Buffers::destroyBuffers(); Buffers::destroyBuffers();
render_present::Render::destroyFenceSemaphores(); Render::destroyFenceSemaphores();
graphics_pipeline::Graphics::destroyCommandPool(); Graphics::destroyCommandPool();
ImGui_ImplVulkan_Shutdown(); ImGui_ImplVulkan_Shutdown();
ImGui_ImplGlfw_Shutdown(); ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext(); ImGui::DestroyContext();
vkDestroyDevice(Global::device, nullptr); vkDestroyDevice(DeviceControl::getDevice(), nullptr);
device_libs::DeviceControl::destroySurface(vulkaninstance); DeviceControl::destroySurface(vulkaninstance);
vkDestroyInstance(vulkaninstance, nullptr); vkDestroyInstance(vulkaninstance, nullptr);
glfwDestroyWindow(Global::window); glfwDestroyWindow(window);
glfwTerminate(); glfwTerminate();
} }
@ -152,7 +164,7 @@ EntryApp::EntryApp() : initialized(false), framebufferResized(false) {}
void EntryApp::initialize() { initialized = true; } void EntryApp::initialize() { initialized = true; }
bool EntryApp::isInitialized() const { return initialized; } bool EntryApp::isInitialized() const { return initialized; }
GLFWwindow *EntryApp::getWindow() { return window; }
void EntryApp::run() { void EntryApp::run() {
initWindow(); initWindow();
initVulkan(); initVulkan();

View File

@ -1,10 +1,6 @@
#pragma once #pragma once
#include "global.h"
#include "graphics/graphicspipeline.h"
#include "graphics/model.h"
#include "graphics/render.h"
#include "graphics/texture.h"
#include <GLFW/glfw3.h>
class EntryApp { class EntryApp {
public: public:
static EntryApp &getInstance(); static EntryApp &getInstance();
@ -13,6 +9,7 @@ public:
void run(); void run();
void setFramebufferResized(bool frame); void setFramebufferResized(bool frame);
bool getFramebufferResized() const; bool getFramebufferResized() const;
static GLFWwindow *getWindow();
private: private:
EntryApp(); EntryApp();

View File

@ -1,71 +0,0 @@
#include "global.h"
namespace Global {
VkSurfaceKHR surface;
VkDevice device;
VkPhysicalDevice physicalDevice;
VkSampleCountFlagBits perPixelSampleCount;
VkSwapchainKHR swapChain;
VkCommandPool commandPool;
std::vector<VkCommandBuffer> commandBuffers;
VkQueue graphicsQueue;
VkQueue presentQueue;
GLFWwindow *window;
VkDescriptorSetLayout descriptorSetLayout;
std::vector<VkDescriptorSet> descriptorSets;
uint32_t currentFrame = 0;
VkImageView textureImageView;
VkSampler textureSampler;
VkImageView colorImageView;
VkImage colorImage;
VkDeviceMemory colorImageMemory;
VkImageView depthImageView;
VkImage depthImage;
VkDeviceMemory depthImageMemory;
std::vector<VkImageView> swapChainImageViews;
std::vector<Vertex> vertices;
// Index buffer definition, showing which points to reuse.
std::vector<uint32_t> 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<VkQueueFamilyProperties> 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

View File

@ -1,129 +0,0 @@
#pragma once
#define VK_NO_PROTOTYPES
#include "volk.h"
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp>
#include <glm/detail/qualifier.hpp>
#include <glm/ext/vector_float2.hpp>
#include <glm/ext/vector_float3.hpp>
#include <glm/fwd.hpp>
#include <glm/gtc/matrix_transform.hpp>
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#include <array>
#include <cstdint>
#include <iostream>
#include <optional>
#include <ostream>
#include <vector>
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<VkCommandBuffer> commandBuffers;
extern VkQueue graphicsQueue;
extern VkQueue presentQueue;
extern GLFWwindow *window;
extern VkSurfaceKHR surface;
extern uint32_t currentFrame;
extern std::vector<VkDescriptorSet> 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<VkImageView> 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<VkVertexInputAttributeDescription, 3>
getAttributeDescriptions() {
std::array<VkVertexInputAttributeDescription, 3> 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<Vertex> vertices;
// Index buffer definition, showing which points to reuse.
extern std::vector<uint32_t> 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<uint32_t> graphicsFamily;
std::optional<uint32_t> presentFamily;
bool isComplete() {
return graphicsFamily.has_value() && presentFamily.has_value();
}
};
Global::QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device);
} // namespace Global

View File

@ -1,12 +1,27 @@
#include "../devicelibrary.h"
#include "buffers.h" #include "buffers.h"
#include <glm/fwd.hpp> #include "texture.h"
#include <chrono>
#include <cstdint>
#include <cstring>
#include <glm/ext/matrix_clip_space.hpp>
#include <glm/ext/matrix_transform.hpp>
VkBuffer vertexBuffer; VkBuffer vertexBuffer;
VkDeviceMemory vertexBufferMemory; VkDeviceMemory vertexBufferMemory;
VkBuffer indexBuffer; VkBuffer indexBuffer;
VkDeviceMemory indexBufferMemory; VkDeviceMemory indexBufferMemory;
VkDescriptorPool descriptorPool;
std::vector<Buffers::Vertex> vertices;
// Index buffer definition, showing which points to reuse.
std::vector<uint32_t> indices;
VkDescriptorPool descriptorPool;
VkDescriptorSetLayout descriptorSetLayout;
std::vector<VkDescriptorSet> descriptorSets;
VkCommandPool commandPool;
std::vector<VkCommandBuffer> commandBuffers;
std::vector<VkBuffer> uniformBuffers; std::vector<VkBuffer> uniformBuffers;
std::vector<VkDeviceMemory> uniformBuffersMemory; std::vector<VkDeviceMemory> uniformBuffersMemory;
std::vector<void *> uniformBuffersMapped; std::vector<void *> uniformBuffersMapped;
@ -18,14 +33,22 @@ float upDir[4] = {0.0f, 0.0f, 1.0f, 0.44f};
float depthField = 45.0f; float depthField = 45.0f;
float distanceField[2] = {0.1f, 100.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, uint32_t Buffers::findMemoryType(uint32_t typeFilter,
VkMemoryPropertyFlags properties) { VkMemoryPropertyFlags properties) {
// Graphics cards offer different types of memory to allocate from, here we // 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 // query to find the right type of memory for our needs. Query the available
// types of memory to iterate over. // types of memory to iterate over.
VkPhysicalDeviceMemoryProperties memProperties; 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 // 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. // case, HOST_VISIBLE and HOST_COHERENT. These will be explained shortly.
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) { for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
@ -41,11 +64,12 @@ void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {
VkCommandBufferAllocateInfo allocInfo{}; VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandPool = Global::commandPool; allocInfo.commandPool = commandPool;
allocInfo.commandBufferCount = 1; allocInfo.commandBufferCount = 1;
VkCommandBuffer commandBuffer; VkCommandBuffer commandBuffer;
vkAllocateCommandBuffers(Global::device, &allocInfo, &commandBuffer); vkAllocateCommandBuffers(DeviceControl::getDevice(), &allocInfo,
&commandBuffer);
VkCommandBufferBeginInfo beginInfo{}; VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 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.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer; submitInfo.pCommandBuffers = &commandBuffer;
vkQueueSubmit(Global::graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); vkQueueSubmit(DeviceControl::getGraphicsQueue(), 1, &submitInfo,
vkQueueWaitIdle(Global::graphicsQueue); 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, void Buffers::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage,
@ -79,13 +105,14 @@ void Buffers::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage,
bufferInfo.usage = usage; bufferInfo.usage = usage;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (vkCreateBuffer(Global::device, &bufferInfo, nullptr, &buffer) != if (vkCreateBuffer(DeviceControl::getDevice(), &bufferInfo, nullptr,
VK_SUCCESS) { &buffer) != VK_SUCCESS) {
throw std::runtime_error("failed to create buffer!"); throw std::runtime_error("failed to create buffer!");
} }
VkMemoryRequirements memRequirements; VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(Global::device, buffer, &memRequirements); vkGetBufferMemoryRequirements(DeviceControl::getDevice(), buffer,
&memRequirements);
VkMemoryAllocateInfo allocInfo{}; VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
@ -93,16 +120,16 @@ void Buffers::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage,
allocInfo.memoryTypeIndex = allocInfo.memoryTypeIndex =
findMemoryType(memRequirements.memoryTypeBits, properties); findMemoryType(memRequirements.memoryTypeBits, properties);
if (vkAllocateMemory(Global::device, &allocInfo, nullptr, &bufferMemory) != if (vkAllocateMemory(DeviceControl::getDevice(), &allocInfo, nullptr,
VK_SUCCESS) { &bufferMemory) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate buffer memory!"); throw std::runtime_error("failed to allocate buffer memory!");
} }
vkBindBufferMemory(Global::device, buffer, bufferMemory, 0); vkBindBufferMemory(DeviceControl::getDevice(), buffer, bufferMemory, 0);
} }
void Buffers::createIndexBuffer() { void Buffers::createIndexBuffer() {
VkDeviceSize bufferSize = sizeof(Global::indices[0]) * Global::indices.size(); VkDeviceSize bufferSize = sizeof(indices[0]) * indices.size();
VkBuffer stagingBuffer; VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory; VkDeviceMemory stagingBufferMemory;
@ -113,10 +140,11 @@ void Buffers::createIndexBuffer() {
stagingBuffer, stagingBufferMemory); stagingBuffer, stagingBufferMemory);
void *data; void *data;
vkMapMemory(Global::device, stagingBufferMemory, 0, bufferSize, 0, &data); vkMapMemory(DeviceControl::getDevice(), stagingBufferMemory, 0, bufferSize, 0,
memcpy(data, Global::indices.data(), (size_t)bufferSize); &data);
memcpy(data, indices.data(), (size_t)bufferSize);
vkUnmapMemory(Global::device, stagingBufferMemory); vkUnmapMemory(DeviceControl::getDevice(), stagingBufferMemory);
createBuffer( createBuffer(
bufferSize, bufferSize,
@ -125,8 +153,8 @@ void Buffers::createIndexBuffer() {
copyBuffer(stagingBuffer, indexBuffer, bufferSize); copyBuffer(stagingBuffer, indexBuffer, bufferSize);
vkDestroyBuffer(Global::device, stagingBuffer, nullptr); vkDestroyBuffer(DeviceControl::getDevice(), stagingBuffer, nullptr);
vkFreeMemory(Global::device, stagingBufferMemory, nullptr); vkFreeMemory(DeviceControl::getDevice(), stagingBufferMemory, nullptr);
} }
void Buffers::createVertexBuffer() { void Buffers::createVertexBuffer() {
// Create a Vertex Buffer to hold the vertex information in memory so it // 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 // 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 // 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. // the graphics queue uses this buffer, so we make it exclusive.
VkDeviceSize bufferSize = VkDeviceSize bufferSize = sizeof(vertices[0]) * vertices.size();
sizeof(Global::vertices[0]) * Global::vertices.size();
VkBuffer stagingBuffer; VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory; VkDeviceMemory stagingBufferMemory;
@ -147,9 +174,10 @@ void Buffers::createVertexBuffer() {
stagingBuffer, stagingBufferMemory); stagingBuffer, stagingBufferMemory);
void *data; void *data;
vkMapMemory(Global::device, stagingBufferMemory, 0, bufferSize, 0, &data); vkMapMemory(DeviceControl::getDevice(), stagingBufferMemory, 0, bufferSize, 0,
memcpy(data, Global::vertices.data(), (size_t)bufferSize); &data);
vkUnmapMemory(Global::device, stagingBufferMemory); memcpy(data, vertices.data(), (size_t)bufferSize);
vkUnmapMemory(DeviceControl::getDevice(), stagingBufferMemory);
createBuffer( createBuffer(
bufferSize, bufferSize,
@ -158,19 +186,17 @@ void Buffers::createVertexBuffer() {
copyBuffer(stagingBuffer, vertexBuffer, bufferSize); copyBuffer(stagingBuffer, vertexBuffer, bufferSize);
vkDestroyBuffer(Global::device, stagingBuffer, nullptr); vkDestroyBuffer(DeviceControl::getDevice(), stagingBuffer, nullptr);
vkFreeMemory(Global::device, stagingBufferMemory, nullptr); vkFreeMemory(DeviceControl::getDevice(), stagingBufferMemory, nullptr);
} }
void Buffers::destroyBuffers() { void Buffers::destroyBuffers() {
vkDestroyBuffer(Global::device, indexBuffer, nullptr); vkDestroyBuffer(DeviceControl::getDevice(), indexBuffer, nullptr);
vkFreeMemory(Global::device, indexBufferMemory, nullptr); vkFreeMemory(DeviceControl::getDevice(), indexBufferMemory, nullptr);
vkDestroyBuffer(Global::device, vertexBuffer, nullptr); vkDestroyBuffer(DeviceControl::getDevice(), vertexBuffer, nullptr);
vkFreeMemory(Global::device, vertexBufferMemory, nullptr); vkFreeMemory(DeviceControl::getDevice(), vertexBufferMemory, nullptr);
} }
VkBuffer Buffers::getVertexBuffer() { return vertexBuffer; }
VkBuffer Buffers::getIndexBuffer() { return indexBuffer; }
// ------------------------------ Uniform Buffer Setup // ------------------------------ Uniform Buffer Setup
// -------------------------------- // // -------------------------------- //
@ -204,8 +230,9 @@ void Buffers::createDescriptorSetLayout() {
layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size()); layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
layoutInfo.pBindings = bindings.data(); layoutInfo.pBindings = bindings.data();
if (vkCreateDescriptorSetLayout(Global::device, &layoutInfo, nullptr, if (vkCreateDescriptorSetLayout(DeviceControl::getDevice(), &layoutInfo,
&Global::descriptorSetLayout) != VK_SUCCESS) { nullptr,
&descriptorSetLayout) != VK_SUCCESS) {
throw std::runtime_error("Failed to create descriptor set layout!"); 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 // later. This stays mapped to memory for the applications lifetime. This
// technique is called "persistent mapping", not having to map the buffer // technique is called "persistent mapping", not having to map the buffer
// every time we need to update it increases performance, though not free // 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); uniformBuffers.resize(MAX_FRAMES_IN_FLIGHT);
uniformBuffersMemory.resize(Global::MAX_FRAMES_IN_FLIGHT); uniformBuffersMemory.resize(MAX_FRAMES_IN_FLIGHT);
uniformBuffersMapped.resize(Global::MAX_FRAMES_IN_FLIGHT); uniformBuffersMapped.resize(MAX_FRAMES_IN_FLIGHT);
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
for (size_t i = 0; i < Global::MAX_FRAMES_IN_FLIGHT; i++) {
createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
uniformBuffers[i], uniformBuffersMemory[i]); uniformBuffers[i], uniformBuffersMemory[i]);
vkMapMemory(Global::device, uniformBuffersMemory[i], 0, bufferSize, 0, vkMapMemory(DeviceControl::getDevice(), uniformBuffersMemory[i], 0,
&uniformBuffersMapped[i]); bufferSize, 0, &uniformBuffersMapped[i]);
} }
} }
void Buffers::updateUniformBuffer(uint32_t currentImage) { void Buffers::updateUniformBuffer(uint32_t currentImage) {
@ -242,7 +268,7 @@ void Buffers::updateUniformBuffer(uint32_t currentImage) {
currentTime - startTime) currentTime - startTime)
.count(); .count();
Global::UniformBufferObject ubo{}; UniformBufferObject ubo{};
ubo.time = time; ubo.time = time;
// Modify the model projection transformation to rotate around the Z over // Modify the model projection transformation to rotate around the Z over
// time. // time.
@ -257,10 +283,10 @@ void Buffers::updateUniformBuffer(uint32_t currentImage) {
glm::vec3(centerPos[0], centerPos[1], centerPos[2]), glm::vec3(centerPos[0], centerPos[1], centerPos[2]),
glm::vec3(upDir[0], upDir[1], upDir[2])); glm::vec3(upDir[0], upDir[1], upDir[2]));
// 45 degree field of view, set aspect ratio, and near and far clipping range. // 45 degree field of view, set aspect ratio, and near and far clipping range.
ubo.proj = glm::perspective( ubo.proj =
glm::radians(depthField), glm::perspective(glm::radians(depthField),
device_libs::DeviceControl::getSwapChainExtent().width / DeviceControl::getSwapChainExtent().width /
(float)device_libs::DeviceControl::getSwapChainExtent().height, (float)DeviceControl::getSwapChainExtent().height,
distanceField[0], distanceField[1]); distanceField[0], distanceField[1]);
// GLM was created for OpenGL, where the Y coordinate was inverted. This // GLM was created for OpenGL, where the Y coordinate was inverted. This
@ -270,63 +296,60 @@ void Buffers::updateUniformBuffer(uint32_t currentImage) {
memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo));
} }
void Buffers::destroyUniformBuffer() { void Buffers::destroyUniformBuffer() {
for (size_t i = 0; i < Global::MAX_FRAMES_IN_FLIGHT; i++) { for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
vkDestroyBuffer(Global::device, uniformBuffers[i], nullptr); vkDestroyBuffer(DeviceControl::getDevice(), uniformBuffers[i], nullptr);
vkFreeMemory(Global::device, uniformBuffersMemory[i], nullptr); vkFreeMemory(DeviceControl::getDevice(), uniformBuffersMemory[i], nullptr);
} }
} }
void Buffers::createDescriptorPool() { void Buffers::createDescriptorPool() {
// Create a pool to be used to allocate descriptor sets. // Create a pool to be used to allocate descriptor sets.
std::array<VkDescriptorPoolSize, 2> poolSizes{}; std::array<VkDescriptorPoolSize, 2> poolSizes{};
poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSizes[0].descriptorCount = poolSizes[0].descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
static_cast<uint32_t>(Global::MAX_FRAMES_IN_FLIGHT);
poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
poolSizes[1].descriptorCount = poolSizes[1].descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
static_cast<uint32_t>(Global::MAX_FRAMES_IN_FLIGHT);
VkDescriptorPoolCreateInfo poolInfo{}; VkDescriptorPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size()); poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
poolInfo.pPoolSizes = poolSizes.data(); poolInfo.pPoolSizes = poolSizes.data();
poolInfo.maxSets = static_cast<uint32_t>(Global::MAX_FRAMES_IN_FLIGHT); poolInfo.maxSets = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
if (vkCreateDescriptorPool(Global::device, &poolInfo, nullptr, if (vkCreateDescriptorPool(DeviceControl::getDevice(), &poolInfo, nullptr,
&descriptorPool) != VK_SUCCESS) { &descriptorPool) != VK_SUCCESS) {
throw std::runtime_error("failed to create descriptor pool!"); throw std::runtime_error("failed to create descriptor pool!");
} }
} }
void Buffers::createDescriptorSets() { void Buffers::createDescriptorSets() {
std::vector<VkDescriptorSetLayout> layouts(Global::MAX_FRAMES_IN_FLIGHT, std::vector<VkDescriptorSetLayout> layouts(MAX_FRAMES_IN_FLIGHT,
Global::descriptorSetLayout); descriptorSetLayout);
VkDescriptorSetAllocateInfo allocInfo{}; VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = descriptorPool; allocInfo.descriptorPool = descriptorPool;
allocInfo.descriptorSetCount = allocInfo.descriptorSetCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
static_cast<uint32_t>(Global::MAX_FRAMES_IN_FLIGHT);
allocInfo.pSetLayouts = layouts.data(); allocInfo.pSetLayouts = layouts.data();
Global::descriptorSets.resize(Global::MAX_FRAMES_IN_FLIGHT); descriptorSets.resize(MAX_FRAMES_IN_FLIGHT);
if (vkAllocateDescriptorSets(Global::device, &allocInfo, if (vkAllocateDescriptorSets(DeviceControl::getDevice(), &allocInfo,
Global::descriptorSets.data()) != VK_SUCCESS) { descriptorSets.data()) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate descriptor sets!"); 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{}; VkDescriptorBufferInfo bufferInfo{};
bufferInfo.buffer = uniformBuffers[i]; bufferInfo.buffer = uniformBuffers[i];
bufferInfo.offset = 0; bufferInfo.offset = 0;
bufferInfo.range = sizeof(Global::UniformBufferObject); bufferInfo.range = sizeof(UniformBufferObject);
VkDescriptorImageInfo imageInfo{}; VkDescriptorImageInfo imageInfo{};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.imageView = Global::textureImageView; imageInfo.imageView = Texture::getTextureImageView();
imageInfo.sampler = Global::textureSampler; imageInfo.sampler = Texture::getTextureSampler();
std::array<VkWriteDescriptorSet, 2> descriptorWrites{}; std::array<VkWriteDescriptorSet, 2> descriptorWrites{};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 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].dstBinding = 0;
descriptorWrites[0].dstArrayElement = 0; descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
@ -334,7 +357,7 @@ void Buffers::createDescriptorSets() {
descriptorWrites[0].pBufferInfo = &bufferInfo; descriptorWrites[0].pBufferInfo = &bufferInfo;
descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 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].dstBinding = 1;
descriptorWrites[1].dstArrayElement = 0; descriptorWrites[1].dstArrayElement = 0;
descriptorWrites[1].descriptorType = descriptorWrites[1].descriptorType =
@ -342,19 +365,37 @@ void Buffers::createDescriptorSets() {
descriptorWrites[1].descriptorCount = 1; descriptorWrites[1].descriptorCount = 1;
descriptorWrites[1].pImageInfo = &imageInfo; descriptorWrites[1].pImageInfo = &imageInfo;
vkUpdateDescriptorSets(Global::device, vkUpdateDescriptorSets(DeviceControl::getDevice(),
static_cast<uint32_t>(descriptorWrites.size()), static_cast<uint32_t>(descriptorWrites.size()),
descriptorWrites.data(), 0, nullptr); descriptorWrites.data(), 0, nullptr);
} }
} }
void Buffers::destroyDescriptorPool() { 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<VkDescriptorSet> &Buffers::getDescriptorSets() {
return descriptorSets;
} }
VkDescriptorPool Buffers::getDescriptorPool() { return descriptorPool; }
float *Buffers::getObjPos() { return objPos; } float *Buffers::getObjPos() { return objPos; }
float *Buffers::getCamPos() { return camPos; } float *Buffers::getCamPos() { return camPos; }
float *Buffers::getCenterPos() { return centerPos; } float *Buffers::getCenterPos() { return centerPos; }
float *Buffers::getUpDir() { return upDir; } float *Buffers::getUpDir() { return upDir; }
float *Buffers::getDepthField() { return &depthField; } float &Buffers::getDepthField() { return depthField; }
float *Buffers::getDistanceField() { return distanceField; } float *Buffers::getDistanceField() { return distanceField; }
} // namespace buffers_libs uint32_t Buffers::getMaxFramesInFlight() { return MAX_FRAMES_IN_FLIGHT; }
std::vector<VkCommandBuffer> &Buffers::getCommandBuffers() {
return commandBuffers;
}
std::vector<VkBuffer> &Buffers::getUniformBuffers() { return uniformBuffers; }
std::vector<VkDeviceMemory> &Buffers::getUniformBuffersMemory() {
return uniformBuffersMemory;
}
VkCommandPool &Buffers::getCommandPool() { return commandPool; }
VkDescriptorSetLayout &Buffers::getDescriptorSetLayout() {
return descriptorSetLayout;
}
std::vector<Buffers::Vertex> &Buffers::getVertices() { return vertices; }
std::vector<uint32_t> &Buffers::getIndices() { return indices; }

View File

@ -1,11 +1,58 @@
#pragma once #pragma once
#include "../devicelibrary.h"
#include <chrono>
#include <cstring>
namespace buffers_libs { #define VK_NO_PROTOTYPES
#include "volk.h"
#include <vector>
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp>
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#include <array>
class Buffers { class Buffers {
public: 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<VkVertexInputAttributeDescription, 3>
getAttributeDescriptions() {
std::array<VkVertexInputAttributeDescription, 3> 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, static void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage,
VkMemoryPropertyFlags props, VkBuffer &buffer, VkMemoryPropertyFlags props, VkBuffer &buffer,
VkDeviceMemory &bufferMemory); VkDeviceMemory &bufferMemory);
@ -14,8 +61,8 @@ public:
static void createIndexBuffer(); static void createIndexBuffer();
static void createVertexBuffer(); static void createVertexBuffer();
static void destroyBuffers(); static void destroyBuffers();
static VkBuffer getVertexBuffer(); static VkBuffer &getVertexBuffer();
static VkBuffer getIndexBuffer(); static VkBuffer &getIndexBuffer();
static void createDescriptorSetLayout(); static void createDescriptorSetLayout();
static void createUniformBuffers(); static void createUniformBuffers();
static void updateUniformBuffer(uint32_t currentImage); static void updateUniformBuffer(uint32_t currentImage);
@ -23,13 +70,21 @@ public:
static void createDescriptorPool(); static void createDescriptorPool();
static void createDescriptorSets(); static void createDescriptorSets();
static void destroyDescriptorPool(); static void destroyDescriptorPool();
static VkDescriptorPool getDescriptorPool(); static VkDescriptorPool &getDescriptorPool();
static VkDescriptorSetLayout &getDescriptorSetLayout();
static std::vector<VkDescriptorSet> &getDescriptorSets();
static float *getObjPos(); static float *getObjPos();
static float *getCamPos(); static float *getCamPos();
static float *getCenterPos(); static float *getCenterPos();
static float *getUpDir(); static float *getUpDir();
static float *getDepthField(); static float &getDepthField();
static float *getDistanceField(); static float *getDistanceField();
static uint32_t getMaxFramesInFlight();
static std::vector<VkCommandBuffer> &getCommandBuffers();
static std::vector<VkBuffer> &getUniformBuffers();
static std::vector<VkDeviceMemory> &getUniformBuffersMemory();
static VkCommandPool &getCommandPool();
static std::vector<Vertex> &getVertices();
static std::vector<uint32_t> &getIndices();
}; };
} // namespace buffers_libs

View File

@ -1,9 +1,11 @@
#include "../devicelibrary.h"
#include "buffers.h"
#include "graphicspipeline.h" #include "graphicspipeline.h"
#include "imgui.h" #include "imgui.h"
#include "imgui_impl_vulkan.h" #include "imgui_impl_vulkan.h"
#include "render.h"
#include "texture.h" #include "texture.h"
#include <fstream>
namespace graphics_pipeline {
std::vector<VkDynamicState> dynamicStates = {VK_DYNAMIC_STATE_VIEWPORT, std::vector<VkDynamicState> dynamicStates = {VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR}; VK_DYNAMIC_STATE_SCISSOR};
@ -43,8 +45,8 @@ VkShaderModule createShaderModule(const std::vector<char> &code,
} }
void Graphics::destroyGraphicsPipeline() { void Graphics::destroyGraphicsPipeline() {
vkDestroyPipeline(Global::device, graphicsPipeline, nullptr); vkDestroyPipeline(DeviceControl::getDevice(), graphicsPipeline, nullptr);
vkDestroyPipelineLayout(Global::device, pipelineLayout, nullptr); vkDestroyPipelineLayout(DeviceControl::getDevice(), pipelineLayout, nullptr);
} }
void Graphics::createGraphicsPipeline() { void Graphics::createGraphicsPipeline() {
@ -53,9 +55,9 @@ void Graphics::createGraphicsPipeline() {
auto vertShaderCode = readFile("src/shaders/vertex.spv"); auto vertShaderCode = readFile("src/shaders/vertex.spv");
auto fragShaderCode = readFile("src/shaders/fragment.spv"); auto fragShaderCode = readFile("src/shaders/fragment.spv");
VkShaderModule vertShaderModule = VkShaderModule vertShaderModule =
createShaderModule(vertShaderCode, Global::device); createShaderModule(vertShaderCode, DeviceControl::getDevice());
VkShaderModule fragShaderModule = VkShaderModule fragShaderModule =
createShaderModule(fragShaderCode, Global::device); createShaderModule(fragShaderCode, DeviceControl::getDevice());
// ------------------ STAGE 1 - INPUT ASSEMBLER ---------------- // // ------------------ STAGE 1 - INPUT ASSEMBLER ---------------- //
// This can get a little complicated, normally, vertices are loaded in // This can get a little complicated, normally, vertices are loaded in
// sequential order, with an element buffer however, you can specify the // sequential order, with an element buffer however, you can specify the
@ -81,8 +83,8 @@ void Graphics::createGraphicsPipeline() {
vertexInputInfo.sType = vertexInputInfo.sType =
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
auto bindingDescription = Global::Vertex::getBindingDescription(); auto bindingDescription = Buffers::Vertex::getBindingDescription();
auto attributeDescriptions = Global::Vertex::getAttributeDescriptions(); auto attributeDescriptions = Buffers::Vertex::getAttributeDescriptions();
vertexInputInfo.vertexBindingDescriptionCount = 1; vertexInputInfo.vertexBindingDescriptionCount = 1;
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription; vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
@ -149,7 +151,7 @@ void Graphics::createGraphicsPipeline() {
multisampling.sType = multisampling.sType =
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_TRUE; multisampling.sampleShadingEnable = VK_TRUE;
multisampling.rasterizationSamples = Global::perPixelSampleCount; multisampling.rasterizationSamples = DeviceControl::getPerPixelSampleCount();
// TODO: Document! // TODO: Document!
VkPipelineDepthStencilStateCreateInfo depthStencil{}; VkPipelineDepthStencilStateCreateInfo depthStencil{};
depthStencil.sType = depthStencil.sType =
@ -175,18 +177,18 @@ void Graphics::createGraphicsPipeline() {
VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1; pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = &Global::descriptorSetLayout; pipelineLayoutInfo.pSetLayouts = &Buffers::getDescriptorSetLayout();
if (vkCreatePipelineLayout(Global::device, &pipelineLayoutInfo, nullptr, if (vkCreatePipelineLayout(DeviceControl::getDevice(), &pipelineLayoutInfo,
&pipelineLayout) != VK_SUCCESS) { nullptr, &pipelineLayout) != VK_SUCCESS) {
throw std::runtime_error("failed to create pipeline layout!"); throw std::runtime_error("failed to create pipeline layout!");
} }
VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo{ VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
.colorAttachmentCount = 1, .colorAttachmentCount = 1,
.pColorAttachmentFormats = device_libs::DeviceControl::getImageFormat(), .pColorAttachmentFormats = &DeviceControl::getImageFormat(),
.depthAttachmentFormat = texture_libs::Texture::findDepthFormat(), .depthAttachmentFormat = Texture::findDepthFormat(),
}; };
// Here we combine all of the structures we created to make the final // Here we combine all of the structures we created to make the final
@ -209,46 +211,48 @@ void Graphics::createGraphicsPipeline() {
.subpass = 0, .subpass = 0,
}; };
if (vkCreateGraphicsPipelines(Global::device, VK_NULL_HANDLE, 1, if (vkCreateGraphicsPipelines(DeviceControl::getDevice(), VK_NULL_HANDLE, 1,
&pipelineInfo, nullptr, &pipelineInfo, nullptr,
&graphicsPipeline) != VK_SUCCESS) { &graphicsPipeline) != VK_SUCCESS) {
throw std::runtime_error("failed to create graphics pipeline!"); throw std::runtime_error("failed to create graphics pipeline!");
} }
vkDestroyShaderModule(Global::device, fragShaderModule, nullptr); vkDestroyShaderModule(DeviceControl::getDevice(), fragShaderModule, nullptr);
vkDestroyShaderModule(Global::device, vertShaderModule, nullptr); vkDestroyShaderModule(DeviceControl::getDevice(), vertShaderModule, nullptr);
} }
void Graphics::createCommandPool() { void Graphics::createCommandPool() {
// Commands in Vulkan are not executed using function calls, you have to // 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 // record the ops you wish to perform to command buffers, pools manage the
// memory used by the buffer! // memory used by the buffer!
Global::QueueFamilyIndices queueFamilyIndices = DeviceControl::QueueFamilyIndices queueFamilyIndices =
Global::findQueueFamilies(Global::physicalDevice); DeviceControl::findQueueFamilies(DeviceControl::getPhysicalDevice());
VkCommandPoolCreateInfo poolInfo{}; VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value(); poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value();
if (vkCreateCommandPool(Global::device, &poolInfo, nullptr, if (vkCreateCommandPool(DeviceControl::getDevice(), &poolInfo, nullptr,
&Global::commandPool) != VK_SUCCESS) { &Buffers::getCommandPool()) != VK_SUCCESS) {
throw std::runtime_error("Failed to create command pool!"); throw std::runtime_error("Failed to create command pool!");
} }
} }
void Graphics::destroyCommandPool() { void Graphics::destroyCommandPool() {
vkDestroyCommandPool(Global::device, Global::commandPool, nullptr); vkDestroyCommandPool(DeviceControl::getDevice(), Buffers::getCommandPool(),
nullptr);
} }
void Graphics::createCommandBuffer() { void Graphics::createCommandBuffer() {
Global::commandBuffers.resize(Global::MAX_FRAMES_IN_FLIGHT); Buffers::getCommandBuffers().resize(Buffers::getMaxFramesInFlight());
VkCommandBufferAllocateInfo allocInfo{}; VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 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.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, if (vkAllocateCommandBuffers(DeviceControl::getDevice(), &allocInfo,
Global::commandBuffers.data()) != VK_SUCCESS) { Buffers::getCommandBuffers().data()) !=
VK_SUCCESS) {
throw std::runtime_error("Failed to allocate command buffers"); throw std::runtime_error("Failed to allocate command buffers");
} }
} }
@ -272,7 +276,7 @@ void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer,
.newLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = device_libs::DeviceControl::getSwapChainImages()[imageIndex], .image = DeviceControl::getSwapChainImages()[imageIndex],
.subresourceRange = .subresourceRange =
{ {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
@ -294,10 +298,10 @@ void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer,
const VkRenderingAttachmentInfo colorAttachmentInfo{ const VkRenderingAttachmentInfo colorAttachmentInfo{
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.imageView = Global::colorImageView, .imageView = Texture::getColorImageView(),
.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT, .resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT,
.resolveImageView = Global::swapChainImageViews[imageIndex], .resolveImageView = DeviceControl::getSwapChainImageViews()[imageIndex],
.resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, .resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE, .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
@ -305,7 +309,7 @@ void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer,
}; };
const VkRenderingAttachmentInfo depthAttachmentInfo{ const VkRenderingAttachmentInfo depthAttachmentInfo{
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.imageView = Global::depthImageView, .imageView = Texture::getDepthImageView(),
.imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, .imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
@ -315,8 +319,7 @@ void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer,
const VkRenderingInfo renderInfo{ const VkRenderingInfo renderInfo{
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO, .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
.renderArea = {.offset = {0, 0}, .renderArea = {.offset = {0, 0},
.extent = .extent = DeviceControl::getSwapChainExtent()},
device_libs::DeviceControl::getSwapChainExtent()},
.layerCount = 1, .layerCount = 1,
.colorAttachmentCount = 1, .colorAttachmentCount = 1,
.pColorAttachments = &colorAttachmentInfo, .pColorAttachments = &colorAttachmentInfo,
@ -330,31 +333,30 @@ void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer,
VkViewport viewport{}; VkViewport viewport{};
viewport.x = 0.0f; viewport.x = 0.0f;
viewport.y = 0.0f; viewport.y = 0.0f;
viewport.width = viewport.width = (float)DeviceControl::getSwapChainExtent().width;
(float)device_libs::DeviceControl::getSwapChainExtent().width; viewport.height = (float)DeviceControl::getSwapChainExtent().height;
viewport.height =
(float)device_libs::DeviceControl::getSwapChainExtent().height;
viewport.minDepth = 0.0f; viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f; viewport.maxDepth = 1.0f;
vkCmdSetViewport(commandBuffer, 0, 1, &viewport); vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
VkRect2D scissor{}; VkRect2D scissor{};
scissor.offset = {0, 0}; scissor.offset = {0, 0};
scissor.extent = device_libs::DeviceControl::getSwapChainExtent(); scissor.extent = DeviceControl::getSwapChainExtent();
vkCmdSetScissor(commandBuffer, 0, 1, &scissor); vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
VkBuffer vertexBuffers[] = {buffers_libs::Buffers::getVertexBuffer()}; VkBuffer vertexBuffers[] = {Buffers::getVertexBuffer()};
VkDeviceSize offsets[] = {0}; VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
vkCmdBindIndexBuffer(commandBuffer, buffers_libs::Buffers::getIndexBuffer(), vkCmdBindIndexBuffer(commandBuffer, Buffers::getIndexBuffer(), 0,
0, VK_INDEX_TYPE_UINT32); VK_INDEX_TYPE_UINT32);
vkCmdBindDescriptorSets( vkCmdBindDescriptorSets(
commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, 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<uint32_t>(Global::indices.size()), vkCmdDrawIndexed(commandBuffer,
1, 0, 0, 0); static_cast<uint32_t>(Buffers::getIndices().size()), 1, 0, 0,
0);
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), commandBuffer); ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), commandBuffer);
@ -371,7 +373,7 @@ void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer,
.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = device_libs::DeviceControl::getSwapChainImages()[imageIndex], .image = DeviceControl::getSwapChainImages()[imageIndex],
.subresourceRange = .subresourceRange =
{ {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
@ -388,11 +390,10 @@ void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer,
.pImageMemoryBarriers = &prePresentImageBarrier, .pImageMemoryBarriers = &prePresentImageBarrier,
}; };
vkCmdPipelineBarrier2(Global::commandBuffers[Global::currentFrame], &depInfo); vkCmdPipelineBarrier2(
Buffers ::getCommandBuffers()[Render::getCurrentFrame()], &depInfo);
if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) { if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
throw std::runtime_error("failed to record command buffer!"); throw std::runtime_error("failed to record command buffer!");
} }
} }
} // namespace graphics_pipeline

View File

@ -1,11 +1,7 @@
#pragma once #pragma once
#include "../global.h" #define VK_NO_PROTOTYPES
#include "../devicelibrary.h" #include "volk.h"
#include "buffers.h"
#include "texture.h"
#include <fstream>
namespace graphics_pipeline {
class Graphics { class Graphics {
public: public:
static void createGraphicsPipeline(); static void createGraphicsPipeline();
@ -15,6 +11,6 @@ namespace graphics_pipeline {
static void createCommandPool(); static void createCommandPool();
static void destroyCommandPool(); static void destroyCommandPool();
static void createCommandBuffer(); static void createCommandBuffer();
static void recordCommandBuffer(VkCommandBuffer cmndBuffer, uint32_t imageIndex); static void recordCommandBuffer(VkCommandBuffer cmndBuffer,
uint32_t imageIndex);
}; };
}

View File

@ -1,25 +1,32 @@
#include "buffers.h"
#include "model.h" #include "model.h"
#include <stdexcept>
#define TINY_OBJ_IMPLEMENTATION
#include <tiny_obj_loader.h>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/hash.hpp>
namespace std { namespace std {
template<> struct hash<Global::Vertex> { template <> struct hash<Buffers::Vertex> {
size_t operator()(Global::Vertex const& vertex) const { size_t operator()(Buffers::Vertex const &vertex) const {
return ((hash<glm::vec3>()(vertex.pos) ^ return ((hash<glm::vec3>()(vertex.pos) ^
(hash<glm::vec3>()(vertex.color) << 1)) >> 1) ^ (hash<glm::vec3>()(vertex.color) << 1)) >>
1) ^
(hash<glm::vec2>()(vertex.texCoord) << 1); (hash<glm::vec2>()(vertex.texCoord) << 1);
} }
}; };
} } // namespace std
namespace modellib { const std::string MODEL_PATH = "assets/models/viking_room.obj";
std::unordered_map<Global::Vertex, uint32_t> uniqueVertices{};
void Model::loadModel() { void Model::loadModel() {
tinyobj::ObjReaderConfig readerConfig; tinyobj::ObjReaderConfig readerConfig;
tinyobj::ObjReader reader; tinyobj::ObjReader reader;
if(!reader.ParseFromFile(Global::MODEL_PATH, readerConfig)) { if (!reader.ParseFromFile(MODEL_PATH, readerConfig)) {
if (!reader.Error().empty()) { if (!reader.Error().empty()) {
throw std::runtime_error(reader.Error()); throw std::runtime_error(reader.Error());
} }
@ -31,34 +38,31 @@ namespace modellib {
auto &attrib = reader.GetAttrib(); auto &attrib = reader.GetAttrib();
auto &shapes = reader.GetShapes(); auto &shapes = reader.GetShapes();
auto &materials = reader.GetMaterials(); auto &materials = reader.GetMaterials();
std::unordered_map<Buffers::Vertex, uint32_t> uniqueVertices{};
for (const auto &shape : shapes) { for (const auto &shape : shapes) {
for (const auto &index : shape.mesh.indices) { for (const auto &index : shape.mesh.indices) {
Global::Vertex vertex{}; Buffers::Vertex vertex{};
vertex.pos = { vertex.pos = {attrib.vertices[3 * index.vertex_index + 0],
attrib.vertices[3 * index.vertex_index + 0],
attrib.vertices[3 * index.vertex_index + 1], attrib.vertices[3 * index.vertex_index + 1],
attrib.vertices[3 * index.vertex_index + 2] attrib.vertices[3 * index.vertex_index + 2]};
};
//TODO: Small fix here, handle if there are no UV's unwrapped for the model. // TODO: Small fix here, handle if there are no UV's unwrapped for the
// As of now, if it is not unwrapped, it segfaults on texCoord assignment. // model.
// Obviously we should always have UV's, but it shouldn't crash, just unwrap // As of now, if it is not unwrapped, it segfaults on texCoord
// in a default method. // assignment. Obviously we should always have UV's, but it
vertex.texCoord = { // shouldn't crash, just unwrap in a default method.
attrib.texcoords[2 * index.texcoord_index + 0], vertex.texCoord = {attrib.texcoords[2 * index.texcoord_index + 0],
1.0f - attrib.texcoords[2 * index.texcoord_index + 1] 1.0f - attrib.texcoords[2 * index.texcoord_index + 1]};
};
vertex.color = {1.0f, 1.0f, 1.0f}; vertex.color = {1.0f, 1.0f, 1.0f};
if (uniqueVertices.count(vertex) == 0) { if (uniqueVertices.count(vertex) == 0) {
uniqueVertices[vertex] = static_cast<uint32_t>(Global::vertices.size()); uniqueVertices[vertex] =
Global::vertices.push_back(vertex); static_cast<uint32_t>(Buffers::getVertices().size());
} Buffers::getVertices().push_back(vertex);
Global::indices.push_back(uniqueVertices[vertex]);
} }
Buffers::getIndices().push_back(uniqueVertices[vertex]);
} }
} }
} }

View File

@ -1,15 +1,6 @@
#pragma once #pragma once
#include "../global.h"
#define TINY_OBJ_IMPLEMENTATION
#include <tiny_obj_loader.h>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/hash.hpp>
namespace modellib {
class Model { class Model {
public: public:
static void loadModel(); static void loadModel();
}; };
} // namespace modellib

View File

@ -1,55 +1,56 @@
#include <stdexcept>
#include "imgui.h"
#include "imgui_impl_vulkan.h"
#include "../devicelibrary.h" #include "../devicelibrary.h"
#include "../entrypoint.h" #include "../entrypoint.h"
#include "buffers.h" #include "buffers.h"
#include "graphicspipeline.h" #include "graphicspipeline.h"
#include "render.h" #include "render.h"
#include "texture.h" #include "texture.h"
#include <stdexcept>
#include "imgui.h"
#include "imgui_impl_vulkan.h"
namespace render_present {
uint32_t currentFrame;
std::vector<VkSemaphore> imageAvailableSemaphores; std::vector<VkSemaphore> imageAvailableSemaphores;
std::vector<VkSemaphore> renderFinishedSemaphores; std::vector<VkSemaphore> renderFinishedSemaphores;
std::vector<VkFence> inFlightFences; std::vector<VkFence> inFlightFences;
void recreateSwapChain() { void recreateSwapChain() {
int width = 0, height = 0; int width = 0, height = 0;
glfwGetFramebufferSize(Global::window, &width, &height); glfwGetFramebufferSize(EntryApp::getWindow(), &width, &height);
while (width == 0 || height == 0) { while (width == 0 || height == 0) {
glfwGetFramebufferSize(Global::window, &width, &height); glfwGetFramebufferSize(EntryApp::getWindow(), &width, &height);
glfwWaitEvents(); glfwWaitEvents();
} }
vkDeviceWaitIdle(Global::device); vkDeviceWaitIdle(DeviceControl::getDevice());
// Don't really wanna do this but I also don't want to create an extra class // Don't really wanna do this but I also don't want to create an extra class
// instance just to call the cleanup function. // instance just to call the cleanup function.
for (auto imageView : Global::swapChainImageViews) { for (auto imageView : DeviceControl::getSwapChainImageViews()) {
vkDestroyImageView(Global::device, imageView, nullptr); vkDestroyImageView(DeviceControl::getDevice(), imageView, nullptr);
} }
vkDestroySwapchainKHR(Global::device, Global::swapChain, nullptr); vkDestroySwapchainKHR(DeviceControl::getDevice(),
DeviceControl::getSwapChain(), nullptr);
device_libs::DeviceControl::createSwapChain(Global::window); DeviceControl::createSwapChain(EntryApp::getWindow());
device_libs::DeviceControl::createImageViews(); DeviceControl::createImageViews();
texture_libs::Texture::createColorResources(); Texture::createColorResources();
texture_libs::Texture::createDepthResources(); Texture::createDepthResources();
} }
// At a high level, rendering in Vulkan consists of 5 steps: // At a high level, rendering in Vulkan consists of 5 steps:
// Wait for the previous frame, acquire a image from the swap chain // Wait for the previous frame, acquire a image from the swap chain
// record a comman d buffer which draws the scene onto that image // record a comman d buffer which draws the scene onto that image
// submit the recorded command buffer and present the image! // submit the recorded command buffer and present the image!
void Render::drawFrame() { void Render::drawFrame() {
vkWaitForFences(Global::device, 1, &inFlightFences[Global::currentFrame], vkWaitForFences(DeviceControl::getDevice(), 1, &inFlightFences[currentFrame],
VK_TRUE, UINT64_MAX); VK_TRUE, UINT64_MAX);
vkResetFences(Global::device, 1, &inFlightFences[Global::currentFrame]); vkResetFences(DeviceControl::getDevice(), 1, &inFlightFences[currentFrame]);
uint32_t imageIndex; uint32_t imageIndex;
VkResult result = VkResult result = vkAcquireNextImageKHR(
vkAcquireNextImageKHR(Global::device, Global::swapChain, UINT64_MAX, DeviceControl::getDevice(), DeviceControl::getSwapChain(), UINT64_MAX,
imageAvailableSemaphores[Global::currentFrame], imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
VK_NULL_HANDLE, &imageIndex);
if (result == VK_ERROR_OUT_OF_DATE_KHR) { if (result == VK_ERROR_OUT_OF_DATE_KHR) {
recreateSwapChain(); recreateSwapChain();
return; return;
@ -57,36 +58,34 @@ void Render::drawFrame() {
throw std::runtime_error("failed to acquire swap chain image!"); 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); /*VkCommandBufferResetFlagBits*/ 0);
graphics_pipeline::Graphics::recordCommandBuffer( Graphics::recordCommandBuffer(Buffers::getCommandBuffers()[currentFrame],
Global::commandBuffers[Global::currentFrame], imageIndex); imageIndex);
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(),
Global::commandBuffers[Global::currentFrame]); Buffers::getCommandBuffers()[currentFrame]);
VkSubmitInfo submitInfo{}; VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore waitSemaphores[] = { VkSemaphore waitSemaphores[] = {imageAvailableSemaphores[currentFrame]};
imageAvailableSemaphores[Global::currentFrame]};
VkPipelineStageFlags waitStages[] = { VkPipelineStageFlags waitStages[] = {
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
submitInfo.waitSemaphoreCount = 1; submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages; submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &Global::commandBuffers[Global::currentFrame]; submitInfo.pCommandBuffers = &Buffers::getCommandBuffers()[currentFrame];
VkSemaphore signalSemaphores[] = { VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[currentFrame]};
renderFinishedSemaphores[Global::currentFrame]};
submitInfo.signalSemaphoreCount = 1; submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores; submitInfo.pSignalSemaphores = signalSemaphores;
if (vkQueueSubmit(Global::graphicsQueue, 1, &submitInfo, if (vkQueueSubmit(DeviceControl::getGraphicsQueue(), 1, &submitInfo,
inFlightFences[Global::currentFrame]) != VK_SUCCESS) { inFlightFences[currentFrame]) != VK_SUCCESS) {
throw std::runtime_error("failed to submit draw command buffer!"); throw std::runtime_error("failed to submit draw command buffer!");
} }
@ -96,12 +95,12 @@ void Render::drawFrame() {
presentInfo.waitSemaphoreCount = 1; presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores; presentInfo.pWaitSemaphores = signalSemaphores;
VkSwapchainKHR swapChains[] = {Global::swapChain}; VkSwapchainKHR swapChains[] = {DeviceControl::getSwapChain()};
presentInfo.swapchainCount = 1; presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapChains; presentInfo.pSwapchains = swapChains;
presentInfo.pImageIndices = &imageIndex; 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 || if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR ||
EntryApp::getInstance().getFramebufferResized()) { EntryApp::getInstance().getFramebufferResized()) {
@ -110,8 +109,7 @@ void Render::drawFrame() {
} else if (result != VK_SUCCESS) { } else if (result != VK_SUCCESS) {
throw std::runtime_error("failed to present swap chain image!"); throw std::runtime_error("failed to present swap chain image!");
} }
Global::currentFrame = currentFrame = (currentFrame + 1) % Buffers::getMaxFramesInFlight();
(Global::currentFrame + 1) % Global::MAX_FRAMES_IN_FLIGHT;
} }
#pragma info #pragma info
@ -139,9 +137,9 @@ void Render::drawFrame() {
#pragma endinfo #pragma endinfo
void Render::createSyncObject() { void Render::createSyncObject() {
imageAvailableSemaphores.resize(Global::MAX_FRAMES_IN_FLIGHT); imageAvailableSemaphores.resize(Buffers::getMaxFramesInFlight());
renderFinishedSemaphores.resize(Global::MAX_FRAMES_IN_FLIGHT); renderFinishedSemaphores.resize(Buffers::getMaxFramesInFlight());
inFlightFences.resize(Global::MAX_FRAMES_IN_FLIGHT); inFlightFences.resize(Buffers::getMaxFramesInFlight());
VkSemaphoreCreateInfo semaphoreInfo{}; VkSemaphoreCreateInfo semaphoreInfo{};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
@ -150,36 +148,42 @@ void Render::createSyncObject() {
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
for (size_t i = 0; i < Global::MAX_FRAMES_IN_FLIGHT; i++) { for (size_t i = 0; i < Buffers::getMaxFramesInFlight(); i++) {
if (vkCreateSemaphore(Global::device, &semaphoreInfo, nullptr, if (vkCreateSemaphore(DeviceControl::getDevice(), &semaphoreInfo, nullptr,
&imageAvailableSemaphores[i]) != VK_SUCCESS || &imageAvailableSemaphores[i]) != VK_SUCCESS ||
vkCreateSemaphore(Global::device, &semaphoreInfo, nullptr, vkCreateSemaphore(DeviceControl::getDevice(), &semaphoreInfo, nullptr,
&renderFinishedSemaphores[i]) != VK_SUCCESS || &renderFinishedSemaphores[i]) != VK_SUCCESS ||
vkCreateFence(Global::device, &fenceInfo, nullptr, vkCreateFence(DeviceControl::getDevice(), &fenceInfo, nullptr,
&inFlightFences[i]) != VK_SUCCESS) { &inFlightFences[i]) != VK_SUCCESS) {
throw std::runtime_error("Failed to create semaphores!"); throw std::runtime_error("Failed to create semaphores!");
} }
} }
} }
void Render::destroyFenceSemaphores() { void Render::destroyFenceSemaphores() {
for (size_t i = 0; i < Global::MAX_FRAMES_IN_FLIGHT; i++) { for (size_t i = 0; i < Buffers::getMaxFramesInFlight(); i++) {
vkDestroySemaphore(Global::device, renderFinishedSemaphores[i], nullptr); vkDestroySemaphore(DeviceControl::getDevice(), renderFinishedSemaphores[i],
vkDestroySemaphore(Global::device, imageAvailableSemaphores[i], nullptr); nullptr);
vkDestroyFence(Global::device, inFlightFences[i], nullptr); vkDestroySemaphore(DeviceControl::getDevice(), imageAvailableSemaphores[i],
nullptr);
vkDestroyFence(DeviceControl::getDevice(), inFlightFences[i], nullptr);
} }
} }
void Render::cleanupSwapChain() { void Render::cleanupSwapChain() {
vkDestroyImageView(Global::device, Global::colorImageView, nullptr); vkDestroyImageView(DeviceControl::getDevice(), Texture::getColorImageView(),
vkDestroyImage(Global::device, Global::colorImage, nullptr); nullptr);
vkFreeMemory(Global::device, Global::colorImageMemory, nullptr); vkDestroyImage(DeviceControl::getDevice(), Texture::getColorImage(), nullptr);
vkDestroyImageView(Global::device, Global::depthImageView, nullptr); vkFreeMemory(DeviceControl::getDevice(), Texture::getColorImageMemory(),
vkDestroyImage(Global::device, Global::depthImage, nullptr); nullptr);
vkFreeMemory(Global::device, Global::depthImageMemory, nullptr); vkDestroyImageView(DeviceControl::getDevice(), Texture::getDepthImageView(),
nullptr);
vkDestroyImage(DeviceControl::getDevice(), Texture::getDepthImage(), nullptr);
vkFreeMemory(DeviceControl::getDevice(), Texture::getDepthImageMemory(),
nullptr);
for (auto imageView : Global::swapChainImageViews) { for (auto imageView : DeviceControl::getSwapChainImageViews()) {
vkDestroyImageView(Global::device, imageView, nullptr); vkDestroyImageView(DeviceControl::getDevice(), imageView, nullptr);
} }
vkDestroySwapchainKHR(Global::device, Global::swapChain, nullptr); vkDestroySwapchainKHR(DeviceControl::getDevice(),
DeviceControl::getSwapChain(), nullptr);
} }
uint32_t Render::getCurrentFrame() { return currentFrame; }
} // namespace render_present

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "../global.h"
namespace render_present { #include <cstdint>
class Render { class Render {
public: public:
static void drawFrame(); static void drawFrame();
@ -9,5 +8,5 @@ public:
static void destroyFenceSemaphores(); static void destroyFenceSemaphores();
static void cleanupSwapChain(); static void cleanupSwapChain();
static float getFloatBar(); static float getFloatBar();
static uint32_t getCurrentFrame();
}; };
} // namespace render_present

View File

@ -1,5 +1,9 @@
#define STB_IMAGE_IMPLEMENTATION #include "../devicelibrary.h"
#include "buffers.h"
#include "texture.h" #include "texture.h"
#include <stdexcept>
#include <string>
#define STB_IMAGE_IMPLEMENTATION
#include <stb/stb_image.h> #include <stb/stb_image.h>
uint32_t mipLevels; uint32_t mipLevels;
@ -9,7 +13,19 @@ VkDeviceMemory textureImageMemory;
VkPipelineStageFlags sourceStage; VkPipelineStageFlags sourceStage;
VkPipelineStageFlags destinationStage; 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, void createImage(uint32_t width, uint32_t height, uint32_t mipLevels,
VkSampleCountFlagBits sampleNum, VkFormat format, VkSampleCountFlagBits sampleNum, VkFormat format,
VkImageTiling tiling, VkImageUsageFlags usage, 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.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.mipLevels = mipLevels; imageInfo.mipLevels = mipLevels;
if (vkCreateImage(Global::device, &imageInfo, nullptr, &image) != if (vkCreateImage(DeviceControl::getDevice(), &imageInfo, nullptr, &image) !=
VK_SUCCESS) { VK_SUCCESS) {
throw std::runtime_error("failed to create image!"); throw std::runtime_error("failed to create image!");
} }
VkMemoryRequirements memRequirements; VkMemoryRequirements memRequirements;
vkGetImageMemoryRequirements(Global::device, image, &memRequirements); vkGetImageMemoryRequirements(DeviceControl::getDevice(), image,
&memRequirements);
VkMemoryAllocateInfo allocInfo{}; VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size; allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = buffers_libs::Buffers::findMemoryType( allocInfo.memoryTypeIndex =
memRequirements.memoryTypeBits, properties); Buffers::findMemoryType(memRequirements.memoryTypeBits, properties);
if (vkAllocateMemory(Global::device, &allocInfo, nullptr, &imageMemory) != if (vkAllocateMemory(DeviceControl::getDevice(), &allocInfo, nullptr,
VK_SUCCESS) { &imageMemory) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate image memory!"); throw std::runtime_error("failed to allocate image memory!");
} }
vkBindImageMemory(Global::device, image, imageMemory, 0); vkBindImageMemory(DeviceControl::getDevice(), image, imageMemory, 0);
} }
VkCommandBuffer beginSingleTimeCommands() { VkCommandBuffer beginSingleTimeCommands() {
@ -61,11 +78,12 @@ VkCommandBuffer beginSingleTimeCommands() {
VkCommandBufferAllocateInfo allocInfo{}; VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandPool = Global::commandPool; allocInfo.commandPool = Buffers::getCommandPool();
allocInfo.commandBufferCount = 1; allocInfo.commandBufferCount = 1;
VkCommandBuffer commandBuffer; VkCommandBuffer commandBuffer;
vkAllocateCommandBuffers(Global::device, &allocInfo, &commandBuffer); vkAllocateCommandBuffers(DeviceControl::getDevice(), &allocInfo,
&commandBuffer);
VkCommandBufferBeginInfo beginInfo{}; VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
@ -85,21 +103,14 @@ void endSingleTimeCommands(VkCommandBuffer commandBuffer) {
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer; submitInfo.pCommandBuffers = &commandBuffer;
vkQueueSubmit(Global::graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); vkQueueSubmit(DeviceControl::getGraphicsQueue(), 1, &submitInfo,
vkQueueWaitIdle(Global::graphicsQueue); 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, &copyRegion);
endSingleTimeCommands(commandBuffer);
}
void transitionImageLayout(VkImage image, VkFormat format, void transitionImageLayout(VkImage image, VkFormat format,
VkImageLayout oldLayout, VkImageLayout newLayout, VkImageLayout oldLayout, VkImageLayout newLayout,
uint32_t mipLevels) { uint32_t mipLevels) {
@ -173,7 +184,8 @@ VkFormat findSupportedFormat(const std::vector<VkFormat> &candidates,
VkFormatFeatureFlags features) { VkFormatFeatureFlags features) {
for (VkFormat format : candidates) { for (VkFormat format : candidates) {
VkFormatProperties props; VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(Global::physicalDevice, format, &props); vkGetPhysicalDeviceFormatProperties(DeviceControl::getPhysicalDevice(),
format, &props);
// Do we support linear tiling? // Do we support linear tiling?
if (tiling == VK_IMAGE_TILING_LINEAR && 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) { int32_t textureHeight, uint32_t mipLevels) {
// Check if image format supports linear blitting // Check if image format supports linear blitting
VkFormatProperties formatProperties; VkFormatProperties formatProperties;
vkGetPhysicalDeviceFormatProperties(Global::physicalDevice, imageFormat, vkGetPhysicalDeviceFormatProperties(DeviceControl::getPhysicalDevice(),
&formatProperties); imageFormat, &formatProperties);
if (!(formatProperties.optimalTilingFeatures & if (!(formatProperties.optimalTilingFeatures &
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) { 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 // colorspace! Its a lot of kind of complicated memory calls to bring it from
// a file -> to a buffer -> to a image object. // a file -> to a buffer -> to a image object.
int textureWidth, textureHeight, textureChannels; 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); &textureHeight, &textureChannels, STBI_rgb_alpha);
mipLevels = static_cast<uint32_t>(std::floor( mipLevels = static_cast<uint32_t>(std::floor(
std::log2(std::max(textureWidth, textureHeight)))) + std::log2(std::max(textureWidth, textureHeight)))) +
@ -296,16 +308,16 @@ void Texture::createTextureImage() {
} }
VkBuffer stagingBuffer; VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory; VkDeviceMemory stagingBufferMemory;
buffers_libs::Buffers::createBuffer(imageSize, Buffers::createBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
stagingBuffer, stagingBufferMemory); stagingBuffer, stagingBufferMemory);
void *data; void *data;
vkMapMemory(Global::device, stagingBufferMemory, 0, imageSize, 0, &data); vkMapMemory(DeviceControl::getDevice(), stagingBufferMemory, 0, imageSize, 0,
&data);
memcpy(data, pixels, static_cast<size_t>(imageSize)); memcpy(data, pixels, static_cast<size_t>(imageSize));
vkUnmapMemory(Global::device, stagingBufferMemory); vkUnmapMemory(DeviceControl::getDevice(), stagingBufferMemory);
stbi_image_free(pixels); stbi_image_free(pixels);
@ -323,8 +335,8 @@ void Texture::createTextureImage() {
static_cast<uint32_t>(textureWidth), static_cast<uint32_t>(textureWidth),
static_cast<uint32_t>(textureHeight)); static_cast<uint32_t>(textureHeight));
vkDestroyBuffer(Global::device, stagingBuffer, nullptr); vkDestroyBuffer(DeviceControl::getDevice(), stagingBuffer, nullptr);
vkFreeMemory(Global::device, stagingBufferMemory, nullptr); vkFreeMemory(DeviceControl::getDevice(), stagingBufferMemory, nullptr);
generateMipmaps(textureImage, VK_FORMAT_R8G8B8A8_SRGB, textureWidth, generateMipmaps(textureImage, VK_FORMAT_R8G8B8A8_SRGB, textureWidth,
textureHeight, mipLevels); textureHeight, mipLevels);
@ -332,9 +344,9 @@ void Texture::createTextureImage() {
void Texture::createTextureImageView() { void Texture::createTextureImageView() {
// Create a texture image view, which is a struct of information about the // Create a texture image view, which is a struct of information about the
// image. // image.
Global::textureImageView = device_libs::DeviceControl::createImageView( textureImageView =
textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT, DeviceControl::createImageView(textureImage, VK_FORMAT_R8G8B8A8_SRGB,
mipLevels); VK_IMAGE_ASPECT_COLOR_BIT, mipLevels);
} }
void Texture::createTextureSampler() { void Texture::createTextureSampler() {
// Create a sampler to access and parse the texture object. // 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; samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
VkPhysicalDeviceProperties properties{}; VkPhysicalDeviceProperties properties{};
vkGetPhysicalDeviceProperties(Global::physicalDevice, &properties); vkGetPhysicalDeviceProperties(DeviceControl::getPhysicalDevice(),
&properties);
// Enable or Disable Anisotropy, and set the amount. // Enable or Disable Anisotropy, and set the amount.
samplerInfo.anisotropyEnable = VK_TRUE; samplerInfo.anisotropyEnable = VK_TRUE;
samplerInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy; samplerInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy;
@ -376,18 +389,18 @@ void Texture::createTextureSampler() {
samplerInfo.minLod = 0.0f; samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = VK_LOD_CLAMP_NONE; samplerInfo.maxLod = VK_LOD_CLAMP_NONE;
if (vkCreateSampler(Global::device, &samplerInfo, nullptr, if (vkCreateSampler(DeviceControl::getDevice(), &samplerInfo, nullptr,
&Global::textureSampler) != VK_SUCCESS) { &textureSampler) != VK_SUCCESS) {
throw std::runtime_error("failed to create texture sampler!"); throw std::runtime_error("failed to create texture sampler!");
} }
} }
void Texture::destroyTextureSampler() { void Texture::destroyTextureSampler() {
vkDestroySampler(Global::device, Global::textureSampler, nullptr); vkDestroySampler(DeviceControl::getDevice(), textureSampler, nullptr);
vkDestroyImageView(Global::device, Global::textureImageView, nullptr); vkDestroyImageView(DeviceControl::getDevice(), textureImageView, nullptr);
} }
void Texture::destroyTextureImage() { void Texture::destroyTextureImage() {
vkDestroyImage(Global::device, textureImage, nullptr); vkDestroyImage(DeviceControl::getDevice(), textureImage, nullptr);
vkFreeMemory(Global::device, textureImageMemory, nullptr); vkFreeMemory(DeviceControl::getDevice(), textureImageMemory, nullptr);
} }
VkFormat Texture::findDepthFormat() { VkFormat Texture::findDepthFormat() {
return findSupportedFormat( return findSupportedFormat(
@ -396,32 +409,42 @@ VkFormat Texture::findDepthFormat() {
VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
} }
void Texture::createColorResources() { void Texture::createColorResources() {
VkFormat colorFormat = *device_libs::DeviceControl::getImageFormat(); VkFormat colorFormat = DeviceControl::getImageFormat();
VkExtent2D swapChainExtent = device_libs::DeviceControl::getSwapChainExtent(); VkExtent2D swapChainExtent = DeviceControl::getSwapChainExtent();
createImage(swapChainExtent.width, swapChainExtent.height, 1, 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_TRANSIENT_ATTACHMENT_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, Global::colorImage, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, colorImage,
Global::colorImageMemory); colorImageMemory);
Global::colorImageView = device_libs::DeviceControl::createImageView( colorImageView = DeviceControl::createImageView(colorImage, colorFormat,
Global::colorImage, colorFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1); VK_IMAGE_ASPECT_COLOR_BIT, 1);
} }
void Texture::createDepthResources() { void Texture::createDepthResources() {
VkFormat depthFormat = findDepthFormat(); VkFormat depthFormat = findDepthFormat();
VkExtent2D swapChainExtent = device_libs::DeviceControl::getSwapChainExtent(); VkExtent2D swapChainExtent = DeviceControl::getSwapChainExtent();
createImage(swapChainExtent.width, swapChainExtent.height, 1, createImage(
Global::perPixelSampleCount, depthFormat, VK_IMAGE_TILING_OPTIMAL, swapChainExtent.width, swapChainExtent.height, 1,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, DeviceControl::getPerPixelSampleCount(), depthFormat,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, Global::depthImage, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
Global::depthImageMemory); VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImage, depthImageMemory);
Global::depthImageView = device_libs::DeviceControl::createImageView( depthImageView = DeviceControl::createImageView(depthImage, depthFormat,
Global::depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT, 1); VK_IMAGE_ASPECT_DEPTH_BIT, 1);
// Explicit transition from the layout of the image to the depth attachment is // Explicit transition from the layout of the image to the depth attachment is
// unnecessary here, since that will be handled in the render pass! // unnecessary here, since that will be handled in the render pass!
} }
// ---------------------------- Getters & Setters // ---------------------------- Getters & Setters
// ---------------------------------// // ---------------------------------//
uint32_t Texture::getMipLevels() { return mipLevels; } 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; }

View File

@ -1,10 +1,7 @@
#pragma once #pragma once
#include "../devicelibrary.h" #define VK_NO_PROTOTYPES
#include "../global.h" #include "volk.h"
#include "buffers.h"
#include <cstdint> #include <cstdint>
namespace texture_libs {
class Texture { class Texture {
public: public:
static void createTextureImage(); static void createTextureImage();
@ -17,5 +14,14 @@ public:
static void createColorResources(); static void createColorResources();
// ------------ Getters & Setters ------------ // // ------------ Getters & Setters ------------ //
static uint32_t getMipLevels(); 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

View File

@ -1,4 +1,5 @@
#include "entrypoint.h" #include "entrypoint.h"
#include <iostream>
#define VOLK_IMPLEMENTATION #define VOLK_IMPLEMENTATION
int main() { int main() {