#include "opengl/data_managers/mesh_vertex_buffer_manager.hpp" #include "util/logger.hpp" #include "opengl/error.hpp" #include "opengl/vertex_buffer_utils.hpp" void zgl::mesh_vertex_buffer_manager::process(store_type& store) { for (const auto& [ id, mesh ] : store) { if (not m_resource_manager.has_resource(id)) { m_mesh_buffer.emplace_back(id, mesh); } } m_buffer_id_buffer.resize(m_mesh_buffer.size()); glGenBuffers(m_buffer_id_buffer.size(), m_buffer_id_buffer.data()); if (const auto e = get_error()) { ztu::logger::error("Error while creating % vertex buffers: %.", m_buffer_id_buffer.size(), e.message()); return; } for (auto [ entry, buffer_id ] : std::ranges::views::zip(m_mesh_buffer, m_buffer_id_buffer)) { auto [ store_id, mesh ] = entry; m_byte_buffer.clear(); std::apply( [&](const auto&... component_buffers) { vertex_buffer_utils::interlace( m_byte_buffer, mesh.component_flags, mesh.vertex_count, component_buffers... ); }, mesh.vertex_component_arrays ); glBindBuffer(GL_ARRAY_BUFFER, buffer_id); if (const auto e = get_error()) { ztu::logger::error("Error while binding vertex buffer %: %.", buffer_id, e.message()); continue; } glBufferData( GL_ARRAY_BUFFER, static_cast(m_byte_buffer.size()), m_byte_buffer.data(), GL_STATIC_DRAW ); if (const auto e = get_error()) { ztu::logger::error("Error while setting vertex buffer data: %.", e.message()); continue; } const auto meta = mesh_vertex_buffer_metadata{ .component_flags = mesh.component_flags, .material_id = mesh.material_id }; m_resource_manager.add_resource(store_id, buffer_id, meta); buffer_id = {}; } glBindBuffer(GL_ARRAY_BUFFER, 0); const auto valid_buffer_ids = std::ranges::remove( m_buffer_id_buffer, 0 ); const auto invalid_buffer_count = m_buffer_id_buffer.size() - valid_buffer_ids.size(); glDeleteBuffers( invalid_buffer_count, m_buffer_id_buffer.data() ); if (const auto e = get_error()) { ztu::logger::error("Error while deleting % buffers: %.", invalid_buffer_count, e.message()); } } std::optional zgl::mesh_vertex_buffer_manager::get_handle( const store_id_type id ) { return m_resource_manager .get_resource(id) .transform( [](auto& resource) { return *reinterpret_cast(resource); } ); } void zgl::mesh_vertex_buffer_manager::collect_garbage(const bool force) { m_resource_manager.collect_garbage(); if (force or m_resource_manager.count_garbage() >= min_garbage_collection_count) { m_buffer_id_buffer.clear(); m_resource_manager.extract_garbage(m_buffer_id_buffer); glDeleteBuffers( m_buffer_id_buffer.size(), m_buffer_id_buffer.data() ); } }