mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2025-10-30 07:01:10 +00:00
refactor: implement new, more basic barrier system
This commit is contained in:
parent
c3cccb4967
commit
5d9660c1eb
7 changed files with 103 additions and 104 deletions
|
|
@ -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<Core::Image>& image) {
|
||||
if (image.has_value()) this->addR2W(*image); return *this; }
|
||||
BarrierBuilder& addW2R(std::optional<Core::Image>& image) {
|
||||
if (image.has_value()) this->addW2R(*image); return *this; }
|
||||
|
||||
/// Add a list of resources to the barrier builder.
|
||||
BarrierBuilder& addR2W(std::vector<Core::Image>& images) {
|
||||
for (auto& image : images) this->addR2W(image); return *this; }
|
||||
BarrierBuilder& addW2R(std::vector<Core::Image>& images) {
|
||||
for (auto& image : images) this->addW2R(image); return *this; }
|
||||
|
||||
/// Add an array of resources to the barrier builder.
|
||||
template<std::size_t N>
|
||||
BarrierBuilder& addR2W(std::array<Core::Image, N>& images) {
|
||||
for (auto& image : images) this->addR2W(image); return *this; }
|
||||
template<std::size_t N>
|
||||
BarrierBuilder& addW2R(std::array<Core::Image, N>& images) {
|
||||
for (auto& image : images) this->addW2R(image); return *this; }
|
||||
|
||||
/// Finish building the barrier
|
||||
void build() const;
|
||||
private:
|
||||
const Core::CommandBuffer* commandBuffer;
|
||||
|
||||
std::vector<VkImageMemoryBarrier2> barriers;
|
||||
};
|
||||
|
||||
///
|
||||
/// Upload a DDS file to a Vulkan image.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -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<uint32_t>(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
|
||||
|
|
@ -50,7 +50,6 @@ namespace VK::Core {
|
|||
/// Get the size of the buffer.
|
||||
[[nodiscard]] auto getSize() const { return this->size; }
|
||||
private:
|
||||
|
||||
std::shared_ptr<VkBuffer> buffer;
|
||||
std::shared_ptr<VkDeviceMemory> memory;
|
||||
|
||||
|
|
|
|||
|
|
@ -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<VkImage>& 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<VkImage>& readableImages,
|
||||
const std::vector<VkImage>& writableImages) const;
|
||||
|
||||
// TODO: Method for copying a buffer to an image
|
||||
// TODO: Method for clearing an image to a color
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#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<VkImage>& images) const {
|
||||
if (*this->state != CommandBufferState::Recording)
|
||||
throw std::logic_error("Command buffer is not in Recording state");
|
||||
|
||||
std::vector<VkImageMemoryBarrier2> 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<uint32_t>(barriers.size()),
|
||||
.pImageMemoryBarriers = barriers.data()
|
||||
};
|
||||
vkCmdPipelineBarrier2(*this->commandBuffer, &dependencyInfo);
|
||||
}
|
||||
|
||||
void CommandBuffer::insertBarrier(
|
||||
const std::vector<VkImage>& readableImages,
|
||||
const std::vector<VkImage>& 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<VkImageMemoryBarrier2> 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<uint32_t>(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");
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
#include <cstddef>
|
||||
#include <volk.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#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 <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
using namespace VK::Core;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue