Add CommandPool class

This commit is contained in:
Grayson Riffe 2025-02-26 01:43:31 -06:00
parent b0e204f03c
commit c62f727052
9 changed files with 160 additions and 116 deletions

View File

@ -1,5 +1,5 @@
# NF library CMakeLists.txt # NF library CMakeLists.txt
add_library(NothinFancy STATIC "src/Engine.cpp" "src/include/nf.h" "src/pch.h" "src/util.h" "src/util/log.h" "src/util/log.cpp" "src/include/nf/config.h" "src/util/util.cpp" "src/util/file.h" "src/util/file.cpp" "src/client/Client.h" "src/client/Client.cpp" "src/client/Window.h" "src/client/Window.cpp" "src/client/render/RenderEngine.h" "src/client/render/RenderEngine.cpp" "src/client/render/ShaderModule.h" "src/client/render/ShaderModule.cpp" "src/client/render/GraphicsResource.h" "src/client/render/Buffer.h" "src/client/render/Buffer.cpp" "src/client/render/VideoMemoryAllocator.h" "src/client/render/VideoMemoryAllocator.cpp" "src/client/render/Image.h" "src/client/render/Image.cpp") add_library(NothinFancy STATIC "src/Engine.cpp" "src/include/nf.h" "src/pch.h" "src/util.h" "src/util/log.h" "src/util/log.cpp" "src/include/nf/config.h" "src/util/util.cpp" "src/util/file.h" "src/util/file.cpp" "src/client/Client.h" "src/client/Client.cpp" "src/client/Window.h" "src/client/Window.cpp" "src/client/render/RenderEngine.h" "src/client/render/RenderEngine.cpp" "src/client/render/ShaderModule.h" "src/client/render/ShaderModule.cpp" "src/client/render/GraphicsResource.h" "src/client/render/Buffer.h" "src/client/render/Buffer.cpp" "src/client/render/VideoMemoryAllocator.h" "src/client/render/VideoMemoryAllocator.cpp" "src/client/render/Image.h" "src/client/render/Image.cpp" "src/client/render/CommandPool.h" "src/client/render/CommandPool.cpp")
# Use C++20 # Use C++20
set_property(TARGET NothinFancy PROPERTY CXX_STANDARD 20) set_property(TARGET NothinFancy PROPERTY CXX_STANDARD 20)

View File

@ -5,7 +5,7 @@
#include "util.h" #include "util.h"
namespace nf::client::render { namespace nf::client::render {
Buffer::Buffer(BufferType type, const VkDevice& device, VideoMemoryAllocator& allocator, const VkCommandPool& commandPool, const VkQueue& queue, void* bufferData, size_t bufferSize) Buffer::Buffer(BufferType type, const VkDevice& device, VideoMemoryAllocator& allocator, const CommandPool& commandPool, void* bufferData, size_t bufferSize)
: GraphicsResource(device) : GraphicsResource(device)
, m_allocator(allocator) , m_allocator(allocator)
, m_handle() , m_handle()
@ -28,7 +28,7 @@ namespace nf::client::render {
return; return;
} }
Buffer stagingBuffer(BufferType::Staging, m_device, m_allocator, nullptr, nullptr, bufferData, bufferSize); Buffer stagingBuffer(BufferType::Staging, m_device, m_allocator, commandPool, bufferData, bufferSize);
VkBufferUsageFlags mainUsage = NULL; VkBufferUsageFlags mainUsage = NULL;
@ -46,7 +46,7 @@ namespace nf::client::render {
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | mainUsage, m_handle); createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | mainUsage, m_handle);
m_allocator.allocateForBuffer(m_handle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, m_allocation); m_allocator.allocateForBuffer(m_handle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, m_allocation);
copyBuffer(stagingBuffer.getHandle(), m_handle, bufferSize, commandPool, queue); copyBuffer(stagingBuffer.getHandle(), m_handle, bufferSize, commandPool);
} }
const VkBuffer& Buffer::getHandle() const { const VkBuffer& Buffer::getHandle() const {
@ -70,30 +70,14 @@ namespace nf::client::render {
NFError("Could not create vertex buffer."); NFError("Could not create vertex buffer.");
} }
void Buffer::copyBuffer(VkBuffer bufferSource, VkBuffer bufferDestination, VkDeviceSize size, VkCommandPool commandPool, VkQueue queue) { void Buffer::copyBuffer(VkBuffer bufferSource, VkBuffer bufferDestination, VkDeviceSize size, const CommandPool& commandPool) {
VkCommandBuffer commandBuffer = nullptr; VkCommandBuffer commandBuffer = commandPool.beginOneTimeExecution();
VkCommandBufferAllocateInfo commandBufferAI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
commandBufferAI.commandPool = commandPool;
commandBufferAI.commandBufferCount = 1;
vkAllocateCommandBuffers(m_device, &commandBufferAI, &commandBuffer);
VkCommandBufferBeginInfo commandBufferBI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
commandBufferBI.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(commandBuffer, &commandBufferBI);
VkBufferCopy bufferCopyRegion = {}; VkBufferCopy bufferCopyRegion = {};
bufferCopyRegion.size = size; bufferCopyRegion.size = size;
vkCmdCopyBuffer(commandBuffer, bufferSource, bufferDestination, 1, &bufferCopyRegion); vkCmdCopyBuffer(commandBuffer, bufferSource, bufferDestination, 1, &bufferCopyRegion);
vkEndCommandBuffer(commandBuffer); commandPool.endOneTimeExecution(commandBuffer);
VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
vkQueueSubmit(queue, 1, &submitInfo, nullptr);
vkQueueWaitIdle(queue);
vkFreeCommandBuffers(m_device, commandPool, 1, &commandBuffer);
} }
void Buffer::destroyBuffer(VkBuffer buffer, VideoMemoryAllocation& allocation) { void Buffer::destroyBuffer(VkBuffer buffer, VideoMemoryAllocation& allocation) {

View File

@ -3,6 +3,7 @@
#include "GraphicsResource.h" #include "GraphicsResource.h"
#include "VideoMemoryAllocator.h" #include "VideoMemoryAllocator.h"
#include "CommandPool.h"
namespace nf::client::render { namespace nf::client::render {
enum class BufferType { enum class BufferType {
@ -14,7 +15,7 @@ namespace nf::client::render {
class Buffer : GraphicsResource { class Buffer : GraphicsResource {
public: public:
Buffer(BufferType type, const VkDevice& device, VideoMemoryAllocator& allocator, const VkCommandPool& commandPool, const VkQueue& queue, void* bufferData, size_t bufferSize); Buffer(BufferType type, const VkDevice& device, VideoMemoryAllocator& allocator, const CommandPool& commandPool, void* bufferData, size_t bufferSize);
const VkBuffer& getHandle() const; const VkBuffer& getHandle() const;
void* getPointer() const; void* getPointer() const;
@ -23,7 +24,7 @@ namespace nf::client::render {
~Buffer(); ~Buffer();
private: private:
void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkBuffer& buffer); void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkBuffer& buffer);
void copyBuffer(VkBuffer sourceBuffer, VkBuffer destinationBuffer, VkDeviceSize size, VkCommandPool commandPool, VkQueue queue); void copyBuffer(VkBuffer sourceBuffer, VkBuffer destinationBuffer, VkDeviceSize size, const CommandPool& commandPool);
void destroyBuffer(VkBuffer buffer, VideoMemoryAllocation& allocation); void destroyBuffer(VkBuffer buffer, VideoMemoryAllocation& allocation);

View File

@ -0,0 +1,61 @@
// CommandPool class implementation
#include "pch.h"
#include "CommandPool.h"
#include "util.h"
namespace nf::client::render {
CommandPool::CommandPool(const VkDevice& device, const VkQueue& queue, uint32_t queueFamilyIndex)
: GraphicsResource(device)
, m_queue(queue)
, m_handle()
{
VkCommandPoolCreateInfo commandPoolCI = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
commandPoolCI.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
commandPoolCI.queueFamilyIndex = queueFamilyIndex;
if (vkCreateCommandPool(m_device, &commandPoolCI, nullptr, &m_handle) != VK_SUCCESS)
NFError("Could not create command pool.");
}
VkCommandBuffer CommandPool::allocateCommandBuffer() const {
VkCommandBuffer commandBuffer = nullptr;
VkCommandBufferAllocateInfo commandBufferAI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
commandBufferAI.commandPool = m_handle;
commandBufferAI.commandBufferCount = 1;
if (vkAllocateCommandBuffers(m_device, &commandBufferAI, &commandBuffer) != VK_SUCCESS)
NFError("Could not create command buffer.");
return commandBuffer;
}
VkCommandBuffer CommandPool::beginOneTimeExecution() const {
VkCommandBuffer commandBuffer = allocateCommandBuffer();
VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(commandBuffer, &beginInfo);
return commandBuffer;
}
void CommandPool::endOneTimeExecution(VkCommandBuffer commandBuffer) const {
vkEndCommandBuffer(commandBuffer);
VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
vkQueueSubmit(m_queue, 1, &submitInfo, nullptr);
vkQueueWaitIdle(m_queue);
vkFreeCommandBuffers(m_device, m_handle, 1, &commandBuffer);
}
CommandPool::~CommandPool() {
vkDestroyCommandPool(m_device, m_handle, nullptr);
}
}

View File

@ -0,0 +1,22 @@
// CommandPool class header
#pragma once
#include "GraphicsResource.h"
namespace nf::client::render {
class CommandPool : GraphicsResource {
public:
CommandPool(const VkDevice& device, const VkQueue& queue, uint32_t queueFamilyIndex);
VkCommandBuffer allocateCommandBuffer() const;
VkCommandBuffer beginOneTimeExecution() const;
void endOneTimeExecution(VkCommandBuffer commandBuffer) const;
~CommandPool();
private:
const VkQueue& m_queue;
VkCommandPool m_handle;
};
}

View File

@ -9,7 +9,7 @@
#include "stb_image.h" #include "stb_image.h"
namespace nf::client::render { namespace nf::client::render {
Image::Image(ImageType type, const VkDevice& device, VideoMemoryAllocator& allocator, const VkCommandPool& commandPool, const VkQueue& queue, const std::string& imageData, VkExtent2D attachmentExtent) Image::Image(ImageType type, const VkDevice& device, VideoMemoryAllocator& allocator, const CommandPool& commandPool, const std::string& imageData, VkExtent2D attachmentExtent)
: GraphicsResource(device) : GraphicsResource(device)
, m_allocator(allocator) , m_allocator(allocator)
, m_handle() , m_handle()
@ -21,7 +21,7 @@ namespace nf::client::render {
switch (type) { switch (type) {
case ImageType::Texture: case ImageType::Texture:
imageFormat = VK_FORMAT_R8G8B8A8_SRGB; imageFormat = VK_FORMAT_R8G8B8A8_SRGB;
createTextureImage(imageFormat, commandPool, queue, imageData); createTextureImage(imageFormat, commandPool, imageData);
break; break;
case ImageType::DepthAttachment: case ImageType::DepthAttachment:
@ -37,28 +37,20 @@ namespace nf::client::render {
return m_view; return m_view;
} }
void Image::createTextureImage(VkFormat imageFormat, const VkCommandPool& commandPool, const VkQueue& queue, const std::string& imageData) { void Image::createTextureImage(VkFormat imageFormat, const CommandPool& commandPool, const std::string& imageData) {
int imageWidth = 0, imageHeight = 0, numChannels = 0; int imageWidth = 0, imageHeight = 0, numChannels = 0;
stbi_uc* rawImageData = stbi_load_from_memory(reinterpret_cast<const stbi_uc*>(imageData.data()), imageData.size(), &imageWidth, &imageHeight, &numChannels, STBI_rgb_alpha); stbi_uc* rawImageData = stbi_load_from_memory(reinterpret_cast<const stbi_uc*>(imageData.data()), imageData.size(), &imageWidth, &imageHeight, &numChannels, STBI_rgb_alpha);
VkDeviceSize imageSize = static_cast<VkDeviceSize>(imageWidth) * imageHeight * 4; VkDeviceSize imageSize = static_cast<VkDeviceSize>(imageWidth) * imageHeight * 4;
Buffer stagingBuffer(BufferType::Staging, m_device, m_allocator, nullptr, nullptr, rawImageData, imageSize); Buffer stagingBuffer(BufferType::Staging, m_device, m_allocator, commandPool, rawImageData, imageSize);
stbi_image_free(rawImageData); stbi_image_free(rawImageData);
VkExtent2D imageExtent = { static_cast<uint32_t>(imageWidth), static_cast<uint32_t>(imageHeight) }; VkExtent2D imageExtent = { static_cast<uint32_t>(imageWidth), static_cast<uint32_t>(imageHeight) };
createImage(imageFormat, imageExtent, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); createImage(imageFormat, imageExtent, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
VkCommandBuffer commandBuffer = nullptr; VkCommandBuffer commandBuffer = commandPool.beginOneTimeExecution();
VkCommandBufferAllocateInfo commandBufferAI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
commandBufferAI.commandPool = commandPool;
commandBufferAI.commandBufferCount = 1;
vkAllocateCommandBuffers(m_device, &commandBufferAI, &commandBuffer);
VkCommandBufferBeginInfo commandBufferBI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
commandBufferBI.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(commandBuffer, &commandBufferBI);
// Image transition undefined -> transfer destination // Image transition undefined -> transfer destination
VkImageMemoryBarrier imageMemoryBarrier = { {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER} }; VkImageMemoryBarrier imageMemoryBarrier = { {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER} };
@ -73,15 +65,9 @@ namespace nf::client::render {
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
vkEndCommandBuffer(commandBuffer); commandPool.endOneTimeExecution(commandBuffer);
VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO }; commandBuffer = commandPool.beginOneTimeExecution();
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
vkQueueSubmit(queue, 1, &submitInfo, nullptr);
vkQueueWaitIdle(queue);
vkBeginCommandBuffer(commandBuffer, &commandBufferBI);
VkBufferImageCopy bufferImageCopyRegion = {}; VkBufferImageCopy bufferImageCopyRegion = {};
bufferImageCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; bufferImageCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
@ -89,11 +75,9 @@ namespace nf::client::render {
bufferImageCopyRegion.imageExtent = { static_cast<uint32_t>(imageWidth), static_cast<uint32_t>(imageHeight), 1 }; bufferImageCopyRegion.imageExtent = { static_cast<uint32_t>(imageWidth), static_cast<uint32_t>(imageHeight), 1 };
vkCmdCopyBufferToImage(commandBuffer, stagingBuffer.getHandle(), m_handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferImageCopyRegion); vkCmdCopyBufferToImage(commandBuffer, stagingBuffer.getHandle(), m_handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferImageCopyRegion);
vkEndCommandBuffer(commandBuffer); commandPool.endOneTimeExecution(commandBuffer);
vkQueueSubmit(queue, 1, &submitInfo, nullptr);
vkQueueWaitIdle(queue);
vkBeginCommandBuffer(commandBuffer, &commandBufferBI); commandBuffer = commandPool.beginOneTimeExecution();
// Image transition transfer destination -> shader read only // Image transition transfer destination -> shader read only
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
@ -102,11 +86,7 @@ namespace nf::client::render {
imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
vkEndCommandBuffer(commandBuffer); commandPool.endOneTimeExecution(commandBuffer);
vkQueueSubmit(queue, 1, &submitInfo, nullptr);
vkQueueWaitIdle(queue);
vkFreeCommandBuffers(m_device, commandPool, 1, &commandBuffer);
} }
void Image::createImage(VkFormat format, VkExtent2D& size, VkImageUsageFlags usage) { void Image::createImage(VkFormat format, VkExtent2D& size, VkImageUsageFlags usage) {

View File

@ -3,6 +3,7 @@
#include "GraphicsResource.h" #include "GraphicsResource.h"
#include "VideoMemoryAllocator.h" #include "VideoMemoryAllocator.h"
#include "CommandPool.h"
namespace nf::client::render { namespace nf::client::render {
enum class ImageType { enum class ImageType {
@ -12,13 +13,13 @@ namespace nf::client::render {
class Image : GraphicsResource { class Image : GraphicsResource {
public: public:
Image(ImageType type, const VkDevice& device, VideoMemoryAllocator& allocator, const VkCommandPool& commandPool, const VkQueue& queue, const std::string& imageData, VkExtent2D attachmentExtent = {}); Image(ImageType type, const VkDevice& device, VideoMemoryAllocator& allocator, const CommandPool& commandPool, const std::string& imageData, VkExtent2D attachmentExtent = {});
const VkImageView& getView() const; const VkImageView& getView() const;
~Image(); ~Image();
private: private:
void createTextureImage(VkFormat imageFormat, const VkCommandPool& commandPool, const VkQueue& queue, const std::string& imageData); void createTextureImage(VkFormat imageFormat, const CommandPool& commandPool, const std::string& imageData);
void createImage(VkFormat imageFormat, VkExtent2D& size, VkImageUsageFlags usage); void createImage(VkFormat imageFormat, VkExtent2D& size, VkImageUsageFlags usage);
void createImageView(VkFormat format); void createImageView(VkFormat format);

View File

@ -23,26 +23,27 @@ namespace nf::client::render {
, m_device() , m_device()
, m_queueGraphics() , m_queueGraphics()
, m_queuePresent() , m_queuePresent()
, m_renderPassOutput()
, m_swapchain()
, m_swapchainImageFormat()
, m_swapchainExtent()
, m_swapchainImages()
, m_swapchainImageViews()
, m_pipelineOutputDescriptorSetLayout()
, m_pipelineOutputLayout()
, m_pipelineOutputDescriptorPool()
, m_pipelineOutput()
, m_commandPool() , m_commandPool()
, m_commandBuffer() , m_commandBuffer()
, m_semaphoreImageAvailable() , m_semaphoreImageAvailable()
, m_semaphoreRenderingDone() , m_semaphoreRenderingDone()
, m_fenceFrameInFlight() , m_fenceFrameInFlight()
, m_swapchain()
, m_swapchainImageFormat()
, m_swapchainExtent()
, m_swapchainImages()
, m_swapchainImageViews()
, m_renderPassOutput()
, m_pipelineOutputDescriptorSetLayout()
, m_pipelineOutputLayout()
, m_pipelineOutputDescriptorPool()
, m_pipelineOutput()
, m_allocator() , m_allocator()
, m_swapchainFramebuffers()
, m_imageDepth() , m_imageDepth()
, m_swapchainFramebuffers()
, m_bufferVertex() , m_bufferVertex()
, m_bufferIndex() , m_bufferIndex()
, m_bufferUniformMVP()
, m_imageTest() , m_imageTest()
, m_sampler() , m_sampler()
, m_pipelineOutputDescriptorSet() , m_pipelineOutputDescriptorSet()
@ -55,10 +56,12 @@ namespace nf::client::render {
createSurface(); createSurface();
pickPhysicalDevice(); pickPhysicalDevice();
createDevice(); createDevice();
createExecutionObjects();
createSwapchain(); createSwapchain();
createOutputRenderPass(); createOutputRenderPass();
createOutputPipeline(); createOutputPipeline();
createExecutionObjects();
m_allocator = std::make_unique<VideoMemoryAllocator>(m_device, m_physicalDevice); m_allocator = std::make_unique<VideoMemoryAllocator>(m_device, m_physicalDevice);
createSwapchainFramebuffers(); createSwapchainFramebuffers();
@ -285,6 +288,21 @@ namespace nf::client::render {
} }
} }
void RenderEngine::createExecutionObjects() {
m_commandPool = std::make_unique<CommandPool>(m_device, m_queueGraphics, m_queueFIGraphics);
m_commandBuffer = m_commandPool->allocateCommandBuffer();
VkSemaphoreCreateInfo semaphoreCI = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
if (vkCreateSemaphore(m_device, &semaphoreCI, nullptr, &m_semaphoreImageAvailable) != VK_SUCCESS ||
vkCreateSemaphore(m_device, &semaphoreCI, nullptr, &m_semaphoreRenderingDone) != VK_SUCCESS)
NFError("Could not create semaphore.");
VkFenceCreateInfo fenceCI = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO };
fenceCI.flags = VK_FENCE_CREATE_SIGNALED_BIT;
if (vkCreateFence(m_device, &fenceCI, nullptr, &m_fenceFrameInFlight) != VK_SUCCESS)
NFError("Could not create fence.");
}
void RenderEngine::createOutputRenderPass() { void RenderEngine::createOutputRenderPass() {
VkAttachmentDescription attachmentDescriptions[2] = {}; VkAttachmentDescription attachmentDescriptions[2] = {};
@ -465,37 +483,11 @@ namespace nf::client::render {
NFError("Could not create graphics pipeline."); NFError("Could not create graphics pipeline.");
} }
void RenderEngine::createExecutionObjects() {
VkCommandPoolCreateInfo commandPoolCI = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
commandPoolCI.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
commandPoolCI.queueFamilyIndex = m_queueFIGraphics;
if (vkCreateCommandPool(m_device, &commandPoolCI, nullptr, &m_commandPool) != VK_SUCCESS)
NFError("Could not create command pool.");
VkCommandBufferAllocateInfo commandBufferAI = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
commandBufferAI.commandPool = m_commandPool;
commandBufferAI.commandBufferCount = 1;
if (vkAllocateCommandBuffers(m_device, &commandBufferAI, &m_commandBuffer) != VK_SUCCESS)
NFError("Could not create command buffer.");
VkSemaphoreCreateInfo semaphoreCI = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
if (vkCreateSemaphore(m_device, &semaphoreCI, nullptr, &m_semaphoreImageAvailable) != VK_SUCCESS ||
vkCreateSemaphore(m_device, &semaphoreCI, nullptr, &m_semaphoreRenderingDone) != VK_SUCCESS)
NFError("Could not create semaphore.");
VkFenceCreateInfo fenceCI = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO };
fenceCI.flags = VK_FENCE_CREATE_SIGNALED_BIT;
if (vkCreateFence(m_device, &fenceCI, nullptr, &m_fenceFrameInFlight) != VK_SUCCESS)
NFError("Could not create fence.");
}
void RenderEngine::createSwapchainFramebuffers() { void RenderEngine::createSwapchainFramebuffers() {
// TODO: Won't need these forever // TODO: Won't need these forever
// Create depth buffer first // Create depth buffer first
m_imageDepth = std::make_unique<Image>(ImageType::DepthAttachment, m_device, *m_allocator, nullptr, nullptr, std::string(), m_swapchainExtent); m_imageDepth = std::make_unique<Image>(ImageType::DepthAttachment, m_device, *m_allocator, *m_commandPool, std::string(), m_swapchainExtent);
m_swapchainFramebuffers.resize(m_swapchainImageViews.size()); m_swapchainFramebuffers.resize(m_swapchainImageViews.size());
for (int i = 0; i < m_swapchainImageViews.size(); i++) { for (int i = 0; i < m_swapchainImageViews.size(); i++) {
@ -550,7 +542,7 @@ namespace nf::client::render {
}; };
size_t cubeVerticesSize = sizeof(cubeVertices[0]) * cubeVertices.size(); size_t cubeVerticesSize = sizeof(cubeVertices[0]) * cubeVertices.size();
m_bufferVertex = std::make_unique<Buffer>(BufferType::Vertex, m_device, *m_allocator, m_commandPool, m_queueGraphics, cubeVertices.data(), cubeVerticesSize); m_bufferVertex = std::make_unique<Buffer>(BufferType::Vertex, m_device, *m_allocator, *m_commandPool, cubeVertices.data(), cubeVerticesSize);
std::vector<uint32_t> cubeIndices = { std::vector<uint32_t> cubeIndices = {
0, 1, 2, 0, 1, 2,
@ -575,16 +567,16 @@ namespace nf::client::render {
}; };
size_t cubeIndicesSize = sizeof(cubeIndices[0]) * cubeIndices.size(); size_t cubeIndicesSize = sizeof(cubeIndices[0]) * cubeIndices.size();
m_bufferIndex = std::make_unique<Buffer>(BufferType::Index, m_device, *m_allocator, m_commandPool, m_queueGraphics, cubeIndices.data(), cubeIndicesSize); m_bufferIndex = std::make_unique<Buffer>(BufferType::Index, m_device, *m_allocator, *m_commandPool, cubeIndices.data(), cubeIndicesSize);
size_t mvpUniformBufferSize = sizeof(glm::mat4); size_t mvpUniformBufferSize = sizeof(glm::mat4);
m_bufferUniformMVP = std::make_unique<Buffer>(BufferType::Uniform, m_device, *m_allocator, nullptr, nullptr, nullptr, mvpUniformBufferSize); m_bufferUniformMVP = std::make_unique<Buffer>(BufferType::Uniform, m_device, *m_allocator, *m_commandPool, nullptr, mvpUniformBufferSize);
} }
void RenderEngine::createImage() { void RenderEngine::createImage() {
std::string imageData; std::string imageData;
util::readFile("grayson.jpg", imageData); util::readFile("grayson.jpg", imageData);
m_imageTest = std::make_unique<Image>(ImageType::Texture, m_device, *m_allocator, m_commandPool, m_queueGraphics, imageData); m_imageTest = std::make_unique<Image>(ImageType::Texture, m_device, *m_allocator, *m_commandPool, imageData);
VkSamplerCreateInfo samplerCI = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; VkSamplerCreateInfo samplerCI = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
samplerCI.magFilter = samplerCI.minFilter = VK_FILTER_LINEAR; samplerCI.magFilter = samplerCI.minFilter = VK_FILTER_LINEAR;
@ -771,17 +763,19 @@ namespace nf::client::render {
m_bufferIndex.reset(); m_bufferIndex.reset();
m_bufferVertex.reset(); m_bufferVertex.reset();
vkDestroyFence(m_device, m_fenceFrameInFlight, nullptr);
vkDestroySemaphore(m_device, m_semaphoreRenderingDone, nullptr);
vkDestroySemaphore(m_device, m_semaphoreImageAvailable, nullptr);
destroySwapchain();
vkDestroyCommandPool(m_device, m_commandPool, nullptr);
vkDestroyPipeline(m_device, m_pipelineOutput, nullptr); vkDestroyPipeline(m_device, m_pipelineOutput, nullptr);
vkDestroyDescriptorPool(m_device, m_pipelineOutputDescriptorPool, nullptr); vkDestroyDescriptorPool(m_device, m_pipelineOutputDescriptorPool, nullptr);
vkDestroyPipelineLayout(m_device, m_pipelineOutputLayout, nullptr); vkDestroyPipelineLayout(m_device, m_pipelineOutputLayout, nullptr);
vkDestroyDescriptorSetLayout(m_device, m_pipelineOutputDescriptorSetLayout, nullptr); vkDestroyDescriptorSetLayout(m_device, m_pipelineOutputDescriptorSetLayout, nullptr);
vkDestroyRenderPass(m_device, m_renderPassOutput, nullptr); vkDestroyRenderPass(m_device, m_renderPassOutput, nullptr);
destroySwapchain();
vkDestroyFence(m_device, m_fenceFrameInFlight, nullptr);
vkDestroySemaphore(m_device, m_semaphoreRenderingDone, nullptr);
vkDestroySemaphore(m_device, m_semaphoreImageAvailable, nullptr);
m_commandPool.reset();
vkDestroyDevice(m_device, nullptr); vkDestroyDevice(m_device, nullptr);
vkDestroySurfaceKHR(m_instance, m_surface, nullptr); vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
vkDestroyInstance(m_instance, nullptr); vkDestroyInstance(m_instance, nullptr);

View File

@ -3,6 +3,7 @@
#include "client/Window.h" #include "client/Window.h"
#include "nf/config.h" #include "nf/config.h"
#include "CommandPool.h"
#include "VideoMemoryAllocator.h" #include "VideoMemoryAllocator.h"
#include "Buffer.h" #include "Buffer.h"
#include "Image.h" #include "Image.h"
@ -21,11 +22,12 @@ namespace nf::client::render {
void createSurface(); void createSurface();
void pickPhysicalDevice(); void pickPhysicalDevice();
void createDevice(); void createDevice();
void createExecutionObjects();
void createSwapchain(); void createSwapchain();
void createOutputRenderPass(); void createOutputRenderPass();
void createOutputPipeline(); void createOutputPipeline();
void createExecutionObjects();
void createSwapchainFramebuffers(); void createSwapchainFramebuffers();
void createBuffers(); void createBuffers();
@ -48,7 +50,12 @@ namespace nf::client::render {
VkDevice m_device; VkDevice m_device;
VkQueue m_queueGraphics, m_queuePresent; VkQueue m_queueGraphics, m_queuePresent;
VkRenderPass m_renderPassOutput; // Execution objects
std::unique_ptr<CommandPool> m_commandPool;
VkCommandBuffer m_commandBuffer;
VkSemaphore m_semaphoreImageAvailable;
VkSemaphore m_semaphoreRenderingDone;
VkFence m_fenceFrameInFlight;
// Swapchain // Swapchain
VkSwapchainKHR m_swapchain; VkSwapchainKHR m_swapchain;
@ -57,19 +64,13 @@ namespace nf::client::render {
std::vector<VkImage> m_swapchainImages; std::vector<VkImage> m_swapchainImages;
std::vector<VkImageView> m_swapchainImageViews; std::vector<VkImageView> m_swapchainImageViews;
// Pipelines // RenderPass and Pipeline
VkRenderPass m_renderPassOutput;
VkDescriptorSetLayout m_pipelineOutputDescriptorSetLayout; VkDescriptorSetLayout m_pipelineOutputDescriptorSetLayout;
VkPipelineLayout m_pipelineOutputLayout; VkPipelineLayout m_pipelineOutputLayout;
VkDescriptorPool m_pipelineOutputDescriptorPool; VkDescriptorPool m_pipelineOutputDescriptorPool;
VkPipeline m_pipelineOutput; VkPipeline m_pipelineOutput;
// Execution objects
VkCommandPool m_commandPool;
VkCommandBuffer m_commandBuffer;
VkSemaphore m_semaphoreImageAvailable;
VkSemaphore m_semaphoreRenderingDone;
VkFence m_fenceFrameInFlight;
// Temporary objects // Temporary objects
std::unique_ptr<VideoMemoryAllocator> m_allocator; std::unique_ptr<VideoMemoryAllocator> m_allocator;
std::unique_ptr<Image> m_imageDepth; std::unique_ptr<Image> m_imageDepth;