Finished depth buffer
This commit is contained in:
35
src/main.cpp
35
src/main.cpp
@@ -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())
|
||||
{
|
||||
|
||||
479
src/private/VulkanBuffers.cpp
Normal file
479
src/private/VulkanBuffers.cpp
Normal 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;
|
||||
}
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "VulkanDebugManager.h"
|
||||
|
||||
#include "utilities/Logger.h"
|
||||
|
||||
VulkanDebugManager::VulkanDebugManager()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "VulkanInstanceManager.h"
|
||||
#include "VulkanInstanceManager.hpp"
|
||||
|
||||
#include "VulkanContext.h"
|
||||
#include "VulkanContext.hpp"
|
||||
#include "utilities/Logger.h"
|
||||
#include <cstring>
|
||||
|
||||
|
||||
@@ -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!");
|
||||
// }
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
|
||||
281
src/private/VulkanTexture.cpp
Normal file
281
src/private/VulkanTexture.cpp
Normal 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);
|
||||
}
|
||||
@@ -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
109
src/public/VulkanBuffers.h
Normal 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;
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
73
src/public/VulkanDepthPass.hpp
Normal file
73
src/public/VulkanDepthPass.hpp
Normal 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;
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -10,7 +10,7 @@ public:
|
||||
|
||||
void Cleanup();
|
||||
|
||||
void CreateRenderPass(VkFormat SwapChainImageFormat);
|
||||
void CreateRenderPass(VkFormat SwapChainImageFormat, VkFormat DepthFormat);
|
||||
|
||||
VkRenderPass GetRenderPass() { return RenderPass; }
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
68
src/public/VulkanTexture.hpp
Normal file
68
src/public/VulkanTexture.hpp
Normal 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
|
||||
);
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user