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

307 lines
6.4 KiB
C++

#pragma once
#include "common.h"
#include "buffer_object.h"
#include "Utilities/geometry.h"
namespace gl
{
class vao;
class buffer_pointer
{
public:
enum class type
{
s8 = GL_BYTE,
u8 = GL_UNSIGNED_BYTE,
s16 = GL_SHORT,
u16 = GL_UNSIGNED_SHORT,
s32 = GL_INT,
u32 = GL_UNSIGNED_INT,
f16 = GL_HALF_FLOAT,
f32 = GL_FLOAT,
f64 = GL_DOUBLE,
fixed = GL_FIXED,
s32_2_10_10_10_rev = GL_INT_2_10_10_10_REV,
u32_2_10_10_10_rev = GL_UNSIGNED_INT_2_10_10_10_REV,
u32_10f_11f_11f_rev = GL_UNSIGNED_INT_10F_11F_11F_REV
};
private:
vao* m_vao;
u32 m_offset;
u32 m_stride;
u32 m_size = 4;
type m_type = type::f32;
bool m_normalize = false;
public:
buffer_pointer(vao* vao, u32 offset = 0, u32 stride = 0)
: m_vao(vao)
, m_offset(offset)
, m_stride(stride)
{
}
const class ::gl::vao& get_vao() const
{
return *m_vao;
}
class ::gl::vao& get_vao()
{
return *m_vao;
}
buffer_pointer& offset(u32 value)
{
m_offset = value;
return *this;
}
u32 offset() const
{
return m_offset;
}
buffer_pointer& stride(u32 value)
{
m_stride = value;
return *this;
}
u32 stride() const
{
return m_stride;
}
buffer_pointer& size(u32 value)
{
m_size = value;
return *this;
}
u32 size() const
{
return m_size;
}
buffer_pointer& set_type(type value)
{
m_type = value;
return *this;
}
type get_type() const
{
return m_type;
}
buffer_pointer& normalize(bool value)
{
m_normalize = value;
return *this;
}
bool normalize() const
{
return m_normalize;
}
buffer_pointer& operator >> (u32 value)
{
return stride(value);
}
buffer_pointer& config(type type_ = type::f32, u32 size_ = 4, bool normalize_ = false)
{
return set_type(type_).size(size_).normalize(normalize_);
}
};
class attrib_t;
class vao
{
template<buffer::target BindId, uint GetStateId>
class entry
{
vao& m_parent;
public:
using save_binding_state = save_binding_state_base<entry, (static_cast<GLuint>(BindId)), GetStateId>;
entry(vao* parent) noexcept : m_parent(*parent)
{
}
entry& operator = (const buffer& buf) noexcept
{
m_parent.bind();
buf.bind(BindId);
return *this;
}
};
GLuint m_id = GL_NONE;
public:
entry<buffer::target::pixel_pack, GL_PIXEL_PACK_BUFFER_BINDING> pixel_pack_buffer{ this };
entry<buffer::target::pixel_unpack, GL_PIXEL_UNPACK_BUFFER_BINDING> pixel_unpack_buffer{ this };
entry<buffer::target::array, GL_ARRAY_BUFFER_BINDING> array_buffer{ this };
entry<buffer::target::element_array, GL_ELEMENT_ARRAY_BUFFER_BINDING> element_array_buffer{ this };
vao() = default;
vao(const vao&) = delete;
vao(vao&& vao_) noexcept
{
swap(vao_);
}
vao(GLuint id) noexcept
{
set_id(id);
}
~vao() noexcept
{
if (created())
remove();
}
void swap(vao& vao_) noexcept
{
auto my_old_id = id();
set_id(vao_.id());
vao_.set_id(my_old_id);
}
vao& operator = (const vao& rhs) = delete;
vao& operator = (vao&& rhs) noexcept
{
swap(rhs);
return *this;
}
void bind() const noexcept
{
glBindVertexArray(m_id);
}
void create() noexcept
{
glGenVertexArrays(1, &m_id);
}
void remove() noexcept
{
if (m_id != GL_NONE)
{
glDeleteVertexArrays(1, &m_id);
m_id = GL_NONE;
}
}
uint id() const noexcept
{
return m_id;
}
void set_id(uint id) noexcept
{
m_id = id;
}
bool created() const noexcept
{
return m_id != GL_NONE;
}
explicit operator bool() const noexcept
{
return created();
}
void enable_for_attributes(std::initializer_list<GLuint> indexes) noexcept
{
for (auto& index : indexes)
{
glEnableVertexAttribArray(index);
}
}
void disable_for_attributes(std::initializer_list<GLuint> indexes) noexcept
{
for (auto& index : indexes)
{
glDisableVertexAttribArray(index);
}
}
void enable_for_attribute(GLuint index) noexcept
{
enable_for_attributes({ index });
}
void disable_for_attribute(GLuint index) noexcept
{
disable_for_attributes({ index });
}
buffer_pointer operator + (u32 offset) noexcept
{
return{ this, offset };
}
buffer_pointer operator >> (u32 stride) noexcept
{
return{ this, {}, stride };
}
operator buffer_pointer() noexcept
{
return{ this };
}
attrib_t operator [] (u32 index) const noexcept;
};
class attrib_t
{
GLint m_location;
public:
attrib_t(GLint location)
: m_location(location)
{
}
GLint location() const
{
return m_location;
}
void operator = (float rhs) const { glDisableVertexAttribArray(location()); glVertexAttrib1f(location(), rhs); }
void operator = (double rhs) const { glDisableVertexAttribArray(location()); glVertexAttrib1d(location(), rhs); }
void operator = (const color1f& rhs) const { glDisableVertexAttribArray(location()); glVertexAttrib1f(location(), rhs.r); }
void operator = (const color1d& rhs) const { glDisableVertexAttribArray(location()); glVertexAttrib1d(location(), rhs.r); }
void operator = (const color2f& rhs) const { glDisableVertexAttribArray(location()); glVertexAttrib2f(location(), rhs.r, rhs.g); }
void operator = (const color2d& rhs) const { glDisableVertexAttribArray(location()); glVertexAttrib2d(location(), rhs.r, rhs.g); }
void operator = (const color3f& rhs) const { glDisableVertexAttribArray(location()); glVertexAttrib3f(location(), rhs.r, rhs.g, rhs.b); }
void operator = (const color3d& rhs) const { glDisableVertexAttribArray(location()); glVertexAttrib3d(location(), rhs.r, rhs.g, rhs.b); }
void operator = (const color4f& rhs) const { glDisableVertexAttribArray(location()); glVertexAttrib4f(location(), rhs.r, rhs.g, rhs.b, rhs.a); }
void operator = (const color4d& rhs) const { glDisableVertexAttribArray(location()); glVertexAttrib4d(location(), rhs.r, rhs.g, rhs.b, rhs.a); }
void operator = (buffer_pointer& pointer) const
{
pointer.get_vao().enable_for_attribute(m_location);
glVertexAttribPointer(location(), pointer.size(), static_cast<GLenum>(pointer.get_type()), pointer.normalize(),
pointer.stride(), reinterpret_cast<const void*>(u64{ pointer.offset() }));
}
};
}