From d807d5c74b4a26e427a0f0dcb421d880be1a0aff Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sun, 4 Oct 2020 17:35:21 +0300 Subject: [PATCH] Refactor mesh setup & properly disable old attribs on re-setup --- libs/gfx/include/psemek/gfx/mesh.hpp | 118 +++++++++++++++------------ 1 file changed, 64 insertions(+), 54 deletions(-) diff --git a/libs/gfx/include/psemek/gfx/mesh.hpp b/libs/gfx/include/psemek/gfx/mesh.hpp index 7268116a..68ecb040 100644 --- a/libs/gfx/include/psemek/gfx/mesh.hpp +++ b/libs/gfx/include/psemek/gfx/mesh.hpp @@ -267,46 +267,50 @@ namespace psemek::gfx } }; - template - struct mesh_setup_base; - - template - struct mesh_setup_base + struct mesh_setup_result { - static std::size_t setup() - { - return 0; - } - - static void setup_impl(int, std::size_t, std::size_t) - {} + std::size_t stride; + std::size_t max_index; }; - template - struct mesh_setup_base + template + struct mesh_setup_base; + + template + struct mesh_setup_base { - static std::size_t setup() + static mesh_setup_result setup() { - std::size_t const stride = stride_helper::stride(); - setup_impl(0, 0, stride); - return stride; + return {0, 0}; } - static void setup_impl(int index, std::size_t offset, std::size_t stride) + static std::size_t setup_impl(std::size_t index, std::size_t, std::size_t) + { + return index; + } + }; + + template + struct mesh_setup_base + { + static mesh_setup_result setup() + { + std::size_t const stride = stride_helper::stride(); + auto const max_index = setup_impl(0, 0, stride); + return {stride, max_index}; + } + + static std::size_t setup_impl(std::size_t index, std::size_t offset, std::size_t stride) { if constexpr (std::is_same_v) { - mesh_setup_base::setup_impl(index + 1, offset, stride); + return mesh_setup_base::setup_impl(index + 1, offset, stride); } else if constexpr (is_padding::value) { - mesh_setup_base::setup_impl(index, offset + Attr1::size, stride); + return mesh_setup_base::setup_impl(index, offset + Attr1::size, stride); } - else if constexpr (!IsInstanced && is_instanced::value) - { - static_assert("cannot use instanced attribute for non-instanced mesh"); - } - else if constexpr (!IsInstanced || (is_instanced::value == InstanceSetup)) + else if constexpr (is_instanced::value == InstanceSetup) { using attr = typename remove_instanced::type; @@ -324,7 +328,7 @@ namespace psemek::gfx gl::VertexAttribDivisor(index + row, 1); } - mesh_setup_base::setup_impl(index + attr::rows, offset + attr_size(), stride); + return mesh_setup_base::setup_impl(index + attr::rows, offset + attr_size(), stride); } else { @@ -336,7 +340,7 @@ namespace psemek::gfx gl::EnableVertexAttribArray(index); gl::VertexAttribPointer(index, traits::size, traits::type, traits::normalized, stride, reinterpret_cast(offset)); - mesh_setup_base::setup_impl(index + 1, offset + attr_size(), stride); + return mesh_setup_base::setup_impl(index + 1, offset + attr_size(), stride); } } else @@ -345,24 +349,39 @@ namespace psemek::gfx if constexpr (is_matrix::value) { - mesh_setup_base::setup_impl(index + attr::rows, offset, stride); + return mesh_setup_base::setup_impl(index + attr::rows, offset, stride); } else { - mesh_setup_base::setup_impl(index + 1, offset, stride); + return mesh_setup_base::setup_impl(index + 1, offset, stride); } } } }; template - using mesh_setup = mesh_setup_base; + using mesh_vertex_setup = mesh_setup_base; template - using instanced_mesh_vertex_setup = mesh_setup_base; + using mesh_instance_setup = mesh_setup_base; - template - using instanced_mesh_instance_setup = mesh_setup_base; + template + struct has_instanced_attribs_impl + : std::false_type + {}; + + template + struct has_instanced_attribs_impl + : has_instanced_attribs_impl + {}; + + template + struct has_instanced_attribs_impl, Args...> + : std::true_type + {}; + + template + constexpr bool has_instanced_attribs = has_instanced_attribs_impl::value; template struct gl_type; @@ -433,24 +452,6 @@ namespace psemek::gfx return std::nullopt; } } - - template - struct has_instanced_attribs_impl - : std::false_type - {}; - - template - struct has_instanced_attribs_impl - : has_instanced_attribs_impl - {}; - - template - struct has_instanced_attribs_impl, Args...> - : std::true_type - {}; - - template - constexpr bool has_instanced_attribs = has_instanced_attribs_impl::value; } /* A generic mesh class @@ -549,6 +550,8 @@ namespace psemek::gfx GLenum primitive_type_; GLenum index_type_; + + std::size_t max_attribute_index_ = 0; }; mesh_info info_; @@ -559,16 +562,23 @@ namespace psemek::gfx { array_.bind(); + for (std::size_t i = 0; i < info_.max_attribute_index_; ++i) + gl::DisableVertexAttribArray(i); + if (!vertex_buffer_) vertex_buffer_ = buffer{}; vertex_buffer_.bind(); - info_.stride_ = detail::instanced_mesh_vertex_setup::setup(); + auto vertex_setup = detail::mesh_vertex_setup::setup(); + info_.stride_ = vertex_setup.stride; + info_.max_attribute_index_ = vertex_setup.max_index; if constexpr (detail::has_instanced_attribs) { if (!instance_buffer_) instance_buffer_ = buffer{}; instance_buffer_.bind(); - info_.instance_stride_ = detail::instanced_mesh_instance_setup::setup(); + auto instance_setup = detail::mesh_instance_setup::setup(); + info_.instance_stride_ = instance_setup.stride; info_.instanced_ = true; + info_.max_attribute_index_ = std::max(info_.max_attribute_index_, instance_setup.max_index); } else {