Started work on draw cache
This commit is contained in:
parent
1095b91cec
commit
1e51bf660f
4 changed files with 94 additions and 14 deletions
|
|
@ -11,6 +11,7 @@ template <typename T, typename IDType> class CollabList {
|
|||
bool syncIgnore;
|
||||
IDType id;
|
||||
T obj;
|
||||
uint64_t pos;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<ObjectInfo> ObjectInfoPtr;
|
||||
|
|
@ -22,6 +23,7 @@ template <typename T, typename IDType> class CollabList {
|
|||
std::function<void()> updateCallback;
|
||||
std::function<void(const ObjectInfoPtr& c)> clientInsertCallback;
|
||||
std::function<void(const ObjectInfoPtr& c)> clientEraseCallback;
|
||||
std::function<void(uint64_t oldPos)> clientServerLastPosShiftCallback;
|
||||
|
||||
void set_server_from_client_list() {
|
||||
serverSideList = clientSideList;
|
||||
|
|
@ -53,6 +55,7 @@ template <typename T, typename IDType> class CollabList {
|
|||
}
|
||||
|
||||
void client_erase_if(const std::function<bool(uint64_t, const std::shared_ptr<ObjectInfo>&)>& 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 <typename T, typename IDType> 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 <typename T, typename IDType> class CollabList {
|
|||
newObj->syncIgnore = true;
|
||||
newObj->id = getNewIDFunc();
|
||||
newObj->obj = item;
|
||||
uint64_t minPos = std::min<uint64_t>(static_cast<uint64_t>(clientSideList.size()), pos);
|
||||
clientSideList.insert(clientSideList.begin() + minPos, newObj);
|
||||
newObj->pos = std::min<uint64_t>(static_cast<uint64_t>(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 <typename T, typename IDType> 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 <typename T, typename IDType> class CollabList {
|
|||
newObj->syncIgnore = false;
|
||||
newObj->id = id;
|
||||
newObj->obj = item;
|
||||
newObj->pos = std::min<uint64_t>(pos, clientSideList.size());
|
||||
serverSideList.insert(serverSideList.begin() + pos, newObj);
|
||||
uint64_t minPos = std::min<uint64_t>(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<uint64_t>(clientSideList.size()); i++)
|
||||
clientSideList[i]->pos++;
|
||||
|
||||
if(clientInsertCallback)
|
||||
clientInsertCallback(newObj);
|
||||
|
||||
sync();
|
||||
return true;
|
||||
}
|
||||
|
|
@ -140,14 +159,38 @@ template <typename T, typename IDType> 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<uint64_t>(clientSideList.size()); i++)
|
||||
clientSideList[i]->pos = i;
|
||||
}
|
||||
|
||||
void sync() {
|
||||
std::vector<std::pair<uint64_t, ObjectInfoPtr>> ignoredToReinsert;
|
||||
for(uint64_t i = 0; i < clientSideList.size(); i++)
|
||||
|
|
@ -165,6 +208,7 @@ template <typename T, typename IDType> class CollabList {
|
|||
}
|
||||
if(updateCallback)
|
||||
updateCallback();
|
||||
complete_client_pos_refresh(true);
|
||||
}
|
||||
std::function<IDType()> getNewIDFunc;
|
||||
std::vector<ObjectInfoPtr> clientSideList;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@
|
|||
#include <poolstl.hpp>
|
||||
#endif
|
||||
|
||||
template <typename T> 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<void(const std::
|
|||
void DrawingProgram::check_all_collisions_base(const SCollision::ColliderCollection<WorldScalar>& checkAgainstWorld, const SCollision::ColliderCollection<float>& checkAgainstCam) {
|
||||
for(auto& c : components.client_list())
|
||||
c->obj->globalCollisionCheck = false;
|
||||
compCache.traverse_bvh_run_function(checkAgainstWorld.bounds, [&](SCollision::AABB<WorldScalar>* nodeAABB, const std::vector<CollabListType::ObjectInfoPtr>& comps) {
|
||||
for(auto& c : comps) {
|
||||
compCache.traverse_bvh_run_function(checkAgainstWorld.bounds, [&](DrawingProgramCache::BVHNode* node, const std::vector<CollabListType::ObjectInfoPtr>& 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<WorldScalar>* nodeAABB, const std::vector<CollabListType::ObjectInfoPtr>& comps) {
|
||||
compCache.traverse_bvh_run_function(drawData.cam.viewingAreaGenerousCollider, [&](DrawingProgramCache::BVHNode* node, const std::vector<CollabListType::ObjectInfoPtr>& comps) {
|
||||
for(auto& c : comps)
|
||||
c->obj->calculate_draw_transform(drawData);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ void DrawingProgramCache::update(const std::vector<CollabListType::ObjectInfoPtr
|
|||
|
||||
void DrawingProgramCache::add_component(const CollabListType::ObjectInfoPtr& c) {
|
||||
unsortedComponents.emplace_back(c);
|
||||
invalidate_cache_before_pos(c->pos);
|
||||
}
|
||||
|
||||
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<DrawingProgramCache::BVHNode*, std::vector<DrawingProgramCache::CollabListType::ObjectInfoPtr>::iterator> DrawingProgramCache::get_bvh_node_fully_containing_recursive(BVHNode& bvhNode, DrawComponent* c) {
|
||||
|
|
@ -52,13 +54,13 @@ std::pair<DrawingProgramCache::BVHNode*, std::vector<DrawingProgramCache::Collab
|
|||
return {nullptr, bvhNode.components.end()};
|
||||
}
|
||||
|
||||
void DrawingProgramCache::traverse_bvh_run_function(const SCollision::AABB<WorldScalar>& aabb, std::function<bool(SCollision::AABB<WorldScalar>* bounds, const std::vector<CollabListType::ObjectInfoPtr>& components)> f) {
|
||||
void DrawingProgramCache::traverse_bvh_run_function(const SCollision::AABB<WorldScalar>& aabb, std::function<bool(BVHNode* node, const std::vector<CollabListType::ObjectInfoPtr>& 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<WorldScalar>& aabb, std::function<bool(SCollision::AABB<WorldScalar>* bounds, const std::vector<CollabListType::ObjectInfoPtr>& 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<WorldScalar>& aabb, std::function<bool(BVHNode* node, const std::vector<CollabListType::ObjectInfoPtr>& 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::vector<CollabListTy
|
|||
build_bvh_node(node.children.emplace_back(), p);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawingProgramCache::invalidate_cache_before_pos(uint64_t placementToInvalidateAt) {
|
||||
// We could use worldAABB of component to invalidate specific areas. However, that comes with some issues:
|
||||
// - The AABB couldve been changed from the last frame, so the current worldAABB doesnt actually represent what we should update
|
||||
// - The worldAABB might not be calculated yet, or mightve been invalidated (worldAABB = nullopt)
|
||||
// For now, we will ignore worldAABB and just clear cache by placement in list
|
||||
|
||||
std::erase_if(nodesWithCachedSurfaces, [&](auto& n) {
|
||||
if(placementToInvalidateAt <= n->drawCache.value().lastDrawnComponentPlacement) {
|
||||
n->drawCache = std::nullopt;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include <vector>
|
||||
#include "../CollabList.hpp"
|
||||
#include "../DrawComponents/DrawComponent.hpp"
|
||||
#include <include/core/SkSurface.h>
|
||||
|
||||
class DrawingProgramCache {
|
||||
public:
|
||||
|
|
@ -14,16 +15,26 @@ class DrawingProgramCache {
|
|||
SCollision::AABB<WorldScalar> bounds;
|
||||
std::vector<CollabListType::ObjectInfoPtr> components;
|
||||
std::vector<BVHNode> children;
|
||||
struct DrawCacheData {
|
||||
uint64_t lastDrawnComponentPlacement;
|
||||
sk_sp<SkSurface> surface;
|
||||
};
|
||||
std::optional<DrawCacheData> drawCache;
|
||||
};
|
||||
|
||||
void traverse_bvh_run_function(const SCollision::AABB<WorldScalar>& aabb, std::function<bool(SCollision::AABB<WorldScalar>* bounds, const std::vector<CollabListType::ObjectInfoPtr>& components)> f);
|
||||
std::vector<BVHNode*> nodesWithCachedSurfaces;
|
||||
|
||||
void traverse_bvh_run_function(const SCollision::AABB<WorldScalar>& aabb, std::function<bool(BVHNode* node, const std::vector<CollabListType::ObjectInfoPtr>& 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<CollabListType::ObjectInfoPtr> components);
|
||||
|
||||
void traverse_bvh_run_function_recursive(BVHNode& bvhNode, const SCollision::AABB<WorldScalar>& aabb, std::function<bool(SCollision::AABB<WorldScalar>* bounds, const std::vector<CollabListType::ObjectInfoPtr>& components)> f);
|
||||
void traverse_bvh_run_function_recursive(BVHNode& bvhNode, const SCollision::AABB<WorldScalar>& aabb, std::function<bool(BVHNode* node, const std::vector<CollabListType::ObjectInfoPtr>& components)> f);
|
||||
std::pair<DrawingProgramCache::BVHNode*, std::vector<DrawingProgramCache::CollabListType::ObjectInfoPtr>::iterator> get_bvh_node_fully_containing_recursive(BVHNode& bvhNode, DrawComponent* c);
|
||||
|
||||
void build_bvh_node(BVHNode& node, std::vector<CollabListType::ObjectInfoPtr> components);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue