Finished depth buffer

This commit is contained in:
2026-02-20 14:00:53 -05:00
parent 023a06c0cd
commit 0e784b7ad2
64 changed files with 7390 additions and 3524 deletions

View File

@@ -2,13 +2,15 @@
#include <GLFW/glfw3.h>
#include <cstdint>
#include <vulkan/vulkan_core.h>
#include "VulkanDeviceManager.h"
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_vulkan.h"
#include "utilities/Logger.h"
#include "GlfwWindowManager.h"
#include "VulkanContext.h"
#include "VulkanContext.hpp"
#include "Primitives.h"
struct AppConfig
{
@@ -28,15 +30,18 @@ struct AppConfig
// };
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 } }
{ { -0.5f, -0.5f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f } },
{ { 0.5f, -0.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f } },
{ { 0.5f, 0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f } },
{ { -0.5f, 0.5f, 0.0f }, { 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f } },
{ { -0.5f, -0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f } },
{ { 0.5f, -0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f } },
{ { 0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f } },
{ { -0.5f, 0.5f, -0.5f }, { 1.0f, 1.0f, 1.0f }, { 1.0f, 1.0f } }
};
const std::vector<uint16_t> SquareIndices = {
0, 1, 2, 2, 3, 0
};
const std::vector<uint16_t> SquareIndices = { 0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4 };
class HelloTriangleApplication
{
@@ -105,13 +110,11 @@ private:
void InitGlfw()
{
FWindowConfig Config = {
Settings.Title,
Settings.Width,
Settings.Height,
Settings.bResizable,
Settings.bFullscreen
};
FWindowConfig Config = { Settings.Title,
Settings.Width,
Settings.Height,
Settings.bResizable,
Settings.bFullscreen };
WindowManager.Initialize(Config);
glfwSetWindowUserPointer(WindowManager.GetWindow(), this);
@@ -129,7 +132,7 @@ private:
void MainLoop()
{
VkPhysicalDeviceProperties Properties{};
vkGetPhysicalDeviceProperties(VkContext.DeviceManager.GetPhysicalDevice(), &Properties);
vkGetPhysicalDeviceProperties(VkContext.DeviceManager->GetPhysicalDevice(), &Properties);
while (!WindowManager.ShouldClose())
{

View File

@@ -0,0 +1,479 @@
#include "VulkanBuffers.h"
#include "imgui.h"
#include "imgui_impl_vulkan.h"
#include "utilities/Logger.h"
#include <cstddef>
#include <vulkan/vulkan_core.h>
void VulkanBuffers::Initialize(FBufferConfig InConfig)
// VkDevice InDevice,
// VkRenderPass InRenderPass)
{
Config = InConfig;
}
void VulkanBuffers::Cleanup(size_t MAX_FRAMES_IN_FLIGHT)
{
vkDestroyCommandPool(Config.Device, CommandPool, nullptr);
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 VulkanBuffers::CreateCommandPool(std::optional<uint32_t> GraphicsFamily)
{
VkCommandPoolCreateInfo PoolInfo{};
PoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
PoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
PoolInfo.queueFamilyIndex = GraphicsFamily.value();
if (vkCreateCommandPool(Config.Device, &PoolInfo, nullptr, &CommandPool) != VK_SUCCESS)
{
Log::Error("Failed to create command pool!");
}
else
{
Log::Info("Successfully created command pool");
}
}
void VulkanBuffers::CreateCommandBuffers(int FramesInFlight)
{
CommandBuffers.resize(FramesInFlight);
VkCommandBufferAllocateInfo AllocateInfo{};
AllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
AllocateInfo.commandPool = CommandPool;
AllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
AllocateInfo.commandBufferCount = (uint32_t)CommandBuffers.size();
if (vkAllocateCommandBuffers(Config.Device, &AllocateInfo, CommandBuffers.data()) != VK_SUCCESS)
{
Log::Error("Failed to allocate command buffers!");
}
else
{
Log::Info("Successfully allocated command buffers.");
}
}
void VulkanBuffers::RecordCommandBuffer(FRecordBuffersParams& Params)
{
VkCommandBufferBeginInfo BeginInfo{};
BeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
BeginInfo.flags = 0;
BeginInfo.pInheritanceInfo = nullptr;
if (vkBeginCommandBuffer(Params.InCommandBuffer, &BeginInfo) != VK_SUCCESS)
{
Log::Error("Failed to begin recording command buffer!");
}
else
{
// Log::Info("Successfully began recording command buffers.");
}
VkRenderPassBeginInfo RenderPassInfo{};
RenderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
RenderPassInfo.renderPass = Config.RenderPass;
RenderPassInfo.framebuffer = Params.SwapChainFramebuffers[Params.ImageIndex];
RenderPassInfo.renderArea.offset = { 0, 0 };
RenderPassInfo.renderArea.extent = { Params.SwapChainExtent };
std::array<VkClearValue, 2> ClearValues{};
ClearValues[0].color = { { 0.0f, 0.0f, 0.0f, 1.0f } };
ClearValues[1].depthStencil = { 1.0f, 0 };
RenderPassInfo.clearValueCount = static_cast<uint32_t>(ClearValues.size());
RenderPassInfo.pClearValues = ClearValues.data();
vkCmdBeginRenderPass(Params.InCommandBuffer, &RenderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(
Params.InCommandBuffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
Params.GraphicsPipeline
);
VkViewport Viewport{};
Viewport.x = 0.0f;
Viewport.y = 0.0f;
Viewport.width = static_cast<float>(Params.SwapChainExtent.width);
Viewport.height = static_cast<float>(Params.SwapChainExtent.height);
Viewport.minDepth = 0.0f;
Viewport.maxDepth = 1.0f;
vkCmdSetViewport(Params.InCommandBuffer, 0, 1, &Viewport);
VkRect2D Scissor{};
Scissor.offset = { 0, 0 };
Scissor.extent = Params.SwapChainExtent;
vkCmdSetScissor(Params.InCommandBuffer, 0, 1, &Scissor);
VkBuffer VertexBuffers[] = { Params.InVertexBuffer };
VkDeviceSize Offsets[] = { 0 };
vkCmdBindVertexBuffers(Params.InCommandBuffer, 0, 1, VertexBuffers, Offsets);
vkCmdBindIndexBuffer(Params.InCommandBuffer, Params.InIndexBuffer, 0, VK_INDEX_TYPE_UINT16);
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)
{
ImGui::Render();
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), Params.InCommandBuffer);
}
vkCmdEndRenderPass(Params.InCommandBuffer);
if (vkEndCommandBuffer(Params.InCommandBuffer) != VK_SUCCESS)
{
Log::Error("Failed to record command buffer!");
}
else
{
// Log::Info("Successfully recorded command buffer.");
}
}
VkCommandBuffer VulkanBuffers::BeginSingleTimeCommands()
{
VkCommandBufferAllocateInfo AllocateInfo{};
AllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
AllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
AllocateInfo.commandPool = 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);
return CommandBuffer;
}
void VulkanBuffers::EndSingleTimeCommands(VkCommandBuffer InCommandBuffer, VkQueue GraphicsQueue)
{
vkEndCommandBuffer(InCommandBuffer);
VkSubmitInfo SubmitInfo{};
SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
SubmitInfo.commandBufferCount = 1;
SubmitInfo.pCommandBuffers = &InCommandBuffer;
vkQueueSubmit(GraphicsQueue, 1, &SubmitInfo, VK_NULL_HANDLE);
vkQueueWaitIdle(GraphicsQueue);
vkFreeCommandBuffers(Config.Device, CommandPool, 1, &InCommandBuffer);
}
void VulkanBuffers::TransitionImageLayout(
VkImage Image,
VkFormat Format,
VkImageLayout OldLayout,
VkImageLayout NewLayout,
bool bHasStencilComponent
)
{
VkCommandBuffer CommandBuffer = BeginSingleTimeCommands();
VkImageMemoryBarrier Barrier{};
Barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
Barrier.oldLayout = OldLayout;
Barrier.newLayout = NewLayout;
Barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
Barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
Barrier.image = Image;
Barrier.subresourceRange.baseMipLevel = 0;
Barrier.subresourceRange.levelCount = 1;
Barrier.subresourceRange.baseArrayLayer = 0;
Barrier.subresourceRange.layerCount = 1;
Barrier.srcAccessMask = 0;
Barrier.dstAccessMask = 0;
VkPipelineStageFlags SourceStage;
VkPipelineStageFlags DestinationStage;
if (NewLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
{
Barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
if (bHasStencilComponent)
{
Barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
}
}
else
{
Barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
}
if (OldLayout == VK_IMAGE_LAYOUT_UNDEFINED && NewLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
{
Barrier.srcAccessMask = 0;
Barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
SourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
DestinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
}
else if (OldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
&& NewLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
{
Barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
Barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
SourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
DestinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
}
else if (OldLayout == VK_IMAGE_LAYOUT_UNDEFINED
&& NewLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
{
Barrier.srcAccessMask = 0;
Barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
SourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
DestinationStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
}
else
{
Log::Error("Unsupported layout transition!");
}
vkCmdPipelineBarrier(
CommandBuffer,
SourceStage,
DestinationStage,
0,
0,
nullptr,
0,
nullptr,
1,
&Barrier
);
EndSingleTimeCommands(CommandBuffer, Config.GraphicsQueue);
}
void VulkanBuffers::CopyBufferToImage(
VkBuffer Buffer,
VkImage Image,
uint32_t Width,
uint32_t Height
)
{
VkCommandBuffer CommandBuffer = BeginSingleTimeCommands();
VkBufferImageCopy Region{};
Region.bufferOffset = 0;
Region.bufferRowLength = 0;
Region.bufferImageHeight = 0;
Region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
Region.imageSubresource.mipLevel = 0;
Region.imageSubresource.baseArrayLayer = 0;
Region.imageSubresource.layerCount = 1;
Region.imageOffset = { 0, 0, 0 };
Region.imageExtent = { Width, Height, 1 };
vkCmdCopyBufferToImage(
CommandBuffer,
Buffer,
Image,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,
&Region
);
EndSingleTimeCommands(CommandBuffer, Config.GraphicsQueue);
}
void VulkanBuffers::CopyBuffer(
VkQueue GraphicsQueue,
VkBuffer SrcBuffer,
VkBuffer DstBuffer,
VkDeviceSize Size
)
{
VkCommandBuffer CommandBuffer = BeginSingleTimeCommands();
VkBufferCopy CopyRegion{};
CopyRegion.size = Size;
vkCmdCopyBuffer(CommandBuffer, SrcBuffer, DstBuffer, 1, &CopyRegion);
EndSingleTimeCommands(CommandBuffer, GraphicsQueue);
}
void VulkanBuffers::CreateBuffer(
VkDeviceSize Size,
VkBufferUsageFlags Usage,
VkMemoryPropertyFlags Properties,
VkBuffer& Buffer,
VkDeviceMemory& BufferMemory
)
{
VkBufferCreateInfo BufferInfo{};
BufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
BufferInfo.size = Size;
BufferInfo.usage = Usage;
BufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (vkCreateBuffer(Config.Device, &BufferInfo, nullptr, &Buffer) != VK_SUCCESS)
{
throw std::runtime_error("failed to create buffer!");
}
VkMemoryRequirements MemRequirements;
vkGetBufferMemoryRequirements(Config.Device, Buffer, &MemRequirements);
VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = MemRequirements.size;
allocInfo.memoryTypeIndex = FindMemoryType(MemRequirements.memoryTypeBits, Properties);
if (vkAllocateMemory(Config.Device, &allocInfo, nullptr, &BufferMemory) != VK_SUCCESS)
{
throw std::runtime_error("failed to allocate buffer memory!");
}
vkBindBufferMemory(Config.Device, Buffer, BufferMemory, 0);
}
void VulkanBuffers::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, 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(Config.GraphicsQueue, StagingBuffer, VertexBuffer, BufferSize);
vkDestroyBuffer(Config.Device, StagingBuffer, nullptr);
vkFreeMemory(Config.Device, StagingBufferMemory, nullptr);
}
void VulkanBuffers::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(Config.GraphicsQueue, StagingBuffer, IndexBuffer, BufferSize);
vkDestroyBuffer(Config.Device, StagingBuffer, nullptr);
vkFreeMemory(Config.Device, StagingBufferMemory, nullptr);
}
void VulkanBuffers::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 VulkanBuffers::FindMemoryType(uint32_t TypeFilter, VkMemoryPropertyFlags Properties)
{
VkPhysicalDeviceMemoryProperties MemoryProperties;
vkGetPhysicalDeviceMemoryProperties(Config.PhysicalDevice, &MemoryProperties);
for (uint32_t i = 0; i < MemoryProperties.memoryTypeCount; i++)
{
if ((TypeFilter & (1 << i))
&& (MemoryProperties.memoryTypes[i].propertyFlags & Properties) == Properties)
{
return i;
}
}
Log::Error("Failed to find suitable memory type!");
return 0;
}

View File

@@ -1,129 +0,0 @@
#include "VulkanCommandBuffers.h"
#include "imgui.h"
#include "imgui_impl_vulkan.h"
#include "utilities/Logger.h"
#include <cstdint>
#include <vulkan/vulkan_core.h>
void VulkanCommandBuffers::Initialize(
VkDevice InDevice,
VkRenderPass InRenderPass)
{
Device = InDevice;
RenderPass = InRenderPass;
}
void VulkanCommandBuffers::Cleanup()
{
vkDestroyCommandPool(Device, CommandPool, nullptr);
}
void VulkanCommandBuffers::CreateCommandPool(std::optional<uint32_t> GraphicsFamily)
{
VkCommandPoolCreateInfo PoolInfo{};
PoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
PoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
PoolInfo.queueFamilyIndex = GraphicsFamily.value();
if (vkCreateCommandPool(Device, &PoolInfo, nullptr, &CommandPool) != VK_SUCCESS)
{
Log::Error("Failed to create command pool!");
}
else
{
Log::Info("Successfully created command pool");
}
}
void VulkanCommandBuffers::CreateCommandBuffers(int FramesInFlight)
{
CommandBuffers.resize(FramesInFlight);
VkCommandBufferAllocateInfo AllocateInfo{};
AllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
AllocateInfo.commandPool = CommandPool;
AllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
AllocateInfo.commandBufferCount = (uint32_t)CommandBuffers.size();
if (vkAllocateCommandBuffers(Device, &AllocateInfo, CommandBuffers.data()) != VK_SUCCESS)
{
Log::Error("Failed to allocate command buffers!");
}
else
{
Log::Info("Successfully allocated command buffers.");
}
}
void VulkanCommandBuffers::RecordCommandBuffer(FRecordCommandBuffersParams& Params)
{
VkCommandBufferBeginInfo BeginInfo{};
BeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
BeginInfo.flags = 0;
BeginInfo.pInheritanceInfo = nullptr;
if (vkBeginCommandBuffer(Params.InCommandBuffer, &BeginInfo) != VK_SUCCESS)
{
Log::Error("Failed to begin recording command buffer!");
}
else
{
// Log::Info("Successfully began recording command buffers.");
}
VkRenderPassBeginInfo RenderPassInfo{};
RenderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
RenderPassInfo.renderPass = RenderPass;
RenderPassInfo.framebuffer = Params.SwapChainFramebuffers[Params.ImageIndex];
RenderPassInfo.renderArea.offset = { 0, 0 };
RenderPassInfo.renderArea.extent = { Params.SwapChainExtent };
VkClearValue ClearColor = { { { 0.0f, 0.0f, 0.0f, 1.0f } } };
RenderPassInfo.clearValueCount = 1;
RenderPassInfo.pClearValues = &ClearColor;
vkCmdBeginRenderPass(Params.InCommandBuffer, &RenderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(Params.InCommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, Params.GraphicsPipeline);
VkViewport Viewport{};
Viewport.x = 0.0f;
Viewport.y = 0.0f;
Viewport.width = static_cast<float>(Params.SwapChainExtent.width);
Viewport.height = static_cast<float>(Params.SwapChainExtent.height);
Viewport.minDepth = 0.0f;
Viewport.maxDepth = 1.0f;
vkCmdSetViewport(Params.InCommandBuffer, 0, 1, &Viewport);
VkRect2D Scissor{};
Scissor.offset = { 0, 0 };
Scissor.extent = Params.SwapChainExtent;
vkCmdSetScissor(Params.InCommandBuffer, 0, 1, &Scissor);
VkBuffer VertexBuffers[] = { Params.InVertexBuffer };
VkDeviceSize Offsets[] = { 0 };
vkCmdBindVertexBuffers(Params.InCommandBuffer, 0, 1, VertexBuffers, Offsets);
vkCmdBindIndexBuffer(Params.InCommandBuffer, Params.InIndexBuffer, 0, VK_INDEX_TYPE_UINT16);
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)
{
ImGui::Render();
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), Params.InCommandBuffer);
}
vkCmdEndRenderPass(Params.InCommandBuffer);
if (vkEndCommandBuffer(Params.InCommandBuffer) != VK_SUCCESS)
{
Log::Error("Failed to record command buffer!");
}
else
{
// Log::Info("Successfully recorded command buffer.");
}
}

View File

@@ -1,15 +1,24 @@
#include "VulkanContext.h"
#include "VulkanCommandBuffers.h"
#include "VulkanContext.hpp"
#include "VulkanTexture.hpp"
#include "VulkanBuffers.h"
#include "VulkanDebugManager.h"
// #include "VulkanDepthPass.hpp"
#include "VulkanDeviceManager.h"
#include "VulkanFramebuffers.h"
#include "VulkanInstanceManager.hpp"
#include "VulkanPipeline.h"
#include "VulkanRenderPass.h"
#include "VulkanSwapChain.h"
#include "VulkanVertexBuffer.h"
#include "utilities/Logger.h"
#include "stb_image.h"
#include <chrono>
#include <cstdint>
#include <memory>
#include <vector>
#include "imgui_impl_glfw.h"
#include "imgui_impl_vulkan.h"
#include "stb_image.h"
#include <GLFW/glfw3.h>
#include <glm/ext/matrix_clip_space.hpp>
@@ -20,120 +29,152 @@
#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEFAULT_ALIGNED_GENTYPES
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <chrono>
#include <cstdint>
#include <vector>
#include "utilities/Logger.h"
VulkanContext::VulkanContext()
{
}
VulkanContext::VulkanContext() {}
VulkanContext::~VulkanContext()
{
}
VulkanContext::~VulkanContext() {}
void VulkanContext::Initialize(FVulkanConfig& InConfig, const std::vector<Vertex>& InVertices, const std::vector<uint16_t>& InIndices)
void VulkanContext::Initialize(
FVulkanConfig& InConfig,
const std::vector<Vertex>& InVertices,
const std::vector<uint16_t>& InIndices
)
{
Config = InConfig;
InstanceManager = std::make_unique<VulkanInstanceManager>();
DebugManager = std::make_unique<VulkanDebugManager>();
if (Config.bValidationEnabled)
{
InstanceManager.CreateInstance(&DebugManager);
DebugManager.Initialize(InstanceManager.GetInstance());
InstanceManager->CreateInstance(DebugManager.get());
DebugManager->Initialize(InstanceManager->GetInstance());
}
else
{
InstanceManager.CreateInstance();
InstanceManager->CreateInstance();
}
CreateSurface(InConfig.Window);
DeviceManager.Initialize(FDeviceConfig(
InstanceManager.GetInstance(),
Config.bValidationEnabled,
DeviceManager = std::make_unique<VulkanDeviceManager>(
InstanceManager->GetInstance(),
Surface,
InConfig.Window));
DeviceManager.PickPhysicalDevice();
DeviceManager.CreateLogicalDevice();
InConfig.Window,
Config.bValidationEnabled
);
DeviceManager->PickPhysicalDevice();
DeviceManager->CreateLogicalDevice();
auto SwapChainSupport = DeviceManager.QuerySwapChainSupport(DeviceManager.GetPhysicalDevice());
VkDevice Device = DeviceManager->GetDevice();
VkPhysicalDevice PhysicalDevice = DeviceManager->GetPhysicalDevice();
VkQueue GraphicsQueue = DeviceManager->GetGraphicsQueue();
SwapChain.Initialize(FSwapConfig(
DeviceManager.GetDevice(),
RenderPass = std::make_unique<VulkanRenderPass>();
RenderPass->Initialize(Device);
GraphicsPipeline = std::make_unique<VulkanPipeline>();
GraphicsPipeline->Initialize(Device);
auto SwapChainSupport = DeviceManager->QuerySwapChainSupport(PhysicalDevice);
SwapChain = std::make_unique<VulkanSwapChain>(
Device,
Surface,
Config.Window,
DeviceManager.GetPhysicalQueueFamilies().GraphicsFamily,
DeviceManager.GetPhysicalQueueFamilies().PresentFamily,
DeviceManager->GetPhysicalQueueFamilies().GraphicsFamily.value(),
DeviceManager->GetPhysicalQueueFamilies().PresentFamily.value(),
SwapChainSupport.Capabilities,
SwapChainSupport.Formats,
SwapChainSupport.PresentModes));
SwapChainSupport.PresentModes
);
SwapChain->CreateSwapChain();
SwapChain->CreateImageViews();
SwapChain.CreateSwapChain();
SwapChain.CreateImageViews();
Buffers = std::make_unique<VulkanBuffers>();
RenderPass.Initialize(DeviceManager.GetDevice());
RenderPass.CreateRenderPass(SwapChain.GetSwapChainImageFormat());
Textures = std::make_unique<VulkanTexture>(
Device,
PhysicalDevice,
GraphicsQueue,
*Buffers,
*SwapChain
);
uint32_t imageCount = SwapChain->GetSwapChainImagesCount();
MAX_FRAMES_IN_FLIGHT = imageCount;
RenderPass->CreateRenderPass(SwapChain->GetSwapChainImageFormat(), Textures->FindDepthFormat());
CreateDescriptorSetLayout();
GraphicsPipeline.Initialize(DeviceManager.GetDevice());
GraphicsPipeline.CreateGraphicsPipeline(SwapChain.GetSwapChainExtent(), RenderPass.GetRenderPass(), DescriptorSetLayout);
GraphicsPipeline->CreateGraphicsPipeline(
SwapChain->GetSwapChainExtent(),
RenderPass->GetRenderPass(),
DescriptorSetLayout
);
Framebuffers.Initialize(FFramebufferConfig(
DeviceManager.GetDevice(),
RenderPass.GetRenderPass(),
SwapChain.GetSwapChainImageViews(),
SwapChain.GetSwapChainExtent()));
Framebuffers.CreateFramebuffers();
Buffers->Initialize(
FBufferConfig(Device, RenderPass->GetRenderPass(), PhysicalDevice, GraphicsQueue)
);
Buffers->CreateCommandPool(DeviceManager->GetPhysicalQueueFamilies().GraphicsFamily);
CommandBuffers.Initialize(DeviceManager.GetDevice(), RenderPass.GetRenderPass());
CommandBuffers.CreateCommandPool(DeviceManager.GetPhysicalQueueFamilies().GraphicsFamily);
Textures->CreateDepthResources();
CreateTextureImage("textures/texture.jpg");
Framebuffers = std::make_unique<VulkanFramebuffers>();
Framebuffers->Initialize(FFramebufferConfig(
Device,
RenderPass->GetRenderPass(),
SwapChain->GetSwapChainImageViews(),
SwapChain->GetSwapChainExtent()
));
Framebuffers->CreateFramebuffers(Textures->GetDepthImageView());
VertexBuffer.Initialize(FVertexBufferConfig(
DeviceManager.GetDevice(),
DeviceManager.GetPhysicalDevice(),
CommandBuffers.GetCommandPool(),
DeviceManager.GetGraphicsQueue()));
VertexBuffer.CreateVertexBuffer(InVertices);
VertexBuffer.CreateIndexBuffer(InIndices);
VertexBuffer.CreateUniformBuffers(MAX_FRAMES_IN_FLIGHT);
Log::Info("textures");
Textures->LoadFromFile("textures/texture.jpg");
Textures->CreateImageView();
Textures->CreateSampler();
Buffers->CreateVertexBuffer(InVertices);
Buffers->CreateIndexBuffer(InIndices);
Buffers->CreateUniformBuffers(MAX_FRAMES_IN_FLIGHT);
CreateDescriptorPool();
CreateDescriptorSets();
CommandBuffers.CreateCommandBuffers(MAX_FRAMES_IN_FLIGHT);
Buffers->CreateCommandBuffers(MAX_FRAMES_IN_FLIGHT);
CreateSyncObjects();
VkDescriptorPoolSize PoolSizes[] = {
{ VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 }
};
VkDescriptorPoolSize PoolSizes[] = { { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 } };
VkDescriptorPoolCreateInfo PoolInfo = {};
PoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
PoolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
PoolInfo.maxSets = 1000;
PoolInfo.poolSizeCount = (uint32_t)std::size(PoolSizes);
PoolInfo.pPoolSizes = PoolSizes;
vkCreateDescriptorPool(DeviceManager.GetDevice(), &PoolInfo, nullptr, &ImGuiPool);
vkCreateDescriptorPool(DeviceManager->GetDevice(), &PoolInfo, nullptr, &ImGuiPool);
}
void VulkanContext::Cleanup()
{
vkDeviceWaitIdle(DeviceManager->GetDevice());
if (bImGuiVulkanInitialized)
{
ImGui_ImplVulkan_Shutdown();
@@ -144,34 +185,41 @@ void VulkanContext::Cleanup()
ImGui_ImplGlfw_Shutdown();
}
CleanupSwapChain();
Textures->Cleanup();
Framebuffers->Cleanup();
SwapChain->Cleanup();
vkDestroyDescriptorPool(DeviceManager.GetDevice(), DescriptorPool, nullptr);
vkDestroyDescriptorSetLayout(DeviceManager.GetDevice(), DescriptorSetLayout, nullptr);
// vkDestroySampler(DeviceManager->GetDevice(), TextureSampler, nullptr);
// vkDestroyImageView(DeviceManager->GetDevice(), TextureImageView, nullptr);
VertexBuffer.Cleanup(MAX_FRAMES_IN_FLIGHT);
vkDestroyDescriptorPool(DeviceManager->GetDevice(), ImGuiPool, nullptr);
// vkDestroyImage(DeviceManager->GetDevice(), TextureImage, nullptr);
// vkFreeMemory(DeviceManager->GetDevice(), TextureImageMemory, nullptr);
GraphicsPipeline.Cleanup();
RenderPass.Cleanup();
vkDestroyDescriptorPool(DeviceManager->GetDevice(), DescriptorPool, nullptr);
vkDestroyDescriptorSetLayout(DeviceManager->GetDevice(), DescriptorSetLayout, nullptr);
Buffers->Cleanup(MAX_FRAMES_IN_FLIGHT);
GraphicsPipeline->Cleanup();
RenderPass->Cleanup();
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
{
vkDestroySemaphore(DeviceManager.GetDevice(), ImageAvailableSemaphores[i], nullptr);
vkDestroySemaphore(DeviceManager.GetDevice(), RenderFinishedSemaphores[i], nullptr);
vkDestroyFence(DeviceManager.GetDevice(), InFlightFences[i], nullptr);
vkDestroySemaphore(DeviceManager->GetDevice(), ImageAvailableSemaphores[i], nullptr);
vkDestroySemaphore(DeviceManager->GetDevice(), RenderFinishedSemaphores[i], nullptr);
vkDestroyFence(DeviceManager->GetDevice(), InFlightFences[i], nullptr);
}
CommandBuffers.Cleanup();
DeviceManager.Cleanup();
DeviceManager->Cleanup();
if (Config.bValidationEnabled)
{
DebugManager.Cleanup();
DebugManager->Cleanup();
}
vkDestroySurfaceKHR(InstanceManager.GetInstance(), Surface, nullptr);
InstanceManager.Cleanup();
vkDestroySurfaceKHR(InstanceManager->GetInstance(), Surface, nullptr);
InstanceManager->Cleanup();
}
void VulkanContext::CreateSurface(GLFWwindow* Window)
@@ -181,12 +229,13 @@ void VulkanContext::CreateSurface(GLFWwindow* Window)
Log::Error("Window not initialized.");
}
if (!InstanceManager.GetInstance())
if (!InstanceManager->GetInstance())
{
Log::Error("Instance is null.");
}
VkResult result = glfwCreateWindowSurface(InstanceManager.GetInstance(), Window, nullptr, &Surface);
VkResult result =
glfwCreateWindowSurface(InstanceManager->GetInstance(), Window, nullptr, &Surface);
if (result != VK_SUCCESS)
{
std::string errorMsg;
@@ -223,12 +272,28 @@ void VulkanContext::CreateDescriptorSetLayout()
UboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
UboLayoutBinding.pImmutableSamplers = nullptr;
VkDescriptorSetLayoutBinding SamplerLayoutBinding{};
SamplerLayoutBinding.binding = 1;
SamplerLayoutBinding.descriptorCount = 1;
SamplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
SamplerLayoutBinding.pImmutableSamplers = nullptr;
SamplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
std::array<VkDescriptorSetLayoutBinding, 2> Bindings = { UboLayoutBinding,
SamplerLayoutBinding };
VkDescriptorSetLayoutCreateInfo LayoutInfo{};
LayoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
LayoutInfo.bindingCount = 1;
LayoutInfo.pBindings = &UboLayoutBinding;
LayoutInfo.bindingCount = static_cast<uint32_t>(Bindings.size());
LayoutInfo.pBindings = Bindings.data();
if (vkCreateDescriptorSetLayout(DeviceManager.GetDevice(), &LayoutInfo, nullptr, &DescriptorSetLayout) != VK_SUCCESS)
if (vkCreateDescriptorSetLayout(
DeviceManager->GetDevice(),
&LayoutInfo,
nullptr,
&DescriptorSetLayout
)
!= VK_SUCCESS)
{
Log::Error("Failed to create descriptor set layout!");
}
@@ -240,17 +305,20 @@ void VulkanContext::CreateDescriptorSetLayout()
void VulkanContext::CreateDescriptorPool()
{
VkDescriptorPoolSize PoolSize{};
PoolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
PoolSize.descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
std::array<VkDescriptorPoolSize, 2> PoolSizes{};
PoolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
PoolSizes[0].descriptorCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
PoolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
PoolSizes[1].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.poolSizeCount = static_cast<uint32_t>(PoolSizes.size());
PoolInfo.pPoolSizes = PoolSizes.data();
PoolInfo.maxSets = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);
if (vkCreateDescriptorPool(DeviceManager.GetDevice(), &PoolInfo, nullptr, &DescriptorPool) != VK_SUCCESS)
if (vkCreateDescriptorPool(DeviceManager->GetDevice(), &PoolInfo, nullptr, &DescriptorPool)
!= VK_SUCCESS)
{
Log::Error("Failed to create descriptor pool!");
}
@@ -271,7 +339,8 @@ void VulkanContext::CreateDescriptorSets()
AllocateInfo.pSetLayouts = Layouts.data();
DescriptorSets.resize(MAX_FRAMES_IN_FLIGHT);
if (vkAllocateDescriptorSets(DeviceManager.GetDevice(), &AllocateInfo, DescriptorSets.data()) != VK_SUCCESS)
if (vkAllocateDescriptorSets(DeviceManager->GetDevice(), &AllocateInfo, DescriptorSets.data())
!= VK_SUCCESS)
{
Log::Error("Failed to allocate descriptor sets!");
}
@@ -283,117 +352,247 @@ void VulkanContext::CreateDescriptorSets()
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
{
VkDescriptorBufferInfo BufferInfo{};
BufferInfo.buffer = VertexBuffer.GetUniformBuffers()[i];
BufferInfo.buffer = Buffers->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;
VkDescriptorImageInfo ImageInfo{};
ImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
ImageInfo.imageView = Textures->GetImageView();
ImageInfo.sampler = Textures->GetSampler();
vkUpdateDescriptorSets(DeviceManager.GetDevice(), 1, &DescriptorWrite, 0, nullptr);
std::array<VkWriteDescriptorSet, 2> DescriptorWrites{};
DescriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
DescriptorWrites[0].dstSet = DescriptorSets[i];
DescriptorWrites[0].dstBinding = 0;
DescriptorWrites[0].dstArrayElement = 0;
DescriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
DescriptorWrites[0].descriptorCount = 1;
DescriptorWrites[0].pBufferInfo = &BufferInfo;
DescriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
DescriptorWrites[1].dstSet = DescriptorSets[i];
DescriptorWrites[1].dstBinding = 1;
DescriptorWrites[1].dstArrayElement = 0;
DescriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
DescriptorWrites[1].descriptorCount = 1;
DescriptorWrites[1].pImageInfo = &ImageInfo;
vkUpdateDescriptorSets(
DeviceManager->GetDevice(),
static_cast<uint32_t>(DescriptorWrites.size()),
DescriptorWrites.data(),
0,
nullptr
);
}
}
void VulkanContext::CreateImage(
uint32_t Width,
uint32_t Height,
VkFormat Format,
VkImageTiling Tiling,
VkImageUsageFlags Usage,
VkMemoryPropertyFlags Properties,
VkImage& Image,
VkDeviceMemory& ImageMemory)
{
// 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 =
// Buffers->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::CreateDepthResources()
// {
// if (!DepthPass)
// {
// DepthPass = std::make_unique<VulkanDepthPass>();
// }
// VkFormat DepthFormat = DepthPass->FindDepthFormat();
// VkExtent2D Extents = SwapChain->GetSwapChainExtent();
//
// CreateImage(
// Extents.width,
// Extents.height,
// DepthFormat,
// VK_IMAGE_TILING_OPTIMAL,
// VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
// VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
// DepthPass->GetDepthImage(),
// DepthPass->GetDepthImageMemory()
// );
//
// DepthPass->SetDepthImageView(SwapChain->CreateImageView(
// DepthPass->GetDepthImage(),
// DepthFormat,
// VK_IMAGE_ASPECT_DEPTH_BIT
// ));
//
// Buffers->TransitionImageLayout(
// DepthPass->GetDepthImage(),
// DepthFormat,
// VK_IMAGE_LAYOUT_UNDEFINED,
// VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
// );
// }
//
// 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;
//
// Buffers->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
// );
//
// Buffers->TransitionImageLayout(
// TextureImage,
// VK_FORMAT_R8G8B8A8_SRGB,
// VK_IMAGE_LAYOUT_UNDEFINED,
// VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
// );
//
// Buffers->CopyBufferToImage(
// StagingBuffer,
// TextureImage,
// static_cast<uint32_t>(TextureWidth),
// static_cast<uint32_t>(TextureHeight)
// );
//
// Buffers->TransitionImageLayout(
// TextureImage,
// VK_FORMAT_R8G8B8A8_SRGB,
// VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
// VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
// );
//
// vkDestroyBuffer(DeviceManager->GetDevice(), StagingBuffer, nullptr);
// vkFreeMemory(DeviceManager->GetDevice(), StagingBufferMemory, nullptr);
// }
//
// void VulkanContext::CreateTextureImageView()
// {
// TextureImageView = SwapChain->CreateImageView(
// TextureImage,
// VK_FORMAT_R8G8B8A8_SRGB,
// VK_IMAGE_ASPECT_COLOR_BIT
// );
// }
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::CreateTextureSampler()
// {
// VkSamplerCreateInfo SamplerInfo{};
// SamplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
// SamplerInfo.magFilter = VK_FILTER_LINEAR;
// SamplerInfo.minFilter = VK_FILTER_LINEAR;
// SamplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
// SamplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
// SamplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
// SamplerInfo.anisotropyEnable = VK_TRUE;
//
// VkPhysicalDeviceProperties Properties{};
// vkGetPhysicalDeviceProperties(DeviceManager->GetPhysicalDevice(), &Properties);
//
// SamplerInfo.maxAnisotropy = Properties.limits.maxSamplerAnisotropy;
// SamplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
// SamplerInfo.unnormalizedCoordinates = VK_FALSE;
// SamplerInfo.compareEnable = VK_FALSE;
// SamplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
// SamplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
// SamplerInfo.mipLodBias = 0.0f;
// SamplerInfo.minLod = 0.0f;
// SamplerInfo.maxLod = 0.0f;
//
// if (vkCreateSampler(DeviceManager->GetDevice(), &SamplerInfo, nullptr, &TextureSampler)
// != VK_SUCCESS)
// {
// Log::Error("Failed to create texture sampler!");
// }
// else
// {
// Log::Info("Successfully created texture sampler.");
// }
// }
void VulkanContext::CreateSyncObjects()
{
@@ -410,9 +609,20 @@ void VulkanContext::CreateSyncObjects()
for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
{
if (vkCreateSemaphore(DeviceManager.GetDevice(), &SemaphoreInfo, nullptr, &ImageAvailableSemaphores[i]) != VK_SUCCESS
|| vkCreateSemaphore(DeviceManager.GetDevice(), &SemaphoreInfo, nullptr, &RenderFinishedSemaphores[i]) != VK_SUCCESS
|| vkCreateFence(DeviceManager.GetDevice(), &FenceInfo, nullptr, &InFlightFences[i]) != VK_SUCCESS)
if (vkCreateSemaphore(
DeviceManager->GetDevice(),
&SemaphoreInfo,
nullptr,
&ImageAvailableSemaphores[i]
) != VK_SUCCESS
|| vkCreateSemaphore(
DeviceManager->GetDevice(),
&SemaphoreInfo,
nullptr,
&RenderFinishedSemaphores[i]
) != VK_SUCCESS
|| vkCreateFence(DeviceManager->GetDevice(), &FenceInfo, nullptr, &InFlightFences[i])
!= VK_SUCCESS)
{
Log::Error("Failed to create semaphores!");
}
@@ -425,16 +635,23 @@ void VulkanContext::CreateSyncObjects()
void VulkanContext::DrawFrame(bool bDrawImGui, uint32_t InVerticesSize, uint32_t InIndexSize)
{
vkWaitForFences(DeviceManager.GetDevice(), 1, &InFlightFences[CurrentFrame], VK_TRUE, UINT64_MAX);
vkWaitForFences(
DeviceManager->GetDevice(),
1,
&InFlightFences[CurrentFrame],
VK_TRUE,
UINT64_MAX
);
uint32_t ImageIndex;
VkResult result = vkAcquireNextImageKHR(
DeviceManager.GetDevice(),
SwapChain.GetSwapChain(),
DeviceManager->GetDevice(),
SwapChain->GetSwapChain(),
UINT64_MAX,
ImageAvailableSemaphores[CurrentFrame],
VK_NULL_HANDLE,
&ImageIndex);
&ImageIndex
);
if (result == VK_ERROR_OUT_OF_DATE_KHR)
{
@@ -446,28 +663,28 @@ void VulkanContext::DrawFrame(bool bDrawImGui, uint32_t InVerticesSize, uint32_t
Log::Error("Failed to acquire swap chain images!");
}
vkResetFences(DeviceManager.GetDevice(), 1, &InFlightFences[CurrentFrame]);
vkResetFences(DeviceManager->GetDevice(), 1, &InFlightFences[CurrentFrame]);
vkResetCommandBuffer(CommandBuffers.GetCommandBuffer(CurrentFrame), 0);
vkResetCommandBuffer(Buffers->GetCommandBuffer(CurrentFrame), 0);
FRecordCommandBuffersParams Params{
CommandBuffers.GetCommandBuffer(CurrentFrame),
FRecordBuffersParams Params{
Buffers->GetCommandBuffer(CurrentFrame),
ImageIndex,
VertexBuffer.GetVertexBuffer(),
Buffers->GetVertexBuffer(),
InVerticesSize,
VertexBuffer.GetIndexBuffer(),
Buffers->GetIndexBuffer(),
InIndexSize,
RenderPass.GetRenderPass(),
SwapChain.GetSwapChainExtent(),
GraphicsPipeline.GetGraphicsPipeline(),
Framebuffers.GetSwapChainFrameBuffers(),
RenderPass->GetRenderPass(),
SwapChain->GetSwapChainExtent(),
GraphicsPipeline->GetGraphicsPipeline(),
Framebuffers->GetSwapChainFrameBuffers(),
DescriptorSets[CurrentFrame],
GraphicsPipeline.GetPipelineLayout(),
GraphicsPipeline->GetPipelineLayout(),
bDrawImGui
// DrawData
};
CommandBuffers.RecordCommandBuffer(Params);
Buffers->RecordCommandBuffer(Params);
UpdateUniformBuffer(CurrentFrame);
@@ -481,14 +698,20 @@ void VulkanContext::DrawFrame(bool bDrawImGui, uint32_t InVerticesSize, uint32_t
SubmitInfo.pWaitDstStageMask = WaitStages;
SubmitInfo.commandBufferCount = 1;
VkCommandBuffer CommandBuffer = CommandBuffers.GetCommandBuffer(CurrentFrame);
VkCommandBuffer CommandBuffer = Buffers->GetCommandBuffer(CurrentFrame);
SubmitInfo.pCommandBuffers = &CommandBuffer;
VkSemaphore SignalSemaphores[] = { RenderFinishedSemaphores[CurrentFrame] };
SubmitInfo.signalSemaphoreCount = 1;
SubmitInfo.pSignalSemaphores = SignalSemaphores;
if (vkQueueSubmit(DeviceManager.GetGraphicsQueue(), 1, &SubmitInfo, InFlightFences[CurrentFrame]) != VK_SUCCESS)
if (vkQueueSubmit(
DeviceManager->GetGraphicsQueue(),
1,
&SubmitInfo,
InFlightFences[CurrentFrame]
)
!= VK_SUCCESS)
{
Log::Error("Failed to submit draw command buffer!");
}
@@ -498,14 +721,14 @@ void VulkanContext::DrawFrame(bool bDrawImGui, uint32_t InVerticesSize, uint32_t
PresentInfo.waitSemaphoreCount = 1;
PresentInfo.pWaitSemaphores = SignalSemaphores;
VkSwapchainKHR SwapChains[] = { SwapChain.GetSwapChain() };
VkSwapchainKHR SwapChains[] = { SwapChain->GetSwapChain() };
PresentInfo.swapchainCount = 1;
PresentInfo.pSwapchains = SwapChains;
PresentInfo.pImageIndices = &ImageIndex;
PresentInfo.pResults = nullptr;
result = vkQueuePresentKHR(DeviceManager.GetPresentQueue(), &PresentInfo);
result = vkQueuePresentKHR(DeviceManager->GetPresentQueue(), &PresentInfo);
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || bFramebufferResized)
{
@@ -526,15 +749,26 @@ void VulkanContext::UpdateUniformBuffer(uint32_t CurrentImage)
auto CurrentTime = std::chrono::high_resolution_clock::now();
float Time = std::chrono::duration<float, std::chrono::seconds::period>(CurrentTime - StartTime).count();
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.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));
memcpy(Buffers->GetUniformBuffersMapped()[CurrentImage], &Ubo, sizeof(Ubo));
}
void VulkanContext::RecreateSwapChain()
@@ -548,30 +782,24 @@ void VulkanContext::RecreateSwapChain()
}
Log::Info("Recreating SwapChain...");
vkDeviceWaitIdle(DeviceManager.GetDevice());
vkDeviceWaitIdle(DeviceManager->GetDevice());
CleanupSwapChain();
auto SwapChainSupport = DeviceManager.QuerySwapChainSupport(DeviceManager.GetPhysicalDevice());
auto SwapChainSupport =
DeviceManager->QuerySwapChainSupport(DeviceManager->GetPhysicalDevice());
SwapChain.Initialize(FSwapConfig(
DeviceManager.GetDevice(),
Surface,
Config.Window,
DeviceManager.GetPhysicalQueueFamilies().GraphicsFamily,
DeviceManager.GetPhysicalQueueFamilies().PresentFamily,
SwapChainSupport.Capabilities,
SwapChainSupport.Formats,
SwapChainSupport.PresentModes));
SwapChain.CreateSwapChain();
SwapChain.CreateImageViews();
SwapChain->CreateSwapChain();
SwapChain->CreateImageViews();
Textures->CreateDepthResources();
Framebuffers.Initialize(FFramebufferConfig(
DeviceManager.GetDevice(),
RenderPass.GetRenderPass(),
SwapChain.GetSwapChainImageViews(),
SwapChain.GetSwapChainExtent()));
Framebuffers.CreateFramebuffers();
Framebuffers->Initialize(FFramebufferConfig(
DeviceManager->GetDevice(),
RenderPass->GetRenderPass(),
SwapChain->GetSwapChainImageViews(),
SwapChain->GetSwapChainExtent()
));
Framebuffers->CreateFramebuffers(Textures->GetDepthImageView());
InitImGui();
}
@@ -595,17 +823,18 @@ void VulkanContext::InitImGui()
}
ImGui_ImplVulkan_InitInfo ImGuiInitInfo = {};
ImGuiInitInfo.Instance = InstanceManager.GetInstance();
ImGuiInitInfo.PhysicalDevice = DeviceManager.GetPhysicalDevice();
ImGuiInitInfo.Device = DeviceManager.GetDevice();
ImGuiInitInfo.QueueFamily = DeviceManager.GetPhysicalQueueFamilies().GraphicsFamily.value_or(0);
ImGuiInitInfo.Queue = DeviceManager.GetGraphicsQueue();
ImGuiInitInfo.Instance = InstanceManager->GetInstance();
ImGuiInitInfo.PhysicalDevice = DeviceManager->GetPhysicalDevice();
ImGuiInitInfo.Device = DeviceManager->GetDevice();
ImGuiInitInfo.QueueFamily =
DeviceManager->GetPhysicalQueueFamilies().GraphicsFamily.value_or(0);
ImGuiInitInfo.Queue = DeviceManager->GetGraphicsQueue();
ImGuiInitInfo.PipelineCache = VK_NULL_HANDLE;
ImGuiInitInfo.DescriptorPool = ImGuiPool;
ImGuiInitInfo.MinImageCount = MAX_FRAMES_IN_FLIGHT;
ImGuiInitInfo.ImageCount = SwapChain.GetSwapChainImageViews().size();
ImGuiInitInfo.ImageCount = SwapChain->GetSwapChainImageViews().size();
ImGuiInitInfo.Allocator = nullptr;
ImGuiInitInfo.PipelineInfoMain.RenderPass = RenderPass.GetRenderPass();
ImGuiInitInfo.PipelineInfoMain.RenderPass = RenderPass->GetRenderPass();
ImGuiInitInfo.PipelineInfoMain.Subpass = 0;
ImGuiInitInfo.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
ImGuiInitInfo.CheckVkResultFn = nullptr;
@@ -621,6 +850,7 @@ void VulkanContext::InitImGui()
void VulkanContext::CleanupSwapChain()
{
Framebuffers.Cleanup();
SwapChain.Cleanup();
Textures->CleanupDepth();
Framebuffers->Cleanup();
SwapChain->Cleanup();
}

View File

@@ -1,4 +1,5 @@
#include "VulkanDebugManager.h"
#include "utilities/Logger.h"
VulkanDebugManager::VulkanDebugManager()

View File

@@ -6,10 +6,19 @@
#include <set>
#include <vulkan/vulkan_core.h>
#include "VulkanContext.h"
#include "VulkanContext.hpp"
#include "utilities/Logger.h"
VulkanDeviceManager::VulkanDeviceManager()
const std::vector<const char*> DeviceExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME
};
VulkanDeviceManager::VulkanDeviceManager(
VkInstance Instance,
VkSurfaceKHR Surface,
GLFWwindow* Window,
bool bEnableValidationLayers)
: Instance(Instance), Surface(Surface), Window(Window), bEnableValidationLayers(bEnableValidationLayers)
{
}
@@ -18,19 +27,6 @@ VulkanDeviceManager::~VulkanDeviceManager()
// Cleanup();
}
void VulkanDeviceManager::Initialize(FDeviceConfig InConfig)
// VkInstance Instance,
// bool bEnableValidationLayers,
// VkSurfaceKHR Surface,
// GLFWwindow* Window)
{
DeviceConfig = InConfig;
// this->Instance = Instance;
// this->Surface = Surface;
// this->bEnableValidationLayers = bEnableValidationLayers;
// this->Window = Window;
}
void VulkanDeviceManager::Cleanup()
{
vkDestroyDevice(Device, nullptr);
@@ -39,7 +35,7 @@ void VulkanDeviceManager::Cleanup()
void VulkanDeviceManager::PickPhysicalDevice()
{
uint32_t DeviceCount = 0;
vkEnumeratePhysicalDevices(DeviceConfig.Instance, &DeviceCount, nullptr);
vkEnumeratePhysicalDevices(Instance, &DeviceCount, nullptr);
if (DeviceCount == 0)
{
@@ -47,7 +43,7 @@ void VulkanDeviceManager::PickPhysicalDevice()
}
std::vector<VkPhysicalDevice> Devices(DeviceCount);
vkEnumeratePhysicalDevices(DeviceConfig.Instance, &DeviceCount, Devices.data());
vkEnumeratePhysicalDevices(Instance, &DeviceCount, Devices.data());
std::multimap<int, VkPhysicalDevice> Candidates;
@@ -84,7 +80,10 @@ bool VulkanDeviceManager::IsDeviceSuitable(VkPhysicalDevice Device)
bSwapChainAdequate = !SwapChainSupport.Formats.empty() && !SwapChainSupport.PresentModes.empty();
}
return Indices.IsComplete() && bExtensionsSupported && bSwapChainAdequate;
VkPhysicalDeviceFeatures SupportedFeatures;
vkGetPhysicalDeviceFeatures(Device, &SupportedFeatures);
return Indices.IsComplete() && bExtensionsSupported && bSwapChainAdequate && SupportedFeatures.samplerAnisotropy;
}
int VulkanDeviceManager::RateDeviceSuitability(VkPhysicalDevice Device)
@@ -149,7 +148,7 @@ QueueFamilyIndices VulkanDeviceManager::FindQueueFamilies(VkPhysicalDevice Devic
}
VkBool32 PresentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR(Device, i, DeviceConfig.Surface, &PresentSupport);
vkGetPhysicalDeviceSurfaceSupportKHR(Device, i, Surface, &PresentSupport);
if (PresentSupport)
{
@@ -185,6 +184,7 @@ void VulkanDeviceManager::CreateLogicalDevice()
}
VkPhysicalDeviceFeatures DeviceFeatures{};
DeviceFeatures.samplerAnisotropy = VK_TRUE;
VkDeviceCreateInfo CreateInfo{};
CreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
@@ -195,7 +195,7 @@ void VulkanDeviceManager::CreateLogicalDevice()
CreateInfo.enabledExtensionCount = static_cast<uint32_t>(DeviceExtensions.size());
CreateInfo.ppEnabledExtensionNames = DeviceExtensions.data();
if (DeviceConfig.bEnableValidationLayers)
if (bEnableValidationLayers)
{
CreateInfo.enabledLayerCount = static_cast<uint32_t>(ValidationLayers.size());
CreateInfo.ppEnabledLayerNames = ValidationLayers.data();
@@ -222,24 +222,24 @@ SwapChainSupportDetails VulkanDeviceManager::QuerySwapChainSupport(VkPhysicalDev
{
SwapChainSupportDetails Details;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(Device, DeviceConfig.Surface, &Details.Capabilities);
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(Device, Surface, &Details.Capabilities);
uint32_t FormatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(Device, DeviceConfig.Surface, &FormatCount, nullptr);
vkGetPhysicalDeviceSurfaceFormatsKHR(Device, Surface, &FormatCount, nullptr);
if (FormatCount != 0)
{
Details.Formats.resize(FormatCount);
vkGetPhysicalDeviceSurfaceFormatsKHR(Device, DeviceConfig.Surface, &FormatCount, Details.Formats.data());
vkGetPhysicalDeviceSurfaceFormatsKHR(Device, Surface, &FormatCount, Details.Formats.data());
}
uint32_t PresentModeCount;
vkGetPhysicalDeviceSurfacePresentModesKHR(Device, DeviceConfig.Surface, &PresentModeCount, nullptr);
vkGetPhysicalDeviceSurfacePresentModesKHR(Device, Surface, &PresentModeCount, nullptr);
if (PresentModeCount != 0)
{
Details.PresentModes.resize(PresentModeCount);
vkGetPhysicalDeviceSurfacePresentModesKHR(Device, DeviceConfig.Surface, &PresentModeCount, Details.PresentModes.data());
vkGetPhysicalDeviceSurfacePresentModesKHR(Device, Surface, &PresentModeCount, Details.PresentModes.data());
}
return Details;

View File

@@ -16,33 +16,39 @@ void VulkanFramebuffers::Cleanup()
}
}
// void VulkanFramebuffers::CreateFramebuffers(VkRenderPass RenderPass, std::vector<VkImageView> SwapChainImageViews, VkExtent2D SwapChainExtent)
void VulkanFramebuffers::CreateFramebuffers()
// void VulkanFramebuffers::CreateFramebuffers(VkRenderPass RenderPass, std::vector<VkImageView>
// SwapChainImageViews, VkExtent2D SwapChainExtent)
void VulkanFramebuffers::CreateFramebuffers(VkImageView DepthImageView)
{
SwapChainFramebuffers.resize(FramebufferConfig.SwapChainImageViews.size());
for (size_t i = 0; i < FramebufferConfig.SwapChainImageViews.size(); i++)
{
VkImageView Attachments[] = {
FramebufferConfig.SwapChainImageViews[i]
};
std::array<VkImageView, 2> Attachments = { FramebufferConfig.SwapChainImageViews[i],
DepthImageView };
VkFramebufferCreateInfo FramebufferInfo{};
FramebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
FramebufferInfo.renderPass = FramebufferConfig.RenderPass;
FramebufferInfo.attachmentCount = 1;
FramebufferInfo.pAttachments = Attachments;
FramebufferInfo.attachmentCount = static_cast<uint32_t>(Attachments.size());
FramebufferInfo.pAttachments = Attachments.data();
FramebufferInfo.width = FramebufferConfig.SwapChainExtent.width;
FramebufferInfo.height = FramebufferConfig.SwapChainExtent.height;
FramebufferInfo.layers = 1;
if (vkCreateFramebuffer(FramebufferConfig.Device, &FramebufferInfo, nullptr, &SwapChainFramebuffers[i]) != VK_SUCCESS)
if (vkCreateFramebuffer(
FramebufferConfig.Device,
&FramebufferInfo,
nullptr,
&SwapChainFramebuffers[i]
)
!= VK_SUCCESS)
{
Log::Error("Failed to create frame buffer!");
}
else
{
// Log::Info("Successfully created framebuffers.");
Log::Info("Successfully created framebuffers.");
}
}
}

View File

@@ -1,6 +1,6 @@
#include "VulkanInstanceManager.h"
#include "VulkanInstanceManager.hpp"
#include "VulkanContext.h"
#include "VulkanContext.hpp"
#include "utilities/Logger.h"
#include <cstring>

View File

@@ -22,7 +22,11 @@ void VulkanPipeline::Cleanup()
vkDestroyPipelineLayout(Device, PipelineLayout, nullptr);
}
void VulkanPipeline::CreateGraphicsPipeline(VkExtent2D SwapChainExtent, VkRenderPass RenderPass, VkDescriptorSetLayout& DescriptorSetLayout)
void VulkanPipeline::CreateGraphicsPipeline(
VkExtent2D SwapChainExtent,
VkRenderPass RenderPass,
VkDescriptorSetLayout& DescriptorSetLayout
)
{
auto VertShaderCode = ReadFile("Shaders/vert.spv");
auto FragShaderCode = ReadFile("Shaders/frag.spv");
@@ -55,7 +59,8 @@ void VulkanPipeline::CreateGraphicsPipeline(VkExtent2D SwapChainExtent, VkRender
VertexInputInfo.vertexBindingDescriptionCount = 1;
VertexInputInfo.pVertexBindingDescriptions = &BindingDescription;
VertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(AttributeDescriptions.size());
VertexInputInfo.vertexAttributeDescriptionCount =
static_cast<uint32_t>(AttributeDescriptions.size());
VertexInputInfo.pVertexAttributeDescriptions = AttributeDescriptions.data();
VkPipelineInputAssemblyStateCreateInfo InputAssembly{};
@@ -75,10 +80,8 @@ void VulkanPipeline::CreateGraphicsPipeline(VkExtent2D SwapChainExtent, VkRender
Scissor.offset = { 0, 0 };
Scissor.extent = SwapChainExtent;
std::vector<VkDynamicState> DynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
std::vector<VkDynamicState> DynamicStates = { VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR };
VkPipelineDynamicStateCreateInfo DynamicState{};
DynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
@@ -113,7 +116,8 @@ void VulkanPipeline::CreateGraphicsPipeline(VkExtent2D SwapChainExtent, VkRender
Multisampling.alphaToOneEnable = VK_FALSE;
VkPipelineColorBlendAttachmentState ColorBlendAttachement{};
ColorBlendAttachement.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
ColorBlendAttachement.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
ColorBlendAttachement.blendEnable = VK_FALSE;
ColorBlendAttachement.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
ColorBlendAttachement.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
@@ -149,6 +153,18 @@ void VulkanPipeline::CreateGraphicsPipeline(VkExtent2D SwapChainExtent, VkRender
Log::Info("Successfully created pipeline layout");
}
VkPipelineDepthStencilStateCreateInfo DepthStencil{};
DepthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
DepthStencil.depthTestEnable = VK_TRUE;
DepthStencil.depthWriteEnable = VK_TRUE;
DepthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
DepthStencil.depthBoundsTestEnable = VK_FALSE;
DepthStencil.minDepthBounds = 0.0f;
DepthStencil.maxDepthBounds = 1.0f;
DepthStencil.stencilTestEnable = VK_FALSE;
DepthStencil.front = {};
DepthStencil.back = {};
VkGraphicsPipelineCreateInfo PipelineInfo{};
PipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
PipelineInfo.stageCount = 2;
@@ -158,7 +174,7 @@ void VulkanPipeline::CreateGraphicsPipeline(VkExtent2D SwapChainExtent, VkRender
PipelineInfo.pViewportState = &ViewportState;
PipelineInfo.pRasterizationState = &Rasterizer;
PipelineInfo.pMultisampleState = &Multisampling;
PipelineInfo.pDepthStencilState = nullptr;
PipelineInfo.pDepthStencilState = &DepthStencil;
PipelineInfo.pColorBlendState = &ColorBlending;
PipelineInfo.pDynamicState = &DynamicState;
PipelineInfo.layout = PipelineLayout;
@@ -167,7 +183,15 @@ void VulkanPipeline::CreateGraphicsPipeline(VkExtent2D SwapChainExtent, VkRender
PipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
PipelineInfo.basePipelineIndex = -1;
if (vkCreateGraphicsPipelines(Device, VK_NULL_HANDLE, 1, &PipelineInfo, nullptr, &GraphicsPipeline) != VK_SUCCESS)
if (vkCreateGraphicsPipelines(
Device,
VK_NULL_HANDLE,
1,
&PipelineInfo,
nullptr,
&GraphicsPipeline
)
!= VK_SUCCESS)
{
Log::Error("Failed to create graphics pipeline!");
}
@@ -248,7 +272,8 @@ VkShaderModule VulkanPipeline::CreateShaderModule(const std::vector<char>& Code)
// }
// }
// void VulkanPipeline::CreateFramebuffers(std::vector<VkImageView> SwapChainImageViews, VkExtent2D SwapChainExtent)
// void VulkanPipeline::CreateFramebuffers(std::vector<VkImageView> SwapChainImageViews, VkExtent2D
// SwapChainExtent)
// {
// SwapChainFrameBuffers.resize(SwapChainImageViews.size());
//
@@ -267,7 +292,8 @@ VkShaderModule VulkanPipeline::CreateShaderModule(const std::vector<char>& Code)
// FramebufferInfo.height = SwapChainExtent.height;
// FramebufferInfo.layers = 1;
//
// if (vkCreateFramebuffer(Device, &FramebufferInfo, nullptr, &SwapChainFrameBuffers[i]) != VK_SUCCESS)
// if (vkCreateFramebuffer(Device, &FramebufferInfo, nullptr, &SwapChainFrameBuffers[i]) !=
// VK_SUCCESS)
// {
// Log::Error("Failed to create frame buffer!");
// }

View File

@@ -1,5 +1,6 @@
#include "VulkanRenderPass.h"
#include "utilities/Logger.h"
#include <vulkan/vulkan_core.h>
void VulkanRenderPass::Initialize(VkDevice InDevice)
{
@@ -11,7 +12,7 @@ void VulkanRenderPass::Cleanup()
vkDestroyRenderPass(Device, RenderPass, nullptr);
}
void VulkanRenderPass::CreateRenderPass(VkFormat SwapChainImageFormat)
void VulkanRenderPass::CreateRenderPass(VkFormat SwapChainImageFormat, VkFormat DepthFormat)
{
VkAttachmentDescription ColorAttachment{};
ColorAttachment.format = SwapChainImageFormat;
@@ -27,25 +28,45 @@ void VulkanRenderPass::CreateRenderPass(VkFormat SwapChainImageFormat)
ColorAttachmentRef.attachment = 0;
ColorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkAttachmentDescription DepthAttachment{};
DepthAttachment.format = DepthFormat;
DepthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
DepthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
DepthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
DepthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
DepthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
DepthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
DepthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkAttachmentReference DepthAttachmentRef{};
DepthAttachmentRef.attachment = 1;
DepthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkSubpassDescription Subpass{};
Subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
Subpass.colorAttachmentCount = 1;
Subpass.pColorAttachments = &ColorAttachmentRef;
VkRenderPassCreateInfo RenderPassInfo{};
RenderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
RenderPassInfo.attachmentCount = 1;
RenderPassInfo.pAttachments = &ColorAttachment;
RenderPassInfo.subpassCount = 1;
RenderPassInfo.pSubpasses = &Subpass;
Subpass.pDepthStencilAttachment = &DepthAttachmentRef;
VkSubpassDependency Dependency{};
Dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
Dependency.dstSubpass = 0;
Dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
Dependency.srcAccessMask = 0;
Dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
Dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
Dependency.srcStageMask =
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
Dependency.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
Dependency.dstStageMask =
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
Dependency.dstAccessMask =
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
std::array<VkAttachmentDescription, 2> Attachments = { ColorAttachment, DepthAttachment };
VkRenderPassCreateInfo RenderPassInfo{};
RenderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
RenderPassInfo.attachmentCount = static_cast<uint32_t>(Attachments.size());
RenderPassInfo.pAttachments = Attachments.data();
RenderPassInfo.subpassCount = 1;
RenderPassInfo.pSubpasses = &Subpass;
RenderPassInfo.dependencyCount = 1;
RenderPassInfo.pDependencies = &Dependency;

View File

@@ -8,7 +8,24 @@
#include "utilities/Logger.h"
VulkanSwapChain::VulkanSwapChain()
VulkanSwapChain::VulkanSwapChain(
VkDevice Device,
VkSurfaceKHR Surface,
GLFWwindow* Window,
uint32_t GraphicsFamily,
uint32_t PresentFamily,
const VkSurfaceCapabilitiesKHR& Capabilities,
const std::vector<VkSurfaceFormatKHR>& Formats,
const std::vector<VkPresentModeKHR>& PresentModes
)
: Device(Device)
, Surface(Surface)
, Window(Window)
, GraphicsFamily(GraphicsFamily)
, PresentFamily(PresentFamily)
, Capabilities(Capabilities)
, Formats(Formats)
, PresentModes(PresentModes)
{
}
@@ -17,25 +34,27 @@ VulkanSwapChain::~VulkanSwapChain()
// Cleanup();
}
void VulkanSwapChain::Initialize(FSwapConfig InSwapConfig)
{
SwapConfig = InSwapConfig;
}
// void VulkanSwapChain::Initialize(FIn
// {
// = In
// }
void VulkanSwapChain::Cleanup()
{
for (auto ImageView : SwapChainImageViews)
{
vkDestroyImageView(SwapConfig.Device, ImageView, nullptr);
vkDestroyImageView(Device, ImageView, nullptr);
}
vkDestroySwapchainKHR(SwapConfig.Device, SwapChain, nullptr);
vkDestroySwapchainKHR(Device, SwapChain, nullptr);
}
VkSurfaceFormatKHR VulkanSwapChain::ChooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& AvailableFormats)
VkSurfaceFormatKHR
VulkanSwapChain::ChooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& AvailableFormats)
{
for (const auto& AvailableFormat : AvailableFormats)
{
if (AvailableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && AvailableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
if (AvailableFormat.format == VK_FORMAT_B8G8R8A8_SRGB
&& AvailableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
{
return AvailableFormat;
}
@@ -43,7 +62,8 @@ VkSurfaceFormatKHR VulkanSwapChain::ChooseSwapSurfaceFormat(const std::vector<Vk
return AvailableFormats[0];
}
VkPresentModeKHR VulkanSwapChain::ChooseSwapPresentMode(const std::vector<VkPresentModeKHR>& AvailablePresentModes)
VkPresentModeKHR
VulkanSwapChain::ChooseSwapPresentMode(const std::vector<VkPresentModeKHR>& AvailablePresentModes)
{
for (const auto& AvailablePresentMode : AvailablePresentModes)
{
@@ -63,20 +83,25 @@ VkExtent2D VulkanSwapChain::ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& Cap
}
else
{
if (SwapConfig.Window == nullptr)
if (Window == nullptr)
{
Log::Error("GLFW window is null in CreateSwapChain!");
}
int Width, Height;
glfwGetFramebufferSize(SwapConfig.Window, &Width, &Height);
glfwGetFramebufferSize(Window, &Width, &Height);
VkExtent2D ActualExtent = {
static_cast<uint32_t>(Width),
static_cast<uint32_t>(Height)
};
VkExtent2D ActualExtent = { static_cast<uint32_t>(Width), static_cast<uint32_t>(Height) };
ActualExtent.width = std::clamp(ActualExtent.width, Capabilities.minImageExtent.width, Capabilities.maxImageExtent.width);
ActualExtent.height = std::clamp(ActualExtent.height, Capabilities.minImageExtent.height, Capabilities.maxImageExtent.height);
ActualExtent.width = std::clamp(
ActualExtent.width,
Capabilities.minImageExtent.width,
Capabilities.maxImageExtent.width
);
ActualExtent.height = std::clamp(
ActualExtent.height,
Capabilities.minImageExtent.height,
Capabilities.maxImageExtent.height
);
return ActualExtent;
}
@@ -84,32 +109,34 @@ VkExtent2D VulkanSwapChain::ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& Cap
void VulkanSwapChain::CreateSwapChain()
{
VkSurfaceFormatKHR SurfaceFormat = ChooseSwapSurfaceFormat(SwapConfig.Formats);
VkPresentModeKHR PresentMode = ChooseSwapPresentMode(SwapConfig.PresentModes);
VkExtent2D Extent = ChooseSwapExtent(SwapConfig.Capabilities);
VkSurfaceFormatKHR SurfaceFormat = ChooseSwapSurfaceFormat(Formats);
VkPresentModeKHR PresentMode = ChooseSwapPresentMode(PresentModes);
VkExtent2D Extent = ChooseSwapExtent(Capabilities);
uint32_t ImageCount = SwapConfig.Capabilities.minImageCount + 1;
uint32_t ImageCount = Capabilities.minImageCount + 1;
if (SwapConfig.Capabilities.maxImageCount > 0 && ImageCount > SwapConfig.Capabilities.maxImageCount)
if (Capabilities.maxImageCount > 0 && ImageCount > Capabilities.maxImageCount)
{
ImageCount = SwapConfig.Capabilities.maxImageCount;
ImageCount = Capabilities.maxImageCount;
}
VkSwapchainCreateInfoKHR CreateInfo{};
CreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
CreateInfo.surface = SwapConfig.Surface;
CreateInfo.surface = Surface;
CreateInfo.minImageCount = ImageCount;
CreateInfo.imageFormat = SurfaceFormat.format;
CreateInfo.imageColorSpace = SurfaceFormat.colorSpace;
CreateInfo.imageExtent = Extent;
CreateInfo.imageArrayLayers = 1;
CreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; // may need VK_IMAGE_USAGE_TRANSFER_DST_BIT for post processing https://vulkan-tutorial.com/Drawing_a_triangle/Presentation/Swap_chain#:~:text=VK%5FIMAGE%5FUSAGE%5FTRANSFER%5FDST%5FBIT
CreateInfo.imageUsage =
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; // may need VK_IMAGE_USAGE_TRANSFER_DST_BIT for post
// processing
// https://vulkan-tutorial.com/Drawing_a_triangle/Presentation/Swap_chain#:~:text=VK%5FIMAGE%5FUSAGE%5FTRANSFER%5FDST%5FBIT
uint32_t QueueFamilyIndices[] = { SwapConfig.GraphicsFamily.value(),
SwapConfig.PresentFamily.value() };
uint32_t QueueFamilyIndices[] = { GraphicsFamily, PresentFamily };
if (SwapConfig.GraphicsFamily != SwapConfig.PresentFamily)
if (GraphicsFamily != PresentFamily)
{
CreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
CreateInfo.queueFamilyIndexCount = 2;
@@ -122,13 +149,13 @@ void VulkanSwapChain::CreateSwapChain()
CreateInfo.pQueueFamilyIndices = nullptr;
}
CreateInfo.preTransform = SwapConfig.Capabilities.currentTransform;
CreateInfo.preTransform = Capabilities.currentTransform;
CreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
CreateInfo.presentMode = PresentMode;
CreateInfo.clipped = VK_TRUE;
CreateInfo.oldSwapchain = VK_NULL_HANDLE;
if (vkCreateSwapchainKHR(SwapConfig.Device, &CreateInfo, nullptr, &SwapChain) != VK_SUCCESS)
if (vkCreateSwapchainKHR(Device, &CreateInfo, nullptr, &SwapChain) != VK_SUCCESS)
{
Log::Error("Failed to create swap chain.");
}
@@ -137,47 +164,49 @@ void VulkanSwapChain::CreateSwapChain()
Log::Info("Successfully created swap chain.");
}
vkGetSwapchainImagesKHR(SwapConfig.Device, SwapChain, &ImageCount, nullptr);
vkGetSwapchainImagesKHR(Device, SwapChain, &ImageCount, nullptr);
SwapChainImages.resize(ImageCount);
vkGetSwapchainImagesKHR(SwapConfig.Device, SwapChain, &ImageCount, SwapChainImages.data());
vkGetSwapchainImagesKHR(Device, SwapChain, &ImageCount, SwapChainImages.data());
SwapChainImageFormat = SurfaceFormat.format;
SwapChainExtent = Extent;
}
VkImageView
VulkanSwapChain::CreateImageView(VkImage Image, VkFormat Format, VkImageAspectFlags AspectFlags)
{
VkImageViewCreateInfo ViewInfo{};
ViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
ViewInfo.image = Image;
ViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
ViewInfo.format = Format;
ViewInfo.subresourceRange.aspectMask = AspectFlags;
ViewInfo.subresourceRange.baseMipLevel = 0;
ViewInfo.subresourceRange.levelCount = 1;
ViewInfo.subresourceRange.baseArrayLayer = 0;
ViewInfo.subresourceRange.layerCount = 1;
VkImageView ImageView;
if (vkCreateImageView(Device, &ViewInfo, nullptr, &ImageView) != VK_SUCCESS)
{
Log::Error("Failed to create image view!");
}
else
{
Log::Info("Successfully created image view.");
}
return ImageView;
}
void VulkanSwapChain::CreateImageViews()
{
SwapChainImageViews.resize(SwapChainImages.size());
int CreatedViews = 0;
for (size_t i = 0; i < SwapChainImages.size(); i++)
{
VkImageViewCreateInfo CreateInfo{};
CreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
CreateInfo.image = SwapChainImages[i];
CreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
CreateInfo.format = SwapChainImageFormat;
CreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
CreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
CreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
CreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
CreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
CreateInfo.subresourceRange.baseMipLevel = 0;
CreateInfo.subresourceRange.levelCount = 1;
CreateInfo.subresourceRange.baseArrayLayer = 0;
CreateInfo.subresourceRange.layerCount = 1;
if (vkCreateImageView(SwapConfig.Device, &CreateInfo, nullptr, &SwapChainImageViews[i]) != VK_SUCCESS)
{
Log::Error("Failed to create image views.");
}
else
{
CreatedViews++;
}
SwapChainImageViews[i] =
CreateImageView(SwapChainImages[i], SwapChainImageFormat, VK_IMAGE_ASPECT_COLOR_BIT);
}
Log::Info("Successfully created " + std::to_string(CreatedViews) + " image views.");
}

View File

@@ -0,0 +1,281 @@
#include "VulkanTexture.hpp"
#include "Logger.h"
#include "VulkanBuffers.h"
#include "VulkanSwapChain.h"
#include <stb_image.h>
VulkanTexture::VulkanTexture(
VkDevice Device,
VkPhysicalDevice PhysicalDevice,
VkQueue GraphicsQueue,
VulkanBuffers& Buffers,
VulkanSwapChain& SwapChain
)
: Device(Device)
, PhysicalDevice(PhysicalDevice)
, GraphicsQueue(GraphicsQueue)
, Buffers(Buffers)
, SwapChain(SwapChain)
{
}
VulkanTexture::~VulkanTexture() {}
void VulkanTexture::Cleanup()
{
CleanupTextures();
CleanupDepth();
}
void VulkanTexture::CleanupTextures()
{
vkDestroySampler(Device, Sampler, nullptr);
vkDestroyImageView(Device, ImageView, nullptr);
vkDestroyImage(Device, Image, nullptr);
vkFreeMemory(Device, ImageMemory, nullptr);
}
void VulkanTexture::CleanupDepth()
{
vkDestroyImageView(Device, DepthImageView, nullptr);
vkDestroyImage(Device, DepthImage, nullptr);
vkFreeMemory(Device, DepthImageMemory, nullptr);
}
void VulkanTexture::LoadFromFile(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;
Buffers.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(Device, StagingBufferMemory, 0, ImageSize, 0, &Data);
memcpy(Data, Pixels, static_cast<size_t>(ImageSize));
vkUnmapMemory(Device, 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,
Image,
ImageMemory
);
Buffers.TransitionImageLayout(
Image,
VK_FORMAT_R8G8B8A8_SRGB,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
HasStencilComponent(VK_FORMAT_R8G8B8A8_SRGB)
);
Buffers.CopyBufferToImage(
StagingBuffer,
Image,
static_cast<uint32_t>(TextureWidth),
static_cast<uint32_t>(TextureHeight)
);
Buffers.TransitionImageLayout(
Image,
VK_FORMAT_R8G8B8A8_SRGB,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
HasStencilComponent(VK_FORMAT_R8G8B8A8_SRGB)
);
vkDestroyBuffer(Device, StagingBuffer, nullptr);
vkFreeMemory(Device, StagingBufferMemory, nullptr);
}
void VulkanTexture::CreateImageView()
{
ImageView =
SwapChain.CreateImageView(Image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT);
}
void VulkanTexture::CreateSampler()
{
VkSamplerCreateInfo SamplerInfo{};
SamplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
SamplerInfo.magFilter = VK_FILTER_LINEAR;
SamplerInfo.minFilter = VK_FILTER_LINEAR;
SamplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
SamplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
SamplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
SamplerInfo.anisotropyEnable = VK_TRUE;
VkPhysicalDeviceProperties Properties{};
vkGetPhysicalDeviceProperties(PhysicalDevice, &Properties);
SamplerInfo.maxAnisotropy = Properties.limits.maxSamplerAnisotropy;
SamplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
SamplerInfo.unnormalizedCoordinates = VK_FALSE;
SamplerInfo.compareEnable = VK_FALSE;
SamplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
SamplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
SamplerInfo.mipLodBias = 0.0f;
SamplerInfo.minLod = 0.0f;
SamplerInfo.maxLod = 0.0f;
if (vkCreateSampler(Device, &SamplerInfo, nullptr, &Sampler) != VK_SUCCESS)
{
Log::Error("Failed to create texture sampler!");
}
else
{
Log::Info("Successfully created texture sampler.");
}
}
void VulkanTexture::CreateDepthResources()
{
VkFormat DepthFormat = FindDepthFormat();
VkExtent2D Extents = SwapChain.GetSwapChainExtent();
CreateImage(
Extents.width,
Extents.height,
DepthFormat,
VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
DepthImage,
DepthImageMemory
);
DepthImageView = SwapChain.CreateImageView(DepthImage, DepthFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
Buffers.TransitionImageLayout(
DepthImage,
DepthFormat,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
HasStencilComponent(DepthFormat)
);
}
VkFormat VulkanTexture::FindSupportedFormat(
const std::vector<VkFormat>& Candidates,
VkImageTiling Tiling,
VkFormatFeatureFlags Features
)
{
for (VkFormat Format : Candidates)
{
VkFormatProperties Properties;
vkGetPhysicalDeviceFormatProperties(PhysicalDevice, Format, &Properties);
if (Tiling == VK_IMAGE_TILING_LINEAR
&& (Properties.linearTilingFeatures & Features) == Features)
{
return Format;
}
else if (Tiling == VK_IMAGE_TILING_OPTIMAL
&& (Properties.optimalTilingFeatures & Features) == Features)
{
return Format;
}
}
Log::Error("Failed to find supported format!");
}
VkFormat VulkanTexture::FindDepthFormat()
{
return FindSupportedFormat(
{ VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT },
VK_IMAGE_TILING_OPTIMAL,
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
);
}
bool VulkanTexture::HasStencilComponent(VkFormat Format)
{
return Format == VK_FORMAT_D32_SFLOAT_S8_UINT || Format == VK_FORMAT_D24_UNORM_S8_UINT;
}
void VulkanTexture::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(Device, &ImageInfo, nullptr, &Image) != VK_SUCCESS)
{
Log::Error("Failed to create image!");
}
else
{
Log::Info("Successfully created image.");
}
VkMemoryRequirements MemoryRequirements;
vkGetImageMemoryRequirements(Device, Image, &MemoryRequirements);
VkMemoryAllocateInfo AllocateInfo{};
AllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
AllocateInfo.allocationSize = MemoryRequirements.size;
AllocateInfo.memoryTypeIndex =
Buffers.FindMemoryType(MemoryRequirements.memoryTypeBits, Properties);
if (vkAllocateMemory(Device, &AllocateInfo, nullptr, &ImageMemory) != VK_SUCCESS)
{
Log::Error("Failed to allocate image memory!");
}
else
{
Log::Info("Successfully allocated imaged memory.");
}
vkBindImageMemory(Device, Image, ImageMemory, 0);
}

View File

@@ -1,176 +0,0 @@
#include "VulkanVertexBuffer.h"
#include "utilities/Logger.h"
#include <cstdint>
#include <vulkan/vulkan_core.h>
#include <cstring>
void VulkanVertexBuffer::Initialize(FVertexBufferConfig InConfig)
{
Config = InConfig;
}
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::CreateBuffer(VkDeviceSize Size, VkBufferUsageFlags Usage, VkMemoryPropertyFlags Properties, VkBuffer& Buffer, VkDeviceMemory& BufferMemory)
{
VkBufferCreateInfo BufferInfo{};
BufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
BufferInfo.size = Size;
BufferInfo.usage = Usage;
BufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (vkCreateBuffer(Config.Device, &BufferInfo, nullptr, &Buffer) != VK_SUCCESS)
{
Log::Error("Failed to create buffer!");
}
else
{
Log::Info("Successfully created buffer.");
}
VkMemoryRequirements 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, Properties);
if (vkAllocateMemory(Config.Device, &AllocateInfo, nullptr, &BufferMemory) != VK_SUCCESS)
{
Log::Error("Failed to allocate vertex buffer memory!");
}
else
{
Log::Info("Successfully allocated vertex buffer memory.");
}
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, 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)
{
VkPhysicalDeviceMemoryProperties MemoryProperties;
vkGetPhysicalDeviceMemoryProperties(Config.PhysicalDevice, &MemoryProperties);
for (uint32_t i = 0; i < MemoryProperties.memoryTypeCount; i++)
{
if ((TypeFilter & (1 << i)) && (MemoryProperties.memoryTypes[i].propertyFlags & Properties) == Properties)
{
return i;
}
}
Log::Error("Failed to find suitable memory type!");
return 0;
}

109
src/public/VulkanBuffers.h Normal file
View File

@@ -0,0 +1,109 @@
#pragma once
#include <vulkan/vulkan_core.h>
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#include <cstdint>
#include <vector>
#include <optional>
#include "Primitives.h"
struct FBufferConfig
{
VkDevice Device;
VkRenderPass RenderPass;
VkPhysicalDevice PhysicalDevice;
VkQueue GraphicsQueue;
};
struct FRecordBuffersParams
{
VkCommandBuffer InCommandBuffer;
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;
};
class VulkanBuffers
{
public:
void Initialize(FBufferConfig InConfig);
// VkDevice InDevice,
// VkRenderPass InRenderPass);
void Cleanup(size_t MAX_FRAMES_IN_FLIGHT);
void CreateCommandPool(std::optional<uint32_t> GraphicsFamily);
void CreateCommandBuffers(int FramesInFlight);
void RecordCommandBuffer(FRecordBuffersParams& Params);
VkCommandBuffer BeginSingleTimeCommands();
void EndSingleTimeCommands(VkCommandBuffer InCommandBuffer, VkQueue GraphicsQueue);
void TransitionImageLayout(
VkImage Image,
VkFormat Format,
VkImageLayout OldLayout,
VkImageLayout NewLayout,
bool bHasStencilComponent
);
void CopyBufferToImage(VkBuffer Buffer, VkImage Image, uint32_t Width, uint32_t Height);
void
CopyBuffer(VkQueue GraphicsQueue, VkBuffer SrcBuffer, VkBuffer DstBuffer, VkDeviceSize Size);
void CreateBuffer(
VkDeviceSize Size,
VkBufferUsageFlags Usage,
VkMemoryPropertyFlags Properties,
VkBuffer& Buffer,
VkDeviceMemory& BufferMemory
);
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);
std::vector<VkCommandBuffer> GetCommandBuffers() { return CommandBuffers; }
VkCommandBuffer GetCommandBuffer(int i) { return CommandBuffers[i]; }
VkCommandPool GetCommandPool() { return CommandPool; }
VkBuffer GetVertexBuffer() { return VertexBuffer; }
VkBuffer GetIndexBuffer() { return IndexBuffer; }
std::vector<VkBuffer> GetUniformBuffers() { return UniformBuffers; }
std::vector<void*> GetUniformBuffersMapped() { return UniformBuffersMapped; }
private:
// VkDevice Device;
// VkRenderPass RenderPass;
// VkQueue GraphicsQueue;
FBufferConfig Config;
std::vector<VkCommandBuffer> CommandBuffers;
VkCommandPool CommandPool;
VkBuffer VertexBuffer;
VkDeviceMemory VertexBufferMemory;
VkBuffer IndexBuffer;
VkDeviceMemory IndexBufferMemory;
std::vector<VkBuffer> UniformBuffers;
std::vector<VkDeviceMemory> UniformBuffersMemory;
std::vector<void*> UniformBuffersMapped;
};

View File

@@ -1,58 +0,0 @@
#pragma once
#include "VulkanVertexBuffer.h"
#include <cstdint>
#include <vulkan/vulkan_core.h>
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#include <vector>
#include <optional>
struct FRecordCommandBuffersParams
{
VkCommandBuffer InCommandBuffer;
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;
};
class VulkanCommandBuffers
{
public:
void Initialize(
VkDevice InDevice,
VkRenderPass InRenderPass);
void Cleanup();
void CreateCommandPool(std::optional<uint32_t> GraphicsFamily);
void CreateCommandBuffers(int FramesInFlight);
void RecordCommandBuffer(FRecordCommandBuffersParams& Params);
std::vector<VkCommandBuffer> GetCommandBuffers() { return CommandBuffers; }
VkCommandBuffer GetCommandBuffer(int i) { return CommandBuffers[i]; }
VkCommandPool GetCommandPool() { return CommandPool; }
private:
VkDevice Device;
VkRenderPass RenderPass;
// VkQueue GraphicsQueue;
std::vector<VkCommandBuffer> CommandBuffers;
VkCommandPool CommandPool;
};

View File

@@ -1,26 +1,26 @@
#pragma once
#include "VulkanCommandBuffers.h"
#include "VulkanFramebuffers.h"
#include "VulkanInstanceManager.h"
#include "VulkanDeviceManager.h"
#include "VulkanDebugManager.h"
#include "VulkanPipeline.h"
#include "VulkanRenderPass.h"
#include "VulkanSwapChain.h"
#include "VulkanVertexBuffer.h"
class VulkanInstanceManager;
class VulkanDebugManager;
class VulkanDeviceManager;
class VulkanSwapChain;
class VulkanPipeline;
class VulkanRenderPass;
class VulkanBuffers;
class VulkanFramebuffers;
class VulkanTexture;
class Vertex;
#include <cstdint>
#include <string>
#include <memory>
#include <vector>
#include <vulkan/vulkan_core.h>
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
static const std::vector<const char*> ValidationLayers = {
"VK_LAYER_KHRONOS_validation"
};
static const std::vector<const char*> ValidationLayers = { "VK_LAYER_KHRONOS_validation" };
static size_t MAX_FRAMES_IN_FLIGHT = 2;
struct FVulkanConfig
{
@@ -36,17 +36,22 @@ public:
VulkanContext();
~VulkanContext();
VulkanInstanceManager InstanceManager;
VulkanDebugManager DebugManager;
VulkanDeviceManager DeviceManager;
VulkanSwapChain SwapChain;
VulkanPipeline GraphicsPipeline;
VulkanRenderPass RenderPass;
VulkanFramebuffers Framebuffers;
VulkanVertexBuffer VertexBuffer;
VulkanCommandBuffers CommandBuffers;
std::unique_ptr<VulkanInstanceManager> InstanceManager;
std::unique_ptr<VulkanDebugManager> DebugManager;
std::unique_ptr<VulkanDeviceManager> DeviceManager;
std::unique_ptr<VulkanSwapChain> SwapChain;
std::unique_ptr<VulkanPipeline> GraphicsPipeline;
std::unique_ptr<VulkanRenderPass> RenderPass;
std::unique_ptr<VulkanFramebuffers> Framebuffers;
std::unique_ptr<VulkanBuffers> Buffers;
std::unique_ptr<VulkanTexture> Textures;
// std::unique_ptr<VulkanDepthPass> DepthPass;
void Initialize(FVulkanConfig& InConfig, const std::vector<Vertex>& InVertices, const std::vector<uint16_t>& InIndices);
void Initialize(
FVulkanConfig& InConfig,
const std::vector<Vertex>& InVertices,
const std::vector<uint16_t>& InIndices
);
void Cleanup();
void CreateSurface(GLFWwindow* Window);
@@ -55,20 +60,10 @@ public:
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, uint32_t InVerticesSize, uint32_t InIndexSize);
void UpdateUniformBuffer(uint32_t CurrentImage);
void RecreateSwapChain();
@@ -95,13 +90,18 @@ private:
VkDescriptorPool DescriptorPool;
std::vector<VkDescriptorSet> DescriptorSets;
VkImage TextureImage;
VkDeviceMemory TextureImageMemory;
// VkImage TextureImage;
// VkDeviceMemory TextureImageMemory;
// VkImageView TextureImageView;
// VkSampler TextureSampler;
//
// VkImage DepthImage;
// VkDeviceMemory DepthImageMemory;
// VkImageView DepthImageView;
bool bFramebufferResized = false;
bool bImGuiGlfwInitialized = false;
bool bImGuiVulkanInitialized = false;
const size_t MAX_FRAMES_IN_FLIGHT = 2;
uint32_t CurrentFrame = 0;
uint32_t CurrentFrame = 0;
};

View File

@@ -0,0 +1,73 @@
#pragma once
#include "Logger.h"
#include "VulkanContext.hpp"
#include <vector>
#include <vulkan/vulkan_core.h>
struct FDepthConfig
{
VkPhysicalDevice PhysicalDevice;
};
class VulkanDepthPass
{
public:
void Initialize(FDepthConfig& InConfig) { Config = InConfig; }
void CreateDepthResources() { VkFormat DepthFormat = FindDepthFormat(); }
VkFormat FindSupportedFormat(
const std::vector<VkFormat>& Candidates,
VkImageTiling Tiling,
VkFormatFeatureFlags Features
)
{
for (VkFormat Format : Candidates)
{
VkFormatProperties Properties;
vkGetPhysicalDeviceFormatProperties(Config.PhysicalDevice, Format, &Properties);
if (Tiling == VK_IMAGE_TILING_LINEAR
&& (Properties.linearTilingFeatures & Features) == Features)
{
return Format;
}
else if (Tiling == VK_IMAGE_TILING_OPTIMAL
&& (Properties.optimalTilingFeatures & Features) == Features)
{
return Format;
}
}
Log::Error("Failed to find supported format!");
}
VkFormat FindDepthFormat()
{
return FindSupportedFormat(
{ VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT },
VK_IMAGE_TILING_OPTIMAL,
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
);
}
bool HasStencilComponent(VkFormat Format)
{
return Format == VK_FORMAT_D32_SFLOAT_S8_UINT || Format == VK_FORMAT_D24_UNORM_S8_UINT;
}
VkImage& GetDepthImage() { return DepthImage; }
VkDeviceMemory& GetDepthImageMemory() { return DepthImageMemory; }
VkImageView& GetDepthImageView() { return DepthImageView; }
void SetDepthImageView(VkImageView ImageView) { DepthImageView = ImageView; }
private:
FDepthConfig Config;
VkImage DepthImage;
VkDeviceMemory DepthImageMemory;
VkImageView DepthImageView;
};

View File

@@ -7,14 +7,6 @@
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
struct FDeviceConfig
{
VkInstance Instance;
bool bEnableValidationLayers;
VkSurfaceKHR Surface;
GLFWwindow* Window;
};
struct QueueFamilyIndices
{
std::optional<uint32_t> GraphicsFamily;
@@ -36,14 +28,13 @@ struct SwapChainSupportDetails
class VulkanDeviceManager
{
public:
VulkanDeviceManager();
~VulkanDeviceManager();
VulkanDeviceManager(
VkInstance Instance,
VkSurfaceKHR Surface,
GLFWwindow* Window,
bool bEnableValidationLayers);
void Initialize(FDeviceConfig InConfig);
// VkInstance Instance,
// bool EnableValidationLayers,
// VkSurfaceKHR Surface,
// GLFWwindow* Window);
~VulkanDeviceManager();
void Cleanup();
@@ -58,7 +49,10 @@ public:
VkQueue GetPresentQueue() { return PresentQueue; }
private:
FDeviceConfig DeviceConfig;
VkInstance Instance;
VkSurfaceKHR Surface;
GLFWwindow* Window;
bool bEnableValidationLayers;
VkDevice Device = VK_NULL_HANDLE;
VkPhysicalDevice PhysicalDevice = VK_NULL_HANDLE;

View File

@@ -21,17 +21,10 @@ public:
void Cleanup();
void CreateFramebuffers();
// void CreateFramebuffers(VkRenderPass RenderPass, std::vector<VkImageView> SwapChainImageViews, VkExtent2D SwapChainExtent);
void CreateFramebuffers(VkImageView DepthImageView);
std::vector<VkFramebuffer> GetSwapChainFrameBuffers() { return SwapChainFramebuffers; }
// void CreateCommandPool(std::optional<uint32_t> GraphicsFamily);
//
// void CreateCommandBuffer();
//
// void RecordCommandBuffer(VkCommandBuffer CommandBuffer, uint32_t imageIndex, VkRenderPass RenderPass, VkExtent2D SwapChainExtent, VkPipeline GraphicsPipeline);
private:
FFramebufferConfig FramebufferConfig;

View File

@@ -15,8 +15,8 @@ public:
void Cleanup();
void CreateInstance(VulkanDebugManager* DebugManager = nullptr);
const VkInstance GetInstance() const { return Instance; }
void CreateInstance(VulkanDebugManager* DebugManager = nullptr);
VkInstance GetInstance() const { return Instance; }
private:
VkInstance Instance = VK_NULL_HANDLE;

View File

@@ -10,7 +10,7 @@ public:
void Cleanup();
void CreateRenderPass(VkFormat SwapChainImageFormat);
void CreateRenderPass(VkFormat SwapChainImageFormat, VkFormat DepthFormat);
VkRenderPass GetRenderPass() { return RenderPass; }

View File

@@ -1,93 +1,64 @@
#pragma once
#include <optional>
#include <cstdint>
#include <vector>
#include <vulkan/vulkan_core.h>
#include <vulkan/vulkan_core.h>
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
const std::vector<const char*> DeviceExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME
};
//
// struct SwapChainSupportDetails
// {
// VkSurfaceCapabilitiesKHR Capabilities;
// std::vector<VkSurfaceFormatKHR> Formats;
// std::vector<VkPresentModeKHR> PresentModes;
// };
struct FSwapConfig
{
VkDevice Device;
VkSurfaceKHR Surface;
GLFWwindow* Window;
std::optional<uint32_t> GraphicsFamily;
std::optional<uint32_t> PresentFamily;
VkSurfaceCapabilitiesKHR Capabilities;
std::vector<VkSurfaceFormatKHR> Formats;
std::vector<VkPresentModeKHR> PresentModes;
};
const std::vector<const char*> DeviceExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
class VulkanSwapChain
{
public:
VulkanSwapChain();
VulkanSwapChain(
VkDevice Device,
VkSurfaceKHR Surface,
GLFWwindow* Window,
uint32_t GraphicsFamily,
uint32_t PresentFamily,
const VkSurfaceCapabilitiesKHR& Capabilities,
const std::vector<VkSurfaceFormatKHR>& Formats,
const std::vector<VkPresentModeKHR>& PresentModes
);
~VulkanSwapChain();
void Initialize(FSwapConfig InConfig);
VulkanSwapChain(const VulkanSwapChain&) = delete;
VulkanSwapChain& operator=(const VulkanSwapChain&) = delete;
// void Initialize(
// VkDevice InDevice,
// VkSurfaceKHR InSurface,
// GLFWwindow* InWindow);
void CreateSwapChain();
void CreateImageViews();
void Cleanup();
void CreateSwapChain();
// void CreateSwapChain(
// std::optional<uint32_t> GraphicsFamily,
// std::optional<uint32_t> PresentFamily,
// VkSurfaceCapabilitiesKHR Capabilities,
// std::vector<VkSurfaceFormatKHR> Formats,
// std::vector<VkPresentModeKHR> PresentModes);
void CreateImageViews();
// void RecreateSwapChain();
VkSwapchainKHR GetSwapChain() { return SwapChain; }
VkFormat GetSwapChainImageFormat() { return SwapChainImageFormat; }
VkExtent2D GetSwapChainExtent() { return SwapChainExtent; }
std::vector<VkImageView> GetSwapChainImageViews() { return SwapChainImageViews; }
VkImageView CreateImageView(VkImage Image, VkFormat Format, VkImageAspectFlags AspectFlags);
VkSwapchainKHR GetSwapChain() { return SwapChain; }
VkFormat GetSwapChainImageFormat() { return SwapChainImageFormat; }
VkExtent2D GetSwapChainExtent() { return SwapChainExtent; }
std::vector<VkImageView>& GetSwapChainImageViews() { return SwapChainImageViews; }
size_t GetSwapChainImagesCount() { return SwapChainImages.size(); }
private:
FSwapConfig SwapConfig;
// VkPhysicalDevice PhysicalDevice;
// VkDevice Device;
// VkSurfaceKHR Surface;
//
// GLFWwindow* Window = nullptr;
std::vector<VkImage> SwapChainImages;
VkSwapchainKHR SwapChain = VK_NULL_HANDLE;
VkFormat SwapChainImageFormat;
VkExtent2D SwapChainExtent;
VkDevice Device;
VkSurfaceKHR Surface;
GLFWwindow* Window;
uint32_t GraphicsFamily;
uint32_t PresentFamily;
VkSurfaceCapabilitiesKHR Capabilities;
std::vector<VkSurfaceFormatKHR> Formats;
std::vector<VkPresentModeKHR> PresentModes;
std::vector<VkImage> SwapChainImages;
VkSwapchainKHR SwapChain = VK_NULL_HANDLE;
VkFormat SwapChainImageFormat;
VkExtent2D SwapChainExtent;
std::vector<VkImageView> SwapChainImageViews;
// bool IsDeviceSuitable(VkPhysicalDevice Device);
//
// int RateDeviceSuitability(VkPhysicalDevice Device);
//
// bool CheckDeviceExtensionSupport(VkPhysicalDevice Device);
// SwapChainSupportDetails QuerySwapChainSupport(VkPhysicalDevice Device);
VkSurfaceFormatKHR ChooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& AvailableFormats);
VkPresentModeKHR ChooseSwapPresentMode(const std::vector<VkPresentModeKHR>& AvailablePresentModes);
VkSurfaceFormatKHR
ChooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& AvailableFormats);
VkPresentModeKHR
ChooseSwapPresentMode(const std::vector<VkPresentModeKHR>& AvailablePresentModes);
VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& Capabilities);
};

View File

@@ -0,0 +1,68 @@
#pragma once
#include <vulkan/vulkan.hpp>
class VulkanBuffers;
class VulkanSwapChain;
class VulkanTexture
{
public:
VulkanTexture(
VkDevice Device,
VkPhysicalDevice PhysicalDevice,
VkQueue GraphicsQueue,
VulkanBuffers& Buffers,
VulkanSwapChain& SwapChain
);
~VulkanTexture();
void Cleanup();
void CleanupTextures();
void CleanupDepth();
void LoadFromFile(const char* Filename);
void CreateImageView();
void CreateSampler();
void CreateDepthResources();
VkFormat FindSupportedFormat(
const std::vector<VkFormat>& Candidates,
VkImageTiling Tiling,
VkFormatFeatureFlags Features
);
VkFormat FindDepthFormat();
bool HasStencilComponent(VkFormat Format);
VkImageView GetImageView() const { return ImageView; }
VkSampler GetSampler() const { return Sampler; }
VkImageView GetDepthImageView() const { return DepthImageView; }
private:
VkDevice Device;
VkPhysicalDevice PhysicalDevice;
VkQueue GraphicsQueue;
VulkanBuffers& Buffers;
VulkanSwapChain& SwapChain;
VkImage Image;
VkDeviceMemory ImageMemory;
VkImageView ImageView;
VkSampler Sampler;
VkImage DepthImage;
VkDeviceMemory DepthImageMemory;
VkImageView DepthImageView;
void CreateImage(
uint32_t Width,
uint32_t Height,
VkFormat Format,
VkImageTiling Tiling,
VkImageUsageFlags Usage,
VkMemoryPropertyFlags Properties,
VkImage& Image,
VkDeviceMemory& ImageMemory
);
};

View File

@@ -1,55 +0,0 @@
#pragma once
#include "Primitives.h"
#include <vector>
#include <vulkan/vulkan_core.h>
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
struct FVertexBufferConfig
{
VkDevice Device;
VkPhysicalDevice PhysicalDevice;
VkCommandPool CommandPool;
VkQueue GraphicsQueue;
};
class VulkanVertexBuffer
{
public:
void Initialize(FVertexBufferConfig InConfig);
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 GetIndexBuffer() { return IndexBuffer; }
std::vector<VkBuffer> GetUniformBuffers() { return UniformBuffers; }
std::vector<void*> GetUniformBuffersMapped() { return UniformBuffersMapped; }
private:
FVertexBufferConfig Config;
VkBuffer VertexBuffer;
VkDeviceMemory VertexBufferMemory;
VkBuffer IndexBuffer;
VkDeviceMemory IndexBufferMemory;
std::vector<VkBuffer> UniformBuffers;
std::vector<VkDeviceMemory> UniformBuffersMemory;
std::vector<void*> UniformBuffersMapped;
};

View File

@@ -1,3 +1,4 @@
#include <glm/fwd.hpp>
#include <glm/glm.hpp>
#include <vulkan/vulkan_core.h>
@@ -5,8 +6,9 @@
struct Vertex
{
glm::vec2 Position;
glm::vec3 Position;
glm::vec3 Color;
glm::vec2 TextureCoordinates;
static VkVertexInputBindingDescription GetBindingDescription()
{
@@ -18,12 +20,12 @@ struct Vertex
return BindingDescription;
}
static std::array<VkVertexInputAttributeDescription, 2> GetAttributeDescriptions()
static std::array<VkVertexInputAttributeDescription, 3> GetAttributeDescriptions()
{
std::array<VkVertexInputAttributeDescription, 2> AttributeDescriptions{};
std::array<VkVertexInputAttributeDescription, 3> AttributeDescriptions{};
AttributeDescriptions[0].binding = 0;
AttributeDescriptions[0].location = 0;
AttributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT;
AttributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
AttributeDescriptions[0].offset = offsetof(Vertex, Position);
AttributeDescriptions[1].binding = 0;
@@ -31,6 +33,11 @@ struct Vertex
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, TextureCoordinates);
return AttributeDescriptions;
}
};