Rebuild cache when framerate drops significantly from uncached objects
This commit is contained in:
parent
d91c7e987f
commit
0b72dd4ea9
4 changed files with 54 additions and 19 deletions
|
|
@ -564,6 +564,8 @@ void DrawingProgram::write_to_file(cereal::PortableBinaryOutputArchive& a) {
|
|||
}
|
||||
|
||||
void DrawingProgram::draw(SkCanvas* canvas, const DrawData& drawData) {
|
||||
std::chrono::microseconds timeToDrawUnsortedComponents(0);
|
||||
|
||||
if(drawData.dontUseDrawProgCache) {
|
||||
parallel_loop_all_components([&](auto& c) {
|
||||
c->obj->calculate_draw_transform(drawData);
|
||||
|
|
@ -577,7 +579,9 @@ void DrawingProgram::draw(SkCanvas* canvas, const DrawData& drawData) {
|
|||
canvas->saveLayer(nullptr, nullptr);
|
||||
canvas->clear(SkColor4f{0.0f, 0.0f, 0.0f, 0.0f});
|
||||
compCache.refresh_all_draw_cache(drawData);
|
||||
compCache.draw_components_to_canvas(canvas, drawData);
|
||||
compCache.draw_components_to_canvas(canvas, drawData, {
|
||||
.timeToDrawUnsortedComponents = &timeToDrawUnsortedComponents
|
||||
});
|
||||
canvas->saveLayer(nullptr, nullptr);
|
||||
selection.draw_components(canvas, drawData);
|
||||
canvas->restore();
|
||||
|
|
@ -586,6 +590,9 @@ void DrawingProgram::draw(SkCanvas* canvas, const DrawData& drawData) {
|
|||
}
|
||||
|
||||
drawTool->draw(canvas, drawData);
|
||||
|
||||
if(timeToDrawUnsortedComponents >= std::chrono::microseconds(16000))
|
||||
force_rebuild_cache();
|
||||
}
|
||||
|
||||
Vector4f* DrawingProgram::get_foreground_color_ptr() {
|
||||
|
|
|
|||
|
|
@ -354,14 +354,20 @@ void DrawingProgramCache::refresh_draw_cache(const std::shared_ptr<DrawingProgra
|
|||
cacheCanvas->clipIRect(clipRect);
|
||||
cacheCanvas->clear(SkColor4f{0, 0, 0, 0});
|
||||
uint64_t lastDrawnComponentPlacementNew = 0;
|
||||
draw_components_to_canvas(cacheCanvas, cacheDrawData, &lastDrawnComponentPlacementNew, clipRectBoundAABBWorld);
|
||||
draw_components_to_canvas(cacheCanvas, cacheDrawData, {
|
||||
.lastDrawnComponentPlacement = &lastDrawnComponentPlacementNew,
|
||||
.drawBounds = clipRectBoundAABBWorld
|
||||
});
|
||||
drawCache.lastDrawnComponentPlacement = std::max(lastDrawnComponentPlacementNew, drawCache.lastDrawnComponentPlacement);
|
||||
cacheCanvas->restore();
|
||||
drawCache.invalidBounds = std::nullopt;
|
||||
}
|
||||
else {
|
||||
cacheCanvas->clear(SkColor4f{0, 0, 0, 0});
|
||||
draw_components_to_canvas(cacheCanvas, cacheDrawData, &drawCache.lastDrawnComponentPlacement, drawCache.invalidBounds);
|
||||
draw_components_to_canvas(cacheCanvas, cacheDrawData, {
|
||||
.lastDrawnComponentPlacement = &drawCache.lastDrawnComponentPlacement,
|
||||
.drawBounds = drawCache.invalidBounds
|
||||
});
|
||||
}
|
||||
|
||||
drawCache.lastRenderTime = std::chrono::steady_clock::now();
|
||||
|
|
@ -382,49 +388,64 @@ void DrawingProgramCache::refresh_draw_cache(const std::shared_ptr<DrawingProgra
|
|||
nodesWithCachedSurfaces.emplace(bvhNode);
|
||||
}
|
||||
|
||||
void DrawingProgramCache::draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, uint64_t* lastDrawnComponentPlacement, std::optional<SCollision::AABB<WorldScalar>> drawBounds) {
|
||||
void DrawingProgramCache::draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, DrawComponentsToCanvasOptionalData optData) {
|
||||
uint64_t lastComponentDrawn = 0;
|
||||
|
||||
std::vector<std::shared_ptr<DrawingProgramCacheBVHNode>> cachedNodesToDraw;
|
||||
std::vector<CollabListType::ObjectInfoPtr> uncachedCompsToDraw;
|
||||
struct UncachedObjectToDraw {
|
||||
CollabListType::ObjectInfoPtr comp;
|
||||
bool isAnUnsortedObject;
|
||||
};
|
||||
std::vector<UncachedObjectToDraw> uncachedCompsToDraw;
|
||||
|
||||
traverse_bvh_run_function(drawBounds.has_value() ? drawBounds.value() : drawData.cam.viewingAreaGenerousCollider, [&](const std::shared_ptr<DrawingProgramCacheBVHNode>& node, const std::vector<CollabListType::ObjectInfoPtr>& comps) {
|
||||
traverse_bvh_run_function(optData.drawBounds.has_value() ? optData.drawBounds.value() : drawData.cam.viewingAreaGenerousCollider, [&](const std::shared_ptr<DrawingProgramCacheBVHNode>& node, const std::vector<CollabListType::ObjectInfoPtr>& comps) {
|
||||
if(node && node->drawCache && !node->drawCache.value().invalidBounds && node->coords.inverseScale <= drawData.cam.c.inverseScale) {
|
||||
cachedNodesToDraw.emplace_back(node);
|
||||
return false;
|
||||
}
|
||||
|
||||
for(auto& c : comps)
|
||||
for(auto& c : comps) {
|
||||
c->obj->calculate_draw_transform(drawData);
|
||||
|
||||
uncachedCompsToDraw.insert(uncachedCompsToDraw.end(), comps.begin(), comps.end());
|
||||
if(c->obj->drawSetupData.shouldDraw)
|
||||
uncachedCompsToDraw.emplace_back(c, !node);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
std::sort(uncachedCompsToDraw.begin(), uncachedCompsToDraw.end(), [](auto& a, auto& b) {
|
||||
return a->pos < b->pos;
|
||||
return a.comp->pos < b.comp->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) {
|
||||
|
||||
std::chrono::microseconds unsortedCompDrawTime(0);
|
||||
|
||||
for(auto& uncachedComp : uncachedCompsToDraw) {
|
||||
for(;;) {
|
||||
if(nextCacheToRender >= cachedNodesToDraw.size() || c->pos <= cachedNodesToDraw[nextCacheToRender]->drawCache.value().lastDrawnComponentPlacement)
|
||||
if(nextCacheToRender >= cachedNodesToDraw.size() || uncachedComp.comp->pos <= cachedNodesToDraw[nextCacheToRender]->drawCache.value().lastDrawnComponentPlacement)
|
||||
break;
|
||||
lastComponentDrawn = std::max(lastComponentDrawn, draw_cache_image_to_canvas(canvas, drawData, cachedNodesToDraw[nextCacheToRender]));
|
||||
nextCacheToRender++;
|
||||
}
|
||||
c->obj->draw(canvas, drawData);
|
||||
c->obj->drawSetupData.shouldDraw = false;
|
||||
lastComponentDrawn = std::max(lastComponentDrawn, c->pos);
|
||||
std::chrono::time_point drawStartTime = std::chrono::steady_clock::now();
|
||||
uncachedComp.comp->obj->draw(canvas, drawData);
|
||||
if(uncachedComp.isAnUnsortedObject)
|
||||
unsortedCompDrawTime += std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - drawStartTime);
|
||||
|
||||
uncachedComp.comp->obj->drawSetupData.shouldDraw = false;
|
||||
lastComponentDrawn = std::max(lastComponentDrawn, uncachedComp.comp->pos);
|
||||
}
|
||||
for(;nextCacheToRender < cachedNodesToDraw.size(); nextCacheToRender++)
|
||||
lastComponentDrawn = std::max(lastComponentDrawn, draw_cache_image_to_canvas(canvas, drawData, cachedNodesToDraw[nextCacheToRender]));
|
||||
|
||||
if(lastDrawnComponentPlacement)
|
||||
*lastDrawnComponentPlacement = lastComponentDrawn;
|
||||
if(optData.lastDrawnComponentPlacement)
|
||||
*optData.lastDrawnComponentPlacement = lastComponentDrawn;
|
||||
|
||||
if(optData.timeToDrawUnsortedComponents)
|
||||
*optData.timeToDrawUnsortedComponents = unsortedCompDrawTime;
|
||||
}
|
||||
|
||||
uint64_t DrawingProgramCache::draw_cache_image_to_canvas(SkCanvas* canvas, const DrawData& drawData, const std::shared_ptr<DrawingProgramCacheBVHNode>& bvhNode) {
|
||||
|
|
|
|||
|
|
@ -57,7 +57,14 @@ class DrawingProgramCache {
|
|||
void invalidate_cache_at_aabb_before_pos(const SCollision::AABB<WorldScalar>& aabb, uint64_t placementToInvalidateAt);
|
||||
void invalidate_cache_at_optional_aabb_before_pos(const std::optional<SCollision::AABB<WorldScalar>>& aabb, uint64_t placementToInvalidateAt);
|
||||
void clear();
|
||||
void draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, uint64_t* lastDrawnComponentPlacement = nullptr, std::optional<SCollision::AABB<WorldScalar>> drawBounds = std::nullopt);
|
||||
|
||||
struct DrawComponentsToCanvasOptionalData {
|
||||
uint64_t* lastDrawnComponentPlacement = nullptr;
|
||||
std::optional<SCollision::AABB<WorldScalar>> drawBounds;
|
||||
std::chrono::microseconds* timeToDrawUnsortedComponents = nullptr;
|
||||
};
|
||||
|
||||
void draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, DrawComponentsToCanvasOptionalData optData);
|
||||
const std::vector<CollabListType::ObjectInfoPtr>& get_unsorted_component_list() const;
|
||||
const std::chrono::steady_clock::time_point& get_last_bvh_build_time() const;
|
||||
void clear_own_cached_surfaces();
|
||||
|
|
|
|||
|
|
@ -453,7 +453,7 @@ void DrawingProgramSelection::draw_components(SkCanvas* canvas, const DrawData&
|
|||
if(!surface)
|
||||
throw std::runtime_error("[DrawingProgramSelection::draw_components] Could not make temporary surface");
|
||||
|
||||
cache.draw_components_to_canvas(surface->getCanvas(), selectionDrawData);
|
||||
cache.draw_components_to_canvas(surface->getCanvas(), selectionDrawData, {});
|
||||
|
||||
SkPaint glowBlurP;
|
||||
glowBlurP.setImageFilter(SkImageFilters::Blur(5, 5, nullptr));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue