From 304a69b676239e6074d857c841b50435a42e51eb Mon Sep 17 00:00:00 2001 From: Lars Ivar Hatledal Date: Sat, 16 Mar 2024 20:32:30 +0100 Subject: [PATCH 1/2] refactor task management --- src/CMakeLists.txt | 1 + src/threepp/canvas/Canvas.cpp | 26 ++++--------------- src/threepp/utils/TaskManager.hpp | 43 +++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 21 deletions(-) create mode 100644 src/threepp/utils/TaskManager.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 05665a6f..e2a2ece4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -233,6 +233,7 @@ set(privateHeaders "threepp/renderers/gl/UniformUtils.hpp" "threepp/utils/RegexUtil.hpp" + "threepp/utils/TaskManager.hpp" ) diff --git a/src/threepp/canvas/Canvas.cpp b/src/threepp/canvas/Canvas.cpp index 53a9505c..3bbc7d36 100644 --- a/src/threepp/canvas/Canvas.cpp +++ b/src/threepp/canvas/Canvas.cpp @@ -4,6 +4,7 @@ #include "threepp/favicon.hpp" #include "threepp/loaders/ImageLoader.hpp" #include "threepp/utils/StringUtils.hpp" +#include "threepp/utils/TaskManager.hpp" #ifndef EMSCRIPTEN #include "threepp/utils/LoadGlad.hpp" @@ -22,12 +23,6 @@ using namespace threepp; namespace { - typedef std::pair, float> Task; - - struct CustomComparator { - bool operator()(const Task& l, const Task& r) const { return l.second > r.second; } - }; - #if EMSCRIPTEN struct FunctionWrapper { std::function loopFunction; @@ -173,7 +168,8 @@ struct Canvas::Impl { bool close_{false}; bool exitOnKeyEscape_; - std::priority_queue, CustomComparator> tasks_; + utils::TaskManager taskManager; + std::optional> resizeListener; explicit Impl(Canvas& scope, const Canvas::Parameters& params) @@ -248,25 +244,13 @@ struct Canvas::Impl { glfwSetWindowSize(window, size.width, size.height); } - inline void handleTasks() { - while (!tasks_.empty()) { - auto& task = tasks_.top(); - if (task.second < glfwGetTime()) { - task.first(); - tasks_.pop(); - } else { - break; - } - } - } - bool animateOnce(const std::function& f) { if (close_ || glfwWindowShouldClose(window)) { return false; } - handleTasks(); + taskManager.handleTasks(static_cast(glfwGetTime())); f(); @@ -290,7 +274,7 @@ struct Canvas::Impl { } void invokeLater(const std::function& f, float t) { - tasks_.emplace(f, static_cast(glfwGetTime()) + t); + taskManager.invokeLater(f, static_cast(glfwGetTime()) + t); } void close() { diff --git a/src/threepp/utils/TaskManager.hpp b/src/threepp/utils/TaskManager.hpp new file mode 100644 index 00000000..6dbdf595 --- /dev/null +++ b/src/threepp/utils/TaskManager.hpp @@ -0,0 +1,43 @@ + +#ifndef THREEPP_TASKMANAGER_HPP +#define THREEPP_TASKMANAGER_HPP + +#include +#include +#include + +namespace threepp::utils { + + using Task = std::pair, float>; + + class TaskManager { + + public: + inline void handleTasks(float currentTime) { + while (!tasks_.empty()) { + auto& task = tasks_.top(); + if (task.second < currentTime) { + task.first(); + tasks_.pop(); + } else { + break; + } + } + } + + void invokeLater(const std::function& f, float tNow, float tPassed = 0) { + + tasks_.emplace(f, tNow + tPassed); + } + + private: + struct CustomComparator { + bool operator()(const Task& l, const Task& r) const { return l.second > r.second; } + }; + + std::priority_queue, CustomComparator> tasks_; + }; + +}// namespace threepp::utils + +#endif//THREEPP_TASKMANAGER_HPP From a804a5d845f448a7ae78e791798e139cfa8f53ab Mon Sep 17 00:00:00 2001 From: Lars Ivar Hatledal Date: Sat, 16 Mar 2024 21:35:59 +0100 Subject: [PATCH 2/2] move tasks to renderer --- examples/extras/physics/physx_demo.cpp | 2 +- examples/geometries/heightmap.cpp | 4 +-- examples/projects/Crane3R/main.cpp | 2 +- examples/projects/Pathfinding/main.cpp | 4 +-- examples/projects/Youbot/youbot.cpp | 2 +- examples/projects/Youbot/youbot_kine.cpp | 2 +- include/threepp/canvas/Canvas.hpp | 2 -- include/threepp/renderers/GLRenderer.hpp | 3 ++ src/threepp/canvas/Canvas.cpp | 15 -------- src/threepp/renderers/GLRenderer.cpp | 44 +++++++++++++++++++++++- src/threepp/utils/TaskManager.hpp | 15 +++++--- 11 files changed, 64 insertions(+), 31 deletions(-) diff --git a/examples/extras/physics/physx_demo.cpp b/examples/extras/physics/physx_demo.cpp index 12a658f2..925b48ce 100644 --- a/examples/extras/physics/physx_demo.cpp +++ b/examples/extras/physics/physx_demo.cpp @@ -229,7 +229,7 @@ int main() { camera.getWorldDirection(world); rb->addForce(toPxVector3(world * 10000)); - canvas.invokeLater([&, obj] { + renderer.invokeLater([&, obj] { scene.remove(*obj); }, 2);// remove after 2 seconds diff --git a/examples/geometries/heightmap.cpp b/examples/geometries/heightmap.cpp index dcdae979..4907b793 100644 --- a/examples/geometries/heightmap.cpp +++ b/examples/geometries/heightmap.cpp @@ -121,7 +121,7 @@ int main() { TextureLoader tl; auto texture = tl.load("data/textures/terrain/aalesund_terrain.png"); - canvas.invokeLater([&, texture, geometry] { + renderer.invokeLater([&, texture, geometry] { material->map = texture; material->needsUpdate(); @@ -130,7 +130,7 @@ int main() { hudText.setText("Terrain loaded..", opts); }); - canvas.invokeLater([&] { + renderer.invokeLater([&] { hud.remove(hudText); }, 2); diff --git a/examples/projects/Crane3R/main.cpp b/examples/projects/Crane3R/main.cpp index 81b48ed7..ff920c57 100644 --- a/examples/projects/Crane3R/main.cpp +++ b/examples/projects/Crane3R/main.cpp @@ -147,7 +147,7 @@ int main() { m.castShadow = true; }); - canvas.invokeLater([&, crane] { + renderer.invokeLater([&, crane] { hud.remove(handle); scene->add(crane); endEffectorHelper->visible = true; diff --git a/examples/projects/Pathfinding/main.cpp b/examples/projects/Pathfinding/main.cpp index eced21c4..30883613 100644 --- a/examples/projects/Pathfinding/main.cpp +++ b/examples/projects/Pathfinding/main.cpp @@ -126,13 +126,13 @@ int main() { auto obj = scene.getObjectByName(getMeshName(c)); obj->material()->as()->color.setHex(Color::green); } - canvas.invokeLater([&] { + renderer.invokeLater([&] { start = std::nullopt; target = std::nullopt; resetBlockColors(); }, 2); } else { std::cerr << "Unable to find path between " << *start << " and " << *target << std::endl; - canvas.invokeLater([&] { + renderer.invokeLater([&] { start = std::nullopt; target = std::nullopt; resetBlockColors(); }, 1); diff --git a/examples/projects/Youbot/youbot.cpp b/examples/projects/Youbot/youbot.cpp index 8a45051d..c6b5a66f 100644 --- a/examples/projects/Youbot/youbot.cpp +++ b/examples/projects/Youbot/youbot.cpp @@ -47,7 +47,7 @@ int main() { std::shared_ptr youbot; auto future = std::async([&] { youbot = Youbot::create("data/models/collada/youbot.dae"); - canvas.invokeLater([&] { + renderer.invokeLater([&] { canvas.addKeyListener(*youbot); scene->add(youbot); handle.setText("Use WASD keys to steer robot", opts); diff --git a/examples/projects/Youbot/youbot_kine.cpp b/examples/projects/Youbot/youbot_kine.cpp index b32bb431..7ea7e0ab 100644 --- a/examples/projects/Youbot/youbot_kine.cpp +++ b/examples/projects/Youbot/youbot_kine.cpp @@ -112,7 +112,7 @@ int main() { youbot->add(targetHelper); youbot->add(endEffectorHelper); endEffectorHelper->visible = true; - canvas.invokeLater([&] { + renderer.invokeLater([&] { canvas.addKeyListener(*youbot); scene->add(youbot); hud.remove(handle); diff --git a/include/threepp/canvas/Canvas.hpp b/include/threepp/canvas/Canvas.hpp index fb4333a9..43484cba 100644 --- a/include/threepp/canvas/Canvas.hpp +++ b/include/threepp/canvas/Canvas.hpp @@ -44,8 +44,6 @@ namespace threepp { // returns false if application should quit, true otherwise bool animateOnce(const std::function& f); - void invokeLater(const std::function& f, float t = 0); - void close(); [[nodiscard]] void* windowPtr() const; diff --git a/include/threepp/renderers/GLRenderer.hpp b/include/threepp/renderers/GLRenderer.hpp index 51225983..ebd3e663 100644 --- a/include/threepp/renderers/GLRenderer.hpp +++ b/include/threepp/renderers/GLRenderer.hpp @@ -17,6 +17,7 @@ #include "threepp/renderers/gl/GLShadowMap.hpp" #include "threepp/renderers/gl/GLState.hpp" +#include #include #include @@ -152,6 +153,8 @@ namespace threepp { void resetState(); + void invokeLater(const std::function& task, float delay = 0); + [[nodiscard]] const gl::GLInfo& info() const; [[nodiscard]] std::optional getGlTextureId(Texture& texture) const; diff --git a/src/threepp/canvas/Canvas.cpp b/src/threepp/canvas/Canvas.cpp index 3bbc7d36..413d0077 100644 --- a/src/threepp/canvas/Canvas.cpp +++ b/src/threepp/canvas/Canvas.cpp @@ -4,7 +4,6 @@ #include "threepp/favicon.hpp" #include "threepp/loaders/ImageLoader.hpp" #include "threepp/utils/StringUtils.hpp" -#include "threepp/utils/TaskManager.hpp" #ifndef EMSCRIPTEN #include "threepp/utils/LoadGlad.hpp" @@ -17,7 +16,6 @@ #include #include -#include using namespace threepp; @@ -168,8 +166,6 @@ struct Canvas::Impl { bool close_{false}; bool exitOnKeyEscape_; - utils::TaskManager taskManager; - std::optional> resizeListener; explicit Impl(Canvas& scope, const Canvas::Parameters& params) @@ -250,8 +246,6 @@ struct Canvas::Impl { return false; } - taskManager.handleTasks(static_cast(glfwGetTime())); - f(); glfwSwapBuffers(window); @@ -273,10 +267,6 @@ struct Canvas::Impl { this->resizeListener = std::move(f); } - void invokeLater(const std::function& f, float t) { - taskManager.invokeLater(f, static_cast(glfwGetTime()) + t); - } - void close() { close_ = true; @@ -400,11 +390,6 @@ void Canvas::onWindowResize(std::function f) { pimpl_->onWindowResize(std::move(f)); } -void Canvas::invokeLater(const std::function& f, float t) { - - pimpl_->invokeLater(f, t); -} - void Canvas::close() { pimpl_->close(); diff --git a/src/threepp/renderers/GLRenderer.cpp b/src/threepp/renderers/GLRenderer.cpp index ff4f1e4a..7cea4fd3 100644 --- a/src/threepp/renderers/GLRenderer.cpp +++ b/src/threepp/renderers/GLRenderer.cpp @@ -21,7 +21,6 @@ #include "threepp/cameras/OrthographicCamera.hpp" #include "threepp/core/InstancedBufferGeometry.hpp" #include "threepp/materials/RawShaderMaterial.hpp" -#include "threepp/math/Frustum.hpp" #include "threepp/objects/Group.hpp" #include "threepp/objects/InstancedMesh.hpp" @@ -33,17 +32,31 @@ #include "threepp/objects/SkinnedMesh.hpp" #include "threepp/objects/Sprite.hpp" +#include "threepp/utils/TaskManager.hpp" + #ifndef EMSCRIPTEN #include "threepp/utils/LoadGlad.hpp" #else #include #endif +#include #include using namespace threepp; +namespace { + + double getCurrentTimeInSeconds() { + using Clock = std::chrono::high_resolution_clock; + const auto now = Clock::now(); + const auto duration = now.time_since_epoch(); + return std::chrono::duration(duration).count(); + } + +}// namespace + struct GLRenderer::Impl { @@ -140,6 +153,10 @@ struct GLRenderer::Impl { gl::GLShadowMap shadowMap; + // used for in-thread task execution + double previousTime{-1}; + utils::TaskManager taskManager; + Impl(GLRenderer& scope, WindowSize size, const GLRenderer::Parameters& parameters) : scope(scope), _size(size), cubemaps(scope), @@ -163,6 +180,11 @@ struct GLRenderer::Impl { this->setScissor(0, 0, _size.width, _size.height); } + void invokeLater(const std::function& task, float delay) { + + taskManager.invokeLater(task, delay); + } + [[nodiscard]] std::optional getGlTextureId(Texture& texture) const { return textures.getGlTexture(texture); @@ -188,8 +210,23 @@ struct GLRenderer::Impl { } } + void handleTasks() { + // handle tasks to be invoked on the render thread + if (previousTime < 0) { + previousTime = getCurrentTimeInSeconds();// first invocation + } + + const auto currentTime = getCurrentTimeInSeconds(); + const auto deltaTime = currentTime - previousTime; + previousTime = currentTime; + + taskManager.handleTasks(deltaTime); + } + void render(Object3D* scene, Camera* camera) { + handleTasks(); + // update scene graph if (auto _scene = scene->as()) { @@ -1363,4 +1400,9 @@ std::optional GLRenderer::getGlTextureId(Texture& texture) const { return pimpl_->getGlTextureId(texture); } +void GLRenderer::invokeLater(const std::function& task, float tThen) { + + return pimpl_->invokeLater(task, tThen); +} + GLRenderer::~GLRenderer() = default; diff --git a/src/threepp/utils/TaskManager.hpp b/src/threepp/utils/TaskManager.hpp index 6dbdf595..a2f73b55 100644 --- a/src/threepp/utils/TaskManager.hpp +++ b/src/threepp/utils/TaskManager.hpp @@ -8,15 +8,18 @@ namespace threepp::utils { - using Task = std::pair, float>; + using Task = std::pair, double>; class TaskManager { public: - inline void handleTasks(float currentTime) { + inline void handleTasks(double deltaTime) { + + time += deltaTime; + while (!tasks_.empty()) { auto& task = tasks_.top(); - if (task.second < currentTime) { + if (task.second < time) { task.first(); tasks_.pop(); } else { @@ -25,9 +28,9 @@ namespace threepp::utils { } } - void invokeLater(const std::function& f, float tNow, float tPassed = 0) { + void invokeLater(const std::function& f, double delay = 0) { - tasks_.emplace(f, tNow + tPassed); + tasks_.emplace(f, time + delay); } private: @@ -35,6 +38,8 @@ namespace threepp::utils { bool operator()(const Task& l, const Task& r) const { return l.second > r.second; } }; + double time{}; + std::priority_queue, CustomComparator> tasks_; };