Files
Archimedes/renderer/vulkanRenderer.h
2024-10-02 00:49:38 -05:00

297 lines
9.3 KiB
C++
Executable File

#pragma once
#include "engine.h"
#include "sdl2Window.h"
const std::string MODEL_PATH = "/home/nathan/Projects/terminal/assets/viking_room.obj";
const std::string TEXTURE_PATH = "/home/nathan/Pictures/Mountain.png";
struct QueueFamilyIndices {
std::optional<uint32_t> graphicsFamily;
std::optional<uint32_t> presentFamily;
bool isComplete() {
return graphicsFamily.has_value() && presentFamily.has_value();
}
};
struct SwapChainSupportDetails {
VkSurfaceCapabilitiesKHR capabilities;
std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> presentModes;
};
static std::vector<char> readFile(const std::string& filename) {
std::ifstream file(filename, std::ios::ate | std::ios::binary);
if (!file.is_open()) {
throw std::runtime_error("failed to open file!");
}
size_t fileSize = (size_t) file.tellg();
std::vector<char> buffer(fileSize);
file.seekg(0);
file.read(buffer.data(), fileSize);
file.close();
return buffer;
}
struct Vertex {
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;
}
};
struct UniformBufferObject {
alignas(16) glm::mat4 model;
alignas(16) glm::mat4 view;
alignas(16) glm::mat4 proj;
};
const std::vector<Vertex> vertices = {
{{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
{{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
{{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
{{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}},
{{-0.5f, -0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
{{0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
{{0.5f, 0.5f, -0.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
{{-0.5f, 0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}
};
const std::vector<uint32_t> indices = {
0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4
};
class Renderer {
public:
Renderer();
~Renderer();
inline VkInstance getInstance() { return instance; }
inline VkPhysicalDevice getPhysicalDevice() { return physicalDevice; }
inline VkDevice getDevice() { return device; }
uint32_t getQueueFamily();
inline VkQueue getGraphicsQueue() { return graphicsQueue; }
inline VkQueue getPresentQueue() { return presentQueue; }
inline VkSurfaceKHR getSurface() { return surface; }
inline VkRenderPass getRenderPass() { return renderPass; }
inline VkDescriptorPool getDescriptorPool() { return descriptorPool; }
inline VkCommandBuffer getCommandBuffer(int frame) { return commandBuffers[frame]; }
inline VkPipeline getPipeline() { return graphicsPipeline; }
inline int getNumImages() { return MAX_FRAMES_IN_FLIGHT; }
inline int getFrame() { return currentFrame; }
inline VkSampleCountFlagBits getMSAASamples() { return msaaSamples; }
private:
const int MAX_FRAMES_IN_FLIGHT = 2;
VkInstance instance;
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
VkDevice device;
VkQueue graphicsQueue;
VkQueue presentQueue;
VkSurfaceKHR surface;
VkSwapchainKHR swapChain;
std::vector<VkImage> swapChainImages;
VkFormat swapChainImageFormat;
VkExtent2D swapChainExtent;
VkRenderPass renderPass;
VkDescriptorPool descriptorPool;
std::vector<VkDescriptorSet> descriptorSets;
VkDescriptorSetLayout descriptorSetLayout;
VkPipelineLayout pipelineLayout;
VkPipeline graphicsPipeline;
std::vector<VkFramebuffer> swapChainFramebuffers;
std::vector<VkImageView> swapChainImageViews;
VkCommandPool commandPool;
std::vector<VkCommandBuffer> commandBuffers;
std::vector<VkSemaphore> imageAvailableSemaphores;
std::vector<VkSemaphore> renderFinishedSemaphores;
std::vector<VkFence> inFlightFences;
uint32_t currentFrame = 0;
VkBuffer vertexBuffer;
VkDeviceMemory vertexBufferMemory;
VkBuffer indexBuffer;
VkDeviceMemory indexBufferMemory;
std::vector<VkBuffer> uniformBuffers;
std::vector<VkDeviceMemory> uniformBuffersMemory;
std::vector<void*> uniformBuffersMapped;
VkImage textureImage;
VkDeviceMemory textureImageMemory;
VkImageView textureImageView;
VkSampler textureSampler;
VkImage depthImage;
VkDeviceMemory depthImageMemory;
VkImageView depthImageView;
VkSampleCountFlagBits msaaSamples = VK_SAMPLE_COUNT_1_BIT;
VkImage colorImage;
VkDeviceMemory colorImageMemory;
VkImageView colorImageView;
VkResult err;
bool enableValidationLayers = false;
const std::vector<const char*> deviceExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME
};
public:
void init();
void shutdown();
void draw();
void createInstance();
void pickPhysicalDevice();
void createLogicalDevice();
void createSurface();
void createSwapChain();
void createImageViews();
void createDescriptorPool();
void createDescriptorSets();
void createDescriptorSetLayout();
void createGraphicsPipeline();
void createRenderPass();
void createFramebuffers();
void createCommandPool();
void createVertexBuffer();
void createIndexBuffer();
void createUniformBuffers();
void updateUniformBuffer(uint32_t);
void createBuffer(VkDeviceSize, VkBufferUsageFlags, VkMemoryPropertyFlags, VkBuffer&, VkDeviceMemory&);
void createCommandBuffer();
void recordCommandBuffer(VkCommandBuffer, uint32_t);
void createSyncObjects();
void loadModel();
bool hasStencilComponent(VkFormat);
VkFormat findDepthFormat();
VkFormat findSupportedFormat(const std::vector<VkFormat>&, VkImageTiling, VkFormatFeatureFlags);
void createDepthResources();
VkImageView createImageView(VkImage, VkFormat, VkImageAspectFlags);
void copyBufferToImage(VkBuffer, VkImage, uint32_t, uint32_t);
void createTextureSampler();
void createTextureImageView();
void transitionImageLayout(VkImage, VkFormat, VkImageLayout, VkImageLayout);
VkCommandBuffer beginSingleTimeCommands();
void endSingleTimeCommands(VkCommandBuffer);
void createImage(uint32_t, uint32_t, VkFormat, VkImageTiling, VkImageUsageFlags, VkMemoryPropertyFlags, VkImage&, VkDeviceMemory&);
void createTextureImage();
VkSampleCountFlagBits getMaxUsableSampleCount();
void copyBuffer(VkBuffer, VkBuffer, VkDeviceSize);
uint32_t findMemoryType(uint32_t, VkMemoryPropertyFlags);
void recreateSwapChain();
void cleanupSwapChain();
VkShaderModule createShaderModule(const std::vector<char>&);
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR&);
VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR>&);
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>&);
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice);
bool checkDeviceExtensionSupport(VkPhysicalDevice);
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice);
bool isDeviceSuitable(VkPhysicalDevice);
bool isExtensionAvailable(const std::vector<VkExtensionProperties>&, const char*);
void check_vk_result();
};