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

View File

@@ -21,10 +21,21 @@ struct AppConfig
bool bVerboseLogging = false;
};
const std::vector<Vertex> TriangleVertices = {
{ { 0.0f, -0.5f }, { 1.0f, 1.0f, 1.0f } },
{ { 0.5f, 0.5f }, { 0.0f, 1.0f, 0.0f } },
{ { -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f } }
// const std::vector<Vertex> TriangleVertices = {
// { { 0.0f, -0.5f }, { 1.0f, 1.0f, 1.0f } },
// { { 0.5f, 0.5f }, { 0.0f, 1.0f, 0.0f } },
// { { -0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f } }
// };
const std::vector<Vertex> SquareVertices = {
{ { -0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f } },
{ { 0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f } },
{ { 0.5f, 0.5f }, { 0.0f, 0.0f, 1.0f } },
{ { -0.5f, 0.5f }, { 1.0f, 1.0f, 1.0f } }
};
const std::vector<uint16_t> SquareIndices = {
0, 1, 2, 2, 3, 0
};
class HelloTriangleApplication
@@ -44,7 +55,7 @@ private:
GlfwWindowManager WindowManager;
VulkanContext VkContext;
bool bShowImGui = true;
bool bShowImGui = false;
bool bShowDemo = false;
static void KeyCallback(GLFWwindow* Window, int Key, int Scancode, int Action, int Mods)
@@ -89,7 +100,7 @@ private:
Settings.bVerboseLogging,
WindowManager.GetWindow(),
};
VkContext.Initialize(Config, TriangleVertices);
VkContext.Initialize(Config, SquareVertices, SquareIndices);
}
void InitGlfw()
@@ -141,7 +152,7 @@ private:
}
}
VkContext.DrawFrame(bShowImGui, TriangleVertices.size());
VkContext.DrawFrame(bShowImGui, SquareVertices.size(), SquareIndices.size());
}
}

View File

@@ -103,8 +103,12 @@ void VulkanCommandBuffers::RecordCommandBuffer(FRecordCommandBuffersParams& Para
VkBuffer VertexBuffers[] = { Params.InVertexBuffer };
VkDeviceSize Offsets[] = { 0 };
vkCmdBindVertexBuffers(Params.InCommandBuffer, 0, 1, VertexBuffers, Offsets);
vkCmdBindIndexBuffer(Params.InCommandBuffer, Params.InIndexBuffer, 0, VK_INDEX_TYPE_UINT16);
vkCmdDraw(Params.InCommandBuffer, static_cast<uint32_t>(Params.InVerticesSize), 1, 0, 0);
vkCmdBindDescriptorSets(Params.InCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, Params.PipelineLayout, 0, 1, &Params.DescriptorSet, 0, nullptr);
// vkCmdDraw(Params.InCommandBuffer, static_cast<uint32_t>(Params.InVerticesSize), 1, 0, 0);
vkCmdDrawIndexed(Params.InCommandBuffer, static_cast<uint32_t>(Params.InIndexSize), 1, 0, 0, 0);
if (Params.bDrawImGui)
{

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;

View File

@@ -22,7 +22,7 @@ void VulkanPipeline::Cleanup()
vkDestroyPipelineLayout(Device, PipelineLayout, nullptr);
}
void VulkanPipeline::CreateGraphicsPipeline(VkExtent2D SwapChainExtent, VkRenderPass RenderPass)
void VulkanPipeline::CreateGraphicsPipeline(VkExtent2D SwapChainExtent, VkRenderPass RenderPass, VkDescriptorSetLayout& DescriptorSetLayout)
{
auto VertShaderCode = ReadFile("Shaders/vert.spv");
auto FragShaderCode = ReadFile("Shaders/frag.spv");
@@ -97,7 +97,7 @@ void VulkanPipeline::CreateGraphicsPipeline(VkExtent2D SwapChainExtent, VkRender
Rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
Rasterizer.lineWidth = 1.0f;
Rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
Rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
Rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
Rasterizer.depthBiasEnable = VK_FALSE;
Rasterizer.depthBiasConstantFactor = 0.0f;
Rasterizer.depthBiasClamp = 0.0f;
@@ -135,8 +135,8 @@ void VulkanPipeline::CreateGraphicsPipeline(VkExtent2D SwapChainExtent, VkRender
VkPipelineLayoutCreateInfo PipelineLayoutInfo{};
PipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
PipelineLayoutInfo.setLayoutCount = 0;
PipelineLayoutInfo.pSetLayouts = nullptr;
PipelineLayoutInfo.setLayoutCount = 1;
PipelineLayoutInfo.pSetLayouts = &DescriptorSetLayout;
PipelineLayoutInfo.pushConstantRangeCount = 0;
PipelineLayoutInfo.pPushConstantRanges = nullptr;

View File

@@ -9,38 +9,47 @@ void VulkanVertexBuffer::Initialize(FVertexBufferConfig InConfig)
Config = InConfig;
}
void VulkanVertexBuffer::Cleanup()
void VulkanVertexBuffer::Cleanup(const uint32_t MAX_FRAMES_IN_FLIGHT)
{
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
{
vkDestroyBuffer(Config.Device, UniformBuffers[i], nullptr);
vkFreeMemory(Config.Device, UniformBuffersMemory[i], nullptr);
}
vkDestroyBuffer(Config.Device, IndexBuffer, nullptr);
vkFreeMemory(Config.Device, IndexBufferMemory, nullptr);
vkDestroyBuffer(Config.Device, VertexBuffer, nullptr);
vkFreeMemory(Config.Device, VertexBufferMemory, nullptr);
}
void VulkanVertexBuffer::CreateVertexBuffer(const std::vector<Vertex>& InVertices)
void VulkanVertexBuffer::CreateBuffer(VkDeviceSize Size, VkBufferUsageFlags Usage, VkMemoryPropertyFlags Properties, VkBuffer& Buffer, VkDeviceMemory& BufferMemory)
{
VkBufferCreateInfo BufferInfo{};
BufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
BufferInfo.size = sizeof(InVertices[0]) * InVertices.size();
BufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
BufferInfo.size = Size;
BufferInfo.usage = Usage;
BufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (vkCreateBuffer(Config.Device, &BufferInfo, nullptr, &VertexBuffer) != VK_SUCCESS)
if (vkCreateBuffer(Config.Device, &BufferInfo, nullptr, &Buffer) != VK_SUCCESS)
{
Log::Error("Failed to create vertex buffer!");
Log::Error("Failed to create buffer!");
}
else
{
Log::Info("Successfully created vertex buffer.");
Log::Info("Successfully created buffer.");
}
VkMemoryRequirements MemoryRequirements;
vkGetBufferMemoryRequirements(Config.Device, VertexBuffer, &MemoryRequirements);
vkGetBufferMemoryRequirements(Config.Device, Buffer, &MemoryRequirements);
VkMemoryAllocateInfo AllocateInfo{};
AllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
AllocateInfo.allocationSize = MemoryRequirements.size;
AllocateInfo.memoryTypeIndex = FindMemoryType(MemoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
AllocateInfo.memoryTypeIndex = FindMemoryType(MemoryRequirements.memoryTypeBits, Properties);
if (vkAllocateMemory(Config.Device, &AllocateInfo, nullptr, &VertexBufferMemory) != VK_SUCCESS)
if (vkAllocateMemory(Config.Device, &AllocateInfo, nullptr, &BufferMemory) != VK_SUCCESS)
{
Log::Error("Failed to allocate vertex buffer memory!");
}
@@ -49,12 +58,104 @@ void VulkanVertexBuffer::CreateVertexBuffer(const std::vector<Vertex>& InVertice
Log::Info("Successfully allocated vertex buffer memory.");
}
vkBindBufferMemory(Config.Device, VertexBuffer, VertexBufferMemory, 0);
vkBindBufferMemory(Config.Device, Buffer, BufferMemory, 0);
}
void VulkanVertexBuffer::CopyBuffer(VkBuffer SrcBuffer, VkBuffer DstBuffer, VkDeviceSize Size)
{
VkCommandBufferAllocateInfo AllocateInfo{};
AllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
AllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
AllocateInfo.commandPool = Config.CommandPool;
AllocateInfo.commandBufferCount = 1;
VkCommandBuffer CommandBuffer;
vkAllocateCommandBuffers(Config.Device, &AllocateInfo, &CommandBuffer);
VkCommandBufferBeginInfo BeginInfo{};
BeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
BeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(CommandBuffer, &BeginInfo);
VkBufferCopy CopyRegion{};
CopyRegion.srcOffset = 0;
CopyRegion.dstOffset = 0;
CopyRegion.size = Size;
vkCmdCopyBuffer(CommandBuffer, SrcBuffer, DstBuffer, 1, &CopyRegion);
vkEndCommandBuffer(CommandBuffer);
VkSubmitInfo SubmitInfo{};
SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
SubmitInfo.commandBufferCount = 1;
SubmitInfo.pCommandBuffers = &CommandBuffer;
vkQueueSubmit(Config.GraphicsQueue, 1, &SubmitInfo, VK_NULL_HANDLE);
vkQueueWaitIdle(Config.GraphicsQueue);
vkFreeCommandBuffers(Config.Device, Config.CommandPool, 1, &CommandBuffer);
}
void VulkanVertexBuffer::CreateVertexBuffer(const std::vector<Vertex>& InVertices)
{
VkDeviceSize BufferSize = sizeof(InVertices[0]) * InVertices.size();
VkBuffer StagingBuffer;
VkDeviceMemory StagingBufferMemory;
CreateBuffer(BufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, StagingBuffer, StagingBufferMemory);
Log::Info("Starting buffer copy...");
void* Data;
vkMapMemory(Config.Device, VertexBufferMemory, 0, BufferInfo.size, 0, &Data);
memcpy(Data, InVertices.data(), (size_t)BufferInfo.size);
vkUnmapMemory(Config.Device, VertexBufferMemory);
vkMapMemory(Config.Device, StagingBufferMemory, 0, BufferSize, 0, &Data);
memcpy(Data, InVertices.data(), (size_t)BufferSize);
vkUnmapMemory(Config.Device, StagingBufferMemory);
Log::Info("Finished buffer copy...");
CreateBuffer(BufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VertexBuffer, VertexBufferMemory);
CopyBuffer(StagingBuffer, VertexBuffer, BufferSize);
vkDestroyBuffer(Config.Device, StagingBuffer, nullptr);
vkFreeMemory(Config.Device, StagingBufferMemory, nullptr);
}
void VulkanVertexBuffer::CreateIndexBuffer(const std::vector<uint16_t>& InIndices)
{
VkDeviceSize BufferSize = sizeof(InIndices[0]) * InIndices.size();
VkBuffer StagingBuffer;
VkDeviceMemory StagingBufferMemory;
CreateBuffer(BufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, StagingBuffer, StagingBufferMemory);
Log::Info("Starting buffer copy...");
void* Data;
vkMapMemory(Config.Device, StagingBufferMemory, 0, BufferSize, 0, &Data);
memcpy(Data, InIndices.data(), (size_t)BufferSize);
vkUnmapMemory(Config.Device, StagingBufferMemory);
Log::Info("Finished buffer copy...");
CreateBuffer(BufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, IndexBuffer, IndexBufferMemory);
CopyBuffer(StagingBuffer, IndexBuffer, BufferSize);
vkDestroyBuffer(Config.Device, StagingBuffer, nullptr);
vkFreeMemory(Config.Device, StagingBufferMemory, nullptr);
}
void VulkanVertexBuffer::CreateUniformBuffers(const uint32_t MAX_FRAMES_IN_FLIGHT)
{
VkDeviceSize BufferSize = sizeof(UniformBufferObject);
UniformBuffers.resize(MAX_FRAMES_IN_FLIGHT);
UniformBuffersMemory.resize(MAX_FRAMES_IN_FLIGHT);
UniformBuffersMapped.resize(MAX_FRAMES_IN_FLIGHT);
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
{
CreateBuffer(BufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, UniformBuffers[i], UniformBuffersMemory[i]);
vkMapMemory(Config.Device, UniformBuffersMemory[i], 0, BufferSize, 0, &UniformBuffersMapped[i]);
}
}
uint32_t VulkanVertexBuffer::FindMemoryType(uint32_t TypeFilter, VkMemoryPropertyFlags Properties)
@@ -71,4 +172,5 @@ uint32_t VulkanVertexBuffer::FindMemoryType(uint32_t TypeFilter, VkMemoryPropert
}
Log::Error("Failed to find suitable memory type!");
return 0;
}

View File

@@ -16,10 +16,14 @@ struct FRecordCommandBuffersParams
uint32_t ImageIndex;
VkBuffer InVertexBuffer;
uint32_t InVerticesSize;
VkBuffer InIndexBuffer;
uint32_t InIndexSize;
VkRenderPass RenderPass;
VkExtent2D SwapChainExtent;
VkPipeline GraphicsPipeline;
std::vector<VkFramebuffer> SwapChainFramebuffers;
VkDescriptorSet DescriptorSet;
VkPipelineLayout PipelineLayout;
bool bDrawImGui = false;
// std::vector<Vertex> InVertices;
// ImDrawData* DrawData = nullptr;
@@ -42,11 +46,12 @@ public:
std::vector<VkCommandBuffer> GetCommandBuffers() { return CommandBuffers; }
VkCommandBuffer GetCommandBuffer(int i) { return CommandBuffers[i]; }
VkCommandPool GetCommandPool() { return CommandPool; }
private:
VkDevice Device;
VkRenderPass RenderPass;
VkQueue GraphicsQueue;
// VkQueue GraphicsQueue;
std::vector<VkCommandBuffer> CommandBuffers;
VkCommandPool CommandPool;

View File

@@ -11,6 +11,7 @@
#include "VulkanVertexBuffer.h"
#include <cstdint>
#include <string>
#include <vector>
#include <vulkan/vulkan_core.h>
@@ -29,8 +30,6 @@ struct FVulkanConfig
// std::vector<Vertex> Vertices;
};
static FVulkanConfig Config = {};
class VulkanContext
{
public:
@@ -46,15 +45,34 @@ public:
VulkanFramebuffers Framebuffers;
VulkanVertexBuffer VertexBuffer;
VulkanCommandBuffers CommandBuffers;
VkDescriptorPool ImGuiPool;
void Initialize(FVulkanConfig& InConfig, const std::vector<Vertex>& InVertices);
void Initialize(FVulkanConfig& InConfig, const std::vector<Vertex>& InVertices, const std::vector<uint16_t>& InIndices);
void Cleanup();
void CreateSurface(GLFWwindow* Window);
void CreateDescriptorSetLayout();
void CreateDescriptorPool();
void CreateDescriptorSets();
void CreateImage(
uint32_t Width,
uint32_t Height,
VkFormat Format,
VkImageTiling Tiling,
VkImageUsageFlags Usage,
VkMemoryPropertyFlags Properties,
VkImage& Image,
VkDeviceMemory& ImageMemory);
void CreateTextureImage(const char* FileName);
void CreateSyncObjects();
void DrawFrame(bool bDrawImGui = false, uint32_t InVerticesSize = 0);
void DrawFrame(bool bDrawImGui, uint32_t InVerticesSize, uint32_t InIndexSize);
void UpdateUniformBuffer(uint32_t CurrentImage);
void RecreateSwapChain();
void InitImGui();
void CleanupSwapChain();
// void DrawFrame(ImDrawData* DrawData = nullptr);
@@ -64,16 +82,26 @@ public:
void SetFramebufferResized(bool bResized) { bFramebufferResized = bResized; }
private:
VkSurfaceKHR Surface = VK_NULL_HANDLE;
FVulkanConfig Config = {};
VkSurfaceKHR Surface = VK_NULL_HANDLE;
std::vector<VkSemaphore> ImageAvailableSemaphores;
std::vector<VkSemaphore> RenderFinishedSemaphores;
std::vector<VkFence> InFlightFences;
VkDescriptorPool ImGuiPool;
VkDescriptorSetLayout DescriptorSetLayout;
VkDescriptorPool DescriptorPool;
std::vector<VkDescriptorSet> DescriptorSets;
VkImage TextureImage;
VkDeviceMemory TextureImageMemory;
bool bFramebufferResized = false;
bool bImGuiGlfwInitialized = false;
bool bImGuiVulkanInitialized = false;
const int MAX_FRAMES_IN_FLIGHT = 2;
uint32_t CurrentFrame = 0;
const size_t MAX_FRAMES_IN_FLIGHT = 2;
uint32_t CurrentFrame = 0;
};

View File

@@ -14,9 +14,10 @@ public:
VkShaderModule CreateShaderModule(const std::vector<char>& Code);
void CreateGraphicsPipeline(VkExtent2D SwapChainExtent, VkRenderPass RenderPass);
void CreateGraphicsPipeline(VkExtent2D SwapChainExtent, VkRenderPass RenderPass, VkDescriptorSetLayout& DescriptorSetLayout);
VkPipeline GetGraphicsPipeline() { return GraphicsPipeline; }
VkPipeline GetGraphicsPipeline() { return GraphicsPipeline; }
VkPipelineLayout GetPipelineLayout() { return PipelineLayout; }
private:
VkDevice Device;

View File

@@ -2,7 +2,6 @@
#include "Primitives.h"
#include <optional>
#include <vector>
#include <vulkan/vulkan_core.h>
@@ -13,6 +12,8 @@ struct FVertexBufferConfig
{
VkDevice Device;
VkPhysicalDevice PhysicalDevice;
VkCommandPool CommandPool;
VkQueue GraphicsQueue;
};
class VulkanVertexBuffer
@@ -20,16 +21,35 @@ class VulkanVertexBuffer
public:
void Initialize(FVertexBufferConfig InConfig);
void Cleanup();
void Cleanup(const uint32_t MAX_FRAMES_IN_FLIGHT);
void CreateBuffer(VkDeviceSize Size, VkBufferUsageFlags Usage, VkMemoryPropertyFlags Properties, VkBuffer& Buffer, VkDeviceMemory& BufferMemory);
void CopyBuffer(VkBuffer SrcBuffer, VkBuffer DstBuffer, VkDeviceSize Size);
void CreateVertexBuffer(const std::vector<Vertex>& InVertices);
void CreateIndexBuffer(const std::vector<uint16_t>& InIndices);
void CreateUniformBuffers(const uint32_t MAX_FRAMES_IN_FLIGHT);
uint32_t FindMemoryType(uint32_t TypeFilter, VkMemoryPropertyFlags Properties);
VkBuffer GetVertexBuffer() { return VertexBuffer; }
VkBuffer GetVertexBuffer() { return VertexBuffer; }
VkBuffer GetIndexBuffer() { return IndexBuffer; }
std::vector<VkBuffer> GetUniformBuffers() { return UniformBuffers; }
std::vector<void*> GetUniformBuffersMapped() { return UniformBuffersMapped; }
private:
FVertexBufferConfig Config;
VkBuffer VertexBuffer;
VkDeviceMemory VertexBufferMemory;
VkBuffer VertexBuffer;
VkDeviceMemory VertexBufferMemory;
VkBuffer IndexBuffer;
VkDeviceMemory IndexBufferMemory;
std::vector<VkBuffer> UniformBuffers;
std::vector<VkDeviceMemory> UniformBuffersMemory;
std::vector<void*> UniformBuffersMapped;
};

View File

@@ -34,3 +34,10 @@ struct Vertex
return AttributeDescriptions;
}
};
struct UniformBufferObject
{
alignas(16) glm::mat4 Model;
alignas(16) glm::mat4 View;
alignas(16) glm::mat4 Projection;
};

View File

@@ -0,0 +1,3 @@
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"