Triangle posting

https://vulkan-tutorial.com/Vertex_buffers/Staging_buffer

Reached the above part of the tutorial. Adding IMGUI now before
continuing.
This commit is contained in:
2026-02-17 18:37:38 -05:00
parent ab28c22446
commit 11ac560009
41 changed files with 1961 additions and 999 deletions

287
src/private/VulkanContext.cpp Executable file
View File

@@ -0,0 +1,287 @@
#include "VulkanContext.h"
#include "VulkanDeviceManager.h"
#include "VulkanFramebuffers.h"
#include "VulkanSwapChain.h"
#include "VulkanVertexBuffer.h"
#include "utilities/Logger.h"
#include <GLFW/glfw3.h>
#include <cstdint>
#include <vulkan/vulkan_core.h>
VulkanContext::VulkanContext()
{
}
VulkanContext::~VulkanContext()
{
}
void VulkanContext::Initialize(FVulkanConfig& InConfig)
{
Config = InConfig;
if (Config.bValidationEnabled)
{
InstanceManager.CreateInstance(&DebugManager);
DebugManager.Initialize(InstanceManager.GetInstance());
}
else
{
InstanceManager.CreateInstance();
}
CreateSurface(InConfig.Window);
DeviceManager.Initialize(FDeviceConfig(
InstanceManager.GetInstance(),
Config.bValidationEnabled,
Surface,
InConfig.Window));
DeviceManager.PickPhysicalDevice();
DeviceManager.CreateLogicalDevice();
SwapChain.Initialize(FSwapConfig(
DeviceManager.GetDevice(),
Surface,
Config.Window,
DeviceManager.GetPhysicalQueueFamilies().GraphicsFamily,
DeviceManager.GetPhysicalQueueFamilies().PresentFamily,
DeviceManager.GetSwapChainSupport().Capabilities,
DeviceManager.GetSwapChainSupport().Formats,
DeviceManager.GetSwapChainSupport().PresentModes));
SwapChain.CreateSwapChain();
SwapChain.CreateImageViews();
RenderPass.Initialize(DeviceManager.GetDevice());
RenderPass.CreateRenderPass(SwapChain.GetSwapChainImageFormat());
GraphicsPipeline.Initialize(DeviceManager.GetDevice());
GraphicsPipeline.CreateGraphicsPipeline(SwapChain.GetSwapChainExtent(), RenderPass.GetRenderPass());
Framebuffers.Initialize(FFramebufferConfig(
DeviceManager.GetDevice(),
RenderPass.GetRenderPass(),
SwapChain.GetSwapChainImageViews(),
SwapChain.GetSwapChainExtent()));
Framebuffers.CreateFramebuffers();
CommandBuffers.Initialize(DeviceManager.GetDevice(), RenderPass.GetRenderPass());
CommandBuffers.CreateCommandPool(DeviceManager.GetPhysicalQueueFamilies().GraphicsFamily);
VertexBuffer.Initialize(FVertexBufferConfig(DeviceManager.GetDevice(), DeviceManager.GetPhysicalDevice()));
VertexBuffer.CreateVertexBuffer(Config.Vertices);
CommandBuffers.CreateCommandBuffers(MAX_FRAMES_IN_FLIGHT);
CreateSyncObjects();
}
void VulkanContext::Cleanup()
{
CleanupSwapChain();
VertexBuffer.Cleanup();
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);
}
CommandBuffers.Cleanup();
DeviceManager.Cleanup();
if (Config.bValidationEnabled)
{
DebugManager.Cleanup();
}
vkDestroySurfaceKHR(InstanceManager.GetInstance(), Surface, nullptr);
InstanceManager.Cleanup();
}
void VulkanContext::CreateSurface(GLFWwindow* Window)
{
if (!Window)
{
Log::Error("Window not initialized.");
}
if (!InstanceManager.GetInstance())
{
Log::Error("Instance is null.");
}
VkResult result = glfwCreateWindowSurface(InstanceManager.GetInstance(), Window, nullptr, &Surface);
if (result != VK_SUCCESS)
{
std::string errorMsg;
switch (result)
{
case VK_ERROR_EXTENSION_NOT_PRESENT:
errorMsg = "VK_ERROR_EXTENSION_NOT_PRESENT - Required extension not present";
break;
case VK_ERROR_INITIALIZATION_FAILED:
errorMsg = "VK_ERROR_INITIALIZATION_FAILED - Initialization failed";
break;
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
errorMsg = "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR - Native window already in use";
break;
default:
errorMsg = "Unknown error code: " + std::to_string(result);
break;
}
Log::Error("Failed to create window surface: " + errorMsg);
}
else
{
Log::Info("Window surface created successfully.");
}
}
void VulkanContext::CreateSyncObjects()
{
ImageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
RenderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
InFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
VkSemaphoreCreateInfo SemaphoreInfo{};
SemaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
VkFenceCreateInfo FenceInfo{};
FenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
FenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
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)
{
Log::Error("Failed to create semaphores!");
}
else
{
Log::Info("Successfully created semaphores");
}
}
}
void VulkanContext::DrawFrame()
{
vkWaitForFences(DeviceManager.GetDevice(), 1, &InFlightFences[CurrentFrame], VK_TRUE, UINT64_MAX);
uint32_t ImageIndex;
VkResult result = vkAcquireNextImageKHR(
DeviceManager.GetDevice(),
SwapChain.GetSwapChain(),
UINT64_MAX,
ImageAvailableSemaphores[CurrentFrame],
VK_NULL_HANDLE,
&ImageIndex);
if (result == VK_ERROR_OUT_OF_DATE_KHR)
{
RecreateSwapChain();
return;
}
else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
{
Log::Error("Failed to acquire swap chain images!");
}
vkResetFences(DeviceManager.GetDevice(), 1, &InFlightFences[CurrentFrame]);
vkAcquireNextImageKHR(DeviceManager.GetDevice(), SwapChain.GetSwapChain(), UINT64_MAX, ImageAvailableSemaphores[CurrentFrame], VK_NULL_HANDLE, &ImageIndex);
vkResetCommandBuffer(CommandBuffers.GetCommandBuffer(CurrentFrame), 0);
CommandBuffers.RecordCommandBuffer(
CommandBuffers.GetCommandBuffer(CurrentFrame),
ImageIndex,
VertexBuffer.GetVertexBuffer(),
Config.Vertices,
RenderPass.GetRenderPass(),
SwapChain.GetSwapChainExtent(),
GraphicsPipeline.GetGraphicsPipeline(),
Framebuffers.GetSwapChainFrameBuffers());
VkSubmitInfo SubmitInfo{};
SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore WaitSemaphores[] = { ImageAvailableSemaphores[CurrentFrame] };
VkPipelineStageFlags WaitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
SubmitInfo.waitSemaphoreCount = 1;
SubmitInfo.pWaitSemaphores = WaitSemaphores;
SubmitInfo.pWaitDstStageMask = WaitStages;
SubmitInfo.commandBufferCount = 1;
VkCommandBuffer CommandBuffer = CommandBuffers.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)
{
Log::Error("Failed to submit draw command buffer!");
}
VkPresentInfoKHR PresentInfo{};
PresentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
PresentInfo.waitSemaphoreCount = 1;
PresentInfo.pWaitSemaphores = SignalSemaphores;
VkSwapchainKHR SwapChains[] = { SwapChain.GetSwapChain() };
PresentInfo.swapchainCount = 1;
PresentInfo.pSwapchains = SwapChains;
PresentInfo.pImageIndices = &ImageIndex;
PresentInfo.pResults = nullptr;
result = vkQueuePresentKHR(DeviceManager.GetPresentQueue(), &PresentInfo);
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || bFramebufferResized)
{
bFramebufferResized = false;
RecreateSwapChain();
}
else if (result != VK_SUCCESS)
{
Log::Error("Failed to present swap chain image!");
}
CurrentFrame = (CurrentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
}
void VulkanContext::RecreateSwapChain()
{
int Width = 0, Height = 0;
glfwGetFramebufferSize(Config.Window, &Width, &Height);
while (Width == 0 || Height == 0)
{
glfwGetFramebufferSize(Config.Window, &Width, &Height);
glfwWaitEvents();
}
Log::Info("Recreating SwapChain...");
vkDeviceWaitIdle(DeviceManager.GetDevice());
CleanupSwapChain();
SwapChain.CreateSwapChain();
SwapChain.CreateImageViews();
Framebuffers.CreateFramebuffers();
}
void VulkanContext::CleanupSwapChain()
{
Framebuffers.Cleanup();
SwapChain.Cleanup();
}