diff options
-rw-r--r-- | editor/draw.cpp | 2 | ||||
-rw-r--r-- | floormat/main.hpp | 4 | ||||
-rw-r--r-- | main/events.cpp | 3 | ||||
-rw-r--r-- | main/main-impl.cpp | 79 | ||||
-rw-r--r-- | main/main-impl.hpp | 10 |
5 files changed, 61 insertions, 37 deletions
diff --git a/editor/draw.cpp b/editor/draw.cpp index f15a93af..c0ee7d1a 100644 --- a/editor/draw.cpp +++ b/editor/draw.cpp @@ -51,7 +51,7 @@ void app::draw() GL::DebugOutput::setEnabled(GL::DebugOutput::Source::Api, GL::DebugOutput::Type::Other, {131185}, false); // nvidia krap render_menu(); if (debug) - GL::DebugOutput::setEnabled(GL::DebugOutput::Source::Api, GL::DebugOutput::Type::Other, {131185}, true); // nvidia krap + GL::DebugOutput::setEnabled(GL::DebugOutput::Source::Api, GL::DebugOutput::Type::Other, {131185}, true); // nvidia krap } } // namespace floormat diff --git a/floormat/main.hpp b/floormat/main.hpp index 6ba3b4c8..da7e59b9 100644 --- a/floormat/main.hpp +++ b/floormat/main.hpp @@ -26,7 +26,7 @@ struct floormat_main virtual Magnum::Math::Vector2<int> window_size() const noexcept = 0; virtual tile_shader& shader() noexcept = 0; virtual const tile_shader& shader() const noexcept = 0; - constexpr float smoothed_dt() const noexcept { return _frame_time; } + constexpr float smoothed_dt() const noexcept { return _frame_time1; } virtual fm_settings& settings() noexcept = 0; virtual const fm_settings& settings() const noexcept = 0; @@ -42,7 +42,7 @@ struct floormat_main [[nodiscard]] static floormat_main* create(floormat_app& app, fm_settings&& options); protected: - float _frame_time = 0; + float _frame_time1 = 0, _frame_time2 = 0; }; } // namespace floormat diff --git a/main/events.cpp b/main/events.cpp index ac8f0766..35340a21 100644 --- a/main/events.cpp +++ b/main/events.cpp @@ -76,6 +76,8 @@ void main_impl::keyReleaseEvent(Platform::Sdl2Application::KeyEvent& event) void main_impl::anyEvent(SDL_Event& event) { if (event.type == SDL_WINDOWEVENT) + { + update_from_window_flags(); switch (event.window.event) { case SDL_WINDOWEVENT_FOCUS_LOST: @@ -89,6 +91,7 @@ void main_impl::anyEvent(SDL_Event& event) default: return app.on_any_event({event}); } + } else return app.on_any_event({event}); } diff --git a/main/main-impl.cpp b/main/main-impl.cpp index 856635d2..66388777 100644 --- a/main/main-impl.cpp +++ b/main/main-impl.cpp @@ -6,7 +6,8 @@ #include "src/world.hpp" #include "src/camera-offset.hpp" #include <Magnum/GL/DefaultFramebuffer.h> -#include <cstdlib> +#include <chrono> +#include <thread> //#define FM_SKIP_MSAA @@ -90,7 +91,6 @@ main_impl::main_impl(floormat_app& app, fm_settings&& s, int& fake_argc) noexcep if (const auto list = GL::Context::current().extensionStrings(); std::find(list.cbegin(), list.cend(), "EXT_swap_control_tear") != list.cbegin()) (void)setSwapInterval(-1); - setMinimalLoopPeriod(0); break; case fm_tristate::off: setSwapInterval(0); @@ -155,14 +155,41 @@ void main_impl::draw_world() noexcept } } +void main_impl::update_from_window_flags() +{ + const auto flags = (SDL_WindowFlags)SDL_GetWindowFlags(window()); + + dt_expected.do_sleep = true; + if (flags & SDL_WINDOW_HIDDEN) + dt_expected.value = 1; + else if (!(flags & SDL_WINDOW_INPUT_FOCUS)) + dt_expected.value = 1.f / 30; +#if 1 + else if (!(flags & SDL_WINDOW_MOUSE_FOCUS)) + dt_expected.value = 1.f / 60; +#endif + else + { + dt_expected.do_sleep = false; + dt_expected.value = 1e-1f; + } +} + void main_impl::drawEvent() { - if (const float dt = timeline.previousFrameDuration(); dt > 0) + float dt = timeline.previousFrameDuration(); + if (dt > 0) { - constexpr float RC = 0.1f; - const float alpha = dt/(dt + RC); + const float RC1 = dt_expected.do_sleep ? 1.f : 1.f/15, + RC2 = dt_expected.do_sleep ? 1.f/15 : 1.f/60; + const float alpha1 = dt/(dt + RC1); + const float alpha2 = dt/(dt + RC2); - _frame_time = _frame_time*(1-alpha) + alpha*dt; + _frame_time1 = _frame_time1*(1-alpha1) + alpha1*dt; + _frame_time2 = _frame_time1*(1-alpha2) + alpha2*dt; + constexpr float max_deviation = 5 * 1e-3f; + if (std::fabs(_frame_time1 - _frame_time2) > max_deviation) + _frame_time1 = _frame_time2; } else { @@ -170,33 +197,9 @@ void main_impl::drawEvent() timeline.nextFrame(); } - { - float dt_max; - unsigned min_loop_period; - - if (const auto flags = SDL_GetWindowFlags(window()); - flags & SDL_WINDOW_HIDDEN) - { - dt_max = 1 + 1e-3f; - min_loop_period = 1000; - } - else if (!(flags & (SDL_WINDOW_INPUT_FOCUS|SDL_WINDOW_MOUSE_FOCUS))) - { - dt_max = 1.f/10; - min_loop_period = 1000/12; - } - else - { - dt_max = 1e-1f; - min_loop_period = 0; - } - - const float dt = std::clamp(timeline.previousFrameDuration(), 1e-6f, dt_max); - setMinimalLoopPeriod(min_loop_period); - - app.update(dt); - } + dt = std::clamp(dt, 1e-5f, dt_expected.value); + app.update(dt); _shader.set_tint({1, 1, 1, 1}); { @@ -217,6 +220,18 @@ void main_impl::drawEvent() swapBuffers(); redraw(); + + if (dt_expected.do_sleep) + { + constexpr float jitter_max_seconds = 1 + 1e-3f; + const float dt0 = timeline.currentFrameTime(), sleep_secs = dt_expected.value - dt0 - dt_expected.jitter; + if (sleep_secs > 0) + std::this_thread::sleep_for(std::chrono::nanoseconds((long long)(sleep_secs * 1e9f))); + dt_expected.jitter += timeline.currentFrameTime() - dt_expected.value; + dt_expected.jitter = std::copysignf(std::fminf(jitter_max_seconds, std::fabsf(dt_expected.jitter)), dt_expected.jitter); + } + else + dt_expected.jitter = 0; timeline.nextFrame(); } diff --git a/main/main-impl.hpp b/main/main-impl.hpp index 964bf1f3..202654db 100644 --- a/main/main-impl.hpp +++ b/main/main-impl.hpp @@ -51,6 +51,7 @@ struct main_impl final : Platform::Sdl2Application, floormat_main [[maybe_unused]] void anyEvent(SDL_Event& event) override; void drawEvent() override; + void update_from_window_flags(); bool is_text_input_active() const noexcept override; void start_text_input() noexcept override; @@ -60,13 +61,18 @@ struct main_impl final : Platform::Sdl2Application, floormat_main private: fm_settings s; - char _dummy = maybe_register_debug_callback(s.gpu_debug); - floormat_app& app; + [[maybe_unused]] char _dummy = maybe_register_debug_callback(s.gpu_debug); + floormat_app& app; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) tile_shader _shader; struct world _world{}; floor_mesh _floor_mesh; wall_mesh _wall_mesh; Magnum::Timeline timeline; + struct { + float value = 1e-1f; + float jitter = 0; + bool do_sleep = true; + } dt_expected; struct draw_bounds final { std::int16_t minx, maxx, miny, maxy; }; |