From 5f3adf0925797bbf3b8e2f2a290fb70f94295b21 Mon Sep 17 00:00:00 2001 From: Christoph Urlacher Date: Tue, 24 Feb 2026 17:24:35 +0100 Subject: [PATCH] wip: don't wait for physics data in render thread --- src/main.cpp | 27 ++++++++++++++------------- src/physics.cpp | 5 ++++- src/state.cpp | 4 ++-- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 66f54c6..90173ae 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -55,23 +55,24 @@ auto main(int argc, char *argv[]) -> int { state.UpdateGraph(); // Add state added after user input // Read positions from physics thread + FrameMarkStart("MainThreadConsumeLock"); { std::unique_lock lock(physics.state.data_mtx); - physics.state.data_ready_cnd.wait(lock, [&] { - return physics.state.data_ready || !physics.state.running.load(); - }); - if (!physics.state.running.load()) { - // Running turned false while we were waiting for the condition - break; + + // Only copy data if any has been produced + if (physics.state.data_ready) { + masses = physics.state.masses; + springs = physics.state.springs; + + physics.state.data_ready = false; + physics.state.data_consumed = true; + + lock.unlock(); + // Notify the physics thread that data has been consumed + physics.state.data_consumed_cnd.notify_all(); } - - masses = physics.state.masses; - springs = physics.state.springs; - - physics.state.data_ready = false; - physics.state.data_consumed = true; } - physics.state.data_consumed_cnd.notify_all(); + FrameMarkEnd("MainThreadConsumeLock"); // Update the camera after the physics, so target lock is smooth std::size_t current_index = state.CurrentMassIndex(); diff --git a/src/physics.cpp b/src/physics.cpp index 5bcb463..752bc93 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -201,12 +201,14 @@ auto ThreadedPhysics::PhysicsThread(ThreadedPhysics::PhysicsState &state) } // Physics update + // TODO: Respect thread-local deltatime + calculate UPS mass_springs.ClearForces(); mass_springs.CalculateSpringForces(); mass_springs.CalculateRepulsionForces(); mass_springs.VerletUpdate(TIMESTEP * SIM_SPEED); // Publish the positions for the renderer (copy) + FrameMarkStart("PhysicsThreadProduceLock"); { std::unique_lock lock(state.data_mtx); state.data_consumed_cnd.wait( @@ -231,9 +233,10 @@ auto ThreadedPhysics::PhysicsThread(ThreadedPhysics::PhysicsState &state) state.data_ready = true; state.data_consumed = false; } - // Notify the rendering thread that new data is available state.data_ready_cnd.notify_all(); + FrameMarkEnd("PhysicsThreadProduceLock"); + FrameMarkEnd("PhysicsThread"); } } diff --git a/src/state.cpp b/src/state.cpp index 048ae9c..805237d 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -6,6 +6,7 @@ auto StateManager::LoadPreset(int preset) -> void { current_preset = preset; + current_state = CurrentGenerator()(); ClearGraph(); edited = false; } @@ -49,11 +50,11 @@ auto StateManager::UpdateGraph() -> void { } if (!states.contains(current_state)) { + states.insert(std::make_pair(current_state, states.size())); physics.AddMassCmd(); physics.AddSpringCmd(states.at(current_state), states.at(previous_state)); } - states.insert(std::make_pair(current_state, states.size())); visited_states.insert(current_state); if (win_conditions[current_preset](current_state)) { winning_states.insert(current_state); @@ -66,7 +67,6 @@ auto StateManager::ClearGraph() -> void { visited_states.clear(); physics.ClearCmd(); - current_state = CurrentGenerator()(); states.insert(std::make_pair(current_state, states.size())); visited_states.insert(current_state); physics.AddMassCmd();