mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-06 15:01:28 +12:00
142 lines
4 KiB
C++
142 lines
4 KiB
C++
#pragma once
|
|
|
|
#include "common.h"
|
|
|
|
namespace gl
|
|
{
|
|
class buffer
|
|
{
|
|
public:
|
|
enum class target
|
|
{
|
|
pixel_pack = GL_PIXEL_PACK_BUFFER,
|
|
pixel_unpack = GL_PIXEL_UNPACK_BUFFER,
|
|
array = GL_ARRAY_BUFFER,
|
|
element_array = GL_ELEMENT_ARRAY_BUFFER,
|
|
uniform = GL_UNIFORM_BUFFER,
|
|
texture = GL_TEXTURE_BUFFER,
|
|
ssbo = GL_SHADER_STORAGE_BUFFER
|
|
};
|
|
|
|
enum class access
|
|
{
|
|
read = GL_MAP_READ_BIT,
|
|
write = GL_MAP_WRITE_BIT,
|
|
read_write = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT
|
|
};
|
|
|
|
enum class memory_type
|
|
{
|
|
undefined = 0,
|
|
local = 1,
|
|
host_visible = 2
|
|
};
|
|
|
|
class save_binding_state
|
|
{
|
|
GLint m_last_binding;
|
|
GLenum m_target;
|
|
|
|
public:
|
|
save_binding_state(target target_, const buffer& new_state) : save_binding_state(target_)
|
|
{
|
|
new_state.bind(target_);
|
|
}
|
|
|
|
save_binding_state(target target_)
|
|
{
|
|
GLenum pname{};
|
|
switch (target_)
|
|
{
|
|
case target::pixel_pack: pname = GL_PIXEL_PACK_BUFFER_BINDING; break;
|
|
case target::pixel_unpack: pname = GL_PIXEL_UNPACK_BUFFER_BINDING; break;
|
|
case target::array: pname = GL_ARRAY_BUFFER_BINDING; break;
|
|
case target::element_array: pname = GL_ELEMENT_ARRAY_BUFFER_BINDING; break;
|
|
case target::uniform: pname = GL_UNIFORM_BUFFER_BINDING; break;
|
|
case target::texture: pname = GL_TEXTURE_BUFFER_BINDING; break;
|
|
case target::ssbo: pname = GL_SHADER_STORAGE_BUFFER_BINDING; break;
|
|
default: fmt::throw_exception("Invalid binding state target (0x%x)", static_cast<int>(target_));
|
|
}
|
|
|
|
glGetIntegerv(pname, &m_last_binding);
|
|
m_target = static_cast<GLenum>(target_);
|
|
}
|
|
|
|
~save_binding_state()
|
|
{
|
|
glBindBuffer(m_target, m_last_binding);
|
|
}
|
|
};
|
|
|
|
protected:
|
|
GLuint m_id = GL_NONE;
|
|
GLsizeiptr m_size = 0;
|
|
target m_target = target::array;
|
|
memory_type m_memory_type = memory_type::undefined;
|
|
|
|
void allocate(GLsizeiptr size, const void* data_, memory_type type, GLenum usage);
|
|
|
|
public:
|
|
buffer() = default;
|
|
buffer(const buffer&) = delete;
|
|
~buffer();
|
|
|
|
void recreate();
|
|
void recreate(GLsizeiptr size, const void* data = nullptr);
|
|
|
|
void create();
|
|
void create(GLsizeiptr size, const void* data_ = nullptr, memory_type type = memory_type::local, GLenum usage = GL_STREAM_DRAW);
|
|
void create(target target_, GLsizeiptr size, const void* data_ = nullptr, memory_type type = memory_type::local, GLenum usage = GL_STREAM_DRAW);
|
|
|
|
void remove();
|
|
|
|
void bind(target target_) const { glBindBuffer(static_cast<GLenum>(target_), m_id); }
|
|
void bind() const { bind(current_target()); }
|
|
|
|
void data(GLsizeiptr size, const void* data_ = nullptr, GLenum usage = GL_STREAM_DRAW);
|
|
void sub_data(GLsizeiptr offset, GLsizeiptr length, GLvoid* data);
|
|
|
|
GLubyte* map(GLsizeiptr offset, GLsizeiptr length, access access_);
|
|
void unmap();
|
|
|
|
void bind_range(u32 index, u32 offset, u32 size) const;
|
|
void bind_range(target target_, u32 index, u32 offset, u32 size) const;
|
|
|
|
void copy_to(buffer* other, u64 src_offset, u64 dst_offset, u64 size);
|
|
|
|
target current_target() const { return m_target; }
|
|
GLsizeiptr size() const { return m_size; }
|
|
uint id() const { return m_id; }
|
|
void set_id(uint id) { m_id = id; }
|
|
bool created() const { return m_id != GL_NONE; }
|
|
|
|
explicit operator bool() const { return created(); }
|
|
};
|
|
|
|
class buffer_view
|
|
{
|
|
buffer* m_buffer = nullptr;
|
|
u32 m_offset = 0;
|
|
u32 m_range = 0;
|
|
GLenum m_format = GL_R8UI;
|
|
|
|
public:
|
|
buffer_view(buffer* _buffer, u32 offset, u32 range, GLenum format = GL_R8UI)
|
|
: m_buffer(_buffer), m_offset(offset), m_range(range), m_format(format)
|
|
{}
|
|
|
|
buffer_view() = default;
|
|
|
|
void update(buffer* _buffer, u32 offset, u32 range, GLenum format = GL_R8UI);
|
|
|
|
u32 offset() const { return m_offset; }
|
|
|
|
u32 range() const { return m_range; }
|
|
|
|
u32 format() const { return m_format; }
|
|
|
|
buffer* value() const { return m_buffer; }
|
|
|
|
bool in_range(u32 address, u32 size, u32& new_offset) const;
|
|
};
|
|
}
|