diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cbe0212a0b..fbba8c5c87 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1886,7 +1886,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto displayPlugin = qApp->getActiveDisplayPlugin(); - properties["render_rate"] = _renderLoopCounter.rate(); + properties["render_rate"] = getRenderLoopRate(); properties["target_render_rate"] = getTargetRenderFrameRate(); properties["present_rate"] = displayPlugin->presentRate(); properties["new_frame_present_rate"] = displayPlugin->newFramePresentRate(); @@ -2900,7 +2900,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) { surfaceContext->setContextProperty("Recording", DependencyManager::get().data()); surfaceContext->setContextProperty("Preferences", DependencyManager::get().data()); surfaceContext->setContextProperty("AddressManager", DependencyManager::get().data()); - surfaceContext->setContextProperty("FrameTimings", &_frameTimingsScriptingInterface); + surfaceContext->setContextProperty("FrameTimings", &_graphicsEngine._frameTimingsScriptingInterface); surfaceContext->setContextProperty("Rates", new RatesScriptingInterface(this)); surfaceContext->setContextProperty("TREE_SCALE", TREE_SCALE); @@ -4437,7 +4437,7 @@ void Application::idle() { if (displayPlugin) { PROFILE_COUNTER_IF_CHANGED(app, "present", float, displayPlugin->presentRate()); } - PROFILE_COUNTER_IF_CHANGED(app, "renderLoopRate", float, _renderLoopCounter.rate()); + PROFILE_COUNTER_IF_CHANGED(app, "renderLoopRate", float, getRenderLoopRate()); PROFILE_COUNTER_IF_CHANGED(app, "currentDownloads", int, ResourceCache::getLoadingRequests().length()); PROFILE_COUNTER_IF_CHANGED(app, "pendingDownloads", int, ResourceCache::getPendingRequestCount()); PROFILE_COUNTER_IF_CHANGED(app, "currentProcessing", int, DependencyManager::get()->getStat("Processing").toInt()); @@ -5382,7 +5382,7 @@ void Application::updateSecondaryCameraViewFrustum() { static bool domainLoadingInProgress = false; void Application::update(float deltaTime) { - PROFILE_RANGE_EX(app, __FUNCTION__, 0xffff0000, (uint64_t)_renderFrameCount + 1); + PROFILE_RANGE_EX(app, __FUNCTION__, 0xffff0000, (uint64_t)_graphicsEngine._renderFrameCount + 1); if (!_physicsEnabled) { if (!domainLoadingInProgress) { @@ -5839,7 +5839,7 @@ void Application::update(float deltaTime) { // load the view frustum // FIXME: This preDisplayRender call is temporary until we create a separate render::scene for the mirror rendering. // Then we can move this logic into the Avatar::simulate call. - myAvatar->preDisplaySide(&_appRenderArgs._renderArgs); +// myAvatar->preDisplaySide(&_appRenderArgs._renderArgs); { @@ -5855,7 +5855,7 @@ void Application::update(float deltaTime) { } void Application::updateRenderArgs(float deltaTime) { - editRenderArgs([this, deltaTime](AppRenderArgs& appRenderArgs) { + _graphicsEngine.editRenderArgs([this, deltaTime](AppRenderArgs& appRenderArgs) { PerformanceTimer perfTimer("editRenderArgs"); appRenderArgs._headPose = getHMDSensorPose(); @@ -5969,6 +5969,13 @@ void Application::updateRenderArgs(float deltaTime) { QMutexLocker viewLocker(&_viewMutex); appRenderArgs._renderArgs.setViewFrustum(_displayViewFrustum); } + + + // HACK + // load the view frustum + // FIXME: This preDisplayRender call is temporary until we create a separate render::scene for the mirror rendering. + // Then we can move this logic into the Avatar::simulate call. + myAvatar->preDisplaySide(&appRenderArgs._renderArgs); }); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 249c5a723a..6f4b24c434 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -78,7 +78,6 @@ #include #include #include -#include "FrameTimingsScriptingInterface.h" #include "Sound.h" @@ -159,7 +158,7 @@ public: void updateCamera(RenderArgs& renderArgs, float deltaTime); bool shouldPaint() const; - void paintGL(); +// void paintGL(); void resizeGL(); bool event(QEvent* event) override; @@ -208,8 +207,8 @@ public: Overlays& getOverlays() { return _overlays; } - size_t getRenderFrameCount() const { return _renderFrameCount; } - float getRenderLoopRate() const { return _renderLoopCounter.rate(); } + size_t getRenderFrameCount() const { return _graphicsEngine.getRenderFrameCount(); } + float getRenderLoopRate() const { return _graphicsEngine.getRenderLoopRate(); } float getTargetRenderFrameRate() const; // frames/second float getFieldOfView() { return _fieldOfView.get(); } @@ -569,14 +568,10 @@ private: QUndoStack _undoStack; UndoStackScriptingInterface _undoStackScriptingInterface; - uint32_t _renderFrameCount { 0 }; // Frame Rate Measurement - RateCounter<500> _renderLoopCounter; RateCounter<500> _gameLoopCounter; - FrameTimingsScriptingInterface _frameTimingsScriptingInterface; - QTimer _minimizedWindowTimer; QElapsedTimer _timerStart; QElapsedTimer _lastTimeUpdated; @@ -671,24 +666,6 @@ private: GameWorkload _gameWorkload; GraphicsEngine _graphicsEngine; - - mutable QMutex _renderArgsMutex{ QMutex::Recursive }; - struct AppRenderArgs { - render::Args _renderArgs; - glm::mat4 _eyeToWorld; - glm::mat4 _view; - glm::mat4 _eyeOffsets[2]; - glm::mat4 _eyeProjections[2]; - glm::mat4 _headPose; - glm::mat4 _sensorToWorld; - float _sensorToWorldScale { 1.0f }; - bool _isStereo{ false }; - }; - AppRenderArgs _appRenderArgs; - - - using RenderArgsEditor = std::function ; - void editRenderArgs(RenderArgsEditor editor); void updateRenderArgs(float deltaTime); diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index ab38096895..82010fa18f 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -19,151 +19,144 @@ #include "Util.h" -// Statically provided display and input plugins -extern DisplayPluginList getDisplayPlugins(); - -void Application::editRenderArgs(RenderArgsEditor editor) { - QMutexLocker renderLocker(&_renderArgsMutex); - editor(_appRenderArgs); - -} - -void Application::paintGL() { - // Some plugins process message events, allowing paintGL to be called reentrantly. - - _renderFrameCount++; - // SG: Moved into the RenderEventHandler - //_lastTimeRendered.start(); - - auto lastPaintBegin = usecTimestampNow(); - PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount); - PerformanceTimer perfTimer("paintGL"); - - if (nullptr == _displayPlugin) { - return; - } - - DisplayPluginPointer displayPlugin; - { - PROFILE_RANGE(render, "/getActiveDisplayPlugin"); - displayPlugin = getActiveDisplayPlugin(); - } - - { - PROFILE_RANGE(render, "/pluginBeginFrameRender"); - // If a display plugin loses it's underlying support, it - // needs to be able to signal us to not use it - if (!displayPlugin->beginFrameRender(_renderFrameCount)) { - QMetaObject::invokeMethod(this, "updateDisplayMode"); - return; - } - } - - RenderArgs renderArgs; - glm::mat4 HMDSensorPose; - glm::mat4 eyeToWorld; - glm::mat4 sensorToWorld; - - bool isStereo; - glm::mat4 stereoEyeOffsets[2]; - glm::mat4 stereoEyeProjections[2]; - - { - QMutexLocker viewLocker(&_renderArgsMutex); - renderArgs = _appRenderArgs._renderArgs; - - // don't render if there is no context. - if (!_appRenderArgs._renderArgs._context) { - return; - } - - HMDSensorPose = _appRenderArgs._headPose; - eyeToWorld = _appRenderArgs._eyeToWorld; - sensorToWorld = _appRenderArgs._sensorToWorld; - isStereo = _appRenderArgs._isStereo; - for_each_eye([&](Eye eye) { - stereoEyeOffsets[eye] = _appRenderArgs._eyeOffsets[eye]; - stereoEyeProjections[eye] = _appRenderArgs._eyeProjections[eye]; - }); - } - - { - PROFILE_RANGE(render, "/gpuContextReset"); - _graphicsEngine.getGPUContext()->beginFrame(_appRenderArgs._view, HMDSensorPose); - // Reset the gpu::Context Stages - // Back to the default framebuffer; - gpu::doInBatch("Application_render::gpuContextReset", _graphicsEngine.getGPUContext(), [&](gpu::Batch& batch) { - batch.resetStages(); - }); - } - { - PROFILE_RANGE(render, "/renderOverlay"); - PerformanceTimer perfTimer("renderOverlay"); - // NOTE: There is no batch associated with this renderArgs - // the ApplicationOverlay class assumes it's viewport is setup to be the device size - renderArgs._viewport = glm::ivec4(0, 0, getDeviceSize() * getRenderResolutionScale()); - _applicationOverlay.renderOverlay(&renderArgs); - } - - { - PROFILE_RANGE(render, "/updateCompositor"); - getApplicationCompositor().setFrameInfo(_renderFrameCount, eyeToWorld, sensorToWorld); - } - - gpu::FramebufferPointer finalFramebuffer; - QSize finalFramebufferSize; - { - PROFILE_RANGE(render, "/getOutputFramebuffer"); - // Primary rendering pass - auto framebufferCache = DependencyManager::get(); - finalFramebufferSize = framebufferCache->getFrameBufferSize(); - // Final framebuffer that will be handled to the display-plugin - finalFramebuffer = framebufferCache->getFramebuffer(); - } - - { - if (isStereo) { - renderArgs._context->enableStereo(true); - renderArgs._context->setStereoProjections(stereoEyeProjections); - renderArgs._context->setStereoViews(stereoEyeOffsets); - } - - renderArgs._hudOperator = displayPlugin->getHUDOperator(); - renderArgs._hudTexture = _applicationOverlay.getOverlayTexture(); - renderArgs._blitFramebuffer = finalFramebuffer; - _graphicsEngine.render_runRenderFrame(&renderArgs); - } - - auto frame = _graphicsEngine.getGPUContext()->endFrame(); - frame->frameIndex = _renderFrameCount; - frame->framebuffer = finalFramebuffer; - frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) { - auto frameBufferCache = DependencyManager::get(); - if (frameBufferCache) { - frameBufferCache->releaseFramebuffer(framebuffer); - } - }; - // deliver final scene rendering commands to the display plugin - { - PROFILE_RANGE(render, "/pluginOutput"); - PerformanceTimer perfTimer("pluginOutput"); - _renderLoopCounter.increment(); - displayPlugin->submitFrame(frame); - } - - // Reset the framebuffer and stereo state - renderArgs._blitFramebuffer.reset(); - renderArgs._context->enableStereo(false); - - { - Stats::getInstance()->setRenderDetails(renderArgs._details); - } - - uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin; - _frameTimingsScriptingInterface.addValue(lastPaintDuration); -} +//void Application::paintGL() { +// // Some plugins process message events, allowing paintGL to be called reentrantly. +// +// _renderFrameCount++; +// // SG: Moved into the RenderEventHandler +// //_lastTimeRendered.start(); +// +// auto lastPaintBegin = usecTimestampNow(); +// PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount); +// PerformanceTimer perfTimer("paintGL"); +// +// if (nullptr == _displayPlugin) { +// return; +// } +// +// DisplayPluginPointer displayPlugin; +// { +// PROFILE_RANGE(render, "/getActiveDisplayPlugin"); +// displayPlugin = getActiveDisplayPlugin(); +// } +// +// { +// PROFILE_RANGE(render, "/pluginBeginFrameRender"); +// // If a display plugin loses it's underlying support, it +// // needs to be able to signal us to not use it +// if (!displayPlugin->beginFrameRender(_renderFrameCount)) { +// QMetaObject::invokeMethod(this, "updateDisplayMode"); +// return; +// } +// } +// +// RenderArgs renderArgs; +// glm::mat4 HMDSensorPose; +// glm::mat4 eyeToWorld; +// glm::mat4 sensorToWorld; +// +// bool isStereo; +// glm::mat4 stereoEyeOffsets[2]; +// glm::mat4 stereoEyeProjections[2]; +// +// { +// QMutexLocker viewLocker(&_renderArgsMutex); +// renderArgs = _appRenderArgs._renderArgs; +// +// // don't render if there is no context. +// if (!_appRenderArgs._renderArgs._context) { +// return; +// } +// +// HMDSensorPose = _appRenderArgs._headPose; +// eyeToWorld = _appRenderArgs._eyeToWorld; +// sensorToWorld = _appRenderArgs._sensorToWorld; +// isStereo = _appRenderArgs._isStereo; +// for_each_eye([&](Eye eye) { +// stereoEyeOffsets[eye] = _appRenderArgs._eyeOffsets[eye]; +// stereoEyeProjections[eye] = _appRenderArgs._eyeProjections[eye]; +// }); +// } +// +// { +// PROFILE_RANGE(render, "/gpuContextReset"); +// _graphicsEngine.getGPUContext()->beginFrame(_appRenderArgs._view, HMDSensorPose); +// // Reset the gpu::Context Stages +// // Back to the default framebuffer; +// gpu::doInBatch("Application_render::gpuContextReset", _graphicsEngine.getGPUContext(), [&](gpu::Batch& batch) { +// batch.resetStages(); +// }); +// } +// +// +// { +// PROFILE_RANGE(render, "/renderOverlay"); +// PerformanceTimer perfTimer("renderOverlay"); +// // NOTE: There is no batch associated with this renderArgs +// // the ApplicationOverlay class assumes it's viewport is setup to be the device size +// renderArgs._viewport = glm::ivec4(0, 0, getDeviceSize() * getRenderResolutionScale()); +// _applicationOverlay.renderOverlay(&renderArgs); +// } +// +// { +// PROFILE_RANGE(render, "/updateCompositor"); +// getApplicationCompositor().setFrameInfo(_renderFrameCount, eyeToWorld, sensorToWorld); +// } +// +// gpu::FramebufferPointer finalFramebuffer; +// QSize finalFramebufferSize; +// { +// PROFILE_RANGE(render, "/getOutputFramebuffer"); +// // Primary rendering pass +// auto framebufferCache = DependencyManager::get(); +// finalFramebufferSize = framebufferCache->getFrameBufferSize(); +// // Final framebuffer that will be handled to the display-plugin +// finalFramebuffer = framebufferCache->getFramebuffer(); +// } +// +// { +// if (isStereo) { +// renderArgs._context->enableStereo(true); +// renderArgs._context->setStereoProjections(stereoEyeProjections); +// renderArgs._context->setStereoViews(stereoEyeOffsets); +// } +// +// renderArgs._hudOperator = displayPlugin->getHUDOperator(); +// renderArgs._hudTexture = _applicationOverlay.getOverlayTexture(); +// renderArgs._blitFramebuffer = finalFramebuffer; +// _graphicsEngine.render_runRenderFrame(&renderArgs); +// } +// +// auto frame = _graphicsEngine.getGPUContext()->endFrame(); +// frame->frameIndex = _renderFrameCount; +// frame->framebuffer = finalFramebuffer; +// frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) { +// auto frameBufferCache = DependencyManager::get(); +// if (frameBufferCache) { +// frameBufferCache->releaseFramebuffer(framebuffer); +// } +// }; +// // deliver final scene rendering commands to the display plugin +// { +// PROFILE_RANGE(render, "/pluginOutput"); +// PerformanceTimer perfTimer("pluginOutput"); +// _renderLoopCounter.increment(); +// displayPlugin->submitFrame(frame); +// } +// +// // Reset the framebuffer and stereo state +// renderArgs._blitFramebuffer.reset(); +// renderArgs._context->enableStereo(false); +// +// { +// Stats::getInstance()->setRenderDetails(renderArgs._details); +// } +// +// uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin; +// _frameTimingsScriptingInterface.addValue(lastPaintDuration); +//} // WorldBox Render Data & rendering functions diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index eea54c7b8a..f256b0dfb5 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -25,6 +26,12 @@ #include #include #include +#include + +#include +#include +#include "ui/Stats.h" +#include "Application.h" GraphicsEngine::GraphicsEngine() { } @@ -44,7 +51,11 @@ void GraphicsEngine::initializeGPU(GLWidget* glwidget) { _offscreenContext->doneCurrent(); _offscreenContext->setThreadContext(); - _renderEventHandler = new RenderEventHandler(glwidget->qglContext()); + _renderEventHandler = new RenderEventHandler( + glwidget->qglContext(), + [this]() { this->render_performFrame(); } + ); + if (!_offscreenContext->makeCurrent()) { qFatal("Unable to make offscreen context current"); } @@ -84,8 +95,6 @@ void GraphicsEngine::initializeRender(bool disableDeferred) { } void GraphicsEngine::startup() { - - static_cast(_renderEventHandler)->resumeThread(); } @@ -110,27 +119,12 @@ void GraphicsEngine::shutdown() { 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()->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)) { + render::Transaction transaction; auto worldBoxRenderData = std::make_shared(); auto worldBoxRenderPayload = std::make_shared(worldBoxRenderData); @@ -141,7 +135,6 @@ void GraphicsEngine::render_runRenderFrame(RenderArgs* renderArgs) { } { - // PerformanceTimer perfTimer("EngineRun"); _renderEngine->getRenderContext()->args = renderArgs; _renderEngine->run(); } @@ -154,7 +147,6 @@ static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SI bool GraphicsEngine::shouldPaint() const { - // Throttle if requested if ((static_cast(_renderEventHandler)->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { return false; @@ -167,3 +159,149 @@ bool GraphicsEngine::checkPendingRenderEvent() { bool expected = false; return (_renderEventHandler && static_cast(_renderEventHandler)->_pendingRenderEvent.compare_exchange_strong(expected, true)); } + + + +void GraphicsEngine::render_performFrame() { + // Some plugins process message events, allowing paintGL to be called reentrantly. + + _renderFrameCount++; + // SG: Moved into the RenderEventHandler + //_lastTimeRendered.start(); + + auto lastPaintBegin = usecTimestampNow(); + PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount); + PerformanceTimer perfTimer("paintGL"); + + /* if (nullptr == _displayPlugin) { + return; + }*/ + + DisplayPluginPointer displayPlugin; + { + PROFILE_RANGE(render, "/getActiveDisplayPlugin"); + displayPlugin = qApp->getActiveDisplayPlugin(); + } + + { + PROFILE_RANGE(render, "/pluginBeginFrameRender"); + // If a display plugin loses it's underlying support, it + // needs to be able to signal us to not use it + if (!displayPlugin->beginFrameRender(_renderFrameCount)) { + QMetaObject::invokeMethod(qApp, "updateDisplayMode"); + return; + } + } + + RenderArgs renderArgs; + glm::mat4 HMDSensorPose; + glm::mat4 eyeToWorld; + glm::mat4 sensorToWorld; + + bool isStereo; + glm::mat4 stereoEyeOffsets[2]; + glm::mat4 stereoEyeProjections[2]; + + { + QMutexLocker viewLocker(&_renderArgsMutex); + renderArgs = _appRenderArgs._renderArgs; + + // don't render if there is no context. + if (!_appRenderArgs._renderArgs._context) { + return; + } + + HMDSensorPose = _appRenderArgs._headPose; + eyeToWorld = _appRenderArgs._eyeToWorld; + sensorToWorld = _appRenderArgs._sensorToWorld; + isStereo = _appRenderArgs._isStereo; + for_each_eye([&](Eye eye) { + stereoEyeOffsets[eye] = _appRenderArgs._eyeOffsets[eye]; + stereoEyeProjections[eye] = _appRenderArgs._eyeProjections[eye]; + }); + } + + { + PROFILE_RANGE(render, "/gpuContextReset"); + getGPUContext()->beginFrame(_appRenderArgs._view, HMDSensorPose); + // Reset the gpu::Context Stages + // Back to the default framebuffer; + gpu::doInBatch("Application_render::gpuContextReset", getGPUContext(), [&](gpu::Batch& batch) { + batch.resetStages(); + }); + } + + + { + PROFILE_RANGE(render, "/renderOverlay"); + PerformanceTimer perfTimer("renderOverlay"); + // NOTE: There is no batch associated with this renderArgs + // the ApplicationOverlay class assumes it's viewport is setup to be the device size + renderArgs._viewport = glm::ivec4(0, 0, qApp->getDeviceSize() * qApp->getRenderResolutionScale()); + qApp->getApplicationOverlay().renderOverlay(&renderArgs); + } + + { + PROFILE_RANGE(render, "/updateCompositor"); + qApp->getApplicationCompositor().setFrameInfo(_renderFrameCount, eyeToWorld, sensorToWorld); + } + + gpu::FramebufferPointer finalFramebuffer; + QSize finalFramebufferSize; + { + PROFILE_RANGE(render, "/getOutputFramebuffer"); + // Primary rendering pass + auto framebufferCache = DependencyManager::get(); + finalFramebufferSize = framebufferCache->getFrameBufferSize(); + // Final framebuffer that will be handled to the display-plugin + finalFramebuffer = framebufferCache->getFramebuffer(); + } + + { + if (isStereo) { + renderArgs._context->enableStereo(true); + renderArgs._context->setStereoProjections(stereoEyeProjections); + renderArgs._context->setStereoViews(stereoEyeOffsets); + } + + renderArgs._hudOperator = displayPlugin->getHUDOperator(); + renderArgs._hudTexture = qApp->getApplicationOverlay().getOverlayTexture(); + renderArgs._blitFramebuffer = finalFramebuffer; + render_runRenderFrame(&renderArgs); + } + + auto frame = getGPUContext()->endFrame(); + frame->frameIndex = _renderFrameCount; + frame->framebuffer = finalFramebuffer; + frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) { + auto frameBufferCache = DependencyManager::get(); + if (frameBufferCache) { + frameBufferCache->releaseFramebuffer(framebuffer); + } + }; + // deliver final scene rendering commands to the display plugin + { + PROFILE_RANGE(render, "/pluginOutput"); + PerformanceTimer perfTimer("pluginOutput"); + _renderLoopCounter.increment(); + displayPlugin->submitFrame(frame); + } + + // Reset the framebuffer and stereo state + renderArgs._blitFramebuffer.reset(); + renderArgs._context->enableStereo(false); + + { + Stats::getInstance()->setRenderDetails(renderArgs._details); + } + + uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin; + _frameTimingsScriptingInterface.addValue(lastPaintDuration); +} + + +void GraphicsEngine::editRenderArgs(RenderArgsEditor editor) { + QMutexLocker renderLocker(&_renderArgsMutex); + editor(_appRenderArgs); + +} \ No newline at end of file diff --git a/interface/src/graphics/GraphicsEngine.h b/interface/src/graphics/GraphicsEngine.h index 89d1eb1d94..780b4020d2 100644 --- a/interface/src/graphics/GraphicsEngine.h +++ b/interface/src/graphics/GraphicsEngine.h @@ -12,10 +12,30 @@ #include #include +#include #include #include +#include + +#include "FrameTimingsScriptingInterface.h" + + +struct AppRenderArgs { + render::Args _renderArgs; + glm::mat4 _eyeToWorld; + glm::mat4 _view; + glm::mat4 _eyeOffsets[2]; + glm::mat4 _eyeProjections[2]; + glm::mat4 _headPose; + glm::mat4 _sensorToWorld; + float _sensorToWorldScale{ 1.0f }; + bool _isStereo{ false }; +}; + +using RenderArgsEditor = std::function ; + class GraphicsEngine { public: @@ -35,12 +55,25 @@ public: bool shouldPaint() const; bool checkPendingRenderEvent(); + size_t getRenderFrameCount() const { return _renderFrameCount; } + float getRenderLoopRate() const { return _renderLoopCounter.rate(); } + + // Feed GRaphics Engine with new frame configuration + void editRenderArgs(RenderArgsEditor editor); + private: // Thread specific calls + void render_performFrame(); void render_runRenderFrame(RenderArgs* renderArgs); protected: + mutable QMutex _renderArgsMutex{ QMutex::Recursive }; + AppRenderArgs _appRenderArgs; + + RateCounter<500> _renderLoopCounter; + + uint32_t _renderFrameCount{ 0 }; render::ScenePointer _renderScene{ new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) }; render::EnginePointer _renderEngine{ new render::RenderEngine() }; @@ -51,6 +84,8 @@ protected: OffscreenGLCanvas* _offscreenContext{ nullptr }; + FrameTimingsScriptingInterface _frameTimingsScriptingInterface; + friend class Application; }; diff --git a/interface/src/graphics/RenderEventHandler.cpp b/interface/src/graphics/RenderEventHandler.cpp index 0ca82201d5..95e931ebd8 100644 --- a/interface/src/graphics/RenderEventHandler.cpp +++ b/interface/src/graphics/RenderEventHandler.cpp @@ -15,7 +15,9 @@ #include "CrashHandler.h" -RenderEventHandler::RenderEventHandler(QOpenGLContext* context) { +RenderEventHandler::RenderEventHandler(QOpenGLContext* context, RenderCall renderCall) : + _renderCall(renderCall) +{ _renderContext = new OffscreenGLCanvas(); _renderContext->setObjectName("RenderContext"); _renderContext->create(context); @@ -52,7 +54,7 @@ void RenderEventHandler::resumeThread() { void RenderEventHandler::render() { if (qApp->shouldPaint()) { _lastTimeRendered.start(); - qApp->paintGL(); + _renderCall(); } } diff --git a/interface/src/graphics/RenderEventHandler.h b/interface/src/graphics/RenderEventHandler.h index 8b0e4c5e15..913898eb7f 100644 --- a/interface/src/graphics/RenderEventHandler.h +++ b/interface/src/graphics/RenderEventHandler.h @@ -27,7 +27,11 @@ class RenderEventHandler : public QObject { using Parent = QObject; Q_OBJECT public: - RenderEventHandler(QOpenGLContext* context); + + using RenderCall = std::function ; + RenderCall _renderCall; + + RenderEventHandler(QOpenGLContext* context, RenderCall renderCall); QElapsedTimer _lastTimeRendered; std::atomic _pendingRenderEvent{ true }; diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index 1ebc6aa967..0ecfa9bfd7 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -50,10 +50,10 @@ public: _default = toJsonValue(*this).toObject().toVariantMap(); _presets.unite(list.toVariantMap()); - if (C::alwaysEnabled || C::enabled) { + if (C::enabled) { _presets.insert(DEFAULT, _default); } - if (!C::alwaysEnabled) { + if (false) { //!C::alwaysEnabled) { _presets.insert(NONE, QVariantMap{{ "enabled", false }}); } @@ -96,12 +96,11 @@ public: using Persistent = PersistentConfig; JobConfig() = default; - JobConfig(bool enabled) : alwaysEnabled{ false }, enabled{ enabled } {} + JobConfig(bool enabled): enabled{ enabled } {} bool isEnabled() { return /*alwaysEnabled ||*/ enabled; } void setEnabled(bool enable) { enabled = /*alwaysEnabled ||*/ enable; emit dirtyEnabled(); } - bool alwaysEnabled{ false }; bool enabled{ true }; virtual void setPresetList(const QJsonObject& object); diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index 60ccd26b70..c15c0ceb13 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -164,7 +164,7 @@ public: void run(const ContextPointer& jobContext) override { jobContext->jobConfig = std::static_pointer_cast(Concept::_config); - if (jobContext->jobConfig->alwaysEnabled || jobContext->jobConfig->isEnabled()) { + if (/*jobContext->jobConfig->alwaysEnabled || */jobContext->jobConfig->isEnabled()) { jobRun(_data, jobContext, _input.get(), _output.edit()); } jobContext->jobConfig.reset(); @@ -339,7 +339,7 @@ public: void run(const ContextPointer& jobContext) override { auto config = std::static_pointer_cast(Concept::_config); - if (config->alwaysEnabled || config->enabled) { + if (config->enabled) { for (auto job : TaskConcept::_jobs) { job.run(jobContext); if (jobContext->taskFlow.doAbortTask()) {