Implemented image view system for.. viewing images
This commit is contained in:
parent
3bb747bfae
commit
fa14b3fd8f
13
Makefile
13
Makefile
@ -1,6 +1,7 @@
|
||||
CPPFLAGS=-g
|
||||
LDFLAGS=-lglfw -lvulkan -ldl -lpthread -lX11 -lXxf86vm -lXrandr -lXi
|
||||
DEBUGFLAGS=-DDEBUG -fsanitize=address
|
||||
DEBUGFLAGS=-DDEBUG -fsanitize=address
|
||||
GDBFLAGS=
|
||||
SRC=$(shell find . -name *.cpp)
|
||||
OBJ=$(SRC:%.cpp=%.o)
|
||||
|
||||
@ -13,13 +14,19 @@ all: $(BIN)
|
||||
.PHONY: run
|
||||
run: $(BIN)
|
||||
./$(BIN)
|
||||
|
||||
.PHONY: gdb
|
||||
gdb: LDFLAGS+=$(GDBFLAGS)
|
||||
gdb: $(BIN)
|
||||
gdb -q $(BIN)
|
||||
.PHONY: debug
|
||||
debug: LDFLAGS+=$(DEBUGFLAGS)
|
||||
debug: $(BIN)
|
||||
./$(BIN)
|
||||
|
||||
.PHONY: dep
|
||||
dep:
|
||||
sudo pacman -S gcc glfw glm shaderc libxi libxxf86vm
|
||||
sudo pacman -S gcc glfw glm shaderc libxi libxxf86vm gdb
|
||||
.PHONY: info
|
||||
info:
|
||||
@echo "make: Build executable"
|
||||
@ -33,7 +40,7 @@ $(BIN): $(OBJ)
|
||||
g++ $(CPPFLAGS) -o $(BIN) $(OBJ) $(LDFLAGS)
|
||||
|
||||
%.o: %.cpp
|
||||
g++ -c $< -o $@ $(LDFLAGS)
|
||||
g++ -c -g $< -o $@ $(LDFLAGS)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
|
@ -8,5 +8,5 @@
|
||||
- Implement features for maximum fidelity/performance ratio
|
||||
- Implement custom Raytracing and Raymarching protocols
|
||||
- Mess with cutting edge design, VDB's, 3D Guassian Splatting,
|
||||
- 1000000+ FPS on Potato GPUs /s
|
||||
- 1000000+ FPS on Potato GPUs
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "vulkandebuglibs.h"
|
||||
#include "../global.h"
|
||||
using namespace Debug;
|
||||
|
||||
@ -53,7 +54,7 @@ void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& create
|
||||
createInfo.pUserData = nullptr; // Optional
|
||||
}
|
||||
|
||||
void VulkanDebugLibs::vulkanDebugSetup(VkInstanceCreateInfo& createInfo, VkInstance& instance) {
|
||||
void vulkandebuglibs::vulkanDebugSetup(VkInstanceCreateInfo& createInfo, VkInstance& instance) {
|
||||
// This function is quite useful, we first populate the debug create info structure, all the parameters dictating how the debug messenger will operate.
|
||||
// The reason we populate the debug messenger so late is actually on purpose, we need to set the createInfo, which depends on the debugMessenger info,
|
||||
// and if we set it before the creation of the instance, we cant debug vkCreateInstance or vkDestroyInstance! It's timed perfectly as of now.
|
||||
@ -79,14 +80,14 @@ void VulkanDebugLibs::vulkanDebugSetup(VkInstanceCreateInfo& createInfo, VkInsta
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanDebugLibs::checkUnavailableValidationLayers() {
|
||||
void vulkandebuglibs::checkUnavailableValidationLayers() {
|
||||
// Check if we are trying to hook validation layers in without support.
|
||||
if(Global::enableValidationLayers && !checkValidationLayerSupport()) {
|
||||
throw std::runtime_error("Validation layers request, but not available! Are your SDK path variables set?");
|
||||
}
|
||||
}
|
||||
|
||||
bool VulkanDebugLibs::checkValidationLayerSupport() {
|
||||
bool vulkandebuglibs::checkValidationLayerSupport() {
|
||||
// This function is used to check Validation Layer Support, validation layers are the debug trace tools in the Vulkan SDK.
|
||||
// layerCount will be used as the var to keep track of the number of requested validation layer
|
||||
// VkLayerProperties is a structure with data on the layername, desc, versions and etc.
|
||||
@ -131,7 +132,7 @@ VkResult CreateDebugUtilsMessengerEXT(
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanDebugLibs::DestroyDebugUtilsMessengerEXT(VkInstance instance,
|
||||
void vulkandebuglibs::DestroyDebugUtilsMessengerEXT(VkInstance instance,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
// We are doing kind of the same thing as before in the create function, find the address of the DestroyDebugUtils function, and call it.
|
||||
|
||||
@ -141,7 +142,7 @@ void VulkanDebugLibs::DestroyDebugUtilsMessengerEXT(VkInstance instance,
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanDebugLibs::setupDebugMessenger(VkInstance& vulkanInstance) {
|
||||
void vulkandebuglibs::setupDebugMessenger(VkInstance& vulkanInstance) {
|
||||
// This is a pretty simple function! we just pass in the values to build the debug messenger, populate the structure with the data we want,
|
||||
// and safely create it, covering for runtime errors as per usual, this is the first thing that will be called!
|
||||
if(!Global::enableValidationLayers) return;
|
@ -3,7 +3,7 @@
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace Debug {
|
||||
class VulkanDebugLibs {
|
||||
class vulkandebuglibs {
|
||||
|
||||
public:
|
||||
void vulkanDebugSetup(VkInstanceCreateInfo& createInfo, VkInstance& instance);
|
@ -1,4 +1,4 @@
|
||||
#include "DeviceLibrary.h"
|
||||
#include "devicelibrary.h"
|
||||
#include "global.h"
|
||||
|
||||
#include <algorithm>
|
||||
@ -10,6 +10,7 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
namespace DeviceControl {
|
||||
|
||||
@ -23,6 +24,7 @@ namespace DeviceControl {
|
||||
std::vector<VkImage> swapChainImages;
|
||||
VkFormat swapChainImageFormat;
|
||||
VkExtent2D swapChainExtent;
|
||||
std::vector<VkImageView> swapChainImageViews;
|
||||
|
||||
VkQueue graphicsQueue;
|
||||
VkQueue presentQueue;
|
||||
@ -142,7 +144,6 @@ namespace DeviceControl {
|
||||
|
||||
return deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
|
||||
&& deviceFeatures.multiViewport
|
||||
&& deviceFeatures.geometryShader
|
||||
&& indices.isComplete()
|
||||
&& extensionSupported
|
||||
&& swapChainAdequate;
|
||||
@ -166,9 +167,12 @@ namespace DeviceControl {
|
||||
// This is most similarly to standard V-Sync.
|
||||
for(const auto& availablePresentMode : availablePresentModes) {
|
||||
if(availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
|
||||
if(Global::enableValidationLayers) std::cout << "Using Triple Buffering\n" << std::endl;
|
||||
return availablePresentMode;
|
||||
}
|
||||
}
|
||||
|
||||
if(Global::enableValidationLayers) std::cout << "Using FIFO (V-Sync)\n" << std::endl;
|
||||
return VK_PRESENT_MODE_FIFO_KHR;
|
||||
}
|
||||
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window) {
|
||||
@ -179,22 +183,22 @@ namespace DeviceControl {
|
||||
if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) {
|
||||
return capabilities.currentExtent;
|
||||
} else {
|
||||
int width, height;
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
int width, height;
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
|
||||
VkExtent2D actualExtent = {
|
||||
static_cast<uint32_t>(width),
|
||||
static_cast<uint32_t>(height)
|
||||
};
|
||||
VkExtent2D actualExtent = {
|
||||
static_cast<uint32_t>(width),
|
||||
static_cast<uint32_t>(height)
|
||||
};
|
||||
// Clamp the image size to the minimum extent values specified by vulkan for our window manager.
|
||||
actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
|
||||
actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
|
||||
actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
|
||||
actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
|
||||
|
||||
return actualExtent;
|
||||
return actualExtent;
|
||||
}
|
||||
}
|
||||
// --------------------------------------- External Functions -----------------------------------------//
|
||||
void DeviceLibrary::pickPhysicalDevice(VkInstance& instance) {
|
||||
void devicelibrary::pickPhysicalDevice(VkInstance& instance) {
|
||||
uint32_t deviceCount = 0;
|
||||
vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
|
||||
|
||||
@ -206,7 +210,7 @@ namespace DeviceControl {
|
||||
|
||||
for(const auto& device : devices) {
|
||||
if(isDeviceSuitable(device)) {
|
||||
std::cout << "Using device: " << deviceProperties.deviceName << std::endl;
|
||||
if(Global::enableValidationLayers) std::cout << "Using device: " << deviceProperties.deviceName << std::endl;
|
||||
//Once we have buttons or such, maybe ask the user or write a config file for which GPU to use?
|
||||
physicalDevice = device;
|
||||
break;
|
||||
@ -216,17 +220,17 @@ namespace DeviceControl {
|
||||
throw std::runtime_error("Failed to find a suitable GPU!");
|
||||
}
|
||||
}
|
||||
void DeviceLibrary::destroySurface(VkInstance& instance) {
|
||||
void devicelibrary::destroySurface(VkInstance& instance) {
|
||||
vkDestroySurfaceKHR(instance, surface, nullptr);
|
||||
std::cout << "Destroyed surface safely\n" << std::endl;
|
||||
if(Global::enableValidationLayers) std::cout << "Destroyed surface safely\n" << std::endl;
|
||||
}
|
||||
void DeviceLibrary::createSurface(VkInstance& instance, GLFWwindow* window) {
|
||||
void devicelibrary::createSurface(VkInstance& instance, GLFWwindow* window) {
|
||||
if(glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS) {
|
||||
throw std::runtime_error("Failed to create window surface!!");
|
||||
}
|
||||
std::cout << "GLFW Window Surface created successfully\n" << std::endl;
|
||||
if(Global::enableValidationLayers) std::cout << "GLFW Window Surface created successfully\n" << std::endl;
|
||||
}
|
||||
void DeviceLibrary::createLogicalDevice(VkDevice& device) {
|
||||
void devicelibrary::createLogicalDevice(VkDevice& device) {
|
||||
// Describe how many queues we want for a single family (1) here, right now we are solely interested in graphics capabilites,
|
||||
// but Compute Shaders, transfer ops, decode and encode operations can also queued with setup! We also assign each queue a priority.
|
||||
// We do this by looping over all the queueFamilies and sorting them by indices to fill the queue at the end!
|
||||
@ -264,12 +268,12 @@ namespace DeviceControl {
|
||||
if(vkCreateDevice(physicalDevice, &createDeviceInfo, nullptr, &device) != VK_SUCCESS) {
|
||||
throw std::runtime_error("Failed to create logical device");
|
||||
}
|
||||
std::cout << "Created Logical device successfully!\n" << std::endl;
|
||||
if(Global::enableValidationLayers) std::cout << "Created Logical device successfully!\n" << std::endl;
|
||||
|
||||
vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue);
|
||||
vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue);
|
||||
}
|
||||
void DeviceLibrary::createSwapChain(GLFWwindow* window, VkDevice& device) {
|
||||
void devicelibrary::createSwapChain(GLFWwindow* window, VkDevice& device) {
|
||||
SwapChainSupportDetails swapChainSupport = querySwapChainSupport(physicalDevice);
|
||||
|
||||
VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);
|
||||
@ -326,7 +330,7 @@ namespace DeviceControl {
|
||||
if(vkCreateSwapchainKHR(device, &createSwapChainInfo, nullptr, &swapChain) != VK_SUCCESS) {
|
||||
throw std::runtime_error("Failed to create the swap chain!!");
|
||||
}
|
||||
std::cout << "Swap Chain created successfully\n" << std::endl;
|
||||
if(Global::enableValidationLayers) std::cout << "Swap Chain created successfully\n" << std::endl;
|
||||
|
||||
vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr);
|
||||
swapChainImages.resize(imageCount);
|
||||
@ -335,8 +339,42 @@ namespace DeviceControl {
|
||||
swapChainImageFormat = surfaceFormat.format;
|
||||
swapChainExtent = extent;
|
||||
}
|
||||
void DeviceLibrary::destroySwapChain(VkDevice& device) {
|
||||
void devicelibrary::destroySwapChain(VkDevice& device) {
|
||||
vkDestroySwapchainKHR(device, swapChain, nullptr);
|
||||
std::cout << "Destroyed Swap Chain safely\n" << std::endl;
|
||||
if(Global::enableValidationLayers) std::cout << "Destroyed Swap Chain safely\n" << std::endl;
|
||||
}
|
||||
void devicelibrary::createImageViews(VkDevice& device) {
|
||||
swapChainImageViews.resize(swapChainImages.size());
|
||||
for(size_t i = 0; i < swapChainImages.size(); i++) {
|
||||
VkImageViewCreateInfo createImageViewInfo{};
|
||||
createImageViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
createImageViewInfo.image = swapChainImages[i];
|
||||
// Are we treating images as 1D, 2D or 3D?
|
||||
createImageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
createImageViewInfo.format = swapChainImageFormat;
|
||||
// Allow us to swizzle color channels
|
||||
createImageViewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
createImageViewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
createImageViewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
createImageViewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
|
||||
createImageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
createImageViewInfo.subresourceRange.baseMipLevel = 0;
|
||||
createImageViewInfo.subresourceRange.levelCount = 1;
|
||||
createImageViewInfo.subresourceRange.baseArrayLayer = 0;
|
||||
// Yet another setting we would increase for VR applications, and specifically create a swap chain with more layers as well. The other layers would be the eye outputs.
|
||||
createImageViewInfo.subresourceRange.layerCount = 1;
|
||||
|
||||
if(vkCreateImageView(device, &createImageViewInfo, nullptr, &swapChainImageViews[i]) != VK_SUCCESS) {
|
||||
throw std::runtime_error("failed to create image views!");
|
||||
}
|
||||
if(Global::enableValidationLayers) std::cout << "Image views created successfully\n" << std::endl;
|
||||
}
|
||||
}
|
||||
void devicelibrary::destroyImageViews(VkDevice& device) {
|
||||
for (auto imageView : swapChainImageViews) {
|
||||
vkDestroyImageView(device, imageView, nullptr);
|
||||
}
|
||||
if(Global::enableValidationLayers) std::cout << "Image destroyed safely\n" << std::endl;
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "global.h"
|
||||
namespace DeviceControl {
|
||||
class DeviceLibrary {
|
||||
class devicelibrary {
|
||||
public:
|
||||
|
||||
void pickPhysicalDevice(VkInstance& instance);
|
||||
@ -10,6 +10,8 @@ namespace DeviceControl {
|
||||
void destroySurface(VkInstance& instance);
|
||||
void createSwapChain(GLFWwindow* window, VkDevice& device);
|
||||
void destroySwapChain(VkDevice& device);
|
||||
void createImageViews(VkDevice& device);
|
||||
void destroyImageViews(VkDevice& device);
|
||||
};
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "debug/VulkanDebugLibs.h"
|
||||
#include "debug/vulkandebuglibs.h"
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
19
src/main.cpp
19
src/main.cpp
@ -1,6 +1,5 @@
|
||||
|
||||
#include "DeviceLibrary.h" // Device Library includes global, redundant to include with it here
|
||||
#include "debug/VulkanDebugLibs.h"
|
||||
#include "devicelibrary.h" // Device Library includes global, redundant to include with it here
|
||||
#include "debug/vulkandebuglibs.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
@ -22,8 +21,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
DeviceControl::DeviceLibrary deviceLibs;
|
||||
Debug::VulkanDebugLibs debugController;
|
||||
DeviceControl::devicelibrary deviceLibs;
|
||||
Debug::vulkandebuglibs debugController;
|
||||
|
||||
GLFWwindow* window;
|
||||
VkInstance instance;
|
||||
@ -42,15 +41,16 @@ private:
|
||||
|
||||
void initVulkan() {
|
||||
createInstance();
|
||||
debugController.setupDebugMessenger(instance); // The debug messenger is out holy grail, it gives us Vulkan related debug info when built with the -DNDEBUG flag (as per the makefile)
|
||||
debugController.setupDebugMessenger(instance); // The debug messenger is out holy grail, it gives us Vulkan related debug info when built with the -DNDEBUG flag (as per the makefile)
|
||||
deviceLibs.createSurface(instance, window);
|
||||
deviceLibs.pickPhysicalDevice(instance);
|
||||
deviceLibs.createLogicalDevice(device);
|
||||
deviceLibs.createSwapChain(window, device);
|
||||
deviceLibs.createImageViews(device);
|
||||
}
|
||||
|
||||
void createInstance() {
|
||||
debugController.checkUnavailableValidationLayers(); // Check if there is a mistake with our Validation Layers.
|
||||
debugController.checkUnavailableValidationLayers(); // Check if there is a mistake with our Validation Layers.
|
||||
|
||||
// Set application info for the vulkan instance!
|
||||
VkApplicationInfo appInfo{};
|
||||
@ -66,7 +66,7 @@ private:
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; // Tell vulkan this is a info structure
|
||||
createInfo.pApplicationInfo = &appInfo; // We just created a new appInfo structure, so we pass the pointer to it.
|
||||
|
||||
debugController.vulkanDebugSetup(createInfo, instance); // Handoff to the debug library to wrap the validation libs in! (And set the window up!)
|
||||
debugController.vulkanDebugSetup(createInfo, instance); // Handoff to the debug library to wrap the validation libs in! (And set the window up!)
|
||||
}
|
||||
|
||||
void mainLoop() { // This loop just updates the GLFW window.
|
||||
@ -75,7 +75,8 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup() { // Similar to the last handoff, destroy the debug util in a safe manner in the library!
|
||||
void cleanup() { // Similar to the last handoff, destroy the utils in a safe manner in the library!
|
||||
deviceLibs.destroyImageViews(device);
|
||||
deviceLibs.destroySwapChain(device);
|
||||
vkDestroyDevice(device, nullptr);
|
||||
if(Global::enableValidationLayers) {
|
||||
|
Loading…
Reference in New Issue
Block a user