mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 18:26:26 +02:00
INtroducing th eGraphics Engine to group al the graphics related (render and gpu) elements
This commit is contained in:
parent
acab1c7203
commit
0f3cb0fb84
15 changed files with 686 additions and 320 deletions
|
@ -83,7 +83,7 @@
|
||||||
#include <FramebufferCache.h>
|
#include <FramebufferCache.h>
|
||||||
#include <gpu/Batch.h>
|
#include <gpu/Batch.h>
|
||||||
#include <gpu/Context.h>
|
#include <gpu/Context.h>
|
||||||
#include <gpu/gl/GLBackend.h>
|
//#include <gpu/gl/GLBackend.h>
|
||||||
#include <InfoView.h>
|
#include <InfoView.h>
|
||||||
#include <input-plugins/InputPlugin.h>
|
#include <input-plugins/InputPlugin.h>
|
||||||
#include <controllers/UserInputMapper.h>
|
#include <controllers/UserInputMapper.h>
|
||||||
|
@ -116,8 +116,8 @@
|
||||||
#include <plugins/SteamClientPlugin.h>
|
#include <plugins/SteamClientPlugin.h>
|
||||||
#include <plugins/InputConfiguration.h>
|
#include <plugins/InputConfiguration.h>
|
||||||
#include <RecordingScriptingInterface.h>
|
#include <RecordingScriptingInterface.h>
|
||||||
#include <UpdateSceneTask.h>
|
//#include <UpdateSceneTask.h>
|
||||||
#include <RenderViewTask.h>
|
//#include <RenderViewTask.h>
|
||||||
#include <SecondaryCamera.h>
|
#include <SecondaryCamera.h>
|
||||||
#include <ResourceCache.h>
|
#include <ResourceCache.h>
|
||||||
#include <ResourceRequest.h>
|
#include <ResourceRequest.h>
|
||||||
|
@ -247,71 +247,7 @@ extern "C" {
|
||||||
#include "AndroidHelper.h"
|
#include "AndroidHelper.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum ApplicationEvent {
|
#include "graphics/RenderEventHandler.h"
|
||||||
// Execute a lambda function
|
|
||||||
Lambda = QEvent::User + 1,
|
|
||||||
// Trigger the next render
|
|
||||||
Render,
|
|
||||||
// Trigger the next idle
|
|
||||||
Idle,
|
|
||||||
};
|
|
||||||
|
|
||||||
class RenderEventHandler : public QObject {
|
|
||||||
using Parent = QObject;
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
RenderEventHandler(QOpenGLContext* context) {
|
|
||||||
_renderContext = new OffscreenGLCanvas();
|
|
||||||
_renderContext->setObjectName("RenderContext");
|
|
||||||
_renderContext->create(context);
|
|
||||||
if (!_renderContext->makeCurrent()) {
|
|
||||||
qFatal("Unable to make rendering context current");
|
|
||||||
}
|
|
||||||
_renderContext->doneCurrent();
|
|
||||||
|
|
||||||
// Deleting the object with automatically shutdown the thread
|
|
||||||
connect(qApp, &QCoreApplication::aboutToQuit, this, &QObject::deleteLater);
|
|
||||||
|
|
||||||
// Transfer to a new thread
|
|
||||||
moveToNewNamedThread(this, "RenderThread", [this](QThread* renderThread) {
|
|
||||||
hifi::qt::addBlockingForbiddenThread("Render", renderThread);
|
|
||||||
_renderContext->moveToThreadWithContext(renderThread);
|
|
||||||
qApp->_lastTimeRendered.start();
|
|
||||||
}, std::bind(&RenderEventHandler::initialize, this), QThread::HighestPriority);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void initialize() {
|
|
||||||
setObjectName("Render");
|
|
||||||
PROFILE_SET_THREAD_NAME("Render");
|
|
||||||
setCrashAnnotation("render_thread_id", std::to_string((size_t)QThread::currentThreadId()));
|
|
||||||
if (!_renderContext->makeCurrent()) {
|
|
||||||
qFatal("Unable to make rendering context current on render thread");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void render() {
|
|
||||||
if (qApp->shouldPaint()) {
|
|
||||||
qApp->paintGL();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool event(QEvent* event) override {
|
|
||||||
switch ((int)event->type()) {
|
|
||||||
case ApplicationEvent::Render:
|
|
||||||
render();
|
|
||||||
qApp->_pendingRenderEvent.store(false);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return Parent::event(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
OffscreenGLCanvas* _renderContext { nullptr };
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(trace_app_input_mouse, "trace.app.input.mouse")
|
Q_LOGGING_CATEGORY(trace_app_input_mouse, "trace.app.input.mouse")
|
||||||
|
|
||||||
|
@ -2254,7 +2190,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
DependencyManager::get<TabletScriptingInterface>()->preloadSounds();
|
DependencyManager::get<TabletScriptingInterface>()->preloadSounds();
|
||||||
|
|
||||||
_pendingIdleEvent = false;
|
_pendingIdleEvent = false;
|
||||||
_pendingRenderEvent = false;
|
// _pendingRenderEvent = false;
|
||||||
|
_graphicsEngine.startup();
|
||||||
|
|
||||||
qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID());
|
qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID());
|
||||||
|
|
||||||
|
@ -2469,8 +2406,8 @@ void Application::cleanupBeforeQuit() {
|
||||||
// The cleanup process enqueues the transactions but does not process them. Calling this here will force the actual
|
// The cleanup process enqueues the transactions but does not process them. Calling this here will force the actual
|
||||||
// removal of the items.
|
// removal of the items.
|
||||||
// See https://highfidelity.fogbugz.com/f/cases/5328
|
// See https://highfidelity.fogbugz.com/f/cases/5328
|
||||||
_main3DScene->enqueueFrame(); // flush all the transactions
|
// _main3DScene->enqueueFrame(); // flush all the transactions
|
||||||
_main3DScene->processTransactionQueue(); // process and apply deletions
|
// _main3DScene->processTransactionQueue(); // process and apply deletions
|
||||||
|
|
||||||
// first stop all timers directly or by invokeMethod
|
// first stop all timers directly or by invokeMethod
|
||||||
// depending on what thread they run in
|
// depending on what thread they run in
|
||||||
|
@ -2485,7 +2422,7 @@ void Application::cleanupBeforeQuit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_window->saveGeometry();
|
_window->saveGeometry();
|
||||||
_gpuContext->shutdown();
|
// _gpuContext->shutdown();
|
||||||
|
|
||||||
// Destroy third party processes after scripts have finished using them.
|
// Destroy third party processes after scripts have finished using them.
|
||||||
#ifdef HAVE_DDE
|
#ifdef HAVE_DDE
|
||||||
|
@ -2539,9 +2476,10 @@ Application::~Application() {
|
||||||
assert(_shapeManager.getNumShapes() == 0);
|
assert(_shapeManager.getNumShapes() == 0);
|
||||||
|
|
||||||
// shutdown render engine
|
// shutdown render engine
|
||||||
_main3DScene = nullptr;
|
//_main3DScene = nullptr;
|
||||||
_renderEngine = nullptr;
|
//_renderEngine = nullptr;
|
||||||
|
_graphicsEngine.shutdown();
|
||||||
|
|
||||||
_gameWorkload.shutdown();
|
_gameWorkload.shutdown();
|
||||||
|
|
||||||
DependencyManager::destroy<Preferences>();
|
DependencyManager::destroy<Preferences>();
|
||||||
|
@ -2655,7 +2593,7 @@ void Application::initializeGL() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build an offscreen GL context for the main thread.
|
/* // Build an offscreen GL context for the main thread.
|
||||||
_offscreenContext = new OffscreenGLCanvas();
|
_offscreenContext = new OffscreenGLCanvas();
|
||||||
_offscreenContext->setObjectName("MainThreadContext");
|
_offscreenContext->setObjectName("MainThreadContext");
|
||||||
_offscreenContext->create(_glWidget->qglContext());
|
_offscreenContext->create(_glWidget->qglContext());
|
||||||
|
@ -2664,34 +2602,36 @@ void Application::initializeGL() {
|
||||||
}
|
}
|
||||||
_offscreenContext->doneCurrent();
|
_offscreenContext->doneCurrent();
|
||||||
_offscreenContext->setThreadContext();
|
_offscreenContext->setThreadContext();
|
||||||
|
*/
|
||||||
_glWidget->makeCurrent();
|
_glWidget->makeCurrent();
|
||||||
glClearColor(0.2f, 0.2f, 0.2f, 1);
|
glClearColor(0.2f, 0.2f, 0.2f, 1);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
_glWidget->swapBuffers();
|
_glWidget->swapBuffers();
|
||||||
|
|
||||||
// Move the GL widget context to the render event handler thread
|
// Move the GL widget context to the render event handler thread
|
||||||
_renderEventHandler = new RenderEventHandler(_glWidget->qglContext());
|
// _renderEventHandler = new RenderEventHandler(_glWidget->qglContext());
|
||||||
if (!_offscreenContext->makeCurrent()) {
|
// if (!_offscreenContext->makeCurrent()) {
|
||||||
qFatal("Unable to make offscreen context current");
|
// qFatal("Unable to make offscreen context current");
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Create the GPU backend
|
// Create the GPU backend
|
||||||
|
|
||||||
// Requires the window context, because that's what's used in the actual rendering
|
//// Requires the window context, because that's what's used in the actual rendering
|
||||||
// and the GPU backend will make things like the VAO which cannot be shared across
|
//// and the GPU backend will make things like the VAO which cannot be shared across
|
||||||
// contexts
|
//// contexts
|
||||||
_glWidget->makeCurrent();
|
//_glWidget->makeCurrent();
|
||||||
gpu::Context::init<gpu::gl::GLBackend>();
|
//gpu::Context::init<gpu::gl::GLBackend>();
|
||||||
qApp->setProperty(hifi::properties::gl::MAKE_PROGRAM_CALLBACK,
|
//qApp->setProperty(hifi::properties::gl::MAKE_PROGRAM_CALLBACK,
|
||||||
QVariant::fromValue((void*)(&gpu::gl::GLBackend::makeProgram)));
|
// QVariant::fromValue((void*)(&gpu::gl::GLBackend::makeProgram)));
|
||||||
_glWidget->makeCurrent();
|
//_glWidget->makeCurrent();
|
||||||
_gpuContext = std::make_shared<gpu::Context>();
|
//_gpuContext = std::make_shared<gpu::Context>();
|
||||||
|
|
||||||
DependencyManager::get<TextureCache>()->setGPUContext(_gpuContext);
|
//DependencyManager::get<TextureCache>()->setGPUContext(_gpuContext);
|
||||||
|
|
||||||
// Restore the default main thread context
|
//// Restore the default main thread context
|
||||||
_offscreenContext->makeCurrent();
|
//_offscreenContext->makeCurrent();
|
||||||
|
|
||||||
|
_graphicsEngine.initializeGPU(_glWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const QString SPLASH_SKYBOX{ "{\"ProceduralEntity\":{ \"version\":2, \"shaderUrl\":\"qrc:///shaders/splashSkybox.frag\" } }" };
|
static const QString SPLASH_SKYBOX{ "{\"ProceduralEntity\":{ \"version\":2, \"shaderUrl\":\"qrc:///shaders/splashSkybox.frag\" } }" };
|
||||||
|
@ -2705,7 +2645,7 @@ void Application::initializeDisplayPlugins() {
|
||||||
// Once time initialization code
|
// Once time initialization code
|
||||||
DisplayPluginPointer targetDisplayPlugin;
|
DisplayPluginPointer targetDisplayPlugin;
|
||||||
foreach(auto displayPlugin, displayPlugins) {
|
foreach(auto displayPlugin, displayPlugins) {
|
||||||
displayPlugin->setContext(_gpuContext);
|
displayPlugin->setContext(_graphicsEngine.getGPUContext());
|
||||||
if (displayPlugin->getName() == lastActiveDisplayPluginName) {
|
if (displayPlugin->getName() == lastActiveDisplayPluginName) {
|
||||||
targetDisplayPlugin = displayPlugin;
|
targetDisplayPlugin = displayPlugin;
|
||||||
}
|
}
|
||||||
|
@ -2719,14 +2659,14 @@ void Application::initializeDisplayPlugins() {
|
||||||
setDisplayPlugin(defaultDisplayPlugin);
|
setDisplayPlugin(defaultDisplayPlugin);
|
||||||
|
|
||||||
// Now set the desired plugin if it's not the same as the default plugin
|
// Now set the desired plugin if it's not the same as the default plugin
|
||||||
if (targetDisplayPlugin != defaultDisplayPlugin) {
|
if (targetDisplayPlugin && (targetDisplayPlugin != defaultDisplayPlugin)) {
|
||||||
setDisplayPlugin(targetDisplayPlugin);
|
setDisplayPlugin(targetDisplayPlugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Submit a default frame to render until the engine starts up
|
// Submit a default frame to render until the engine starts up
|
||||||
updateRenderArgs(0.0f);
|
updateRenderArgs(0.0f);
|
||||||
|
|
||||||
_offscreenContext->makeCurrent();
|
_graphicsEngine._offscreenContext->makeCurrent();
|
||||||
|
|
||||||
#define ENABLE_SPLASH_FRAME 0
|
#define ENABLE_SPLASH_FRAME 0
|
||||||
#if ENABLE_SPLASH_FRAME
|
#if ENABLE_SPLASH_FRAME
|
||||||
|
@ -2769,11 +2709,12 @@ void Application::initializeDisplayPlugins() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::initializeRenderEngine() {
|
void Application::initializeRenderEngine() {
|
||||||
_offscreenContext->makeCurrent();
|
// _offscreenContext->makeCurrent();
|
||||||
|
|
||||||
// FIXME: on low end systems os the shaders take up to 1 minute to compile, so we pause the deadlock watchdog thread.
|
// FIXME: on low end systems os the shaders take up to 1 minute to compile, so we pause the deadlock watchdog thread.
|
||||||
DeadlockWatchdogThread::withPause([&] {
|
DeadlockWatchdogThread::withPause([&] {
|
||||||
// Set up the render engine
|
_graphicsEngine.initializeRender(DISABLE_DEFERRED);
|
||||||
|
/* // Set up the render engine
|
||||||
render::CullFunctor cullFunctor = LODManager::shouldRender;
|
render::CullFunctor cullFunctor = LODManager::shouldRender;
|
||||||
_renderEngine->addJob<UpdateSceneTask>("UpdateScene");
|
_renderEngine->addJob<UpdateSceneTask>("UpdateScene");
|
||||||
#ifndef Q_OS_ANDROID
|
#ifndef Q_OS_ANDROID
|
||||||
|
@ -2785,7 +2726,7 @@ void Application::initializeRenderEngine() {
|
||||||
|
|
||||||
// Now that OpenGL is initialized, we are sure we have a valid context and can create the various pipeline shaders with success.
|
// Now that OpenGL is initialized, we are sure we have a valid context and can create the various pipeline shaders with success.
|
||||||
DependencyManager::get<GeometryCache>()->initializeShapePipelines();
|
DependencyManager::get<GeometryCache>()->initializeShapePipelines();
|
||||||
});
|
*/ });
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void setupPreferences();
|
extern void setupPreferences();
|
||||||
|
@ -2999,7 +2940,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) {
|
||||||
surfaceContext->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
|
surfaceContext->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
|
||||||
surfaceContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
surfaceContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
|
||||||
surfaceContext->setContextProperty("Scene", DependencyManager::get<SceneScriptingInterface>().data());
|
surfaceContext->setContextProperty("Scene", DependencyManager::get<SceneScriptingInterface>().data());
|
||||||
surfaceContext->setContextProperty("Render", _renderEngine->getConfiguration().get());
|
surfaceContext->setContextProperty("Render", _graphicsEngine.getRenderEngine()->getConfiguration().get());
|
||||||
surfaceContext->setContextProperty("Workload", _gameWorkload._engine->getConfiguration().get());
|
surfaceContext->setContextProperty("Workload", _gameWorkload._engine->getConfiguration().get());
|
||||||
surfaceContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface());
|
surfaceContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface());
|
||||||
surfaceContext->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
|
surfaceContext->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
|
||||||
|
@ -3454,8 +3395,8 @@ void Application::onPresent(quint32 frameCount) {
|
||||||
postEvent(this, new QEvent((QEvent::Type)ApplicationEvent::Idle), Qt::HighEventPriority);
|
postEvent(this, new QEvent((QEvent::Type)ApplicationEvent::Idle), Qt::HighEventPriority);
|
||||||
}
|
}
|
||||||
expected = false;
|
expected = false;
|
||||||
if (_renderEventHandler && !isAboutToQuit() && _pendingRenderEvent.compare_exchange_strong(expected, true)) {
|
if (_graphicsEngine.checkPendingRenderEvent() && !isAboutToQuit()) {
|
||||||
postEvent(_renderEventHandler, new QEvent((QEvent::Type)ApplicationEvent::Render));
|
postEvent(_graphicsEngine._renderEventHandler, new QEvent((QEvent::Type)ApplicationEvent::Render));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4229,7 +4170,8 @@ bool Application::shouldPaint() const {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Throttle if requested
|
// Throttle if requested
|
||||||
if (displayPlugin->isThrottled() && (_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) {
|
//if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) {
|
||||||
|
if (displayPlugin->isThrottled() && _graphicsEngine.shouldPaint()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4481,7 +4423,7 @@ void Application::idle() {
|
||||||
if (offscreenUi->size() != fromGlm(uiSize)) {
|
if (offscreenUi->size() != fromGlm(uiSize)) {
|
||||||
qCDebug(interfaceapp) << "Device pixel ratio changed, triggering resize to " << uiSize;
|
qCDebug(interfaceapp) << "Device pixel ratio changed, triggering resize to " << uiSize;
|
||||||
offscreenUi->resize(fromGlm(uiSize));
|
offscreenUi->resize(fromGlm(uiSize));
|
||||||
_offscreenContext->makeCurrent();
|
_graphicsEngine._offscreenContext->makeCurrent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4493,8 +4435,8 @@ void Application::idle() {
|
||||||
PROFILE_COUNTER_IF_CHANGED(app, "pendingDownloads", int, ResourceCache::getPendingRequestCount());
|
PROFILE_COUNTER_IF_CHANGED(app, "pendingDownloads", int, ResourceCache::getPendingRequestCount());
|
||||||
PROFILE_COUNTER_IF_CHANGED(app, "currentProcessing", int, DependencyManager::get<StatTracker>()->getStat("Processing").toInt());
|
PROFILE_COUNTER_IF_CHANGED(app, "currentProcessing", int, DependencyManager::get<StatTracker>()->getStat("Processing").toInt());
|
||||||
PROFILE_COUNTER_IF_CHANGED(app, "pendingProcessing", int, DependencyManager::get<StatTracker>()->getStat("PendingProcessing").toInt());
|
PROFILE_COUNTER_IF_CHANGED(app, "pendingProcessing", int, DependencyManager::get<StatTracker>()->getStat("PendingProcessing").toInt());
|
||||||
auto renderConfig = _renderEngine->getConfiguration();
|
auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration();
|
||||||
PROFILE_COUNTER_IF_CHANGED(render, "gpuTime", float, (float)_gpuContext->getFrameTimerGPUAverage());
|
PROFILE_COUNTER_IF_CHANGED(render, "gpuTime", float, (float)_graphicsEngine.getGPUContext()->getFrameTimerGPUAverage());
|
||||||
auto opaqueRangeTimer = renderConfig->getConfig("OpaqueRangeTimer");
|
auto opaqueRangeTimer = renderConfig->getConfig("OpaqueRangeTimer");
|
||||||
auto linearDepth = renderConfig->getConfig("LinearDepth");
|
auto linearDepth = renderConfig->getConfig("LinearDepth");
|
||||||
auto surfaceGeometry = renderConfig->getConfig("SurfaceGeometry");
|
auto surfaceGeometry = renderConfig->getConfig("SurfaceGeometry");
|
||||||
|
@ -4536,7 +4478,7 @@ void Application::idle() {
|
||||||
bool showWarnings = getLogger()->extraDebugging();
|
bool showWarnings = getLogger()->extraDebugging();
|
||||||
PerformanceWarning warn(showWarnings, "idle()");
|
PerformanceWarning warn(showWarnings, "idle()");
|
||||||
|
|
||||||
if (!_offscreenContext->makeCurrent()) {
|
if (!_graphicsEngine._offscreenContext->makeCurrent()) {
|
||||||
qFatal("Unable to make main thread context current");
|
qFatal("Unable to make main thread context current");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4866,12 +4808,12 @@ QVector<EntityItemID> Application::pasteEntities(float x, float y, float z) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::init() {
|
void Application::init() {
|
||||||
_offscreenContext->makeCurrent();
|
_graphicsEngine._offscreenContext->makeCurrent();
|
||||||
// Make sure Login state is up to date
|
// Make sure Login state is up to date
|
||||||
DependencyManager::get<DialogsManager>()->toggleLoginDialog();
|
DependencyManager::get<DialogsManager>()->toggleLoginDialog();
|
||||||
if (!DISABLE_DEFERRED) {
|
// if (!DISABLE_DEFERRED) {
|
||||||
DependencyManager::get<DeferredLightingEffect>()->init();
|
// DependencyManager::get<DeferredLightingEffect>()->init();
|
||||||
}
|
// }
|
||||||
DependencyManager::get<AvatarManager>()->init();
|
DependencyManager::get<AvatarManager>()->init();
|
||||||
|
|
||||||
_timerStart.start();
|
_timerStart.start();
|
||||||
|
@ -4940,7 +4882,7 @@ void Application::init() {
|
||||||
}
|
}
|
||||||
}, Qt::QueuedConnection);
|
}, Qt::QueuedConnection);
|
||||||
|
|
||||||
_gameWorkload.startup(getEntities()->getWorkloadSpace(), _main3DScene, _entitySimulation);
|
_gameWorkload.startup(getEntities()->getWorkloadSpace(), _graphicsEngine.getRenderScene(), _entitySimulation);
|
||||||
_entitySimulation->setWorkloadSpace(getEntities()->getWorkloadSpace());
|
_entitySimulation->setWorkloadSpace(getEntities()->getWorkloadSpace());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4974,7 +4916,7 @@ void Application::updateLOD(float deltaTime) const {
|
||||||
// adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode
|
// adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode
|
||||||
if (!isThrottleRendering()) {
|
if (!isThrottleRendering()) {
|
||||||
float presentTime = getActiveDisplayPlugin()->getAveragePresentTime();
|
float presentTime = getActiveDisplayPlugin()->getAveragePresentTime();
|
||||||
float engineRunTime = (float)(_renderEngine->getConfiguration().get()->getCPURunTime());
|
float engineRunTime = (float)(_graphicsEngine.getRenderEngine()->getConfiguration().get()->getCPURunTime());
|
||||||
float gpuTime = getGPUContext()->getFrameTimerGPUAverage();
|
float gpuTime = getGPUContext()->getFrameTimerGPUAverage();
|
||||||
auto lodManager = DependencyManager::get<LODManager>();
|
auto lodManager = DependencyManager::get<LODManager>();
|
||||||
lodManager->setRenderTimes(presentTime, engineRunTime, gpuTime);
|
lodManager->setRenderTimes(presentTime, engineRunTime, gpuTime);
|
||||||
|
@ -5364,7 +5306,7 @@ void Application::updateSecondaryCameraViewFrustum() {
|
||||||
// camera should be.
|
// camera should be.
|
||||||
|
|
||||||
// Code based on SecondaryCameraJob
|
// Code based on SecondaryCameraJob
|
||||||
auto renderConfig = _renderEngine->getConfiguration();
|
auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration();
|
||||||
assert(renderConfig);
|
assert(renderConfig);
|
||||||
auto camera = dynamic_cast<SecondaryCameraJobConfig*>(renderConfig->getConfig("SecondaryCamera"));
|
auto camera = dynamic_cast<SecondaryCameraJobConfig*>(renderConfig->getConfig("SecondaryCamera"));
|
||||||
|
|
||||||
|
@ -5935,7 +5877,7 @@ void Application::updateRenderArgs(float deltaTime) {
|
||||||
_viewFrustum.setProjection(adjustedProjection);
|
_viewFrustum.setProjection(adjustedProjection);
|
||||||
_viewFrustum.calculate();
|
_viewFrustum.calculate();
|
||||||
}
|
}
|
||||||
appRenderArgs._renderArgs = RenderArgs(_gpuContext, lodManager->getOctreeSizeScale(),
|
appRenderArgs._renderArgs = RenderArgs(_graphicsEngine.getGPUContext(), lodManager->getOctreeSizeScale(),
|
||||||
lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
|
lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
|
||||||
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
|
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
|
||||||
appRenderArgs._renderArgs._scene = getMain3DScene();
|
appRenderArgs._renderArgs._scene = getMain3DScene();
|
||||||
|
@ -6597,7 +6539,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
||||||
scriptEngine->registerFunction("HMD", "getHUDLookAtPosition3D", HMDScriptingInterface::getHUDLookAtPosition3D, 0);
|
scriptEngine->registerFunction("HMD", "getHUDLookAtPosition3D", HMDScriptingInterface::getHUDLookAtPosition3D, 0);
|
||||||
|
|
||||||
scriptEngine->registerGlobalObject("Scene", DependencyManager::get<SceneScriptingInterface>().data());
|
scriptEngine->registerGlobalObject("Scene", DependencyManager::get<SceneScriptingInterface>().data());
|
||||||
scriptEngine->registerGlobalObject("Render", _renderEngine->getConfiguration().get());
|
scriptEngine->registerGlobalObject("Render", _graphicsEngine.getRenderEngine()->getConfiguration().get());
|
||||||
scriptEngine->registerGlobalObject("Workload", _gameWorkload._engine->getConfiguration().get());
|
scriptEngine->registerGlobalObject("Workload", _gameWorkload._engine->getConfiguration().get());
|
||||||
|
|
||||||
GraphicsScriptingInterface::registerMetaTypes(scriptEngine.data());
|
GraphicsScriptingInterface::registerMetaTypes(scriptEngine.data());
|
||||||
|
@ -8241,7 +8183,7 @@ QOpenGLContext* Application::getPrimaryContext() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::makeRenderingContextCurrent() {
|
bool Application::makeRenderingContextCurrent() {
|
||||||
return _offscreenContext->makeCurrent();
|
return _graphicsEngine._offscreenContext->makeCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::isForeground() const {
|
bool Application::isForeground() const {
|
||||||
|
|
|
@ -73,6 +73,7 @@
|
||||||
#include "UndoStackScriptingInterface.h"
|
#include "UndoStackScriptingInterface.h"
|
||||||
|
|
||||||
#include "workload/GameWorkload.h"
|
#include "workload/GameWorkload.h"
|
||||||
|
#include "graphics/GraphicsEngine.h"
|
||||||
|
|
||||||
#include <procedural/ProceduralSkybox.h>
|
#include <procedural/ProceduralSkybox.h>
|
||||||
#include <graphics/Skybox.h>
|
#include <graphics/Skybox.h>
|
||||||
|
@ -157,6 +158,7 @@ public:
|
||||||
void updateSecondaryCameraViewFrustum();
|
void updateSecondaryCameraViewFrustum();
|
||||||
|
|
||||||
void updateCamera(RenderArgs& renderArgs, float deltaTime);
|
void updateCamera(RenderArgs& renderArgs, float deltaTime);
|
||||||
|
bool shouldPaint() const;
|
||||||
void paintGL();
|
void paintGL();
|
||||||
void resizeGL();
|
void resizeGL();
|
||||||
|
|
||||||
|
@ -271,10 +273,16 @@ public:
|
||||||
void setMaxOctreePacketsPerSecond(int maxOctreePPS);
|
void setMaxOctreePacketsPerSecond(int maxOctreePPS);
|
||||||
int getMaxOctreePacketsPerSecond() const;
|
int getMaxOctreePacketsPerSecond() const;
|
||||||
|
|
||||||
render::ScenePointer getMain3DScene() override { return _main3DScene; }
|
/* render::ScenePointer getMain3DScene() override { return _main3DScene; }
|
||||||
const render::ScenePointer& getMain3DScene() const { return _main3DScene; }
|
const render::ScenePointer& getMain3DScene() const { return _main3DScene; }
|
||||||
render::EnginePointer getRenderEngine() override { return _renderEngine; }
|
render::EnginePointer getRenderEngine() override { return _renderEngine; }
|
||||||
gpu::ContextPointer getGPUContext() const { return _gpuContext; }
|
gpu::ContextPointer getGPUContext() const { return _gpuContext; }
|
||||||
|
*/
|
||||||
|
render::ScenePointer getMain3DScene() override { return _graphicsEngine.getRenderScene(); }
|
||||||
|
const render::ScenePointer& getMain3DScene() const { return _graphicsEngine.getRenderScene(); }
|
||||||
|
render::EnginePointer getRenderEngine() override { return _graphicsEngine.getRenderEngine(); }
|
||||||
|
gpu::ContextPointer getGPUContext() const { return _graphicsEngine.getGPUContext(); }
|
||||||
|
|
||||||
|
|
||||||
const GameWorkload& getGameWorkload() const { return _gameWorkload; }
|
const GameWorkload& getGameWorkload() const { return _gameWorkload; }
|
||||||
|
|
||||||
|
@ -490,7 +498,6 @@ private:
|
||||||
bool handleFileOpenEvent(QFileOpenEvent* event);
|
bool handleFileOpenEvent(QFileOpenEvent* event);
|
||||||
void cleanupBeforeQuit();
|
void cleanupBeforeQuit();
|
||||||
|
|
||||||
bool shouldPaint() const;
|
|
||||||
void idle();
|
void idle();
|
||||||
void update(float deltaTime);
|
void update(float deltaTime);
|
||||||
|
|
||||||
|
@ -510,7 +517,7 @@ private:
|
||||||
|
|
||||||
void initializeAcceptedFiles();
|
void initializeAcceptedFiles();
|
||||||
|
|
||||||
void runRenderFrame(RenderArgs* renderArgs/*, Camera& whichCamera, bool selfAvatarOnly = false*/);
|
// void runRenderFrame(RenderArgs* renderArgs/*, Camera& whichCamera, bool selfAvatarOnly = false*/);
|
||||||
|
|
||||||
bool importJSONFromURL(const QString& urlString);
|
bool importJSONFromURL(const QString& urlString);
|
||||||
bool importSVOFromURL(const QString& urlString);
|
bool importSVOFromURL(const QString& urlString);
|
||||||
|
@ -551,7 +558,7 @@ private:
|
||||||
|
|
||||||
bool _previousSessionCrashed;
|
bool _previousSessionCrashed;
|
||||||
|
|
||||||
OffscreenGLCanvas* _offscreenContext { nullptr };
|
// OffscreenGLCanvas* _offscreenContext { nullptr };
|
||||||
DisplayPluginPointer _displayPlugin;
|
DisplayPluginPointer _displayPlugin;
|
||||||
QMetaObject::Connection _displayPluginPresentConnection;
|
QMetaObject::Connection _displayPluginPresentConnection;
|
||||||
mutable std::mutex _displayPluginLock;
|
mutable std::mutex _displayPluginLock;
|
||||||
|
@ -573,7 +580,7 @@ private:
|
||||||
QTimer _minimizedWindowTimer;
|
QTimer _minimizedWindowTimer;
|
||||||
QElapsedTimer _timerStart;
|
QElapsedTimer _timerStart;
|
||||||
QElapsedTimer _lastTimeUpdated;
|
QElapsedTimer _lastTimeUpdated;
|
||||||
QElapsedTimer _lastTimeRendered;
|
// QElapsedTimer _lastTimeRendered;
|
||||||
|
|
||||||
ShapeManager _shapeManager;
|
ShapeManager _shapeManager;
|
||||||
PhysicalEntitySimulationPointer _entitySimulation;
|
PhysicalEntitySimulationPointer _entitySimulation;
|
||||||
|
@ -657,12 +664,14 @@ private:
|
||||||
|
|
||||||
quint64 _lastFaceTrackerUpdate;
|
quint64 _lastFaceTrackerUpdate;
|
||||||
|
|
||||||
render::ScenePointer _main3DScene{ new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) };
|
// render::ScenePointer _main3DScene{ new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) };
|
||||||
render::EnginePointer _renderEngine{ new render::RenderEngine() };
|
// render::EnginePointer _renderEngine{ new render::RenderEngine() };
|
||||||
gpu::ContextPointer _gpuContext; // initialized during window creation
|
// gpu::ContextPointer _gpuContext; // initialized during window creation
|
||||||
|
|
||||||
GameWorkload _gameWorkload;
|
GameWorkload _gameWorkload;
|
||||||
|
|
||||||
|
GraphicsEngine _graphicsEngine;
|
||||||
|
|
||||||
mutable QMutex _renderArgsMutex{ QMutex::Recursive };
|
mutable QMutex _renderArgsMutex{ QMutex::Recursive };
|
||||||
struct AppRenderArgs {
|
struct AppRenderArgs {
|
||||||
render::Args _renderArgs;
|
render::Args _renderArgs;
|
||||||
|
@ -720,8 +729,6 @@ private:
|
||||||
|
|
||||||
bool _keyboardDeviceHasFocus { true };
|
bool _keyboardDeviceHasFocus { true };
|
||||||
|
|
||||||
QString _returnFromFullScreenMirrorTo;
|
|
||||||
|
|
||||||
ConnectionMonitor _connectionMonitor;
|
ConnectionMonitor _connectionMonitor;
|
||||||
|
|
||||||
QTimer _addAssetToWorldResizeTimer;
|
QTimer _addAssetToWorldResizeTimer;
|
||||||
|
@ -754,12 +761,12 @@ private:
|
||||||
|
|
||||||
QUrl _avatarOverrideUrl;
|
QUrl _avatarOverrideUrl;
|
||||||
bool _saveAvatarOverrideUrl { false };
|
bool _saveAvatarOverrideUrl { false };
|
||||||
QObject* _renderEventHandler{ nullptr };
|
// QObject* _renderEventHandler{ nullptr };
|
||||||
|
|
||||||
friend class RenderEventHandler;
|
// friend class RenderEventHandler;
|
||||||
|
|
||||||
std::atomic<bool> _pendingIdleEvent { true };
|
std::atomic<bool> _pendingIdleEvent { true };
|
||||||
std::atomic<bool> _pendingRenderEvent { true };
|
// std::atomic<bool> _pendingRenderEvent { true };
|
||||||
|
|
||||||
bool quitWhenFinished { false };
|
bool quitWhenFinished { false };
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,7 +32,8 @@ void Application::paintGL() {
|
||||||
// Some plugins process message events, allowing paintGL to be called reentrantly.
|
// Some plugins process message events, allowing paintGL to be called reentrantly.
|
||||||
|
|
||||||
_renderFrameCount++;
|
_renderFrameCount++;
|
||||||
_lastTimeRendered.start();
|
// SG: Moved into the RenderEventHandler
|
||||||
|
//_lastTimeRendered.start();
|
||||||
|
|
||||||
auto lastPaintBegin = usecTimestampNow();
|
auto lastPaintBegin = usecTimestampNow();
|
||||||
PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount);
|
PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount);
|
||||||
|
@ -88,10 +89,10 @@ void Application::paintGL() {
|
||||||
|
|
||||||
{
|
{
|
||||||
PROFILE_RANGE(render, "/gpuContextReset");
|
PROFILE_RANGE(render, "/gpuContextReset");
|
||||||
_gpuContext->beginFrame(_appRenderArgs._view, HMDSensorPose);
|
_graphicsEngine.getGPUContext()->beginFrame(_appRenderArgs._view, HMDSensorPose);
|
||||||
// Reset the gpu::Context Stages
|
// Reset the gpu::Context Stages
|
||||||
// Back to the default framebuffer;
|
// Back to the default framebuffer;
|
||||||
gpu::doInBatch("Application_render::gpuContextReset", _gpuContext, [&](gpu::Batch& batch) {
|
gpu::doInBatch("Application_render::gpuContextReset", _graphicsEngine.getGPUContext(), [&](gpu::Batch& batch) {
|
||||||
batch.resetStages();
|
batch.resetStages();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -132,10 +133,10 @@ void Application::paintGL() {
|
||||||
renderArgs._hudOperator = displayPlugin->getHUDOperator();
|
renderArgs._hudOperator = displayPlugin->getHUDOperator();
|
||||||
renderArgs._hudTexture = _applicationOverlay.getOverlayTexture();
|
renderArgs._hudTexture = _applicationOverlay.getOverlayTexture();
|
||||||
renderArgs._blitFramebuffer = finalFramebuffer;
|
renderArgs._blitFramebuffer = finalFramebuffer;
|
||||||
runRenderFrame(&renderArgs);
|
_graphicsEngine.render_runRenderFrame(&renderArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto frame = _gpuContext->endFrame();
|
auto frame = _graphicsEngine.getGPUContext()->endFrame();
|
||||||
frame->frameIndex = _renderFrameCount;
|
frame->frameIndex = _renderFrameCount;
|
||||||
frame->framebuffer = finalFramebuffer;
|
frame->framebuffer = finalFramebuffer;
|
||||||
frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) {
|
frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) {
|
||||||
|
@ -163,68 +164,68 @@ void Application::paintGL() {
|
||||||
|
|
||||||
|
|
||||||
// WorldBox Render Data & rendering functions
|
// WorldBox Render Data & rendering functions
|
||||||
|
//
|
||||||
class WorldBoxRenderData {
|
//class WorldBoxRenderData {
|
||||||
public:
|
//public:
|
||||||
typedef render::Payload<WorldBoxRenderData> Payload;
|
// typedef render::Payload<WorldBoxRenderData> Payload;
|
||||||
typedef Payload::DataPointer Pointer;
|
// typedef Payload::DataPointer Pointer;
|
||||||
|
//
|
||||||
int _val = 0;
|
// int _val = 0;
|
||||||
static render::ItemID _item; // unique WorldBoxRenderData
|
// static render::ItemID _item; // unique WorldBoxRenderData
|
||||||
};
|
//};
|
||||||
|
//
|
||||||
render::ItemID WorldBoxRenderData::_item{ render::Item::INVALID_ITEM_ID };
|
//render::ItemID WorldBoxRenderData::_item{ render::Item::INVALID_ITEM_ID };
|
||||||
|
//
|
||||||
namespace render {
|
//namespace render {
|
||||||
template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); }
|
// template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); }
|
||||||
template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); }
|
// template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); }
|
||||||
template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) {
|
// template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) {
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) {
|
// if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) {
|
||||||
PerformanceTimer perfTimer("worldBox");
|
// PerformanceTimer perfTimer("worldBox");
|
||||||
|
//
|
||||||
auto& batch = *args->_batch;
|
// auto& batch = *args->_batch;
|
||||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
|
// DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
|
||||||
renderWorldBox(args, batch);
|
// renderWorldBox(args, batch);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
void Application::runRenderFrame(RenderArgs* renderArgs) {
|
//void Application::runRenderFrame(RenderArgs* renderArgs) {
|
||||||
PROFILE_RANGE(render, __FUNCTION__);
|
// PROFILE_RANGE(render, __FUNCTION__);
|
||||||
PerformanceTimer perfTimer("display");
|
// PerformanceTimer perfTimer("display");
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::runRenderFrame()");
|
// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::runRenderFrame()");
|
||||||
|
//
|
||||||
// The pending changes collecting the changes here
|
// // The pending changes collecting the changes here
|
||||||
render::Transaction transaction;
|
// render::Transaction transaction;
|
||||||
|
//
|
||||||
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderEntities()) {
|
// if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderEntities()) {
|
||||||
// render models...
|
// // render models...
|
||||||
PerformanceTimer perfTimer("entities");
|
// PerformanceTimer perfTimer("entities");
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
"Application::runRenderFrame() ... entities...");
|
// "Application::runRenderFrame() ... entities...");
|
||||||
|
//
|
||||||
RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE;
|
// RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE;
|
||||||
|
//
|
||||||
renderArgs->_debugFlags = renderDebugFlags;
|
// renderArgs->_debugFlags = renderDebugFlags;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Make sure the WorldBox is in the scene
|
// // Make sure the WorldBox is in the scene
|
||||||
// For the record, this one RenderItem is the first one we created and added to the scene.
|
// // For the record, this one RenderItem is the first one we created and added to the scene.
|
||||||
// We could move that code elsewhere but you know...
|
// // We could move that code elsewhere but you know...
|
||||||
if (!render::Item::isValidID(WorldBoxRenderData::_item)) {
|
// if (!render::Item::isValidID(WorldBoxRenderData::_item)) {
|
||||||
auto worldBoxRenderData = std::make_shared<WorldBoxRenderData>();
|
// auto worldBoxRenderData = std::make_shared<WorldBoxRenderData>();
|
||||||
auto worldBoxRenderPayload = std::make_shared<WorldBoxRenderData::Payload>(worldBoxRenderData);
|
// auto worldBoxRenderPayload = std::make_shared<WorldBoxRenderData::Payload>(worldBoxRenderData);
|
||||||
|
//
|
||||||
WorldBoxRenderData::_item = _main3DScene->allocateID();
|
// WorldBoxRenderData::_item = _main3DScene->allocateID();
|
||||||
|
//
|
||||||
transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload);
|
// transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload);
|
||||||
_main3DScene->enqueueTransaction(transaction);
|
// _main3DScene->enqueueTransaction(transaction);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
{
|
// {
|
||||||
PerformanceTimer perfTimer("EngineRun");
|
// PerformanceTimer perfTimer("EngineRun");
|
||||||
_renderEngine->getRenderContext()->args = renderArgs;
|
// _renderEngine->getRenderContext()->args = renderArgs;
|
||||||
_renderEngine->run();
|
// _renderEngine->run();
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
|
|
@ -36,114 +36,6 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
void renderWorldBox(RenderArgs* args, gpu::Batch& batch) {
|
|
||||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
|
||||||
|
|
||||||
// Show center of world
|
|
||||||
static const glm::vec3 RED(1.0f, 0.0f, 0.0f);
|
|
||||||
static const glm::vec3 GREEN(0.0f, 1.0f, 0.0f);
|
|
||||||
static const glm::vec3 BLUE(0.0f, 0.0f, 1.0f);
|
|
||||||
static const glm::vec3 GREY(0.5f, 0.5f, 0.5f);
|
|
||||||
static const glm::vec4 GREY4(0.5f, 0.5f, 0.5f, 1.0f);
|
|
||||||
|
|
||||||
static const glm::vec4 DASHED_RED(1.0f, 0.0f, 0.0f, 1.0f);
|
|
||||||
static const glm::vec4 DASHED_GREEN(0.0f, 1.0f, 0.0f, 1.0f);
|
|
||||||
static const glm::vec4 DASHED_BLUE(0.0f, 0.0f, 1.0f, 1.0f);
|
|
||||||
static const float DASH_LENGTH = 1.0f;
|
|
||||||
static const float GAP_LENGTH = 1.0f;
|
|
||||||
auto transform = Transform{};
|
|
||||||
static std::array<int, 18> geometryIds;
|
|
||||||
static std::once_flag initGeometryIds;
|
|
||||||
std::call_once(initGeometryIds, [&] {
|
|
||||||
for (size_t i = 0; i < geometryIds.size(); ++i) {
|
|
||||||
geometryIds[i] = geometryCache->allocateID();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
batch.setModelTransform(transform);
|
|
||||||
|
|
||||||
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(HALF_TREE_SCALE, 0.0f, 0.0f), RED, geometryIds[0]);
|
|
||||||
geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(-HALF_TREE_SCALE, 0.0f, 0.0f), DASHED_RED,
|
|
||||||
DASH_LENGTH, GAP_LENGTH, geometryIds[1]);
|
|
||||||
|
|
||||||
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, HALF_TREE_SCALE, 0.0f), GREEN, geometryIds[2]);
|
|
||||||
geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, -HALF_TREE_SCALE, 0.0f), DASHED_GREEN,
|
|
||||||
DASH_LENGTH, GAP_LENGTH, geometryIds[3]);
|
|
||||||
|
|
||||||
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, HALF_TREE_SCALE), BLUE, geometryIds[4]);
|
|
||||||
geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, -HALF_TREE_SCALE), DASHED_BLUE,
|
|
||||||
DASH_LENGTH, GAP_LENGTH, geometryIds[5]);
|
|
||||||
|
|
||||||
// X center boundaries
|
|
||||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f),
|
|
||||||
glm::vec3(HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f), GREY,
|
|
||||||
geometryIds[6]);
|
|
||||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f),
|
|
||||||
glm::vec3(-HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY,
|
|
||||||
geometryIds[7]);
|
|
||||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f),
|
|
||||||
glm::vec3(HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY,
|
|
||||||
geometryIds[8]);
|
|
||||||
geometryCache->renderLine(batch, glm::vec3(HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f),
|
|
||||||
glm::vec3(HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY,
|
|
||||||
geometryIds[9]);
|
|
||||||
|
|
||||||
// Z center boundaries
|
|
||||||
geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, -HALF_TREE_SCALE),
|
|
||||||
glm::vec3(0.0f, -HALF_TREE_SCALE, HALF_TREE_SCALE), GREY,
|
|
||||||
geometryIds[10]);
|
|
||||||
geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, -HALF_TREE_SCALE),
|
|
||||||
glm::vec3(0.0f, HALF_TREE_SCALE, -HALF_TREE_SCALE), GREY,
|
|
||||||
geometryIds[11]);
|
|
||||||
geometryCache->renderLine(batch, glm::vec3(0.0f, HALF_TREE_SCALE, -HALF_TREE_SCALE),
|
|
||||||
glm::vec3(0.0f, HALF_TREE_SCALE, HALF_TREE_SCALE), GREY,
|
|
||||||
geometryIds[12]);
|
|
||||||
geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, HALF_TREE_SCALE),
|
|
||||||
glm::vec3(0.0f, HALF_TREE_SCALE, HALF_TREE_SCALE), GREY,
|
|
||||||
geometryIds[13]);
|
|
||||||
|
|
||||||
// Center boundaries
|
|
||||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE),
|
|
||||||
glm::vec3(-HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY,
|
|
||||||
geometryIds[14]);
|
|
||||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE),
|
|
||||||
glm::vec3(HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE), GREY,
|
|
||||||
geometryIds[15]);
|
|
||||||
geometryCache->renderLine(batch, glm::vec3(HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE),
|
|
||||||
glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY,
|
|
||||||
geometryIds[16]);
|
|
||||||
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE),
|
|
||||||
glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY,
|
|
||||||
geometryIds[17]);
|
|
||||||
|
|
||||||
|
|
||||||
geometryCache->renderWireCubeInstance(args, batch, GREY4);
|
|
||||||
|
|
||||||
// Draw meter markers along the 3 axis to help with measuring things
|
|
||||||
const float MARKER_DISTANCE = 1.0f;
|
|
||||||
const float MARKER_RADIUS = 0.05f;
|
|
||||||
|
|
||||||
transform = Transform().setScale(MARKER_RADIUS);
|
|
||||||
batch.setModelTransform(transform);
|
|
||||||
geometryCache->renderSolidSphereInstance(args, batch, RED);
|
|
||||||
|
|
||||||
transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, 0.0f)).setScale(MARKER_RADIUS);
|
|
||||||
batch.setModelTransform(transform);
|
|
||||||
geometryCache->renderSolidSphereInstance(args, batch, RED);
|
|
||||||
|
|
||||||
transform = Transform().setTranslation(glm::vec3(0.0f, MARKER_DISTANCE, 0.0f)).setScale(MARKER_RADIUS);
|
|
||||||
batch.setModelTransform(transform);
|
|
||||||
geometryCache->renderSolidSphereInstance(args, batch, GREEN);
|
|
||||||
|
|
||||||
transform = Transform().setTranslation(glm::vec3(0.0f, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS);
|
|
||||||
batch.setModelTransform(transform);
|
|
||||||
geometryCache->renderSolidSphereInstance(args, batch, BLUE);
|
|
||||||
|
|
||||||
transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS);
|
|
||||||
batch.setModelTransform(transform);
|
|
||||||
geometryCache->renderSolidSphereInstance(args, batch, GREY);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do some basic timing tests and report the results
|
// Do some basic timing tests and report the results
|
||||||
void runTimingTests() {
|
void runTimingTests() {
|
||||||
// How long does it take to make a call to get the time?
|
// How long does it take to make a call to get the time?
|
||||||
|
|
|
@ -15,14 +15,9 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
|
||||||
#include <gpu/Batch.h>
|
|
||||||
#include <render/Forward.h>
|
|
||||||
|
|
||||||
class ShapeEntityItem;
|
class ShapeEntityItem;
|
||||||
class ShapeInfo;
|
class ShapeInfo;
|
||||||
|
|
||||||
void renderWorldBox(RenderArgs* args, gpu::Batch& batch);
|
|
||||||
|
|
||||||
void runTimingTests();
|
void runTimingTests();
|
||||||
void runUnitTests();
|
void runUnitTests();
|
||||||
|
|
||||||
|
|
167
interface/src/graphics/GraphicsEngine.cpp
Normal file
167
interface/src/graphics/GraphicsEngine.cpp
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
//
|
||||||
|
// GraphicsEngine.cpp
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 29/6/2018.
|
||||||
|
// Copyright 2018 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#include "GraphicsEngine.h"
|
||||||
|
|
||||||
|
#include <shared/GlobalAppProperties.h>
|
||||||
|
|
||||||
|
#include "WorldBox.h"
|
||||||
|
#include "LODManager.h"
|
||||||
|
|
||||||
|
#include <GeometryCache.h>
|
||||||
|
#include <TextureCache.h>
|
||||||
|
#include <UpdateSceneTask.h>
|
||||||
|
#include <RenderViewTask.h>
|
||||||
|
#include <SecondaryCamera.h>
|
||||||
|
|
||||||
|
#include "RenderEventHandler.h"
|
||||||
|
|
||||||
|
#include <gpu/Batch.h>
|
||||||
|
#include <gpu/Context.h>
|
||||||
|
#include <gpu/gl/GLBackend.h>
|
||||||
|
|
||||||
|
GraphicsEngine::GraphicsEngine() {
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsEngine::~GraphicsEngine() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsEngine::initializeGPU(GLWidget* glwidget) {
|
||||||
|
|
||||||
|
// Build an offscreen GL context for the main thread.
|
||||||
|
_offscreenContext = new OffscreenGLCanvas();
|
||||||
|
_offscreenContext->setObjectName("MainThreadContext");
|
||||||
|
_offscreenContext->create(glwidget->qglContext());
|
||||||
|
if (!_offscreenContext->makeCurrent()) {
|
||||||
|
qFatal("Unable to make offscreen context current");
|
||||||
|
}
|
||||||
|
_offscreenContext->doneCurrent();
|
||||||
|
_offscreenContext->setThreadContext();
|
||||||
|
|
||||||
|
_renderEventHandler = new RenderEventHandler(glwidget->qglContext());
|
||||||
|
if (!_offscreenContext->makeCurrent()) {
|
||||||
|
qFatal("Unable to make offscreen context current");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requires the window context, because that's what's used in the actual rendering
|
||||||
|
// and the GPU backend will make things like the VAO which cannot be shared across
|
||||||
|
// contexts
|
||||||
|
glwidget->makeCurrent();
|
||||||
|
gpu::Context::init<gpu::gl::GLBackend>();
|
||||||
|
qApp->setProperty(hifi::properties::gl::MAKE_PROGRAM_CALLBACK,
|
||||||
|
QVariant::fromValue((void*)(&gpu::gl::GLBackend::makeProgram)));
|
||||||
|
glwidget->makeCurrent();
|
||||||
|
_gpuContext = std::make_shared<gpu::Context>();
|
||||||
|
|
||||||
|
DependencyManager::get<TextureCache>()->setGPUContext(_gpuContext);
|
||||||
|
|
||||||
|
// Restore the default main thread context
|
||||||
|
_offscreenContext->makeCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsEngine::initializeRender(bool disableDeferred) {
|
||||||
|
|
||||||
|
// Set up the render engine
|
||||||
|
render::CullFunctor cullFunctor = LODManager::shouldRender;
|
||||||
|
_renderEngine->addJob<UpdateSceneTask>("UpdateScene");
|
||||||
|
#ifndef Q_OS_ANDROID
|
||||||
|
_renderEngine->addJob<SecondaryCameraRenderTask>("SecondaryCameraJob", cullFunctor, !disableDeferred);
|
||||||
|
#endif
|
||||||
|
_renderEngine->addJob<RenderViewTask>("RenderMainView", cullFunctor, !disableDeferred, render::ItemKey::TAG_BITS_0, render::ItemKey::TAG_BITS_0);
|
||||||
|
_renderEngine->load();
|
||||||
|
_renderEngine->registerScene(_renderScene);
|
||||||
|
|
||||||
|
// Now that OpenGL is initialized, we are sure we have a valid context and can create the various pipeline shaders with success.
|
||||||
|
DependencyManager::get<GeometryCache>()->initializeShapePipelines();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsEngine::startup() {
|
||||||
|
|
||||||
|
|
||||||
|
static_cast<RenderEventHandler*>(_renderEventHandler)->resumeThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsEngine::shutdown() {
|
||||||
|
// The cleanup process enqueues the transactions but does not process them. Calling this here will force the actual
|
||||||
|
// removal of the items.
|
||||||
|
// See https://highfidelity.fogbugz.com/f/cases/5328
|
||||||
|
_renderScene->enqueueFrame(); // flush all the transactions
|
||||||
|
_renderScene->processTransactionQueue(); // process and apply deletions
|
||||||
|
|
||||||
|
_gpuContext->shutdown();
|
||||||
|
|
||||||
|
|
||||||
|
// shutdown render engine
|
||||||
|
_renderScene = nullptr;
|
||||||
|
_renderEngine = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GraphicsEngine::render_runRenderFrame(RenderArgs* renderArgs) {
|
||||||
|
PROFILE_RANGE(render, __FUNCTION__);
|
||||||
|
PerformanceTimer perfTimer("render");
|
||||||
|
// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::runRenderFrame()");
|
||||||
|
|
||||||
|
// The pending changes collecting the changes here
|
||||||
|
render::Transaction transaction;
|
||||||
|
|
||||||
|
// this is not in use at all anymore
|
||||||
|
//if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderEntities()) {
|
||||||
|
// render models...
|
||||||
|
// PerformanceTimer perfTimer("entities");
|
||||||
|
// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
|
// "Application::runRenderFrame() ... entities...");
|
||||||
|
|
||||||
|
//RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE;
|
||||||
|
|
||||||
|
//renderArgs->_debugFlags = renderDebugFlags;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Make sure the WorldBox is in the scene
|
||||||
|
// For the record, this one RenderItem is the first one we created and added to the scene.
|
||||||
|
// We could move that code elsewhere but you know...
|
||||||
|
if (!render::Item::isValidID(WorldBoxRenderData::_item)) {
|
||||||
|
auto worldBoxRenderData = std::make_shared<WorldBoxRenderData>();
|
||||||
|
auto worldBoxRenderPayload = std::make_shared<WorldBoxRenderData::Payload>(worldBoxRenderData);
|
||||||
|
|
||||||
|
WorldBoxRenderData::_item = _renderScene->allocateID();
|
||||||
|
|
||||||
|
transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload);
|
||||||
|
_renderScene->enqueueTransaction(transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// PerformanceTimer perfTimer("EngineRun");
|
||||||
|
_renderEngine->getRenderContext()->args = renderArgs;
|
||||||
|
_renderEngine->run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned int THROTTLED_SIM_FRAMERATE = 15;
|
||||||
|
static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SIM_FRAMERATE;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool GraphicsEngine::shouldPaint() const {
|
||||||
|
|
||||||
|
// Throttle if requested
|
||||||
|
if ((static_cast<RenderEventHandler*>(_renderEventHandler)->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsEngine::checkPendingRenderEvent() {
|
||||||
|
bool expected = false;
|
||||||
|
return (_renderEventHandler && static_cast<RenderEventHandler*>(_renderEventHandler)->_pendingRenderEvent.compare_exchange_strong(expected, true));
|
||||||
|
}
|
57
interface/src/graphics/GraphicsEngine.h
Normal file
57
interface/src/graphics/GraphicsEngine.h
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
//
|
||||||
|
// GraphicsEngine.h
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 29/6/2018.
|
||||||
|
// Copyright 2018 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#ifndef hifi_GraphicsEngine_h
|
||||||
|
#define hifi_GraphicsEngine_h
|
||||||
|
|
||||||
|
#include <gl/OffscreenGLCanvas.h>
|
||||||
|
#include <gl/GLWidget.h>
|
||||||
|
|
||||||
|
#include <render/Engine.h>
|
||||||
|
|
||||||
|
#include <OctreeConstants.h>
|
||||||
|
|
||||||
|
class GraphicsEngine {
|
||||||
|
public:
|
||||||
|
GraphicsEngine();
|
||||||
|
~GraphicsEngine();
|
||||||
|
|
||||||
|
void initializeGPU(GLWidget*);
|
||||||
|
void initializeRender(bool disableDeferred);
|
||||||
|
void startup();
|
||||||
|
void shutdown();
|
||||||
|
|
||||||
|
render::ScenePointer getRenderScene() const { return _renderScene; }
|
||||||
|
render::EnginePointer getRenderEngine() const { return _renderEngine; }
|
||||||
|
gpu::ContextPointer getGPUContext() const { return _gpuContext; }
|
||||||
|
|
||||||
|
// Same as the one in application
|
||||||
|
bool shouldPaint() const;
|
||||||
|
bool checkPendingRenderEvent();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// THread specific calls
|
||||||
|
void render_runRenderFrame(RenderArgs* renderArgs);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
render::ScenePointer _renderScene{ new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) };
|
||||||
|
render::EnginePointer _renderEngine{ new render::RenderEngine() };
|
||||||
|
|
||||||
|
gpu::ContextPointer _gpuContext; // initialized during window creation
|
||||||
|
|
||||||
|
QObject* _renderEventHandler{ nullptr };
|
||||||
|
friend class RenderEventHandler;
|
||||||
|
|
||||||
|
OffscreenGLCanvas* _offscreenContext{ nullptr };
|
||||||
|
|
||||||
|
friend class Application;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_GraphicsEngine_h
|
71
interface/src/graphics/RenderEventHandler.cpp
Normal file
71
interface/src/graphics/RenderEventHandler.cpp
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
//
|
||||||
|
// RenderEventHandler.cpp
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 29/6/2018.
|
||||||
|
// Copyright 2018 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#include "RenderEventHandler.h"
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
#include <shared/GlobalAppProperties.h>
|
||||||
|
#include <shared/QtHelpers.h>
|
||||||
|
|
||||||
|
#include "CrashHandler.h"
|
||||||
|
|
||||||
|
RenderEventHandler::RenderEventHandler(QOpenGLContext* context) {
|
||||||
|
_renderContext = new OffscreenGLCanvas();
|
||||||
|
_renderContext->setObjectName("RenderContext");
|
||||||
|
_renderContext->create(context);
|
||||||
|
if (!_renderContext->makeCurrent()) {
|
||||||
|
qFatal("Unable to make rendering context current");
|
||||||
|
}
|
||||||
|
_renderContext->doneCurrent();
|
||||||
|
|
||||||
|
// Deleting the object with automatically shutdown the thread
|
||||||
|
connect(qApp, &QCoreApplication::aboutToQuit, this, &QObject::deleteLater);
|
||||||
|
|
||||||
|
// Transfer to a new thread
|
||||||
|
moveToNewNamedThread(this, "RenderThread", [this](QThread* renderThread) {
|
||||||
|
hifi::qt::addBlockingForbiddenThread("Render", renderThread);
|
||||||
|
_renderContext->moveToThreadWithContext(renderThread);
|
||||||
|
_lastTimeRendered.start();
|
||||||
|
}, std::bind(&RenderEventHandler::initialize, this), QThread::HighestPriority);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderEventHandler::initialize() {
|
||||||
|
setObjectName("Render");
|
||||||
|
PROFILE_SET_THREAD_NAME("Render");
|
||||||
|
setCrashAnnotation("render_thread_id", std::to_string((size_t)QThread::currentThreadId()));
|
||||||
|
if (!_renderContext->makeCurrent()) {
|
||||||
|
qFatal("Unable to make rendering context current on render thread");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderEventHandler::resumeThread() {
|
||||||
|
_pendingRenderEvent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderEventHandler::render() {
|
||||||
|
if (qApp->shouldPaint()) {
|
||||||
|
_lastTimeRendered.start();
|
||||||
|
qApp->paintGL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenderEventHandler::event(QEvent* event) {
|
||||||
|
switch ((int)event->type()) {
|
||||||
|
case ApplicationEvent::Render:
|
||||||
|
render();
|
||||||
|
_pendingRenderEvent.store(false);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return Parent::event(event);
|
||||||
|
}
|
||||||
|
|
47
interface/src/graphics/RenderEventHandler.h
Normal file
47
interface/src/graphics/RenderEventHandler.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
//
|
||||||
|
// RenderEventHandler.h
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 29/6/2018.
|
||||||
|
// Copyright 2018 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#ifndef hifi_RenderEventHandler_h
|
||||||
|
#define hifi_RenderEventHandler_h
|
||||||
|
|
||||||
|
#include "gl/OffscreenGLCanvas.h"
|
||||||
|
#include <QEvent.h>
|
||||||
|
#include <QElapsedTimer.h>
|
||||||
|
|
||||||
|
enum ApplicationEvent {
|
||||||
|
// Execute a lambda function
|
||||||
|
Lambda = QEvent::User + 1,
|
||||||
|
// Trigger the next render
|
||||||
|
Render,
|
||||||
|
// Trigger the next idle
|
||||||
|
Idle,
|
||||||
|
};
|
||||||
|
|
||||||
|
class RenderEventHandler : public QObject {
|
||||||
|
using Parent = QObject;
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
RenderEventHandler(QOpenGLContext* context);
|
||||||
|
|
||||||
|
QElapsedTimer _lastTimeRendered;
|
||||||
|
std::atomic<bool> _pendingRenderEvent{ true };
|
||||||
|
|
||||||
|
void resumeThread();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initialize();
|
||||||
|
|
||||||
|
void render();
|
||||||
|
|
||||||
|
bool event(QEvent* event) override;
|
||||||
|
|
||||||
|
OffscreenGLCanvas* _renderContext{ nullptr };
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // #include hifi_RenderEventHandler_h
|
138
interface/src/graphics/WorldBox.cpp
Normal file
138
interface/src/graphics/WorldBox.cpp
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
//
|
||||||
|
// WorldBox.cpp
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 01/07/2018.
|
||||||
|
// Copyright 2018 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#include "WorldBox.h"
|
||||||
|
|
||||||
|
#include "OctreeConstants.h"
|
||||||
|
|
||||||
|
render::ItemID WorldBoxRenderData::_item{ render::Item::INVALID_ITEM_ID };
|
||||||
|
|
||||||
|
|
||||||
|
namespace render {
|
||||||
|
template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); }
|
||||||
|
template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); }
|
||||||
|
template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) {
|
||||||
|
if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) {
|
||||||
|
PerformanceTimer perfTimer("worldBox");
|
||||||
|
|
||||||
|
auto& batch = *args->_batch;
|
||||||
|
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
|
||||||
|
WorldBoxRenderData::renderWorldBox(args, batch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldBoxRenderData::renderWorldBox(RenderArgs* args, gpu::Batch& batch) {
|
||||||
|
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||||
|
|
||||||
|
// Show center of world
|
||||||
|
static const glm::vec3 RED(1.0f, 0.0f, 0.0f);
|
||||||
|
static const glm::vec3 GREEN(0.0f, 1.0f, 0.0f);
|
||||||
|
static const glm::vec3 BLUE(0.0f, 0.0f, 1.0f);
|
||||||
|
static const glm::vec3 GREY(0.5f, 0.5f, 0.5f);
|
||||||
|
static const glm::vec4 GREY4(0.5f, 0.5f, 0.5f, 1.0f);
|
||||||
|
|
||||||
|
static const glm::vec4 DASHED_RED(1.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
static const glm::vec4 DASHED_GREEN(0.0f, 1.0f, 0.0f, 1.0f);
|
||||||
|
static const glm::vec4 DASHED_BLUE(0.0f, 0.0f, 1.0f, 1.0f);
|
||||||
|
static const float DASH_LENGTH = 1.0f;
|
||||||
|
static const float GAP_LENGTH = 1.0f;
|
||||||
|
auto transform = Transform{};
|
||||||
|
static std::array<int, 18> geometryIds;
|
||||||
|
static std::once_flag initGeometryIds;
|
||||||
|
std::call_once(initGeometryIds, [&] {
|
||||||
|
for (size_t i = 0; i < geometryIds.size(); ++i) {
|
||||||
|
geometryIds[i] = geometryCache->allocateID();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
batch.setModelTransform(transform);
|
||||||
|
|
||||||
|
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(HALF_TREE_SCALE, 0.0f, 0.0f), RED, geometryIds[0]);
|
||||||
|
geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(-HALF_TREE_SCALE, 0.0f, 0.0f), DASHED_RED,
|
||||||
|
DASH_LENGTH, GAP_LENGTH, geometryIds[1]);
|
||||||
|
|
||||||
|
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, HALF_TREE_SCALE, 0.0f), GREEN, geometryIds[2]);
|
||||||
|
geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, -HALF_TREE_SCALE, 0.0f), DASHED_GREEN,
|
||||||
|
DASH_LENGTH, GAP_LENGTH, geometryIds[3]);
|
||||||
|
|
||||||
|
geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, HALF_TREE_SCALE), BLUE, geometryIds[4]);
|
||||||
|
geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, -HALF_TREE_SCALE), DASHED_BLUE,
|
||||||
|
DASH_LENGTH, GAP_LENGTH, geometryIds[5]);
|
||||||
|
|
||||||
|
// X center boundaries
|
||||||
|
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f),
|
||||||
|
glm::vec3(HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f), GREY,
|
||||||
|
geometryIds[6]);
|
||||||
|
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f),
|
||||||
|
glm::vec3(-HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY,
|
||||||
|
geometryIds[7]);
|
||||||
|
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f),
|
||||||
|
glm::vec3(HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY,
|
||||||
|
geometryIds[8]);
|
||||||
|
geometryCache->renderLine(batch, glm::vec3(HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f),
|
||||||
|
glm::vec3(HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY,
|
||||||
|
geometryIds[9]);
|
||||||
|
|
||||||
|
// Z center boundaries
|
||||||
|
geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, -HALF_TREE_SCALE),
|
||||||
|
glm::vec3(0.0f, -HALF_TREE_SCALE, HALF_TREE_SCALE), GREY,
|
||||||
|
geometryIds[10]);
|
||||||
|
geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, -HALF_TREE_SCALE),
|
||||||
|
glm::vec3(0.0f, HALF_TREE_SCALE, -HALF_TREE_SCALE), GREY,
|
||||||
|
geometryIds[11]);
|
||||||
|
geometryCache->renderLine(batch, glm::vec3(0.0f, HALF_TREE_SCALE, -HALF_TREE_SCALE),
|
||||||
|
glm::vec3(0.0f, HALF_TREE_SCALE, HALF_TREE_SCALE), GREY,
|
||||||
|
geometryIds[12]);
|
||||||
|
geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, HALF_TREE_SCALE),
|
||||||
|
glm::vec3(0.0f, HALF_TREE_SCALE, HALF_TREE_SCALE), GREY,
|
||||||
|
geometryIds[13]);
|
||||||
|
|
||||||
|
// Center boundaries
|
||||||
|
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE),
|
||||||
|
glm::vec3(-HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY,
|
||||||
|
geometryIds[14]);
|
||||||
|
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE),
|
||||||
|
glm::vec3(HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE), GREY,
|
||||||
|
geometryIds[15]);
|
||||||
|
geometryCache->renderLine(batch, glm::vec3(HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE),
|
||||||
|
glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY,
|
||||||
|
geometryIds[16]);
|
||||||
|
geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE),
|
||||||
|
glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY,
|
||||||
|
geometryIds[17]);
|
||||||
|
|
||||||
|
|
||||||
|
geometryCache->renderWireCubeInstance(args, batch, GREY4);
|
||||||
|
|
||||||
|
// Draw meter markers along the 3 axis to help with measuring things
|
||||||
|
const float MARKER_DISTANCE = 1.0f;
|
||||||
|
const float MARKER_RADIUS = 0.05f;
|
||||||
|
|
||||||
|
transform = Transform().setScale(MARKER_RADIUS);
|
||||||
|
batch.setModelTransform(transform);
|
||||||
|
geometryCache->renderSolidSphereInstance(args, batch, RED);
|
||||||
|
|
||||||
|
transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, 0.0f)).setScale(MARKER_RADIUS);
|
||||||
|
batch.setModelTransform(transform);
|
||||||
|
geometryCache->renderSolidSphereInstance(args, batch, RED);
|
||||||
|
|
||||||
|
transform = Transform().setTranslation(glm::vec3(0.0f, MARKER_DISTANCE, 0.0f)).setScale(MARKER_RADIUS);
|
||||||
|
batch.setModelTransform(transform);
|
||||||
|
geometryCache->renderSolidSphereInstance(args, batch, GREEN);
|
||||||
|
|
||||||
|
transform = Transform().setTranslation(glm::vec3(0.0f, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS);
|
||||||
|
batch.setModelTransform(transform);
|
||||||
|
geometryCache->renderSolidSphereInstance(args, batch, BLUE);
|
||||||
|
|
||||||
|
transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS);
|
||||||
|
batch.setModelTransform(transform);
|
||||||
|
geometryCache->renderSolidSphereInstance(args, batch, GREY);
|
||||||
|
}
|
||||||
|
|
43
interface/src/graphics/WorldBox.h
Normal file
43
interface/src/graphics/WorldBox.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
//
|
||||||
|
// WorldBox.h
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 01/07/2018.
|
||||||
|
// Copyright 2018 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#ifndef hifi_WorldBox_h
|
||||||
|
#define hifi_WorldBox_h
|
||||||
|
|
||||||
|
#include <PerfStat.h>
|
||||||
|
|
||||||
|
#include <gpu/Batch.h>
|
||||||
|
#include <render/Forward.h>
|
||||||
|
|
||||||
|
#include <render/Item.h>
|
||||||
|
#include <GeometryCache.h>
|
||||||
|
#include "Menu.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class WorldBoxRenderData {
|
||||||
|
public:
|
||||||
|
typedef render::Payload<WorldBoxRenderData> Payload;
|
||||||
|
typedef Payload::DataPointer Pointer;
|
||||||
|
|
||||||
|
int _val = 0;
|
||||||
|
static render::ItemID _item; // unique WorldBoxRenderData
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void renderWorldBox(RenderArgs* args, gpu::Batch& batch);
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace render {
|
||||||
|
template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff);
|
||||||
|
template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff);
|
||||||
|
template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // hifi_WorldBox_h
|
|
@ -55,7 +55,7 @@ ApplicationOverlay::~ApplicationOverlay() {
|
||||||
// Renders the overlays either to a texture or to the screen
|
// Renders the overlays either to a texture or to the screen
|
||||||
void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) {
|
void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) {
|
||||||
PROFILE_RANGE(render, __FUNCTION__);
|
PROFILE_RANGE(render, __FUNCTION__);
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()");
|
// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()");
|
||||||
|
|
||||||
buildFramebufferObject();
|
buildFramebufferObject();
|
||||||
|
|
||||||
|
|
|
@ -712,11 +712,16 @@ void RenderDeferredCleanup::run(const render::RenderContextPointer& renderContex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RenderDeferred::RenderDeferred(bool renderShadows):
|
||||||
|
_renderShadows(renderShadows)
|
||||||
|
{
|
||||||
|
DependencyManager::get<DeferredLightingEffect>()->init();
|
||||||
|
}
|
||||||
|
|
||||||
void RenderDeferred::configure(const Config& config) {
|
void RenderDeferred::configure(const Config& config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderDeferred::run(const RenderContextPointer& renderContext, const Inputs& inputs) {
|
void RenderDeferred::run(const RenderContextPointer& renderContext, const Inputs& inputs) {
|
||||||
PROFILE_RANGE(render, "DeferredLighting");
|
|
||||||
|
|
||||||
auto deferredTransform = inputs.get0();
|
auto deferredTransform = inputs.get0();
|
||||||
auto deferredFramebuffer = inputs.get1();
|
auto deferredFramebuffer = inputs.get1();
|
||||||
|
|
|
@ -167,8 +167,7 @@ public:
|
||||||
using Config = RenderDeferredConfig;
|
using Config = RenderDeferredConfig;
|
||||||
using JobModel = render::Job::ModelI<RenderDeferred, Inputs, Config>;
|
using JobModel = render::Job::ModelI<RenderDeferred, Inputs, Config>;
|
||||||
|
|
||||||
RenderDeferred() {}
|
RenderDeferred(bool renderShadows = false);
|
||||||
RenderDeferred(bool renderShadows) : _renderShadows(renderShadows) {}
|
|
||||||
|
|
||||||
void configure(const Config& config);
|
void configure(const Config& config);
|
||||||
|
|
||||||
|
|
|
@ -424,10 +424,12 @@ LightStageSetup::LightStageSetup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightStageSetup::run(const render::RenderContextPointer& renderContext) {
|
void LightStageSetup::run(const render::RenderContextPointer& renderContext) {
|
||||||
auto stage = renderContext->_scene->getStage(LightStage::getName());
|
if (renderContext->_scene) {
|
||||||
if (!stage) {
|
auto stage = renderContext->_scene->getStage(LightStage::getName());
|
||||||
stage = std::make_shared<LightStage>();
|
if (!stage) {
|
||||||
renderContext->_scene->resetStage(LightStage::getName(), stage);
|
stage = std::make_shared<LightStage>();
|
||||||
|
renderContext->_scene->resetStage(LightStage::getName(), stage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue