gl: Implement scratch ring buffer with memory barriers

This commit is contained in:
kd-11 2022-06-02 21:28:24 +03:00 committed by kd-11
parent 3fd846687e
commit 764fb57fdc
2 changed files with 98 additions and 0 deletions

View File

@ -238,4 +238,73 @@ namespace gl
{ {
flush(); flush();
} }
scratch_ring_buffer::~scratch_ring_buffer()
{
if (m_storage)
{
remove();
}
}
void scratch_ring_buffer::create(buffer::target target_, u64 size)
{
if (m_storage)
{
remove();
}
m_storage.create(target_, size, nullptr, gl::buffer::memory_type::local, GL_STATIC_COPY);
}
void scratch_ring_buffer::remove()
{
if (m_storage)
{
m_storage.remove();
}
m_barriers.clear();
m_alloc_pointer = 0;
}
u32 scratch_ring_buffer::alloc(u32 size, u32 alignment)
{
u64 start = utils::align(m_alloc_pointer, alignment);
m_alloc_pointer = (start + size);
if (m_alloc_pointer > m_storage.size())
{
start = 0;
m_alloc_pointer = size;
}
pop_barrier(start, size);
return start;
}
void scratch_ring_buffer::pop_barrier(u32 start, u32 length)
{
const auto range = utils::address_range::start_length(start, length);
m_barriers.erase(std::remove_if(m_barriers.begin(), m_barriers.end(), [&range](auto& barrier_)
{
if (barrier_.range.overlaps(range))
{
barrier_.signal.wait_for_signal();
}
}), m_barriers.end());
}
void scratch_ring_buffer::push_barrier(u32 start, u32 length)
{
if (!length)
{
return;
}
barrier barrier_;
barrier_.range = utils::address_range::start_length(start, length);
barrier_.signal.create();
m_barriers.emplace_back(barrier_);
}
} }

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "buffer_object.h" #include "buffer_object.h"
#include "Utilities/address_range.h"
namespace gl namespace gl
{ {
@ -78,4 +79,32 @@ namespace gl
void unmap() override; void unmap() override;
}; };
// Simple GPU-side ring buffer with no map/unmap semantics
class scratch_ring_buffer
{
struct barrier
{
fence signal;
utils::address_range range;
};
buffer m_storage;
std::vector<barrier> m_barriers;
u64 m_alloc_pointer = 0;
void pop_barrier(u32 start, u32 length);
public:
scratch_ring_buffer() = default;
scratch_ring_buffer(const scratch_ring_buffer&) = delete;
~scratch_ring_buffer();
void create(buffer::target _target, u64 size);
void remove();
u32 alloc(u32 size, u32 alignment);
void push_barrier(u32 start, u32 length);
};
} }