From 1e51bf660fd87eba206a2f1783af6cf4735ecd6b Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Sat, 19 Jul 2025 19:41:25 +0300 Subject: [PATCH] Started work on draw cache --- src/CollabList.hpp | 52 ++++++++++++++++++++-- src/DrawingProgram/DrawingProgram.cpp | 13 ++++-- src/DrawingProgram/DrawingProgramCache.cpp | 28 ++++++++++-- src/DrawingProgram/DrawingProgramCache.hpp | 15 ++++++- 4 files changed, 94 insertions(+), 14 deletions(-) diff --git a/src/CollabList.hpp b/src/CollabList.hpp index c4dc50d..271b7cd 100644 --- a/src/CollabList.hpp +++ b/src/CollabList.hpp @@ -11,6 +11,7 @@ template class CollabList { bool syncIgnore; IDType id; T obj; + uint64_t pos; }; typedef std::shared_ptr ObjectInfoPtr; @@ -22,6 +23,7 @@ template class CollabList { std::function updateCallback; std::function clientInsertCallback; std::function clientEraseCallback; + std::function clientServerLastPosShiftCallback; void set_server_from_client_list() { serverSideList = clientSideList; @@ -53,6 +55,7 @@ template class CollabList { } void client_erase_if(const std::function&)>& func) { + bool erasedSomething = false; for(int64_t i = 0; i < (int64_t)clientSideList.size(); i++) { if(func((uint64_t)i, clientSideList[i])) { if(clientEraseCallback) @@ -61,8 +64,11 @@ template class CollabList { i--; if(updateCallback) updateCallback(); + erasedSomething = true; } } + if(erasedSomething) + complete_client_pos_refresh(false); } IDType client_insert(uint64_t pos, const T& item) { @@ -70,15 +76,20 @@ template class CollabList { newObj->syncIgnore = true; newObj->id = getNewIDFunc(); newObj->obj = item; - uint64_t minPos = std::min(static_cast(clientSideList.size()), pos); - clientSideList.insert(clientSideList.begin() + minPos, newObj); + newObj->pos = std::min(static_cast(clientSideList.size()), pos); + clientSideList.insert(clientSideList.begin() + newObj->pos, newObj); + + client_pos_refresh_after_insert(newObj->pos); + if(clientInsertCallback) clientInsertCallback(newObj); if(updateCallback) updateCallback(); + return newObj->id; } void client_erase(const T& item, IDType& erasedID) { + bool erasedSomething = false; std::erase_if(clientSideList, [&](const auto& obj) { if(obj->obj == item) { if(clientEraseCallback) @@ -87,10 +98,13 @@ template class CollabList { obj->syncIgnore = true; if(updateCallback) updateCallback(); + erasedSomething = true; return true; } return false; }); + if(erasedSomething) + complete_client_pos_refresh(false); } bool server_insert(uint64_t pos, IDType id, const T& item) { @@ -108,11 +122,16 @@ template class CollabList { newObj->syncIgnore = false; newObj->id = id; newObj->obj = item; + newObj->pos = std::min(pos, clientSideList.size()); serverSideList.insert(serverSideList.begin() + pos, newObj); - uint64_t minPos = std::min(pos, clientSideList.size()); - clientSideList.insert(clientSideList.begin() + minPos, newObj); + clientSideList.insert(clientSideList.begin() + newObj->pos, newObj); + + for(uint64_t i = newObj->pos + 1; i < static_cast(clientSideList.size()); i++) + clientSideList[i]->pos++; + if(clientInsertCallback) clientInsertCallback(newObj); + sync(); return true; } @@ -140,14 +159,38 @@ template class CollabList { newObj->syncIgnore = false; newObj->id = id; newObj->obj = item; + newObj->pos = clientSideList.size() - 1; + serverSideList.emplace_back(newObj); clientSideList.emplace_back(newObj); + if(clientInsertCallback) clientInsertCallback(newObj); if(updateCallback) updateCallback(); } private: + void complete_client_pos_refresh(bool syncFromServer) { + uint64_t lastShiftPos = 0; + bool shiftHappened = false; + for(uint64_t i = 0; i < clientSideList.size(); i++) { + auto& c = clientSideList[i]; + if(c->pos != i) { + lastShiftPos = std::max(lastShiftPos, c->pos); + lastShiftPos = std::max(lastShiftPos, i); + shiftHappened = true; + c->pos = i; + } + } + if(syncFromServer && shiftHappened && clientServerLastPosShiftCallback) + clientServerLastPosShiftCallback(lastShiftPos); + } + + void client_pos_refresh_after_insert(uint64_t posToRefreshAfter) { + for(uint64_t i = posToRefreshAfter + 1; i < static_cast(clientSideList.size()); i++) + clientSideList[i]->pos = i; + } + void sync() { std::vector> ignoredToReinsert; for(uint64_t i = 0; i < clientSideList.size(); i++) @@ -165,6 +208,7 @@ template class CollabList { } if(updateCallback) updateCallback(); + complete_client_pos_refresh(true); } std::function getNewIDFunc; std::vector clientSideList; diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index da532ca..2130f94 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -28,6 +28,9 @@ #include #endif +template void parallel_loop_vector_any_type() { +} + DrawingProgram::DrawingProgram(World& initWorld): world(initWorld), components([&](){ return world.get_new_id(); }), @@ -52,6 +55,9 @@ DrawingProgram::DrawingProgram(World& initWorld): components.clientEraseCallback = [&](const CollabListType::ObjectInfoPtr& c) { compCache.erase_component(c); }; + components.clientServerLastPosShiftCallback = [&](uint64_t lastShiftPos) { + compCache.invalidate_cache_before_pos(lastShiftPos); + }; } void DrawingProgram::init_client_callbacks() { @@ -138,10 +144,9 @@ void DrawingProgram::parallel_loop_all_components(std::function& checkAgainstWorld, const SCollision::ColliderCollection& checkAgainstCam) { for(auto& c : components.client_list()) c->obj->globalCollisionCheck = false; - compCache.traverse_bvh_run_function(checkAgainstWorld.bounds, [&](SCollision::AABB* nodeAABB, const std::vector& comps) { - for(auto& c : comps) { + compCache.traverse_bvh_run_function(checkAgainstWorld.bounds, [&](DrawingProgramCache::BVHNode* node, const std::vector& comps) { + for(auto& c : comps) c->obj->globalCollisionCheck = c->obj->collides_with(world.drawData.cam.c, checkAgainstWorld, checkAgainstCam, colliderAllocated); - } return true; }); } @@ -553,7 +558,7 @@ void DrawingProgram::draw(SkCanvas* canvas, const DrawData& drawData) { else { for(auto& c : components.client_list()) c->obj->drawSetupData.shouldDraw = false; - compCache.traverse_bvh_run_function(drawData.cam.viewingAreaGenerousCollider, [&](SCollision::AABB* nodeAABB, const std::vector& comps) { + compCache.traverse_bvh_run_function(drawData.cam.viewingAreaGenerousCollider, [&](DrawingProgramCache::BVHNode* node, const std::vector& comps) { for(auto& c : comps) c->obj->calculate_draw_transform(drawData); return true; diff --git a/src/DrawingProgram/DrawingProgramCache.cpp b/src/DrawingProgram/DrawingProgramCache.cpp index 0c2a61f..b159793 100644 --- a/src/DrawingProgram/DrawingProgramCache.cpp +++ b/src/DrawingProgram/DrawingProgramCache.cpp @@ -20,6 +20,7 @@ void DrawingProgramCache::update(const std::vectorpos); } void DrawingProgramCache::erase_component(const CollabListType::ObjectInfoPtr& c) { @@ -33,6 +34,7 @@ void DrawingProgramCache::erase_component(const CollabListType::ObjectInfoPtr& c if(bvhNodePair.first) bvhNodePair.first->components.erase(bvhNodePair.second); } + invalidate_cache_before_pos(c->pos); } std::pair::iterator> DrawingProgramCache::get_bvh_node_fully_containing_recursive(BVHNode& bvhNode, DrawComponent* c) { @@ -52,13 +54,13 @@ std::pair& aabb, std::function* bounds, const std::vector& components)> f) { +void DrawingProgramCache::traverse_bvh_run_function(const SCollision::AABB& aabb, std::function& components)> f) { f(nullptr, unsortedComponents); traverse_bvh_run_function_recursive(bvhRoot, aabb, f); } -void DrawingProgramCache::traverse_bvh_run_function_recursive(BVHNode& bvhNode, const SCollision::AABB& aabb, std::function* bounds, const std::vector& components)> f) { - if(SCollision::collide(aabb, bvhNode.bounds) && f(&bvhNode.bounds, bvhNode.components)) { +void DrawingProgramCache::traverse_bvh_run_function_recursive(BVHNode& bvhNode, const SCollision::AABB& aabb, std::function& components)> f) { + if(SCollision::collide(aabb, bvhNode.bounds) && f(&bvhNode, bvhNode.components)) { for(auto& p : bvhNode.children) traverse_bvh_run_function_recursive(p, aabb, f); } @@ -68,14 +70,17 @@ void DrawingProgramCache::preupdate_component(DrawComponent* c) { auto it = std::find_if(unsortedComponents.begin(), unsortedComponents.end(), [&](const auto& comp) { return comp->obj.get() == c; }); - if(it != unsortedComponents.end()) + if(it != unsortedComponents.end()) { + invalidate_cache_before_pos((*it)->pos); return; + } else { if(!c->worldAABB.has_value()) return; auto bvhNodePair = get_bvh_node_fully_containing_recursive(bvhRoot, c); if(bvhNodePair.first) { unsortedComponents.emplace_back(*bvhNodePair.second); + invalidate_cache_before_pos((*bvhNodePair.second)->pos); bvhNodePair.first->components.erase(bvhNodePair.second); } } @@ -117,3 +122,18 @@ void DrawingProgramCache::build_bvh_node(BVHNode& node, std::vectordrawCache.value().lastDrawnComponentPlacement) { + n->drawCache = std::nullopt; + return true; + } + return false; + }); +} diff --git a/src/DrawingProgram/DrawingProgramCache.hpp b/src/DrawingProgram/DrawingProgramCache.hpp index 8cfdca7..e93b183 100644 --- a/src/DrawingProgram/DrawingProgramCache.hpp +++ b/src/DrawingProgram/DrawingProgramCache.hpp @@ -2,6 +2,7 @@ #include #include "../CollabList.hpp" #include "../DrawComponents/DrawComponent.hpp" +#include class DrawingProgramCache { public: @@ -14,16 +15,26 @@ class DrawingProgramCache { SCollision::AABB bounds; std::vector components; std::vector children; + struct DrawCacheData { + uint64_t lastDrawnComponentPlacement; + sk_sp surface; + }; + std::optional drawCache; }; - void traverse_bvh_run_function(const SCollision::AABB& aabb, std::function* bounds, const std::vector& components)> f); + std::vector nodesWithCachedSurfaces; + + void traverse_bvh_run_function(const SCollision::AABB& aabb, std::function& components)> f); // Run before actually updating the component void preupdate_component(DrawComponent* c); + + void invalidate_cache_before_pos(uint64_t placementToInvalidateAt); private: + void build(std::vector components); - void traverse_bvh_run_function_recursive(BVHNode& bvhNode, const SCollision::AABB& aabb, std::function* bounds, const std::vector& components)> f); + void traverse_bvh_run_function_recursive(BVHNode& bvhNode, const SCollision::AABB& aabb, std::function& components)> f); std::pair::iterator> get_bvh_node_fully_containing_recursive(BVHNode& bvhNode, DrawComponent* c); void build_bvh_node(BVHNode& node, std::vector components);