Index

zydeco / 3c60e1a

Experiment in graphics programming, C++, OpenGL, simulation techniques.

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
505 Aug 2023 23:143c60e1aUse GL3WJosh Stockin11312G

Blob @ zydeco / src / Engine.cpp

text/plain4254 bytesdownload raw
1#include <chrono>
2#include <atomic>
3#include <thread>
4
5#include "ZydecoCommon.hpp"
6#include "Engine.hpp"
7#include "IEventHandler.hpp"
8#include "IWindow.hpp"
9
10
11Logger LOGGER("ENGINE");
12Logger EVENT_LOGGER("ENGINE::EVENT");
13Logger RENDER_LOGGER("ENGINE::RENDER");
14
15
16Engine::Engine(IEventHandler& r_event_handler, IWindow& r_window):
17 m_rEventHandler(r_event_handler),
18 m_rWindow(r_window),
19 m_framerate(60),
20 m_frameRenderTimeUs(static_cast<int64_t>(1'000'000 / m_framerate))
21{
22 LOGGER.Log(Logger::DEBUG, "Engine creating");
23 LOGGER.Log(Logger::VERBOSE, "Frame render time: {}us", m_frameRenderTimeUs.count());
24
25 r_event_handler.RegisterQuitEventSubscriber(this);
26
27 std::atomic_init(&m_aIsExiting, false);
28
29 LOGGER.Log(Logger::DEBUG, "Engine created");
30}
31
32Engine::~Engine()
33{
34 LOGGER.Log(Logger::DEBUG, "Engine destroyed");
35}
36
37void Engine::OnQuitEvent()
38{
39 LOGGER.Log(Logger::VERBOSE, "QuitEvent occurred. Trigger exit.");
40
41 m_aIsExiting.store(true);
42}
43
44void Engine::Execute()
45{
46 LOGGER.Log(Logger::INFO, "Entering engine loop (thread handler)");
47
48 LOGGER.Log(Logger::DEBUG, "Starting event handler thread");
49 std::thread event_thread(&Engine::DoEventLoop, this);
50 m_threads["Event Handler"] = &event_thread;
51
52 LOGGER.Log(Logger::DEBUG, "Starting render thread");
53 std::thread render_thread(&Engine::DoRenderLoop, this);
54 m_threads["Renderer"] = &render_thread;
55
56 // std::thread(&Engine::DoEventLoop, this);
57 // std::thread(&Engine::DoGameLoop, this);
58
59 // Step clock while subsystems are running
60 while (m_aIsExiting.load() == false)
61 {
62 m_currentTime = std::chrono::time_point_cast<std::chrono::microseconds, std::chrono::steady_clock, std::chrono::nanoseconds>(
63 std::chrono::steady_clock::now()
64 );
65 std::this_thread::sleep_for(std::chrono::microseconds(100));
66 }
67
68 // Subsystem signaled exiting
69 LOGGER.Log(Logger::DEBUG, "Signal to quit");
70
71 // Wait for program completion
72 for (auto active_thread : m_threads)
73 {
74 while (active_thread.second->joinable()) {
75 LOGGER.Log(Logger::DEBUG, "Waiting thread {} to exit", active_thread.first);
76 active_thread.second->join();
77 }
78 }
79
80 LOGGER.Log(Logger::INFO, "Exiting engine loop (thread handler)");
81}
82
83void Engine::DoEventLoop()
84{
85 EVENT_LOGGER.Log(Logger::DEBUG, "Starting event loop");
86
87 m_rEventHandler.Update(0);
88
89 EVENT_LOGGER.Log(Logger::DEBUG, "Exiting event loop");
90 m_aIsExiting.store(true);
91}
92
93void Engine::DoRenderLoop()
94{
95 RENDER_LOGGER.Log(Logger::DEBUG, "Starting render loop");
96
97 std::chrono::time_point<std::chrono::steady_clock, std::chrono::microseconds> expected_end_time;
98 std::chrono::microseconds time_since_last_tick;
99 std::chrono::microseconds remaining_time_before_next_tick;
100
101 // Loop while not exiting
102 while (m_aIsExiting.load() == false)
103 {
104 // Calculate time since last tick, update tick start/end times
105 time_since_last_tick = std::chrono::duration_cast<std::chrono::microseconds>(m_currentTime - m_frameRenderStartTime);
106 m_frameRenderStartTime = m_currentTime;
107 expected_end_time = m_currentTime + m_frameRenderTimeUs;
108
109 // Update system with time since last tick
110 bool exiting = m_rWindow.Update(time_since_last_tick.count());
111 if (exiting) { break; }
112
113 // Calculate remaining tick time; if >0, sleep until next tick
114 remaining_time_before_next_tick = expected_end_time - m_currentTime;
115 if (remaining_time_before_next_tick.count() > 0)
116 {
117 std::this_thread::sleep_until(expected_end_time);
118 }
119 else
120 {
121 int64_t tick_time = (m_currentTime - m_frameRenderStartTime).count();
122 RENDER_LOGGER.Log(Logger::WARNING, "Overutilized! Tick time: {}us ({} ticks per second)", tick_time, 1'000'000./(float)tick_time);
123 }
124 }
125
126 RENDER_LOGGER.Log(Logger::INFO, "Exiting render loop");
127 m_aIsExiting.store(true);
128}
129
130/*
131class Engine
132{
133public:
134 Engine();
135 ~Engine();
136
137 void Start();
138 void Kill();
139
140 void Update();
141
142protected:
143 Window m_sdlWindow;
144 Scene m_scene;
145 Renderer m_renderer;
146 EventHandler m_eventHandler;
147};
148*/
149