Reorganize cache code and call flushAndSubmit in main
This commit is contained in:
parent
f46d25b8e6
commit
f6c4eeb9f3
6 changed files with 43 additions and 42 deletions
|
|
@ -36,9 +36,6 @@
|
|||
|
||||
#include "Tools/EraserTool.hpp"
|
||||
|
||||
size_t DrawingProgram::MILLISECOND_FRAME_TIME_TO_FORCE_CACHE_REFRESH = 33; // Around 30FPS
|
||||
size_t DrawingProgram::MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH = 400;
|
||||
|
||||
DrawingProgram::DrawingProgram(World& initWorld):
|
||||
world(initWorld),
|
||||
drawCache(*this),
|
||||
|
|
@ -238,23 +235,6 @@ void DrawingProgram::modify_grid(const NetworkingObjects::NetObjWeakPtr<WorldGri
|
|||
}
|
||||
|
||||
void DrawingProgram::update() {
|
||||
if(world.main.window.lastFrameTime > std::chrono::milliseconds(MILLISECOND_FRAME_TIME_TO_FORCE_CACHE_REFRESH)) {
|
||||
if(!badFrametimeTimePoint)
|
||||
badFrametimeTimePoint = std::chrono::steady_clock::now();
|
||||
else if(unorderedObjectsExistTimePoint && std::chrono::steady_clock::now() - badFrametimeTimePoint.value() >= std::chrono::milliseconds(MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH) && std::chrono::steady_clock::now() - unorderedObjectsExistTimePoint.value() >= std::chrono::milliseconds(MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH)) {
|
||||
rebuild_cache();
|
||||
unorderedObjectsExistTimePoint = std::nullopt;
|
||||
badFrametimeTimePoint = std::nullopt;
|
||||
}
|
||||
}
|
||||
else
|
||||
badFrametimeTimePoint = std::nullopt;
|
||||
|
||||
if(!drawCache.unsorted_components_exist())
|
||||
unorderedObjectsExistTimePoint = std::nullopt;
|
||||
else if(!unorderedObjectsExistTimePoint)
|
||||
unorderedObjectsExistTimePoint = std::chrono::steady_clock::now();
|
||||
|
||||
tool_temporary_switch_update();
|
||||
|
||||
controls.cursorHoveringOverCanvas = !world.main.toolbar.io->hoverObstructed;
|
||||
|
|
@ -340,7 +320,7 @@ void DrawingProgram::update() {
|
|||
update_downloading_dropped_files();
|
||||
check_updateable_components();
|
||||
|
||||
if(drawCache.should_rebuild())
|
||||
if(drawCache.check_rebuild_needed_from_framerate() || drawCache.should_rebuild())
|
||||
rebuild_cache();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ class World;
|
|||
|
||||
class DrawingProgram {
|
||||
public:
|
||||
static size_t MILLISECOND_FRAME_TIME_TO_FORCE_CACHE_REFRESH;
|
||||
static size_t MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH;
|
||||
DrawingProgram(World& initWorld);
|
||||
void server_init_no_file();
|
||||
void toolbar_gui();
|
||||
|
|
@ -65,8 +63,6 @@ class DrawingProgram {
|
|||
void check_updateable_components();
|
||||
void update_downloading_dropped_files();
|
||||
|
||||
std::optional<std::chrono::steady_clock::time_point> badFrametimeTimePoint;
|
||||
std::optional<std::chrono::steady_clock::time_point> unorderedObjectsExistTimePoint;
|
||||
|
||||
bool selection_action_menu(Vector2f popupPos);
|
||||
void rebuild_cache();
|
||||
|
|
|
|||
|
|
@ -13,8 +13,14 @@
|
|||
|
||||
size_t DrawingProgramCache::MINIMUM_COMPONENTS_TO_START_REBUILD = 1000;
|
||||
size_t DrawingProgramCache::MAXIMUM_COMPONENTS_IN_SINGLE_NODE = 50;
|
||||
size_t DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES = 40;
|
||||
#ifdef __EMSCRIPTEN__
|
||||
size_t DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES = 40; // Use less VRAM in web build
|
||||
#else
|
||||
size_t DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES = 96;
|
||||
#endif
|
||||
size_t DrawingProgramCache::CACHE_NODE_RESOLUTION = 2048;
|
||||
size_t DrawingProgramCache::MILLISECOND_FRAME_TIME_TO_FORCE_CACHE_REFRESH = 33; // Around 30FPS
|
||||
size_t DrawingProgramCache::MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH = 5000; // Should be a bit long to prevent objects that are being updated, like brush strokes, from constantly refreshing the cache.
|
||||
|
||||
std::unordered_map<std::shared_ptr<DrawingProgramCacheBVHNode>, DrawingProgramCache::NodeCache> DrawingProgramCache::nodeCacheMap;
|
||||
DrawingProgramCache::WindowCache DrawingProgramCache::windowCache;
|
||||
|
|
@ -64,8 +70,25 @@ bool DrawingProgramCache::should_rebuild() const {
|
|||
return (unsortedComponents.size() >= MINIMUM_COMPONENTS_TO_START_REBUILD);
|
||||
}
|
||||
|
||||
bool DrawingProgramCache::unsorted_components_exist() const {
|
||||
return !unsortedComponents.empty();
|
||||
bool DrawingProgramCache::check_rebuild_needed_from_framerate() {
|
||||
if(drawP.world.main.window.lastFrameTime > std::chrono::milliseconds(MILLISECOND_FRAME_TIME_TO_FORCE_CACHE_REFRESH)) {
|
||||
if(!badFrametimeTimePoint)
|
||||
badFrametimeTimePoint = std::chrono::steady_clock::now();
|
||||
else if(unorderedObjectsExistTimePoint && std::chrono::steady_clock::now() - badFrametimeTimePoint.value() >= std::chrono::milliseconds(MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH) && std::chrono::steady_clock::now() - unorderedObjectsExistTimePoint.value() >= std::chrono::milliseconds(MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH)) {
|
||||
unorderedObjectsExistTimePoint = std::nullopt;
|
||||
badFrametimeTimePoint = std::nullopt;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
badFrametimeTimePoint = std::nullopt;
|
||||
|
||||
if(unsortedComponents.empty())
|
||||
unorderedObjectsExistTimePoint = std::nullopt;
|
||||
else if(!unorderedObjectsExistTimePoint)
|
||||
unorderedObjectsExistTimePoint = std::chrono::steady_clock::now();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void DrawingProgramCache::build(const std::unordered_set<CanvasComponentContainer::ObjInfo*>& objsToExclude) {
|
||||
|
|
@ -202,18 +225,13 @@ void DrawingProgramCache::build_bvh_node_coords_and_resolution(DrawingProgramCac
|
|||
}
|
||||
|
||||
void DrawingProgramCache::refresh_all_draw_cache(const DrawData& drawData) {
|
||||
std::deque<std::shared_ptr<DrawingProgramCacheBVHNode>> nodeFlatList; // We want to render children before parents, so that parents can make use of the cached children
|
||||
traverse_bvh_run_function(drawData.cam.viewingAreaGenerousCollider, [&](std::shared_ptr<DrawingProgramCacheBVHNode> node) {
|
||||
if(node && node->coords.inverseScale <= drawData.cam.c.inverseScale) {
|
||||
auto it = nodeCacheMap.find(node);
|
||||
if((it == nodeCacheMap.end()) || it->second.invalidBounds.has_value())
|
||||
nodeFlatList.emplace_front(node);
|
||||
refresh_draw_cache(node, drawData);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if(!nodeFlatList.empty())
|
||||
refresh_draw_cache(nodeFlatList.front(), drawData);
|
||||
}
|
||||
|
||||
void DrawingProgramCache::traverse_bvh_run_function(const SCollision::AABB<WorldScalar>& aabb, std::function<bool(const std::shared_ptr<DrawingProgramCacheBVHNode>& node)> f) {
|
||||
|
|
@ -243,6 +261,8 @@ void DrawingProgramCache::refresh_draw_cache(const std::shared_ptr<DrawingProgra
|
|||
auto bvhNodeCacheIt = nodeCacheMap.find(bvhNode);
|
||||
if(bvhNodeCacheIt != nodeCacheMap.end()) {
|
||||
nodeCache = bvhNodeCacheIt->second;
|
||||
if(!nodeCache.invalidBounds.has_value()) // Node is cached already, and doesn't have invalid areas, so there's nothing to do
|
||||
return;
|
||||
nodeCacheMap.erase(bvhNode); // Ensure nodeCache is erased, so that the draw_components_to_canvas function doesnt use it while drawing
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ class DrawingProgramCache {
|
|||
static size_t MAXIMUM_COMPONENTS_IN_SINGLE_NODE;
|
||||
static size_t MAXIMUM_DRAW_CACHE_SURFACES;
|
||||
static size_t CACHE_NODE_RESOLUTION;
|
||||
static size_t MILLISECOND_FRAME_TIME_TO_FORCE_CACHE_REFRESH;
|
||||
static size_t MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH;
|
||||
|
||||
DrawingProgramCache(DrawingProgram& initDrawP);
|
||||
void add_component(CanvasComponentContainer::ObjInfo* c);
|
||||
|
|
@ -32,9 +34,9 @@ class DrawingProgramCache {
|
|||
void node_loop_erase_if_components(const std::shared_ptr<DrawingProgramCacheBVHNode>& bvhNode, std::function<bool(CanvasComponentContainer::ObjInfo* comp)> f);
|
||||
void node_loop_components(const std::shared_ptr<DrawingProgramCacheBVHNode>& bvhNode, std::function<void(CanvasComponentContainer::ObjInfo* comp)> f);
|
||||
bool should_rebuild() const;
|
||||
bool check_rebuild_needed_from_framerate();
|
||||
void update_and_draw_cached_canvas(SkCanvas* canvas, const DrawData& drawData);
|
||||
void draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, const std::optional<SCollision::AABB<WorldScalar>>& drawBounds);
|
||||
bool unsorted_components_exist() const;
|
||||
void invalidate_cache_at_aabb(const SCollision::AABB<WorldScalar>& aabb);
|
||||
void set_clear_window_cache();
|
||||
|
||||
|
|
@ -69,6 +71,9 @@ class DrawingProgramCache {
|
|||
void draw_cache_image_to_canvas(SkCanvas* canvas, const DrawData& drawData, const std::shared_ptr<DrawingProgramCacheBVHNode>& bvhNode);
|
||||
void recursive_draw_layer_item_to_canvas(const DrawingProgramLayerListItem& layerListItem, SkCanvas* canvas, const DrawData& drawData, const std::optional<SCollision::AABB<WorldScalar>>& drawBounds, const std::vector<std::shared_ptr<DrawingProgramCacheBVHNode>>& nodesToDraw);
|
||||
|
||||
std::optional<std::chrono::steady_clock::time_point> badFrametimeTimePoint;
|
||||
std::optional<std::chrono::steady_clock::time_point> unorderedObjectsExistTimePoint;
|
||||
|
||||
std::shared_ptr<DrawingProgramCacheBVHNode> bvhRoot;
|
||||
std::vector<CanvasComponentContainer::ObjInfo*> unsortedComponents;
|
||||
DrawingProgram& drawP;
|
||||
|
|
|
|||
|
|
@ -285,8 +285,8 @@ nlohmann::json Toolbar::get_config_json() {
|
|||
debugJson["maxCacheNodes"] = DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES;
|
||||
debugJson["maxComponentsInNode"] = DrawingProgramCache::MAXIMUM_COMPONENTS_IN_SINGLE_NODE;
|
||||
debugJson["componentCountToForceCacheRebuild"] = DrawingProgramCache::MINIMUM_COMPONENTS_TO_START_REBUILD;
|
||||
debugJson["maximumFrameTimeToForceCacheRebuild"] = DrawingProgram::MILLISECOND_FRAME_TIME_TO_FORCE_CACHE_REFRESH;
|
||||
debugJson["millisecondMinimumTimeToCheckForCacheRebuild"] = DrawingProgram::MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH;
|
||||
debugJson["maximumFrameTimeToForceCacheRebuild"] = DrawingProgramCache::MILLISECOND_FRAME_TIME_TO_FORCE_CACHE_REFRESH;
|
||||
debugJson["millisecondMinimumTimeToCheckForCacheRebuild"] = DrawingProgramCache::MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH;
|
||||
toRet["debug"] = debugJson;
|
||||
|
||||
return toRet;
|
||||
|
|
@ -354,8 +354,8 @@ void Toolbar::set_config_json(const nlohmann::json& j, VersionNumber version) {
|
|||
try{j.at("debug").at("maxCacheNodes").get_to(DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES);} catch(...) {}
|
||||
try{j.at("debug").at("maxComponentsInNode").get_to(DrawingProgramCache::MAXIMUM_COMPONENTS_IN_SINGLE_NODE);} catch(...) {}
|
||||
try{j.at("debug").at("componentCountToForceCacheRebuild").get_to(DrawingProgramCache::MINIMUM_COMPONENTS_TO_START_REBUILD);} catch(...) {}
|
||||
try{j.at("debug").at("maximumFrameTimeToForceCacheRebuild").get_to(DrawingProgram::MILLISECOND_FRAME_TIME_TO_FORCE_CACHE_REFRESH);} catch(...) {}
|
||||
try{j.at("debug").at("millisecondMinimumTimeToCheckForCacheRebuild").get_to(DrawingProgram::MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH);} catch(...) {}
|
||||
try{j.at("debug").at("maximumFrameTimeToForceCacheRebuild").get_to(DrawingProgramCache::MILLISECOND_FRAME_TIME_TO_FORCE_CACHE_REFRESH);} catch(...) {}
|
||||
try{j.at("debug").at("millisecondMinimumTimeToCheckForCacheRebuild").get_to(DrawingProgramCache::MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH);} catch(...) {}
|
||||
|
||||
main.update_display_names();
|
||||
}
|
||||
|
|
@ -1860,8 +1860,8 @@ void Toolbar::options_menu() {
|
|||
gui.text_label_light("Cache max VRAM consumption (MB): " + std::to_string(cacheVRAMConsumptionInMB));
|
||||
gui.input_scalar_field<size_t>("max components in node", "Maximum components in single node", &DrawingProgramCache::MAXIMUM_COMPONENTS_IN_SINGLE_NODE, 2, 10000);
|
||||
gui.input_scalar_field<size_t>("components to force cache rebuild", "Number of components to force cache rebuild", &DrawingProgramCache::MINIMUM_COMPONENTS_TO_START_REBUILD, 1, 1000000);
|
||||
gui.input_scalar_field<size_t>("maximum frame time to force cache rebuild", "Maximum frame time to force cache rebuild (ms)", &DrawingProgram::MILLISECOND_FRAME_TIME_TO_FORCE_CACHE_REFRESH, 1, 1000000);
|
||||
gui.input_scalar_field<size_t>("minimum time to force cache rebuild", "Minimum time to check cache rebuild (ms)", &DrawingProgram::MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH, 1, 1000000);
|
||||
gui.input_scalar_field<size_t>("maximum frame time to force cache rebuild", "Maximum frame time to force cache rebuild (ms)", &DrawingProgramCache::MILLISECOND_FRAME_TIME_TO_FORCE_CACHE_REFRESH, 1, 1000000);
|
||||
gui.input_scalar_field<size_t>("minimum time to force cache rebuild", "Minimum time to check cache rebuild (ms)", &DrawingProgramCache::MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH, 1, 1000000);
|
||||
gui.pop_id();
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -608,7 +608,7 @@ SDL_AppResult SDL_AppIterate(void *appstate) {
|
|||
|
||||
mS.canvas->drawImage(mS.intermediateSurface->makeTemporaryImage(), 0, 0);
|
||||
|
||||
mS.ctx->flush();
|
||||
mS.ctx->flushAndSubmit();
|
||||
|
||||
SDL_GL_SwapWindow(mS.window);
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue