Index

zydeco / 7457fba

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

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
803 Sep 2023 23:177457fbaImGui bringupJosh Stockin131G

Blob @ zydeco / src / Engine.cpp

text/plain3376 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#include "GLRenderObjectBackground.hpp"
13#include "GLRenderObjectRainbowTriangle.hpp"
14#include "GLRenderObjectImGui.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 auto imgui = new GLRenderObjectImGui {};
40
41
42
43 r_event_handler.RegisterQuitEventSubscriber(this);
44 std::atomic_init(&m_aIsExiting, false);
45}
46
47Engine::~Engine()
48{
49 LOGGER.Log(Logger::TRACE, "~Engine()");
50}
51
52void Engine::OnQuitEvent()
53{
54 LOGGER.Log(Logger::VERBOSE, "OnQuitEvent(): Quit event received");
55
56 m_aIsExiting.store(true);
57}
58
59void Engine::Execute()
60{
61 LOGGER.Log(Logger::TRACE, "Execute()");
62
63 // Called from main()
64 LOGGER.Log(Logger::INFO, "Execute(): Entering engine main loop");
65
66 // Create and start subsystem threads
67 LOGGER.Log(Logger::DEBUG, "Execute(): Spawning subsystem threads");
68
69 ThreadLooping event_thread {"Event Handler", m_rEventHandler};
70 m_threads.push_back(&event_thread);
71 ThreadLooping timer_thread {"Core Timer", m_rCoreTimer};
72 m_threads.push_back(&timer_thread);
73 ThreadLooping render_thread {"Renderer", m_rRenderer};
74 m_threads.push_back(&render_thread);
75
76 for (auto* thread : m_threads)
77 {
78 thread->Start();
79 }
80
81 // Main thread busy wait until signalled to exit, or until a thread exits
82 m_rCoreTimer.SetTimeout(1000);
83 m_rCoreTimer.Start();
84 while (m_aIsExiting.load() == false)
85 {
86 // While waiting: periodically run debug output commands
87 if (m_rCoreTimer.IsExpired())
88 {
89 LOGGER.Log(Logger::VERBOSE, "Execute(): Dispatching debug commands");
90 LOGGER.Log(Logger::VERBOSE, "Execute(): Time: {}", *m_rCoreTimer.GetGlobalTimePointer());
91 m_rRenderer.UpdateDebug();
92 m_rCoreTimer.Reset();
93 m_rCoreTimer.Start();
94 }
95
96 // Check for any thread exit
97 for (auto* thread : m_threads)
98 {
99 if (thread->IsRunning() == false)
100 {
101 m_aIsExiting.store(true);
102 break;
103 }
104 }
105 }
106
107 // Subsystem signaled exiting
108 LOGGER.Log(Logger::DEBUG, "Execute(): Signal to quit. Terminating threads...");
109
110 // Signal any running threads to terminate, and wait for termination
111 for (auto* thread : m_threads)
112 {
113 thread->Terminate();
114 thread->WaitUntilFinished();
115 }
116
117 // All threads terminated. Exit main engine loop...
118 LOGGER.Log(Logger::INFO, "Execute(): Exiting engine loop (thread handler)");
119}
120