From: Mikko Rasa Date: Sat, 30 Oct 2021 19:07:48 +0000 (+0300) Subject: Use a sorted vector in place of set for small data X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=84e0e55710123e54617d342df852007f8b60af24;p=libs%2Fgl.git Use a sorted vector in place of set for small data Despite having worse algorithmic performance, cache effects make the vector faster for total data size of up to about 8 kB (YMMV). The GLSL compiler can keep its sets for now, I'll create a proper class for this at some point. --- diff --git a/source/effects/effect.cpp b/source/effects/effect.cpp index 05ef5a10..e59aeed8 100644 --- a/source/effects/effect.cpp +++ b/source/effects/effect.cpp @@ -1,3 +1,4 @@ +#include #include "effect.h" namespace Msp { @@ -6,17 +7,27 @@ namespace GL { Effect::Effect(Renderable &r): renderable(r) { - enabled_methods.insert(Tag()); + enable_for_method(Tag()); } void Effect::enable_for_method(Tag tag) { - enabled_methods.insert(tag); + auto i = lower_bound(enabled_methods, tag); + if(i==enabled_methods.end() || *i!=tag) + enabled_methods.insert(i, tag); } void Effect::disable_for_method(Tag tag) { - enabled_methods.erase(tag); + auto i = lower_bound(enabled_methods, tag); + if(i!=enabled_methods.end() && *i==tag) + enabled_methods.erase(i); +} + +bool Effect::is_enabled_for_method(Tag tag) const +{ + auto i = lower_bound(enabled_methods, tag); + return (i!=enabled_methods.end() && *i==tag); } diff --git a/source/effects/effect.h b/source/effects/effect.h index eadb4dc8..0d794a3a 100644 --- a/source/effects/effect.h +++ b/source/effects/effect.h @@ -35,7 +35,7 @@ public: protected: Renderable &renderable; - std::set enabled_methods; + std::vector enabled_methods; protected: Effect(Renderable &); @@ -44,6 +44,7 @@ public: void enable_for_method(Tag); void disable_for_method(Tag); + bool is_enabled_for_method(Tag) const; virtual const Matrix *get_matrix() const { return renderable.get_matrix(); } virtual const Geometry::BoundingSphere *get_bounding_sphere() const { return renderable.get_bounding_sphere(); } diff --git a/source/effects/environmentmap.cpp b/source/effects/environmentmap.cpp index b9a7124c..b1a50ecc 100644 --- a/source/effects/environmentmap.cpp +++ b/source/effects/environmentmap.cpp @@ -169,7 +169,7 @@ void EnvironmentMap::render(Renderer &renderer, Tag tag) const { if(in_setup_frame) return; - if(!enabled_methods.count(tag)) + if(!is_enabled_for_method(tag)) return renderable.render(renderer, tag); Renderer::Push _push_rend(renderer); diff --git a/source/effects/shadowmap.cpp b/source/effects/shadowmap.cpp index 55da7301..6b926dd8 100644 --- a/source/effects/shadowmap.cpp +++ b/source/effects/shadowmap.cpp @@ -250,7 +250,7 @@ void ShadowMap::finish_frame() void ShadowMap::render(Renderer &renderer, Tag tag) const { - if(!enabled_methods.count(tag)) + if(!is_enabled_for_method(tag)) return renderable.render(renderer, tag); Renderer::Push _push_rend(renderer); diff --git a/source/effects/sky.cpp b/source/effects/sky.cpp index ab322f23..0744e7b9 100644 --- a/source/effects/sky.cpp +++ b/source/effects/sky.cpp @@ -132,7 +132,7 @@ void Sky::render(Renderer &renderer, Tag tag) const { renderable.render(renderer, tag); - if(!enabled_methods.count(tag)) + if(!is_enabled_for_method(tag)) return; Renderer::Push push(renderer); diff --git a/source/render/occludedscene.cpp b/source/render/occludedscene.cpp index 5d85b5d5..bfe17349 100644 --- a/source/render/occludedscene.cpp +++ b/source/render/occludedscene.cpp @@ -1,4 +1,4 @@ -#include +#include #include "camera.h" #include "mesh.h" #include "occludedscene.h" @@ -21,14 +21,22 @@ OccludedScene::OccludedScene(): void OccludedScene::add(Renderable &r) { - renderables.insert(&r); - cache_dirty = true; + auto i = lower_bound(renderables, &r); + if(i==renderables.end() || *i!=&r) + { + renderables.insert(i, &r); + cache_dirty = true; + } } void OccludedScene::remove(Renderable &r) { - renderables.erase(&r); - cache_dirty = true; + auto i = lower_bound(renderables, &r); + if(i!=renderables.end() && *i==&r) + { + renderables.erase(i); + cache_dirty = true; + } } void OccludedScene::populate_cache() const diff --git a/source/render/occludedscene.h b/source/render/occludedscene.h index 6efb354e..4d56db7a 100644 --- a/source/render/occludedscene.h +++ b/source/render/occludedscene.h @@ -36,7 +36,7 @@ private: const Program &bounding_shader; Blend no_color_write; DepthTest no_depth_write = { LEQUAL, false }; - std::set renderables; + std::vector renderables; float occluder_min_size = 0.25f; mutable QueryPool queries; mutable std::vector occluded_cache; diff --git a/source/render/simplescene.cpp b/source/render/simplescene.cpp index 4ddbeca6..fbdb004f 100644 --- a/source/render/simplescene.cpp +++ b/source/render/simplescene.cpp @@ -1,3 +1,4 @@ +#include #include "renderer.h" #include "simplescene.h" @@ -6,51 +7,41 @@ namespace GL { void SimpleScene::add(Renderable &r) { - // Add to cache as well if the cache is valid - if(renderables.insert(&r).second && !cache.empty()) - cache.push_back(&r); + auto i = lower_bound(renderables, &r); + if(i==renderables.end() || *i!=&r) + renderables.insert(i, &r); } void SimpleScene::remove(Renderable &r) { - renderables.erase(&r); - cache.clear(); -} - -void SimpleScene::populate_cache() const -{ - if(cache.empty() && !renderables.empty()) - { - cache.reserve(renderables.size()); - cache.insert(cache.end(), renderables.begin(), renderables.end()); - } + auto i = find(renderables, &r); + if(i!=renderables.end()) + renderables.erase(i); } void SimpleScene::setup_frame(Renderer &renderer) { - populate_cache(); - for(Renderable *r: cache) + for(Renderable *r: renderables) r->setup_frame(renderer); } void SimpleScene::finish_frame() { - for(Renderable *r: cache) + for(Renderable *r: renderables) r->finish_frame(); } void SimpleScene::render(Renderer &renderer, Tag tag) const { - populate_cache(); if(setup_frustum(renderer)) { - for(Renderable *r: cache) + for(Renderable *r: renderables) if(!frustum_cull(*r)) r->render(renderer, tag); } else { - for(Renderable *r: cache) + for(Renderable *r: renderables) r->render(renderer, tag); } } diff --git a/source/render/simplescene.h b/source/render/simplescene.h index 1e90874b..ccca360a 100644 --- a/source/render/simplescene.h +++ b/source/render/simplescene.h @@ -16,17 +16,12 @@ public: using Scene::Loader; private: - std::set renderables; - mutable std::vector cache; + std::vector renderables; public: virtual void add(Renderable &); virtual void remove(Renderable &); -private: - void populate_cache() const; - -public: virtual void setup_frame(Renderer &); virtual void finish_frame(); diff --git a/source/render/zsortedscene.cpp b/source/render/zsortedscene.cpp index dd5f1f3a..af3c5b86 100644 --- a/source/render/zsortedscene.cpp +++ b/source/render/zsortedscene.cpp @@ -1,3 +1,4 @@ +#include #include "camera.h" #include "renderer.h" #include "zsortedscene.h" @@ -9,14 +10,23 @@ namespace GL { void ZSortedScene::add(Renderable &r) { - if(renderables.insert(&r).second && !sorted_cache.empty()) - sorted_cache.push_back(&r); + auto i = lower_bound(renderables, &r); + if(i==renderables.end() || *i!=&r) + { + renderables.insert(i, &r); + if(!sorted_cache.empty()) + sorted_cache.push_back(&r); + } } void ZSortedScene::remove(Renderable &r) { - renderables.erase(&r); - sorted_cache.clear(); + auto i = lower_bound(renderables, &r); + if(i!=renderables.end() && *i==&r) + { + renderables.erase(i); + sorted_cache.clear(); + } } void ZSortedScene::set_order(SortOrder o) diff --git a/source/render/zsortedscene.h b/source/render/zsortedscene.h index f268f529..749a9705 100644 --- a/source/render/zsortedscene.h +++ b/source/render/zsortedscene.h @@ -42,7 +42,7 @@ private: bool operator<(const SortedRenderable &o) const { return depth renderables; + std::vector renderables; SortOrder order = BACK_TO_FRONT; DepthReference reference = FURTHEST; mutable std::vector sorted_cache;