mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-16 16:21:02 +00:00
gl: Implement scratch ring buffer with memory barriers
This commit is contained in:
parent
3fd846687e
commit
764fb57fdc
@ -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_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
};
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user