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