History

INtroducing th eGraphics Engine to group al the graphics related (render and gpu) elements

Sam Gateau committed 8 years ago

Commit 0f3cb0f1 parent acab1c715 files · +686 −320Browse files

Showing the changes to interface/src/graphics/GraphicsEngine.cpp (1 of 15 files). Show all

Unified · Split

interface/src/graphics/GraphicsEngine.cpp+167−0
@@ -0,0 +1,167 @@
1+//
2+// GraphicsEngine.cpp
3+//
4+// Created by Sam Gateau on 29/6/2018.
5+// Copyright 2018 High Fidelity, Inc.
6+//
7+// Distributed under the Apache License, Version 2.0.
8+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
9+//
10+#include "GraphicsEngine.h"
11+
12+#include <shared/GlobalAppProperties.h>
13+
14+#include "WorldBox.h"
15+#include "LODManager.h"
16+
17+#include <GeometryCache.h>
18+#include <TextureCache.h>
19+#include <UpdateSceneTask.h>
20+#include <RenderViewTask.h>
21+#include <SecondaryCamera.h>
22+
23+#include "RenderEventHandler.h"
24+
25+#include <gpu/Batch.h>
26+#include <gpu/Context.h>
27+#include <gpu/gl/GLBackend.h>
28+
29+GraphicsEngine::GraphicsEngine() {
30+}
31+
32+GraphicsEngine::~GraphicsEngine() {
33+}
34+
35+void GraphicsEngine::initializeGPU(GLWidget* glwidget) {
36+
37+ // Build an offscreen GL context for the main thread.
38+ _offscreenContext = new OffscreenGLCanvas();
39+ _offscreenContext->setObjectName("MainThreadContext");
40+ _offscreenContext->create(glwidget->qglContext());
41+ if (!_offscreenContext->makeCurrent()) {
42+ qFatal("Unable to make offscreen context current");
43+ }
44+ _offscreenContext->doneCurrent();
45+ _offscreenContext->setThreadContext();
46+
47+ _renderEventHandler = new RenderEventHandler(glwidget->qglContext());
48+ if (!_offscreenContext->makeCurrent()) {
49+ qFatal("Unable to make offscreen context current");
50+ }
51+
52+ // Requires the window context, because that's what's used in the actual rendering
53+ // and the GPU backend will make things like the VAO which cannot be shared across
54+ // contexts
55+ glwidget->makeCurrent();
56+ gpu::Context::init<gpu::gl::GLBackend>();
57+ qApp->setProperty(hifi::properties::gl::MAKE_PROGRAM_CALLBACK,
58+ QVariant::fromValue((void*)(&gpu::gl::GLBackend::makeProgram)));
59+ glwidget->makeCurrent();
60+ _gpuContext = std::make_shared<gpu::Context>();
61+
62+ DependencyManager::get<TextureCache>()->setGPUContext(_gpuContext);
63+
64+ // Restore the default main thread context
65+ _offscreenContext->makeCurrent();
66+}
67+
68+void GraphicsEngine::initializeRender(bool disableDeferred) {
69+
70+ // Set up the render engine
71+ render::CullFunctor cullFunctor = LODManager::shouldRender;
72+ _renderEngine->addJob<UpdateSceneTask>("UpdateScene");
73+#ifndef Q_OS_ANDROID
74+ _renderEngine->addJob<SecondaryCameraRenderTask>("SecondaryCameraJob", cullFunctor, !disableDeferred);
75+#endif
76+ _renderEngine->addJob<RenderViewTask>("RenderMainView", cullFunctor, !disableDeferred, render::ItemKey::TAG_BITS_0, render::ItemKey::TAG_BITS_0);
77+ _renderEngine->load();
78+ _renderEngine->registerScene(_renderScene);
79+
80+ // Now that OpenGL is initialized, we are sure we have a valid context and can create the various pipeline shaders with success.
81+ DependencyManager::get<GeometryCache>()->initializeShapePipelines();
82+
83+
84+}
85+
86+void GraphicsEngine::startup() {
87+
88+
89+ static_cast<RenderEventHandler*>(_renderEventHandler)->resumeThread();
90+}
91+
92+void GraphicsEngine::shutdown() {
93+ // The cleanup process enqueues the transactions but does not process them. Calling this here will force the actual
94+ // removal of the items.
95+ // See https://highfidelity.fogbugz.com/f/cases/5328
96+ _renderScene->enqueueFrame(); // flush all the transactions
97+ _renderScene->processTransactionQueue(); // process and apply deletions
98+
99+ _gpuContext->shutdown();
100+
101+
102+ // shutdown render engine
103+ _renderScene = nullptr;
104+ _renderEngine = nullptr;
105+}
106+
107+
108+void GraphicsEngine::render_runRenderFrame(RenderArgs* renderArgs) {
109+ PROFILE_RANGE(render, __FUNCTION__);
110+ PerformanceTimer perfTimer("render");
111+// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::runRenderFrame()");
112+
113+ // The pending changes collecting the changes here
114+ render::Transaction transaction;
115+
116+ // this is not in use at all anymore
117+ //if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderEntities()) {
118+ // render models...
119+ // PerformanceTimer perfTimer("entities");
120+ // PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
121+ // "Application::runRenderFrame() ... entities...");
122+
123+ //RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE;
124+
125+ //renderArgs->_debugFlags = renderDebugFlags;
126+ //}
127+
128+ // Make sure the WorldBox is in the scene
129+ // For the record, this one RenderItem is the first one we created and added to the scene.
130+ // We could move that code elsewhere but you know...
131+ if (!render::Item::isValidID(WorldBoxRenderData::_item)) {
132+ auto worldBoxRenderData = std::make_shared<WorldBoxRenderData>();
133+ auto worldBoxRenderPayload = std::make_shared<WorldBoxRenderData::Payload>(worldBoxRenderData);
134+
135+ WorldBoxRenderData::_item = _renderScene->allocateID();
136+
137+ transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload);
138+ _renderScene->enqueueTransaction(transaction);
139+ }
140+
141+ {
142+ // PerformanceTimer perfTimer("EngineRun");
143+ _renderEngine->getRenderContext()->args = renderArgs;
144+ _renderEngine->run();
145+ }
146+}
147+
148+static const unsigned int THROTTLED_SIM_FRAMERATE = 15;
149+static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SIM_FRAMERATE;
150+
151+
152+
153+
154+bool GraphicsEngine::shouldPaint() const {
155+
156+ // Throttle if requested
157+ if ((static_cast<RenderEventHandler*>(_renderEventHandler)->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) {
158+ return false;
159+ }
160+
161+ return true;
162+}
163+
164+bool GraphicsEngine::checkPendingRenderEvent() {
165+ bool expected = false;
166+ return (_renderEventHandler && static_cast<RenderEventHandler*>(_renderEventHandler)->_pendingRenderEvent.compare_exchange_strong(expected, true));
167+}