diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index a71abf8..cef2837 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -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() { diff --git a/src/DrawingProgram/DrawingProgramCache.cpp b/src/DrawingProgram/DrawingProgramCache.cpp index 55e3bc8..d745072 100644 --- a/src/DrawingProgram/DrawingProgramCache.cpp +++ b/src/DrawingProgram/DrawingProgramCache.cpp @@ -354,14 +354,20 @@ void DrawingProgramCache::refresh_draw_cache(const std::shared_ptrclipIRect(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> drawBounds) { +void DrawingProgramCache::draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, DrawComponentsToCanvasOptionalData optData) { uint64_t lastComponentDrawn = 0; std::vector> cachedNodesToDraw; - std::vector uncachedCompsToDraw; + struct UncachedObjectToDraw { + CollabListType::ObjectInfoPtr comp; + bool isAnUnsortedObject; + }; + std::vector uncachedCompsToDraw; - traverse_bvh_run_function(drawBounds.has_value() ? drawBounds.value() : drawData.cam.viewingAreaGenerousCollider, [&](const std::shared_ptr& node, const std::vector& comps) { + traverse_bvh_run_function(optData.drawBounds.has_value() ? optData.drawBounds.value() : drawData.cam.viewingAreaGenerousCollider, [&](const std::shared_ptr& node, const std::vector& 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::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& bvhNode) { diff --git a/src/DrawingProgram/DrawingProgramCache.hpp b/src/DrawingProgram/DrawingProgramCache.hpp index 1c1c538..d3e4c7c 100644 --- a/src/DrawingProgram/DrawingProgramCache.hpp +++ b/src/DrawingProgram/DrawingProgramCache.hpp @@ -57,7 +57,14 @@ class DrawingProgramCache { void invalidate_cache_at_aabb_before_pos(const SCollision::AABB& aabb, uint64_t placementToInvalidateAt); void invalidate_cache_at_optional_aabb_before_pos(const std::optional>& aabb, uint64_t placementToInvalidateAt); void clear(); - void draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, uint64_t* lastDrawnComponentPlacement = nullptr, std::optional> drawBounds = std::nullopt); + + struct DrawComponentsToCanvasOptionalData { + uint64_t* lastDrawnComponentPlacement = nullptr; + std::optional> drawBounds; + std::chrono::microseconds* timeToDrawUnsortedComponents = nullptr; + }; + + void draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, DrawComponentsToCanvasOptionalData optData); const std::vector& get_unsorted_component_list() const; const std::chrono::steady_clock::time_point& get_last_bvh_build_time() const; void clear_own_cached_surfaces(); diff --git a/src/DrawingProgram/DrawingProgramSelection.cpp b/src/DrawingProgram/DrawingProgramSelection.cpp index b87e1cd..8239023 100644 --- a/src/DrawingProgram/DrawingProgramSelection.cpp +++ b/src/DrawingProgram/DrawingProgramSelection.cpp @@ -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));