From 2e9e8eaf8b55f604b208b6ae12e1ccaef17c5837 Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Sat, 24 Jan 2026 12:31:55 +0300 Subject: [PATCH] Added cache related settings --- src/DrawingProgram/DrawingProgram.cpp | 7 ++-- src/DrawingProgram/DrawingProgram.hpp | 2 ++ src/DrawingProgram/DrawingProgramCache.cpp | 15 ++++---- src/DrawingProgram/DrawingProgramCache.hpp | 7 ++-- src/Toolbar.cpp | 40 ++++++++++++++++++---- 5 files changed, 54 insertions(+), 17 deletions(-) diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index d4f7100..da23391 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -36,6 +36,9 @@ #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), @@ -233,10 +236,10 @@ void DrawingProgram::modify_grid(const NetworkingObjects::NetObjWeakPtr std::chrono::milliseconds(33)) { // Around 30FPS + 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::seconds(5) && std::chrono::steady_clock::now() - unorderedObjectsExistTimePoint.value() >= std::chrono::seconds(5)) { + 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; diff --git a/src/DrawingProgram/DrawingProgram.hpp b/src/DrawingProgram/DrawingProgram.hpp index f5845e0..ed44a03 100644 --- a/src/DrawingProgram/DrawingProgram.hpp +++ b/src/DrawingProgram/DrawingProgram.hpp @@ -22,6 +22,8 @@ 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(); diff --git a/src/DrawingProgram/DrawingProgramCache.cpp b/src/DrawingProgram/DrawingProgramCache.cpp index 2332bbf..34fd12a 100644 --- a/src/DrawingProgram/DrawingProgramCache.cpp +++ b/src/DrawingProgram/DrawingProgramCache.cpp @@ -11,6 +11,11 @@ #include #endif +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; +size_t DrawingProgramCache::CACHE_NODE_RESOLUTION = 2048; + std::unordered_map, DrawingProgramCache::NodeCache> DrawingProgramCache::nodeCacheMap; DrawingProgramCache::WindowCache DrawingProgramCache::windowCache; @@ -178,16 +183,14 @@ void DrawingProgramCache::build_bvh_node_coords_and_resolution(DrawingProgramCac // - We dont have to recalculate it every time we refresh the cache // - Some of the data here is needed to determine whether to generate the cache in the first place - constexpr int MAX_DIMENSION_RESOLUTION = 2048; - WorldVec cacheBoundDim = node.bounds.dim(); if(cacheBoundDim.x() > cacheBoundDim.y()) { - node.resolution.x() = MAX_DIMENSION_RESOLUTION; - node.resolution.y() = MAX_DIMENSION_RESOLUTION * static_cast(cacheBoundDim.y() / cacheBoundDim.x()); + node.resolution.x() = CACHE_NODE_RESOLUTION; + node.resolution.y() = CACHE_NODE_RESOLUTION * static_cast(cacheBoundDim.y() / cacheBoundDim.x()); } else { - node.resolution.y() = MAX_DIMENSION_RESOLUTION; - node.resolution.x() = MAX_DIMENSION_RESOLUTION * static_cast(cacheBoundDim.x() / cacheBoundDim.y()); + node.resolution.y() = CACHE_NODE_RESOLUTION; + node.resolution.x() = CACHE_NODE_RESOLUTION * static_cast(cacheBoundDim.x() / cacheBoundDim.y()); } node.coords.rotation = 0.0; node.coords.pos = node.bounds.min; diff --git a/src/DrawingProgram/DrawingProgramCache.hpp b/src/DrawingProgram/DrawingProgramCache.hpp index ea4ad72..c7ebe45 100644 --- a/src/DrawingProgram/DrawingProgramCache.hpp +++ b/src/DrawingProgram/DrawingProgramCache.hpp @@ -15,9 +15,10 @@ struct DrawingProgramCacheBVHNode { class DrawingProgramCache { public: - static constexpr size_t MINIMUM_COMPONENTS_TO_START_REBUILD = 1000; - static constexpr size_t MAXIMUM_COMPONENTS_IN_SINGLE_NODE = 50; - static constexpr size_t MAXIMUM_DRAW_CACHE_SURFACES = 40; + static size_t MINIMUM_COMPONENTS_TO_START_REBUILD; + static size_t MAXIMUM_COMPONENTS_IN_SINGLE_NODE; + static size_t MAXIMUM_DRAW_CACHE_SURFACES; + static size_t CACHE_NODE_RESOLUTION; DrawingProgramCache(DrawingProgram& initDrawP); void add_component(CanvasComponentContainer::ObjInfo* c); diff --git a/src/Toolbar.cpp b/src/Toolbar.cpp index 83a4157..3804879 100644 --- a/src/Toolbar.cpp +++ b/src/Toolbar.cpp @@ -258,11 +258,9 @@ nlohmann::json Toolbar::get_config_json() { #ifndef __EMSCRIPTEN__ toRet["applyDisplayScale"] = main.window.applyDisplayScale; #endif - toRet["showPerformance"] = showPerformance; toRet["displayName"] = main.displayName; toRet["useNativeFilePicker"] = useNativeFilePicker; toRet["themeInUse"] = themeData.themeCurrentlyLoaded; - toRet["jumpTransitionEasing"] = jumpTransitionEasing; toRet["defaultCanvasBackgroundColor"] = main.defaultCanvasBackgroundColor; toRet["flipZoomToolDirection"] = flipZoomToolDirection; #ifndef __EMSCRIPTEN__ @@ -277,9 +275,20 @@ nlohmann::json Toolbar::get_config_json() { tablet["ignoreMouseMovementWhenPenInProximity"] = tabletOptions.ignoreMouseMovementWhenPenInProximity; tablet["brushMinimumSize"] = tabletOptions.brushMinimumSize; tablet["zoomWhilePenDownAndButtonHeld"] = tabletOptions.zoomWhilePenDownAndButtonHeld; - toRet["tablet"] = tablet; + json debugJson; + debugJson["showPerformance"] = showPerformance; + debugJson["fpsLimit"] = main.fpsLimit; + debugJson["jumpTransitionEasing"] = jumpTransitionEasing; + debugJson["cacheNodeResolution"] = DrawingProgramCache::CACHE_NODE_RESOLUTION; + 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; + toRet["debug"] = debugJson; + return toRet; } @@ -308,7 +317,6 @@ void Toolbar::set_config_json(const nlohmann::json& j, VersionNumber version) { main.input.keyAssignments = main.input.defaultKeyAssignments; } try{j.at("displayName").get_to(main.displayName);} catch(...) {} - try{j.at("jumpTransitionTime").get_to(jumpTransitionTime);} catch(...) {} try{j.at("dragZoomSpeed").get_to(dragZoomSpeed);} catch(...) {} try{j.at("scrollZoomSpeed").get_to(scrollZoomSpeed);} catch(...) {} try { @@ -322,10 +330,8 @@ void Toolbar::set_config_json(const nlohmann::json& j, VersionNumber version) { try{j.at("applyDisplayScale").get_to(main.window.applyDisplayScale);} catch(...) {} #endif try{j.at("guiScale").get_to(guiScale);} catch(...) {} - try{j.at("showPerformance").get_to(showPerformance);} catch(...) {} try{j.at("useNativeFilePicker").get_to(useNativeFilePicker);} catch(...) {} try{j.at("themeInUse").get_to(themeData.themeCurrentlyLoaded);} catch(...) {} - try{j.at("jumpTransitionEasing").get_to(jumpTransitionEasing);} catch(...) {} if(version >= VersionNumber(0, 3, 0)) try{j.at("defaultCanvasBackgroundColor").get_to(main.defaultCanvasBackgroundColor);} catch(...) {} try{j.at("flipZoomToolDirection").get_to(flipZoomToolDirection);} catch(...) {} @@ -341,6 +347,16 @@ void Toolbar::set_config_json(const nlohmann::json& j, VersionNumber version) { try{j.at("tablet").at("brushMinimumSize").get_to(tabletOptions.brushMinimumSize);} catch(...) {} try{j.at("tablet").at("zoomWhilePenDownAndButtonHeld").get_to(tabletOptions.zoomWhilePenDownAndButtonHeld);} catch(...) {} + try{j.at("debug").at("showPerformance").get_to(showPerformance);} catch(...) {} + try{j.at("debug").at("fpsLimit").get_to(main.fpsLimit);} catch(...) {} + try{j.at("debug").at("jumpTransitionEasing").get_to(jumpTransitionEasing);} catch(...) {} + try{j.at("debug").at("cacheNodeResolution").get_to(DrawingProgramCache::CACHE_NODE_RESOLUTION);} catch(...) {} + 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(...) {} + main.update_display_names(); } @@ -1833,6 +1849,18 @@ void Toolbar::options_menu() { #ifndef __EMSCRIPTEN__ gui.input_scalar_field("fps cap slider", "FPS cap", &main.fpsLimit, 3.0f, 10000.0f); #endif + gui.text_label_light("Cache related settings"); + gui.input_scalar_field("cache node resolution", "Cache node resolution", &DrawingProgramCache::CACHE_NODE_RESOLUTION, 256, 8192); + gui.input_scalar_field("max cache nodes", "Maximum cached nodes", &DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES, 2, 10000); + size_t cacheVRAMConsumptionInMB = ( DrawingProgramCache::MAXIMUM_DRAW_CACHE_SURFACES // Number of surfaces + * DrawingProgramCache::CACHE_NODE_RESOLUTION * DrawingProgramCache::CACHE_NODE_RESOLUTION // Number of pixels per cache surface + * 4) // 4 Channels per pixel (RGBA) + / (1024 * 1024); // Bytes -> Megabytes conversion + gui.text_label_light("Cache max VRAM consumption (MB): " + std::to_string(cacheVRAMConsumptionInMB)); + gui.input_scalar_field("max components in node", "Maximum components in single node", &DrawingProgramCache::MAXIMUM_COMPONENTS_IN_SINGLE_NODE, 2, 10000); + gui.input_scalar_field("components to force cache rebuild", "Number of components to force cache rebuild", &DrawingProgramCache::MINIMUM_COMPONENTS_TO_START_REBUILD, 1, 1000000); + gui.input_scalar_field("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("minimum time to force cache rebuild", "Minimum time to check cache rebuild (ms)", &DrawingProgram::MILLISECOND_MINIMUM_TIME_TO_CHECK_FORCE_REFRESH, 1, 1000000); gui.pop_id(); break; }