diff --git a/src/CollabList.hpp b/src/CollabList.hpp index d048f49..0950899 100644 --- a/src/CollabList.hpp +++ b/src/CollabList.hpp @@ -163,12 +163,13 @@ template class CollabList { newObj->syncIgnore = false; newObj->id = id; newObj->obj = item; - newObj->pos = clientSideList.size() - 1; item->collabListInfo = newObj; serverSideList.emplace_back(newObj); clientSideList.emplace_back(newObj); + newObj->pos = clientSideList.size() - 1; + if(clientInsertCallback) clientInsertCallback(newObj); if(updateCallback) diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index 24e798f..aa6384f 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -564,8 +564,10 @@ void DrawingProgram::draw(SkCanvas* canvas, const DrawData& drawData) { parallel_loop_all_components([&](auto& c) { c->obj->calculate_draw_transform(drawData); }); - for(auto& c : components.client_list()) + for(auto& c : components.client_list()) { c->obj->draw(canvas, drawData); + c->obj->drawSetupData.shouldDraw = false; + } } else { SkCanvas* drawProgCacheCanvas = world.main.drawProgCache.surface->getCanvas(); @@ -609,13 +611,11 @@ void DrawingProgram::draw(SkCanvas* canvas, const DrawData& drawData) { } } -void DrawingProgram::draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, bool dontUseCache) { +uint64_t DrawingProgram::draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, bool dontUseCache) { + uint64_t lastComponentDrawn = 0; + std::vector> cachedNodesToDraw; std::vector uncachedCompsToDraw; - size_t numOfUncachedComponentsToDraw = 0; - - const size_t maxUncachedCompsToUseAltStrategy = 1000; - const size_t minCompsToUseAltStrategy = 100000; compCache.traverse_bvh_run_function(drawData.cam.viewingAreaGenerousCollider, [&](const std::shared_ptr& node, const std::vector& comps) { if(!dontUseCache && node && node->drawCache && node->coords.inverseScale <= drawData.cam.c.inverseScale) { @@ -626,51 +626,30 @@ void DrawingProgram::draw_components_to_canvas(SkCanvas* canvas, const DrawData& for(auto& c : comps) c->obj->calculate_draw_transform(drawData); - if(numOfUncachedComponentsToDraw < minCompsToUseAltStrategy && components.client_list().size() > maxUncachedCompsToUseAltStrategy) { - uncachedCompsToDraw.insert(uncachedCompsToDraw.end(), comps.begin(), comps.end()); - numOfUncachedComponentsToDraw += comps.size(); - } + uncachedCompsToDraw.insert(uncachedCompsToDraw.end(), comps.begin(), comps.end()); return true; }); - if(numOfUncachedComponentsToDraw < minCompsToUseAltStrategy && components.client_list().size() > maxUncachedCompsToUseAltStrategy) { - std::sort(uncachedCompsToDraw.begin(), uncachedCompsToDraw.end(), [](auto& a, auto& b) { - return a->pos < b->pos; - }); - std::sort(cachedNodesToDraw.begin(), cachedNodesToDraw.end(), [](auto& a, auto& b) { - return a->drawCache.value().lastDrawnComponentPlacement < b->drawCache.value().lastDrawnComponentPlacement; - }); - size_t nextCacheToRender = 0; - for(auto& c : uncachedCompsToDraw) { - for(;;) { - if(nextCacheToRender >= cachedNodesToDraw.size() || c->pos >= cachedNodesToDraw[nextCacheToRender]->drawCache.value().lastDrawnComponentPlacement) - break; - auto& bvhNode = cachedNodesToDraw[nextCacheToRender]; - auto& drawCache = bvhNode->drawCache.value(); - canvas->save(); - bvhNode->coords.transform_sk_canvas(canvas, drawData); - drawCache.lastRenderTime = std::chrono::steady_clock::now(); - - SkPaint p; - p.setBlendMode(SkBlendMode::kSrc); - - // Note, no mipmaps here. You might need to generate mipmaps in the future (withDefaultMipmaps) - canvas->drawImage(drawCache.surface->makeTemporaryImage(), 0, 0, {SkFilterMode::kLinear, SkMipmapMode::kLinear}, &p); - - canvas->restore(); - nextCacheToRender++; - } - c->obj->draw(canvas, drawData); - c->obj->drawSetupData.shouldDraw = false; - } - for(;nextCacheToRender < cachedNodesToDraw.size(); nextCacheToRender++) { + std::sort(uncachedCompsToDraw.begin(), uncachedCompsToDraw.end(), [](auto& a, auto& b) { + return a->pos < b->pos; + }); + std::sort(cachedNodesToDraw.begin(), cachedNodesToDraw.end(), [](auto& a, auto& b) { + return a->drawCache.value().lastDrawnComponentPlacement < b->drawCache.value().lastDrawnComponentPlacement; + }); + size_t nextCacheToRender = 0; + for(auto& c : uncachedCompsToDraw) { + for(;;) { + if(nextCacheToRender >= cachedNodesToDraw.size() || c->pos < cachedNodesToDraw[nextCacheToRender]->drawCache.value().lastDrawnComponentPlacement) + break; auto& bvhNode = cachedNodesToDraw[nextCacheToRender]; auto& drawCache = bvhNode->drawCache.value(); canvas->save(); bvhNode->coords.transform_sk_canvas(canvas, drawData); drawCache.lastRenderTime = std::chrono::steady_clock::now(); - + + lastComponentDrawn = std::max(lastComponentDrawn, drawCache.lastDrawnComponentPlacement); + SkPaint p; p.setBlendMode(SkBlendMode::kSrc); @@ -678,31 +657,31 @@ void DrawingProgram::draw_components_to_canvas(SkCanvas* canvas, const DrawData& canvas->drawImage(drawCache.surface->makeTemporaryImage(), 0, 0, {SkFilterMode::kLinear, SkMipmapMode::kLinear}, &p); canvas->restore(); + nextCacheToRender++; } + c->obj->draw(canvas, drawData); + c->obj->drawSetupData.shouldDraw = false; + lastComponentDrawn = std::max(lastComponentDrawn, c->pos); } - else { - for(uint64_t i = 0; i < components.client_list().size(); i++) { - auto& c = components.client_list()[i]; - c->obj->draw(canvas, drawData); - for(const std::shared_ptr& bvhNode : cachedNodesToDraw) { - auto& drawCache = bvhNode->drawCache.value(); - if(drawCache.lastDrawnComponentPlacement == i) { - canvas->save(); - bvhNode->coords.transform_sk_canvas(canvas, drawData); - drawCache.lastRenderTime = std::chrono::steady_clock::now(); - - SkPaint p; - p.setBlendMode(SkBlendMode::kSrc); + for(;nextCacheToRender < cachedNodesToDraw.size(); nextCacheToRender++) { + auto& bvhNode = cachedNodesToDraw[nextCacheToRender]; + auto& drawCache = bvhNode->drawCache.value(); + canvas->save(); + bvhNode->coords.transform_sk_canvas(canvas, drawData); + drawCache.lastRenderTime = std::chrono::steady_clock::now(); - // Note, no mipmaps here. You might need to generate mipmaps in the future (withDefaultMipmaps) - canvas->drawImage(drawCache.surface->makeTemporaryImage(), 0, 0, {SkFilterMode::kLinear, SkMipmapMode::kLinear}, &p); + lastComponentDrawn = std::max(lastComponentDrawn, drawCache.lastDrawnComponentPlacement); - canvas->restore(); - } - } - c->obj->drawSetupData.shouldDraw = false; - } + SkPaint p; + p.setBlendMode(SkBlendMode::kSrc); + + // Note, no mipmaps here. You might need to generate mipmaps in the future (withDefaultMipmaps) + canvas->drawImage(drawCache.surface->makeTemporaryImage(), 0, 0, {SkFilterMode::kLinear, SkMipmapMode::kLinear}, &p); + + canvas->restore(); } + + return lastComponentDrawn; } Vector4f* DrawingProgram::get_foreground_color_ptr() { diff --git a/src/DrawingProgram/DrawingProgram.hpp b/src/DrawingProgram/DrawingProgram.hpp index 9ee9bcb..7b6b630 100644 --- a/src/DrawingProgram/DrawingProgram.hpp +++ b/src/DrawingProgram/DrawingProgram.hpp @@ -86,7 +86,7 @@ class DrawingProgram { void add_undo_place_component(uint64_t placement, const std::shared_ptr& comp); void add_undo_place_components(uint64_t placement, const std::vector>& comps); - void draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, bool dontUseCache); + uint64_t draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, bool dontUseCache); BrushTool brushTool; EraserTool eraserTool; diff --git a/src/DrawingProgram/DrawingProgramCache.cpp b/src/DrawingProgram/DrawingProgramCache.cpp index e42b0e7..ddc8a67 100644 --- a/src/DrawingProgram/DrawingProgramCache.cpp +++ b/src/DrawingProgram/DrawingProgramCache.cpp @@ -11,7 +11,9 @@ #include #endif -#define MAXIMUM_DRAW_CACHE_SURFACES 32 +#define MAXIMUM_DRAW_CACHE_SURFACES 64 + +std::unordered_set> DrawingProgramCache::nodesWithCachedSurfaces; DrawingProgramCache::DrawingProgramCache(DrawingProgram& initDrawP): drawP(initDrawP) @@ -22,7 +24,7 @@ DrawingProgramCache::DrawingProgramCache(DrawingProgram& initDrawP): void DrawingProgramCache::build(std::vector components) { bvhRoot = std::make_shared(); unsortedComponents.clear(); - nodesWithCachedSurfaces.clear(); + clear_own_cached_surfaces(); std::erase_if(components, [&](auto& c) { if(!c->obj->worldAABB) { unsortedComponents.emplace_back(c); @@ -35,6 +37,12 @@ void DrawingProgramCache::build(std::vector compo lastBvhBuildTime = std::chrono::steady_clock::now(); } +void DrawingProgramCache::clear_own_cached_surfaces() { + std::erase_if(nodesWithCachedSurfaces, [&](auto& s) { + return s->drawCache.value().attachedDrawP == &drawP; + }); +} + void DrawingProgramCache::update() { if(unsortedComponents.size() >= 1000 && (std::chrono::steady_clock::now() - lastBvhBuildTime) >= std::chrono::seconds(5)) force_rebuild(); @@ -257,10 +265,10 @@ void DrawingProgramCache::refresh_draw_cache(const std::shared_ptr& bvh cacheDrawData.cam.changed = nullptr; cacheDrawData.cam.set_viewing_area(bvhNode->resolution.cast()); cacheDrawData.refresh_draw_optimizing_values(); - drawP.draw_components_to_canvas(cacheCanvas, cacheDrawData, false); - drawCache.lastDrawnComponentPlacement = drawP.components.client_list().size() - 1; + drawCache.lastDrawnComponentPlacement = drawP.draw_components_to_canvas(cacheCanvas, cacheDrawData, false); drawCache.lastRenderTime = std::chrono::steady_clock::now(); + drawCache.attachedDrawP = &drawP; bvhNode->drawCache = drawCache; // Set the drawCache after rendering is done, so that the draw function doesnt assume we have this node cached diff --git a/src/DrawingProgram/DrawingProgramCache.hpp b/src/DrawingProgram/DrawingProgramCache.hpp index 2a1501c..d92e6fd 100644 --- a/src/DrawingProgram/DrawingProgramCache.hpp +++ b/src/DrawingProgram/DrawingProgramCache.hpp @@ -30,12 +30,13 @@ class DrawingProgramCache { uint64_t lastDrawnComponentPlacement; sk_sp surface; std::chrono::steady_clock::time_point lastRenderTime; + DrawingProgram* attachedDrawP; }; std::optional drawCache; }; - std::unordered_set> nodesWithCachedSurfaces; + static std::unordered_set> nodesWithCachedSurfaces; void traverse_bvh_collision_check(const SCollision::ColliderCollection& checkAgainstWorld, const SCollision::ColliderCollection& checkAgainstCam); void traverse_bvh_run_function(const SCollision::AABB& aabb, std::function node, const std::vector& components)> f); @@ -46,6 +47,7 @@ class DrawingProgramCache { void invalidate_cache_before_pos(uint64_t placementToInvalidateAt); private: + void clear_own_cached_surfaces(); void traverse_bvh_collision_check_recursive(const std::shared_ptr& bvhNode, const SCollision::ColliderCollection& checkAgainstWorld, const SCollision::ColliderCollection& checkAgainstCam); void traverse_bvh_collision_check_recursive_tiny(const std::shared_ptr& bvhNode);