From 5d9660c1ebcb54d8f4ddaf09566f6535016c8dfe Mon Sep 17 00:00:00 2001 From: PancakeTAS Date: Mon, 1 Sep 2025 18:04:11 +0200 Subject: [PATCH] refactor: implement new, more basic barrier system --- framegen/.old/include/utils.hpp | 45 ------------- framegen/.old/src/{common => }/utils.cpp | 51 --------------- framegen/include/vk/core/buffer.hpp | 1 - framegen/include/vk/core/commandbuffer.hpp | 25 +++++++- framegen/include/vk/core/image.hpp | 2 +- framegen/src/vk/core/commandbuffer.cpp | 74 ++++++++++++++++++++++ framegen/src/vk/core/descriptorset.cpp | 9 ++- 7 files changed, 103 insertions(+), 104 deletions(-) rename framegen/.old/src/{common => }/utils.cpp (71%) diff --git a/framegen/.old/include/utils.hpp b/framegen/.old/include/utils.hpp index 82e7039..99a6f2d 100644 --- a/framegen/.old/include/utils.hpp +++ b/framegen/.old/include/utils.hpp @@ -19,51 +19,6 @@ namespace LSFG::Utils { - /// - /// Insert memory barriers for images in a command buffer. - /// - /// @throws std::logic_error if the command buffer is not in Recording state - /// - class BarrierBuilder { - public: - /// Create a barrier builder. - BarrierBuilder(const Core::CommandBuffer& buffer) - : commandBuffer(&buffer) { - this->barriers.reserve(16); // this is performance critical - } - - // Add a resource to the barrier builder. - BarrierBuilder& addR2W(Core::Image& image); - BarrierBuilder& addW2R(Core::Image& image); - - // Add an optional resource to the barrier builder. - BarrierBuilder& addR2W(std::optional& image) { - if (image.has_value()) this->addR2W(*image); return *this; } - BarrierBuilder& addW2R(std::optional& image) { - if (image.has_value()) this->addW2R(*image); return *this; } - - /// Add a list of resources to the barrier builder. - BarrierBuilder& addR2W(std::vector& images) { - for (auto& image : images) this->addR2W(image); return *this; } - BarrierBuilder& addW2R(std::vector& images) { - for (auto& image : images) this->addW2R(image); return *this; } - - /// Add an array of resources to the barrier builder. - template - BarrierBuilder& addR2W(std::array& images) { - for (auto& image : images) this->addR2W(image); return *this; } - template - BarrierBuilder& addW2R(std::array& images) { - for (auto& image : images) this->addW2R(image); return *this; } - - /// Finish building the barrier - void build() const; - private: - const Core::CommandBuffer* commandBuffer; - - std::vector barriers; - }; - /// /// Upload a DDS file to a Vulkan image. /// diff --git a/framegen/.old/src/common/utils.cpp b/framegen/.old/src/utils.cpp similarity index 71% rename from framegen/.old/src/common/utils.cpp rename to framegen/.old/src/utils.cpp index 20346c5..f210a5a 100644 --- a/framegen/.old/src/common/utils.cpp +++ b/framegen/.old/src/utils.cpp @@ -21,57 +21,6 @@ using namespace LSFG; using namespace LSFG::Utils; -BarrierBuilder& BarrierBuilder::addR2W(Core::Image& image) { - this->barriers.emplace_back(VkImageMemoryBarrier2 { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, - .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, - .srcAccessMask = VK_ACCESS_2_SHADER_READ_BIT, - .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, - .dstAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT, - .oldLayout = image.getLayout(), - .newLayout = VK_IMAGE_LAYOUT_GENERAL, - .image = image.handle(), - .subresourceRange = { - .aspectMask = image.getAspectFlags(), - .levelCount = 1, - .layerCount = 1 - } - }); - image.setLayout(VK_IMAGE_LAYOUT_GENERAL); - - return *this; -} - -BarrierBuilder& BarrierBuilder::addW2R(Core::Image& image) { - this->barriers.emplace_back(VkImageMemoryBarrier2 { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, - .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, - .srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT, - .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, - .dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT, - .oldLayout = image.getLayout(), - .newLayout = VK_IMAGE_LAYOUT_GENERAL, - .image = image.handle(), - .subresourceRange = { - .aspectMask = image.getAspectFlags(), - .levelCount = 1, - .layerCount = 1 - } - }); - image.setLayout(VK_IMAGE_LAYOUT_GENERAL); - - return *this; -} - -void BarrierBuilder::build() const { - const VkDependencyInfo dependencyInfo = { - .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, - .imageMemoryBarrierCount = static_cast(this->barriers.size()), - .pImageMemoryBarriers = this->barriers.data() - }; - vkCmdPipelineBarrier2(this->commandBuffer->handle(), &dependencyInfo); -} - void Utils::uploadImage(const Core::Device& device, const Core::CommandPool& commandPool, Core::Image& image, const std::string& path) { // read image bytecode diff --git a/framegen/include/vk/core/buffer.hpp b/framegen/include/vk/core/buffer.hpp index 3ef2df7..84500e4 100644 --- a/framegen/include/vk/core/buffer.hpp +++ b/framegen/include/vk/core/buffer.hpp @@ -50,7 +50,6 @@ namespace VK::Core { /// Get the size of the buffer. [[nodiscard]] auto getSize() const { return this->size; } private: - std::shared_ptr buffer; std::shared_ptr memory; diff --git a/framegen/include/vk/core/commandbuffer.hpp b/framegen/include/vk/core/commandbuffer.hpp index 4c81a9f..f1a0f1e 100644 --- a/framegen/include/vk/core/commandbuffer.hpp +++ b/framegen/include/vk/core/commandbuffer.hpp @@ -1,7 +1,7 @@ #pragma once -#include "vk/core/commandpool.hpp" #include "vk/core/descriptorset.hpp" +#include "vk/core/commandpool.hpp" #include "vk/core/semaphore.hpp" #include "vk/core/pipeline.hpp" #include "vk/core/device.hpp" @@ -76,8 +76,27 @@ namespace VK::Core { /// void bindDescriptorSet(const Pipeline& pipeline, const DescriptorSet& set) const; - // TODO: Method for inserting a pipeline barrier. - // TODO: Rework abstraction for barriers. + /// + /// Insert memory barriers transitioning images into the general layout. + /// + /// @param images Images to transition to general layout + /// + /// @throws std::logic_error if the command buffer is not in Recording state + /// + void insertBarrier(const std::vector& images) const; + + /// + /// Insert memory barriers for images in the command buffer. + /// + /// @param readableImages Images that will be transitioned from rw to read-only + /// @param writableImages Images that will be transitioned from read-only to rw + /// + /// @throws std::logic_error if the command buffer is not in Recording state + /// + void insertBarrier( + const std::vector& readableImages, + const std::vector& writableImages) const; + // TODO: Method for copying a buffer to an image // TODO: Method for clearing an image to a color diff --git a/framegen/include/vk/core/image.hpp b/framegen/include/vk/core/image.hpp index 767156a..952ee1c 100644 --- a/framegen/include/vk/core/image.hpp +++ b/framegen/include/vk/core/image.hpp @@ -33,7 +33,7 @@ namespace VK::Core { Image(const Device& device, VkExtent2D extent, VkFormat format = VK_FORMAT_R8G8B8A8_UNORM, VkImageUsageFlags usage = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, - VkImageAspectFlags aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT); + VkImageAspectFlags aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT); // TODO: get rid /// /// Create the image with shared backing memory. diff --git a/framegen/src/vk/core/commandbuffer.cpp b/framegen/src/vk/core/commandbuffer.cpp index a6cd7d0..fd55a16 100644 --- a/framegen/src/vk/core/commandbuffer.cpp +++ b/framegen/src/vk/core/commandbuffer.cpp @@ -2,6 +2,7 @@ #include #include "vk/core/commandbuffer.hpp" +#include "vk/core/descriptorset.hpp" #include "vk/core/commandpool.hpp" #include "vk/core/semaphore.hpp" #include "vk/core/pipeline.hpp" @@ -72,6 +73,79 @@ void CommandBuffer::bindDescriptorSet(const Pipeline& pipeline, const Descriptor 0, 1, &descriptorSetHandle, 0, nullptr); } +void CommandBuffer::insertBarrier( + const std::vector& images) const { + if (*this->state != CommandBufferState::Recording) + throw std::logic_error("Command buffer is not in Recording state"); + + std::vector barriers(images.size()); + for (size_t i = 0; i < images.size(); i++) { + barriers[i] = { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = VK_IMAGE_LAYOUT_GENERAL, + .image = images[i], + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .levelCount = 1, + .layerCount = 1 + } + }; + } + + const VkDependencyInfo dependencyInfo = { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .imageMemoryBarrierCount = static_cast(barriers.size()), + .pImageMemoryBarriers = barriers.data() + }; + vkCmdPipelineBarrier2(*this->commandBuffer, &dependencyInfo); +} + +void CommandBuffer::insertBarrier( + const std::vector& readableImages, + const std::vector& writableImages) const { + if (*this->state != CommandBufferState::Recording) + throw std::logic_error("Command buffer is not in Recording state"); + + // create barriers + const VkImageMemoryBarrier2 dummyBarrier{ + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .srcStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + .dstStageMask = VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .levelCount = 1, + .layerCount = 1 + } + }; + + const size_t totalImages = + readableImages.size() + writableImages.size(); + std::vector barriers(totalImages); + + for (const auto& image : readableImages) { + VkImageMemoryBarrier2& barrier = barriers.emplace_back(dummyBarrier); + barrier.srcAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_2_SHADER_READ_BIT; + barrier.image = image; + } + + for (const auto& image : writableImages) { + VkImageMemoryBarrier2& barrier = barriers.emplace_back(dummyBarrier); + barrier.srcAccessMask = VK_ACCESS_2_SHADER_READ_BIT; + barrier.dstAccessMask = VK_ACCESS_2_SHADER_WRITE_BIT; + barrier.image = image; + } + + // insert barriers + const VkDependencyInfo dependencyInfo = { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .imageMemoryBarrierCount = static_cast(barriers.size()), + .pImageMemoryBarriers = barriers.data() + }; + vkCmdPipelineBarrier2(*this->commandBuffer, &dependencyInfo); +} + void CommandBuffer::dispatch(uint32_t x, uint32_t y, uint32_t z) const { if (*this->state != CommandBufferState::Recording) throw std::logic_error("Command buffer is not in Recording state"); diff --git a/framegen/src/vk/core/descriptorset.cpp b/framegen/src/vk/core/descriptorset.cpp index 9dc1cd3..23d682a 100644 --- a/framegen/src/vk/core/descriptorset.cpp +++ b/framegen/src/vk/core/descriptorset.cpp @@ -1,13 +1,16 @@ -#include #include #include -#include "vk/core/descriptorset.hpp" -#include "vk/core/device.hpp" #include "vk/core/descriptorpool.hpp" +#include "vk/core/descriptorset.hpp" +#include "vk/core/shadermodule.hpp" +#include "vk/core/device.hpp" #include "vk/exception.hpp" +#include +#include #include +#include using namespace VK::Core;