rpcsx/rpcs3/Emu/RSX/GL/glutils/buffer_object.h
DH 62ad27d1e2 split rpcs3 and hle libraries
merge rpcs3 utilities
2025-04-08 19:46:57 +03:00

202 lines
4.5 KiB
C++

#pragma once
#include "Emu/RSX/GL/OpenGL.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,
rw = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
persistent_rw = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT
};
enum class memory_type
{
undefined = 0,
local = 1,
host_visible = 2,
userptr = 4
};
enum usage
{
host_write = (1 << 0),
host_read = (1 << 1),
persistent_map = (1 << 2),
dynamic_update = (1 << 3),
};
class save_binding_state
{
GLint m_last_binding = GL_ZERO;
GLenum m_target = GL_NONE;
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()
{
if (!m_target)
{
return;
}
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;
// Metadata
mutable std::pair<u32, u32> m_bound_range{};
void allocate(GLsizeiptr size, const void* data_, memory_type type, GLuint usage_bits);
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, GLuint usage_bits = 0);
void create(target target_, GLsizeiptr size, const void* data_ = nullptr, memory_type type = memory_type::local, GLuint usage_bits = 0);
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, const 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;
}
std::pair<u32, u32> bound_range() const
{
return m_bound_range;
}
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;
};
} // namespace gl