Index

zydeco / 5f524c5

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

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
703 Sep 2023 16:015f524c5OpenGL render abstractionsJosh Stockin14816G

Blob @ zydeco / src / Engine.cpp

text/plain3296 bytesdownload raw
1#include <chrono>
2#include <atomic>
3
4#include "ZydecoCommon.hpp"
5#include "Engine.hpp"
6#include "Renderer.hpp"
7#include "ThreadLooping.hpp"
8#include "IEventHandler.hpp"
9#include "IWindow.hpp"
10#include "ITimer.hpp"
11
12
13#include "GLRenderObjectBackground.hpp"
14#include "GLRenderObjectRainbowTriangle.hpp"
15
16
17Logger LOGGER("Engine");
18
19
20Engine::Engine(IEventHandler& r_event_handler, ITimer& r_core_timer, Renderer& r_renderer):
21 m_rEventHandler(r_event_handler),
22 m_rCoreTimer(r_core_timer),
23 m_rRenderer(r_renderer)
24{
25 LOGGER.Log(Logger::TRACE, "Engine()");
26
27
28
29 // <in some game logic thread>
30 auto bg = new GLRenderObjectBackground {};
31 // GLRenderObject.RenderSetUniform<var count, var type>("uniform name", { pointers to vars } )
32 bg->RenderSetUniform<1, unsigned int>("time", { r_core_timer.GetGlobalTimePointer() });
33
34
35 // <in some other game logic thread>
36 auto tringle = new GLRenderObjectRainbowTriangle {};
37 tringle->RenderSetUniform<1, unsigned int>("time", { r_core_timer.GetGlobalTimePointer() });
38
39
40
41 r_event_handler.RegisterQuitEventSubscriber(this);
42 std::atomic_init(&m_aIsExiting, false);
43}
44
45Engine::~Engine()
46{
47 LOGGER.Log(Logger::TRACE, "~Engine()");
48}
49
50void Engine::OnQuitEvent()
51{
52 LOGGER.Log(Logger::VERBOSE, "OnQuitEvent(): Quit event received");
53
54 m_aIsExiting.store(true);
55}
56
57void Engine::Execute()
58{
59 LOGGER.Log(Logger::TRACE, "Execute()");
60
61 // Called from main()
62 LOGGER.Log(Logger::INFO, "Execute(): Entering engine main loop");
63
64 // Create and start subsystem threads
65 LOGGER.Log(Logger::DEBUG, "Execute(): Spawning subsystem threads");
66
67 ThreadLooping event_thread {"Event Handler", m_rEventHandler};
68 m_threads.push_back(&event_thread);
69 ThreadLooping timer_thread {"Core Timer", m_rCoreTimer};
70 m_threads.push_back(&timer_thread);
71 ThreadLooping render_thread {"Renderer", m_rRenderer};
72 m_threads.push_back(&render_thread);
73
74 for (auto* thread : m_threads)
75 {
76 thread->Start();
77 }
78
79 // Main thread busy wait until signalled to exit, or until a thread exits
80 m_rCoreTimer.SetTimeout(1000);
81 m_rCoreTimer.Start();
82 while (m_aIsExiting.load() == false)
83 {
84 // While waiting: periodically run debug output commands
85 if (m_rCoreTimer.IsExpired())
86 {
87 LOGGER.Log(Logger::VERBOSE, "Execute(): Dispatching debug commands");
88 LOGGER.Log(Logger::VERBOSE, "Execute(): Time: {}", *m_rCoreTimer.GetGlobalTimePointer());
89 m_rRenderer.UpdateDebug();
90 m_rCoreTimer.Reset();
91 m_rCoreTimer.Start();
92 }
93
94 // Check for any thread exit
95 for (auto* thread : m_threads)
96 {
97 if (thread->IsRunning() == false)
98 {
99 m_aIsExiting.store(true);
100 break;
101 }
102 }
103 }
104
105 // Subsystem signaled exiting
106 LOGGER.Log(Logger::DEBUG, "Execute(): Signal to quit. Terminating threads...");
107
108 // Signal any running threads to terminate, and wait for termination
109 for (auto* thread : m_threads)
110 {
111 thread->Terminate();
112 thread->WaitUntilFinished();
113 }
114
115 // All threads terminated. Exit main engine loop...
116 LOGGER.Log(Logger::INFO, "Execute(): Exiting engine loop (thread handler)");
117}
118