--- /dev/null
+#ifndef BLANK_APP_FRAMECOUNTER_HPP_
+#define BLANK_APP_FRAMECOUNTER_HPP_
+
+#include <iosfwd>
+#include <SDL.h>
+
+
+namespace blank {
+
+class FrameCounter {
+
+public:
+ void EnterFrame() noexcept;
+ void EnterHandle() noexcept;
+ void ExitHandle() noexcept;
+ void EnterUpdate() noexcept;
+ void ExitUpdate() noexcept;
+ void EnterRender() noexcept;
+ void ExitRender() noexcept;
+ void ExitFrame() noexcept;
+
+ float AvgHandle() const noexcept { return avg.handle; }
+ float AvgUpdate() const noexcept { return avg.update; }
+ float AvgRender() const noexcept { return avg.render; }
+ float AvgFrame() const noexcept { return avg.total; }
+ float AvgRunning() const noexcept { return avg.handle + avg.update + avg.render; }
+ float AvgWaiting() const noexcept { return avg.total - AvgRunning(); }
+
+ bool Changed() const noexcept { return changed; }
+
+ void Print(std::ostream &) const;
+
+private:
+ int Tick() noexcept;
+
+private:
+ static constexpr int NUM_FRAMES = 32;
+ static constexpr float factor = 1.0f / float(NUM_FRAMES);
+
+ template<class T>
+ struct Frame {
+ T handle = T(0);
+ T update = T(0);
+ T render = T(0);
+ T total = T(0);
+ };
+
+ Uint32 last_enter = 0;
+ Uint32 last_tick = 0;
+
+ int cur_frame = 0;
+ Frame<int> running = Frame<int>{};
+ Frame<float> avg = Frame<float>{};
+ bool changed = false;
+
+};
+
+}
+
+#endif
#include "Application.hpp"
#include "Assets.hpp"
+#include "FrameCounter.hpp"
#include "../graphics/Font.hpp"
#include "../world/BlockType.hpp"
, ctx(window.CreateContext())
, init_glew()
, assets(get_asset_path())
+, counter()
, chunk_prog()
, entity_prog()
, sprite_prog()
}
void Application::Loop(int dt) {
+ counter.EnterFrame();
HandleEvents();
Update(dt);
Render();
+ counter.ExitFrame();
}
void Application::HandleEvents() {
+ counter.EnterHandle();
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
break;
}
}
+ counter.ExitHandle();
}
void Application::Handle(const SDL_WindowEvent &event) {
}
void Application::Update(int dt) {
+ counter.EnterUpdate();
interface.Update(dt);
test_controller.Update(dt);
world.Update(dt);
+ counter.ExitUpdate();
}
void Application::Render() {
+ // gl implementation may (and will probably) delay vsync blocking until
+ // the first write after flipping, which is this clear call
GLContext::Clear();
+ counter.EnterRender();
chunk_prog.SetProjection(cam.Projection());
entity_prog.SetProjection(cam.Projection());
interface.Render(entity_prog, sprite_prog);
+ counter.ExitRender();
window.Flip();
}
return Font(full.c_str(), size);
}
+
+void FrameCounter::EnterFrame() noexcept {
+ last_enter = SDL_GetTicks();
+ last_tick = last_enter;
+}
+
+void FrameCounter::EnterHandle() noexcept {
+ Tick();
+}
+
+void FrameCounter::ExitHandle() noexcept {
+ running.handle += Tick();
+}
+
+void FrameCounter::EnterUpdate() noexcept {
+ Tick();
+}
+
+void FrameCounter::ExitUpdate() noexcept {
+ running.update += Tick();
+}
+
+void FrameCounter::EnterRender() noexcept {
+ Tick();
+}
+
+void FrameCounter::ExitRender() noexcept {
+ running.render += Tick();
+}
+
+void FrameCounter::ExitFrame() noexcept {
+ Uint32 now = SDL_GetTicks();
+ running.total += now - last_enter;
+ ++cur_frame;
+ if (cur_frame >= NUM_FRAMES) {
+ avg.handle = running.handle * factor;
+ avg.update = running.update * factor;
+ avg.render = running.render * factor;
+ avg.total = running.total * factor;
+ running = Frame<int>{};
+ cur_frame = 0;
+ changed = true;
+ } else {
+ changed = false;
+ }
+}
+
+int FrameCounter::Tick() noexcept {
+ Uint32 now = SDL_GetTicks();
+ int delta = now - last_tick;
+ last_tick = now;
+ return delta;
+}
+
+void FrameCounter::Print(std::ostream &out) const {
+ out << "frame: " << AvgFrame() << std::endl;
+ out << " handle: " << AvgHandle() << std::endl;
+ out << " update: " << AvgUpdate() << std::endl;
+ out << " render: " << AvgRender() << std::endl;
+ out << " running: " << AvgRunning() << std::endl;
+ out << " waiting: " << AvgWaiting() << std::endl;
+ out << std::endl;
+}
+
}