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