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