From 764fb57fdcd9c6382b152e1f5dbfbaf88e0547ad Mon Sep 17 00:00:00 2001 From: kd-11 Date: Thu, 2 Jun 2022 21:28:24 +0300 Subject: [PATCH] gl: Implement scratch ring buffer with memory barriers --- rpcs3/Emu/RSX/GL/glutils/ring_buffer.cpp | 69 ++++++++++++++++++++++++ rpcs3/Emu/RSX/GL/glutils/ring_buffer.h | 29 ++++++++++ 2 files changed, 98 insertions(+) diff --git a/rpcs3/Emu/RSX/GL/glutils/ring_buffer.cpp b/rpcs3/Emu/RSX/GL/glutils/ring_buffer.cpp index 1c416d05ac..7feb8be196 100644 --- a/rpcs3/Emu/RSX/GL/glutils/ring_buffer.cpp +++ b/rpcs3/Emu/RSX/GL/glutils/ring_buffer.cpp @@ -238,4 +238,73 @@ namespace gl { 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_); + } } diff --git a/rpcs3/Emu/RSX/GL/glutils/ring_buffer.h b/rpcs3/Emu/RSX/GL/glutils/ring_buffer.h index 5016dffe70..9ec47247a7 100644 --- a/rpcs3/Emu/RSX/GL/glutils/ring_buffer.h +++ b/rpcs3/Emu/RSX/GL/glutils/ring_buffer.h @@ -1,6 +1,7 @@ #pragma once #include "buffer_object.h" +#include "Utilities/address_range.h" namespace gl { @@ -78,4 +79,32 @@ namespace gl 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 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); + }; } \ No newline at end of file