Started work on draw cache

This commit is contained in:
Yousef Khadadeh 2025-07-19 19:41:25 +03:00
parent 1095b91cec
commit 1e51bf660f
4 changed files with 94 additions and 14 deletions

View file

@ -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;

View file

@ -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;
});
}

View file

@ -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);