This commit is contained in:
25
src/main.cpp
25
src/main.cpp
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
3
src/utilities/stb_image_impl.cpp
Normal file
3
src/utilities/stb_image_impl.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
Reference in New Issue
Block a user