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;
GLenum type;
GLboolean normalized;
GLsizei stride;
void const * pointer;
GLuint divisor;
};
@ -27,7 +26,11 @@ namespace psemek::gfx
struct attribs_description
{
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)
@ -35,12 +38,21 @@ namespace psemek::gfx
for (auto a : d2.attribs)
{
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.index_count += d2.index_count;
d1.vertex_size += d2.vertex_size;
d1.instance_size += d2.instance_size;
return d1;
}
inline attribs_description & attribs_description::operator += (attribs_description const & d)
{
(*this) = (*this) + d;
return *this;
}
template <typename T>
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>
struct make_attribs_description_impl;
@ -298,9 +284,17 @@ namespace psemek::gfx
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;
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)
{
std::size_t const stride = stride_helper<Instance, Attr1, Attribs...>::stride();
make_impl(result, 0, 0, stride);
make_impl(result, 0, 0);
}
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>)
{
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)
{
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)
{
@ -339,14 +332,13 @@ namespace psemek::gfx
attr.size = traits::size;
attr.type = traits::type;
attr.normalized = traits::normalized;
attr.stride = stride;
attr.pointer = reinterpret_cast<char const *>(offset + row * attr::static_columns * sizeof(T));
attr.divisor = Instance ? 1 : 0;
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
{
@ -358,13 +350,12 @@ namespace psemek::gfx
attr.size = traits::size;
attr.type = traits::type;
attr.normalized = traits::normalized;
attr.stride = stride;
attr.pointer = reinterpret_cast<char const *>(offset);
attr.divisor = Instance ? 1 : 0;
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
@ -373,11 +364,11 @@ namespace psemek::gfx
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
{
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;
bool instanced = false;
std::size_t stride = 0;
std::size_t instance_stride = 0;
for (auto const & a : attribs.attribs)
{
max_index = std::max<std::size_t>(max_index, a.index);
if (a.divisor == 0)
{
stride = a.stride;
}
else
if (a.divisor != 0)
{
assert(a.divisor == 1);
instance_stride = a.stride;
instanced = true;
}
}
info_.max_attribute_index_ = max_index;
info_.stride_ = stride;
info_.instance_stride_ = instance_stride;
info_.stride_ = attribs.vertex_size;
info_.instance_stride_ = attribs.instance_size;
info_.instanced_ = instanced;
if (!vertex_buffer_) vertex_buffer_ = buffer{};
@ -77,7 +70,7 @@ namespace psemek::gfx
if (a.divisor != 0) continue;
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)
@ -90,7 +83,7 @@ namespace psemek::gfx
if (a.divisor == 0) continue;
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);
}
}