2026-02-19 11:03:22 -05:00
parent 96213d6cb3
commit 023a06c0cd
43 changed files with 9736 additions and 226 deletions

View File

@@ -4,13 +4,28 @@
#include "VulkanFramebuffers.h"
#include "VulkanSwapChain.h"
#include "VulkanVertexBuffer.h"
#include "utilities/Logger.h"
#include "stb_image.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_vulkan.h"
#include "utilities/Logger.h"
#include <GLFW/glfw3.h>
#include <glm/ext/matrix_clip_space.hpp>
#include <glm/ext/matrix_transform.hpp>
#include <glm/fwd.hpp>
#include <glm/trigonometric.hpp>
#include <vulkan/vulkan_core.h>
#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEFAULT_ALIGNED_GENTYPES
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <chrono>
#include <cstdint>
#include <vector>
#include <vulkan/vulkan_core.h>
VulkanContext::VulkanContext()
{
@@ -20,7 +35,7 @@ VulkanContext::~VulkanContext()
{
}
void VulkanContext::Initialize(FVulkanConfig& InConfig, const std::vector<Vertex>& InVertices)
void VulkanContext::Initialize(FVulkanConfig& InConfig, const std::vector<Vertex>& InVertices, const std::vector<uint16_t>& InIndices)
{
Config = InConfig;
@@ -62,8 +77,10 @@ void VulkanContext::Initialize(FVulkanConfig& InConfig, const std::vector<Vertex
RenderPass.Initialize(DeviceManager.GetDevice());
RenderPass.CreateRenderPass(SwapChain.GetSwapChainImageFormat());
CreateDescriptorSetLayout();
GraphicsPipeline.Initialize(DeviceManager.GetDevice());
GraphicsPipeline.CreateGraphicsPipeline(SwapChain.GetSwapChainExtent(), RenderPass.GetRenderPass());
GraphicsPipeline.CreateGraphicsPipeline(SwapChain.GetSwapChainExtent(), RenderPass.GetRenderPass(), DescriptorSetLayout);
Framebuffers.Initialize(FFramebufferConfig(
DeviceManager.GetDevice(),
@@ -75,8 +92,19 @@ void VulkanContext::Initialize(FVulkanConfig& InConfig, const std::vector<Vertex
CommandBuffers.Initialize(DeviceManager.GetDevice(), RenderPass.GetRenderPass());
CommandBuffers.CreateCommandPool(DeviceManager.GetPhysicalQueueFamilies().GraphicsFamily);
VertexBuffer.Initialize(FVertexBufferConfig(DeviceManager.GetDevice(), DeviceManager.GetPhysicalDevice()));
CreateTextureImage("textures/texture.jpg");
VertexBuffer.Initialize(FVertexBufferConfig(
DeviceManager.GetDevice(),
DeviceManager.GetPhysicalDevice(),
CommandBuffers.GetCommandPool(),
DeviceManager.GetGraphicsQueue()));
VertexBuffer.CreateVertexBuffer(InVertices);
VertexBuffer.CreateIndexBuffer(InIndices);
VertexBuffer.CreateUniformBuffers(MAX_FRAMES_IN_FLIGHT);
CreateDescriptorPool();
CreateDescriptorSets();
CommandBuffers.CreateCommandBuffers(MAX_FRAMES_IN_FLIGHT);
@@ -118,7 +146,10 @@ void VulkanContext::Cleanup()
CleanupSwapChain();
VertexBuffer.Cleanup();
vkDestroyDescriptorPool(DeviceManager.GetDevice(), DescriptorPool, nullptr);
vkDestroyDescriptorSetLayout(DeviceManager.GetDevice(), DescriptorSetLayout, nullptr);
VertexBuffer.Cleanup(MAX_FRAMES_IN_FLIGHT);
GraphicsPipeline.Cleanup();
RenderPass.Cleanup();
@@ -183,6 +214,187 @@ void VulkanContext::CreateSurface(GLFWwindow* Window)
}
}
void VulkanContext::CreateDescriptorSetLayout()
{
VkDescriptorSetLayoutBinding UboLayoutBinding{};
UboLayoutBinding.binding = 0;
UboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
UboLayoutBinding.descriptorCount = 1;
UboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
UboLayoutBinding.pImmutableSamplers = nullptr;
VkDescriptorSetLayoutCreateInfo LayoutInfo{};
LayoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
LayoutInfo.bindingCount = 1;
LayoutInfo.pBindings = &UboLayoutBinding;
if (vkCreateDescriptorSetLayout(DeviceManager.GetDevice(), &LayoutInfo, nullptr, &DescriptorSetLayout) != VK_SUCCESS)
{
Log::Error("Failed to create descriptor set layout!");
}
else
{
Log::Info("Successfully created descriptor set layout.");
}
}
void VulkanContext::CreateDescriptorPool()
{
VkDescriptorPoolSize PoolSize{};
PoolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
PoolSize.descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
VkDescriptorPoolCreateInfo PoolInfo{};
PoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
PoolInfo.poolSizeCount = 1;
PoolInfo.pPoolSizes = &PoolSize;
PoolInfo.maxSets = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
if (vkCreateDescriptorPool(DeviceManager.GetDevice(), &PoolInfo, nullptr, &DescriptorPool) != VK_SUCCESS)
{
Log::Error("Failed to create descriptor pool!");
}
else
{
Log::Info("Successfully created descriptor pool.");
}
}
void VulkanContext::CreateDescriptorSets()
{
std::vector<VkDescriptorSetLayout> Layouts(MAX_FRAMES_IN_FLIGHT, DescriptorSetLayout);
VkDescriptorSetAllocateInfo AllocateInfo{};
AllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
AllocateInfo.descriptorPool = DescriptorPool;
AllocateInfo.descriptorSetCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
AllocateInfo.pSetLayouts = Layouts.data();
DescriptorSets.resize(MAX_FRAMES_IN_FLIGHT);
if (vkAllocateDescriptorSets(DeviceManager.GetDevice(), &AllocateInfo, DescriptorSets.data()) != VK_SUCCESS)
{
Log::Error("Failed to allocate descriptor sets!");
}
else
{
Log::Info("Successfully allocated descriptor sets.");
}
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
{
VkDescriptorBufferInfo BufferInfo{};
BufferInfo.buffer = VertexBuffer.GetUniformBuffers()[i];
BufferInfo.offset = 0;
BufferInfo.range = sizeof(UniformBufferObject);
VkWriteDescriptorSet DescriptorWrite{};
DescriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
DescriptorWrite.dstSet = DescriptorSets[i];
DescriptorWrite.dstBinding = 0;
DescriptorWrite.dstArrayElement = 0;
DescriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
DescriptorWrite.descriptorCount = 1;
DescriptorWrite.pBufferInfo = &BufferInfo;
DescriptorWrite.pImageInfo = nullptr;
DescriptorWrite.pTexelBufferView = nullptr;
vkUpdateDescriptorSets(DeviceManager.GetDevice(), 1, &DescriptorWrite, 0, nullptr);
}
}
void VulkanContext::CreateImage(
uint32_t Width,
uint32_t Height,
VkFormat Format,
VkImageTiling Tiling,
VkImageUsageFlags Usage,
VkMemoryPropertyFlags Properties,
VkImage& Image,
VkDeviceMemory& ImageMemory)
{
VkImageCreateInfo ImageInfo{};
ImageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
ImageInfo.imageType = VK_IMAGE_TYPE_2D;
ImageInfo.extent.width = Width;
ImageInfo.extent.height = Height;
ImageInfo.extent.depth = 1;
ImageInfo.mipLevels = 1;
ImageInfo.arrayLayers = 1;
ImageInfo.format = Format;
ImageInfo.tiling = Tiling;
ImageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
ImageInfo.usage = Usage;
ImageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
ImageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (vkCreateImage(DeviceManager.GetDevice(), &ImageInfo, nullptr, &Image) != VK_SUCCESS)
{
Log::Error("Failed to create image!");
}
else
{
Log::Info("Successfully created image.");
}
VkMemoryRequirements MemoryRequirements;
vkGetImageMemoryRequirements(DeviceManager.GetDevice(), Image, &MemoryRequirements);
VkMemoryAllocateInfo AllocateInfo{};
AllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
AllocateInfo.allocationSize = MemoryRequirements.size;
AllocateInfo.memoryTypeIndex = VertexBuffer.FindMemoryType(MemoryRequirements.memoryTypeBits, Properties);
if (vkAllocateMemory(DeviceManager.GetDevice(), &AllocateInfo, nullptr, &ImageMemory) != VK_SUCCESS)
{
Log::Error("Failed to allocate image memory!");
}
else
{
Log::Info("Successfully allocated imaged memory.");
}
vkBindImageMemory(DeviceManager.GetDevice(), Image, ImageMemory, 0);
}
void VulkanContext::CreateTextureImage(const char* FileName)
{
int TextureWidth, TextureHeight, TextureChannels;
stbi_uc* Pixels = stbi_load(FileName, &TextureWidth, &TextureHeight, &TextureChannels, STBI_rgb_alpha);
VkDeviceSize ImageSize = TextureWidth * TextureHeight * 4;
if (!Pixels)
{
Log::Error("Failed to load texture image!");
}
else
{
Log::Info("Successfully loaded texture image.");
}
VkBuffer StagingBuffer;
VkDeviceMemory StagingBufferMemory;
VertexBuffer.CreateBuffer(ImageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, StagingBuffer, StagingBufferMemory);
void* Data;
vkMapMemory(DeviceManager.GetDevice(), StagingBufferMemory, 0, ImageSize, 0, &Data);
memcpy(Data, Pixels, static_cast<size_t>(ImageSize));
vkUnmapMemory(DeviceManager.GetDevice(), StagingBufferMemory);
stbi_image_free(Pixels);
CreateImage(
TextureWidth,
TextureHeight,
VK_FORMAT_R8G8B8A8_SRGB,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
TextureImage,
TextureImageMemory);
}
void VulkanContext::CreateSyncObjects()
{
ImageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
@@ -211,7 +423,7 @@ void VulkanContext::CreateSyncObjects()
}
}
void VulkanContext::DrawFrame(bool bDrawImGui, uint32_t InVerticesSize)
void VulkanContext::DrawFrame(bool bDrawImGui, uint32_t InVerticesSize, uint32_t InIndexSize)
{
vkWaitForFences(DeviceManager.GetDevice(), 1, &InFlightFences[CurrentFrame], VK_TRUE, UINT64_MAX);
@@ -243,16 +455,22 @@ void VulkanContext::DrawFrame(bool bDrawImGui, uint32_t InVerticesSize)
ImageIndex,
VertexBuffer.GetVertexBuffer(),
InVerticesSize,
VertexBuffer.GetIndexBuffer(),
InIndexSize,
RenderPass.GetRenderPass(),
SwapChain.GetSwapChainExtent(),
GraphicsPipeline.GetGraphicsPipeline(),
Framebuffers.GetSwapChainFrameBuffers(),
DescriptorSets[CurrentFrame],
GraphicsPipeline.GetPipelineLayout(),
bDrawImGui
// DrawData
};
CommandBuffers.RecordCommandBuffer(Params);
UpdateUniformBuffer(CurrentFrame);
VkSubmitInfo SubmitInfo{};
SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
@@ -302,6 +520,23 @@ void VulkanContext::DrawFrame(bool bDrawImGui, uint32_t InVerticesSize)
CurrentFrame = (CurrentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
}
void VulkanContext::UpdateUniformBuffer(uint32_t CurrentImage)
{
static auto StartTime = std::chrono::high_resolution_clock::now();
auto CurrentTime = std::chrono::high_resolution_clock::now();
float Time = std::chrono::duration<float, std::chrono::seconds::period>(CurrentTime - StartTime).count();
UniformBufferObject Ubo{};
Ubo.Model = glm::rotate(glm::mat4(1.0f), Time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
Ubo.View = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
Ubo.Projection = glm::perspective(glm::radians(45.0f), SwapChain.GetSwapChainExtent().width / (float)SwapChain.GetSwapChainExtent().height, 0.1f, 10.0f);
Ubo.Projection[1][1] *= -1;
memcpy(VertexBuffer.GetUniformBuffersMapped()[CurrentImage], &Ubo, sizeof(Ubo));
}
void VulkanContext::RecreateSwapChain()
{
int Width = 0, Height = 0;