diff options
| author | Stanislaw Halik <sthalik@misaki.pl> | 2024-05-20 12:24:30 +0200 |
|---|---|---|
| committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-05-20 16:09:42 +0200 |
| commit | df58a09b9f673d4617f552ecd0e3354b51883e05 (patch) | |
| tree | d9478ce42b903009e3e151befee22c851c40bf2a | |
| parent | 492950224cb06b08490d81e06af68b5fbbb6aab6 (diff) | |
draw consecutive vbo same-atlas objects in one draw call
| -rw-r--r-- | draw/anim.cpp | 93 | ||||
| -rw-r--r-- | draw/anim.hpp | 2 |
2 files changed, 78 insertions, 17 deletions
diff --git a/draw/anim.cpp b/draw/anim.cpp index a5dddebe..d840c8c6 100644 --- a/draw/anim.cpp +++ b/draw/anim.cpp @@ -14,6 +14,68 @@ namespace floormat { +namespace { + +std::array<UnsignedShort, 6> make_index_array() +{ + return {{ + 0, 1, 2, + 2, 1, 3, + }}; +} + +struct minmax_s { uint32_t len, min; }; + +bool check_contig_draw(ArrayView<const chunk::object_draw_order> array, uint32_t start, uint32_t end, minmax_s& ret) +{ + const auto& e0 = array[start]; + uint32_t min = e0.mesh_idx, max = min; + + for (auto i = start+1; i < end; i++) + { + const auto& e = array[i]; + min = Math::min(min, e.mesh_idx); + max = Math::max(max, e.mesh_idx); + } + + auto len = max - min; + auto sz = end - start; + ret = { + .len = sz, + .min = min, + }; + return len+1 == sz; +} + +uint32_t get_contig_draw_max_len(ArrayView<const chunk::object_draw_order> array, uint32_t start) +{ + const auto size = (uint32_t)array.size(); + uint32_t len = 1; + const auto* a0 = array[start].e->atlas.get(); + for (auto i = start+1; i < size; i++) + { + const auto& e = array[i]; + if (e.e->atlas.get() != a0) + break; + if (e.mesh_idx == (uint32_t)-1) + break; + len++; + } + return len; +} + +minmax_s get_contig_draw_len(ArrayView<const chunk::object_draw_order> array, uint32_t start) +{ + auto r = minmax_s { .len = 1, .min = array[start].mesh_idx, }; + auto len = get_contig_draw_max_len(array, start); + for (auto i = len; i > 1; i--) + if (check_contig_draw(array, start, start + i, r)) + return r; + return r; +} + +} // namespace + anim_mesh::anim_mesh() : _vertex_buffer{quad_data{}, Magnum::GL::BufferUsage::DynamicDraw}, _index_buffer{make_index_array()} @@ -24,14 +86,6 @@ anim_mesh::anim_mesh() : CORRADE_INTERNAL_ASSERT(_mesh.isIndexed()); } -std::array<UnsignedShort, 6> anim_mesh::make_index_array() -{ - return {{ - 0, 1, 2, - 2, 1, 3, - }}; -} - void anim_mesh::add_clickable(tile_shader& shader, const Vector2i& win_size, object* sʹ, const chunk::topo_sort_data& data, Array<clickable>& list) @@ -64,13 +118,14 @@ void anim_mesh::draw(tile_shader& shader, const Vector2i& win_size, chunk& c, Ar { constexpr auto quad_index_count = 6; - auto [mesh_, es, size] = c.ensure_scenery_mesh({ _draw_array, _draw_vertexes, _draw_indexes }); + auto [mesh_, es, size] = c.ensure_scenery_mesh({ _draw_array, _draw_vertexes, _draw_indexes, }); const auto max_index = uint32_t(size*quad_index_count - 1); - uint32_t i = 0; + uint32_t k = 0; - for (const auto& x : es) + while (k < es.size()) { + const auto& x = es[k]; fm_assert(x.e); add_clickable(shader, win_size, x.data.in, x.data, list); auto& e = *x.e; @@ -79,12 +134,18 @@ void anim_mesh::draw(tile_shader& shader, const Vector2i& win_size, chunk& c, Ar fm_assert(e.is_dynamic() == (x.mesh_idx == (uint32_t)-1)); if (!e.is_dynamic()) { - fm_assert(i < size); +#if 1 + auto r = get_contig_draw_len(es, k); +#else + auto r = minmax_s{1, x.mesh_idx}; +#endif + uint32_t count = r.len; GL::MeshView mesh{mesh_}; - mesh.setCount(quad_index_count * 1); - mesh.setIndexOffset((int)(x.mesh_idx*quad_index_count), 0, max_index); + mesh.setCount(quad_index_count * (Int)count); + mesh.setIndexOffset((int)(r.min*quad_index_count), 0, max_index); shader.draw(atlas.texture(), mesh); - i++; + //if (count > 1) Debug{} << "foo" << atlas.name() << count; + k += count; } else { @@ -95,8 +156,10 @@ void anim_mesh::draw(tile_shader& shader, const Vector2i& win_size, chunk& c, Ar const auto depth0 = e.depth_offset(); const auto depth = tile_shader::depth_value(e.coord.local(), depth0); draw(shader, atlas, e.r, e.frame, e.coord.local(), e.offset, depth); + k++; } } + fm_assert(k == es.size()); } void anim_mesh::draw(tile_shader& shader, anim_atlas& atlas, rotation r, size_t frame, const Vector3& center, float depth) diff --git a/draw/anim.hpp b/draw/anim.hpp index a9fd6011..9a49289a 100644 --- a/draw/anim.hpp +++ b/draw/anim.hpp @@ -34,8 +34,6 @@ struct anim_mesh Array<clickable>& list); private: - static std::array<UnsignedShort, 6> make_index_array(); - struct vertex_data { Vector3 position; |
