Finished basic Vulkan setup
This commit is contained in:
@@ -33,7 +33,8 @@ add_executable(VulkanRenderer
|
|||||||
main.cpp
|
main.cpp
|
||||||
src/managers/GLFWManager.h
|
src/managers/GLFWManager.h
|
||||||
src/managers/GLFWManager.cpp
|
src/managers/GLFWManager.cpp
|
||||||
src/managers/VulkanManager.cpp
|
src/managers/VulkanManagerInit.cpp
|
||||||
|
src/managers/VulkanManagerRender.cpp
|
||||||
src/managers/VulkanManager.h
|
src/managers/VulkanManager.h
|
||||||
src/VulkanRenderer.h
|
src/VulkanRenderer.h
|
||||||
)
|
)
|
||||||
|
|||||||
3
main.cpp
3
main.cpp
@@ -37,6 +37,9 @@ int main()
|
|||||||
while (!glfwWindowShouldClose(window))
|
while (!glfwWindowShouldClose(window))
|
||||||
{
|
{
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
||||||
|
if (!VulkanManager::RenderPass(window))
|
||||||
|
CleanupAllAndExit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cleans up GLFW and Vulkan */
|
/* Cleans up GLFW and Vulkan */
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
/* Commonly used C++ STD files */
|
/* Commonly used C++ STD files */
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ namespace PB::Renderer
|
|||||||
class VulkanManager
|
class VulkanManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
VulkanManager() = delete;
|
||||||
|
~VulkanManager() = delete;
|
||||||
|
|
||||||
static bool InitAll(GLFWwindow* window);
|
static bool InitAll(GLFWwindow* window);
|
||||||
static std::optional<VkInstance> Init();
|
static std::optional<VkInstance> Init();
|
||||||
static bool Cleanup();
|
static bool Cleanup();
|
||||||
@@ -38,6 +41,9 @@ namespace PB::Renderer
|
|||||||
static bool CreateFramebuffer();
|
static bool CreateFramebuffer();
|
||||||
static bool CreateGraphicsPipeline();
|
static bool CreateGraphicsPipeline();
|
||||||
static bool CreateCommandBuffers();
|
static bool CreateCommandBuffers();
|
||||||
|
static void CreateSemaphores();
|
||||||
|
|
||||||
|
static bool RenderPass(GLFWwindow* window);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool IsDeviceSuitable(VkPhysicalDevice device, VkSurfaceKHR surface);
|
static bool IsDeviceSuitable(VkPhysicalDevice device, VkSurfaceKHR surface);
|
||||||
@@ -76,5 +82,8 @@ namespace PB::Renderer
|
|||||||
|
|
||||||
static VkCommandPool s_CommandPool;
|
static VkCommandPool s_CommandPool;
|
||||||
static std::vector<VkCommandBuffer> s_CommandBuffers;
|
static std::vector<VkCommandBuffer> s_CommandBuffers;
|
||||||
|
|
||||||
|
static VkSemaphore s_ImageAvailableSemaphore;
|
||||||
|
static VkSemaphore s_RenderFinishedSemaphore;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ namespace PB::Renderer
|
|||||||
VkCommandPool VulkanManager::s_CommandPool = VK_NULL_HANDLE;
|
VkCommandPool VulkanManager::s_CommandPool = VK_NULL_HANDLE;
|
||||||
std::vector<VkCommandBuffer> VulkanManager::s_CommandBuffers = {};
|
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)
|
bool VulkanManager::InitAll(GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (const std::optional<VkInstance> instance = VulkanManager::Init(); !instance)
|
if (const std::optional<VkInstance> instance = VulkanManager::Init(); !instance)
|
||||||
@@ -37,19 +40,19 @@ namespace PB::Renderer
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!(
|
if (!(
|
||||||
VulkanManager::PickPhysicalDevice() ||
|
VulkanManager::PickPhysicalDevice() &&
|
||||||
VulkanManager::PickPhysicalDevice() ||
|
VulkanManager::CreateLogicalDevice() &&
|
||||||
VulkanManager::CreateLogicalDevice() ||
|
VulkanManager::CreateSwapChain(window) &&
|
||||||
VulkanManager::CreateSwapChain(window) ||
|
VulkanManager::CreateImageViews() &&
|
||||||
VulkanManager::CreateImageViews() ||
|
VulkanManager::CreateRenderPass() &&
|
||||||
VulkanManager::CreateRenderPass() ||
|
VulkanManager::CreateFramebuffer() &&
|
||||||
VulkanManager::CreateFramebuffer() ||
|
VulkanManager::CreateGraphicsPipeline() &&
|
||||||
VulkanManager::CreateGraphicsPipeline() ||
|
|
||||||
VulkanManager::CreateCommandBuffers()
|
VulkanManager::CreateCommandBuffers()
|
||||||
)) {
|
)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VulkanManager::CreateSemaphores();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,8 +536,8 @@ namespace PB::Renderer
|
|||||||
|
|
||||||
bool VulkanManager::CreateGraphicsPipeline()
|
bool VulkanManager::CreateGraphicsPipeline()
|
||||||
{
|
{
|
||||||
VkShaderModule vertShaderModule = CreateShaderModule("shaders/vert.spv");
|
VkShaderModule vertShaderModule = CreateShaderModule("../shaders/vert.spv");
|
||||||
VkShaderModule fragShaderModule = CreateShaderModule("shaders/frag.spv");
|
VkShaderModule fragShaderModule = CreateShaderModule("../shaders/frag.spv");
|
||||||
|
|
||||||
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
|
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
|
||||||
vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
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);
|
std::ifstream file(filename, std::ios::ate | std::ios::binary);
|
||||||
if (!file.is_open())
|
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();
|
const size_t fileSize = file.tellg();
|
||||||
@@ -666,6 +670,14 @@ namespace PB::Renderer
|
|||||||
|
|
||||||
bool VulkanManager::CreateCommandBuffers()
|
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());
|
s_CommandBuffers.resize(s_Framebuffers.size());
|
||||||
|
|
||||||
VkCommandBufferAllocateInfo allocInfo{};
|
VkCommandBufferAllocateInfo allocInfo{};
|
||||||
@@ -674,7 +686,7 @@ namespace PB::Renderer
|
|||||||
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||||
allocInfo.commandBufferCount = static_cast<uint32_t>(s_CommandBuffers.size());
|
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;
|
return false;
|
||||||
|
|
||||||
for (size_t i = 0; i < s_CommandBuffers.size(); i++)
|
for (size_t i = 0; i < s_CommandBuffers.size(); i++)
|
||||||
@@ -691,7 +703,7 @@ namespace PB::Renderer
|
|||||||
renderPassInfo.renderArea.offset = {0, 0};
|
renderPassInfo.renderArea.offset = {0, 0};
|
||||||
renderPassInfo.renderArea.extent = s_SwapChainExtent;
|
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.clearValueCount = 1;
|
||||||
renderPassInfo.pClearValues = &clearColor;
|
renderPassInfo.pClearValues = &clearColor;
|
||||||
|
|
||||||
@@ -709,4 +721,13 @@ namespace PB::Renderer
|
|||||||
|
|
||||||
return true;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
76
src/managers/VulkanManagerRender.cpp
Normal file
76
src/managers/VulkanManagerRender.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user