Refactor gfx attribs: store vertex & instance size in attrib description

This commit is contained in:
Nikita Lisitsa 2021-03-07 18:29:25 +03:00
parent 0bed4ae39f
commit e4f0675a1d
2 changed files with 36 additions and 52 deletions

View file

@ -19,7 +19,6 @@ namespace psemek::gfx
GLint size; GLint size;
GLenum type; GLenum type;
GLboolean normalized; GLboolean normalized;
GLsizei stride;
void const * pointer; void const * pointer;
GLuint divisor; GLuint divisor;
}; };
@ -27,7 +26,11 @@ namespace psemek::gfx
struct attribs_description struct attribs_description
{ {
std::vector<attrib_description> attribs; std::vector<attrib_description> attribs;
GLuint index_count; GLuint index_count = 0;
GLuint vertex_size = 0;
GLuint instance_size = 0;
attribs_description & operator += (attribs_description const & d);
}; };
inline attribs_description operator + (attribs_description d1, attribs_description const & d2) inline attribs_description operator + (attribs_description d1, attribs_description const & d2)
@ -35,12 +38,21 @@ namespace psemek::gfx
for (auto a : d2.attribs) for (auto a : d2.attribs)
{ {
a.index += d1.index_count; a.index += d1.index_count;
a.pointer = reinterpret_cast<char const *>(a.pointer) + (a.divisor == 0 ? d1.vertex_size : d1.instance_size);
d1.attribs.push_back(a); d1.attribs.push_back(a);
} }
d1.index_count += d2.index_count; d1.index_count += d2.index_count;
d1.vertex_size += d2.vertex_size;
d1.instance_size += d2.instance_size;
return d1; return d1;
} }
inline attribs_description & attribs_description::operator += (attribs_description const & d)
{
(*this) = (*this) + d;
return *this;
}
template <typename T> template <typename T>
struct normalized struct normalized
{ {
@ -263,32 +275,6 @@ namespace psemek::gfx
} }
} }
template <bool Instance, typename ... Attribs>
struct stride_helper;
template <bool Instance>
struct stride_helper<Instance>
{
static std::size_t stride()
{
return 0;
}
};
template <bool Instance, typename Attr1, typename ... Attribs>
struct stride_helper<Instance, Attr1, Attribs...>
{
static std::size_t stride()
{
std::size_t s = 0;
if constexpr (is_instanced<Attr1>::value == Instance)
{
s = attr_size<Attr1>();
}
return s + stride_helper<Instance, Attribs...>::stride();
}
};
template <bool Instance, typename ... Attribs> template <bool Instance, typename ... Attribs>
struct make_attribs_description_impl; struct make_attribs_description_impl;
@ -298,9 +284,17 @@ namespace psemek::gfx
static void make(attribs_description &) static void make(attribs_description &)
{} {}
static void make_impl(attribs_description & result, std::size_t index, std::size_t, std::size_t) static void make_impl(attribs_description & result, std::size_t index, std::size_t offset)
{ {
result.index_count = index; result.index_count = index;
if constexpr (Instance)
{
result.instance_size = offset;
}
else
{
result.vertex_size = offset;
}
} }
}; };
@ -309,19 +303,18 @@ namespace psemek::gfx
{ {
static void make(attribs_description & result) static void make(attribs_description & result)
{ {
std::size_t const stride = stride_helper<Instance, Attr1, Attribs...>::stride(); make_impl(result, 0, 0);
make_impl(result, 0, 0, stride);
} }
static void make_impl(attribs_description & result, std::size_t index, std::size_t offset, std::size_t stride) static void make_impl(attribs_description & result, std::size_t index, std::size_t offset)
{ {
if constexpr (std::is_same_v<Attr1, skip>) if constexpr (std::is_same_v<Attr1, skip>)
{ {
make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + 1, offset, stride); make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + 1, offset);
} }
else if constexpr (is_padding<Attr1>::value) else if constexpr (is_padding<Attr1>::value)
{ {
make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index, Instance ? offset : offset + Attr1::size, stride); make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index, Instance ? offset : offset + Attr1::size);
} }
else if constexpr (is_instanced<Attr1>::value == Instance) else if constexpr (is_instanced<Attr1>::value == Instance)
{ {
@ -339,14 +332,13 @@ namespace psemek::gfx
attr.size = traits::size; attr.size = traits::size;
attr.type = traits::type; attr.type = traits::type;
attr.normalized = traits::normalized; attr.normalized = traits::normalized;
attr.stride = stride;
attr.pointer = reinterpret_cast<char const *>(offset + row * attr::static_columns * sizeof(T)); attr.pointer = reinterpret_cast<char const *>(offset + row * attr::static_columns * sizeof(T));
attr.divisor = Instance ? 1 : 0; attr.divisor = Instance ? 1 : 0;
result.attribs.push_back(attr); result.attribs.push_back(attr);
} }
make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + attr::static_rows, offset + attr_size<Attr1>(), stride); make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + attr::static_rows, offset + attr_size<Attr1>());
} }
else else
{ {
@ -358,13 +350,12 @@ namespace psemek::gfx
attr.size = traits::size; attr.size = traits::size;
attr.type = traits::type; attr.type = traits::type;
attr.normalized = traits::normalized; attr.normalized = traits::normalized;
attr.stride = stride;
attr.pointer = reinterpret_cast<char const *>(offset); attr.pointer = reinterpret_cast<char const *>(offset);
attr.divisor = Instance ? 1 : 0; attr.divisor = Instance ? 1 : 0;
result.attribs.push_back(attr); result.attribs.push_back(attr);
make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + 1, offset + attr_size<Attr1>(), stride); make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + 1, offset + attr_size<Attr1>());
} }
} }
else else
@ -373,11 +364,11 @@ namespace psemek::gfx
if constexpr (is_matrix<attr>::value) if constexpr (is_matrix<attr>::value)
{ {
make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + attr::static_rows, offset, stride); make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + attr::static_rows, offset);
} }
else else
{ {
make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + 1, offset, stride); make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + 1, offset);
} }
} }
} }

View file

@ -45,28 +45,21 @@ namespace psemek::gfx
std::size_t max_index = 0; std::size_t max_index = 0;
bool instanced = false; bool instanced = false;
std::size_t stride = 0;
std::size_t instance_stride = 0;
for (auto const & a : attribs.attribs) for (auto const & a : attribs.attribs)
{ {
max_index = std::max<std::size_t>(max_index, a.index); max_index = std::max<std::size_t>(max_index, a.index);
if (a.divisor == 0) if (a.divisor != 0)
{
stride = a.stride;
}
else
{ {
assert(a.divisor == 1); assert(a.divisor == 1);
instance_stride = a.stride;
instanced = true; instanced = true;
} }
} }
info_.max_attribute_index_ = max_index; info_.max_attribute_index_ = max_index;
info_.stride_ = stride; info_.stride_ = attribs.vertex_size;
info_.instance_stride_ = instance_stride; info_.instance_stride_ = attribs.instance_size;
info_.instanced_ = instanced; info_.instanced_ = instanced;
if (!vertex_buffer_) vertex_buffer_ = buffer{}; if (!vertex_buffer_) vertex_buffer_ = buffer{};
@ -77,7 +70,7 @@ namespace psemek::gfx
if (a.divisor != 0) continue; if (a.divisor != 0) continue;
gl::EnableVertexAttribArray(a.index); gl::EnableVertexAttribArray(a.index);
gl::VertexAttribPointer(a.index, a.size, a.type, a.normalized, a.stride, a.pointer); gl::VertexAttribPointer(a.index, a.size, a.type, a.normalized, attribs.vertex_size, a.pointer);
} }
if (instanced) if (instanced)
@ -90,7 +83,7 @@ namespace psemek::gfx
if (a.divisor == 0) continue; if (a.divisor == 0) continue;
gl::EnableVertexAttribArray(a.index); gl::EnableVertexAttribArray(a.index);
gl::VertexAttribPointer(a.index, a.size, a.type, a.normalized, a.stride, a.pointer); gl::VertexAttribPointer(a.index, a.size, a.type, a.normalized, attribs.instance_size, a.pointer);
gl::VertexAttribDivisor(a.index, a.divisor); gl::VertexAttribDivisor(a.index, a.divisor);
} }
} }