diff --git a/include/physics.hpp b/include/physics.hpp index ca4a8a3..56f59a1 100644 --- a/include/physics.hpp +++ b/include/physics.hpp @@ -2,6 +2,7 @@ #define __PHYSICS_HPP_ #include +#include #include #include #include @@ -150,7 +151,11 @@ class ThreadedPhysics { TracyLockable(std::mutex, command_mtx); std::queue pending_commands; - TracyLockable(std::mutex, pos_mtx); + TracyLockable(std::mutex, data_mtx); + std::condition_variable_any data_ready_cnd; + std::condition_variable_any data_consumed_cnd; + bool data_ready = false; + bool data_consumed = true; std::vector masses; // Read by renderer std::unordered_map state_masses; // Read by renderer std::vector springs; // Read by renderer diff --git a/include/renderer.hpp b/include/renderer.hpp index 642d391..334d350 100644 --- a/include/renderer.hpp +++ b/include/renderer.hpp @@ -61,10 +61,9 @@ public: } private: - auto AllocateGraphInstancing(const std::vector &masses) -> void; + auto AllocateGraphInstancing(std::size_t size) -> void; - auto ReallocateGraphInstancingIfNecessary(const std::vector &masses) - -> void; + auto ReallocateGraphInstancingIfNecessary(std::size_t size) -> void; public: auto UpdateTextureSizes() -> void; diff --git a/src/main.cpp b/src/main.cpp index fc8c98b..7ca8fe9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -81,12 +81,19 @@ auto main(int argc, char *argv[]) -> int { // TODO: Don't download each frame if nothing changed, check for update // first { - std::lock_guard lock(physics.state.pos_mtx); + std::unique_lock lock(physics.state.data_mtx); + physics.state.data_ready_cnd.wait( + lock, [&] { return physics.state.data_ready; }); + masses = physics.state.masses; state_masses = physics.state.state_masses; springs = physics.state.springs; state_springs = physics.state.state_springs; + + physics.state.data_ready = false; + physics.state.data_consumed = true; } + physics.state.data_consumed_cnd.notify_one(); // Update the camera after the physics, so target lock is smooth if (state_masses.contains(state.current_state)) { diff --git a/src/physics.cpp b/src/physics.cpp index bbac526..db590cb 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -349,7 +349,7 @@ auto ThreadedPhysics::PhysicsThread(ThreadedPhysics::PhysicsState &state) [&](const struct ClearGraph &cg) { mass_springs.Clear(); }, }; - while (state.running) { + while (state.running.load()) { // Handle queued commands { std::lock_guard lock(state.command_mtx); @@ -366,7 +366,6 @@ auto ThreadedPhysics::PhysicsThread(ThreadedPhysics::PhysicsState &state) } // Physics update - // TODO: I need this thread to run at a constant rate mass_springs.ClearForces(); mass_springs.CalculateSpringForces(); mass_springs.CalculateRepulsionForces(); @@ -380,12 +379,20 @@ auto ThreadedPhysics::PhysicsThread(ThreadedPhysics::PhysicsState &state) // Publish the positions for the renderer (copy) { - std::lock_guard lock(state.pos_mtx); + std::unique_lock lock(state.data_mtx); + state.data_consumed_cnd.wait(lock, [&] { return state.data_consumed; }); + state.masses = mass_springs.masses; state.state_masses = mass_springs.state_masses; state.springs = mass_springs.springs; state.state_springs = mass_springs.state_springs; + + state.data_ready = true; + state.data_consumed = false; } + + // Notify the rendering thread that new data is available + state.data_ready_cnd.notify_one(); } } diff --git a/src/renderer.cpp b/src/renderer.cpp index 725395e..21b0508 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -33,8 +33,7 @@ auto Renderer::UpdateTextureSizes() -> void { menu_target = LoadRenderTexture(width * 2, MENU_HEIGHT); } -auto Renderer::AllocateGraphInstancing(const std::vector &masses) - -> void { +auto Renderer::AllocateGraphInstancing(std::size_t size) -> void { cube_instance = GenMeshCube(VERTEX_SIZE, VERTEX_SIZE, VERTEX_SIZE); instancing_shader = LoadShader("shader/instancing_vertex.glsl", @@ -48,16 +47,14 @@ auto Renderer::AllocateGraphInstancing(const std::vector &masses) vertex_mat.maps[MATERIAL_MAP_DIFFUSE].color = VERTEX_COLOR; vertex_mat.shader = instancing_shader; - transforms = (Matrix *)MemAlloc(masses.size() * sizeof(Matrix)); - transforms_size = masses.size(); + transforms = (Matrix *)MemAlloc(size * sizeof(Matrix)); + transforms_size = size; } -auto Renderer::ReallocateGraphInstancingIfNecessary( - const std::vector &masses) -> void { - if (transforms_size != masses.size()) { - transforms = - (Matrix *)MemRealloc(transforms, masses.size() * sizeof(Matrix)); - transforms_size = masses.size(); +auto Renderer::ReallocateGraphInstancingIfNecessary(std::size_t size) -> void { + if (transforms_size != size) { + transforms = (Matrix *)MemRealloc(transforms, size * sizeof(Matrix)); + transforms_size = size; } } @@ -76,9 +73,9 @@ auto Renderer::DrawMassSprings( ZoneNamedN(prepare_masses, "PrepareMasses", true); if (masses.size() < DRAW_VERTICES_LIMIT) { if (transforms == nullptr) { - AllocateGraphInstancing(masses); + AllocateGraphInstancing(masses.size()); } - ReallocateGraphInstancingIfNecessary(masses); + ReallocateGraphInstancingIfNecessary(masses.size()); int i = 0; for (const auto &mass : masses) { diff --git a/src/state.cpp b/src/state.cpp index 59f3d7a..f54628e 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -43,7 +43,7 @@ auto StateManager::FillGraph() -> void { // 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(); } auto StateManager::UpdateGraph() -> void { @@ -74,7 +74,7 @@ auto StateManager::FindWinningStates() -> void { winning_states.clear(); std::unordered_map state_masses; { - std::lock_guard lock(physics.state.pos_mtx); + std::lock_guard lock(physics.state.data_mtx); state_masses = physics.state.state_masses; } for (const auto &[state, mass] : state_masses) {