From 11a240e2db79671bbd1a41b4a3909034afc1d83f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 18 Jun 2018 12:47:13 -0700 Subject: [PATCH 01/20] Exploring the performance profile of the render engine --- interface/src/SecondaryCamera.cpp | 4 +- libraries/task/src/task/Config.h | 6 +- scripts/developer/utilities/lib/jet/jet.js | 114 ++++++++++++++ .../utilities/lib/jet/qml/TaskListView.qml | 128 ++++++++-------- .../lib/jet/qml/TaskTimeFrameView.qml | 141 ++++++++++++++++++ .../developer/utilities/lib/jet/qml/qmldir | 3 +- .../utilities/render/engineInspector.js | 10 +- .../utilities/render/engineInspector.qml | 3 +- 8 files changed, 338 insertions(+), 71 deletions(-) create mode 100644 scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index b9a767f700..766c64043d 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -196,11 +196,13 @@ public: void run(const render::RenderContextPointer& renderContext, const RenderArgsPointer& cachedArgs) { auto args = renderContext->args; + if (cachedArgs) { args->_blitFramebuffer = cachedArgs->_blitFramebuffer; args->_viewport = cachedArgs->_viewport; - args->popViewFrustum(); args->_displayMode = cachedArgs->_displayMode; args->_renderMode = cachedArgs->_renderMode; + } + args->popViewFrustum(); gpu::doInBatch("EndSecondaryCameraFrame::run", args->_context, [&](gpu::Batch& batch) { batch.restoreContextStereo(); diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index 00fa01808b..c94ed5f8ce 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -98,10 +98,10 @@ public: JobConfig() = default; JobConfig(bool enabled) : alwaysEnabled{ false }, enabled{ enabled } {} - bool isEnabled() { return alwaysEnabled || enabled; } - void setEnabled(bool enable) { enabled = alwaysEnabled || enable; emit dirtyEnabled(); } + bool isEnabled() { return /*alwaysEnabled ||*/ enabled; } + void setEnabled(bool enable) { enabled = /*alwaysEnabled ||*/ enable; emit dirtyEnabled(); } - bool alwaysEnabled{ true }; + bool alwaysEnabled{ false }; bool enabled{ true }; virtual void setPresetList(const QJsonObject& object); diff --git a/scripts/developer/utilities/lib/jet/jet.js b/scripts/developer/utilities/lib/jet/jet.js index 16840e59bd..041be0f8a6 100644 --- a/scripts/developer/utilities/lib/jet/jet.js +++ b/scripts/developer/utilities/lib/jet/jet.js @@ -73,6 +73,120 @@ function job_print_functor(printout, showProps, maxDepth) { } } +// Use this function to create a functor that will build a tree datastructure of the Job visited + +function job_tree_model_array_functor(jobTreeArray, newNodeFunctor) { + var jobsRoot; + var numJobs = 0; + var jobTreePath = [] + if (newNodeFunctor === undefined) newNodeFunctor = function (node) {} + + return function (job, depth, index) { + var id = numJobs + var newItem = {"name": job.objectName, "level": depth, "index": index, "id": id, "subNode": [], "path": ""} + if (depth == 0) { + newNodeFunctor(newItem) + jobTreeArray.push(newItem) + numJobs++ + jobsRoot = jobTreeArray[0].subNode; + } else { + if (jobTreePath.length < depth) { + var node = jobsRoot; + var path; + for (var n = 0; n < jobTreePath.length; n++) { + newItem.path += (n > 0 ? "." : "") + node[jobTreePath[n]].name + node = node[jobTreePath[n]].subNode + } + + newNodeFunctor(newItem) + node.push((newItem)) + numJobs++ + jobTreePath.push(0); + } else if (jobTreePath.length >= depth) { + var node = jobsRoot; + for (var n = 0; n < (depth - 1); n++) { + newItem.path += (n > 0 ? "." : "") + node[jobTreePath[n]].name + node = node[jobTreePath[n]].subNode + } + + newNodeFunctor(newItem) + node.push((newItem)) + numJobs++ + jobTreePath[depth-1] = index; + while (jobTreePath.length > depth) { + jobTreePath.pop(); + } + } + } + return true; + } +} + +function job_tree_model_functor(jobTreeModel, maxLevel, newNodeFunctor) { + var jobsRoot; + var numJobs = 0; + var jobTreePath = [] + if (newNodeFunctor === undefined) newNodeFunctor = function (node) {} + + return function (job, depth, index) { + var id = numJobs + var newItem = {"name": job.objectName, "level": depth, "index": index, "id": id, "subNode": [], "path": "", "init": (depth < maxLevel), "ud": {}} + if (depth == 0) { + newNodeFunctor(newItem) + jobTreeModel.append(newItem) + numJobs++ + jobsRoot = jobTreeModel.get(0).subNode; + } else { + if (jobTreePath.length < depth) { + var node = jobsRoot; + var path; + for (var n = 0; n < jobTreePath.length; n++) { + newItem.path += (n > 0 ? "." : "") + node.get(jobTreePath[n]).name + node = node.get(jobTreePath[n]).subNode + } + + newNodeFunctor(newItem) + node.append((newItem)) + numJobs++ + jobTreePath.push(0); + } else if (jobTreePath.length >= depth) { + var node = jobsRoot; + for (var n = 0; n < (depth - 1); n++) { + newItem.path += (n > 0 ? "." : "") + node.get(jobTreePath[n]).name + node = node.get(jobTreePath[n]).subNode + } + + newNodeFunctor(newItem) + node.append((newItem)) + numJobs++ + jobTreePath[depth-1] = index; + while (jobTreePath.length > depth) { + jobTreePath.pop(); + } + } + } + return true; + } +} + + +// Traverse the jobTreenode data structure created above +function job_traverseTreeNode(root, functor, depth) { + // if (root.subNode.length) { + depth++; + for (var i = 0; i 0 ? "." : "") + node.get(jobTreePath[n]).name - node = node.get(jobTreePath[n]).subNode - } - node.append(newItem) - jobTreePath.push(0); - } else if (jobTreePath.length >= depth) { - var node = jobsRoot; - for (var n = 0; n < (depth - 1); n++) { - newItem.path += (n > 0 ? "." : "") + node.get(jobTreePath[n]).name - node = node.get(jobTreePath[n]).subNode - } - node.append(newItem) - jobTreePath[depth-1] = index; - while (jobTreePath.length > depth) { - jobTreePath.pop(); - } - } - } - return true; - } - + //var functor = Jet.job_tree_model_functor(jobsModel) + /* var functor = Jet.job_tree_model_functor(jobsModel, 1, function(node) { + node["cpuT"] = 0.0 + }) Jet.task_traverseTree(rootConfig, functor); - } + */ + + var tfunctor = Jet.job_tree_model_array_functor(jobsModel.engineJobItemModel, function(node) { + node["init"] = (node.level < 3) + node["fullpath"] = (node.path + "." + node.name) + node["cpuT"] = 0.0 + }) + + Jet.task_traverseTree(rootConfig, tfunctor); + + // var currentParentStach = [] + // currentParentStach.push(jobsModel); + + + Jet.job_traverseTreeNodeRoot(jobsModel.engineJobItemModel[0], function(node, depth, index) { + print(node.name + depth + " - " + index) + return true + }) + } + ListModel { id: jobsModel + property var engineJobItemModel : [] } Component { @@ -77,30 +64,49 @@ Rectangle { id: objRecursiveColumn clip: true visible: model.init - - MouseArea { - width: objRow.implicitWidth - height: objRow.implicitHeight - onDoubleClicked: { - for(var i = 1; i < parent.children.length - 1; ++i) { - parent.children[i].visible = !parent.children[i].visible - } - } - Row { - id: objRow - Item { - height: 1 - width: model.level * 15 - } - HifiControls.CheckBox { - property var config: root.rootConfig.getConfig(model.path + "." + model.name); - text: (objRecursiveColumn.children.length > 2 ? - objRecursiveColumn.children[1].visible ? - qsTr("- ") : qsTr("+ ") : qsTr(" ")) + model.name + " ms=" + config.cpuRunTime.toFixed(2) - checked: config.enabled - } + // visible: (node.level < 2) + + function switchFold() { + for(var i = 1; i < children.length - 1; ++i) { + children[i].visible = !children[i].visible } } + + Row { + id: objRow + Item { + height: 1 + width: model.level * 15 + } + + HifiControls.CheckBox { + id: objCheck + property var config: root.rootConfig.getConfig(model.path + "." + model.name); + text: " " + checked: config.enabled + onCheckedChanged: { config.enabled = checked } + } + + MouseArea { + width: objLabel.implicitWidth + height: objLabel.implicitHeight + onDoubleClicked: { + parent.parent.switchFold() + } + + HifiControls.Label { + id: objLabel + colorScheme: hifi.colorSchemes.dark + // property var config: root.rootConfig.getConfig(model.path + "." + model.name); + text: (objRecursiveColumn.children.length > 2 ? + objRecursiveColumn.children[1].visible ? + qsTr("- ") : qsTr("+ ") : qsTr(" ")) + model.name + + " ms=" + root.rootConfig.getConfig(model.path + "." + model.name).cpuRunTime.toFixed(3) + + " id=" + model.id + } + } + } + Repeater { model: subNode delegate: objRecursiveDelegate diff --git a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml new file mode 100644 index 0000000000..ed1649a47a --- /dev/null +++ b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml @@ -0,0 +1,141 @@ +// +// jet/TaskTimeFrameView.qml +// +// Created by Sam Gateau, 2018/06/15 +// 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 +// + +import QtQuick 2.7 +import QtQuick.Controls 1.4 as Original +import QtQuick.Controls.Styles 1.4 + +import "qrc:///qml/styles-uit" +import "qrc:///qml/controls-uit" as HifiControls + +import "../jet.js" as Jet + +Rectangle { + HifiConstants { id: hifi;} + color: hifi.colors.baseGray; + id: root; + + property var rootConfig : Workload + + property var jobsTree + property var jobsArray + + Component.onCompleted: { + if (!jobsTree) { jobsTree = new Array(); } + if (!jobsArray) { jobsArray = new Array(); } + + var tfunctor = Jet.job_tree_model_array_functor(jobsTree, function(node) { + var job = { "fullpath": (node.path + "." + node.name), "cpuT": 0.0, "depth": node.level } + jobsArray.push(job) + }) + Jet.task_traverseTree(rootConfig, tfunctor); + + for (var j = 0; j 0) { + + var rangeStack =new Array() + var frameDuration = Math.max(jobsArray[0].cpuT, 1) + rangeStack.push( { "b": 0.0, "e": frameDuration } ) + var timeScale = width * 0.9 / frameDuration; + + drawJob(ctx, 0, 0, jobsArray[0].cpuT, 0, timeScale) + + for (var i = 1; i lastDepth) { + timeOffset = rangeStack[lastDepth].b + while(rangeStack.length <= depth) { + rangeStack.push( { "b": timeOffset, "e": duration } ) + } + + } else { + if (depth < lastDepth) { + while(rangeStack.length != (depth + 1)) { + rangeStack.pop() + } + } + + timeOffset = rangeStack[depth].e + rangeStack[depth].b = timeOffset + rangeStack[depth].e = timeOffset + duration + } + + print("j " + i + " depth " + depth + " lastDepth " + lastDepth + " off " + timeOffset + " dur " + duration) + drawJob(ctx, depth, i, duration, timeOffset, timeScale) + } + } + } + } + } +} \ No newline at end of file diff --git a/scripts/developer/utilities/lib/jet/qml/qmldir b/scripts/developer/utilities/lib/jet/qml/qmldir index 3134545625..930641b10b 100644 --- a/scripts/developer/utilities/lib/jet/qml/qmldir +++ b/scripts/developer/utilities/lib/jet/qml/qmldir @@ -1,2 +1,3 @@ TaskList 1.0 TaskList.qml -TaskViewList 1.0 TaskViewList.qml \ No newline at end of file +TaskViewList 1.0 TaskViewList.qml +TaskTimeFrameView 1.0 TaskTimeFrameView.qml \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineInspector.js b/scripts/developer/utilities/render/engineInspector.js index dcf13157b5..348ae8f54f 100644 --- a/scripts/developer/utilities/render/engineInspector.js +++ b/scripts/developer/utilities/render/engineInspector.js @@ -4,10 +4,12 @@ var window = new OverlayWindow({ title: 'Render Engine', source: qml, - width: 300, - height: 400 + width: 500, + height: 100 }); window.setPosition(200, 50); - //window.closed.connect(function() { Script.stop(); }); + window.closed.connect(function() { Script.stop(); }); } - openEngineTaskView(); \ No newline at end of file + openEngineTaskView(); + + \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineInspector.qml b/scripts/developer/utilities/render/engineInspector.qml index 1b9941e64e..d2a6e01524 100644 --- a/scripts/developer/utilities/render/engineInspector.qml +++ b/scripts/developer/utilities/render/engineInspector.qml @@ -23,7 +23,8 @@ Item { property var mainViewTask: Render.getConfig("RenderMainView") - Jet.TaskListView { + //Jet.TaskListView { + Jet.TaskTimeFrameView { rootConfig: Render anchors.fill: render } From 3a910489c8b88b0c5d2a4de0f3cd3354deff3c62 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 20 Jun 2018 16:56:35 -0700 Subject: [PATCH 02/20] Regfining --- libraries/task/src/task/Config.h | 5 +- .../lib/jet/qml/TaskTimeFrameView.qml | 176 +++++++++++++++--- .../utilities/render/engineInspector.js | 60 +++++- .../utilities/render/engineInspector.qml | 7 +- 4 files changed, 217 insertions(+), 31 deletions(-) diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index c94ed5f8ce..a1e05cd043 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -123,7 +123,7 @@ public: // Running Time measurement // The new stats signal is emitted once per run time of a job when stats (cpu runtime) are updated - void setCPURunTime(const std::chrono::nanoseconds& runtime) { _msCPURunTime = std::chrono::duration(runtime).count(); emit newStats(); } + void setCPURunTime(const std::chrono::nanoseconds& runtime) { _msCPURunTime = std::chrono::duration(runtime).count(); /* emit newStats();*/ } double getCPURunTime() const { return _msCPURunTime; } // Describe the node graph data connections of the associated Job/Task @@ -230,7 +230,8 @@ public: auto tokens = path.split('.', QString::SkipEmptyParts); if (tokens.empty()) { - tokens.push_back(QString()); + return dynamic_cast(const_cast (root)); + // tokens.push_back(QString()); } else { while (tokens.size() > 1) { auto name = tokens.front(); diff --git a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml index ed1649a47a..4eca5075d0 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml @@ -27,27 +27,32 @@ Rectangle { property var jobsTree property var jobsArray + Component.onCompleted: { if (!jobsTree) { jobsTree = new Array(); } if (!jobsArray) { jobsArray = new Array(); } var tfunctor = Jet.job_tree_model_array_functor(jobsTree, function(node) { - var job = { "fullpath": (node.path + "." + node.name), "cpuT": 0.0, "depth": node.level } + var job = { "fullpath": (node.path + "." + node.name), "cpuT": 0.0, "depth": node.level, "name": node.name } jobsArray.push(job) }) Jet.task_traverseTree(rootConfig, tfunctor); for (var j = 0; j ") + height: 24 + width: 24 + onClicked: { + print("list of highlight styles") + myCanvasTimer.running = !myCanvasTimer.running + } + } + } Canvas { id: mycanvas - anchors.fill:parent + anchors.top:myHeaderRow.bottom + anchors.bottom:parent.bottom + anchors.left:parent.left + anchors.right:parent.right - onPaint: { - print("mycanvasOnPaint " + jobsArray.length) - var lineHeight = 12; - var frameWidth = width; + property var frameDuration: 10 + property var frameViewBegin: 0 + property var frameViewRange: width - + function reset() { + frameViewBegin = 0 + frameViewRange = width + } + + function checkView() { + if (frameViewBegin > width * 0.9) { + frameViewBegin = width * 0.9 + } else if (frameViewBegin + frameViewRange < width * 0.1) { + frameViewBegin = width * 0.1 -frameViewRange + } + } + + function drag(deltaX) { + frameViewBegin -= deltaX + checkView() + } + + function pivotScale(pivotX, deltaX) { + var newRange = frameViewRange + 2 * deltaX + if (newRange <= 1) { + newRange = 2; + } + frameViewBegin = pivotX - frameViewRange * (pivotX - frameViewBegin) / newRange + frameViewRange = newRange + print( "pivot= " + pivotX + " deltaX= " + (deltaX)) + checkView() + } + + + onPaint: { + // print("mycanvasOnPaint " + jobsArray.length) + var lineHeight = 12; + + function getXFromTime(t) { + return (t / mycanvas.frameDuration) * mycanvas.frameViewRange - (mycanvas.frameViewBegin) + } + function getWFromDuration(d) { + return (d / mycanvas.frameDuration) * mycanvas.frameViewRange + } function displayBackground(ctx) { ctx.fillStyle = Qt.rgba(0, 0, 0, root.backgroundOpacity); ctx.fillRect(0, 0, width, height); @@ -80,15 +147,34 @@ Rectangle { ctx.lineTo(width, lineHeight + 1); ctx.moveTo(0, height); ctx.lineTo(width, height); + + var x0 = getXFromTime(0) + ctx.moveTo(x0, 0); + ctx.lineTo(x0, height); + + x0 = getXFromTime(5) + ctx.moveTo(x0, 0); + ctx.lineTo(x0, height); + + x0 = getXFromTime(10) + ctx.moveTo(x0, 0); + ctx.lineTo(x0, height); + ctx.stroke(); } - function drawJob(ctx, depth, index, duration, timeOffset, timeScale) { + function drawJob(ctx, depth, index, duration, timeOffset) { //print(root.jobsArray[index].cpuT) // ctx.fillStyle = Qt.rgba(255, 255, 0, root.backgroundOpacity); ctx.fillStyle = ( depth % 2 ? ( index % 2 ? "blue" : "yellow") : ( index % 2 ? "green" : "red")) - ctx.fillRect(timeOffset * timeScale, lineHeight * depth, duration * timeScale, lineHeight * 0.6); - + ctx.fillRect(getXFromTime(timeOffset), lineHeight * 2 * depth,getWFromDuration(duration), lineHeight); + + if (depth,getWFromDuration(duration) >= width * 0.1) { + ctx.fillStyle = "grey"; + ctx.textAlign = "center"; + ctx.fillText( root.jobsArray[index].name, getXFromTime(timeOffset + duration * 0.5), lineHeight * 2 * depth); + + } } var ctx = getContext("2d"); @@ -97,26 +183,22 @@ Rectangle { displayBackground(ctx); if (jobsArray.length > 0) { - + mycanvas.frameDuration = Math.max(jobsArray[0].cpuT, 1) var rangeStack =new Array() - var frameDuration = Math.max(jobsArray[0].cpuT, 1) - rangeStack.push( { "b": 0.0, "e": frameDuration } ) - var timeScale = width * 0.9 / frameDuration; - - drawJob(ctx, 0, 0, jobsArray[0].cpuT, 0, timeScale) + rangeStack.push( { "b": 0.0, "e": mycanvas.frameDuration } ) + + drawJob(ctx, 0, 0, jobsArray[0].cpuT, 0) for (var i = 1; i lastDepth) { timeOffset = rangeStack[lastDepth].b while(rangeStack.length <= depth) { - rangeStack.push( { "b": timeOffset, "e": duration } ) + rangeStack.push( { "b": timeOffset, "e": timeOffset + duration } ) } } else { @@ -130,12 +212,54 @@ Rectangle { rangeStack[depth].b = timeOffset rangeStack[depth].e = timeOffset + duration } - - print("j " + i + " depth " + depth + " lastDepth " + lastDepth + " off " + timeOffset + " dur " + duration) - drawJob(ctx, depth, i, duration, timeOffset, timeScale) + if (duration > 0.0) { + drawJob(ctx, depth, i, duration, timeOffset) } } } } } + + MouseArea { + id: hitbox + anchors.fill: mycanvas + acceptedButtons: Qt.LeftButton | Qt.RightButton + + property var pivotX + property var dragPos + onPressed: { + dragPos = { "x":mouse.x, "y":mouse.y } + pivotX = mouse.x + } + onPositionChanged: { + if (dragPos !== undefined) { + var delta = mouse.x - dragPos.x + + if (mouse.buttons & Qt.LeftButton) { + mycanvas.drag(delta) + } + + if (mouse.buttons & Qt.RightButton) { + mycanvas.pivotScale(pivotX, delta) + } + + dragPos.x = mouse.x + dragPos.y = mouse.y + mycanvas.requestPaint() + } + } + onReleased: { + dragPos = undefined + } + + onWheel: { + mycanvas.pivotScale(wheel.x, mycanvas.frameViewRange * 0.02 * (wheel.angleDelta.y / 120.0)) + mycanvas.requestPaint() + } + + onDoubleClicked: { + mycanvas.reset() + mycanvas.requestPaint() + } + } } \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineInspector.js b/scripts/developer/utilities/render/engineInspector.js index 348ae8f54f..e6be7f1c3c 100644 --- a/scripts/developer/utilities/render/engineInspector.js +++ b/scripts/developer/utilities/render/engineInspector.js @@ -1,4 +1,4 @@ - function openEngineTaskView() { + /*function openEngineTaskView() { // Set up the qml ui var qml = Script.resolvePath('engineInspector.qml'); var window = new OverlayWindow({ @@ -10,6 +10,62 @@ window.setPosition(200, 50); window.closed.connect(function() { Script.stop(); }); } - openEngineTaskView(); + openEngineTaskView();*/ + (function() { + var TABLET_BUTTON_NAME = "Render Engine"; + var QMLAPP_URL = Script.resolvePath("./engineInspector.qml"); + var ICON_URL = Script.resolvePath("../../../system/assets/images/lod-i.svg"); + var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/lod-a.svg"); + + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + text: TABLET_BUTTON_NAME, + icon: ICON_URL, + activeIcon: ACTIVE_ICON_URL + }); + + Script.scriptEnding.connect(function () { + killWindow() + button.clicked.disconnect(onClicked); + tablet.removeButton(button); + }); + + button.clicked.connect(onClicked); + + var onScreen = false; + var window; + + function onClicked() { + if (onScreen) { + killWindow() + } else { + createWindow() + } + } + + function createWindow() { + var qml = Script.resolvePath(QMLAPP_URL); + window = new OverlayWindow({ + title: 'Render Engine', + source: qml, + width: 500, + height: 100 + }); + window.setPosition(200, 50); + window.closed.connect(killWindow); + onScreen = true + button.editProperties({isActive: true}); + } + + function killWindow() { + if (window !== undefined) { + window.closed.disconnect(killWindow); + window.close() + window = undefined + } + onScreen = false + button.editProperties({isActive: false}) + } + }()); \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineInspector.qml b/scripts/developer/utilities/render/engineInspector.qml index d2a6e01524..d3bd2e96fd 100644 --- a/scripts/developer/utilities/render/engineInspector.qml +++ b/scripts/developer/utilities/render/engineInspector.qml @@ -23,9 +23,14 @@ Item { property var mainViewTask: Render.getConfig("RenderMainView") - //Jet.TaskListView { + Jet.TaskTimeFrameView { rootConfig: Render anchors.fill: render } + /* Jet.TaskListView { + rootConfig: Render + anchors.fill: render + } */ + } \ No newline at end of file From 0f3cb0fb84a2928c699b888dbfa454ef394286c2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 3 Jul 2018 12:50:52 +0200 Subject: [PATCH 03/20] INtroducing th eGraphics Engine to group al the graphics related (render and gpu) elements --- interface/src/Application.cpp | 176 ++++++------------ interface/src/Application.h | 33 ++-- interface/src/Application_render.cpp | 139 +++++++------- interface/src/Util.cpp | 108 ----------- interface/src/Util.h | 5 - interface/src/graphics/GraphicsEngine.cpp | 167 +++++++++++++++++ interface/src/graphics/GraphicsEngine.h | 57 ++++++ interface/src/graphics/RenderEventHandler.cpp | 71 +++++++ interface/src/graphics/RenderEventHandler.h | 47 +++++ interface/src/graphics/WorldBox.cpp | 138 ++++++++++++++ interface/src/graphics/WorldBox.h | 43 +++++ interface/src/ui/ApplicationOverlay.cpp | 2 +- .../src/DeferredLightingEffect.cpp | 7 +- .../render-utils/src/DeferredLightingEffect.h | 3 +- libraries/render-utils/src/LightStage.cpp | 10 +- 15 files changed, 686 insertions(+), 320 deletions(-) create mode 100644 interface/src/graphics/GraphicsEngine.cpp create mode 100644 interface/src/graphics/GraphicsEngine.h create mode 100644 interface/src/graphics/RenderEventHandler.cpp create mode 100644 interface/src/graphics/RenderEventHandler.h create mode 100644 interface/src/graphics/WorldBox.cpp create mode 100644 interface/src/graphics/WorldBox.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a60d72073c..dc7a34e728 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -83,7 +83,7 @@ #include #include #include -#include +//#include #include #include #include @@ -116,8 +116,8 @@ #include #include #include -#include -#include +//#include +//#include #include #include #include @@ -247,71 +247,7 @@ extern "C" { #include "AndroidHelper.h" #endif -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) { - _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 }; -}; - +#include "graphics/RenderEventHandler.h" 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()->preloadSounds(); _pendingIdleEvent = false; - _pendingRenderEvent = false; + // _pendingRenderEvent = false; + _graphicsEngine.startup(); 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 // removal of the items. // See https://highfidelity.fogbugz.com/f/cases/5328 - _main3DScene->enqueueFrame(); // flush all the transactions - _main3DScene->processTransactionQueue(); // process and apply deletions + // _main3DScene->enqueueFrame(); // flush all the transactions + // _main3DScene->processTransactionQueue(); // process and apply deletions // first stop all timers directly or by invokeMethod // depending on what thread they run in @@ -2485,7 +2422,7 @@ void Application::cleanupBeforeQuit() { } _window->saveGeometry(); - _gpuContext->shutdown(); + // _gpuContext->shutdown(); // Destroy third party processes after scripts have finished using them. #ifdef HAVE_DDE @@ -2539,9 +2476,10 @@ Application::~Application() { assert(_shapeManager.getNumShapes() == 0); // shutdown render engine - _main3DScene = nullptr; - _renderEngine = nullptr; - + //_main3DScene = nullptr; + //_renderEngine = nullptr; + _graphicsEngine.shutdown(); + _gameWorkload.shutdown(); DependencyManager::destroy(); @@ -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->setObjectName("MainThreadContext"); _offscreenContext->create(_glWidget->qglContext()); @@ -2664,34 +2602,36 @@ void Application::initializeGL() { } _offscreenContext->doneCurrent(); _offscreenContext->setThreadContext(); - +*/ _glWidget->makeCurrent(); glClearColor(0.2f, 0.2f, 0.2f, 1); glClear(GL_COLOR_BUFFER_BIT); _glWidget->swapBuffers(); // Move the GL widget context to the render event handler thread - _renderEventHandler = new RenderEventHandler(_glWidget->qglContext()); - if (!_offscreenContext->makeCurrent()) { - qFatal("Unable to make offscreen context current"); - } + // _renderEventHandler = new RenderEventHandler(_glWidget->qglContext()); + // if (!_offscreenContext->makeCurrent()) { + // qFatal("Unable to make offscreen context current"); + // } // Create the GPU backend - // 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(); - qApp->setProperty(hifi::properties::gl::MAKE_PROGRAM_CALLBACK, - QVariant::fromValue((void*)(&gpu::gl::GLBackend::makeProgram))); - _glWidget->makeCurrent(); - _gpuContext = std::make_shared(); + //// 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(); + //qApp->setProperty(hifi::properties::gl::MAKE_PROGRAM_CALLBACK, + // QVariant::fromValue((void*)(&gpu::gl::GLBackend::makeProgram))); + //_glWidget->makeCurrent(); + //_gpuContext = std::make_shared(); - DependencyManager::get()->setGPUContext(_gpuContext); + //DependencyManager::get()->setGPUContext(_gpuContext); - // Restore the default main thread context - _offscreenContext->makeCurrent(); + //// Restore the default main thread context + //_offscreenContext->makeCurrent(); + + _graphicsEngine.initializeGPU(_glWidget); } static const QString SPLASH_SKYBOX{ "{\"ProceduralEntity\":{ \"version\":2, \"shaderUrl\":\"qrc:///shaders/splashSkybox.frag\" } }" }; @@ -2705,7 +2645,7 @@ void Application::initializeDisplayPlugins() { // Once time initialization code DisplayPluginPointer targetDisplayPlugin; foreach(auto displayPlugin, displayPlugins) { - displayPlugin->setContext(_gpuContext); + displayPlugin->setContext(_graphicsEngine.getGPUContext()); if (displayPlugin->getName() == lastActiveDisplayPluginName) { targetDisplayPlugin = displayPlugin; } @@ -2719,14 +2659,14 @@ void Application::initializeDisplayPlugins() { setDisplayPlugin(defaultDisplayPlugin); // Now set the desired plugin if it's not the same as the default plugin - if (targetDisplayPlugin != defaultDisplayPlugin) { + if (targetDisplayPlugin && (targetDisplayPlugin != defaultDisplayPlugin)) { setDisplayPlugin(targetDisplayPlugin); } // Submit a default frame to render until the engine starts up updateRenderArgs(0.0f); - _offscreenContext->makeCurrent(); + _graphicsEngine._offscreenContext->makeCurrent(); #define ENABLE_SPLASH_FRAME 0 #if ENABLE_SPLASH_FRAME @@ -2769,11 +2709,12 @@ void Application::initializeDisplayPlugins() { } 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. DeadlockWatchdogThread::withPause([&] { - // Set up the render engine + _graphicsEngine.initializeRender(DISABLE_DEFERRED); + /* // Set up the render engine render::CullFunctor cullFunctor = LODManager::shouldRender; _renderEngine->addJob("UpdateScene"); #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. DependencyManager::get()->initializeShapePipelines(); - }); + */ }); } extern void setupPreferences(); @@ -2999,7 +2940,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) { surfaceContext->setContextProperty("LODManager", DependencyManager::get().data()); surfaceContext->setContextProperty("HMD", DependencyManager::get().data()); surfaceContext->setContextProperty("Scene", DependencyManager::get().data()); - surfaceContext->setContextProperty("Render", _renderEngine->getConfiguration().get()); + surfaceContext->setContextProperty("Render", _graphicsEngine.getRenderEngine()->getConfiguration().get()); surfaceContext->setContextProperty("Workload", _gameWorkload._engine->getConfiguration().get()); surfaceContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface()); surfaceContext->setContextProperty("Snapshot", DependencyManager::get().data()); @@ -3454,8 +3395,8 @@ void Application::onPresent(quint32 frameCount) { postEvent(this, new QEvent((QEvent::Type)ApplicationEvent::Idle), Qt::HighEventPriority); } expected = false; - if (_renderEventHandler && !isAboutToQuit() && _pendingRenderEvent.compare_exchange_strong(expected, true)) { - postEvent(_renderEventHandler, new QEvent((QEvent::Type)ApplicationEvent::Render)); + if (_graphicsEngine.checkPendingRenderEvent() && !isAboutToQuit()) { + postEvent(_graphicsEngine._renderEventHandler, new QEvent((QEvent::Type)ApplicationEvent::Render)); } } @@ -4229,7 +4170,8 @@ bool Application::shouldPaint() const { #endif // 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; } @@ -4481,7 +4423,7 @@ void Application::idle() { if (offscreenUi->size() != fromGlm(uiSize)) { qCDebug(interfaceapp) << "Device pixel ratio changed, triggering resize to " << 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, "currentProcessing", int, DependencyManager::get()->getStat("Processing").toInt()); PROFILE_COUNTER_IF_CHANGED(app, "pendingProcessing", int, DependencyManager::get()->getStat("PendingProcessing").toInt()); - auto renderConfig = _renderEngine->getConfiguration(); - PROFILE_COUNTER_IF_CHANGED(render, "gpuTime", float, (float)_gpuContext->getFrameTimerGPUAverage()); + auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration(); + PROFILE_COUNTER_IF_CHANGED(render, "gpuTime", float, (float)_graphicsEngine.getGPUContext()->getFrameTimerGPUAverage()); auto opaqueRangeTimer = renderConfig->getConfig("OpaqueRangeTimer"); auto linearDepth = renderConfig->getConfig("LinearDepth"); auto surfaceGeometry = renderConfig->getConfig("SurfaceGeometry"); @@ -4536,7 +4478,7 @@ void Application::idle() { bool showWarnings = getLogger()->extraDebugging(); PerformanceWarning warn(showWarnings, "idle()"); - if (!_offscreenContext->makeCurrent()) { + if (!_graphicsEngine._offscreenContext->makeCurrent()) { qFatal("Unable to make main thread context current"); } @@ -4866,12 +4808,12 @@ QVector Application::pasteEntities(float x, float y, float z) { } void Application::init() { - _offscreenContext->makeCurrent(); + _graphicsEngine._offscreenContext->makeCurrent(); // Make sure Login state is up to date DependencyManager::get()->toggleLoginDialog(); - if (!DISABLE_DEFERRED) { - DependencyManager::get()->init(); - } +// if (!DISABLE_DEFERRED) { + // DependencyManager::get()->init(); + // } DependencyManager::get()->init(); _timerStart.start(); @@ -4940,7 +4882,7 @@ void Application::init() { } }, Qt::QueuedConnection); - _gameWorkload.startup(getEntities()->getWorkloadSpace(), _main3DScene, _entitySimulation); + _gameWorkload.startup(getEntities()->getWorkloadSpace(), _graphicsEngine.getRenderScene(), _entitySimulation); _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 if (!isThrottleRendering()) { float presentTime = getActiveDisplayPlugin()->getAveragePresentTime(); - float engineRunTime = (float)(_renderEngine->getConfiguration().get()->getCPURunTime()); + float engineRunTime = (float)(_graphicsEngine.getRenderEngine()->getConfiguration().get()->getCPURunTime()); float gpuTime = getGPUContext()->getFrameTimerGPUAverage(); auto lodManager = DependencyManager::get(); lodManager->setRenderTimes(presentTime, engineRunTime, gpuTime); @@ -5364,7 +5306,7 @@ void Application::updateSecondaryCameraViewFrustum() { // camera should be. // Code based on SecondaryCameraJob - auto renderConfig = _renderEngine->getConfiguration(); + auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration(); assert(renderConfig); auto camera = dynamic_cast(renderConfig->getConfig("SecondaryCamera")); @@ -5935,7 +5877,7 @@ void Application::updateRenderArgs(float deltaTime) { _viewFrustum.setProjection(adjustedProjection); _viewFrustum.calculate(); } - appRenderArgs._renderArgs = RenderArgs(_gpuContext, lodManager->getOctreeSizeScale(), + appRenderArgs._renderArgs = RenderArgs(_graphicsEngine.getGPUContext(), lodManager->getOctreeSizeScale(), lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); appRenderArgs._renderArgs._scene = getMain3DScene(); @@ -6597,7 +6539,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe scriptEngine->registerFunction("HMD", "getHUDLookAtPosition3D", HMDScriptingInterface::getHUDLookAtPosition3D, 0); scriptEngine->registerGlobalObject("Scene", DependencyManager::get().data()); - scriptEngine->registerGlobalObject("Render", _renderEngine->getConfiguration().get()); + scriptEngine->registerGlobalObject("Render", _graphicsEngine.getRenderEngine()->getConfiguration().get()); scriptEngine->registerGlobalObject("Workload", _gameWorkload._engine->getConfiguration().get()); GraphicsScriptingInterface::registerMetaTypes(scriptEngine.data()); @@ -8241,7 +8183,7 @@ QOpenGLContext* Application::getPrimaryContext() { } bool Application::makeRenderingContextCurrent() { - return _offscreenContext->makeCurrent(); + return _graphicsEngine._offscreenContext->makeCurrent(); } bool Application::isForeground() const { diff --git a/interface/src/Application.h b/interface/src/Application.h index 346ea258da..249c5a723a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -73,6 +73,7 @@ #include "UndoStackScriptingInterface.h" #include "workload/GameWorkload.h" +#include "graphics/GraphicsEngine.h" #include #include @@ -157,6 +158,7 @@ public: void updateSecondaryCameraViewFrustum(); void updateCamera(RenderArgs& renderArgs, float deltaTime); + bool shouldPaint() const; void paintGL(); void resizeGL(); @@ -271,10 +273,16 @@ public: void setMaxOctreePacketsPerSecond(int maxOctreePPS); int getMaxOctreePacketsPerSecond() const; - render::ScenePointer getMain3DScene() override { return _main3DScene; } +/* render::ScenePointer getMain3DScene() override { return _main3DScene; } const render::ScenePointer& getMain3DScene() const { return _main3DScene; } render::EnginePointer getRenderEngine() override { return _renderEngine; } 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; } @@ -490,7 +498,6 @@ private: bool handleFileOpenEvent(QFileOpenEvent* event); void cleanupBeforeQuit(); - bool shouldPaint() const; void idle(); void update(float deltaTime); @@ -510,7 +517,7 @@ private: 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 importSVOFromURL(const QString& urlString); @@ -551,7 +558,7 @@ private: bool _previousSessionCrashed; - OffscreenGLCanvas* _offscreenContext { nullptr }; + // OffscreenGLCanvas* _offscreenContext { nullptr }; DisplayPluginPointer _displayPlugin; QMetaObject::Connection _displayPluginPresentConnection; mutable std::mutex _displayPluginLock; @@ -573,7 +580,7 @@ private: QTimer _minimizedWindowTimer; QElapsedTimer _timerStart; QElapsedTimer _lastTimeUpdated; - QElapsedTimer _lastTimeRendered; + // QElapsedTimer _lastTimeRendered; ShapeManager _shapeManager; PhysicalEntitySimulationPointer _entitySimulation; @@ -657,12 +664,14 @@ private: quint64 _lastFaceTrackerUpdate; - render::ScenePointer _main3DScene{ 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 + // render::ScenePointer _main3DScene{ 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 GameWorkload _gameWorkload; + GraphicsEngine _graphicsEngine; + mutable QMutex _renderArgsMutex{ QMutex::Recursive }; struct AppRenderArgs { render::Args _renderArgs; @@ -720,8 +729,6 @@ private: bool _keyboardDeviceHasFocus { true }; - QString _returnFromFullScreenMirrorTo; - ConnectionMonitor _connectionMonitor; QTimer _addAssetToWorldResizeTimer; @@ -754,12 +761,12 @@ private: QUrl _avatarOverrideUrl; bool _saveAvatarOverrideUrl { false }; - QObject* _renderEventHandler{ nullptr }; + // QObject* _renderEventHandler{ nullptr }; - friend class RenderEventHandler; + // friend class RenderEventHandler; std::atomic _pendingIdleEvent { true }; - std::atomic _pendingRenderEvent { true }; + // std::atomic _pendingRenderEvent { true }; bool quitWhenFinished { false }; }; diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index 2daa49dcf7..9fe259ea36 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -32,7 +32,8 @@ void Application::paintGL() { // Some plugins process message events, allowing paintGL to be called reentrantly. _renderFrameCount++; - _lastTimeRendered.start(); + // SG: Moved into the RenderEventHandler + //_lastTimeRendered.start(); auto lastPaintBegin = usecTimestampNow(); PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount); @@ -88,10 +89,10 @@ void Application::paintGL() { { PROFILE_RANGE(render, "/gpuContextReset"); - _gpuContext->beginFrame(_appRenderArgs._view, HMDSensorPose); + _graphicsEngine.getGPUContext()->beginFrame(_appRenderArgs._view, HMDSensorPose); // Reset the gpu::Context Stages // 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(); }); } @@ -132,10 +133,10 @@ void Application::paintGL() { renderArgs._hudOperator = displayPlugin->getHUDOperator(); renderArgs._hudTexture = _applicationOverlay.getOverlayTexture(); renderArgs._blitFramebuffer = finalFramebuffer; - runRenderFrame(&renderArgs); + _graphicsEngine.render_runRenderFrame(&renderArgs); } - auto frame = _gpuContext->endFrame(); + auto frame = _graphicsEngine.getGPUContext()->endFrame(); frame->frameIndex = _renderFrameCount; frame->framebuffer = finalFramebuffer; frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) { @@ -163,68 +164,68 @@ void Application::paintGL() { // WorldBox Render Data & rendering functions - -class WorldBoxRenderData { -public: - typedef render::Payload Payload; - typedef Payload::DataPointer Pointer; - - int _val = 0; - static render::ItemID _item; // unique WorldBoxRenderData -}; - -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()->bindSimpleProgram(batch); - renderWorldBox(args, batch); - } - } -} - -void Application::runRenderFrame(RenderArgs* renderArgs) { - PROFILE_RANGE(render, __FUNCTION__); - PerformanceTimer perfTimer("display"); - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::runRenderFrame()"); - - // The pending changes collecting the changes here - render::Transaction transaction; - - 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)) { - auto worldBoxRenderData = std::make_shared(); - auto worldBoxRenderPayload = std::make_shared(worldBoxRenderData); - - WorldBoxRenderData::_item = _main3DScene->allocateID(); - - transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload); - _main3DScene->enqueueTransaction(transaction); - } - - { - PerformanceTimer perfTimer("EngineRun"); - _renderEngine->getRenderContext()->args = renderArgs; - _renderEngine->run(); - } -} +// +//class WorldBoxRenderData { +//public: +// typedef render::Payload Payload; +// typedef Payload::DataPointer Pointer; +// +// int _val = 0; +// static render::ItemID _item; // unique WorldBoxRenderData +//}; +// +//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()->bindSimpleProgram(batch); +// renderWorldBox(args, batch); +// } +// } +//} +// +//void Application::runRenderFrame(RenderArgs* renderArgs) { +// PROFILE_RANGE(render, __FUNCTION__); +// PerformanceTimer perfTimer("display"); +// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::runRenderFrame()"); +// +// // The pending changes collecting the changes here +// render::Transaction transaction; +// +// 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)) { +// auto worldBoxRenderData = std::make_shared(); +// auto worldBoxRenderPayload = std::make_shared(worldBoxRenderData); +// +// WorldBoxRenderData::_item = _main3DScene->allocateID(); +// +// transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload); +// _main3DScene->enqueueTransaction(transaction); +// } +// +// { +// PerformanceTimer perfTimer("EngineRun"); +// _renderEngine->getRenderContext()->args = renderArgs; +// _renderEngine->run(); +// } +//} diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index e5e94da68a..e09872434a 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -36,114 +36,6 @@ using namespace std; -void renderWorldBox(RenderArgs* args, gpu::Batch& batch) { - auto geometryCache = DependencyManager::get(); - - // 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 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 void runTimingTests() { // How long does it take to make a call to get the time? diff --git a/interface/src/Util.h b/interface/src/Util.h index 976a26ce82..ef289f5416 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -15,14 +15,9 @@ #include #include -#include -#include - class ShapeEntityItem; class ShapeInfo; -void renderWorldBox(RenderArgs* args, gpu::Batch& batch); - void runTimingTests(); void runUnitTests(); diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp new file mode 100644 index 0000000000..af207b988a --- /dev/null +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -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 + +#include "WorldBox.h" +#include "LODManager.h" + +#include +#include +#include +#include +#include + +#include "RenderEventHandler.h" + +#include +#include +#include + +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(); + qApp->setProperty(hifi::properties::gl::MAKE_PROGRAM_CALLBACK, + QVariant::fromValue((void*)(&gpu::gl::GLBackend::makeProgram))); + glwidget->makeCurrent(); + _gpuContext = std::make_shared(); + + DependencyManager::get()->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("UpdateScene"); +#ifndef Q_OS_ANDROID + _renderEngine->addJob("SecondaryCameraJob", cullFunctor, !disableDeferred); +#endif + _renderEngine->addJob("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()->initializeShapePipelines(); + + +} + +void GraphicsEngine::startup() { + + + static_cast(_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()->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(); + auto worldBoxRenderPayload = std::make_shared(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)->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { + return false; + } + + return true; +} + +bool GraphicsEngine::checkPendingRenderEvent() { + bool expected = false; + return (_renderEventHandler && static_cast(_renderEventHandler)->_pendingRenderEvent.compare_exchange_strong(expected, true)); +} diff --git a/interface/src/graphics/GraphicsEngine.h b/interface/src/graphics/GraphicsEngine.h new file mode 100644 index 0000000000..29128daafd --- /dev/null +++ b/interface/src/graphics/GraphicsEngine.h @@ -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 +#include + +#include + +#include + +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 diff --git a/interface/src/graphics/RenderEventHandler.cpp b/interface/src/graphics/RenderEventHandler.cpp new file mode 100644 index 0000000000..0ca82201d5 --- /dev/null +++ b/interface/src/graphics/RenderEventHandler.cpp @@ -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 +#include + +#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); +} + diff --git a/interface/src/graphics/RenderEventHandler.h b/interface/src/graphics/RenderEventHandler.h new file mode 100644 index 0000000000..8b0e4c5e15 --- /dev/null +++ b/interface/src/graphics/RenderEventHandler.h @@ -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 +#include + +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 _pendingRenderEvent{ true }; + + void resumeThread(); + +private: + void initialize(); + + void render(); + + bool event(QEvent* event) override; + + OffscreenGLCanvas* _renderContext{ nullptr }; +}; + +#endif // #include hifi_RenderEventHandler_h \ No newline at end of file diff --git a/interface/src/graphics/WorldBox.cpp b/interface/src/graphics/WorldBox.cpp new file mode 100644 index 0000000000..908055e9c6 --- /dev/null +++ b/interface/src/graphics/WorldBox.cpp @@ -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()->bindSimpleProgram(batch); + WorldBoxRenderData::renderWorldBox(args, batch); + } + } +} + +void WorldBoxRenderData::renderWorldBox(RenderArgs* args, gpu::Batch& batch) { + auto geometryCache = DependencyManager::get(); + + // 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 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); +} + diff --git a/interface/src/graphics/WorldBox.h b/interface/src/graphics/WorldBox.h new file mode 100644 index 0000000000..114777ba0f --- /dev/null +++ b/interface/src/graphics/WorldBox.h @@ -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 + +#include +#include + +#include +#include +#include "Menu.h" + + + +class WorldBoxRenderData { +public: + typedef render::Payload 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 \ No newline at end of file diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index ea660fb0e2..a0b4f856a1 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -55,7 +55,7 @@ ApplicationOverlay::~ApplicationOverlay() { // Renders the overlays either to a texture or to the screen void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { PROFILE_RANGE(render, __FUNCTION__); - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); +// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); buildFramebufferObject(); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 9223e0fa03..6b6d8f00b7 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -712,11 +712,16 @@ void RenderDeferredCleanup::run(const render::RenderContextPointer& renderContex } } +RenderDeferred::RenderDeferred(bool renderShadows): + _renderShadows(renderShadows) +{ + DependencyManager::get()->init(); +} + void RenderDeferred::configure(const Config& config) { } void RenderDeferred::run(const RenderContextPointer& renderContext, const Inputs& inputs) { - PROFILE_RANGE(render, "DeferredLighting"); auto deferredTransform = inputs.get0(); auto deferredFramebuffer = inputs.get1(); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 9b55083ad7..96d3f42958 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -167,8 +167,7 @@ public: using Config = RenderDeferredConfig; using JobModel = render::Job::ModelI; - RenderDeferred() {} - RenderDeferred(bool renderShadows) : _renderShadows(renderShadows) {} + RenderDeferred(bool renderShadows = false); void configure(const Config& config); diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index ceac4ae3c8..9d6a8e6016 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -424,10 +424,12 @@ LightStageSetup::LightStageSetup() { } void LightStageSetup::run(const render::RenderContextPointer& renderContext) { - auto stage = renderContext->_scene->getStage(LightStage::getName()); - if (!stage) { - stage = std::make_shared(); - renderContext->_scene->resetStage(LightStage::getName(), stage); + if (renderContext->_scene) { + auto stage = renderContext->_scene->getStage(LightStage::getName()); + if (!stage) { + stage = std::make_shared(); + renderContext->_scene->resetStage(LightStage::getName(), stage); + } } } From f9bd6f5d039eec7c4f797cf6d4a8635d1d1daf36 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 4 Jul 2018 11:34:58 +0200 Subject: [PATCH 04/20] slowly clening up --- interface/src/Application.cpp | 4 ++-- interface/src/graphics/GraphicsEngine.cpp | 2 ++ interface/src/graphics/GraphicsEngine.h | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 12d5c537d1..dc091f3809 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2536,7 +2536,7 @@ Application::~Application() { // Can't log to file passed this point, FileLogger about to be deleted qInstallMessageHandler(LogHandler::verboseMessageHandler); - _renderEventHandler->deleteLater(); +// _renderEventHandler->deleteLater(); } void Application::initializeGL() { @@ -4178,7 +4178,7 @@ bool Application::shouldPaint() const { // Throttle if requested //if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { - if (displayPlugin->isThrottled() && _graphicsEngine.shouldPaint()) { + if (displayPlugin->isThrottled() && !_graphicsEngine.shouldPaint()) { return false; } diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index af207b988a..eea54c7b8a 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -102,6 +102,8 @@ void GraphicsEngine::shutdown() { // shutdown render engine _renderScene = nullptr; _renderEngine = nullptr; + + _renderEventHandler->deleteLater(); } diff --git a/interface/src/graphics/GraphicsEngine.h b/interface/src/graphics/GraphicsEngine.h index 29128daafd..89d1eb1d94 100644 --- a/interface/src/graphics/GraphicsEngine.h +++ b/interface/src/graphics/GraphicsEngine.h @@ -36,7 +36,7 @@ public: bool checkPendingRenderEvent(); private: - // THread specific calls + // Thread specific calls void render_runRenderFrame(RenderArgs* renderArgs); protected: From d2a66b9e7de8a1f4a3a68c95a9de7665ec0e5295 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 4 Jul 2018 17:26:24 +0200 Subject: [PATCH 05/20] Moving the paintGL to a true GraphicsEngine::render_performFrame() --- interface/src/Application.cpp | 19 +- interface/src/Application.h | 29 +- interface/src/Application_render.cpp | 279 +++++++++--------- interface/src/graphics/GraphicsEngine.cpp | 180 +++++++++-- interface/src/graphics/GraphicsEngine.h | 35 +++ interface/src/graphics/RenderEventHandler.cpp | 6 +- interface/src/graphics/RenderEventHandler.h | 6 +- libraries/task/src/task/Config.h | 7 +- libraries/task/src/task/Task.h | 4 +- 9 files changed, 360 insertions(+), 205 deletions(-) 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()) { From 2eec5b01fa69874c580fb49febe32dbe16d7c41f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 6 Jul 2018 10:53:09 +0200 Subject: [PATCH 06/20] debugging and fixing the problem to get Config for complex path --- interface/src/Application.cpp | 6 ++--- libraries/task/src/task/Config.h | 23 ++++++++++++++----- .../utilities/lib/jet/qml/TaskListView.qml | 15 ++++++------ .../utilities/render/engineInspector.qml | 8 +++---- 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fbba8c5c87..487fafe2df 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4444,7 +4444,7 @@ void Application::idle() { PROFILE_COUNTER_IF_CHANGED(app, "pendingProcessing", int, DependencyManager::get()->getStat("PendingProcessing").toInt()); auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration(); 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 surfaceGeometry = renderConfig->getConfig("SurfaceGeometry"); auto renderDeferred = renderConfig->getConfig("RenderDeferred"); @@ -4456,7 +4456,7 @@ void Application::idle() { { "SurfaceGeometry", surfaceGeometry ? surfaceGeometry->property("gpuRunTime") : 0 }, { "RenderDeferred", renderDeferred ? renderDeferred->property("gpuRunTime") : 0 }, { "ToneAndPostRangeTimer", toneAndPostRangeTimer ? toneAndPostRangeTimer->property("gpuRunTime") : 0 } - }); + });*/ PROFILE_RANGE(app, __FUNCTION__); @@ -5759,7 +5759,7 @@ void Application::update(float deltaTime) { // TODO: Fix this by modeling the way the secondary camera works on how the main camera works // ie. Use a camera object stored in the game logic and informs the Engine on where the secondary // camera should be. - updateSecondaryCameraViewFrustum(); + // updateSecondaryCameraViewFrustum(); } quint64 now = usecTimestampNow(); diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index 0ecfa9bfd7..4a9414fd42 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -219,30 +219,41 @@ public: // optional sub_parent_names and finally from there looking for the job_name (assuming every job in the path were found) // // getter for qml integration, prefer the templated getter +#pragma optimize("", off) Q_INVOKABLE QObject* getConfig(const QString& name) { return getConfig(name.toStdString()); } // getter for cpp (strictly typed), prefer this getter template typename T::Config* getConfig(std::string job = "") const { const TaskConfig* root = this; - QString path = (job.empty() ? QString() : QString(job.c_str())); // an empty string is not a null string - auto tokens = path.split('.', QString::SkipEmptyParts); + std::string jobPath = (job); + //QString path = (job.empty() ? QString() : QString(job.c_str())); // an empty string is not a null string + //auto tokens = path.split('.', QString::SkipEmptyParts); + std::list tokens; + std::size_t pos = 0, found; + while ((found = jobPath.find_first_of('.', pos)) != std::string::npos) { + tokens.push_back(jobPath.substr(pos, found - pos)); + pos = found + 1; + } + tokens.push_back(jobPath.substr(pos)); + QString jobToken; if (tokens.empty()) { // return dynamic_cast(const_cast (root)); - tokens.push_back(QString()); + //tokens.push_back(std::string()); } else { while (tokens.size() > 1) { auto name = tokens.front(); tokens.pop_front(); - root = QObject::findChild(name); + root = root->findChild((name.empty() ? QString() : QString(name.c_str()))); if (!root) { return nullptr; } } + jobToken = QString(tokens.front().c_str()); } - return root->findChild(tokens.front()); + return root->findChild(jobToken); } - +#pragma optimize("", on) Q_INVOKABLE bool isTask() const override { return true; } Q_INVOKABLE QObjectList getSubConfigs() const override { auto list = findChildren(QRegExp(".*"), Qt::FindDirectChildrenOnly); diff --git a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml index 7c077f495a..f8997dfaf4 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml @@ -27,29 +27,29 @@ Rectangle { Component.onCompleted: { //var functor = Jet.job_tree_model_functor(jobsModel) - /* var functor = Jet.job_tree_model_functor(jobsModel, 1, function(node) { + var functor = Jet.job_tree_model_functor(jobsModel, 3, function(node) { node["cpuT"] = 0.0 }) Jet.task_traverseTree(rootConfig, functor); - */ + - var tfunctor = Jet.job_tree_model_array_functor(jobsModel.engineJobItemModel, function(node) { + /* var tfunctor = Jet.job_tree_model_array_functor(jobsModel.engineJobItemModel, function(node) { node["init"] = (node.level < 3) node["fullpath"] = (node.path + "." + node.name) node["cpuT"] = 0.0 }) Jet.task_traverseTree(rootConfig, tfunctor); - +*/ // var currentParentStach = [] // currentParentStach.push(jobsModel); - Jet.job_traverseTreeNodeRoot(jobsModel.engineJobItemModel[0], function(node, depth, index) { + /* Jet.job_traverseTreeNodeRoot(jobsModel.engineJobItemModel[0], function(node, depth, index) { print(node.name + depth + " - " + index) return true - }) + })*/ } @@ -64,8 +64,7 @@ Rectangle { id: objRecursiveColumn clip: true visible: model.init - // visible: (node.level < 2) - + function switchFold() { for(var i = 1; i < children.length - 1; ++i) { children[i].visible = !children[i].visible diff --git a/scripts/developer/utilities/render/engineInspector.qml b/scripts/developer/utilities/render/engineInspector.qml index d3bd2e96fd..7a2dfcc9e2 100644 --- a/scripts/developer/utilities/render/engineInspector.qml +++ b/scripts/developer/utilities/render/engineInspector.qml @@ -24,13 +24,13 @@ Item { property var mainViewTask: Render.getConfig("RenderMainView") - Jet.TaskTimeFrameView { + /* Jet.TaskTimeFrameView { rootConfig: Render anchors.fill: render - } - /* Jet.TaskListView { + }*/ + Jet.TaskListView { rootConfig: Render anchors.fill: render - } */ + } } \ No newline at end of file From 07299291fca218aea3167950227362d5af2ba23d Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 6 Jul 2018 19:29:06 +0200 Subject: [PATCH 07/20] clarifying the engine inspector and engine profiler --- interface/src/SecondaryCamera.cpp | 2 +- libraries/task/src/task/Config.cpp | 54 +++++++++++++++++ libraries/task/src/task/Config.h | 37 ++---------- .../utilities/lib/jet/qml/TaskListView.qml | 2 +- .../lib/jet/qml/TaskTimeFrameView.qml | 2 +- .../utilities/render/deferredLighting.qml | 19 ++++-- .../utilities/render/engineInspector.js | 2 +- .../utilities/render/engineInspector.qml | 20 +++---- .../utilities/render/engineProfiler.js | 59 +++++++++++++++++++ .../utilities/render/engineProfiler.qml | 31 ++++++++++ scripts/developer/utilities/render/luci.js | 32 ++++++++-- 11 files changed, 202 insertions(+), 58 deletions(-) create mode 100644 scripts/developer/utilities/render/engineProfiler.js create mode 100644 scripts/developer/utilities/render/engineProfiler.qml diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index a940aab4db..184762632f 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -171,7 +171,7 @@ void SecondaryCameraJobConfig::setOrientation(glm::quat orient) { } void SecondaryCameraJobConfig::enableSecondaryCameraRenderConfigs(bool enabled) { - qApp->getRenderEngine()->getConfiguration()->getConfig()->setEnabled(enabled); + qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCameraJob")->setEnabled(enabled); setEnabled(enabled); } diff --git a/libraries/task/src/task/Config.cpp b/libraries/task/src/task/Config.cpp index b378237c9c..ac7105be29 100644 --- a/libraries/task/src/task/Config.cpp +++ b/libraries/task/src/task/Config.cpp @@ -68,3 +68,57 @@ void TaskConfig::refresh() { _task->applyConfiguration(); } +TaskConfig* TaskConfig::getRootConfig(const std::string& jobPath, std::string& jobName) const { + TaskConfig* root = const_cast (this); + + std::list tokens; + std::size_t pos = 0, sepPos; + while ((sepPos = jobPath.find_first_of('.', pos)) != std::string::npos) { + std::string token = jobPath.substr(pos, sepPos - pos); + if (!token.empty()) { + tokens.push_back(token); + } + pos = sepPos + 1; + } + { + std::string token = jobPath.substr(pos, sepPos - pos); + if (!token.empty()) { + tokens.push_back(token); + } + } + + if (tokens.empty()) { + return root; + } + else { + while (tokens.size() > 1) { + auto taskName = tokens.front(); + tokens.pop_front(); + root = root->findChild((taskName.empty() ? QString() : QString(taskName.c_str()))); + if (!root) { + return nullptr; + } + } + jobName = tokens.front(); + } + return root; +} + +JobConfig* TaskConfig::getJobConfig(const std::string& jobPath) const { + std::string jobName; + auto root = getRootConfig(jobPath, jobName); + + if (!root) { + return nullptr; + } + if (jobName.empty()) { + return root; + } else { + + auto found = root->findChild((jobName.empty() ? QString() : QString(jobName.c_str()))); + if (!found) { + return nullptr; + } + return found; + } +} diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index 4a9414fd42..b76c57521f 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -219,41 +219,16 @@ public: // optional sub_parent_names and finally from there looking for the job_name (assuming every job in the path were found) // // getter for qml integration, prefer the templated getter -#pragma optimize("", off) Q_INVOKABLE QObject* getConfig(const QString& name) { return getConfig(name.toStdString()); } + // getter for cpp (strictly typed), prefer this getter - template typename T::Config* getConfig(std::string job = "") const { - const TaskConfig* root = this; - std::string jobPath = (job); - //QString path = (job.empty() ? QString() : QString(job.c_str())); // an empty string is not a null string - //auto tokens = path.split('.', QString::SkipEmptyParts); - std::list tokens; - std::size_t pos = 0, found; - while ((found = jobPath.find_first_of('.', pos)) != std::string::npos) { - tokens.push_back(jobPath.substr(pos, found - pos)); - pos = found + 1; - } - tokens.push_back(jobPath.substr(pos)); + TaskConfig* getRootConfig(const std::string& jobPath, std::string& jobName) const; + JobConfig* getJobConfig(const std::string& jobPath) const; - QString jobToken; - if (tokens.empty()) { - // return dynamic_cast(const_cast (root)); - //tokens.push_back(std::string()); - } else { - while (tokens.size() > 1) { - auto name = tokens.front(); - tokens.pop_front(); - root = root->findChild((name.empty() ? QString() : QString(name.c_str()))); - if (!root) { - return nullptr; - } - } - jobToken = QString(tokens.front().c_str()); - } - - return root->findChild(jobToken); + template typename T::Config* getConfig(std::string jobPath = "") const { + return dynamic_cast(getJobConfig(jobPath)); } -#pragma optimize("", on) + Q_INVOKABLE bool isTask() const override { return true; } Q_INVOKABLE QObjectList getSubConfigs() const override { auto list = findChildren(QRegExp(".*"), Qt::FindDirectChildrenOnly); diff --git a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml index f8997dfaf4..1229ef7dc7 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml @@ -19,7 +19,7 @@ import "../jet.js" as Jet Rectangle { HifiConstants { id: hifi;} - color: hifi.colors.baseGray; + // color: hifi.colors.baseGray; id: root; property var rootConfig : Workload diff --git a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml index 4eca5075d0..267344fca5 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml @@ -19,7 +19,7 @@ import "../jet.js" as Jet Rectangle { HifiConstants { id: hifi;} - color: hifi.colors.baseGray; + // color: hifi.colors.baseGray; id: root; property var rootConfig : Workload diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index 8a4a8f0622..abb15d5a38 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -277,11 +277,20 @@ Rectangle { } } Separator {} - HifiControls.Button { - text: "Engine" - // activeFocusOnPress: false - onClicked: { - sendToScript({method: "openEngineView"}); + Row { + HifiControls.Button { + text: "Inspector" + // activeFocusOnPress: false + onClicked: { + sendToScript({method: "openEngineInspector"}); + } + } + HifiControls.Button { + text: "EnProfilergine" + // activeFocusOnPress: false + onClicked: { + sendToScript({method: "openEngineProfiler"}); + } } } } diff --git a/scripts/developer/utilities/render/engineInspector.js b/scripts/developer/utilities/render/engineInspector.js index e6be7f1c3c..868a421c8d 100644 --- a/scripts/developer/utilities/render/engineInspector.js +++ b/scripts/developer/utilities/render/engineInspector.js @@ -47,7 +47,7 @@ function createWindow() { var qml = Script.resolvePath(QMLAPP_URL); window = new OverlayWindow({ - title: 'Render Engine', + title: 'Render Engine Inspector', source: qml, width: 500, height: 100 diff --git a/scripts/developer/utilities/render/engineInspector.qml b/scripts/developer/utilities/render/engineInspector.qml index 7a2dfcc9e2..52a9879038 100644 --- a/scripts/developer/utilities/render/engineInspector.qml +++ b/scripts/developer/utilities/render/engineInspector.qml @@ -1,7 +1,7 @@ // -// deferredLighting.qml +// EngineInspector.qml // -// Created by Sam Gateau on 6/6/2016 +// Created by Sam Gateau on 06/07/2018 // Copyright 2016 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -18,19 +18,13 @@ import "../lib/jet/qml" as Jet Item { HifiConstants { id: hifi;} - id: render; + id: root; anchors.fill: parent - property var mainViewTask: Render.getConfig("RenderMainView") + property var rootConfig: Render.getConfig("RenderMainView") - - /* Jet.TaskTimeFrameView { - rootConfig: Render - anchors.fill: render - }*/ Jet.TaskListView { - rootConfig: Render - anchors.fill: render - } - + rootConfig: root.rootConfig + anchors.fill: root + } } \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineProfiler.js b/scripts/developer/utilities/render/engineProfiler.js new file mode 100644 index 0000000000..b9443da1e9 --- /dev/null +++ b/scripts/developer/utilities/render/engineProfiler.js @@ -0,0 +1,59 @@ + + + (function() { + var TABLET_BUTTON_NAME = "Render Engine Profiler"; + var QMLAPP_URL = Script.resolvePath("./engineProfiler.qml"); + var ICON_URL = Script.resolvePath("../../../system/assets/images/lod-i.svg"); + var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/lod-a.svg"); + + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + text: TABLET_BUTTON_NAME, + icon: ICON_URL, + activeIcon: ACTIVE_ICON_URL + }); + + Script.scriptEnding.connect(function () { + killWindow() + button.clicked.disconnect(onClicked); + tablet.removeButton(button); + }); + + button.clicked.connect(onClicked); + + var onScreen = false; + var window; + + function onClicked() { + if (onScreen) { + killWindow() + } else { + createWindow() + } + } + + function createWindow() { + var qml = Script.resolvePath(QMLAPP_URL); + window = new OverlayWindow({ + title: 'Render Engine Profiler', + source: qml, + width: 500, + height: 100 + }); + window.setPosition(200, 50); + window.closed.connect(killWindow); + onScreen = true + button.editProperties({isActive: true}); + } + + function killWindow() { + if (window !== undefined) { + window.closed.disconnect(killWindow); + window.close() + window = undefined + } + onScreen = false + button.editProperties({isActive: false}) + } + }()); + \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineProfiler.qml b/scripts/developer/utilities/render/engineProfiler.qml new file mode 100644 index 0000000000..bfa049d089 --- /dev/null +++ b/scripts/developer/utilities/render/engineProfiler.qml @@ -0,0 +1,31 @@ +// +// EngineProfiler.qml +// +// Created by Sam Gateau on 06/07/2018 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +import "qrc:///qml/styles-uit" +import "qrc:///qml/controls-uit" as HifiControls + +import "../lib/jet/qml" as Jet + +Item { + HifiConstants { id: hifi;} + id: root; + anchors.fill: parent + + property var rootConfig: Render.getConfig("") + + + Jet.TaskTimeFrameView { + rootConfig: root.rootConfig + anchors.fill: root + } +} \ No newline at end of file diff --git a/scripts/developer/utilities/render/luci.js b/scripts/developer/utilities/render/luci.js index 005d96780a..9f0f32ee41 100644 --- a/scripts/developer/utilities/render/luci.js +++ b/scripts/developer/utilities/render/luci.js @@ -90,19 +90,22 @@ function fromQml(message) { switch (message.method) { - case "openEngineView": - openEngineTaskView(); + case "openEngineInspector": + openEngineInspector(); + break; + case "openEngineProfiler": + openEngineProfiler(); break; } } var engineInspectorView = null - function openEngineTaskView() { + function openEngineInspector() { if (engineInspectorView == null) { var qml = Script.resolvePath('engineInspector.qml'); var window = new OverlayWindow({ - title: 'Render Engine', + title: 'Render Engine Inspector', source: qml, width: 300, height: 400 @@ -115,7 +118,23 @@ } } - + var engineProfilerView = null + function openEngineProfiler() { + if (engineProfilerView == null) { + var qml = Script.resolvePath('engineProfiler.qml'); + var window = new OverlayWindow({ + title: 'Render Engine Profiler', + source: qml, + width: 300, + height: 400 + }); + window.setPosition(200, 50); + engineProfilerView = window + window.closed.connect(function() { engineProfilerView = null; }); + } else { + engineProfilerView.setPosition(200, 50); + } + } Script.scriptEnding.connect(function () { if (onLuciScreen) { @@ -128,5 +147,8 @@ if (engineInspectorView !== null) { engineInspectorView.close() } + if (engineProfilerView !== null) { + engineProfilerView.close() + } }); }()); \ No newline at end of file From 66199e9aab72362238647ad57fa089d5d8c4064d Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 11 Jul 2018 11:57:18 +0200 Subject: [PATCH 08/20] Cleaning up the isENabled interface andthe qml --- libraries/render-utils/src/BloomEffect.cpp | 3 ++- .../render-utils/src/RenderShadowTask.cpp | 2 +- libraries/render/src/render/DrawSceneOctree.h | 2 -- libraries/render/src/render/DrawStatus.cpp | 2 +- libraries/task/src/task/Config.cpp | 14 ++++++++++++ libraries/task/src/task/Config.h | 22 +++++++++++-------- libraries/task/src/task/Task.h | 2 +- .../utilities/lib/jet/qml/TaskListView.qml | 10 ++++----- .../lib/jet/qml/TaskTimeFrameView.qml | 5 +++-- .../utilities/render/engineInspector.js | 10 ++++----- .../utilities/render/engineInspector.qml | 2 +- .../utilities/render/engineProfiler.js | 6 ++--- 12 files changed, 49 insertions(+), 31 deletions(-) diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index ee06e17578..b198442b15 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -333,7 +333,8 @@ void Bloom::configure(const Config& config) { for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) { blurName.back() = '0' + i; auto blurConfig = config.getConfig(blurName); - blurConfig->setProperty("filterScale", 1.0f); + blurConfig->filterScale = 1.0f; + //blurConfig->setProperty("filterScale", 1.0f); } } diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 91eb777199..d9ae0caade 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -282,7 +282,7 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende } void RenderShadowTask::configure(const Config& configuration) { - DependencyManager::get()->setShadowMapEnabled(configuration.enabled); + DependencyManager::get()->setShadowMapEnabled(configuration.isEnabled()); // This is a task, so must still propogate configure() to its Jobs // Task::configure(configuration); } diff --git a/libraries/render/src/render/DrawSceneOctree.h b/libraries/render/src/render/DrawSceneOctree.h index 9c416262ca..97cf45ebcf 100644 --- a/libraries/render/src/render/DrawSceneOctree.h +++ b/libraries/render/src/render/DrawSceneOctree.h @@ -20,7 +20,6 @@ namespace render { class DrawSceneOctreeConfig : public Job::Config { Q_OBJECT - Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty()) Q_PROPERTY(bool showVisibleCells READ getShowVisibleCells WRITE setShowVisibleCells NOTIFY dirty()) Q_PROPERTY(bool showEmptyCells READ getShowEmptyCells WRITE setShowEmptyCells NOTIFY dirty()) Q_PROPERTY(int numAllocatedCells READ getNumAllocatedCells) @@ -82,7 +81,6 @@ namespace render { class DrawItemSelectionConfig : public Job::Config { Q_OBJECT - Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty()) Q_PROPERTY(bool showInsideItems READ getShowInsideItems WRITE setShowInsideItems NOTIFY dirty()) Q_PROPERTY(bool showInsideSubcellItems READ getShowInsideSubcellItems WRITE setShowInsideSubcellItems NOTIFY dirty()) Q_PROPERTY(bool showPartialItems READ getShowPartialItems WRITE setShowPartialItems NOTIFY dirty()) diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index 496b2000a9..b1e7620b19 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -29,7 +29,7 @@ using namespace render; void DrawStatusConfig::dirtyHelper() { - enabled = showNetwork || showDisplay; + _isEnabled = showNetwork || showDisplay; emit dirty(); } diff --git a/libraries/task/src/task/Config.cpp b/libraries/task/src/task/Config.cpp index ac7105be29..c0e9c41468 100644 --- a/libraries/task/src/task/Config.cpp +++ b/libraries/task/src/task/Config.cpp @@ -18,6 +18,17 @@ using namespace task; +JobConfig::~JobConfig() { + +} + +void JobConfig::setEnabled(bool enable) { + if (_isEnabled != enable) { + _isEnabled = enable; + emit dirtyEnabled(); + } +} + void JobConfig::setPresetList(const QJsonObject& object) { for (auto it = object.begin(); it != object.end(); it++) { JobConfig* child = findChild(it.key(), Qt::FindDirectChildrenOnly); @@ -30,6 +41,7 @@ void JobConfig::setPresetList(const QJsonObject& object) { void TaskConfig::connectChildConfig(QConfigPointer childConfig, const std::string& name) { childConfig->setParent(this); childConfig->setObjectName(name.c_str()); + // childConfig->propagateParentEnabled((_isParentEnabled ? _isEnabled : false)); // Connect loaded->refresh QObject::connect(childConfig.get(), SIGNAL(loaded()), this, SLOT(refresh())); @@ -57,6 +69,8 @@ void TaskConfig::transferChildrenConfigs(QConfigPointer source) { QObject::connect(child, SIGNAL(dirtyEnabled()), this, SLOT(refresh())); } } + + // propagateParentEnabledToSubs(); } void TaskConfig::refresh() { diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index b76c57521f..ab3303110b 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -50,12 +50,10 @@ public: _default = toJsonValue(*this).toObject().toVariantMap(); _presets.unite(list.toVariantMap()); - if (C::enabled) { + if (C::isEnabled()) { _presets.insert(DEFAULT, _default); } - if (false) { //!C::alwaysEnabled) { - _presets.insert(NONE, QVariantMap{{ "enabled", false }}); - } + _presets.insert(NONE, QVariantMap{{ "enabled", false }}); auto preset = _preset.get(); if (preset != _preset.getDefault() && _presets.contains(preset)) { @@ -92,16 +90,21 @@ class JobConfig : public QObject { Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY dirtyEnabled()) double _msCPURunTime{ 0.0 }; + +protected: + friend class TaskConfig; + + bool _isEnabled{ true }; + public: using Persistent = PersistentConfig; JobConfig() = default; - JobConfig(bool enabled): enabled{ enabled } {} + JobConfig(bool enabled): _isEnabled{ enabled } {} + ~JobConfig(); - bool isEnabled() { return /*alwaysEnabled ||*/ enabled; } - void setEnabled(bool enable) { enabled = /*alwaysEnabled ||*/ enable; emit dirtyEnabled(); } - - bool enabled{ true }; + bool isEnabled() const { return _isEnabled; } + void setEnabled(bool enable); virtual void setPresetList(const QJsonObject& object); @@ -199,6 +202,7 @@ public: */ class TaskConfig : public JobConfig { Q_OBJECT + public: using Persistent = PersistentConfig; diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index c15c0ceb13..8d2fd867c4 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -339,7 +339,7 @@ public: void run(const ContextPointer& jobContext) override { auto config = std::static_pointer_cast(Concept::_config); - if (config->enabled) { + if (config->isEnabled()) { for (auto job : TaskConcept::_jobs) { job.run(jobContext); if (jobContext->taskFlow.doAbortTask()) { diff --git a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml index 1229ef7dc7..02225aba62 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml @@ -19,7 +19,7 @@ import "../jet.js" as Jet Rectangle { HifiConstants { id: hifi;} - // color: hifi.colors.baseGray; + color: Qt.rgba(hifi.colors.baseGray.r, hifi.colors.baseGray.g, hifi.colors.baseGray.b, 0.8); id: root; property var rootConfig : Workload @@ -82,8 +82,8 @@ Rectangle { id: objCheck property var config: root.rootConfig.getConfig(model.path + "." + model.name); text: " " - checked: config.enabled - onCheckedChanged: { config.enabled = checked } + checked: root.rootConfig.getConfig(model.path + "." + model.name).enabled + onCheckedChanged: { root.rootConfig.getConfig(model.path + "." + model.name).enabled = checked } } MouseArea { @@ -95,12 +95,12 @@ Rectangle { HifiControls.Label { id: objLabel - colorScheme: hifi.colorSchemes.dark // property var config: root.rootConfig.getConfig(model.path + "." + model.name); + colorScheme: (root.rootConfig.getConfig(model.path + "." + model.name) ? hifi.colorSchemes.dark : hifi.colorSchemes.light) text: (objRecursiveColumn.children.length > 2 ? objRecursiveColumn.children[1].visible ? qsTr("- ") : qsTr("+ ") : qsTr(" ")) + model.name - + " ms=" + root.rootConfig.getConfig(model.path + "." + model.name).cpuRunTime.toFixed(3) + // + " ms=" + config.cpuRunTime.toFixed(3) + " id=" + model.id } } diff --git a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml index 267344fca5..e1d9bd7ce1 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml @@ -19,7 +19,7 @@ import "../jet.js" as Jet Rectangle { HifiConstants { id: hifi;} - // color: hifi.colors.baseGray; + color: Qt.rgba(hifi.colors.baseGray.r, hifi.colors.baseGray.g, hifi.colors.baseGray.b, 0.8); id: root; property var rootConfig : Workload @@ -59,7 +59,8 @@ Rectangle { function pullFreshValues() { for (var j = 0; j Date: Fri, 13 Jul 2018 13:12:06 +0200 Subject: [PATCH 09/20] typo --- libraries/gpu/src/gpu/Buffer.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libraries/gpu/src/gpu/Buffer.cpp b/libraries/gpu/src/gpu/Buffer.cpp index d085b4df76..b3716c3490 100644 --- a/libraries/gpu/src/gpu/Buffer.cpp +++ b/libraries/gpu/src/gpu/Buffer.cpp @@ -163,13 +163,6 @@ Buffer::Size Buffer::getSize() const { const Element BufferView::DEFAULT_ELEMENT = Element( gpu::SCALAR, gpu::UINT8, gpu::RAW ); - -BufferPointer _buffer; -Size _offset{ 0 }; -Size _size{ 0 }; -Element _element{ DEFAULT_ELEMENT }; -uint16 _stride{ 0 }; - BufferView::BufferView(const BufferView& view) : _buffer(view._buffer), _offset(view._offset), From c24083c1f0c981458552c84ff3fe04d3de0c9720 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 25 Jul 2018 10:50:15 +0200 Subject: [PATCH 10/20] drafting along the RenderTHread class --- interface/src/Application.cpp | 67 ++++++----- interface/src/Application.h | 2 +- interface/src/graphics/GraphicsEngine.cpp | 38 +++++- interface/src/graphics/GraphicsEngine.h | 6 + interface/src/graphics/RenderEventHandler.cpp | 5 +- interface/src/graphics/RenderEventHandler.h | 5 +- interface/src/graphics/RenderThread.cpp | 1 + interface/src/graphics/RenderThread.h | 108 ++++++++++++++++++ 8 files changed, 187 insertions(+), 45 deletions(-) create mode 100644 interface/src/graphics/RenderThread.cpp create mode 100644 interface/src/graphics/RenderThread.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0ad27e0dd3..24dcf4ce72 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2425,6 +2425,7 @@ void Application::cleanupBeforeQuit() { } _window->saveGeometry(); + // _gpuContext->shutdown(); // Destroy third party processes after scripts have finished using them. @@ -4178,41 +4179,37 @@ bool Application::acceptSnapshot(const QString& urlString) { } return true; } - -static uint32_t _renderedFrameIndex { INVALID_FRAME }; - -bool Application::shouldPaint() const { - if (_aboutToQuit || _window->isMinimized()) { - return false; - } - - - auto displayPlugin = getActiveDisplayPlugin(); - -#ifdef DEBUG_PAINT_DELAY - static uint64_t paintDelaySamples{ 0 }; - static uint64_t paintDelayUsecs{ 0 }; - - paintDelayUsecs += displayPlugin->getPaintDelayUsecs(); - - static const int PAINT_DELAY_THROTTLE = 1000; - if (++paintDelaySamples % PAINT_DELAY_THROTTLE == 0) { - qCDebug(interfaceapp).nospace() << - "Paint delay (" << paintDelaySamples << " samples): " << - (float)paintDelaySamples / paintDelayUsecs << "us"; - } -#endif - - // Throttle if requested - //if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { - if (displayPlugin->isThrottled() && !_graphicsEngine.shouldPaint()) { - return false; - } - - // Sync up the _renderedFrameIndex - _renderedFrameIndex = displayPlugin->presentCount(); - return true; -} +// +//bool Application::shouldPaint() const { +// if (_aboutToQuit || _window->isMinimized()) { +// return false; +// } +// +// +// auto displayPlugin = getActiveDisplayPlugin(); +// +//#ifdef DEBUG_PAINT_DELAY +// static uint64_t paintDelaySamples{ 0 }; +// static uint64_t paintDelayUsecs{ 0 }; +// +// paintDelayUsecs += displayPlugin->getPaintDelayUsecs(); +// +// static const int PAINT_DELAY_THROTTLE = 1000; +// if (++paintDelaySamples % PAINT_DELAY_THROTTLE == 0) { +// qCDebug(interfaceapp).nospace() << +// "Paint delay (" << paintDelaySamples << " samples): " << +// (float)paintDelaySamples / paintDelayUsecs << "us"; +// } +//#endif +// +// // Throttle if requested +// //if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { +// if (displayPlugin->isThrottled() && !_graphicsEngine.shouldPaint()) { +// return false; +// } +// +// return true; +//} #ifdef Q_OS_WIN #include diff --git a/interface/src/Application.h b/interface/src/Application.h index fb8edf3b86..6d57ca9d8d 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -157,7 +157,7 @@ public: void updateSecondaryCameraViewFrustum(); void updateCamera(RenderArgs& renderArgs, float deltaTime); - bool shouldPaint() const; + // bool shouldPaint() const; // void paintGL(); void resizeGL(); diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index 21c9a9b22d..d115d8914c 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -53,6 +53,7 @@ void GraphicsEngine::initializeGPU(GLWidget* glwidget) { _renderEventHandler = new RenderEventHandler( glwidget->qglContext(), + [this]() { return this->shouldPaint(); }, [this]() { this->render_performFrame(); } ); @@ -147,12 +148,37 @@ 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; - } - - return true; + +// if (_aboutToQuit || _window->isMinimized()) { +// return false; + // } + + + auto displayPlugin = qApp->getActiveDisplayPlugin(); + +#ifdef DEBUG_PAINT_DELAY + static uint64_t paintDelaySamples{ 0 }; + static uint64_t paintDelayUsecs{ 0 }; + + paintDelayUsecs += displayPlugin->getPaintDelayUsecs(); + + static const int PAINT_DELAY_THROTTLE = 1000; + if (++paintDelaySamples % PAINT_DELAY_THROTTLE == 0) { + qCDebug(interfaceapp).nospace() << + "Paint delay (" << paintDelaySamples << " samples): " << + (float)paintDelaySamples / paintDelayUsecs << "us"; + } +#endif + + // Throttle if requested + //if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { + if ( displayPlugin->isThrottled() && + (static_cast(_renderEventHandler)->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { + return false; + } + + return true; + // } } bool GraphicsEngine::checkPendingRenderEvent() { diff --git a/interface/src/graphics/GraphicsEngine.h b/interface/src/graphics/GraphicsEngine.h index 780b4020d2..bc2121429a 100644 --- a/interface/src/graphics/GraphicsEngine.h +++ b/interface/src/graphics/GraphicsEngine.h @@ -16,6 +16,8 @@ #include +#include "RenderThread.h" + #include #include @@ -51,6 +53,8 @@ public: render::EnginePointer getRenderEngine() const { return _renderEngine; } gpu::ContextPointer getGPUContext() const { return _gpuContext; } + FrameQueuePointer getFrameQueue() const { return _frameQueue; } + // Same as the one in application bool shouldPaint() const; bool checkPendingRenderEvent(); @@ -79,6 +83,8 @@ protected: gpu::ContextPointer _gpuContext; // initialized during window creation + FrameQueuePointer _frameQueue{ new FrameQueue() }; + QObject* _renderEventHandler{ nullptr }; friend class RenderEventHandler; diff --git a/interface/src/graphics/RenderEventHandler.cpp b/interface/src/graphics/RenderEventHandler.cpp index 95e931ebd8..5b587ab171 100644 --- a/interface/src/graphics/RenderEventHandler.cpp +++ b/interface/src/graphics/RenderEventHandler.cpp @@ -15,7 +15,8 @@ #include "CrashHandler.h" -RenderEventHandler::RenderEventHandler(QOpenGLContext* context, RenderCall renderCall) : +RenderEventHandler::RenderEventHandler(QOpenGLContext* context, CheckCall checkCall, RenderCall renderCall) : + _checkCall(checkCall), _renderCall(renderCall) { _renderContext = new OffscreenGLCanvas(); @@ -52,7 +53,7 @@ void RenderEventHandler::resumeThread() { } void RenderEventHandler::render() { - if (qApp->shouldPaint()) { + if (_checkCall()) { _lastTimeRendered.start(); _renderCall(); } diff --git a/interface/src/graphics/RenderEventHandler.h b/interface/src/graphics/RenderEventHandler.h index 913898eb7f..43b16a76bd 100644 --- a/interface/src/graphics/RenderEventHandler.h +++ b/interface/src/graphics/RenderEventHandler.h @@ -28,10 +28,13 @@ class RenderEventHandler : public QObject { Q_OBJECT public: + using CheckCall = std::function ; using RenderCall = std::function ; + + CheckCall _checkCall; RenderCall _renderCall; - RenderEventHandler(QOpenGLContext* context, RenderCall renderCall); + RenderEventHandler(QOpenGLContext* context, CheckCall checkCall, RenderCall renderCall); QElapsedTimer _lastTimeRendered; std::atomic _pendingRenderEvent{ true }; diff --git a/interface/src/graphics/RenderThread.cpp b/interface/src/graphics/RenderThread.cpp new file mode 100644 index 0000000000..63df2033e8 --- /dev/null +++ b/interface/src/graphics/RenderThread.cpp @@ -0,0 +1 @@ +#include "RenderThread.h" \ No newline at end of file diff --git a/interface/src/graphics/RenderThread.h b/interface/src/graphics/RenderThread.h new file mode 100644 index 0000000000..abddf746e6 --- /dev/null +++ b/interface/src/graphics/RenderThread.h @@ -0,0 +1,108 @@ +#ifndef PRODUCERCONSUMERPIPE_H +#define PRODUCERCONSUMERPIPE_H + +#include +#include +#include +#include +#include + +// Producer is blocked if the consumer doesn't consume enough +// Consumer reads same value if producer doesn't produce enough +template +class ProducerConsumerPipe { +public: + + ProducerConsumerPipe(); + ProducerConsumerPipe(const T& initValue); + + const T& read(); + void read(T& value, const T& resetValue); + void write(const T& value); + bool isWritePossible(); + +private: + + short _readIndex; + short _writeIndex; + std::array _values; + std::array _used; + + void initialize(); + void updateReadIndex(); +}; + +template +ProducerConsumerPipe::ProducerConsumerPipe() { + initialize(); +} + +template +ProducerConsumerPipe::ProducerConsumerPipe(const T& initValue) { + _values.fill(initValue); + initialize(); +} + +template +void ProducerConsumerPipe::initialize() { + _readIndex = 0; + _writeIndex = 2; + _used[_readIndex].test_and_set(std::memory_order_acquire); + _used[_writeIndex].test_and_set(std::memory_order_acquire); + _used[1].clear(); +} + +template +void ProducerConsumerPipe::updateReadIndex() { + int nextReadIndex = (_readIndex + 1) % _values.size(); + + if (!_used[nextReadIndex].test_and_set(std::memory_order_acquire)) { + int readIndex = _readIndex; + _used[readIndex].clear(std::memory_order_release); + _readIndex = nextReadIndex; + } +} + +template +const T& ProducerConsumerPipe::read() { + updateReadIndex(); + return _values[_readIndex]; +} + +template +void ProducerConsumerPipe::read(T& value, const T& resetValue) { + updateReadIndex(); + value = _values[_readIndex]; + _values[_readIndex] = resetValue; +} + +template +bool ProducerConsumerPipe::isWritePossible() { + int nextWriteIndex = (_writeIndex + 1) % _values.size(); + return (_used[nextWriteIndex].test_and_set(std::memory_order_acquire)); +} + +template +void ProducerConsumerPipe::write(const T& value) { + int nextWriteIndex = (_writeIndex + 1) % _values.size(); + int writeIndex = _writeIndex; + + _values[writeIndex] = value; + + while (_used[nextWriteIndex].test_and_set(std::memory_order_acquire)) { + // spin + std::this_thread::yield(); + } + _used[writeIndex].clear(std::memory_order_release); + _writeIndex = nextWriteIndex; +} + + +#include + +using FrameQueue = ProducerConsumerPipe; + +using FrameQueuePointer = std::shared_ptr; + + +#endif From c0bbe1599b2cd5fc1eda5af267dc4414e277089d Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 30 Jul 2018 11:28:56 +0200 Subject: [PATCH 11/20] Trying to sync the thotling for all render threads --- .../Basic2DWindowOpenGLDisplayPlugin.cpp | 6 +++--- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 11 ++++++++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index d8b8cbd54a..7e95727fcc 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -165,11 +165,11 @@ static const uint32_t MIN_THROTTLE_CHECK_FRAMES = 60; bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const { static auto lastCheck = presentCount(); // Don't access the menu API every single frame - if ((presentCount() - lastCheck) > MIN_THROTTLE_CHECK_FRAMES) { + // if ((presentCount() - lastCheck) > MIN_THROTTLE_CHECK_FRAMES) { static const QString ThrottleFPSIfNotFocus = "Throttle FPS If Not Focus"; // FIXME - this value duplicated in Menu.h _isThrottled = (!_container->isForeground() && _container->isOptionChecked(ThrottleFPSIfNotFocus)); - lastCheck = presentCount(); - } + // lastCheck = presentCount(); + // } return _isThrottled; } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 9200843cf8..b18f9f988b 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -198,7 +198,16 @@ public: // If there's no active plugin, just sleep if (currentPlugin == nullptr) { // Minimum sleep ends up being about 2 ms anyway - QThread::msleep(1); + QThread::msleep(16); + continue; + } + + static uint _vsyncLoopIndex = 0; + _vsyncLoopIndex++; + + if (currentPlugin->isThrottled() && (_vsyncLoopIndex % 8)) { + // Minimum sleep ends up being about 2 ms anyway + QThread::msleep(16); continue; } From 837b321004e0901330c5f131753911f67b734495 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sat, 17 Nov 2018 10:35:05 -0800 Subject: [PATCH 12/20] merging with master --- interface/src/graphics/RenderEventHandler.cpp | 2 +- libraries/render-utils/src/AmbientOcclusionEffect.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/graphics/RenderEventHandler.cpp b/interface/src/graphics/RenderEventHandler.cpp index 3ac48b894d..42af3bb9c0 100644 --- a/interface/src/graphics/RenderEventHandler.cpp +++ b/interface/src/graphics/RenderEventHandler.cpp @@ -25,7 +25,7 @@ RenderEventHandler::RenderEventHandler(CheckCall checkCall, RenderCall renderCal // Transfer to a new thread moveToNewNamedThread(this, "RenderThread", [this](QThread* renderThread) { hifi::qt::addBlockingForbiddenThread("Render", renderThread); - _renderContext->moveToThreadWithContext(renderThread); + //_renderContext->moveToThreadWithContext(renderThread); _lastTimeRendered.start(); }, std::bind(&RenderEventHandler::initialize, this), QThread::HighestPriority); } diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 864aef09e4..af6f6b21a3 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -78,7 +78,6 @@ using AmbientOcclusionFramebufferPointer = std::shared_ptr Date: Tue, 20 Nov 2018 17:32:04 -0800 Subject: [PATCH 13/20] Getting ready for merge --- interface/src/Application.cpp | 39 +---- interface/src/Application.h | 18 -- interface/src/graphics/GraphicsEngine.cpp | 31 +--- interface/src/graphics/GraphicsEngine.h | 6 - interface/src/graphics/RenderEventHandler.cpp | 4 - interface/src/graphics/RenderThread.cpp | 1 - interface/src/graphics/RenderThread.h | 108 ------------ interface/src/ui/ApplicationOverlay.cpp | 2 - .../utilities/render/GlobalLighting.js | 155 ------------------ .../utilities/render/engineInspector.js | 71 -------- .../utilities/render/engineInspector.qml | 30 ---- .../utilities/render/engineProfiler.js | 59 ------- .../utilities/render/engineProfiler.qml | 31 ---- 13 files changed, 10 insertions(+), 545 deletions(-) delete mode 100644 interface/src/graphics/RenderThread.cpp delete mode 100644 interface/src/graphics/RenderThread.h delete mode 100644 scripts/developer/utilities/render/GlobalLighting.js delete mode 100644 scripts/developer/utilities/render/engineInspector.js delete mode 100644 scripts/developer/utilities/render/engineInspector.qml delete mode 100644 scripts/developer/utilities/render/engineProfiler.js delete mode 100644 scripts/developer/utilities/render/engineProfiler.qml diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f4bd15403e..dae9e3dad2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -87,7 +87,6 @@ #include #include #include -//#include #include #include #include @@ -2313,7 +2312,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->createKeyboard(); _pendingIdleEvent = false; - // _pendingRenderEvent = false; _graphicsEngine.startup(); qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID()); @@ -2578,11 +2576,6 @@ void Application::cleanupBeforeQuit() { // Cleanup all overlays after the scripts, as scripts might add more _overlays.cleanupAllOverlays(); - // 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 - // _main3DScene->enqueueFrame(); // flush all the transactions - // _main3DScene->processTransactionQueue(); // process and apply deletions // first stop all timers directly or by invokeMethod // depending on what thread they run in @@ -2598,8 +2591,6 @@ void Application::cleanupBeforeQuit() { _window->saveGeometry(); - // _gpuContext->shutdown(); - // Destroy third party processes after scripts have finished using them. #ifdef HAVE_DDE DependencyManager::destroy(); @@ -2655,9 +2646,7 @@ Application::~Application() { _shapeManager.collectGarbage(); assert(_shapeManager.getNumShapes() == 0); - // shutdown render engine - //_main3DScene = nullptr; - //_renderEngine = nullptr; + // shutdown graphics engine _graphicsEngine.shutdown(); _gameWorkload.shutdown(); @@ -2717,9 +2706,6 @@ Application::~Application() { // Can't log to file passed this point, FileLogger about to be deleted qInstallMessageHandler(LogHandler::verboseMessageHandler); - - -// _renderEventHandler->deleteLater(); } void Application::initializeGL() { @@ -4681,19 +4667,6 @@ void Application::idle() { PROFILE_COUNTER_IF_CHANGED(app, "pendingProcessing", int, DependencyManager::get()->getStat("PendingProcessing").toInt()); auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration(); PROFILE_COUNTER_IF_CHANGED(render, "gpuTime", float, (float)_graphicsEngine.getGPUContext()->getFrameTimerGPUAverage()); -/* auto opaqueRangeTimer = renderConfig->getConfig("OpaqueRangeTimer"); - auto linearDepth = renderConfig->getConfig("LinearDepth"); - auto surfaceGeometry = renderConfig->getConfig("SurfaceGeometry"); - auto renderDeferred = renderConfig->getConfig("RenderDeferred"); - auto toneAndPostRangeTimer = renderConfig->getConfig("ToneAndPostRangeTimer"); - - PROFILE_COUNTER(render_detail, "gpuTimes", { - { "OpaqueRangeTimer", opaqueRangeTimer ? opaqueRangeTimer->property("gpuRunTime") : 0 }, - { "LinearDepth", linearDepth ? linearDepth->property("gpuRunTime") : 0 }, - { "SurfaceGeometry", surfaceGeometry ? surfaceGeometry->property("gpuRunTime") : 0 }, - { "RenderDeferred", renderDeferred ? renderDeferred->property("gpuRunTime") : 0 }, - { "ToneAndPostRangeTimer", toneAndPostRangeTimer ? toneAndPostRangeTimer->property("gpuRunTime") : 0 } - });*/ PROFILE_RANGE(app, __FUNCTION__); @@ -5062,9 +5035,6 @@ QVector Application::pasteEntities(float x, float y, float z) { void Application::init() { // Make sure Login state is up to date DependencyManager::get()->toggleLoginDialog(); -// if (!DISABLE_DEFERRED) { - // DependencyManager::get()->init(); - // } DependencyManager::get()->init(); _timerStart.start(); @@ -6129,13 +6099,6 @@ void Application::update(float deltaTime) { updateRenderArgs(deltaTime); - // 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); - - { PerformanceTimer perfTimer("AnimDebugDraw"); AnimDebugDraw::getInstance().update(); diff --git a/interface/src/Application.h b/interface/src/Application.h index b5ce040c94..2f23fc72d7 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -153,8 +153,6 @@ public: void updateSecondaryCameraViewFrustum(); void updateCamera(RenderArgs& renderArgs, float deltaTime); - // bool shouldPaint() const; -// void paintGL(); void resizeGL(); bool event(QEvent* event) override; @@ -276,11 +274,6 @@ public: void setMaxOctreePacketsPerSecond(int maxOctreePPS); int getMaxOctreePacketsPerSecond() const; -/* render::ScenePointer getMain3DScene() override { return _main3DScene; } - const render::ScenePointer& getMain3DScene() const { return _main3DScene; } - render::EnginePointer getRenderEngine() override { return _renderEngine; } - 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(); } @@ -541,8 +534,6 @@ private: void initializeAcceptedFiles(); - // void runRenderFrame(RenderArgs* renderArgs/*, Camera& whichCamera, bool selfAvatarOnly = false*/); - bool importJSONFromURL(const QString& urlString); bool importSVOFromURL(const QString& urlString); bool importFromZIP(const QString& filePath); @@ -598,7 +589,6 @@ private: QTimer _minimizedWindowTimer; QElapsedTimer _timerStart; QElapsedTimer _lastTimeUpdated; - // QElapsedTimer _lastTimeRendered; int _minimumGPUTextureMemSizeStabilityCount { 30 }; @@ -684,10 +674,6 @@ private: quint64 _lastFaceTrackerUpdate; - // render::ScenePointer _main3DScene{ 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 - GameWorkload _gameWorkload; GraphicsEngine _graphicsEngine; @@ -769,12 +755,8 @@ private: QUrl _avatarOverrideUrl; bool _saveAvatarOverrideUrl { false }; - // QObject* _renderEventHandler{ nullptr }; - - // friend class RenderEventHandler; std::atomic _pendingIdleEvent { true }; - // std::atomic _pendingRenderEvent { true }; bool quitWhenFinished { false }; diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index 55be37ba60..aecaa74d12 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -127,12 +127,7 @@ static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SI bool GraphicsEngine::shouldPaint() const { -// if (_aboutToQuit || _window->isMinimized()) { -// return false; - // } - - - auto displayPlugin = qApp->getActiveDisplayPlugin(); + auto displayPlugin = qApp->getActiveDisplayPlugin(); #ifdef DEBUG_PAINT_DELAY static uint64_t paintDelaySamples{ 0 }; @@ -148,15 +143,14 @@ bool GraphicsEngine::shouldPaint() const { } #endif - // Throttle if requested - //if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { - if ( displayPlugin->isThrottled() && - (static_cast(_renderEventHandler)->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { - return false; - } + // Throttle if requested + //if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { + if ( displayPlugin->isThrottled() && + (static_cast(_renderEventHandler)->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { + return false; + } - return true; - // } + return true; } bool GraphicsEngine::checkPendingRenderEvent() { @@ -170,17 +164,11 @@ 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"); @@ -310,5 +298,4 @@ void GraphicsEngine::render_performFrame() { 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 6efddce51a..490f5312b5 100644 --- a/interface/src/graphics/GraphicsEngine.h +++ b/interface/src/graphics/GraphicsEngine.h @@ -16,8 +16,6 @@ #include -#include "RenderThread.h" - #include #include @@ -53,8 +51,6 @@ public: render::EnginePointer getRenderEngine() const { return _renderEngine; } gpu::ContextPointer getGPUContext() const { return _gpuContext; } - FrameQueuePointer getFrameQueue() const { return _frameQueue; } - // Same as the one in application bool shouldPaint() const; bool checkPendingRenderEvent(); @@ -83,8 +79,6 @@ protected: gpu::ContextPointer _gpuContext; // initialized during window creation - FrameQueuePointer _frameQueue{ new FrameQueue() }; - QObject* _renderEventHandler{ nullptr }; friend class RenderEventHandler; diff --git a/interface/src/graphics/RenderEventHandler.cpp b/interface/src/graphics/RenderEventHandler.cpp index 42af3bb9c0..bdb2cae060 100644 --- a/interface/src/graphics/RenderEventHandler.cpp +++ b/interface/src/graphics/RenderEventHandler.cpp @@ -19,13 +19,9 @@ RenderEventHandler::RenderEventHandler(CheckCall checkCall, RenderCall renderCal _checkCall(checkCall), _renderCall(renderCall) { - // 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); } diff --git a/interface/src/graphics/RenderThread.cpp b/interface/src/graphics/RenderThread.cpp deleted file mode 100644 index 63df2033e8..0000000000 --- a/interface/src/graphics/RenderThread.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "RenderThread.h" \ No newline at end of file diff --git a/interface/src/graphics/RenderThread.h b/interface/src/graphics/RenderThread.h deleted file mode 100644 index abddf746e6..0000000000 --- a/interface/src/graphics/RenderThread.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef PRODUCERCONSUMERPIPE_H -#define PRODUCERCONSUMERPIPE_H - -#include -#include -#include -#include -#include - -// Producer is blocked if the consumer doesn't consume enough -// Consumer reads same value if producer doesn't produce enough -template -class ProducerConsumerPipe { -public: - - ProducerConsumerPipe(); - ProducerConsumerPipe(const T& initValue); - - const T& read(); - void read(T& value, const T& resetValue); - void write(const T& value); - bool isWritePossible(); - -private: - - short _readIndex; - short _writeIndex; - std::array _values; - std::array _used; - - void initialize(); - void updateReadIndex(); -}; - -template -ProducerConsumerPipe::ProducerConsumerPipe() { - initialize(); -} - -template -ProducerConsumerPipe::ProducerConsumerPipe(const T& initValue) { - _values.fill(initValue); - initialize(); -} - -template -void ProducerConsumerPipe::initialize() { - _readIndex = 0; - _writeIndex = 2; - _used[_readIndex].test_and_set(std::memory_order_acquire); - _used[_writeIndex].test_and_set(std::memory_order_acquire); - _used[1].clear(); -} - -template -void ProducerConsumerPipe::updateReadIndex() { - int nextReadIndex = (_readIndex + 1) % _values.size(); - - if (!_used[nextReadIndex].test_and_set(std::memory_order_acquire)) { - int readIndex = _readIndex; - _used[readIndex].clear(std::memory_order_release); - _readIndex = nextReadIndex; - } -} - -template -const T& ProducerConsumerPipe::read() { - updateReadIndex(); - return _values[_readIndex]; -} - -template -void ProducerConsumerPipe::read(T& value, const T& resetValue) { - updateReadIndex(); - value = _values[_readIndex]; - _values[_readIndex] = resetValue; -} - -template -bool ProducerConsumerPipe::isWritePossible() { - int nextWriteIndex = (_writeIndex + 1) % _values.size(); - return (_used[nextWriteIndex].test_and_set(std::memory_order_acquire)); -} - -template -void ProducerConsumerPipe::write(const T& value) { - int nextWriteIndex = (_writeIndex + 1) % _values.size(); - int writeIndex = _writeIndex; - - _values[writeIndex] = value; - - while (_used[nextWriteIndex].test_and_set(std::memory_order_acquire)) { - // spin - std::this_thread::yield(); - } - _used[writeIndex].clear(std::memory_order_release); - _writeIndex = nextWriteIndex; -} - - -#include - -using FrameQueue = ProducerConsumerPipe; - -using FrameQueuePointer = std::shared_ptr; - - -#endif diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index aed54463ba..46cdbd5b3e 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -55,8 +55,6 @@ ApplicationOverlay::~ApplicationOverlay() { // Renders the overlays either to a texture or to the screen void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { PROFILE_RANGE(render, __FUNCTION__); -// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); - buildFramebufferObject(); if (!_overlayFramebuffer) { diff --git a/scripts/developer/utilities/render/GlobalLighting.js b/scripts/developer/utilities/render/GlobalLighting.js deleted file mode 100644 index 766b87314f..0000000000 --- a/scripts/developer/utilities/render/GlobalLighting.js +++ /dev/null @@ -1,155 +0,0 @@ -// -// Global lighting.js -// -// Sam Gateau, created on 6/7/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 -// -var createdOverlays = []; -var overlayFrames = {}; - -Script.scriptEnding.connect(function () { - for (var i = 0; i < createdOverlays.length; i++) { - Overlays.deleteOverlay(createdOverlays[i]); - } -}); - - -var DIM = {x: 0.1, y: 0.13, z: 0.1}; -var avatarHeadJoint = MyAvatar.getJointIndex("Head"); - -function createOrb(i) { - - var props = { - dimensions: DIM, - } - - props["url"] = "https://github.com/highfidelity/hifi_tests/blob/master/assets/models/material_matrix_models/fbx/blender/hifi_metallicV_albedoV_ao.fbx?raw=true" - props["position"] = getCamePos(i) - // props["localPosition"] = { x: 0.4 * i, y: 0, z: 0} - props["rotation"] = getCameOri() - - if (createdOverlays.length > 0) { - props["parentID"] = createdOverlays[0] - - } - - var oID = Overlays.addOverlay("model", props); - - /* { - position: getCamePos(), - // position: MyAvatar.getJointPosition(avatarHeadJoint), - // localPosition: {x: 0, y: 1, z: 0}, - // localRotation: {x: 0, y: 0, z: 0, w:1}, - url: "https://github.com/highfidelity/hifi_tests/blob/master/assets/models/material_matrix_models/fbx/blender/hifi_metallicV_albedoV_ao.fbx?raw=true", - dimensions: DIM, - // parentID: MyAvatar.SELF_ID, - // parentJointIndex: avatarHeadJoint, - })*/ - - overlayFrames[oID] = { position: getCamePos(), rotation: getCameOri() } - - // Overlays.editOverlay(oID, overlayFrames[oID]) - - props = Overlays.getProperties(oID, ["position", "rotation"]) - print("createOrb" + oID + JSON.stringify(props)) - - return oID; -} - - -function createSnap(i) { - - var props = { - // dimensions: DIM, - // url: "resource://spectatorCameraFrame", - emissive: true, - url: "https://hifi-public.s3.amazonaws.com/sam/2018-oct/code/PackagedApp/asset/CarrotHunt.png", - dimensions: DIM, - // parentID: MyAvatar.SELF_ID, - // parentJointIndex: avatarHeadJoint, - alpha: 1, - // localRotation: { w: 1, x: 0, y: 0, z: 0 }, - // localPosition: { x: 0, y: 0.0, z: -1.0 }, - dimensions: DIM - } - - // props["url"] = "https://github.com/highfidelity/hifi_tests/blob/master/assets/models/material_matrix_models/fbx/blender/hifi_metallicV_albedoV_ao.fbx?raw=true" - props["position"] = getCamePos(i) - // props["localPosition"] = { x: 0.4 * i, y: 0, z: 0} - props["rotation"] = getCameOri() - - if (createdOverlays.length > 0) { - props["parentID"] = createdOverlays[0] - - } - - var oID = Overlays.addOverlay("image3d", props); - - /* { - position: getCamePos(), - // position: MyAvatar.getJointPosition(avatarHeadJoint), - // localPosition: {x: 0, y: 1, z: 0}, - // localRotation: {x: 0, y: 0, z: 0, w:1}, - url: "https://github.com/highfidelity/hifi_tests/blob/master/assets/models/material_matrix_models/fbx/blender/hifi_metallicV_albedoV_ao.fbx?raw=true", - dimensions: DIM, - // parentID: MyAvatar.SELF_ID, - // parentJointIndex: avatarHeadJoint, - })*/ - - overlayFrames[oID] = { position: getCamePos(), rotation: getCameOri() } - - // Overlays.editOverlay(oID, overlayFrames[oID]) - - props = Overlays.getProperties(oID, ["position", "rotation"]) - print("createOrb" + oID + JSON.stringify(props)) - - return oID; -} - -function createOrbs() { - print("createOrbs") - - createdOverlays.push(createOrb(0)); - createdOverlays.push(createOrb(1)); - createdOverlays.push(createSnap(2)); - -} - -var camSpace = {} - -function updateCamSpace() { - camSpace["pos"] = Camera.Position; - camSpace["ori"] = Camera.orientation; - camSpace["X"] = Vec3.multiply(Quat.getRight(Camera.orientation), Camera.frustum.aspectRatio); - camSpace["Y"] = Quat.getUp(Camera.orientation); - camSpace["Z"] = Vec3.multiply(Quat.getForward(), -1); -} - -function getCamePos(i) { - - return Vec3.sum(Camera.position, Vec3.multiplyQbyV(Camera.orientation, { x: -0.5 + 0.2 * i, y: -0.3, z: -1 })) - // return Vec3.add(Camera.position, {x: i * 0.3, y:0, z:1} -} -function getCameOri() { - return Camera.orientation -} -function updateFrames() { - for (var i = 0; i < createdOverlays.length; i++) { - overlayFrames[createdOverlays[i]] = { position: getCamePos(i), rotation: getCameOri() } - } - Overlays.editOverlays(overlayFrames) - -} - - -createOrbs() - -var accumulated = 0; -Script.update.connect(function(deltaTime) { - accumulated += deltaTime; - if (accumulated > 1) - updateFrames() -}); \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineInspector.js b/scripts/developer/utilities/render/engineInspector.js deleted file mode 100644 index 74e4231ff1..0000000000 --- a/scripts/developer/utilities/render/engineInspector.js +++ /dev/null @@ -1,71 +0,0 @@ - /*function openEngineTaskView() { - // Set up the qml ui - var qml = Script.resolvePath('engineInspector.qml'); - var window = new OverlayWindow({ - title: 'Render Engine', - source: qml, - width: 500, - height: 100 - }); - window.setPosition(200, 50); - window.closed.connect(function() { Script.stop(); }); - } - openEngineTaskView();*/ - - (function() { - var TABLET_BUTTON_NAME = "Inspector"; - var QMLAPP_URL = Script.resolvePath("./engineInspector.qml"); - var ICON_URL = Script.resolvePath("../../../system/assets/images/luci-i.svg"); - var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/luci-a.svg"); - - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - var button = tablet.addButton({ - text: TABLET_BUTTON_NAME, - icon: ICON_URL, - activeIcon: ACTIVE_ICON_URL - }); - - Script.scriptEnding.connect(function () { - killWindow() - button.clicked.disconnect(onClicked); - tablet.removeButton(button); - }); - - button.clicked.connect(onClicked); - - var onScreen = false; - var window; - - function onClicked() { - if (onScreen) { - killWindow() - } else { - createWindow() - } - } - - function createWindow() { - var qml = Script.resolvePath(QMLAPP_URL); - window = new OverlayWindow({ - title: 'Render Engine Inspector', - source: qml, - width: 250, - height: 500 - }); - window.setPosition(200, 50); - window.closed.connect(killWindow); - onScreen = true - button.editProperties({isActive: true}); - } - - function killWindow() { - if (window !== undefined) { - window.closed.disconnect(killWindow); - window.close() - window = undefined - } - onScreen = false - button.editProperties({isActive: false}) - } - }()); - \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineInspector.qml b/scripts/developer/utilities/render/engineInspector.qml deleted file mode 100644 index 31283a4756..0000000000 --- a/scripts/developer/utilities/render/engineInspector.qml +++ /dev/null @@ -1,30 +0,0 @@ -// -// EngineInspector.qml -// -// Created by Sam Gateau on 06/07/2018 -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html -// -import QtQuick 2.7 -import QtQuick.Controls 1.4 -import QtQuick.Layouts 1.3 - -import stylesUit 1.0 -import controlsUit 1.0 as HifiControls - -import "../lib/jet/qml" as Jet - -Item { - HifiConstants { id: hifi;} - id: root; - anchors.fill: parent - - property var rootConfig: Render.getConfig("") - - Jet.TaskListView { - rootConfig: root.rootConfig - anchors.fill: root - } -} \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineProfiler.js b/scripts/developer/utilities/render/engineProfiler.js deleted file mode 100644 index 418cab8622..0000000000 --- a/scripts/developer/utilities/render/engineProfiler.js +++ /dev/null @@ -1,59 +0,0 @@ - - - (function() { - var TABLET_BUTTON_NAME = "Profiler"; - var QMLAPP_URL = Script.resolvePath("./engineProfiler.qml"); - var ICON_URL = Script.resolvePath("../../../system/assets/images/luci-i.svg"); - var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/luci-a.svg"); - - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - var button = tablet.addButton({ - text: TABLET_BUTTON_NAME, - icon: ICON_URL, - activeIcon: ACTIVE_ICON_URL - }); - - Script.scriptEnding.connect(function () { - killWindow() - button.clicked.disconnect(onClicked); - tablet.removeButton(button); - }); - - button.clicked.connect(onClicked); - - var onScreen = false; - var window; - - function onClicked() { - if (onScreen) { - killWindow() - } else { - createWindow() - } - } - - function createWindow() { - var qml = Script.resolvePath(QMLAPP_URL); - window = Desktop.createWindow(Script.resolvePath(QMLAPP_URL), { - title: 'Render Engine Profiler', - flags: Desktop.ALWAYS_ON_TOP, - presentationMode: Desktop.PresentationMode.NATIVE, - size: {x: 500, y: 100} - }); - window.setPosition(200, 50); - window.closed.connect(killWindow); - onScreen = true - button.editProperties({isActive: true}); - } - - function killWindow() { - if (window !== undefined) { - window.closed.disconnect(killWindow); - window.close() - window = undefined - } - onScreen = false - button.editProperties({isActive: false}) - } - }()); - \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineProfiler.qml b/scripts/developer/utilities/render/engineProfiler.qml deleted file mode 100644 index bfa049d089..0000000000 --- a/scripts/developer/utilities/render/engineProfiler.qml +++ /dev/null @@ -1,31 +0,0 @@ -// -// EngineProfiler.qml -// -// Created by Sam Gateau on 06/07/2018 -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html -// -import QtQuick 2.7 -import QtQuick.Controls 1.4 -import QtQuick.Layouts 1.3 - -import "qrc:///qml/styles-uit" -import "qrc:///qml/controls-uit" as HifiControls - -import "../lib/jet/qml" as Jet - -Item { - HifiConstants { id: hifi;} - id: root; - anchors.fill: parent - - property var rootConfig: Render.getConfig("") - - - Jet.TaskTimeFrameView { - rootConfig: root.rootConfig - anchors.fill: root - } -} \ No newline at end of file From f3bbd412d147719dc97f763657ab6e35f595680d Mon Sep 17 00:00:00 2001 From: sam gateau Date: Tue, 20 Nov 2018 17:40:59 -0800 Subject: [PATCH 14/20] Cleaning too many changes --- .../Basic2DWindowOpenGLDisplayPlugin.cpp | 6 +++--- .../display-plugins/OpenGLDisplayPlugin.cpp | 11 +---------- libraries/gpu/src/gpu/Buffer.cpp | 18 ------------------ libraries/gpu/src/gpu/Buffer.h | 4 ++-- 4 files changed, 6 insertions(+), 33 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 7e95727fcc..d8b8cbd54a 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -165,11 +165,11 @@ static const uint32_t MIN_THROTTLE_CHECK_FRAMES = 60; bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const { static auto lastCheck = presentCount(); // Don't access the menu API every single frame - // if ((presentCount() - lastCheck) > MIN_THROTTLE_CHECK_FRAMES) { + if ((presentCount() - lastCheck) > MIN_THROTTLE_CHECK_FRAMES) { static const QString ThrottleFPSIfNotFocus = "Throttle FPS If Not Focus"; // FIXME - this value duplicated in Menu.h _isThrottled = (!_container->isForeground() && _container->isOptionChecked(ThrottleFPSIfNotFocus)); - // lastCheck = presentCount(); - // } + lastCheck = presentCount(); + } return _isThrottled; } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 362952ddd7..190d4d4104 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -172,16 +172,7 @@ public: // If there's no active plugin, just sleep if (currentPlugin == nullptr) { // Minimum sleep ends up being about 2 ms anyway - QThread::msleep(16); - continue; - } - - static uint _vsyncLoopIndex = 0; - _vsyncLoopIndex++; - - if (currentPlugin->isThrottled() && (_vsyncLoopIndex % 8)) { - // Minimum sleep ends up being about 2 ms anyway - QThread::msleep(16); + QThread::msleep(1); continue; } diff --git a/libraries/gpu/src/gpu/Buffer.cpp b/libraries/gpu/src/gpu/Buffer.cpp index b3716c3490..ebb768e597 100644 --- a/libraries/gpu/src/gpu/Buffer.cpp +++ b/libraries/gpu/src/gpu/Buffer.cpp @@ -163,24 +163,6 @@ Buffer::Size Buffer::getSize() const { const Element BufferView::DEFAULT_ELEMENT = Element( gpu::SCALAR, gpu::UINT8, gpu::RAW ); -BufferView::BufferView(const BufferView& view) : - _buffer(view._buffer), - _offset(view._offset), - _size(view._size), - _element(view._element), - _stride(view._stride) -{} - -BufferView& BufferView::operator=(const BufferView& view) { - _buffer = (view._buffer); - _offset = (view._offset); - _size = (view._size); - _element = (view._element); - _stride = (view._stride); - - return (*this); -} - BufferView::BufferView() : BufferView(DEFAULT_ELEMENT) {} diff --git a/libraries/gpu/src/gpu/Buffer.h b/libraries/gpu/src/gpu/Buffer.h index e486e2392a..01cc652fd1 100644 --- a/libraries/gpu/src/gpu/Buffer.h +++ b/libraries/gpu/src/gpu/Buffer.h @@ -183,8 +183,8 @@ public: Element _element { DEFAULT_ELEMENT }; uint16 _stride { 0 }; - BufferView(const BufferView& view); - BufferView& operator=(const BufferView& view); + BufferView(const BufferView& view) = default; + BufferView& operator=(const BufferView& view) = default; BufferView(); BufferView(const Element& element); From 6b1c7bf96e3a67420c0c7929bf9d65691f5d696a Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 20 Nov 2018 23:15:09 -0800 Subject: [PATCH 15/20] restoring the engine render views and cleaning up the task / config section of the pr --- libraries/render-utils/src/BloomEffect.cpp | 1 - libraries/task/src/task/Config.cpp | 3 - libraries/task/src/task/Config.h | 2 +- libraries/task/src/task/Task.h | 2 +- scripts/developer/utilities/lib/jet/jet.js | 5 +- .../utilities/render/engineInspector.js | 71 +++++++++++++++++++ .../utilities/render/engineInspector.qml | 30 ++++++++ .../utilities/render/engineProfiler.js | 59 +++++++++++++++ .../utilities/render/engineProfiler.qml | 31 ++++++++ 9 files changed, 196 insertions(+), 8 deletions(-) create mode 100644 scripts/developer/utilities/render/engineInspector.js create mode 100644 scripts/developer/utilities/render/engineInspector.qml create mode 100644 scripts/developer/utilities/render/engineProfiler.js create mode 100644 scripts/developer/utilities/render/engineProfiler.qml diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index e5b32bb1d4..414a1c3f91 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -283,7 +283,6 @@ void BloomEffect::configure(const Config& config) { blurName.back() = '0' + i; auto blurConfig = config.getConfig(blurName); blurConfig->filterScale = 1.0f; - //blurConfig->setProperty("filterScale", 1.0f); } } diff --git a/libraries/task/src/task/Config.cpp b/libraries/task/src/task/Config.cpp index c0e9c41468..5e8e4b246d 100644 --- a/libraries/task/src/task/Config.cpp +++ b/libraries/task/src/task/Config.cpp @@ -41,7 +41,6 @@ void JobConfig::setPresetList(const QJsonObject& object) { void TaskConfig::connectChildConfig(QConfigPointer childConfig, const std::string& name) { childConfig->setParent(this); childConfig->setObjectName(name.c_str()); - // childConfig->propagateParentEnabled((_isParentEnabled ? _isEnabled : false)); // Connect loaded->refresh QObject::connect(childConfig.get(), SIGNAL(loaded()), this, SLOT(refresh())); @@ -69,8 +68,6 @@ void TaskConfig::transferChildrenConfigs(QConfigPointer source) { QObject::connect(child, SIGNAL(dirtyEnabled()), this, SLOT(refresh())); } } - - // propagateParentEnabledToSubs(); } void TaskConfig::refresh() { diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index ab3303110b..da9b95a274 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -125,7 +125,7 @@ public: // Running Time measurement // The new stats signal is emitted once per run time of a job when stats (cpu runtime) are updated - void setCPURunTime(const std::chrono::nanoseconds& runtime) { _msCPURunTime = std::chrono::duration(runtime).count(); /* emit newStats();*/ } + void setCPURunTime(const std::chrono::nanoseconds& runtime) { _msCPURunTime = std::chrono::duration(runtime).count(); emit newStats(); } double getCPURunTime() const { return _msCPURunTime; } // Describe the node graph data connections of the associated Job/Task diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index 0f4c67478e..fb7012b16c 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->isEnabled()) { jobRun(_data, jobContext, _input.get(), _output.edit()); } jobContext->jobConfig.reset(); diff --git a/scripts/developer/utilities/lib/jet/jet.js b/scripts/developer/utilities/lib/jet/jet.js index cb78e2cc3f..71fb3e1f70 100644 --- a/scripts/developer/utilities/lib/jet/jet.js +++ b/scripts/developer/utilities/lib/jet/jet.js @@ -172,7 +172,7 @@ function job_tree_model_functor(jobTreeModel, maxLevel, newNodeFunctor) { // Traverse the jobTreenode data structure created above function job_traverseTreeNode(root, functor, depth) { - // if (root.subNode.length) { + if (root.subNode.length) { depth++; for (var i = 0; i Date: Wed, 21 Nov 2018 13:31:54 -0800 Subject: [PATCH 16/20] Warnings from build --- interface/src/Application.cpp | 2 -- interface/src/Application.h | 1 - .../src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp | 2 +- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dae9e3dad2..61365f3625 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -324,8 +324,6 @@ static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SI static const int ENTITY_SERVER_ADDED_TIMEOUT = 5000; static const int ENTITY_SERVER_CONNECTION_TIMEOUT = 5000; -static const uint32_t INVALID_FRAME = UINT32_MAX; - static const float INITIAL_QUERY_RADIUS = 10.0f; // priority radius for entities before physics enabled static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); diff --git a/interface/src/Application.h b/interface/src/Application.h index 2f23fc72d7..ead7231ffc 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -275,7 +275,6 @@ public: int getMaxOctreePacketsPerSecond() const; 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(); } diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index d8b8cbd54a..9d39a1968c 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -148,7 +148,7 @@ void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() { batch.draw(gpu::TRIANGLE_STRIP, 4); batch.setResourceTexture(0, _virtualPadStickTexture); - batch.setModelTransform(stickTransform); + batch.setModelTransform(stickTransform);, batch.draw(gpu::TRIANGLE_STRIP, 4); batch.setResourceTexture(0, _virtualPadJumpBtnTexture); From 48f32dc36b9c737970eedece356629b274ecaec8 Mon Sep 17 00:00:00 2001 From: sam gateau Date: Wed, 21 Nov 2018 13:35:36 -0800 Subject: [PATCH 17/20] Remove stuppid error --- .../src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 9d39a1968c..d8b8cbd54a 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -148,7 +148,7 @@ void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() { batch.draw(gpu::TRIANGLE_STRIP, 4); batch.setResourceTexture(0, _virtualPadStickTexture); - batch.setModelTransform(stickTransform);, + batch.setModelTransform(stickTransform); batch.draw(gpu::TRIANGLE_STRIP, 4); batch.setResourceTexture(0, _virtualPadJumpBtnTexture); From 9ee35def3dc5aa5118d064919e3b8a1152e15e37 Mon Sep 17 00:00:00 2001 From: sam gateau Date: Wed, 21 Nov 2018 15:42:35 -0800 Subject: [PATCH 18/20] trying to fix the include issue --- interface/src/graphics/RenderEventHandler.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/graphics/RenderEventHandler.h b/interface/src/graphics/RenderEventHandler.h index c566202b5b..93f8b548d0 100644 --- a/interface/src/graphics/RenderEventHandler.h +++ b/interface/src/graphics/RenderEventHandler.h @@ -10,9 +10,9 @@ #ifndef hifi_RenderEventHandler_h #define hifi_RenderEventHandler_h +#include +#include #include "gl/OffscreenGLCanvas.h" -#include -#include enum ApplicationEvent { // Execute a lambda function From aa749b0980e5649e974c499ea55de51a3b24ef6d Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 28 Nov 2018 21:46:13 -0800 Subject: [PATCH 19/20] adressing review comments --- .../utilities/lib/jet/qml/TaskListView.qml | 24 +------------------ .../lib/jet/qml/TaskTimeFrameView.qml | 1 - .../utilities/render/engineInspector.js | 14 ----------- .../utilities/render/engineInspector.qml | 2 +- 4 files changed, 2 insertions(+), 39 deletions(-) diff --git a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml index bc14404ee2..e2576fe783 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml @@ -26,30 +26,10 @@ Rectangle { Component.onCompleted: { - //var functor = Jet.job_tree_model_functor(jobsModel) var functor = Jet.job_tree_model_functor(jobsModel, 3, function(node) { node["cpuT"] = 0.0 }) Jet.task_traverseTree(rootConfig, functor); - - - - /* var tfunctor = Jet.job_tree_model_array_functor(jobsModel.engineJobItemModel, function(node) { - node["init"] = (node.level < 3) - node["fullpath"] = (node.path + "." + node.name) - node["cpuT"] = 0.0 - }) - - Jet.task_traverseTree(rootConfig, tfunctor); -*/ - // var currentParentStach = [] - // currentParentStach.push(jobsModel); - - - /* Jet.job_traverseTreeNodeRoot(jobsModel.engineJobItemModel[0], function(node, depth, index) { - print(node.name + depth + " - " + index) - return true - })*/ } @@ -95,15 +75,13 @@ Rectangle { HifiControls.Label { id: objLabel - // property var config: root.rootConfig.getConfig(model.path + "." + model.name); colorScheme: (root.rootConfig.getConfig(model.path + "." + model.name) ? hifi.colorSchemes.dark : hifi.colorSchemes.light) text: (objRecursiveColumn.children.length > 2 ? objRecursiveColumn.children[1].visible ? qsTr("- ") : qsTr("+ ") : qsTr(" ")) + model.name - // + " ms=" + config.cpuRunTime.toFixed(3) + " id=" + model.id } - } + } } Repeater { diff --git a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml index e1d9bd7ce1..f3ca550e44 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml @@ -166,7 +166,6 @@ Rectangle { function drawJob(ctx, depth, index, duration, timeOffset) { //print(root.jobsArray[index].cpuT) - // ctx.fillStyle = Qt.rgba(255, 255, 0, root.backgroundOpacity); ctx.fillStyle = ( depth % 2 ? ( index % 2 ? "blue" : "yellow") : ( index % 2 ? "green" : "red")) ctx.fillRect(getXFromTime(timeOffset), lineHeight * 2 * depth,getWFromDuration(duration), lineHeight); diff --git a/scripts/developer/utilities/render/engineInspector.js b/scripts/developer/utilities/render/engineInspector.js index 74e4231ff1..cd2b74f907 100644 --- a/scripts/developer/utilities/render/engineInspector.js +++ b/scripts/developer/utilities/render/engineInspector.js @@ -1,17 +1,3 @@ - /*function openEngineTaskView() { - // Set up the qml ui - var qml = Script.resolvePath('engineInspector.qml'); - var window = new OverlayWindow({ - title: 'Render Engine', - source: qml, - width: 500, - height: 100 - }); - window.setPosition(200, 50); - window.closed.connect(function() { Script.stop(); }); - } - openEngineTaskView();*/ - (function() { var TABLET_BUTTON_NAME = "Inspector"; var QMLAPP_URL = Script.resolvePath("./engineInspector.qml"); diff --git a/scripts/developer/utilities/render/engineInspector.qml b/scripts/developer/utilities/render/engineInspector.qml index 31283a4756..1e05605ac7 100644 --- a/scripts/developer/utilities/render/engineInspector.qml +++ b/scripts/developer/utilities/render/engineInspector.qml @@ -26,5 +26,5 @@ Item { Jet.TaskListView { rootConfig: root.rootConfig anchors.fill: root - } + } } \ No newline at end of file From 54fa4365b84d3a8d6e5cf0185b4b73611c517fff Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 28 Nov 2018 22:21:58 -0800 Subject: [PATCH 20/20] FIxing build issue doh... --- interface/src/Application.cpp | 6 ------ interface/src/Application_render.cpp | 3 --- 2 files changed, 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2e46043dba..d92eae5221 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5088,13 +5088,7 @@ void Application::init() { // Make sure Login state is up to date #if !defined(DISABLE_QML) DependencyManager::get()->toggleLoginDialog(); -<<<<<<< HEAD -======= #endif - if (!DISABLE_DEFERRED) { - DependencyManager::get()->init(); - } ->>>>>>> f4535e6784be56de3e3b0a21517280c12a434425 DependencyManager::get()->init(); _timerStart.start(); diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index 1e66953a49..5063f6118d 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -19,9 +19,6 @@ #include "Util.h" - - -<<<<<<< HEAD //void Application::paintGL() { // // Some plugins process message events, allowing paintGL to be called reentrantly. //