Files
Vulkan_TestApp/vulkan/vulkan_app.hpp
T
2025-04-04 16:29:13 +02:00

210 lines
6.6 KiB
C++

//
// Created by timo on 03.04.25.
//
#ifndef VULKAN_APP_H
#define VULKAN_APP_H
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <iostream>
#include <stdexcept>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <vector>
#include <optional>
#include <set>
#include <limits>
#include <algorithm>
#include <fstream>
#include <array>
#include <chrono>
namespace vapp{
// Change here for other presentMode
const VkPresentModeKHR WISHED_PRESENT_MODE = VK_PRESENT_MODE_MAILBOX_KHR;
struct Vertex{
glm::vec2 pos;
glm::vec3 color;
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, 2> getAttributeDescriptions(){
std::array<VkVertexInputAttributeDescription, 2> attributeDescriptions{};
attributeDescriptions[0].binding = 0;
attributeDescriptions[0].location = 0;
attributeDescriptions[0].format = VK_FORMAT_R32G32_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);
return attributeDescriptions;
}
};
// TODO: Remove
const std::vector<Vertex> vertices = {
{{-0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
{{0.5f, -0.5f}, {0.0f, 0.0f, 1.0f}},
{{0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}},
{{-0.5f, 0.5f}, {1.0f, 0.0f, 0.0f}}
};
// uint16_t also possible -> change in vkCmdBindIndexBuffer also
const std::vector<uint32_t> indices = { 0, 1, 2, 2, 3, 0 };
// END Remove
struct UniformBufferObject{
glm::mat4 model;
glm::mat4 view;
glm::mat4 proj;
};
struct QueueFamilyIndices{
std::optional<uint32_t> graphicsFamily;
std::optional<uint32_t> presentFamily;
bool isComplete(){
return graphicsFamily.has_value();
}
};
struct SwapChainSupportDetails{
VkSurfaceCapabilitiesKHR capabilities;
std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> presentModes;
};
static std::vector<char> readFile(const std::string& filename);
static std::array<VkVertexInputAttributeDescription, 2> getAttributeDescription();
class Vulkan{
private:
#pragma region Fields
GLFWwindow *window;
uint32_t _width, _height;
VkInstance instance;
VkDebugUtilsMessengerEXT debugMessenger;
VkSurfaceKHR surface;
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
VkDevice device;
VkQueue graphicsQueue;
VkQueue presentQueue;
VkSwapchainKHR swapChain;
std::vector<VkImage> swapChainImages;
VkFormat swapChainImageFormat;
VkExtent2D swapChainExtent;
std::vector<VkImageView> swapChainImageViews;
VkRenderPass renderPass;
VkDescriptorSetLayout descriptorSetLayout;
VkPipelineLayout pipelineLayout;
VkPipeline graphicsPipeline;
VkCommandPool commandPool;
std::vector<VkCommandBuffer> commandBuffers;
std::vector<VkSemaphore> imageAvailableSemaphores, renderFinishedSemaphores;
std::vector<VkFence> inFlightFences;
std::vector<VkFramebuffer> swapChainFramebuffers;
const int MAX_FRAMES_IN_FLIGHT = 2;
uint32_t currentFrame = 0;
VkBuffer vertexBuffer;
VkDeviceMemory vertexBufferMemory;
VkBuffer indexBuffer;
VkDeviceMemory indexBufferMemory;
std::vector<VkBuffer> uniformBuffers;
std::vector<VkDeviceMemory> uniformBuffersMemory;
std::vector<void*> uniformBuffersMapped;
VkDescriptorPool descriptorPool;
std::vector<VkDescriptorSet> descriptorSets;
#pragma endregion
bool checkValidationLayerSupport();
std::vector<const char*> getRequiredExtensions();
void createInstance();
void setupDebugMessenger();
void pickPhysicalDevice();
void createLogicalDevice();
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device);
bool checkDeviceExtensionSupport(VkPhysicalDevice device);
bool isDeviceSuitable(VkPhysicalDevice device);
void createSurface();
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device);
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats);
VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR> availablePresentModes);
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities);
void createSwapChain();
void createImageViews();
void createDescriptorSetLayout();
void createGraphicsPipeline();
VkShaderModule createShaderModule(const std::vector<char>& code);
void createRenderPass();
void createFrameBuffers();
void createCommandPool();
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer &buffer, VkDeviceMemory &bufferMemory);
void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
void createVertexBuffer();
void createIndexBuffer();
void createUniformBuffers();
void createDescriptorPool();
void createDescriptorSets();
void createCommandBuffers();
void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex);
void createSyncObjects();
void updateUniformBuffer(uint32_t currentFrame);
void drawFrame();
void cleanupSwapChain();
void recreateSwapChain();
void initWindow(const char *windowName);
void initVulkan();
void mainLoop();
void cleanup();
public:
#ifdef DEBUG
const bool enableValidationLayers = true;
#else
const bool enableValidationLayers = false;
#endif
bool framebufferResized = false;
void run(const char *windowName, const uint32_t width = 800, const uint32_t height = 600);
};
} // vapp
#endif //VULKAN_APP_H