Index

zydeco / 0dd781a

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

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
405 Aug 2023 20:500dd781aCreate event handling and threads structureJosh Stockin11470G

Blob @ zydeco / src / Engine.cpp

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