rpcsx/rpcs3/Emu/RSX/GL/glutils/ring_buffer.h
2022-07-13 02:09:58 +03:00

114 lines
2.6 KiB
C++

#pragma once
#include "buffer_object.h"
#include "sync.hpp"
#include "Utilities/address_range.h"
namespace gl
{
class ring_buffer : public buffer
{
protected:
u32 m_data_loc = 0;
void* m_memory_mapping = nullptr;
fence m_fence;
public:
virtual void bind() { buffer::bind(); }
virtual void recreate(GLsizeiptr size, const void* data = nullptr);
void create(target target_, GLsizeiptr size, const void* data_ = nullptr);
virtual std::pair<void*, u32> alloc_from_heap(u32 alloc_size, u16 alignment);
virtual void remove();
virtual void reserve_storage_on_heap(u32 /*alloc_size*/) {}
virtual void unmap() {}
virtual void flush() {}
virtual void notify();
};
class legacy_ring_buffer : public ring_buffer
{
u32 m_mapped_bytes = 0;
u32 m_mapping_offset = 0;
u32 m_alignment_offset = 0;
public:
void recreate(GLsizeiptr size, const void* data = nullptr) override;
void create(target target_, GLsizeiptr size, const void* data_ = nullptr);
void reserve_storage_on_heap(u32 alloc_size) override;
std::pair<void*, u32> alloc_from_heap(u32 alloc_size, u16 alignment) override;
void remove() override;
void unmap() override;
void notify() override {}
};
// A non-persistent ring buffer
// Internally maps and unmaps data. Uses persistent storage just like the regular persistent variant
// Works around drivers that have issues using mapped data for specific sources (e.g AMD proprietary driver with index buffers)
class transient_ring_buffer : public ring_buffer
{
bool dirty = false;
void* map_internal(u32 offset, u32 length);
public:
void bind() override;
void recreate(GLsizeiptr size, const void* data = nullptr) override;
std::pair<void*, u32> alloc_from_heap(u32 alloc_size, u16 alignment) override;
void flush() 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);
buffer& get() { return m_storage; }
u64 size() const { return m_storage.size(); }
};
}