Skip to content

Commit

Permalink
gh-78: new barriers management api
Browse files Browse the repository at this point in the history
- add new barriers
- remove implicit barriers from vk
- add batched barriers support
  • Loading branch information
EgorOrachyov committed Jul 22, 2024
1 parent 2539a1e commit 5d857d4
Show file tree
Hide file tree
Showing 13 changed files with 320 additions and 289 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
paths:
- '.github/**'
- 'deps/**'
- 'engine/code/**'
- 'engine/runtime/**'
- 'engine/plugins/**'
- 'games/**'
- 'template/**'
Expand Down
24 changes: 15 additions & 9 deletions engine/runtime/gfx/gfx_cmd_list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ namespace wmoge {
public:
~GfxCmdList() override = default;

virtual void update_vert_buffer(const Ref<GfxVertBuffer>& buffer, int offset, int range, const Ref<Data>& data) = 0;
virtual void update_index_buffer(const Ref<GfxIndexBuffer>& buffer, int offset, int range, const Ref<Data>& data) = 0;
virtual void update_uniform_buffer(const Ref<GfxUniformBuffer>& buffer, int offset, int range, const Ref<Data>& data) = 0;
virtual void update_storage_buffer(const Ref<GfxStorageBuffer>& buffer, int offset, int range, const Ref<Data>& data) = 0;
virtual void update_texture_2d(const Ref<GfxTexture>& texture, int mip, Rect2i region, const Ref<Data>& data) = 0;
virtual void update_texture_2d_array(const Ref<GfxTexture>& texture, int mip, int slice, Rect2i region, const Ref<Data>& data) = 0;
virtual void update_texture_cube(const Ref<GfxTexture>& texture, int mip, int face, Rect2i region, const Ref<Data>& data) = 0;
virtual void update_vert_buffer(const Ref<GfxVertBuffer>& buffer, int offset, int range, array_view<const std::uint8_t> data) = 0;
virtual void update_index_buffer(const Ref<GfxIndexBuffer>& buffer, int offset, int range, array_view<const std::uint8_t> data) = 0;
virtual void update_uniform_buffer(const Ref<GfxUniformBuffer>& buffer, int offset, int range, array_view<const std::uint8_t> data) = 0;
virtual void update_storage_buffer(const Ref<GfxStorageBuffer>& buffer, int offset, int range, array_view<const std::uint8_t> data) = 0;
virtual void update_texture_2d(const Ref<GfxTexture>& texture, int mip, Rect2i region, array_view<const std::uint8_t> data) = 0;
virtual void update_texture_2d_array(const Ref<GfxTexture>& texture, int mip, int slice, Rect2i region, array_view<const std::uint8_t> dataa) = 0;
virtual void update_texture_cube(const Ref<GfxTexture>& texture, int mip, int face, Rect2i region, array_view<const std::uint8_t> data) = 0;

virtual void* map_vert_buffer(const Ref<GfxVertBuffer>& buffer) = 0;
virtual void* map_index_buffer(const Ref<GfxIndexBuffer>& buffer) = 0;
Expand All @@ -72,8 +72,14 @@ namespace wmoge {
virtual void unmap_uniform_buffer(const Ref<GfxUniformBuffer>& buffer) = 0;
virtual void unmap_storage_buffer(const Ref<GfxStorageBuffer>& buffer) = 0;

virtual void barrier_image(const Ref<GfxTexture>& texture, GfxTexBarrierType barrier_type) = 0;
virtual void barrier_buffer(const Ref<GfxStorageBuffer>& buffer) = 0;
virtual void barrier_image(const Ref<GfxTexture>& texture, GfxTexBarrierType src, GfxTexBarrierType dst) = 0;
virtual void barrier_buffer(const Ref<GfxVertBuffer>& buffer) = 0;
virtual void barrier_buffer(const Ref<GfxIndexBuffer>& buffer) = 0;
virtual void barrier_buffer(const Ref<GfxUniformBuffer>& buffer) = 0;
virtual void barrier_buffer(const Ref<GfxStorageBuffer>& buffer) = 0;

virtual void barrier_images(array_view<GfxTexture*> textures, GfxTexBarrierType src, GfxTexBarrierType dst) = 0;
virtual void barrier_buffers(array_view<GfxBuffer*> buffers) = 0;

virtual void begin_render_pass(const GfxRenderPassBeginInfo& pass_desc) = 0;
virtual void peek_render_pass(GfxRenderPassRef& rp) = 0;
Expand Down
13 changes: 9 additions & 4 deletions engine/runtime/gfx/gfx_defs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ namespace wmoge {
static constexpr int NUM_TYPES = int(GfxType::Max);
/** Max num of shader platfroms */
static constexpr int NUM_PLATFORMS = int(GfxShaderPlatform::Max);
/** Barriers standard batch size */
static constexpr int NUM_INLINE_BARRIERS = 64;
};

/** @brief Type of gfx queues for submission */
Expand Down Expand Up @@ -155,10 +157,13 @@ namespace wmoge {

/** @brief Texture manual barrier type */
enum class GfxTexBarrierType : int {
RenderTarget,// For drawing into texture
Sampling, // For sampling from shader in read-only mode
Storage, // For read-write in compute shader
Presentation // For presentation to the screen
RenderTarget, // For drawing into texture
Sampling, // For sampling from shader in read-only mode
Storage, // For read-write in compute shader
CopySource, // For copy, as source of data
CopyDestination,// For copy, as destination
Presentation, // For presentation to the screen
Undefined, // For initial transition
};

/** @brief Texture type */
Expand Down
87 changes: 7 additions & 80 deletions engine/runtime/gfx/vulkan/vk_buffers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include "vk_buffers.hpp"

#include "gfx/vulkan/vk_cmd_list.hpp"
#include "gfx/vulkan/vk_driver.hpp"

namespace wmoge {
Expand Down Expand Up @@ -65,7 +66,7 @@ namespace wmoge {
mem_man->staging_allocate(m_size, m_staging_buffer, m_staging_allocation);
return mem_man->staging_map(m_staging_allocation);
}
void VKBuffer::unmap(VkCommandBuffer cmd) {
void VKBuffer::unmap(VKCmdList* cmd) {
assert(m_staging_buffer != VK_NULL_HANDLE);

auto mem_man = driver().mem_manager();
Expand All @@ -77,15 +78,15 @@ namespace wmoge {
copy_region.dstOffset = 0;
copy_region.size = m_size;

vkCmdCopyBuffer(cmd, m_staging_buffer, m_buffer, 1, &copy_region);
vkCmdCopyBuffer(cmd->get_handle(), m_staging_buffer, m_buffer, 1, &copy_region);
cmd->barrier(this);

m_staging_buffer = VK_NULL_HANDLE;
m_staging_allocation = VK_NULL_HANDLE;
}
void VKBuffer::update(VkCommandBuffer cmd, VkDeviceSize offset, VkDeviceSize size, const Ref<Data>& mem) {
assert(mem);
void VKBuffer::update(VkCommandBuffer cmd, VkDeviceSize offset, VkDeviceSize size, array_view<const std::uint8_t> data) {
assert(size > 0);
assert(size <= mem->size());
assert(size <= data.size());
assert(offset + size <= m_size);

auto mem_man = driver().mem_manager();
Expand All @@ -96,7 +97,7 @@ namespace wmoge {
// allocate staging buffer of required size, map it and update
mem_man->staging_allocate(size, staging_buffer, staging_allocation);
void* mapped = mem_man->staging_map(staging_allocation);
std::memcpy(mapped, mem->buffer(), size);
std::memcpy(mapped, data.data(), size);
mem_man->staging_unmap(staging_allocation);

// copy staging buffer into our buffer (remember about offset)
Expand All @@ -107,20 +108,6 @@ namespace wmoge {

vkCmdCopyBuffer(cmd, staging_buffer, m_buffer, 1, &copy_region);
}
void VKBuffer::barrier(VkCommandBuffer cmd, VkDeviceSize offset, VkDeviceSize size, VkAccessFlags dst_access, VkPipelineStageFlags dst_pipeline_stage) {
VkBufferMemoryBarrier barrier{};
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = dst_access;
barrier.buffer = m_buffer;
barrier.offset = offset;
barrier.size = size;

vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_pipeline_stage, 0,
0, nullptr, 1, &barrier, 0, nullptr);
}

VKVertBuffer::VKVertBuffer(VKDriver& driver) : VKResource<GfxVertBuffer>(driver) {
}
Expand All @@ -134,14 +121,6 @@ namespace wmoge {
VKBuffer::init(size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, usage);
WG_VK_NAME(m_driver.device(), m_buffer, VK_OBJECT_TYPE_BUFFER, name);
}
void VKVertBuffer::unmap(VkCommandBuffer cmd) {
VKBuffer::unmap(cmd);
VKBuffer::barrier(cmd, 0, VKBuffer::m_size, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT);
}
void VKVertBuffer::update(VkCommandBuffer cmd, VkDeviceSize offset, VkDeviceSize size, const Ref<Data>& mem) {
VKBuffer::update(cmd, offset, size, mem);
VKBuffer::barrier(cmd, offset, size, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT);
}

VKIndexBuffer::VKIndexBuffer(VKDriver& driver) : VKResource<GfxIndexBuffer>(driver) {
}
Expand All @@ -155,14 +134,6 @@ namespace wmoge {
VKBuffer::init(size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, usage);
WG_VK_NAME(m_driver.device(), m_buffer, VK_OBJECT_TYPE_BUFFER, name);
}
void VKIndexBuffer::unmap(VkCommandBuffer cmd) {
VKBuffer::unmap(cmd);
VKBuffer::barrier(cmd, 0, VKBuffer::m_size, VK_ACCESS_INDEX_READ_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT);
}
void VKIndexBuffer::update(VkCommandBuffer cmd, VkDeviceSize offset, VkDeviceSize size, const Ref<Data>& mem) {
VKBuffer::update(cmd, offset, size, mem);
VKBuffer::barrier(cmd, offset, size, VK_ACCESS_INDEX_READ_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT);
}

VKUniformBuffer::VKUniformBuffer(VKDriver& driver) : VKResource<GfxUniformBuffer>(driver) {
}
Expand All @@ -176,14 +147,6 @@ namespace wmoge {
VKBuffer::init(size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, usage);
WG_VK_NAME(m_driver.device(), m_buffer, VK_OBJECT_TYPE_BUFFER, name);
}
void VKUniformBuffer::unmap(VkCommandBuffer cmd) {
VKBuffer::unmap(cmd);
VKBuffer::barrier(cmd, 0, VKBuffer::m_size, VK_ACCESS_UNIFORM_READ_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT);
}
void VKUniformBuffer::update(VkCommandBuffer cmd, VkDeviceSize offset, VkDeviceSize size, const Ref<Data>& mem) {
VKBuffer::update(cmd, offset, size, mem);
VKBuffer::barrier(cmd, offset, size, VK_ACCESS_UNIFORM_READ_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT);
}

VKStorageBuffer::VKStorageBuffer(VKDriver& driver) : VKResource<GfxStorageBuffer>(driver) {
}
Expand All @@ -197,41 +160,5 @@ namespace wmoge {
VKBuffer::init(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, usage);
WG_VK_NAME(m_driver.device(), m_buffer, VK_OBJECT_TYPE_BUFFER, name);
}
void VKStorageBuffer::unmap(VkCommandBuffer cmd) {
VKBuffer::unmap(cmd);
VKBuffer::barrier(cmd, 0, VKBuffer::m_size, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT);
}
void VKStorageBuffer::update(VkCommandBuffer cmd, VkDeviceSize offset, VkDeviceSize size, const Ref<Data>& mem) {
VKBuffer::update(cmd, offset, size, mem);
VKBuffer::barrier(cmd, offset, size, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
}

void VKStorageBuffer::barrier(VkCommandBuffer cmd) {
const VkAccessFlags flags =
VK_ACCESS_SHADER_READ_BIT |
VK_ACCESS_SHADER_WRITE_BIT |
VK_ACCESS_TRANSFER_READ_BIT |
VK_ACCESS_TRANSFER_WRITE_BIT;

const VkPipelineStageFlags stages =
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
VK_PIPELINE_STAGE_TRANSFER_BIT;

VkBufferMemoryBarrier barrier{};
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.srcAccessMask = flags;
barrier.dstAccessMask = flags;
barrier.buffer = m_buffer;
barrier.offset = 0;
barrier.size = VKBuffer::m_size;

vkCmdPipelineBarrier(cmd, stages, stages, 0,
0, nullptr, 1, &barrier, 0, nullptr);
}

}// namespace wmoge
18 changes: 5 additions & 13 deletions engine/runtime/gfx/vulkan/vk_buffers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#pragma once

#include "core/array_view.hpp"
#include "core/data.hpp"
#include "gfx/gfx_buffers.hpp"
#include "gfx/vulkan/vk_defs.hpp"
Expand All @@ -40,20 +41,20 @@ namespace wmoge {
*/
class VKBuffer {
public:
virtual ~VKBuffer() = default;

void init(VkDeviceSize size, VkBufferUsageFlags flags, GfxMemUsage usage);
void release();
void* map();
virtual void unmap(VkCommandBuffer cmd);
virtual void update(VkCommandBuffer cmd, VkDeviceSize offset, VkDeviceSize size, const Ref<Data>& mem);
void unmap(class VKCmdList* cmd);
void update(VkCommandBuffer cmd, VkDeviceSize offset, VkDeviceSize size, array_view<const std::uint8_t> data);
virtual class VKDriver& driver() = 0;

VkDeviceSize size() const { return m_size; }
VkBuffer buffer() const { return m_buffer; }
VmaAllocation allocation() const { return m_allocation; }

protected:
void barrier(VkCommandBuffer cmd, VkDeviceSize offset, VkDeviceSize size, VkAccessFlags dst_access, VkPipelineStageFlags dst_pipeline_stage);

VkDeviceSize m_size = 0;
VkBuffer m_buffer = VK_NULL_HANDLE;
VmaAllocation m_allocation = VK_NULL_HANDLE;
Expand All @@ -71,8 +72,6 @@ namespace wmoge {
~VKVertBuffer() override;

void create(int size, GfxMemUsage usage, const Strid& name);
void unmap(VkCommandBuffer cmd) override;
void update(VkCommandBuffer cmd, VkDeviceSize offset, VkDeviceSize size, const Ref<Data>& mem) override;
class VKDriver& driver() override { return m_driver; }
};

Expand All @@ -86,8 +85,6 @@ namespace wmoge {
~VKIndexBuffer() override;

void create(int size, GfxMemUsage usage, const Strid& name);
void unmap(VkCommandBuffer cmd) override;
void update(VkCommandBuffer cmd, VkDeviceSize offset, VkDeviceSize size, const Ref<Data>& mem) override;
class VKDriver& driver() override { return m_driver; }
};

Expand All @@ -101,8 +98,6 @@ namespace wmoge {
~VKUniformBuffer() override;

void create(int size, GfxMemUsage usage, const Strid& name);
void unmap(VkCommandBuffer cmd) override;
void update(VkCommandBuffer cmd, VkDeviceSize offset, VkDeviceSize size, const Ref<Data>& mem) override;
class VKDriver& driver() override { return m_driver; }
};

Expand All @@ -116,9 +111,6 @@ namespace wmoge {
~VKStorageBuffer() override;

void create(int size, GfxMemUsage usage, const Strid& name);
void unmap(VkCommandBuffer cmd) override;
void update(VkCommandBuffer cmd, VkDeviceSize offset, VkDeviceSize size, const Ref<Data>& mem) override;
void barrier(VkCommandBuffer cmd);
class VKDriver& driver() override { return m_driver; }
};

Expand Down
Loading

0 comments on commit 5d857d4

Please sign in to comment.