Finished basic Vulkan setup

This commit is contained in:
Pasha Bibko
2025-11-16 17:06:24 +00:00
parent 8ca07fc723
commit 038396338e
6 changed files with 125 additions and 14 deletions

View File

@@ -25,6 +25,9 @@ namespace PB::Renderer
class VulkanManager
{
public:
VulkanManager() = delete;
~VulkanManager() = delete;
static bool InitAll(GLFWwindow* window);
static std::optional<VkInstance> Init();
static bool Cleanup();
@@ -38,6 +41,9 @@ namespace PB::Renderer
static bool CreateFramebuffer();
static bool CreateGraphicsPipeline();
static bool CreateCommandBuffers();
static void CreateSemaphores();
static bool RenderPass(GLFWwindow* window);
private:
static bool IsDeviceSuitable(VkPhysicalDevice device, VkSurfaceKHR surface);
@@ -76,5 +82,8 @@ namespace PB::Renderer
static VkCommandPool s_CommandPool;
static std::vector<VkCommandBuffer> s_CommandBuffers;
static VkSemaphore s_ImageAvailableSemaphore;
static VkSemaphore s_RenderFinishedSemaphore;
};
}

View File

@@ -28,6 +28,9 @@ namespace PB::Renderer
VkCommandPool VulkanManager::s_CommandPool = VK_NULL_HANDLE;
std::vector<VkCommandBuffer> VulkanManager::s_CommandBuffers = {};
VkSemaphore VulkanManager::s_ImageAvailableSemaphore = VK_NULL_HANDLE;
VkSemaphore VulkanManager::s_RenderFinishedSemaphore = VK_NULL_HANDLE;
bool VulkanManager::InitAll(GLFWwindow* window)
{
if (const std::optional<VkInstance> instance = VulkanManager::Init(); !instance)
@@ -37,19 +40,19 @@ namespace PB::Renderer
return false;
if (!(
VulkanManager::PickPhysicalDevice() ||
VulkanManager::PickPhysicalDevice() ||
VulkanManager::CreateLogicalDevice() ||
VulkanManager::CreateSwapChain(window) ||
VulkanManager::CreateImageViews() ||
VulkanManager::CreateRenderPass() ||
VulkanManager::CreateFramebuffer() ||
VulkanManager::CreateGraphicsPipeline() ||
VulkanManager::PickPhysicalDevice() &&
VulkanManager::CreateLogicalDevice() &&
VulkanManager::CreateSwapChain(window) &&
VulkanManager::CreateImageViews() &&
VulkanManager::CreateRenderPass() &&
VulkanManager::CreateFramebuffer() &&
VulkanManager::CreateGraphicsPipeline() &&
VulkanManager::CreateCommandBuffers()
)) {
return false;
}
VulkanManager::CreateSemaphores();
return true;
}
@@ -533,8 +536,8 @@ namespace PB::Renderer
bool VulkanManager::CreateGraphicsPipeline()
{
VkShaderModule vertShaderModule = CreateShaderModule("shaders/vert.spv");
VkShaderModule fragShaderModule = CreateShaderModule("shaders/frag.spv");
VkShaderModule vertShaderModule = CreateShaderModule("../shaders/vert.spv");
VkShaderModule fragShaderModule = CreateShaderModule("../shaders/frag.spv");
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
@@ -641,7 +644,8 @@ namespace PB::Renderer
std::ifstream file(filename, std::ios::ate | std::ios::binary);
if (!file.is_open())
{
throw std::runtime_error("Failed to open shader file: " + filename);
std::cout << "Failed to open shader file at '" << std::filesystem::absolute(filename) << "'" << std::endl;
return VK_NULL_HANDLE;
}
const size_t fileSize = file.tellg();
@@ -666,6 +670,14 @@ namespace PB::Renderer
bool VulkanManager::CreateCommandBuffers()
{
VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
poolInfo.queueFamilyIndex = s_QueueIndices.graphicsFamily.value();
if (vkCreateCommandPool(s_Device, &poolInfo, nullptr, &s_CommandPool) != VK_SUCCESS)
return false;
s_CommandBuffers.resize(s_Framebuffers.size());
VkCommandBufferAllocateInfo allocInfo{};
@@ -674,7 +686,7 @@ namespace PB::Renderer
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = static_cast<uint32_t>(s_CommandBuffers.size());
if (vkAllocateCommandBuffers(s_Device, &allocInfo, s_CommandBuffers.data()) != VK_SUCCESS)
if (vkAllocateCommandBuffers(s_Device, &allocInfo, s_CommandBuffers.data()) != VK_SUCCESS) // <- Crashes here
return false;
for (size_t i = 0; i < s_CommandBuffers.size(); i++)
@@ -691,7 +703,7 @@ namespace PB::Renderer
renderPassInfo.renderArea.offset = {0, 0};
renderPassInfo.renderArea.extent = s_SwapChainExtent;
VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
VkClearValue clearColor = {0.0f, 0.0f, 0.0f, 1.0f};
renderPassInfo.clearValueCount = 1;
renderPassInfo.pClearValues = &clearColor;
@@ -709,4 +721,13 @@ namespace PB::Renderer
return true;
}
void VulkanManager::CreateSemaphores()
{
VkSemaphoreCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
vkCreateSemaphore(s_Device, &createInfo, nullptr, &s_ImageAvailableSemaphore);
vkCreateSemaphore(s_Device, &createInfo, nullptr, &s_RenderFinishedSemaphore);
}
}

View File

@@ -0,0 +1,76 @@
#include "VulkanManager.h"
namespace PB::Renderer
{
bool VulkanManager::RenderPass(GLFWwindow* window)
{
uint32_t imageIndex;
VkResult result = vkAcquireNextImageKHR(
s_Device,
s_SwapChain,
UINT64_MAX,
s_ImageAvailableSemaphore,
VK_NULL_HANDLE,
&imageIndex
);
if (result == VK_ERROR_OUT_OF_DATE_KHR)
{
return false;
}
if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
{
std::cout << "PB::Renderer::VulkanManager::RenderPass(): Failed to acquire swap chain image!" << std::endl;
return false;
}
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore waitSemaphores[] = { s_ImageAvailableSemaphore };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &s_CommandBuffers[imageIndex];
VkSemaphore signalSemaphores[] = { s_RenderFinishedSemaphore };
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
if (vkQueueSubmit(s_GraphicsQueue, 1, &submitInfo, VK_NULL_HANDLE) != VK_SUCCESS)
{
std::cout << "PB::Renderer::VulkanManager::RenderPass(): Failed to submit draw command buffer!" << std::endl;
return false;
}
VkPresentInfoKHR presentInfo{};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores;
VkSwapchainKHR swapChains[] = { s_SwapChain };
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapChains;
presentInfo.pImageIndices = &imageIndex;
result = vkQueuePresentKHR(s_PresentQueue, &presentInfo);
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR)
{
return false;
}
else if (result != VK_SUCCESS)
{
std::cout << "PB::Renderer::VulkanManager::RenderPass(): Failed to present swap chain image!" << std::endl;
return false;
}
vkQueueWaitIdle(s_PresentQueue);
return true;
}
}