wip: don't lock command mutex for each mass/spring in FillGraph()

This commit is contained in:
2026-02-24 02:05:44 +01:00
parent 550970f8a1
commit 5e8a110f45
5 changed files with 36 additions and 8 deletions

View File

@ -30,7 +30,7 @@ constexpr float ROT_SPEED = 1.0;
constexpr float CAMERA_SMOOTH_SPEED = 15.0; constexpr float CAMERA_SMOOTH_SPEED = 15.0;
// Physics Engine // Physics Engine
constexpr float SIM_SPEED = 4.0; // How large each update should be constexpr float SIM_SPEED = 0.2; // How large each update should be
constexpr float TIMESTEP = 1.0 / 90; // Do 90 physics updates per second constexpr float TIMESTEP = 1.0 / 90; // Do 90 physics updates per second
constexpr float MASS = 1.0; // Mass spring system constexpr float MASS = 1.0; // Mass spring system
constexpr float SPRING_CONSTANT = 5.0; // Mass spring system constexpr float SPRING_CONSTANT = 5.0; // Mass spring system

View File

@ -188,6 +188,10 @@ public:
auto AddSpringCmd(const State &a, const State &b) -> void; auto AddSpringCmd(const State &a, const State &b) -> void;
auto ClearCmd() -> void; auto ClearCmd() -> void;
auto NonLockingAddMassCmd(const State &_state) -> void;
auto NonLockingAddSpringCmd(const State &a, const State &b) -> void;
}; };
// https://en.cppreference.com/w/cpp/utility/variant/visit // https://en.cppreference.com/w/cpp/utility/variant/visit

View File

@ -39,7 +39,7 @@ auto main(int argc, char *argv[]) -> int {
OrbitCamera3D camera; OrbitCamera3D camera;
Renderer renderer(camera); Renderer renderer(camera);
ThreadedPhysics physics; ThreadedPhysics physics;
StateManager state(physics); StateManager state(physics); // TODO: What is this warning?
InputHandler input(state, renderer); InputHandler input(state, renderer);
std::vector<Mass> masses; // Read from physics std::vector<Mass> masses; // Read from physics
@ -74,7 +74,7 @@ auto main(int argc, char *argv[]) -> int {
*/ */
// Read positions from physics thread // Read positions from physics thread
// TODO: We're reading a HUGE amount of SHIT, because the state // TODO: We're copying a HUGE amount of SHIT, because the state
// representations (std::string, ~100 Bytes) are copied ~3 times per // representations (std::string, ~100 Bytes) are copied ~3 times per
// spring: state_masses<State, int> and state_springs<<State, State>, // spring: state_masses<State, int> and state_springs<<State, State>,
// int> // int>

View File

@ -366,11 +366,18 @@ auto ThreadedPhysics::PhysicsThread(ThreadedPhysics::PhysicsState &state)
} }
// Physics update // Physics update
// TODO: I need this thread to run at a constant rate
mass_springs.ClearForces(); mass_springs.ClearForces();
mass_springs.CalculateSpringForces(); mass_springs.CalculateSpringForces();
mass_springs.CalculateRepulsionForces(); mass_springs.CalculateRepulsionForces();
mass_springs.VerletUpdate(TIMESTEP * SIM_SPEED); mass_springs.VerletUpdate(TIMESTEP * SIM_SPEED);
// TODO: Notify the main thread of update
// TODO: Just wait here until the main thread has fetched the data?
// Then only the copying would be sequential, while the main thread
// renders this thread can already calculate the physics...
// TODO: Would std::swap help in any way?
// Publish the positions for the renderer (copy) // Publish the positions for the renderer (copy)
{ {
std::lock_guard<LockableBase(std::mutex)> lock(state.pos_mtx); std::lock_guard<LockableBase(std::mutex)> lock(state.pos_mtx);
@ -402,3 +409,12 @@ auto ThreadedPhysics::ClearCmd() -> void {
state.pending_commands.push(ClearGraph{}); state.pending_commands.push(ClearGraph{});
} }
} }
auto ThreadedPhysics::NonLockingAddMassCmd(const State &_state) -> void {
state.pending_commands.push(AddMass{_state});
}
auto ThreadedPhysics::NonLockingAddSpringCmd(const State &a, const State &b)
-> void {
state.pending_commands.push(AddSpring{a, b});
}

View File

@ -37,12 +37,20 @@ auto StateManager::FillGraph() -> void {
std::pair<std::unordered_set<State>, std::vector<std::pair<State, State>>> std::pair<std::unordered_set<State>, std::vector<std::pair<State, State>>>
closure = current_state.Closure(); closure = current_state.Closure();
for (const auto &state : closure.first) {
physics.AddMassCmd(state); {
} std::lock_guard<LockableBase(std::mutex)> lock(physics.state.command_mtx);
for (const auto &[from, to] : closure.second) { for (const auto &state : closure.first) {
physics.AddSpringCmd(from, to); physics.NonLockingAddMassCmd(state);
}
for (const auto &[from, to] : closure.second) {
physics.NonLockingAddSpringCmd(from, to);
}
} }
// TODO: We have only dispatched the commands, the states won't be downloaded
// when calling this... Make FindWinningStates() another command?
// Or recalculate whenever masses.size() changes?
FindWinningStates(); FindWinningStates();
} }