From 473f8d0ca5918bc8b8fc3ff322ec0a527809cc3f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 23 Aug 2018 11:39:47 -0700 Subject: [PATCH 01/24] Working on the LOD system --- interface/resources/qml/+android/Stats.qml | 15 ++++ interface/resources/qml/Stats.qml | 17 ++++ interface/src/LODManager.cpp | 7 ++ interface/src/LODManager.h | 10 ++- interface/src/ui/Stats.cpp | 6 ++ interface/src/ui/Stats.h | 13 ++- .../render/configSlider/ConfigSlider.qml | 6 +- scripts/developer/utilities/render/lod.js | 88 +++++++++++++++---- scripts/developer/utilities/render/lod.qml | 60 ++++++++++++- 9 files changed, 198 insertions(+), 24 deletions(-) diff --git a/interface/resources/qml/+android/Stats.qml b/interface/resources/qml/+android/Stats.qml index fe827f6ece..0dcb07e730 100644 --- a/interface/resources/qml/+android/Stats.qml +++ b/interface/resources/qml/+android/Stats.qml @@ -264,20 +264,27 @@ Item { StatText { text: "GPU: " + root.gpuFrameTime.toFixed(1) + " ms" } + StatText { + text: "Drawcalls: " + root.drawcalls + } StatText { text: "Triangles: " + root.triangles + " / Material Switches: " + root.materialSwitches } StatText { + visible: root.expanded; text: "GPU Free Memory: " + root.gpuFreeMemory + " MB"; } StatText { + visible: root.expanded; text: "GPU Textures: "; } StatText { + visible: root.expanded; text: " Count: " + root.gpuTextures; } StatText { + visible: root.expanded; text: " Pressure State: " + root.gpuTextureMemoryPressureState; } StatText { @@ -287,27 +294,35 @@ Item { text: " " + root.gpuTextureResourceMemory + " / " + root.gpuTextureResourcePopulatedMemory + " / " + root.texturePendingTransfers + " MB"; } StatText { + visible: root.expanded; text: " Resident Memory: " + root.gpuTextureResidentMemory + " MB"; } StatText { + visible: root.expanded; text: " Framebuffer Memory: " + root.gpuTextureFramebufferMemory + " MB"; } StatText { + visible: root.expanded; text: " External Memory: " + root.gpuTextureExternalMemory + " MB"; } StatText { + visible: root.expanded; text: "GPU Buffers: " } StatText { + visible: root.expanded; text: " Count: " + root.gpuBuffers; } StatText { + visible: root.expanded; text: " Memory: " + root.gpuBufferMemory + " MB"; } StatText { + visible: root.expanded; text: "GL Swapchain Memory: " + root.glContextSwapchainMemory + " MB"; } StatText { + visible: root.expanded; text: "QML Texture Memory: " + root.qmlTextureMemory + " MB"; } StatText { diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 2e6e909312..574ceb62a4 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -285,52 +285,69 @@ Item { StatText { text: "GPU frame size: " + root.gpuFrameSize.x + " x " + root.gpuFrameSize.y } + StatText { + text: "Drawcalls: " + root.drawcalls + } StatText { text: "Triangles: " + root.triangles + " / Material Switches: " + root.materialSwitches } StatText { + visible: root.expanded; text: "GPU Free Memory: " + root.gpuFreeMemory + " MB"; } StatText { + visible: root.expanded; text: "GPU Textures: "; } StatText { + visible: root.expanded; text: " Count: " + root.gpuTextures; } StatText { + visible: root.expanded; text: " Pressure State: " + root.gpuTextureMemoryPressureState; } StatText { + visible: root.expanded; property bool showIdeal: (root.gpuTextureResourceIdealMemory != root.gpuTextureResourceMemory); text: " Resource Allocated " + (showIdeal ? "(Ideal)" : "") + " / Populated / Pending: "; } StatText { + visible: root.expanded; property bool showIdeal: (root.gpuTextureResourceIdealMemory != root.gpuTextureResourceMemory); text: " " + root.gpuTextureResourceMemory + (showIdeal ? ("(" + root.gpuTextureResourceIdealMemory + ")") : "") + " / " + root.gpuTextureResourcePopulatedMemory + " / " + root.texturePendingTransfers + " MB"; } StatText { + visible: root.expanded; text: " Resident Memory: " + root.gpuTextureResidentMemory + " MB"; } StatText { + visible: root.expanded; text: " Framebuffer Memory: " + root.gpuTextureFramebufferMemory + " MB"; } StatText { + visible: root.expanded; text: " External Memory: " + root.gpuTextureExternalMemory + " MB"; } StatText { + visible: root.expanded; text: "GPU Buffers: " } StatText { + visible: root.expanded; text: " Count: " + root.gpuBuffers; } StatText { + visible: root.expanded; text: " Memory: " + root.gpuBufferMemory + " MB"; } StatText { + visible: root.expanded; text: "GL Swapchain Memory: " + root.glContextSwapchainMemory + " MB"; } StatText { + visible: root.expanded; text: "QML Texture Memory: " + root.qmlTextureMemory + " MB"; } StatText { diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index da1f14c450..681bdaf884 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -87,6 +87,7 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { _octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE; } emit LODDecreased(); + emit LODChanged(); // Assuming the LOD adjustment will work: we optimistically reset _avgRenderTime // to provide an FPS just above the decrease threshold. It will drift close to its // true value after a few LOD_ADJUST_TIMESCALEs and we'll adjust again as necessary. @@ -108,6 +109,8 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { _octreeSizeScale = ADJUST_LOD_MAX_SIZE_SCALE; } emit LODIncreased(); + emit LODChanged(); + // Assuming the LOD adjustment will work: we optimistically reset _avgRenderTime // to provide an FPS just below the increase threshold. It will drift close to its // true value after a few LOD_ADJUST_TIMESCALEs and we'll adjust again as necessary. @@ -145,6 +148,10 @@ float LODManager::getLODLevel() const { return simpleLOD; } +void LODManager::setLODLevel(float level) { + +} + const float MIN_DECREASE_FPS = 0.5f; void LODManager::setDesktopLODDecreaseFPS(float fps) { diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 8f88da63a8..f0bc1aabf9 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -30,7 +30,9 @@ const float INCREASE_LOD_GAP_FPS = 10.0f; // fps // The default value DEFAULT_OCTREE_SIZE_SCALE means you can be 400 meters away from a 1 meter object in order to see it (which is ~20:20 vision). const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE; // This controls how low the auto-adjust LOD will go. We want a minimum vision of ~20:500 or 0.04 of default -const float ADJUST_LOD_MIN_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE * 0.04f; +// const float ADJUST_LOD_MIN_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE * 0.04f; +// const float ADJUST_LOD_MIN_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE * 0.02f; +const float ADJUST_LOD_MIN_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE * 0.01f; class AABox; @@ -60,9 +62,10 @@ class LODManager : public QObject, public Dependency { Q_PROPERTY(float gpuTime READ getGPUTime) Q_PROPERTY(float avgRenderTime READ getAverageRenderTime) Q_PROPERTY(float fps READ getMaxTheoreticalFPS) - Q_PROPERTY(float lodLevel READ getLODLevel) + Q_PROPERTY(float lodLevel READ getLODLevel WRITE setLODLevel NOTIFY LODChanged) Q_PROPERTY(float lodDecreaseFPS READ getLODDecreaseFPS) Q_PROPERTY(float lodIncreaseFPS READ getLODIncreaseFPS) + Q_PROPERTY(bool automaticLODAdjust READ getAutomaticLODAdjust WRITE setAutomaticLODAdjust) public: @@ -174,6 +177,7 @@ public: float getAverageRenderTime() const { return _avgRenderTime; }; float getMaxTheoreticalFPS() const { return (float)MSECS_PER_SECOND / _avgRenderTime; }; float getLODLevel() const; + void setLODLevel(float level); signals: @@ -189,6 +193,8 @@ signals: */ void LODDecreased(); + void LODChanged(); + private: LODManager(); diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index ce1cd51de1..912e851c00 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -376,6 +376,12 @@ void Stats::updateStats(bool force) { STAT_UPDATE(rectifiedTextureCount, (int)RECTIFIED_TEXTURE_COUNT.load()); STAT_UPDATE(decimatedTextureCount, (int)DECIMATED_TEXTURE_COUNT.load()); + gpu::ContextStats gpuFrameStats; + gpuContext->getFrameStats(gpuFrameStats); + + STAT_UPDATE(drawcalls, gpuFrameStats._DSNumDrawcalls); + + // Incoming packets QLocale locale(QLocale::English); auto voxelPacketsToProcess = qApp->getOctreePacketProcessor().packetsToProcessCount(); diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index cf624b54c3..f9043f8f56 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -239,7 +239,8 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, processing, 0) STATS_PROPERTY(int, processingPending, 0) STATS_PROPERTY(int, triangles, 0) - STATS_PROPERTY(int, quads, 0) + STATS_PROPERTY(int, drawcalls, 0) + // STATS_PROPERTY(int, quads, 0) STATS_PROPERTY(int, materialSwitches, 0) STATS_PROPERTY(int, itemConsidered, 0) STATS_PROPERTY(int, itemOutOfView, 0) @@ -708,12 +709,20 @@ signals: */ void trianglesChanged(); + /**jsdoc + * Triggered when the value of the drawcalls property changes. + * This + * @function Stats.drawcallsChanged + * @returns {Signal} + */ + void drawcallsChanged(); + /**jsdoc * Triggered when the value of the quads property changes. * @function Stats.quadsChanged * @returns {Signal} */ - void quadsChanged(); + // void quadsChanged(); /**jsdoc * Triggered when the value of the materialSwitches property changes. diff --git a/scripts/developer/utilities/render/configSlider/ConfigSlider.qml b/scripts/developer/utilities/render/configSlider/ConfigSlider.qml index 41de77fb09..345b29e791 100644 --- a/scripts/developer/utilities/render/configSlider/ConfigSlider.qml +++ b/scripts/developer/utilities/render/configSlider/ConfigSlider.qml @@ -56,13 +56,13 @@ Item { anchors.verticalCenter: root.verticalCenter } - Binding { + /* Binding { id: bindingControl target: root.config property: root.property value: sliderControl.value when: false - } + }*/ HifiControls.Slider { id: sliderControl @@ -73,7 +73,7 @@ Item { anchors.top: root.top anchors.topMargin: 0 - onValueChanged: { root.valueChanged(value) } + // onValueChanged: { root.valueChanged(value) } } HifiControls.Label { diff --git a/scripts/developer/utilities/render/lod.js b/scripts/developer/utilities/render/lod.js index 307e509d39..632f4e50c5 100644 --- a/scripts/developer/utilities/render/lod.js +++ b/scripts/developer/utilities/render/lod.js @@ -16,15 +16,9 @@ var ICON_URL = Script.resolvePath("../../../system/assets/images/lod-i.svg"); var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/lod-a.svg"); - var onScreen = false; + var onTablet = false; // set this to true to use the tablet, false use a floating window - function onClicked() { - if (onScreen) { - tablet.gotoHomeScreen(); - } else { - tablet.loadQMLSource(QMLAPP_URL); - } - } + var onAppScreen = false; var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var button = tablet.addButton({ @@ -35,6 +29,51 @@ var hasEventBridge = false; + var onScreen = false; + var window; + + function onClicked() { + if (onTablet) { + if (onAppScreen) { + tablet.gotoHomeScreen(); + } else { + tablet.loadQMLSource(QMLAPP_URL); + } + } else { + if (onScreen) { + killWindow() + } else { + createWindow() + } + } + } + + function createWindow() { + var qml = Script.resolvePath(QMLAPP_URL); + window = Desktop.createWindow(Script.resolvePath(QMLAPP_URL), { + title: TABLET_BUTTON_NAME, + flags: Desktop.ALWAYS_ON_TOP, + presentationMode: Desktop.PresentationMode.NATIVE, + size: {x: 400, y: 600} + }); + // window.setPosition(200, 50); + window.closed.connect(killWindow); + window.fromQml.connect(fromQml); + onScreen = true + button.editProperties({isActive: true}); + } + + function killWindow() { + if (window !== undefined) { + window.closed.disconnect(killWindow); + window.fromQml.disconnect(fromQml); + window.close() + window = undefined + } + onScreen = false + button.editProperties({isActive: false}) + } + function wireEventBridge(on) { if (!tablet) { print("Warning in wireEventBridge(): 'tablet' undefined!"); @@ -54,23 +93,42 @@ } function onScreenChanged(type, url) { - onScreen = (url === QMLAPP_URL); - button.editProperties({isActive: onScreen}); - wireEventBridge(onScreen); - } - - function fromQml(message) { + if (onTablet) { + if (url === QMLAPP_URL) { + onAppScreen = true; + } else { + onAppScreen = false; + } + + button.editProperties({isActive: onAppScreen}); + wireEventBridge(onAppScreen); + } } button.clicked.connect(onClicked); tablet.screenChanged.connect(onScreenChanged); Script.scriptEnding.connect(function () { - if (onScreen) { + killWindow() + if (onAppScreen) { tablet.gotoHomeScreen(); } button.clicked.disconnect(onClicked); tablet.screenChanged.disconnect(onScreenChanged); tablet.removeButton(button); }); + + function fromQml(message) { + } + + function sendToQml(message) { + if (onTablet) { + tablet.sendToQml(message); + } else { + if (window) { + window.sendToQml(message); + } + } + } + }()); diff --git a/scripts/developer/utilities/render/lod.qml b/scripts/developer/utilities/render/lod.qml index d7b9f1cd57..36a19c10f2 100644 --- a/scripts/developer/utilities/render/lod.qml +++ b/scripts/developer/utilities/render/lod.qml @@ -10,20 +10,73 @@ // import QtQuick 2.5 import QtQuick.Controls 1.4 + +import "qrc:///qml/styles-uit" +import "qrc:///qml/controls-uit" as HifiControls + import "../lib/plotperf" +import "configSlider" Item { id: lodIU anchors.fill:parent + Component.onCompleted: { + Render.getConfig("RenderMainView.DrawSceneOctree").showVisibleCells = false + Render.getConfig("RenderMainView.DrawSceneOctree").showEmptyCells = false + } + + Component.onDestruction: { + Render.getConfig("RenderMainView.DrawSceneOctree").enabled = false + } + + Column { + id: topHeader + spacing: 8 + anchors.right: parent.right + anchors.left: parent.left + + HifiControls.CheckBox { + boxSize: 20 + text: "Show LOD Reticule" + checked: Render.getConfig("RenderMainView.DrawSceneOctree").enabled + onCheckedChanged: { Render.getConfig("RenderMainView.DrawSceneOctree").enabled = checked } + } + HifiControls.CheckBox { + boxSize: 20 + text: "Manual LOD" + checked: LODManager.getAutomaticLODAdjust() + onCheckedChanged: { LODManager.setAutomaticLODAdjust(checked) } + } + ConfigSlider { + showLabel: true + config: LODManager + property: "lodLevel" + max: 13 + min: 0 + integral: false + + anchors.left: parent.left + anchors.right: parent.right + } + + } + Column { id: stats spacing: 8 - anchors.fill:parent + anchors.right: parent.right + anchors.left: parent.left + anchors.top: topHeader.bottom + anchors.bottom: parent.bottom function evalEvenHeight() { // Why do we have to do that manually ? cannot seem to find a qml / anchor / layout mode that does that ? - return (height - spacing * (children.length - 1)) / children.length + return (height - topLine.height - bottomLine.height - spacing * (children.length - 3)) / (children.length - 2) + } + + Separator { + id: topLine } PlotPerf { @@ -87,6 +140,9 @@ Item { color: "#9999FF" } ] + } + Separator { + id: bottomLine } } } From cee9b909300906f84e156595920e44ab5546dc28 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 23 Aug 2018 16:48:42 -0700 Subject: [PATCH 02/24] working on the LOD behavior --- interface/src/LODManager.cpp | 72 ++++++++++++++++ interface/src/LODManager.h | 11 ++- interface/src/ui/PreferencesDialog.cpp | 9 +- .../render/configSlider/ConfigSlider.qml | 6 +- .../render/configSlider/RichSlider.qml | 82 +++++++++++++++++++ .../utilities/render/configSlider/qmldir | 3 +- scripts/developer/utilities/render/lod.qml | 45 ++++++++-- 7 files changed, 213 insertions(+), 15 deletions(-) create mode 100644 scripts/developer/utilities/render/configSlider/RichSlider.qml diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 681bdaf884..4f90dee2e5 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -136,6 +136,11 @@ void LODManager::resetLODAdjust() { _decreaseFPSExpiry = _increaseFPSExpiry = usecTimestampNow() + LOD_AUTO_ADJUST_PERIOD; } +void LODManager::setAutomaticLODAdjust(bool value) { + _automaticLODAdjust = value; + emit autoLODChanged(); +} + float LODManager::getLODLevel() const { // simpleLOD is a linearized and normalized number that represents how much LOD is being applied. // It ranges from: @@ -149,7 +154,14 @@ float LODManager::getLODLevel() const { } void LODManager::setLODLevel(float level) { + float simpleLOD = level; + if (!_automaticLODAdjust) { + const float LOG_MIN_LOD_RATIO = logf(ADJUST_LOD_MIN_SIZE_SCALE / ADJUST_LOD_MAX_SIZE_SCALE); + float power = LOG_MIN_LOD_RATIO - (simpleLOD * LOG_MIN_LOD_RATIO); + float sizeScale = expf(power) * ADJUST_LOD_MAX_SIZE_SCALE; + setOctreeSizeScale(sizeScale); + } } const float MIN_DECREASE_FPS = 0.5f; @@ -247,3 +259,63 @@ void LODManager::saveSettings() { hmdLODDecreaseFPS.set(getHMDLODDecreaseFPS()); } +void LODManager::setWorldDetailQuality(float quality) { + + static const float MAX_DESKTOP_FPS = 60; + static const float MAX_HMD_FPS = 90; + static const float MIN_FPS = 10; + static const float LOW = 0.25f; + static const float MEDIUM = 0.5f; + static const float HIGH = 0.75f; + static const float THRASHING_DIFFERENCE = 10; + + bool isLowestValue = quality == LOW; + bool isHMDMode = qApp->isHMDMode(); + + float maxFPS = isHMDMode ? MAX_HMD_FPS : MAX_DESKTOP_FPS; + float desiredFPS = maxFPS - THRASHING_DIFFERENCE; + + if (!isLowestValue) { + float calculatedFPS = (maxFPS - (maxFPS * quality)) - THRASHING_DIFFERENCE; + desiredFPS = calculatedFPS < MIN_FPS ? MIN_FPS : calculatedFPS; + } + + if (isHMDMode) { + setHMDLODDecreaseFPS(desiredFPS); + } + else { + setDesktopLODDecreaseFPS(desiredFPS); + } + + emit worldDetailQualityChanged(); +} + +float LODManager::getWorldDetailQuality() const { + + + static const float MAX_DESKTOP_FPS = 60; + static const float MAX_HMD_FPS = 90; + static const float MIN_FPS = 10; + static const float LOW = 0.25f; + static const float MEDIUM = 0.5f; + static const float HIGH = 0.75f; + + bool inHMD = qApp->isHMDMode(); + + float increaseFPS = 0; + if (inHMD) { + increaseFPS = getHMDLODDecreaseFPS(); + } else { + increaseFPS = getDesktopLODDecreaseFPS(); + } + float maxFPS = inHMD ? MAX_HMD_FPS : MAX_DESKTOP_FPS; + float percentage = increaseFPS / maxFPS; + + if (percentage >= HIGH) { + return LOW; + } + else if (percentage >= LOW) { + return MEDIUM; + } + return HIGH; +} diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index f0bc1aabf9..de026274ad 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -65,7 +65,9 @@ class LODManager : public QObject, public Dependency { Q_PROPERTY(float lodLevel READ getLODLevel WRITE setLODLevel NOTIFY LODChanged) Q_PROPERTY(float lodDecreaseFPS READ getLODDecreaseFPS) Q_PROPERTY(float lodIncreaseFPS READ getLODIncreaseFPS) - Q_PROPERTY(bool automaticLODAdjust READ getAutomaticLODAdjust WRITE setAutomaticLODAdjust) + Q_PROPERTY(bool automaticLODAdjust READ getAutomaticLODAdjust WRITE setAutomaticLODAdjust NOTIFY autoLODChanged) + + Q_PROPERTY(float worldDetailQuality READ getWorldDetailQuality WRITE setWorldDetailQuality NOTIFY worldDetailQualityChanged) public: @@ -73,7 +75,7 @@ public: * @function LODManager.setAutomaticLODAdjust * @param {boolean} value */ - Q_INVOKABLE void setAutomaticLODAdjust(bool value) { _automaticLODAdjust = value; } + Q_INVOKABLE void setAutomaticLODAdjust(bool value); /**jsdoc * @function LODManager.getAutomaticLODAdjust @@ -179,6 +181,9 @@ public: float getLODLevel() const; void setLODLevel(float level); + void setWorldDetailQuality(float quality); + float getWorldDetailQuality() const; + signals: /**jsdoc @@ -194,6 +199,8 @@ signals: void LODDecreased(); void LODChanged(); + void autoLODChanged(); + void worldDetailQualityChanged(); private: LODManager(); diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 79ca2063ec..a271e9436c 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -55,7 +55,7 @@ void setupPreferences() { // Graphics quality static const QString GRAPHICS_QUALITY { "Graphics Quality" }; { - static const float MAX_DESKTOP_FPS = 60; + /* static const float MAX_DESKTOP_FPS = 60; static const float MAX_HMD_FPS = 90; static const float MIN_FPS = 10; static const float LOW = 0.25f; @@ -102,6 +102,13 @@ void setupPreferences() { } else { lodManager->setDesktopLODDecreaseFPS(desiredFPS); } + };*/ + auto getter = []()->float { + return DependencyManager::get()->getWorldDetailQuality(); + }; + + auto setter = [](float value) { + DependencyManager::get()->setWorldDetailQuality(value); }; auto wodSlider = new SliderPreference(GRAPHICS_QUALITY, "World Detail", getter, setter); diff --git a/scripts/developer/utilities/render/configSlider/ConfigSlider.qml b/scripts/developer/utilities/render/configSlider/ConfigSlider.qml index 345b29e791..41de77fb09 100644 --- a/scripts/developer/utilities/render/configSlider/ConfigSlider.qml +++ b/scripts/developer/utilities/render/configSlider/ConfigSlider.qml @@ -56,13 +56,13 @@ Item { anchors.verticalCenter: root.verticalCenter } - /* Binding { + Binding { id: bindingControl target: root.config property: root.property value: sliderControl.value when: false - }*/ + } HifiControls.Slider { id: sliderControl @@ -73,7 +73,7 @@ Item { anchors.top: root.top anchors.topMargin: 0 - // onValueChanged: { root.valueChanged(value) } + onValueChanged: { root.valueChanged(value) } } HifiControls.Label { diff --git a/scripts/developer/utilities/render/configSlider/RichSlider.qml b/scripts/developer/utilities/render/configSlider/RichSlider.qml new file mode 100644 index 0000000000..c44727cfa4 --- /dev/null +++ b/scripts/developer/utilities/render/configSlider/RichSlider.qml @@ -0,0 +1,82 @@ +// +// RichSlider.qml +// +// Created by Zach Pomerantz on 2/8/2016 +// 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 as Original +import QtQuick.Controls.Styles 1.4 + +import "qrc:///qml/styles-uit" +import "qrc:///qml/controls-uit" as HifiControls + + +Item { + HifiConstants { id: hifi } + id: root + + anchors.left: parent.left + anchors.right: parent.right + height: 24 + + function defaultGet() { return 0 } + function defaultSet(value) { } + + property var labelAreaWidthScale: 0.5 + + property bool integral: false + property var valueVarGetter: defaultGet + property var valueVarSetter: defaultSet + // property string property + property alias valueVar : sliderControl.value + // property alias valueSetter : sliderControl.value + property alias min: sliderControl.minimumValue + property alias max: sliderControl.maximumValue + + property alias label: labelControl.text + property bool showLabel: true + + property bool showValue: true + + + + signal valueChanged(real value) + + Component.onCompleted: { + } + + HifiControls.Label { + id: labelControl + text: root.label + enabled: root.showLabel + anchors.left: root.left + width: root.width * root.labelAreaWidthScale + anchors.verticalCenter: root.verticalCenter + } + + HifiControls.Slider { + id: sliderControl + stepSize: root.integral ? 1.0 : 0.0 + anchors.left: labelControl.right + anchors.right: root.right + anchors.rightMargin: 0 + anchors.top: root.top + anchors.topMargin: 0 + onValueChanged: { root.valueVarSetter(value) } + } + + HifiControls.Label { + id: labelValue + enabled: root.showValue + text: sliderControl.value.toFixed(root.integral ? 0 : 2) + anchors.right: labelControl.right + anchors.rightMargin: 5 + anchors.verticalCenter: root.verticalCenter + } + +} diff --git a/scripts/developer/utilities/render/configSlider/qmldir b/scripts/developer/utilities/render/configSlider/qmldir index 6680ec9638..479f786b22 100644 --- a/scripts/developer/utilities/render/configSlider/qmldir +++ b/scripts/developer/utilities/render/configSlider/qmldir @@ -1 +1,2 @@ -ConfigSlider 1.0 ConfigSlider.qml \ No newline at end of file +ConfigSlider 1.0 ConfigSlider.qml +RichSlider 1.0 RichSlider.qml \ No newline at end of file diff --git a/scripts/developer/utilities/render/lod.qml b/scripts/developer/utilities/render/lod.qml index 36a19c10f2..25a0d20db6 100644 --- a/scripts/developer/utilities/render/lod.qml +++ b/scripts/developer/utilities/render/lod.qml @@ -44,21 +44,50 @@ Item { } HifiControls.CheckBox { boxSize: 20 - text: "Manual LOD" - checked: LODManager.getAutomaticLODAdjust() - onCheckedChanged: { LODManager.setAutomaticLODAdjust(checked) } + text: "Auto LOD" + checked: LODManager.automaticLODAdjust + onCheckedChanged: { LODManager.automaticLODAdjust = (checked) } } - ConfigSlider { +property var lodObject: LODManager + + RichSlider { showLabel: true - config: LODManager - property: "lodLevel" - max: 13 - min: 0 + label: "lodLevel" + valueVar: LODManager["lodLevel"] + valueVarSetter: (function (v) { LODManager["lodLevel"] = v }) + max: 1.0 + min: 0.0 integral: false anchors.left: parent.left anchors.right: parent.right } + RichSlider { + showLabel: true + // config: lodObject + // property: "worldDetailQuality" + // valueVar: LODManager["worldDetailQuality"] + label: "World Quality" + valueVar: LODManager["worldDetailQuality"] + // valueVarGetter: { return LODManager["worldDetailQuality"] } + valueVarSetter: (function (v) { LODManager["worldDetailQuality"] = v }) + max: 0.75 + min: 0.25 + integral: false + + anchors.left: parent.left + anchors.right: parent.right + } + /* HifiControls.Slider { + id: sliderControl + stepSize: 0.0 + minimumValue: 0.0 + maximumValue: 1.2 + anchors.left: parent.left + anchors.right: parent.right + value: LODManager["lodLevel"] + onValueChanged: { LODManager["lodLevel"] = value } + }*/ } From 57fd824005681efef2b798e4ceb40bc20a67f0c7 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 23 Aug 2018 17:30:23 -0700 Subject: [PATCH 03/24] working on the LOD behavior --- .../render/configSlider/RichSlider.qml | 8 +-- scripts/developer/utilities/render/lod.qml | 59 ++++++++----------- 2 files changed, 27 insertions(+), 40 deletions(-) diff --git a/scripts/developer/utilities/render/configSlider/RichSlider.qml b/scripts/developer/utilities/render/configSlider/RichSlider.qml index c44727cfa4..1613cac1b4 100644 --- a/scripts/developer/utilities/render/configSlider/RichSlider.qml +++ b/scripts/developer/utilities/render/configSlider/RichSlider.qml @@ -28,13 +28,11 @@ Item { function defaultSet(value) { } property var labelAreaWidthScale: 0.5 - property bool integral: false - property var valueVarGetter: defaultGet + property var valueVarSetter: defaultSet - // property string property - property alias valueVar : sliderControl.value - // property alias valueSetter : sliderControl.value + property alias valueVar : sliderControl.value + property alias min: sliderControl.minimumValue property alias max: sliderControl.maximumValue diff --git a/scripts/developer/utilities/render/lod.qml b/scripts/developer/utilities/render/lod.qml index 25a0d20db6..452d5c7930 100644 --- a/scripts/developer/utilities/render/lod.qml +++ b/scripts/developer/utilities/render/lod.qml @@ -42,17 +42,33 @@ Item { checked: Render.getConfig("RenderMainView.DrawSceneOctree").enabled onCheckedChanged: { Render.getConfig("RenderMainView.DrawSceneOctree").enabled = checked } } - HifiControls.CheckBox { - boxSize: 20 - text: "Auto LOD" - checked: LODManager.automaticLODAdjust - onCheckedChanged: { LODManager.automaticLODAdjust = (checked) } - } -property var lodObject: LODManager RichSlider { showLabel: true - label: "lodLevel" + showValue: false + label: "World Quality" + valueVar: LODManager["worldDetailQuality"] + valueVarSetter: (function (v) { LODManager["worldDetailQuality"] = v }) + max: 0.75 + min: 0.25 + integral: false + + anchors.left: autoLOD.left + anchors.right: parent.right + } + + HifiControls.CheckBox { + id: autoLOD + boxSize: 20 + text: "Auto LOD" + checked: LODManager.automaticLODAdjust + onCheckedChanged: { LODManager.automaticLODAdjust = (checked) } + } + + RichSlider { + visible: !LODManager.automaticLODAdjust + showLabel: true + label: "LOD Level" valueVar: LODManager["lodLevel"] valueVarSetter: (function (v) { LODManager["lodLevel"] = v }) max: 1.0 @@ -62,33 +78,6 @@ property var lodObject: LODManager anchors.left: parent.left anchors.right: parent.right } - RichSlider { - showLabel: true - // config: lodObject - // property: "worldDetailQuality" - // valueVar: LODManager["worldDetailQuality"] - label: "World Quality" - valueVar: LODManager["worldDetailQuality"] - // valueVarGetter: { return LODManager["worldDetailQuality"] } - valueVarSetter: (function (v) { LODManager["worldDetailQuality"] = v }) - max: 0.75 - min: 0.25 - integral: false - - anchors.left: parent.left - anchors.right: parent.right - } - /* HifiControls.Slider { - id: sliderControl - stepSize: 0.0 - minimumValue: 0.0 - maximumValue: 1.2 - anchors.left: parent.left - anchors.right: parent.right - value: LODManager["lodLevel"] - onValueChanged: { LODManager["lodLevel"] = value } - }*/ - } Column { From 294fe51fdebd5dd5f21f5b6d084d2ec3599f77aa Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 24 Aug 2018 16:48:23 -0700 Subject: [PATCH 04/24] Trying to simplify the LOD culling test --- interface/src/Application.cpp | 2 +- interface/src/LODManager.cpp | 6 ++++++ interface/src/LODManager.h | 4 ++++ libraries/octree/src/OctreeUtils.cpp | 8 ++++++-- libraries/octree/src/OctreeUtils.h | 1 + libraries/render/src/render/Args.h | 5 +++++ scripts/developer/utilities/render/lod.qml | 16 +++++++++++++++- tests-manual/render-perf/src/main.cpp | 2 +- 8 files changed, 39 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e290531471..817c6b1e43 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5987,7 +5987,7 @@ void Application::updateRenderArgs(float deltaTime) { _viewFrustum.calculate(); } appRenderArgs._renderArgs = RenderArgs(_gpuContext, lodManager->getOctreeSizeScale(), - lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, + lodManager->getBoundaryLevelAdjust(), lodManager->getSolidAngleHalfTan(), RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); appRenderArgs._renderArgs._scene = getMain3DScene(); diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 4f90dee2e5..c46933b2fc 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -319,3 +319,9 @@ float LODManager::getWorldDetailQuality() const { } return HIGH; } + + +float LODManager::getSolidAngleHalfTan() const { + return getPerspectiveAccuracyAngleTan(_octreeSizeScale, _boundaryLevelAdjust); +} + diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index de026274ad..2ba933f91d 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -69,6 +69,8 @@ class LODManager : public QObject, public Dependency { Q_PROPERTY(float worldDetailQuality READ getWorldDetailQuality WRITE setWorldDetailQuality NOTIFY worldDetailQualityChanged) + Q_PROPERTY(float solidAngleHalfTan READ getSolidAngleHalfTan) + public: /**jsdoc @@ -184,6 +186,8 @@ public: void setWorldDetailQuality(float quality); float getWorldDetailQuality() const; + float getSolidAngleHalfTan() const; + signals: /**jsdoc diff --git a/libraries/octree/src/OctreeUtils.cpp b/libraries/octree/src/OctreeUtils.cpp index 8eaf22e198..be8c194a95 100644 --- a/libraries/octree/src/OctreeUtils.cpp +++ b/libraries/octree/src/OctreeUtils.cpp @@ -64,10 +64,14 @@ float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeSc return voxelSizeScale / powf(2.0f, renderLevel); } -float getPerspectiveAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust) { +float getPerspectiveAccuracyAngleTan(float octreeSizeScale, int boundaryLevelAdjust) { const float maxScale = (float)TREE_SCALE; float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO; - return atan(maxScale / visibleDistanceAtMaxScale); + return (maxScale / visibleDistanceAtMaxScale); +} + +float getPerspectiveAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust) { + return atan(getPerspectiveAccuracyAngleTan(octreeSizeScale, boundaryLevelAdjust)); } float getOrthographicAccuracySize(float octreeSizeScale, int boundaryLevelAdjust) { diff --git a/libraries/octree/src/OctreeUtils.h b/libraries/octree/src/OctreeUtils.h index dff56cad64..4539a54dc3 100644 --- a/libraries/octree/src/OctreeUtils.h +++ b/libraries/octree/src/OctreeUtils.h @@ -29,6 +29,7 @@ float calculateRenderAccuracy(const glm::vec3& position, float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale); +float getPerspectiveAccuracyAngleTan(float octreeSizeScale, int boundaryLevelAdjust); float getPerspectiveAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust); float getOrthographicAccuracySize(float octreeSizeScale, int boundaryLevelAdjust); diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index 627d4f17b2..a46b914826 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -73,12 +73,14 @@ namespace render { Args(const gpu::ContextPointer& context, float sizeScale = 1.0f, int boundaryLevelAdjust = 0, + float solidAngleHalfTan = 0.1f, RenderMode renderMode = DEFAULT_RENDER_MODE, DisplayMode displayMode = MONO, DebugFlags debugFlags = RENDER_DEBUG_NONE, gpu::Batch* batch = nullptr) : _context(context), _sizeScale(sizeScale), + _solidAngleHalfTan(solidAngleHalfTan), _boundaryLevelAdjust(boundaryLevelAdjust), _renderMode(renderMode), _displayMode(displayMode), @@ -105,8 +107,11 @@ namespace render { std::stack _viewFrustums; glm::ivec4 _viewport { 0.0f, 0.0f, 1.0f, 1.0f }; glm::vec3 _boomOffset { 0.0f, 0.0f, 1.0f }; + float _sizeScale { 1.0f }; int _boundaryLevelAdjust { 0 }; + float _solidAngleHalfTan{ 0.1f }; + RenderMode _renderMode { DEFAULT_RENDER_MODE }; DisplayMode _displayMode { MONO }; DebugFlags _debugFlags { RENDER_DEBUG_NONE }; diff --git a/scripts/developer/utilities/render/lod.qml b/scripts/developer/utilities/render/lod.qml index 452d5c7930..688cef142f 100644 --- a/scripts/developer/utilities/render/lod.qml +++ b/scripts/developer/utilities/render/lod.qml @@ -158,7 +158,21 @@ Item { color: "#9999FF" } ] - } + } + PlotPerf { + title: "Solid Angle Half Tan" + height: parent.evalEvenHeight() + object: LODManager + valueScale: 1.0 + valueUnit: "" + plots: [ + { + prop: "solidAngleHalfTan", + label: "SAHT", + color: "#9999FF" + } + ] + } Separator { id: bottomLine } diff --git a/tests-manual/render-perf/src/main.cpp b/tests-manual/render-perf/src/main.cpp index 9238e0dc1c..c9724ea352 100644 --- a/tests-manual/render-perf/src/main.cpp +++ b/tests-manual/render-perf/src/main.cpp @@ -659,7 +659,7 @@ private: update(); _initContext.makeCurrent(); - RenderArgs renderArgs(_renderThread._gpuContext, DEFAULT_OCTREE_SIZE_SCALE, 0, RenderArgs::DEFAULT_RENDER_MODE, + RenderArgs renderArgs(_renderThread._gpuContext, DEFAULT_OCTREE_SIZE_SCALE, 0, getPerspectiveAccuracyAngleTan(DEFAULT_OCTREE_SIZE_SCALE, 0), RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); QSize windowSize = _size; From d97d655148ab70514241f31c6de19ea691d227c1 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sun, 26 Aug 2018 23:17:29 -0700 Subject: [PATCH 05/24] USing a simpler halfTan test for culling --- interface/src/LODManager.cpp | 13 +++++++++++-- interface/src/LODManager.h | 2 ++ libraries/octree/src/OctreeUtils.cpp | 6 ------ libraries/octree/src/OctreeUtils.h | 2 -- libraries/render-utils/src/RenderShadowTask.cpp | 4 ++-- libraries/render/src/render/CullTask.cpp | 2 +- libraries/render/src/render/CullTask.h | 6 +++--- scripts/developer/utilities/render/lod.qml | 9 +++++---- 8 files changed, 24 insertions(+), 20 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index c46933b2fc..cd692bccf0 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -237,8 +237,14 @@ QString LODManager::getLODFeedbackText() { bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) { // FIXME - eventually we want to use the render accuracy as an indicator for the level of detail // to use in rendering. - float renderAccuracy = calculateRenderAccuracy(args->getViewFrustum().getPosition(), bounds, args->_sizeScale, args->_boundaryLevelAdjust); - return (renderAccuracy > 0.0f); + // float renderAccuracy = calculateRenderAccuracy(args->getViewFrustum().getPosition(), bounds, args->_sizeScale, args->_boundaryLevelAdjust); + // return (renderAccuracy > 0.0f); + + auto pos = args->getViewFrustum().getPosition() - bounds.calcCenter(); + auto dim = bounds.getDimensions(); + auto halfTanSq = 0.25f * glm::dot(dim, dim) / glm::dot(pos, pos); + return (halfTanSq >= args->_solidAngleHalfTan * args->_solidAngleHalfTan); + }; void LODManager::setOctreeSizeScale(float sizeScale) { @@ -325,3 +331,6 @@ float LODManager::getSolidAngleHalfTan() const { return getPerspectiveAccuracyAngleTan(_octreeSizeScale, _boundaryLevelAdjust); } +float LODManager::getSolidAngle() const { + return glm::degrees(2.0 * atan(getSolidAngleHalfTan())); +} diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 2ba933f91d..340292c579 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -70,6 +70,7 @@ class LODManager : public QObject, public Dependency { Q_PROPERTY(float worldDetailQuality READ getWorldDetailQuality WRITE setWorldDetailQuality NOTIFY worldDetailQualityChanged) Q_PROPERTY(float solidAngleHalfTan READ getSolidAngleHalfTan) + Q_PROPERTY(float solidAngle READ getSolidAngle) public: @@ -187,6 +188,7 @@ public: float getWorldDetailQuality() const; float getSolidAngleHalfTan() const; + float getSolidAngle() const; signals: diff --git a/libraries/octree/src/OctreeUtils.cpp b/libraries/octree/src/OctreeUtils.cpp index be8c194a95..7ed9c2ed3c 100644 --- a/libraries/octree/src/OctreeUtils.cpp +++ b/libraries/octree/src/OctreeUtils.cpp @@ -79,9 +79,3 @@ float getOrthographicAccuracySize(float octreeSizeScale, int boundaryLevelAdjust const float smallestSize = 0.01f; return (smallestSize * MAX_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT) / boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale); } - -bool isAngularSizeBigEnough(glm::vec3 position, const AACube& cube, float lodScaleFactor, float minDiameter) { - float distance = glm::distance(cube.calcCenter(), position) + MIN_VISIBLE_DISTANCE; - float angularDiameter = cube.getScale() / distance; - return angularDiameter > minDiameter * lodScaleFactor; -} diff --git a/libraries/octree/src/OctreeUtils.h b/libraries/octree/src/OctreeUtils.h index 4539a54dc3..eedbfe8bda 100644 --- a/libraries/octree/src/OctreeUtils.h +++ b/libraries/octree/src/OctreeUtils.h @@ -39,6 +39,4 @@ const float MIN_ELEMENT_ANGULAR_DIAMETER = 0.0043301f; // radians const float MIN_ENTITY_ANGULAR_DIAMETER = MIN_ELEMENT_ANGULAR_DIAMETER * SQRT_THREE; const float MIN_VISIBLE_DISTANCE = 0.0001f; // helps avoid divide-by-zero check -bool isAngularSizeBigEnough(glm::vec3 position, const AACube& cube, float lodScaleFactor, float minDiameter); - #endif // hifi_OctreeUtils_h diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index b073037e32..137ee07c96 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -62,8 +62,8 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterReceiverFilter, queryResolution).asVarying(); const auto shadowSelection = task.addJob("FetchShadowTree", fetchInput); - const auto selectionInputs = FetchSpatialSelection::Inputs(shadowSelection, shadowCasterReceiverFilter).asVarying(); - const auto shadowItems = task.addJob("FetchShadowSelection", selectionInputs); + const auto selectionInputs = FilterSpatialSelection::Inputs(shadowSelection, shadowCasterReceiverFilter).asVarying(); + const auto shadowItems = task.addJob("FilterShadowSelection", selectionInputs); // Cull objects that are not visible in camera view. Hopefully the cull functor only performs LOD culling, not // frustum culling or this will make shadow casters out of the camera frustum disappear. diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index b5f1718f6c..7d03f67d3f 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -445,7 +445,7 @@ void ApplyCullFunctorOnItemBounds::run(const RenderContextPointer& renderContext } } -void FetchSpatialSelection::run(const RenderContextPointer& renderContext, +void FilterSpatialSelection::run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems) { assert(renderContext->args); auto& scene = renderContext->_scene; diff --git a/libraries/render/src/render/CullTask.h b/libraries/render/src/render/CullTask.h index 2ef9e92eaa..99ca7abe6c 100644 --- a/libraries/render/src/render/CullTask.h +++ b/libraries/render/src/render/CullTask.h @@ -147,12 +147,12 @@ namespace render { }; - class FetchSpatialSelection { + class FilterSpatialSelection { public: using Inputs = render::VaryingSet2; - using JobModel = Job::ModelIO; + using JobModel = Job::ModelIO; - FetchSpatialSelection() {} + FilterSpatialSelection() {} void run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems); }; diff --git a/scripts/developer/utilities/render/lod.qml b/scripts/developer/utilities/render/lod.qml index 688cef142f..c08c089bad 100644 --- a/scripts/developer/utilities/render/lod.qml +++ b/scripts/developer/utilities/render/lod.qml @@ -160,15 +160,16 @@ Item { ] } PlotPerf { - title: "Solid Angle Half Tan" + title: "Solid Angle" height: parent.evalEvenHeight() object: LODManager valueScale: 1.0 - valueUnit: "" + valueUnit: "deg" + //valueNumDigits: 0 plots: [ { - prop: "solidAngleHalfTan", - label: "SAHT", + prop: "solidAngle", + label: "Solid Angle", color: "#9999FF" } ] From 63eb57c741c352e86caaa59515e203a3e8f6e13c Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 28 Aug 2018 08:58:25 -0700 Subject: [PATCH 06/24] Exploring PID again --- interface/src/LODManager.cpp | 73 +++++++++++++++++++--- interface/src/LODManager.h | 21 ++++++- libraries/render/src/render/Args.h | 2 + scripts/developer/utilities/render/lod.qml | 53 ++++++++++++++++ 4 files changed, 140 insertions(+), 9 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index cd692bccf0..91a547cf31 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -75,9 +75,41 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { return; } + auto Kp = _pid.x; + auto Ki = _pid.y; + auto Kd = _pid.z; + float oldOctreeSizeScale = _octreeSizeScale; + float oldSolidAngle = getSolidAngle(); + + float targetFPS = getLODDecreaseFPS(); + float targetPeriod = 1.0f / targetFPS; + float currentFPS = (float)MSECS_PER_SECOND / _avgRenderTime; + static uint64_t lastTime = usecTimestampNow(); uint64_t now = usecTimestampNow(); + auto dt = (float) ((now - lastTime) / double(USECS_PER_MSEC)); + if (dt < targetPeriod * _pid.w) return; + + float deltaFPS = currentFPS - getLODDecreaseFPS(); + + lastTime = now; + auto previous_error = 0.f; + auto integral = 0.f; + + auto error = getLODDecreaseFPS() - currentFPS; + integral = integral + error * dt; + auto derivative = (error - previous_error) / dt; + auto output = Kp * error + Ki * integral + Kd * derivative; + previous_error = error; + + auto newSolidAngle = std::max( 0.1f, std::min(output, 45.f)); + + auto halTan = glm::tan(glm::radians(newSolidAngle * 0.5f)); + + auto octreeSizeScale = TREE_SCALE * OCTREE_TO_MESH_RATIO / halTan; + _octreeSizeScale = octreeSizeScale; +/* if (currentFPS < getLODDecreaseFPS()) { if (now > _decreaseFPSExpiry) { _decreaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; @@ -123,7 +155,7 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { _increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; _decreaseFPSExpiry = _increaseFPSExpiry; } - +*/ if (oldOctreeSizeScale != _octreeSizeScale) { auto lodToolsDialog = DependencyManager::get()->getLodToolsDialog(); if (lodToolsDialog) { @@ -243,7 +275,7 @@ bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) { auto pos = args->getViewFrustum().getPosition() - bounds.calcCenter(); auto dim = bounds.getDimensions(); auto halfTanSq = 0.25f * glm::dot(dim, dim) / glm::dot(pos, pos); - return (halfTanSq >= args->_solidAngleHalfTan * args->_solidAngleHalfTan); + return (halfTanSq >= args->_solidAngleHalfTanSq); }; @@ -279,10 +311,10 @@ void LODManager::setWorldDetailQuality(float quality) { bool isHMDMode = qApp->isHMDMode(); float maxFPS = isHMDMode ? MAX_HMD_FPS : MAX_DESKTOP_FPS; - float desiredFPS = maxFPS - THRASHING_DIFFERENCE; + float desiredFPS = maxFPS /* - THRASHING_DIFFERENCE*/; if (!isLowestValue) { - float calculatedFPS = (maxFPS - (maxFPS * quality)) - THRASHING_DIFFERENCE; + float calculatedFPS = (maxFPS - (maxFPS * quality))/* - THRASHING_DIFFERENCE*/; desiredFPS = calculatedFPS < MIN_FPS ? MIN_FPS : calculatedFPS; } @@ -315,14 +347,15 @@ float LODManager::getWorldDetailQuality() const { increaseFPS = getDesktopLODDecreaseFPS(); } float maxFPS = inHMD ? MAX_HMD_FPS : MAX_DESKTOP_FPS; - float percentage = increaseFPS / maxFPS; + float percentage = 1.0 - increaseFPS / maxFPS; - if (percentage >= HIGH) { + if (percentage <= LOW) { return LOW; } - else if (percentage >= LOW) { + else if (percentage <= MEDIUM) { return MEDIUM; } + return HIGH; } @@ -334,3 +367,29 @@ float LODManager::getSolidAngleHalfTan() const { float LODManager::getSolidAngle() const { return glm::degrees(2.0 * atan(getSolidAngleHalfTan())); } + + +float LODManager::getPidKp() const { + return _pid.x; +} +float LODManager::getPidKi() const { + return _pid.y; +} +float LODManager::getPidKd() const { + return _pid.z; +} +float LODManager::getPidT() const { + return _pid.w; +} +void LODManager::setPidKp(float k) { + _pid.x = k; +} +void LODManager::setPidKi(float k) { + _pid.y = k; +} +void LODManager::setPidKd(float k) { + _pid.z = k; +} +void LODManager::setPidT(float t) { + _pid.w = t; +} diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 340292c579..2251281ae2 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -23,8 +23,8 @@ const float DEFAULT_DESKTOP_LOD_DOWN_FPS = 30.0f; const float DEFAULT_HMD_LOD_DOWN_FPS = 34.0f; const float DEFAULT_DESKTOP_MAX_RENDER_TIME = (float)MSECS_PER_SECOND / DEFAULT_DESKTOP_LOD_DOWN_FPS; // msec const float DEFAULT_HMD_MAX_RENDER_TIME = (float)MSECS_PER_SECOND / DEFAULT_HMD_LOD_DOWN_FPS; // msec -const float MAX_LIKELY_DESKTOP_FPS = 59.0f; // this is essentially, V-synch - 1 fps -const float MAX_LIKELY_HMD_FPS = 74.0f; // this is essentially, V-synch - 1 fps +const float MAX_LIKELY_DESKTOP_FPS = 61.0f; // this is essentially, V-synch - 1 fps +const float MAX_LIKELY_HMD_FPS = 91.0f; // this is essentially, V-synch - 1 fps const float INCREASE_LOD_GAP_FPS = 10.0f; // fps // The default value DEFAULT_OCTREE_SIZE_SCALE means you can be 400 meters away from a 1 meter object in order to see it (which is ~20:20 vision). @@ -72,6 +72,12 @@ class LODManager : public QObject, public Dependency { Q_PROPERTY(float solidAngleHalfTan READ getSolidAngleHalfTan) Q_PROPERTY(float solidAngle READ getSolidAngle) + Q_PROPERTY(float pidKp READ getPidKp WRITE setPidKp) + Q_PROPERTY(float pidKi READ getPidKi WRITE setPidKi) + Q_PROPERTY(float pidKd READ getPidKd WRITE setPidKd) + Q_PROPERTY(float pidT READ getPidT WRITE setPidT) + + public: /**jsdoc @@ -190,6 +196,15 @@ public: float getSolidAngleHalfTan() const; float getSolidAngle() const; + float getPidKp() const; + float getPidKi() const; + float getPidKd() const; + float getPidT() const; + void setPidKp(float k); + void setPidKi(float k); + void setPidKd(float k); + void setPidT(float t); + signals: /**jsdoc @@ -222,6 +237,8 @@ private: float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE; int _boundaryLevelAdjust = 0; + glm::vec4 _pid{ 0.1f, 0.0f, 0.0f, 3.0f }; + uint64_t _decreaseFPSExpiry { 0 }; uint64_t _increaseFPSExpiry { 0 }; }; diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index a46b914826..589945e9c7 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -81,6 +81,7 @@ namespace render { _context(context), _sizeScale(sizeScale), _solidAngleHalfTan(solidAngleHalfTan), + _solidAngleHalfTanSq(solidAngleHalfTan * solidAngleHalfTan), _boundaryLevelAdjust(boundaryLevelAdjust), _renderMode(renderMode), _displayMode(displayMode), @@ -111,6 +112,7 @@ namespace render { float _sizeScale { 1.0f }; int _boundaryLevelAdjust { 0 }; float _solidAngleHalfTan{ 0.1f }; + float _solidAngleHalfTanSq{ _solidAngleHalfTan * _solidAngleHalfTan }; RenderMode _renderMode { DEFAULT_RENDER_MODE }; DisplayMode _displayMode { MONO }; diff --git a/scripts/developer/utilities/render/lod.qml b/scripts/developer/utilities/render/lod.qml index c08c089bad..742e8c0dc1 100644 --- a/scripts/developer/utilities/render/lod.qml +++ b/scripts/developer/utilities/render/lod.qml @@ -78,6 +78,59 @@ Item { anchors.left: parent.left anchors.right: parent.right } + + RichSlider { + visible: LODManager.automaticLODAdjust + showLabel: true + label: "LOD PID Kp" + valueVar: LODManager["pidKp"] + valueVarSetter: (function (v) { LODManager["pidKp"] = v }) + max: 1.0 + min: 0.0 + integral: false + + anchors.left: parent.left + anchors.right: parent.right + } + RichSlider { + visible: LODManager.automaticLODAdjust + showLabel: true + label: "LOD PID Ki" + valueVar: LODManager["pidKi"] + valueVarSetter: (function (v) { LODManager["pidKi"] = v }) + max: 1.0 + min: 0.0 + integral: false + + anchors.left: parent.left + anchors.right: parent.right + } + RichSlider { + visible: LODManager.automaticLODAdjust + showLabel: true + label: "LOD PID Kd" + valueVar: LODManager["pidKd"] + valueVarSetter: (function (v) { LODManager["pidKd"] = v }) + max: 1.0 + min: 0.0 + integral: false + + anchors.left: parent.left + anchors.right: parent.right + } + RichSlider { + visible: LODManager.automaticLODAdjust + showLabel: true + label: "LOD PID Num T" + valueVar: LODManager["pidT"] + valueVarSetter: (function (v) { LODManager["pidT"] = v }) + max: 5.0 + min: 0.0 + integral: false + + anchors.left: parent.left + anchors.right: parent.right + } } Column { From 7dfdc796448e23c5f231a3c319fe64c94fa1abdb Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 28 Aug 2018 12:21:15 -0700 Subject: [PATCH 07/24] Picking pid values --- interface/src/LODManager.cpp | 5 ++++- interface/src/LODManager.h | 2 +- scripts/developer/utilities/render/lod.qml | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 91a547cf31..411e0156b5 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -103,7 +103,10 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { auto output = Kp * error + Ki * integral + Kd * derivative; previous_error = error; - auto newSolidAngle = std::max( 0.1f, std::min(output, 45.f)); + + auto newSolidAngle = oldSolidAngle + output; + + newSolidAngle = std::max( 0.5f, std::min(newSolidAngle, 90.f)); auto halTan = glm::tan(glm::radians(newSolidAngle * 0.5f)); diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 2251281ae2..b2e324a820 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -237,7 +237,7 @@ private: float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE; int _boundaryLevelAdjust = 0; - glm::vec4 _pid{ 0.1f, 0.0f, 0.0f, 3.0f }; + glm::vec4 _pid{ 0.06f, 0.005f, 0.01f, 4.0f }; uint64_t _decreaseFPSExpiry { 0 }; uint64_t _increaseFPSExpiry { 0 }; diff --git a/scripts/developer/utilities/render/lod.qml b/scripts/developer/utilities/render/lod.qml index 742e8c0dc1..1ca9b68de2 100644 --- a/scripts/developer/utilities/render/lod.qml +++ b/scripts/developer/utilities/render/lod.qml @@ -98,7 +98,7 @@ Item { label: "LOD PID Ki" valueVar: LODManager["pidKi"] valueVarSetter: (function (v) { LODManager["pidKi"] = v }) - max: 1.0 + max: 0.02 min: 0.0 integral: false @@ -111,7 +111,7 @@ Item { label: "LOD PID Kd" valueVar: LODManager["pidKd"] valueVarSetter: (function (v) { LODManager["pidKd"] = v }) - max: 1.0 + max: 0.1 min: 0.0 integral: false From 0da22db837d58c419ca0d58497c96164706b293c Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 28 Aug 2018 16:05:57 -0700 Subject: [PATCH 08/24] Picking pid values --- interface/src/Application.cpp | 2 +- interface/src/LODManager.cpp | 86 +++++++++++++------ interface/src/LODManager.h | 23 +++-- .../render/configSlider/RichSlider.qml | 3 +- scripts/developer/utilities/render/lod.qml | 52 ++++++----- 5 files changed, 112 insertions(+), 54 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 817c6b1e43..e7b17b3d69 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5987,7 +5987,7 @@ void Application::updateRenderArgs(float deltaTime) { _viewFrustum.calculate(); } appRenderArgs._renderArgs = RenderArgs(_gpuContext, lodManager->getOctreeSizeScale(), - lodManager->getBoundaryLevelAdjust(), lodManager->getSolidAngleHalfTan(), RenderArgs::DEFAULT_RENDER_MODE, + lodManager->getBoundaryLevelAdjust(), lodManager->getLODAngleHalfTan(), RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); appRenderArgs._renderArgs._scene = getMain3DScene(); diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 411e0156b5..7f99e74a2a 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -75,12 +75,8 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { return; } - auto Kp = _pid.x; - auto Ki = _pid.y; - auto Kd = _pid.z; - float oldOctreeSizeScale = _octreeSizeScale; - float oldSolidAngle = getSolidAngle(); + float oldSolidAngle = getLODAngleDeg(); float targetFPS = getLODDecreaseFPS(); float targetPeriod = 1.0f / targetFPS; @@ -89,29 +85,44 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { static uint64_t lastTime = usecTimestampNow(); uint64_t now = usecTimestampNow(); auto dt = (float) ((now - lastTime) / double(USECS_PER_MSEC)); - if (dt < targetPeriod * _pid.w) return; + if (dt < targetPeriod * _pidCoefs.w) return; float deltaFPS = currentFPS - getLODDecreaseFPS(); lastTime = now; - auto previous_error = 0.f; - auto integral = 0.f; + auto previous_error = _pidHistory.x; + auto previous_integral = _pidHistory.y; auto error = getLODDecreaseFPS() - currentFPS; - integral = integral + error * dt; + auto integral = previous_integral + error * dt; auto derivative = (error - previous_error) / dt; - auto output = Kp * error + Ki * integral + Kd * derivative; - previous_error = error; + _pidHistory.x = error; + _pidHistory.y = integral; + _pidHistory.z = derivative; + + auto Kp = _pidCoefs.x; + auto Ki = _pidCoefs.y; + auto Kd = _pidCoefs.z; + + _pidOutputs.x = Kp * error; + _pidOutputs.y = Ki * integral; + _pidOutputs.z = Kd * derivative; + + auto output = _pidOutputs.x + _pidOutputs.y + _pidOutputs.z; + + _pidOutputs.w = output; auto newSolidAngle = oldSolidAngle + output; - newSolidAngle = std::max( 0.5f, std::min(newSolidAngle, 90.f)); + setLODAngleDeg(newSolidAngle); - auto halTan = glm::tan(glm::radians(newSolidAngle * 0.5f)); + //newSolidAngle = std::max( 0.5f, std::min(newSolidAngle, 90.f)); - auto octreeSizeScale = TREE_SCALE * OCTREE_TO_MESH_RATIO / halTan; - _octreeSizeScale = octreeSizeScale; + //auto halTan = glm::tan(glm::radians(newSolidAngle * 0.5f)); + + //auto octreeSizeScale = TREE_SCALE * OCTREE_TO_MESH_RATIO / halTan; + // _octreeSizeScale = octreeSizeScale; /* if (currentFPS < getLODDecreaseFPS()) { if (now > _decreaseFPSExpiry) { @@ -363,36 +374,57 @@ float LODManager::getWorldDetailQuality() const { } -float LODManager::getSolidAngleHalfTan() const { +float LODManager::getLODAngleHalfTan() const { return getPerspectiveAccuracyAngleTan(_octreeSizeScale, _boundaryLevelAdjust); } - -float LODManager::getSolidAngle() const { - return glm::degrees(2.0 * atan(getSolidAngleHalfTan())); +float LODManager::getLODAngle() const { + return 2.0f * atan(getLODAngleHalfTan()); +} +float LODManager::getLODAngleDeg() const { + return glm::degrees(getLODAngle()); } +void LODManager::setLODAngleDeg(float lodAngle) { + auto newSolidAngle = std::max(0.5f, std::min(lodAngle, 90.f)); + auto halTan = glm::tan(glm::radians(newSolidAngle * 0.5f)); + auto octreeSizeScale = TREE_SCALE * OCTREE_TO_MESH_RATIO / halTan; + setOctreeSizeScale(octreeSizeScale); +} float LODManager::getPidKp() const { - return _pid.x; + return _pidCoefs.x; } float LODManager::getPidKi() const { - return _pid.y; + return _pidCoefs.y; } float LODManager::getPidKd() const { - return _pid.z; + return _pidCoefs.z; } float LODManager::getPidT() const { - return _pid.w; + return _pidCoefs.w; } void LODManager::setPidKp(float k) { - _pid.x = k; + _pidCoefs.x = k; } void LODManager::setPidKi(float k) { - _pid.y = k; + _pidCoefs.y = k; } void LODManager::setPidKd(float k) { - _pid.z = k; + _pidCoefs.z = k; } void LODManager::setPidT(float t) { - _pid.w = t; + _pidCoefs.w = t; } + +float LODManager::getPidOp() const { + return _pidOutputs.x; +} +float LODManager::getPidOi() const { + return _pidOutputs.y; +} +float LODManager::getPidOd() const { + return _pidOutputs.z; +} +float LODManager::getPidO() const { + return _pidOutputs.w; +} \ No newline at end of file diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index b2e324a820..e4ca9912fb 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -69,14 +69,17 @@ class LODManager : public QObject, public Dependency { Q_PROPERTY(float worldDetailQuality READ getWorldDetailQuality WRITE setWorldDetailQuality NOTIFY worldDetailQualityChanged) - Q_PROPERTY(float solidAngleHalfTan READ getSolidAngleHalfTan) - Q_PROPERTY(float solidAngle READ getSolidAngle) + Q_PROPERTY(float lodAngleDeg READ getLODAngleDeg WRITE setLODAngleDeg) Q_PROPERTY(float pidKp READ getPidKp WRITE setPidKp) Q_PROPERTY(float pidKi READ getPidKi WRITE setPidKi) Q_PROPERTY(float pidKd READ getPidKd WRITE setPidKd) Q_PROPERTY(float pidT READ getPidT WRITE setPidT) + Q_PROPERTY(float pidOp READ getPidOp) + Q_PROPERTY(float pidOi READ getPidOi) + Q_PROPERTY(float pidOd READ getPidOd) + Q_PROPERTY(float pidO READ getPidO) public: @@ -187,14 +190,17 @@ public: float getAverageRenderTime() const { return _avgRenderTime; }; float getMaxTheoreticalFPS() const { return (float)MSECS_PER_SECOND / _avgRenderTime; }; + float getLODLevel() const; void setLODLevel(float level); void setWorldDetailQuality(float quality); float getWorldDetailQuality() const; - float getSolidAngleHalfTan() const; - float getSolidAngle() const; + float getLODAngleDeg() const; + void setLODAngleDeg(float lodAngle); + float getLODAngleHalfTan() const; + float getLODAngle() const; float getPidKp() const; float getPidKi() const; @@ -205,6 +211,11 @@ public: void setPidKd(float k); void setPidT(float t); + float getPidOp() const; + float getPidOi() const; + float getPidOd() const; + float getPidO() const; + signals: /**jsdoc @@ -237,7 +248,9 @@ private: float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE; int _boundaryLevelAdjust = 0; - glm::vec4 _pid{ 0.06f, 0.005f, 0.01f, 4.0f }; + glm::vec4 _pidCoefs{ 0.1526f, 0.00000015f, 15.f, 4.0f }; + glm::vec4 _pidHistory{ 0.0f }; + glm::vec4 _pidOutputs{ 0.0f }; uint64_t _decreaseFPSExpiry { 0 }; uint64_t _increaseFPSExpiry { 0 }; diff --git a/scripts/developer/utilities/render/configSlider/RichSlider.qml b/scripts/developer/utilities/render/configSlider/RichSlider.qml index 1613cac1b4..01b14f3d48 100644 --- a/scripts/developer/utilities/render/configSlider/RichSlider.qml +++ b/scripts/developer/utilities/render/configSlider/RichSlider.qml @@ -29,6 +29,7 @@ Item { property var labelAreaWidthScale: 0.5 property bool integral: false + property var numDigits: 2 property var valueVarSetter: defaultSet property alias valueVar : sliderControl.value @@ -71,7 +72,7 @@ Item { HifiControls.Label { id: labelValue enabled: root.showValue - text: sliderControl.value.toFixed(root.integral ? 0 : 2) + text: sliderControl.value.toFixed(root.integral ? 0 : root.numDigits) anchors.right: labelControl.right anchors.rightMargin: 5 anchors.verticalCenter: root.verticalCenter diff --git a/scripts/developer/utilities/render/lod.qml b/scripts/developer/utilities/render/lod.qml index 1ca9b68de2..90e7573fda 100644 --- a/scripts/developer/utilities/render/lod.qml +++ b/scripts/developer/utilities/render/lod.qml @@ -68,11 +68,11 @@ Item { RichSlider { visible: !LODManager.automaticLODAdjust showLabel: true - label: "LOD Level" - valueVar: LODManager["lodLevel"] - valueVarSetter: (function (v) { LODManager["lodLevel"] = v }) - max: 1.0 - min: 0.0 + label: "LOD Angle [deg]" + valueVar: LODManager["lodAngleDeg"] + valueVarSetter: (function (v) { LODManager["lodAngleDeg"] = v }) + max: 90.0 + min: 0.5 integral: false anchors.left: parent.left @@ -85,9 +85,10 @@ Item { label: "LOD PID Kp" valueVar: LODManager["pidKp"] valueVarSetter: (function (v) { LODManager["pidKp"] = v }) - max: 1.0 + max: 0.2 min: 0.0 integral: false + numDigits: 3 anchors.left: parent.left anchors.right: parent.right @@ -98,9 +99,10 @@ Item { label: "LOD PID Ki" valueVar: LODManager["pidKi"] valueVarSetter: (function (v) { LODManager["pidKi"] = v }) - max: 0.02 + max: 0.000005 min: 0.0 integral: false + numDigits: 8 anchors.left: parent.left anchors.right: parent.right @@ -111,9 +113,10 @@ Item { label: "LOD PID Kd" valueVar: LODManager["pidKd"] valueVarSetter: (function (v) { LODManager["pidKd"] = v }) - max: 0.1 + max: 10.0 min: 0.0 integral: false + numDigits: 3 anchors.left: parent.left anchors.right: parent.right @@ -124,9 +127,9 @@ Item { label: "LOD PID Num T" valueVar: LODManager["pidT"] valueVarSetter: (function (v) { LODManager["pidT"] = v }) - max: 5.0 + max: 10.0 min: 0.0 - integral: false + integral: true anchors.left: parent.left anchors.right: parent.right @@ -199,34 +202,43 @@ Item { ] } PlotPerf { - title: "LOD" + title: "LOD Angle" height: parent.evalEvenHeight() object: LODManager - valueScale: 0.1 - valueUnit: "" + valueScale: 1.0 + valueUnit: "deg" plots: [ { - prop: "lodLevel", - label: "LOD", + prop: "lodAngleDeg", + label: "LOD Angle", color: "#9999FF" } ] } PlotPerf { - title: "Solid Angle" + title: "PID Output" height: parent.evalEvenHeight() object: LODManager valueScale: 1.0 valueUnit: "deg" - //valueNumDigits: 0 plots: [ { - prop: "solidAngle", - label: "Solid Angle", + prop: "pidOp", + label: "Op", color: "#9999FF" + }, + { + prop: "pidOi", + label: "Oi", + color: "#FFFFFF" + }, + { + prop: "pidOd", + label: "Od", + color: "#FF6666" } ] - } + } Separator { id: bottomLine } From 37b4cf6223c2a8ce9cc20b99a4f014d53d8480dc Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 28 Aug 2018 17:39:35 -0700 Subject: [PATCH 09/24] Picking pid values --- interface/src/Application.cpp | 3 ++- interface/src/LODManager.cpp | 12 +++++---- interface/src/LODManager.h | 8 ++++-- .../utilities/lib/plotperf/PlotPerf.qml | 27 ++++++++++++++++++- scripts/developer/utilities/render/lod.qml | 2 +- 5 files changed, 42 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e7b17b3d69..fc62b01ca6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5028,8 +5028,9 @@ void Application::updateLOD(float deltaTime) const { float presentTime = getActiveDisplayPlugin()->getAveragePresentTime(); float engineRunTime = (float)(_renderEngine->getConfiguration().get()->getCPURunTime()); float gpuTime = getGPUContext()->getFrameTimerGPUAverage(); + float batchTime = getGPUContext()->getFrameTimerBatchAverage(); auto lodManager = DependencyManager::get(); - lodManager->setRenderTimes(presentTime, engineRunTime, gpuTime); + lodManager->setRenderTimes(presentTime, engineRunTime, batchTime, gpuTime); lodManager->autoAdjustLOD(deltaTime); } else { DependencyManager::get()->resetLODAdjust(); diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 7f99e74a2a..a32f3472ab 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -58,18 +58,21 @@ const uint64_t LOD_AUTO_ADJUST_PERIOD = 4 * (uint64_t)(LOD_ADJUST_RUNNING_AVG_TI const float LOD_AUTO_ADJUST_DECREMENT_FACTOR = 0.8f; const float LOD_AUTO_ADJUST_INCREMENT_FACTOR = 1.2f; -void LODManager::setRenderTimes(float presentTime, float engineRunTime, float gpuTime) { +void LODManager::setRenderTimes(float presentTime, float engineRunTime, float batchTime, float gpuTime) { _presentTime = presentTime; _engineRunTime = engineRunTime; + _batchTime = batchTime; _gpuTime = gpuTime; } void LODManager::autoAdjustLOD(float realTimeDelta) { + // float maxRenderTime = glm::max(glm::max(_presentTime, _engineRunTime), _gpuTime); float maxRenderTime = glm::max(glm::max(_presentTime, _engineRunTime), _gpuTime); // compute time-weighted running average maxRenderTime // Note: we MUST clamp the blend to 1.0 for stability float blend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE) ? realTimeDelta / LOD_ADJUST_RUNNING_AVG_TIMESCALE : 1.0f; _avgRenderTime = (1.0f - blend) * _avgRenderTime + blend * maxRenderTime; // msec + // _avgRenderTime = maxRenderTime; if (!_automaticLODAdjust || _avgRenderTime == 0.0f) { // early exit return; @@ -78,7 +81,7 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { float oldOctreeSizeScale = _octreeSizeScale; float oldSolidAngle = getLODAngleDeg(); - float targetFPS = getLODDecreaseFPS(); + float targetFPS = 0.5 * (getLODDecreaseFPS() + getLODIncreaseFPS()); float targetPeriod = 1.0f / targetFPS; float currentFPS = (float)MSECS_PER_SECOND / _avgRenderTime; @@ -87,13 +90,12 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { auto dt = (float) ((now - lastTime) / double(USECS_PER_MSEC)); if (dt < targetPeriod * _pidCoefs.w) return; - float deltaFPS = currentFPS - getLODDecreaseFPS(); - lastTime = now; auto previous_error = _pidHistory.x; auto previous_integral = _pidHistory.y; - auto error = getLODDecreaseFPS() - currentFPS; + auto error = (targetFPS - currentFPS) / targetFPS; + error = glm::clamp(error, -1.0f, 1.0f); auto integral = previous_integral + error * dt; auto derivative = (error - previous_error) / dt; diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index e4ca9912fb..74075f2400 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -59,6 +59,7 @@ class LODManager : public QObject, public Dependency { Q_PROPERTY(float presentTime READ getPresentTime) Q_PROPERTY(float engineRunTime READ getEngineRunTime) + Q_PROPERTY(float batchTime READ getBatchTime) Q_PROPERTY(float gpuTime READ getGPUTime) Q_PROPERTY(float avgRenderTime READ getAverageRenderTime) Q_PROPERTY(float fps READ getMaxTheoreticalFPS) @@ -178,10 +179,11 @@ public: float getPresentTime() const { return _presentTime; } float getEngineRunTime() const { return _engineRunTime; } + float getBatchTime() const { return _batchTime; } float getGPUTime() const { return _gpuTime; } static bool shouldRender(const RenderArgs* args, const AABox& bounds); - void setRenderTimes(float presentTime, float engineRunTime, float gpuTime); + void setRenderTimes(float presentTime, float engineRunTime, float batchTime, float gpuTime); void autoAdjustLOD(float realTimeDelta); void loadSettings(); @@ -240,7 +242,9 @@ private: bool _automaticLODAdjust = true; float _presentTime { 0.0f }; // msec float _engineRunTime { 0.0f }; // msec + float _batchTime{ 0.0f }; // msec float _gpuTime { 0.0f }; // msec + float _avgRenderTime { 0.0f }; // msec float _desktopMaxRenderTime { DEFAULT_DESKTOP_MAX_RENDER_TIME }; float _hmdMaxRenderTime { DEFAULT_HMD_MAX_RENDER_TIME }; @@ -248,7 +252,7 @@ private: float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE; int _boundaryLevelAdjust = 0; - glm::vec4 _pidCoefs{ 0.1526f, 0.00000015f, 15.f, 4.0f }; + glm::vec4 _pidCoefs{ 4.0f, 0.0000000f, 0.f, 4.0f }; glm::vec4 _pidHistory{ 0.0f }; glm::vec4 _pidOutputs{ 0.0f }; diff --git a/scripts/developer/utilities/lib/plotperf/PlotPerf.qml b/scripts/developer/utilities/lib/plotperf/PlotPerf.qml index 916c9cae55..99ff5f712e 100644 --- a/scripts/developer/utilities/lib/plotperf/PlotPerf.qml +++ b/scripts/developer/utilities/lib/plotperf/PlotPerf.qml @@ -48,6 +48,7 @@ Item { property var valueMax : 1 + property var valueMin : 0 property var _values property var tick : 0 @@ -90,6 +91,11 @@ Item { _values[i].valueMax *= 0.25 // Fast reduce the max value as we click } } + function resetMin() { + for (var i = 0; i < _values.length; i++) { + _values[i].valueMin *= 0.25 // Fast reduce the min value as we click + } + } function pullFreshValues() { // Wait until values are created to begin pulling @@ -99,6 +105,7 @@ Item { tick++; var currentValueMax = 0 + var currentValueMin = 0 for (var i = 0; i < _values.length; i++) { var currentVal = (+_values[i].object[_values[i].value]) * _values[i].scale; @@ -112,26 +119,44 @@ Item { _values[i].valueMax *= 0.99 _values[i].numSamplesConstantMax = 0 } + if (lostValue <= _values[i].valueMin) { + _values[i].valueMin *= 0.99 + _values[i].numSamplesConstantMin = 0 + } } if (_values[i].valueMax < currentVal) { _values[i].valueMax = currentVal; _values[i].numSamplesConstantMax = 0 } + if (_values[i].valueMin < currentVal) { + _values[i].valueMin = currentVal; + _values[i].numSamplesConstantMin = 0 + } if (_values[i].numSamplesConstantMax > VALUE_HISTORY_SIZE) { _values[i].numSamplesConstantMax = 0 _values[i].valueMax *= 0.95 // lower slowly the current max if no new above max since a while } - + if (_values[i].numSamplesConstantMin > VALUE_HISTORY_SIZE) { + _values[i].numSamplesConstantMin = 0 + _values[i].valueMin *= 0.95 // lower slowly the current min if no new above min since a while + } + if (currentValueMax < _values[i].valueMax) { currentValueMax = _values[i].valueMax } + if (currentValueMin < _values[i].valueMin) { + currentValueMin = _values[i].valueMin + } } if ((valueMax < currentValueMax) || (tick % VALUE_HISTORY_SIZE == 0)) { valueMax = currentValueMax; } + if ((valueMin < currentValueMin) || (tick % VALUE_HISTORY_SIZE == 0)) { + valueMin = currentValueMin; + } mycanvas.requestPaint() } diff --git a/scripts/developer/utilities/render/lod.qml b/scripts/developer/utilities/render/lod.qml index 90e7573fda..fe284fec93 100644 --- a/scripts/developer/utilities/render/lod.qml +++ b/scripts/developer/utilities/render/lod.qml @@ -85,7 +85,7 @@ Item { label: "LOD PID Kp" valueVar: LODManager["pidKp"] valueVarSetter: (function (v) { LODManager["pidKp"] = v }) - max: 0.2 + max: 2.0 min: 0.0 integral: false numDigits: 3 From ed4dbaa4c71de483334c26808053ec98d59955e5 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 29 Aug 2018 16:07:30 -0700 Subject: [PATCH 10/24] Refining the plot widget to be able to represent negative values --- interface/src/LODManager.cpp | 16 +++++- interface/src/LODManager.h | 12 +++- .../utilities/lib/plotperf/PlotPerf.qml | 56 ++++++++++++++++--- scripts/developer/utilities/render/lod.qml | 16 +++++- 4 files changed, 87 insertions(+), 13 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index a32f3472ab..ce674f7295 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -72,6 +72,11 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { // Note: we MUST clamp the blend to 1.0 for stability float blend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE) ? realTimeDelta / LOD_ADJUST_RUNNING_AVG_TIMESCALE : 1.0f; _avgRenderTime = (1.0f - blend) * _avgRenderTime + blend * maxRenderTime; // msec + + float smoothBlend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE * _pidCoefs.w) ? realTimeDelta / (LOD_ADJUST_RUNNING_AVG_TIMESCALE * _pidCoefs.w) : 1.0f; + _smoothRenderTime = (1.0f - smoothBlend) * _smoothRenderTime + smoothBlend * maxRenderTime; // msec + + // _avgRenderTime = maxRenderTime; if (!_automaticLODAdjust || _avgRenderTime == 0.0f) { // early exit @@ -82,13 +87,17 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { float oldSolidAngle = getLODAngleDeg(); float targetFPS = 0.5 * (getLODDecreaseFPS() + getLODIncreaseFPS()); + // float targetFPS = (getLODDecreaseFPS()); float targetPeriod = 1.0f / targetFPS; float currentFPS = (float)MSECS_PER_SECOND / _avgRenderTime; + static uint64_t lastTime = usecTimestampNow(); + uint64_t now = usecTimestampNow(); auto dt = (float) ((now - lastTime) / double(USECS_PER_MSEC)); - if (dt < targetPeriod * _pidCoefs.w) return; + // if (dt < targetPeriod * _pidCoefs.w) return; + dt = realTimeDelta; lastTime = now; auto previous_error = _pidHistory.x; @@ -96,7 +105,12 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { auto error = (targetFPS - currentFPS) / targetFPS; error = glm::clamp(error, -1.0f, 1.0f); + if (error <= 0.0f) { + // error = error * 2.0f; + } auto integral = previous_integral + error * dt; + glm::clamp(integral, -1.0f, 1.0f); + auto derivative = (error - previous_error) / dt; _pidHistory.x = error; diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 74075f2400..167533a236 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -61,8 +61,13 @@ class LODManager : public QObject, public Dependency { Q_PROPERTY(float engineRunTime READ getEngineRunTime) Q_PROPERTY(float batchTime READ getBatchTime) Q_PROPERTY(float gpuTime READ getGPUTime) + Q_PROPERTY(float avgRenderTime READ getAverageRenderTime) Q_PROPERTY(float fps READ getMaxTheoreticalFPS) + + Q_PROPERTY(float smoothRenderTime READ getSmoothRenderTime) + Q_PROPERTY(float smoothFPS READ getSmoothFPS) + Q_PROPERTY(float lodLevel READ getLODLevel WRITE setLODLevel NOTIFY LODChanged) Q_PROPERTY(float lodDecreaseFPS READ getLODDecreaseFPS) Q_PROPERTY(float lodIncreaseFPS READ getLODIncreaseFPS) @@ -193,6 +198,10 @@ public: float getAverageRenderTime() const { return _avgRenderTime; }; float getMaxTheoreticalFPS() const { return (float)MSECS_PER_SECOND / _avgRenderTime; }; + float getSmoothRenderTime() const { return _smoothRenderTime; }; + float getSmoothFPS() const { return (float)MSECS_PER_SECOND / _smoothRenderTime; }; + + float getLODLevel() const; void setLODLevel(float level); @@ -246,13 +255,14 @@ private: float _gpuTime { 0.0f }; // msec float _avgRenderTime { 0.0f }; // msec + float _smoothRenderTime{ 0.0f }; float _desktopMaxRenderTime { DEFAULT_DESKTOP_MAX_RENDER_TIME }; float _hmdMaxRenderTime { DEFAULT_HMD_MAX_RENDER_TIME }; float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE; int _boundaryLevelAdjust = 0; - glm::vec4 _pidCoefs{ 4.0f, 0.0000000f, 0.f, 4.0f }; + glm::vec4 _pidCoefs{ 1.0f, 0.0000000f, 0.f, 8.0f }; glm::vec4 _pidHistory{ 0.0f }; glm::vec4 _pidOutputs{ 0.0f }; diff --git a/scripts/developer/utilities/lib/plotperf/PlotPerf.qml b/scripts/developer/utilities/lib/plotperf/PlotPerf.qml index 99ff5f712e..46056be5fd 100644 --- a/scripts/developer/utilities/lib/plotperf/PlotPerf.qml +++ b/scripts/developer/utilities/lib/plotperf/PlotPerf.qml @@ -50,6 +50,10 @@ Item { property var valueMax : 1 property var valueMin : 0 + property var displayMinAt0 : true + property var _displayMaxValue : 1 + property var _displayMinValue : 0 + property var _values property var tick : 0 @@ -72,7 +76,9 @@ Item { value: value, fromBinding: isBinding, valueMax: 1, + valueMin: 0, numSamplesConstantMax: 0, + numSamplesConstantMin: 0, valueHistory: new Array(), label: (plot["label"] !== undefined ? plot["label"] : ""), color: (plot["color"] !== undefined ? plot["color"] : "white"), @@ -129,7 +135,7 @@ Item { _values[i].valueMax = currentVal; _values[i].numSamplesConstantMax = 0 } - if (_values[i].valueMin < currentVal) { + if (_values[i].valueMin > currentVal) { _values[i].valueMin = currentVal; _values[i].numSamplesConstantMin = 0 } @@ -146,7 +152,7 @@ Item { if (currentValueMax < _values[i].valueMax) { currentValueMax = _values[i].valueMax } - if (currentValueMin < _values[i].valueMin) { + if (currentValueMin > _values[i].valueMin) { currentValueMin = _values[i].valueMin } } @@ -154,9 +160,12 @@ Item { if ((valueMax < currentValueMax) || (tick % VALUE_HISTORY_SIZE == 0)) { valueMax = currentValueMax; } - if ((valueMin < currentValueMin) || (tick % VALUE_HISTORY_SIZE == 0)) { + if ((valueMin > currentValueMin) || (tick % VALUE_HISTORY_SIZE == 0)) { valueMin = currentValueMin; } + _displayMaxValue = valueMax; + _displayMinValue = ( displayMinAt0 ? 0 : valueMin ) + mycanvas.requestPaint() } @@ -177,10 +186,10 @@ Item { } function pixelFromVal(val, valScale) { - return lineHeight + (height - lineHeight) * (1 - (0.9) * val / valueMax); + return lineHeight + (height - lineHeight) * (1 - (0.9) * (val - _displayMinValue) / (_displayMaxValue - _displayMinValue)); } function valueFromPixel(pixY) { - return ((pixY - lineHeight) / (height - lineHeight) - 1) * valueMax / (-0.9); + return _displayMinValue + (((pixY - lineHeight) / (height - lineHeight) - 1) * (_displayMaxValue - _displayMinValue) / (-0.9)); } function plotValueHistory(ctx, valHistory, color) { var widthStep= width / (valHistory.length - 1); @@ -208,8 +217,10 @@ Item { function displayTitle(ctx, text, maxVal) { ctx.fillStyle = "grey"; ctx.textAlign = "right"; - ctx.fillText(displayValue(valueFromPixel(lineHeight), root.valueUnit), width, lineHeight); + ctx.fillText("max" + displayValue(_displayMaxValue, root.valueUnit), width, pixelFromVal(_displayMaxValue)); + ctx.fillText("min" + displayValue(_displayMinValue, root.valueUnit), width, pixelFromVal(_displayMinValue)); + ctx.fillStyle = "white"; ctx.textAlign = "left"; ctx.fillText(text, 0, lineHeight); @@ -218,15 +229,39 @@ Item { ctx.fillStyle = Qt.rgba(0, 0, 0, root.backgroundOpacity); ctx.fillRect(0, 0, width, height); - ctx.strokeStyle= "grey"; + /* ctx.strokeStyle= "grey"; ctx.lineWidth="2"; ctx.beginPath(); ctx.moveTo(0, lineHeight + 1); - ctx.lineTo(width, lineHeight + 1); + ctx.lineTo(width, lineHeight + 1); ctx.moveTo(0, height); ctx.lineTo(width, height); + ctx.stroke();*/ + } + + function displayMaxZeroMin(ctx) { + var maxY = pixelFromVal(_displayMaxValue); + + ctx.strokeStyle= "LightSlateGray"; + ctx.lineWidth="1"; + // ctx.strokeStyle= "grey"; + ctx.beginPath(); + ctx.moveTo(0, maxY); + ctx.lineTo(width, maxY); ctx.stroke(); + + if (_displayMinValue != 0) { + var zeroY = pixelFromVal(0); + var minY = pixelFromVal(_displayMinValue); + // ctx.strokeStyle= "DarkRed"; + ctx.beginPath(); + ctx.moveTo(0, zeroY); + ctx.lineTo(width, zeroY); + ctx.moveTo(0, minY); + ctx.lineTo(width, minY); + ctx.stroke(); + } } var ctx = getContext("2d"); @@ -240,7 +275,9 @@ Item { displayValueLegend(ctx, _values[i], i) } - displayTitle(ctx, title, valueMax) + displayMaxZeroMin(ctx); + + displayTitle(ctx, title, _displayMaxValue) } } @@ -250,6 +287,7 @@ Item { onClicked: { resetMax(); + resetMin(); } } } diff --git a/scripts/developer/utilities/render/lod.qml b/scripts/developer/utilities/render/lod.qml index fe284fec93..d0562e1020 100644 --- a/scripts/developer/utilities/render/lod.qml +++ b/scripts/developer/utilities/render/lod.qml @@ -99,7 +99,7 @@ Item { label: "LOD PID Ki" valueVar: LODManager["pidKi"] valueVarSetter: (function (v) { LODManager["pidKi"] = v }) - max: 0.000005 + max: 0.1 min: 0.0 integral: false numDigits: 8 @@ -165,6 +165,11 @@ Item { label: "present", color: "#FFFF00" }, + { + prop: "batchTime", + label: "batch", + color: "#00FF00" + }, { prop: "engineRunTime", label: "engineRun", @@ -192,7 +197,12 @@ Item { { prop: "fps", label: "FPS", - color: "#FFFFFF" + color: "#FFFF55" + }, + { + prop: "smoothFPS", + label: "Smooth FPS", + color: "#9999FF" }, { prop: "lodDecreaseFPS", @@ -221,6 +231,8 @@ Item { object: LODManager valueScale: 1.0 valueUnit: "deg" + valueNumDigits: 1 + displayMinAt0: false plots: [ { prop: "pidOp", From 4844f06e5e172e6b2e1b61f694145d5f5dbe649b Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 29 Aug 2018 17:33:39 -0700 Subject: [PATCH 11/24] brain freeze --- interface/src/LODManager.cpp | 4 +--- scripts/developer/utilities/lib/plotperf/PlotPerf.qml | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index ce674f7295..df371f3a59 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -105,9 +105,7 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { auto error = (targetFPS - currentFPS) / targetFPS; error = glm::clamp(error, -1.0f, 1.0f); - if (error <= 0.0f) { - // error = error * 2.0f; - } + auto integral = previous_integral + error * dt; glm::clamp(integral, -1.0f, 1.0f); diff --git a/scripts/developer/utilities/lib/plotperf/PlotPerf.qml b/scripts/developer/utilities/lib/plotperf/PlotPerf.qml index 46056be5fd..27101a2867 100644 --- a/scripts/developer/utilities/lib/plotperf/PlotPerf.qml +++ b/scripts/developer/utilities/lib/plotperf/PlotPerf.qml @@ -186,10 +186,10 @@ Item { } function pixelFromVal(val, valScale) { - return lineHeight + (height - lineHeight) * (1 - (0.9) * (val - _displayMinValue) / (_displayMaxValue - _displayMinValue)); + return lineHeight + (height - lineHeight) * (1 - (0.99) * (val - _displayMinValue) / (_displayMaxValue - _displayMinValue)); } function valueFromPixel(pixY) { - return _displayMinValue + (((pixY - lineHeight) / (height - lineHeight) - 1) * (_displayMaxValue - _displayMinValue) / (-0.9)); + return _displayMinValue + (((pixY - lineHeight) / (height - lineHeight) - 1) * (_displayMaxValue - _displayMinValue) / (-0.99)); } function plotValueHistory(ctx, valHistory, color) { var widthStep= width / (valHistory.length - 1); From 6c502e79e350924d5006d457c22ea85f8995d0d9 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 29 Aug 2018 22:56:44 -0700 Subject: [PATCH 12/24] Fine tuning a LOD regulator PV that works --- interface/src/LODManager.cpp | 102 ++++-------- interface/src/LODManager.h | 15 +- .../utilities/lib/plotperf/PlotPerf.qml | 6 +- scripts/developer/utilities/render/lod.qml | 153 +++++++++++------- 4 files changed, 139 insertions(+), 137 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index df371f3a59..df3b9a9f69 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -66,14 +66,23 @@ void LODManager::setRenderTimes(float presentTime, float engineRunTime, float ba } void LODManager::autoAdjustLOD(float realTimeDelta) { - // float maxRenderTime = glm::max(glm::max(_presentTime, _engineRunTime), _gpuTime); - float maxRenderTime = glm::max(glm::max(_presentTime, _engineRunTime), _gpuTime); + // The "render time" is the worse of: + // - engineRunTime: Time spent in the render thread in the engine producing the gpu::Frame N + // - batchTime: Time spent in the present thread processing the batches of gpu::Frame N+1 + // - presentTime: Time spent in the present thread between the last 2 swap buffers considered the total time to submit gpu::Frame N+1 + // - gpuTime: Time spent in the GPU executing the gpu::Frame N + 2 + + // But Present time is in reality synched with the monitor/display refresh rate, it s always longer than batchTime. + // So if batchTime is fast enough relative to PResent Time we are using it, otherwise we are using presentTime. got it ? + auto presentTime = (_presentTime - _batchTime > 3.0f ? _batchTime + 3.0f : _presentTime); + float maxRenderTime = glm::max(glm::max(presentTime, _engineRunTime), _gpuTime); + // compute time-weighted running average maxRenderTime // Note: we MUST clamp the blend to 1.0 for stability float blend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE) ? realTimeDelta / LOD_ADJUST_RUNNING_AVG_TIMESCALE : 1.0f; _avgRenderTime = (1.0f - blend) * _avgRenderTime + blend * maxRenderTime; // msec - float smoothBlend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE * _pidCoefs.w) ? realTimeDelta / (LOD_ADJUST_RUNNING_AVG_TIMESCALE * _pidCoefs.w) : 1.0f; + float smoothBlend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE * _smoothScale) ? realTimeDelta / (LOD_ADJUST_RUNNING_AVG_TIMESCALE * _smoothScale) : 1.0f; _smoothRenderTime = (1.0f - smoothBlend) * _smoothRenderTime + smoothBlend * maxRenderTime; // msec @@ -87,24 +96,29 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { float oldSolidAngle = getLODAngleDeg(); float targetFPS = 0.5 * (getLODDecreaseFPS() + getLODIncreaseFPS()); - // float targetFPS = (getLODDecreaseFPS()); float targetPeriod = 1.0f / targetFPS; float currentFPS = (float)MSECS_PER_SECOND / _avgRenderTime; + float currentSmoothFPS = (float)MSECS_PER_SECOND / _smoothRenderTime; + float currentVarianceFPS = (currentSmoothFPS - currentFPS); + currentVarianceFPS *= currentVarianceFPS; - static uint64_t lastTime = usecTimestampNow(); + auto dt = realTimeDelta; - uint64_t now = usecTimestampNow(); - auto dt = (float) ((now - lastTime) / double(USECS_PER_MSEC)); - // if (dt < targetPeriod * _pidCoefs.w) return; - dt = realTimeDelta; - - lastTime = now; auto previous_error = _pidHistory.x; auto previous_integral = _pidHistory.y; - auto error = (targetFPS - currentFPS) / targetFPS; - error = glm::clamp(error, -1.0f, 1.0f); + auto smoothError = (targetFPS - currentSmoothFPS); + + auto fpsError = smoothError; + + auto errorSquare = smoothError * smoothError; + + auto noiseCoef = (errorSquare < _pidCoefs.w * currentVarianceFPS ? 0.0f : 1.0f); + + auto normalizedError = noiseCoef * smoothError / targetFPS; + + auto error = glm::clamp(normalizedError, -1.0f, 1.0f); auto integral = previous_integral + error * dt; glm::clamp(integral, -1.0f, 1.0f); @@ -131,59 +145,6 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { setLODAngleDeg(newSolidAngle); - //newSolidAngle = std::max( 0.5f, std::min(newSolidAngle, 90.f)); - - //auto halTan = glm::tan(glm::radians(newSolidAngle * 0.5f)); - - //auto octreeSizeScale = TREE_SCALE * OCTREE_TO_MESH_RATIO / halTan; - // _octreeSizeScale = octreeSizeScale; -/* - if (currentFPS < getLODDecreaseFPS()) { - if (now > _decreaseFPSExpiry) { - _decreaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; - if (_octreeSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) { - _octreeSizeScale *= LOD_AUTO_ADJUST_DECREMENT_FACTOR; - if (_octreeSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) { - _octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE; - } - emit LODDecreased(); - emit LODChanged(); - // Assuming the LOD adjustment will work: we optimistically reset _avgRenderTime - // to provide an FPS just above the decrease threshold. It will drift close to its - // true value after a few LOD_ADJUST_TIMESCALEs and we'll adjust again as necessary. - _avgRenderTime = (float)MSECS_PER_SECOND / (getLODDecreaseFPS() + 1.0f); - } - _decreaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; - } - _increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; - } else if (currentFPS > getLODIncreaseFPS()) { - if (now > _increaseFPSExpiry) { - _increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; - if (_octreeSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) { - if (_octreeSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) { - _octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE; - } else { - _octreeSizeScale *= LOD_AUTO_ADJUST_INCREMENT_FACTOR; - } - if (_octreeSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) { - _octreeSizeScale = ADJUST_LOD_MAX_SIZE_SCALE; - } - emit LODIncreased(); - emit LODChanged(); - - // Assuming the LOD adjustment will work: we optimistically reset _avgRenderTime - // to provide an FPS just below the increase threshold. It will drift close to its - // true value after a few LOD_ADJUST_TIMESCALEs and we'll adjust again as necessary. - _avgRenderTime = (float)MSECS_PER_SECOND / (getLODIncreaseFPS() - 1.0f); - } - _increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; - } - _decreaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; - } else { - _increaseFPSExpiry = now + LOD_AUTO_ADJUST_PERIOD; - _decreaseFPSExpiry = _increaseFPSExpiry; - } -*/ if (oldOctreeSizeScale != _octreeSizeScale) { auto lodToolsDialog = DependencyManager::get()->getLodToolsDialog(); if (lodToolsDialog) { @@ -325,6 +286,11 @@ void LODManager::saveSettings() { hmdLODDecreaseFPS.set(getHMDLODDecreaseFPS()); } + +void LODManager::setSmoothScale(float t) { + _smoothScale = glm::max(1.0f, t); +} + void LODManager::setWorldDetailQuality(float quality) { static const float MAX_DESKTOP_FPS = 60; @@ -414,7 +380,7 @@ float LODManager::getPidKi() const { float LODManager::getPidKd() const { return _pidCoefs.z; } -float LODManager::getPidT() const { +float LODManager::getPidKv() const { return _pidCoefs.w; } void LODManager::setPidKp(float k) { @@ -426,7 +392,7 @@ void LODManager::setPidKi(float k) { void LODManager::setPidKd(float k) { _pidCoefs.z = k; } -void LODManager::setPidT(float t) { +void LODManager::setPidKv(float t) { _pidCoefs.w = t; } diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 167533a236..6843744d16 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -67,6 +67,7 @@ class LODManager : public QObject, public Dependency { Q_PROPERTY(float smoothRenderTime READ getSmoothRenderTime) Q_PROPERTY(float smoothFPS READ getSmoothFPS) + Q_PROPERTY(float smoothScale READ getSmoothScale WRITE setSmoothScale) Q_PROPERTY(float lodLevel READ getLODLevel WRITE setLODLevel NOTIFY LODChanged) Q_PROPERTY(float lodDecreaseFPS READ getLODDecreaseFPS) @@ -80,7 +81,7 @@ class LODManager : public QObject, public Dependency { Q_PROPERTY(float pidKp READ getPidKp WRITE setPidKp) Q_PROPERTY(float pidKi READ getPidKi WRITE setPidKi) Q_PROPERTY(float pidKd READ getPidKd WRITE setPidKd) - Q_PROPERTY(float pidT READ getPidT WRITE setPidT) + Q_PROPERTY(float pidKv READ getPidKv WRITE setPidKv) Q_PROPERTY(float pidOp READ getPidOp) Q_PROPERTY(float pidOi READ getPidOi) @@ -195,6 +196,9 @@ public: void saveSettings(); void resetLODAdjust(); + void setSmoothScale(float t); + float getSmoothScale() const { return _smoothScale; } + float getAverageRenderTime() const { return _avgRenderTime; }; float getMaxTheoreticalFPS() const { return (float)MSECS_PER_SECOND / _avgRenderTime; }; @@ -216,12 +220,12 @@ public: float getPidKp() const; float getPidKi() const; float getPidKd() const; - float getPidT() const; + float getPidKv() const; void setPidKp(float k); void setPidKi(float k); void setPidKd(float k); - void setPidT(float t); - + void setPidKv(float t); + float getPidOp() const; float getPidOi() const; float getPidOd() const; @@ -254,6 +258,7 @@ private: float _batchTime{ 0.0f }; // msec float _gpuTime { 0.0f }; // msec + float _smoothScale{ 8.0f }; float _avgRenderTime { 0.0f }; // msec float _smoothRenderTime{ 0.0f }; float _desktopMaxRenderTime { DEFAULT_DESKTOP_MAX_RENDER_TIME }; @@ -262,7 +267,7 @@ private: float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE; int _boundaryLevelAdjust = 0; - glm::vec4 _pidCoefs{ 1.0f, 0.0000000f, 0.f, 8.0f }; + glm::vec4 _pidCoefs{ 1.0f, 0.0f, 0.0f, 1.0f }; // Kp, Ki, Kd, Kv glm::vec4 _pidHistory{ 0.0f }; glm::vec4 _pidOutputs{ 0.0f }; diff --git a/scripts/developer/utilities/lib/plotperf/PlotPerf.qml b/scripts/developer/utilities/lib/plotperf/PlotPerf.qml index 27101a2867..f239cc010a 100644 --- a/scripts/developer/utilities/lib/plotperf/PlotPerf.qml +++ b/scripts/developer/utilities/lib/plotperf/PlotPerf.qml @@ -217,9 +217,9 @@ Item { function displayTitle(ctx, text, maxVal) { ctx.fillStyle = "grey"; ctx.textAlign = "right"; - ctx.fillText("max" + displayValue(_displayMaxValue, root.valueUnit), width, pixelFromVal(_displayMaxValue)); + ctx.fillText("max " + displayValue(_displayMaxValue, root.valueUnit), width, pixelFromVal(_displayMaxValue)); - ctx.fillText("min" + displayValue(_displayMinValue, root.valueUnit), width, pixelFromVal(_displayMinValue)); + ctx.fillText("min " + displayValue(_displayMinValue, root.valueUnit), width, pixelFromVal(_displayMinValue)); ctx.fillStyle = "white"; ctx.textAlign = "left"; @@ -245,7 +245,6 @@ Item { ctx.strokeStyle= "LightSlateGray"; ctx.lineWidth="1"; - // ctx.strokeStyle= "grey"; ctx.beginPath(); ctx.moveTo(0, maxY); ctx.lineTo(width, maxY); @@ -254,7 +253,6 @@ Item { if (_displayMinValue != 0) { var zeroY = pixelFromVal(0); var minY = pixelFromVal(_displayMinValue); - // ctx.strokeStyle= "DarkRed"; ctx.beginPath(); ctx.moveTo(0, zeroY); ctx.lineTo(width, zeroY); diff --git a/scripts/developer/utilities/render/lod.qml b/scripts/developer/utilities/render/lod.qml index d0562e1020..28cf744394 100644 --- a/scripts/developer/utilities/render/lod.qml +++ b/scripts/developer/utilities/render/lod.qml @@ -53,18 +53,26 @@ Item { min: 0.25 integral: false - anchors.left: autoLOD.left + anchors.left: parent.left anchors.right: parent.right } - HifiControls.CheckBox { - id: autoLOD - boxSize: 20 - text: "Auto LOD" - checked: LODManager.automaticLODAdjust - onCheckedChanged: { LODManager.automaticLODAdjust = (checked) } + Row { + HifiControls.CheckBox { + id: autoLOD + boxSize: 20 + text: "Auto LOD" + checked: LODManager.automaticLODAdjust + onCheckedChanged: { LODManager.automaticLODAdjust = (checked) } + } + HifiControls.CheckBox { + id: showLODRegulatorDetails + visible: LODManager.automaticLODAdjust + boxSize: 20 + text: "Show LOD Details" + } } - + RichSlider { visible: !LODManager.automaticLODAdjust showLabel: true @@ -78,67 +86,85 @@ Item { anchors.left: parent.left anchors.right: parent.right } - - RichSlider { - visible: LODManager.automaticLODAdjust - showLabel: true - label: "LOD PID Kp" - valueVar: LODManager["pidKp"] - valueVarSetter: (function (v) { LODManager["pidKp"] = v }) - max: 2.0 - min: 0.0 - integral: false - numDigits: 3 - + Column { + id: lodRegulatorDetails + visible: LODManager.automaticLODAdjust && showLODRegulatorDetails.checked anchors.left: parent.left anchors.right: parent.right - } - RichSlider { - visible: LODManager.automaticLODAdjust - showLabel: true - label: "LOD PID Ki" - valueVar: LODManager["pidKi"] - valueVarSetter: (function (v) { LODManager["pidKi"] = v }) - max: 0.1 - min: 0.0 - integral: false - numDigits: 8 + RichSlider { + visible: lodRegulatorDetails.visible + showLabel: true + label: "LOD Kp" + valueVar: LODManager["pidKp"] + valueVarSetter: (function (v) { LODManager["pidKp"] = v }) + max: 2.0 + min: 0.0 + integral: false + numDigits: 3 - anchors.left: parent.left - anchors.right: parent.right - } - RichSlider { - visible: LODManager.automaticLODAdjust - showLabel: true - label: "LOD PID Kd" - valueVar: LODManager["pidKd"] - valueVarSetter: (function (v) { LODManager["pidKd"] = v }) - max: 10.0 - min: 0.0 - integral: false - numDigits: 3 + anchors.left: parent.left + anchors.right: parent.right + } + RichSlider { + visible: false && lodRegulatorDetails.visible + showLabel: true + label: "LOD Ki" + valueVar: LODManager["pidKi"] + valueVarSetter: (function (v) { LODManager["pidKi"] = v }) + max: 0.1 + min: 0.0 + integral: false + numDigits: 8 - anchors.left: parent.left - anchors.right: parent.right - } - RichSlider { - visible: LODManager.automaticLODAdjust - showLabel: true - label: "LOD PID Num T" - valueVar: LODManager["pidT"] - valueVarSetter: (function (v) { LODManager["pidT"] = v }) - max: 10.0 - min: 0.0 - integral: true + anchors.left: parent.left + anchors.right: parent.right + } + RichSlider { + visible: false && lodRegulatorDetails.visible + showLabel: true + label: "LOD Kd" + valueVar: LODManager["pidKd"] + valueVarSetter: (function (v) { LODManager["pidKd"] = v }) + max: 10.0 + min: 0.0 + integral: false + numDigits: 3 - anchors.left: parent.left - anchors.right: parent.right + anchors.left: parent.left + anchors.right: parent.right + } + RichSlider { + visible: lodRegulatorDetails.visible + showLabel: true + label: "LOD Kv" + valueVar: LODManager["pidKv"] + valueVarSetter: (function (v) { LODManager["pidKv"] = v }) + max: 2.0 + min: 0.0 + integral: false + + anchors.left: parent.left + anchors.right: parent.right + } + RichSlider { + visible: lodRegulatorDetails.visible + showLabel: true + label: "LOD Smooth Scale" + valueVar: LODManager["smoothScale"] + valueVarSetter: (function (v) { LODManager["smoothScale"] = v }) + max: 20.0 + min: 1.0 + integral: true + + anchors.left: parent.left + anchors.right: parent.right + } } } Column { id: stats - spacing: 8 + spacing: 4 anchors.right: parent.right anchors.left: parent.left anchors.top: topHeader.bottom @@ -146,7 +172,8 @@ Item { function evalEvenHeight() { // Why do we have to do that manually ? cannot seem to find a qml / anchor / layout mode that does that ? - return (height - topLine.height - bottomLine.height - spacing * (children.length - 3)) / (children.length - 2) + var numPlots = (children.length + (lodRegulatorDetails.visible ? 1 : 0) - 2) + return (height - topLine.height - bottomLine.height - spacing * (numPlots - 1)) / (numPlots) } Separator { @@ -226,6 +253,7 @@ Item { ] } PlotPerf { + // visible: lodRegulatorDetails.visible title: "PID Output" height: parent.evalEvenHeight() object: LODManager @@ -248,6 +276,11 @@ Item { prop: "pidOd", label: "Od", color: "#FF6666" + }, + { + prop: "pidO", + label: "Output", + color: "#66FF66" } ] } From 78c7948ebc374f78666a1978593f9dc4e9884cf2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 30 Aug 2018 12:11:43 -0700 Subject: [PATCH 13/24] fine tuning the noise coef ramp and documenting the algorithm --- interface/src/LODManager.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index df3b9a9f69..925d48f9cd 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -100,8 +100,12 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { float currentFPS = (float)MSECS_PER_SECOND / _avgRenderTime; float currentSmoothFPS = (float)MSECS_PER_SECOND / _smoothRenderTime; + + // Compute the Variance of the FPS signal (FPS - smouthFPS)^2 + // Also scale it by a percentage for fine tuning (default is 100%) float currentVarianceFPS = (currentSmoothFPS - currentFPS); currentVarianceFPS *= currentVarianceFPS; + currentVarianceFPS *= _pidCoefs.w; auto dt = realTimeDelta; @@ -114,11 +118,22 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { auto errorSquare = smoothError * smoothError; - auto noiseCoef = (errorSquare < _pidCoefs.w * currentVarianceFPS ? 0.0f : 1.0f); + // Define a noiseCoef that is trying to adjust the error to the FPS target value based on its strength + // relative to the current Variance of the FPS signal. + // If the error is within the variance, just set to 0. + // if its within 2x the variance scale the control + // and full control if error is bigger than 2x variance + auto noiseCoef = 1.0f; + if (errorSquare < currentVarianceFPS) { + noiseCoef = 0.0f; + } else if (errorSquare < 2.0f * currentVarianceFPS) { + noiseCoef = (errorSquare - currentVarianceFPS) / currentVarianceFPS; + } - auto normalizedError = noiseCoef * smoothError / targetFPS; - - auto error = glm::clamp(normalizedError, -1.0f, 1.0f); + // The final normalized error is the the error to the FPS target, weighted by the noiseCoef, then normailzed by the target FPS. + // it s also clamped in the [-1, 1] range + auto error = noiseCoef * smoothError / targetFPS; + error = glm::clamp(error, -1.0f, 1.0f); auto integral = previous_integral + error * dt; glm::clamp(integral, -1.0f, 1.0f); From 194903692ed5b7cc13e6b939a2bed89ea8c7ee26 Mon Sep 17 00:00:00 2001 From: sam gateau Date: Thu, 30 Aug 2018 18:09:11 -0700 Subject: [PATCH 14/24] clening up the code in LODmanager and the associated js/qml --- interface/src/LODManager.cpp | 498 ++++++++++----------- interface/src/LODManager.h | 157 +++---- interface/src/ui/PreferencesDialog.cpp | 48 -- libraries/render/src/render/Args.h | 10 +- libraries/render/src/render/CullTask.cpp | 2 +- scripts/developer/utilities/render/lod.qml | 13 +- 6 files changed, 317 insertions(+), 411 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 925d48f9cd..738c3dd9fb 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -19,27 +19,15 @@ #include "ui/DialogsManager.h" #include "InterfaceLogging.h" +const float LODManager::DEFAULT_DESKTOP_LOD_DOWN_FPS = LOD_OFFSET_FPS + LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_DESKTOP_FPS; +const float LODManager::DEFAULT_HMD_LOD_DOWN_FPS = LOD_OFFSET_FPS + LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_HMD_FPS; -Setting::Handle desktopLODDecreaseFPS("desktopLODDecreaseFPS", DEFAULT_DESKTOP_LOD_DOWN_FPS); -Setting::Handle hmdLODDecreaseFPS("hmdLODDecreaseFPS", DEFAULT_HMD_LOD_DOWN_FPS); +Setting::Handle desktopLODDecreaseFPS("desktopLODDecreaseFPS", LODManager::DEFAULT_DESKTOP_LOD_DOWN_FPS); +Setting::Handle hmdLODDecreaseFPS("hmdLODDecreaseFPS", LODManager::DEFAULT_HMD_LOD_DOWN_FPS); LODManager::LODManager() { } -float LODManager::getLODDecreaseFPS() const { - if (qApp->isHMDMode()) { - return getHMDLODDecreaseFPS(); - } - return getDesktopLODDecreaseFPS(); -} - -float LODManager::getLODIncreaseFPS() const { - if (qApp->isHMDMode()) { - return getHMDLODIncreaseFPS(); - } - return getDesktopLODIncreaseFPS(); -} - // We use a "time-weighted running average" of the maxRenderTime and compare it against min/max thresholds // to determine if we should adjust the level of detail (LOD). // @@ -55,8 +43,12 @@ const float LOD_ADJUST_RUNNING_AVG_TIMESCALE = 0.08f; // sec // multiples of the running average timescale: const uint64_t LOD_AUTO_ADJUST_PERIOD = 4 * (uint64_t)(LOD_ADJUST_RUNNING_AVG_TIMESCALE * (float)USECS_PER_MSEC); // usec -const float LOD_AUTO_ADJUST_DECREMENT_FACTOR = 0.8f; -const float LOD_AUTO_ADJUST_INCREMENT_FACTOR = 1.2f; +// batchTIme is always contained in presentTime. +// We favor using batchTime instead of presentTime as a representative value for rendering duration (on present thread) +// if batchTime + cushionTime < presentTime. +// since we are shooting for fps around 60, 90Hz, the ideal frames are around 10ms +// so we are picking a cushion time of 3ms +const float LOD_BATCH_TO_PRESENT_CUSHION_TIME = 10.0f; // msec void LODManager::setRenderTimes(float presentTime, float engineRunTime, float batchTime, float gpuTime) { _presentTime = presentTime; @@ -66,6 +58,7 @@ void LODManager::setRenderTimes(float presentTime, float engineRunTime, float ba } void LODManager::autoAdjustLOD(float realTimeDelta) { + // The "render time" is the worse of: // - engineRunTime: Time spent in the render thread in the engine producing the gpu::Frame N // - batchTime: Time spent in the present thread processing the batches of gpu::Frame N+1 @@ -73,50 +66,42 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { // - gpuTime: Time spent in the GPU executing the gpu::Frame N + 2 // But Present time is in reality synched with the monitor/display refresh rate, it s always longer than batchTime. - // So if batchTime is fast enough relative to PResent Time we are using it, otherwise we are using presentTime. got it ? - auto presentTime = (_presentTime - _batchTime > 3.0f ? _batchTime + 3.0f : _presentTime); + // So if batchTime is fast enough relative to presentTime we are using it, otherwise we are using presentTime. got it ? + auto presentTime = (_presentTime > _batchTime + LOD_BATCH_TO_PRESENT_CUSHION_TIME ? _batchTime + LOD_BATCH_TO_PRESENT_CUSHION_TIME : _presentTime); float maxRenderTime = glm::max(glm::max(presentTime, _engineRunTime), _gpuTime); // compute time-weighted running average maxRenderTime // Note: we MUST clamp the blend to 1.0 for stability - float blend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE) ? realTimeDelta / LOD_ADJUST_RUNNING_AVG_TIMESCALE : 1.0f; - _avgRenderTime = (1.0f - blend) * _avgRenderTime + blend * maxRenderTime; // msec + float nowBlend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE) ? realTimeDelta / LOD_ADJUST_RUNNING_AVG_TIMESCALE : 1.0f; + _nowRenderTime = (1.0f - nowBlend) * _nowRenderTime + nowBlend * maxRenderTime; // msec float smoothBlend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE * _smoothScale) ? realTimeDelta / (LOD_ADJUST_RUNNING_AVG_TIMESCALE * _smoothScale) : 1.0f; _smoothRenderTime = (1.0f - smoothBlend) * _smoothRenderTime + smoothBlend * maxRenderTime; // msec - - // _avgRenderTime = maxRenderTime; - if (!_automaticLODAdjust || _avgRenderTime == 0.0f) { + if (!_automaticLODAdjust || _nowRenderTime == 0.0f) { // early exit return; } - float oldOctreeSizeScale = _octreeSizeScale; - float oldSolidAngle = getLODAngleDeg(); + // Previous values for output + float oldOctreeSizeScale = getOctreeSizeScale(); + float oldLODAngle = getLODAngleDeg(); - float targetFPS = 0.5 * (getLODDecreaseFPS() + getLODIncreaseFPS()); - float targetPeriod = 1.0f / targetFPS; - - float currentFPS = (float)MSECS_PER_SECOND / _avgRenderTime; + // Target fps and current fps based on latest measurments + float targetFPS = getLODTargetFPS(); + float currentNowFPS = (float)MSECS_PER_SECOND / _nowRenderTime; float currentSmoothFPS = (float)MSECS_PER_SECOND / _smoothRenderTime; // Compute the Variance of the FPS signal (FPS - smouthFPS)^2 // Also scale it by a percentage for fine tuning (default is 100%) - float currentVarianceFPS = (currentSmoothFPS - currentFPS); + float currentVarianceFPS = (currentSmoothFPS - currentNowFPS); currentVarianceFPS *= currentVarianceFPS; currentVarianceFPS *= _pidCoefs.w; - auto dt = realTimeDelta; - - auto previous_error = _pidHistory.x; - auto previous_integral = _pidHistory.y; - - auto smoothError = (targetFPS - currentSmoothFPS); - - auto fpsError = smoothError; - - auto errorSquare = smoothError * smoothError; + // evaluate current error between the current smoothFPS and target FPS + // and the sqaure of the error to compare against the Variance + auto currentErrorFPS = (targetFPS - currentSmoothFPS); + auto currentErrorFPSSquare = currentErrorFPS * currentErrorFPS; // Define a noiseCoef that is trying to adjust the error to the FPS target value based on its strength // relative to the current Variance of the FPS signal. @@ -124,41 +109,48 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { // if its within 2x the variance scale the control // and full control if error is bigger than 2x variance auto noiseCoef = 1.0f; - if (errorSquare < currentVarianceFPS) { + if (currentErrorFPSSquare < currentVarianceFPS) { noiseCoef = 0.0f; - } else if (errorSquare < 2.0f * currentVarianceFPS) { - noiseCoef = (errorSquare - currentVarianceFPS) / currentVarianceFPS; + } else if (currentErrorFPSSquare < 2.0f * currentVarianceFPS) { + noiseCoef = (currentErrorFPSSquare - currentVarianceFPS) / currentVarianceFPS; } // The final normalized error is the the error to the FPS target, weighted by the noiseCoef, then normailzed by the target FPS. // it s also clamped in the [-1, 1] range - auto error = noiseCoef * smoothError / targetFPS; + auto error = noiseCoef * currentErrorFPS / targetFPS; error = glm::clamp(error, -1.0f, 1.0f); + // Now we are getting into the P.I.D. controler code + // retreive the history of pid error and integral + auto previous_error = _pidHistory.x; + auto previous_integral = _pidHistory.y; + + // The dt used for temporal values of the controller is the current realTimedelta + // clamped to a reasonable granularity to make sure we are not over reacting + auto dt = std::min(realTimeDelta, LOD_ADJUST_RUNNING_AVG_TIMESCALE); + + // Compute the current integral and clamp to avoid accumulation auto integral = previous_integral + error * dt; glm::clamp(integral, -1.0f, 1.0f); + // Compute derivative auto derivative = (error - previous_error) / dt; + // remember history _pidHistory.x = error; _pidHistory.y = integral; _pidHistory.z = derivative; - auto Kp = _pidCoefs.x; - auto Ki = _pidCoefs.y; - auto Kd = _pidCoefs.z; - - _pidOutputs.x = Kp * error; - _pidOutputs.y = Ki * integral; - _pidOutputs.z = Kd * derivative; + // Compute the output of the PID and record intermediate results for tuning + _pidOutputs.x = _pidCoefs.x * error; // Kp * error + _pidOutputs.y = _pidCoefs.y * integral; // Ki * integral + _pidOutputs.z = _pidCoefs.z * derivative; // Kd * derivative auto output = _pidOutputs.x + _pidOutputs.y + _pidOutputs.z; - _pidOutputs.w = output; - auto newSolidAngle = oldSolidAngle + output; - - setLODAngleDeg(newSolidAngle); + // And now add the output of the controller to the LODAngle where we will guarantee it is in the proper range + setLODAngleDeg(oldLODAngle + output); if (oldOctreeSizeScale != _octreeSizeScale) { auto lodToolsDialog = DependencyManager::get()->getLodToolsDialog(); @@ -168,207 +160,6 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { } } -void LODManager::resetLODAdjust() { - _decreaseFPSExpiry = _increaseFPSExpiry = usecTimestampNow() + LOD_AUTO_ADJUST_PERIOD; -} - -void LODManager::setAutomaticLODAdjust(bool value) { - _automaticLODAdjust = value; - emit autoLODChanged(); -} - -float LODManager::getLODLevel() const { - // simpleLOD is a linearized and normalized number that represents how much LOD is being applied. - // It ranges from: - // 1.0 = normal (max) level of detail - // 0.0 = min level of detail - // In other words: as LOD "drops" the value of simpleLOD will also "drop", and it cannot go lower than 0.0. - const float LOG_MIN_LOD_RATIO = logf(ADJUST_LOD_MIN_SIZE_SCALE / ADJUST_LOD_MAX_SIZE_SCALE); - float power = logf(_octreeSizeScale / ADJUST_LOD_MAX_SIZE_SCALE); - float simpleLOD = (LOG_MIN_LOD_RATIO - power) / LOG_MIN_LOD_RATIO; - return simpleLOD; -} - -void LODManager::setLODLevel(float level) { - float simpleLOD = level; - if (!_automaticLODAdjust) { - const float LOG_MIN_LOD_RATIO = logf(ADJUST_LOD_MIN_SIZE_SCALE / ADJUST_LOD_MAX_SIZE_SCALE); - - float power = LOG_MIN_LOD_RATIO - (simpleLOD * LOG_MIN_LOD_RATIO); - float sizeScale = expf(power) * ADJUST_LOD_MAX_SIZE_SCALE; - setOctreeSizeScale(sizeScale); - } -} - -const float MIN_DECREASE_FPS = 0.5f; - -void LODManager::setDesktopLODDecreaseFPS(float fps) { - if (fps < MIN_DECREASE_FPS) { - // avoid divide by zero - fps = MIN_DECREASE_FPS; - } - _desktopMaxRenderTime = (float)MSECS_PER_SECOND / fps; -} - -float LODManager::getDesktopLODDecreaseFPS() const { - return (float)MSECS_PER_SECOND / _desktopMaxRenderTime; -} - -float LODManager::getDesktopLODIncreaseFPS() const { - return glm::min(((float)MSECS_PER_SECOND / _desktopMaxRenderTime) + INCREASE_LOD_GAP_FPS, MAX_LIKELY_DESKTOP_FPS); -} - -void LODManager::setHMDLODDecreaseFPS(float fps) { - if (fps < MIN_DECREASE_FPS) { - // avoid divide by zero - fps = MIN_DECREASE_FPS; - } - _hmdMaxRenderTime = (float)MSECS_PER_SECOND / fps; -} - -float LODManager::getHMDLODDecreaseFPS() const { - return (float)MSECS_PER_SECOND / _hmdMaxRenderTime; -} - -float LODManager::getHMDLODIncreaseFPS() const { - return glm::min(((float)MSECS_PER_SECOND / _hmdMaxRenderTime) + INCREASE_LOD_GAP_FPS, MAX_LIKELY_HMD_FPS); -} - -QString LODManager::getLODFeedbackText() { - // determine granularity feedback - int boundaryLevelAdjust = getBoundaryLevelAdjust(); - QString granularityFeedback; - switch (boundaryLevelAdjust) { - case 0: { - granularityFeedback = QString("."); - } break; - case 1: { - granularityFeedback = QString(" at half of standard granularity."); - } break; - case 2: { - granularityFeedback = QString(" at a third of standard granularity."); - } break; - default: { - granularityFeedback = QString(" at 1/%1th of standard granularity.").arg(boundaryLevelAdjust + 1); - } break; - } - // distance feedback - float octreeSizeScale = getOctreeSizeScale(); - float relativeToDefault = octreeSizeScale / DEFAULT_OCTREE_SIZE_SCALE; - int relativeToTwentyTwenty = 20 / relativeToDefault; - - QString result; - if (relativeToDefault > 1.01f) { - result = QString("20:%1 or %2 times further than average vision%3").arg(relativeToTwentyTwenty).arg(relativeToDefault,0,'f',2).arg(granularityFeedback); - } else if (relativeToDefault > 0.99f) { - result = QString("20:20 or the default distance for average vision%1").arg(granularityFeedback); - } else if (relativeToDefault > 0.01f) { - result = QString("20:%1 or %2 of default distance for average vision%3").arg(relativeToTwentyTwenty).arg(relativeToDefault,0,'f',3).arg(granularityFeedback); - } else { - result = QString("%2 of default distance for average vision%3").arg(relativeToDefault,0,'f',3).arg(granularityFeedback); - } - return result; -} - -bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) { - // FIXME - eventually we want to use the render accuracy as an indicator for the level of detail - // to use in rendering. - // float renderAccuracy = calculateRenderAccuracy(args->getViewFrustum().getPosition(), bounds, args->_sizeScale, args->_boundaryLevelAdjust); - // return (renderAccuracy > 0.0f); - - auto pos = args->getViewFrustum().getPosition() - bounds.calcCenter(); - auto dim = bounds.getDimensions(); - auto halfTanSq = 0.25f * glm::dot(dim, dim) / glm::dot(pos, pos); - return (halfTanSq >= args->_solidAngleHalfTanSq); - -}; - -void LODManager::setOctreeSizeScale(float sizeScale) { - _octreeSizeScale = sizeScale; -} - -void LODManager::setBoundaryLevelAdjust(int boundaryLevelAdjust) { - _boundaryLevelAdjust = boundaryLevelAdjust; -} - -void LODManager::loadSettings() { - setDesktopLODDecreaseFPS(desktopLODDecreaseFPS.get()); - setHMDLODDecreaseFPS(hmdLODDecreaseFPS.get()); -} - -void LODManager::saveSettings() { - desktopLODDecreaseFPS.set(getDesktopLODDecreaseFPS()); - hmdLODDecreaseFPS.set(getHMDLODDecreaseFPS()); -} - - -void LODManager::setSmoothScale(float t) { - _smoothScale = glm::max(1.0f, t); -} - -void LODManager::setWorldDetailQuality(float quality) { - - static const float MAX_DESKTOP_FPS = 60; - static const float MAX_HMD_FPS = 90; - static const float MIN_FPS = 10; - static const float LOW = 0.25f; - static const float MEDIUM = 0.5f; - static const float HIGH = 0.75f; - static const float THRASHING_DIFFERENCE = 10; - - bool isLowestValue = quality == LOW; - bool isHMDMode = qApp->isHMDMode(); - - float maxFPS = isHMDMode ? MAX_HMD_FPS : MAX_DESKTOP_FPS; - float desiredFPS = maxFPS /* - THRASHING_DIFFERENCE*/; - - if (!isLowestValue) { - float calculatedFPS = (maxFPS - (maxFPS * quality))/* - THRASHING_DIFFERENCE*/; - desiredFPS = calculatedFPS < MIN_FPS ? MIN_FPS : calculatedFPS; - } - - if (isHMDMode) { - setHMDLODDecreaseFPS(desiredFPS); - } - else { - setDesktopLODDecreaseFPS(desiredFPS); - } - - emit worldDetailQualityChanged(); -} - -float LODManager::getWorldDetailQuality() const { - - - static const float MAX_DESKTOP_FPS = 60; - static const float MAX_HMD_FPS = 90; - static const float MIN_FPS = 10; - static const float LOW = 0.25f; - static const float MEDIUM = 0.5f; - static const float HIGH = 0.75f; - - bool inHMD = qApp->isHMDMode(); - - float increaseFPS = 0; - if (inHMD) { - increaseFPS = getHMDLODDecreaseFPS(); - } else { - increaseFPS = getDesktopLODDecreaseFPS(); - } - float maxFPS = inHMD ? MAX_HMD_FPS : MAX_DESKTOP_FPS; - float percentage = 1.0 - increaseFPS / maxFPS; - - if (percentage <= LOW) { - return LOW; - } - else if (percentage <= MEDIUM) { - return MEDIUM; - } - - return HIGH; -} - - float LODManager::getLODAngleHalfTan() const { return getPerspectiveAccuracyAngleTan(_octreeSizeScale, _boundaryLevelAdjust); } @@ -386,6 +177,10 @@ void LODManager::setLODAngleDeg(float lodAngle) { setOctreeSizeScale(octreeSizeScale); } +void LODManager::setSmoothScale(float t) { + _smoothScale = glm::max(1.0f, t); +} + float LODManager::getPidKp() const { return _pidCoefs.x; } @@ -422,4 +217,189 @@ float LODManager::getPidOd() const { } float LODManager::getPidO() const { return _pidOutputs.w; -} \ No newline at end of file +} + +void LODManager::resetLODAdjust() { + // _decreaseFPSExpiry = _increaseFPSExpiry = usecTimestampNow() + LOD_AUTO_ADJUST_PERIOD; +} + +void LODManager::setAutomaticLODAdjust(bool value) { + _automaticLODAdjust = value; + emit autoLODChanged(); +} + +bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) { + // To decide if the bound should be rendered or not at the specified Args->lodAngle, + // we need to compute the apparent angle of the bound from the frustum origin, + // and compare it against the lodAngle, if it is greater or equal we should render the content of that bound. + // we abstract the bound as a sphere centered on the bound center and of radius half diagonal of the bound. + + // Instead of comparing angles, we are comparing the tangent of the half angle which are more efficient to compute: + // we are comparing the square of the half tangent apparent angle for the bound against the LODAngle Half tangent square + // if smaller, the bound is too small and we should NOT render it, return true otherwise. + + // Tangent Adjacent side is eye to bound center vector length + auto pos = args->getViewFrustum().getPosition() - bounds.calcCenter(); + auto halfTanAdjacentSq = glm::dot(pos, pos); + + // Tangent Opposite side is the half length of the dimensions vector of the bound + auto dim = bounds.getDimensions(); + auto halfTanOppositeSq = 0.25f * glm::dot(dim, dim); + + // The test is: + // isVisible = halfTanSq >= lodHalfTanSq = (halfTanOppositeSq / halfTanAdjacentSq) >= lodHalfTanSq + // which we express as below to avoid division + // (halfTanOppositeSq) >= lodHalfTanSq * halfTanAdjacentSq + return (halfTanOppositeSq >= args->_lodAngleHalfTanSq * halfTanAdjacentSq); +}; + +void LODManager::setOctreeSizeScale(float sizeScale) { + _octreeSizeScale = sizeScale; +} + +void LODManager::setBoundaryLevelAdjust(int boundaryLevelAdjust) { + _boundaryLevelAdjust = boundaryLevelAdjust; +} + +QString LODManager::getLODFeedbackText() { + // determine granularity feedback + int boundaryLevelAdjust = getBoundaryLevelAdjust(); + QString granularityFeedback; + switch (boundaryLevelAdjust) { + case 0: { + granularityFeedback = QString("."); + } break; + case 1: { + granularityFeedback = QString(" at half of standard granularity."); + } break; + case 2: { + granularityFeedback = QString(" at a third of standard granularity."); + } break; + default: { + granularityFeedback = QString(" at 1/%1th of standard granularity.").arg(boundaryLevelAdjust + 1); + } break; + } + // distance feedback + float octreeSizeScale = getOctreeSizeScale(); + float relativeToDefault = octreeSizeScale / DEFAULT_OCTREE_SIZE_SCALE; + int relativeToTwentyTwenty = 20 / relativeToDefault; + + QString result; + if (relativeToDefault > 1.01f) { + result = QString("20:%1 or %2 times further than average vision%3").arg(relativeToTwentyTwenty).arg(relativeToDefault, 0, 'f', 2).arg(granularityFeedback); + } + else if (relativeToDefault > 0.99f) { + result = QString("20:20 or the default distance for average vision%1").arg(granularityFeedback); + } + else if (relativeToDefault > 0.01f) { + result = QString("20:%1 or %2 of default distance for average vision%3").arg(relativeToTwentyTwenty).arg(relativeToDefault, 0, 'f', 3).arg(granularityFeedback); + } + else { + result = QString("%2 of default distance for average vision%3").arg(relativeToDefault, 0, 'f', 3).arg(granularityFeedback); + } + return result; +} + +void LODManager::loadSettings() { + setDesktopLODTargetFPS(desktopLODDecreaseFPS.get()); + setHMDLODTargetFPS(hmdLODDecreaseFPS.get()); +} + +void LODManager::saveSettings() { + desktopLODDecreaseFPS.set(getDesktopLODTargetFPS()); + hmdLODDecreaseFPS.set(getHMDLODTargetFPS()); +} + +const float MIN_DECREASE_FPS = 0.5f; + +void LODManager::setDesktopLODTargetFPS(float fps) { + if (fps < MIN_DECREASE_FPS) { + // avoid divide by zero + fps = MIN_DECREASE_FPS; + } + _desktopTargetFPS = fps; +} + +float LODManager::getDesktopLODTargetFPS() const { + return _desktopTargetFPS; +} + +void LODManager::setHMDLODTargetFPS(float fps) { + if (fps < MIN_DECREASE_FPS) { + // avoid divide by zero + fps = MIN_DECREASE_FPS; + } + _hmdTargetFPS = fps; +} + +float LODManager::getHMDLODTargetFPS() const { + return _hmdTargetFPS; +} + +float LODManager::getLODTargetFPS() const { + if (qApp->isHMDMode()) { + return getHMDLODTargetFPS(); + } + return getDesktopLODTargetFPS(); +} + +void LODManager::setWorldDetailQuality(float quality) { + static const float MIN_FPS = 10; + static const float LOW = 0.25f; + + bool isLowestValue = quality == LOW; + bool isHMDMode = qApp->isHMDMode(); + + float maxFPS = isHMDMode ? LOD_MAX_LIKELY_HMD_FPS : LOD_MAX_LIKELY_DESKTOP_FPS; + float desiredFPS = maxFPS; + + if (!isLowestValue) { + float calculatedFPS = (maxFPS - (maxFPS * quality)); + desiredFPS = calculatedFPS < MIN_FPS ? MIN_FPS : calculatedFPS; + } + + if (isHMDMode) { + setHMDLODTargetFPS(desiredFPS); + } + else { + setDesktopLODTargetFPS(desiredFPS); + } + + emit worldDetailQualityChanged(); +} + +float LODManager::getWorldDetailQuality() const { + + static const float LOW = 0.25f; + static const float MEDIUM = 0.5f; + static const float HIGH = 0.75f; + + bool inHMD = qApp->isHMDMode(); + + float targetFPS = 0; + if (inHMD) { + targetFPS = getHMDLODTargetFPS(); + } else { + targetFPS = getDesktopLODTargetFPS(); + } + float maxFPS = inHMD ? LOD_MAX_LIKELY_HMD_FPS : LOD_MAX_LIKELY_DESKTOP_FPS; + float percentage = 1.0 - targetFPS / maxFPS; + + if (percentage <= LOW) { + return LOW; + } + else if (percentage <= MEDIUM) { + return MEDIUM; + } + + return HIGH; +} + + +void LODManager::setLODQualityLevel(float quality) { + _lodQualityLevel; +} + +float LODManager::getLODQualityLevel() const { + return _lodQualityLevel; +} diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 6843744d16..0af745bcf4 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -19,20 +19,11 @@ #include #include -const float DEFAULT_DESKTOP_LOD_DOWN_FPS = 30.0f; -const float DEFAULT_HMD_LOD_DOWN_FPS = 34.0f; -const float DEFAULT_DESKTOP_MAX_RENDER_TIME = (float)MSECS_PER_SECOND / DEFAULT_DESKTOP_LOD_DOWN_FPS; // msec -const float DEFAULT_HMD_MAX_RENDER_TIME = (float)MSECS_PER_SECOND / DEFAULT_HMD_LOD_DOWN_FPS; // msec -const float MAX_LIKELY_DESKTOP_FPS = 61.0f; // this is essentially, V-synch - 1 fps -const float MAX_LIKELY_HMD_FPS = 91.0f; // this is essentially, V-synch - 1 fps -const float INCREASE_LOD_GAP_FPS = 10.0f; // fps -// The default value DEFAULT_OCTREE_SIZE_SCALE means you can be 400 meters away from a 1 meter object in order to see it (which is ~20:20 vision). -const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE; -// This controls how low the auto-adjust LOD will go. We want a minimum vision of ~20:500 or 0.04 of default -// const float ADJUST_LOD_MIN_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE * 0.04f; -// const float ADJUST_LOD_MIN_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE * 0.02f; -const float ADJUST_LOD_MIN_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE * 0.01f; +const float LOD_DEFAULT_QUALITY_LEVEL = 0.5f; // default quality level setting is Mid +const float LOD_MAX_LIKELY_DESKTOP_FPS = 60.0f; // this is essentially, V-synch fps +const float LOD_MAX_LIKELY_HMD_FPS = 90.0f; // this is essentially, V-synch fps +const float LOD_OFFSET_FPS = 5.0f; // offset of FPS to add for computing the target framerate class AABox; @@ -55,41 +46,42 @@ class AABox; class LODManager : public QObject, public Dependency { Q_OBJECT - SINGLETON_DEPENDENCY + SINGLETON_DEPENDENCY - Q_PROPERTY(float presentTime READ getPresentTime) - Q_PROPERTY(float engineRunTime READ getEngineRunTime) - Q_PROPERTY(float batchTime READ getBatchTime) - Q_PROPERTY(float gpuTime READ getGPUTime) + Q_PROPERTY(float worldDetailQuality READ getWorldDetailQuality WRITE setWorldDetailQuality NOTIFY worldDetailQualityChanged) - Q_PROPERTY(float avgRenderTime READ getAverageRenderTime) - Q_PROPERTY(float fps READ getMaxTheoreticalFPS) + Q_PROPERTY(float lodQualityLevel READ getLODQualityLevel WRITE setLODQualityLevel NOTIFY lodQualityLevelChanged) - Q_PROPERTY(float smoothRenderTime READ getSmoothRenderTime) - Q_PROPERTY(float smoothFPS READ getSmoothFPS) - Q_PROPERTY(float smoothScale READ getSmoothScale WRITE setSmoothScale) + Q_PROPERTY(bool automaticLODAdjust READ getAutomaticLODAdjust WRITE setAutomaticLODAdjust NOTIFY autoLODChanged) - Q_PROPERTY(float lodLevel READ getLODLevel WRITE setLODLevel NOTIFY LODChanged) - Q_PROPERTY(float lodDecreaseFPS READ getLODDecreaseFPS) - Q_PROPERTY(float lodIncreaseFPS READ getLODIncreaseFPS) - Q_PROPERTY(bool automaticLODAdjust READ getAutomaticLODAdjust WRITE setAutomaticLODAdjust NOTIFY autoLODChanged) + Q_PROPERTY(float presentTime READ getPresentTime) + Q_PROPERTY(float engineRunTime READ getEngineRunTime) + Q_PROPERTY(float batchTime READ getBatchTime) + Q_PROPERTY(float gpuTime READ getGPUTime) - Q_PROPERTY(float worldDetailQuality READ getWorldDetailQuality WRITE setWorldDetailQuality NOTIFY worldDetailQualityChanged) + Q_PROPERTY(float nowRenderTime READ getNowRenderTime) + Q_PROPERTY(float nowRenderFPS READ getNowRenderFPS) - Q_PROPERTY(float lodAngleDeg READ getLODAngleDeg WRITE setLODAngleDeg) + Q_PROPERTY(float smoothScale READ getSmoothScale WRITE setSmoothScale) + Q_PROPERTY(float smoothRenderTime READ getSmoothRenderTime) + Q_PROPERTY(float smoothRenderFPS READ getSmoothRenderFPS) - Q_PROPERTY(float pidKp READ getPidKp WRITE setPidKp) - Q_PROPERTY(float pidKi READ getPidKi WRITE setPidKi) - Q_PROPERTY(float pidKd READ getPidKd WRITE setPidKd) - Q_PROPERTY(float pidKv READ getPidKv WRITE setPidKv) + Q_PROPERTY(float lodTargetFPS READ getLODTargetFPS) - Q_PROPERTY(float pidOp READ getPidOp) - Q_PROPERTY(float pidOi READ getPidOi) - Q_PROPERTY(float pidOd READ getPidOd) - Q_PROPERTY(float pidO READ getPidO) + Q_PROPERTY(float lodAngleDeg READ getLODAngleDeg WRITE setLODAngleDeg) + + Q_PROPERTY(float pidKp READ getPidKp WRITE setPidKp) + Q_PROPERTY(float pidKi READ getPidKi WRITE setPidKi) + Q_PROPERTY(float pidKd READ getPidKd WRITE setPidKd) + Q_PROPERTY(float pidKv READ getPidKv WRITE setPidKv) + + Q_PROPERTY(float pidOp READ getPidOp) + Q_PROPERTY(float pidOi READ getPidOi) + Q_PROPERTY(float pidOd READ getPidOd) + Q_PROPERTY(float pidO READ getPidO) public: - + /**jsdoc * @function LODManager.setAutomaticLODAdjust * @param {boolean} value @@ -103,42 +95,31 @@ public: Q_INVOKABLE bool getAutomaticLODAdjust() const { return _automaticLODAdjust; } /**jsdoc - * @function LODManager.setDesktopLODDecreaseFPS + * @function LODManager.setDesktopLODTargetFPS * @param {number} value */ - Q_INVOKABLE void setDesktopLODDecreaseFPS(float value); + Q_INVOKABLE void setDesktopLODTargetFPS(float value); /**jsdoc - * @function LODManager.getDesktopLODDecreaseFPS + * @function LODManager.getDesktopLODTargetFPS * @returns {number} */ - Q_INVOKABLE float getDesktopLODDecreaseFPS() const; + Q_INVOKABLE float getDesktopLODTargetFPS() const; /**jsdoc - * @function LODManager.getDesktopLODIncreaseFPS - * @returns {number} - */ - Q_INVOKABLE float getDesktopLODIncreaseFPS() const; - - /**jsdoc - * @function LODManager.setHMDLODDecreaseFPS + * @function LODManager.setHMDLODTargetFPS * @param {number} value */ - - Q_INVOKABLE void setHMDLODDecreaseFPS(float value); + + Q_INVOKABLE void setHMDLODTargetFPS(float value); /**jsdoc - * @function LODManager.getHMDLODDecreaseFPS + * @function LODManager.getHMDLODTargetFPS * @returns {number} */ - Q_INVOKABLE float getHMDLODDecreaseFPS() const; + Q_INVOKABLE float getHMDLODTargetFPS() const; - /**jsdoc - * @function LODManager.getHMDLODIncreaseFPS - * @returns {number} - */ - Q_INVOKABLE float getHMDLODIncreaseFPS() const; // User Tweakable LOD Items /**jsdoc @@ -172,16 +153,11 @@ public: Q_INVOKABLE int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; } /**jsdoc - * @function LODManager.getLODDecreaseFPS - * @returns {number} - */ - Q_INVOKABLE float getLODDecreaseFPS() const; + * @function LODManager.getLODTargetFPS + * @returns {number} + */ + Q_INVOKABLE float getLODTargetFPS() const; - /**jsdoc - * @function LODManager.getLODIncreaseFPS - * @returns {number} - */ - Q_INVOKABLE float getLODIncreaseFPS() const; float getPresentTime() const { return _presentTime; } float getEngineRunTime() const { return _engineRunTime; } @@ -196,22 +172,21 @@ public: void saveSettings(); void resetLODAdjust(); + float getNowRenderTime() const { return _nowRenderTime; }; + float getNowRenderFPS() const { return (float)MSECS_PER_SECOND / _nowRenderTime; }; + void setSmoothScale(float t); float getSmoothScale() const { return _smoothScale; } - float getAverageRenderTime() const { return _avgRenderTime; }; - float getMaxTheoreticalFPS() const { return (float)MSECS_PER_SECOND / _avgRenderTime; }; - float getSmoothRenderTime() const { return _smoothRenderTime; }; - float getSmoothFPS() const { return (float)MSECS_PER_SECOND / _smoothRenderTime; }; - - - float getLODLevel() const; - void setLODLevel(float level); + float getSmoothRenderFPS() const { return (float)MSECS_PER_SECOND / _smoothRenderTime; }; void setWorldDetailQuality(float quality); float getWorldDetailQuality() const; + void setLODQualityLevel(float quality); + float getLODQualityLevel() const; + float getLODAngleDeg() const; void setLODAngleDeg(float lodAngle); float getLODAngleHalfTan() const; @@ -225,12 +200,15 @@ public: void setPidKi(float k); void setPidKd(float k); void setPidKv(float t); - + float getPidOp() const; float getPidOi() const; float getPidOd() const; float getPidO() const; + static const float DEFAULT_DESKTOP_LOD_DOWN_FPS; + static const float DEFAULT_HMD_LOD_DOWN_FPS; + signals: /**jsdoc @@ -245,24 +223,28 @@ signals: */ void LODDecreased(); - void LODChanged(); void autoLODChanged(); + void lodQualityLevelChanged(); void worldDetailQualityChanged(); private: LODManager(); bool _automaticLODAdjust = true; - float _presentTime { 0.0f }; // msec - float _engineRunTime { 0.0f }; // msec - float _batchTime{ 0.0f }; // msec - float _gpuTime { 0.0f }; // msec - float _smoothScale{ 8.0f }; - float _avgRenderTime { 0.0f }; // msec - float _smoothRenderTime{ 0.0f }; - float _desktopMaxRenderTime { DEFAULT_DESKTOP_MAX_RENDER_TIME }; - float _hmdMaxRenderTime { DEFAULT_HMD_MAX_RENDER_TIME }; + float _presentTime{ 0.0f }; // msec + float _engineRunTime{ 0.0f }; // msec + float _batchTime{ 0.0f }; // msec + float _gpuTime{ 0.0f }; // msec + + float _nowRenderTime{ 0.0f }; // msec + float _smoothScale{ 10.0f }; // smooth is evaluated over 10 times longer than now + float _smoothRenderTime{ 0.0f }; // msec + + float _lodQualityLevel{ LOD_DEFAULT_QUALITY_LEVEL }; + + float _desktopTargetFPS { LOD_OFFSET_FPS + LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_DESKTOP_FPS }; + float _hmdTargetFPS { LOD_OFFSET_FPS + LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_HMD_FPS }; float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE; int _boundaryLevelAdjust = 0; @@ -270,9 +252,6 @@ private: glm::vec4 _pidCoefs{ 1.0f, 0.0f, 0.0f, 1.0f }; // Kp, Ki, Kd, Kv glm::vec4 _pidHistory{ 0.0f }; glm::vec4 _pidOutputs{ 0.0f }; - - uint64_t _decreaseFPSExpiry { 0 }; - uint64_t _increaseFPSExpiry { 0 }; }; #endif // hifi_LODManager_h diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index a271e9436c..951925214c 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -55,54 +55,6 @@ void setupPreferences() { // Graphics quality static const QString GRAPHICS_QUALITY { "Graphics Quality" }; { - /* static const float MAX_DESKTOP_FPS = 60; - static const float MAX_HMD_FPS = 90; - static const float MIN_FPS = 10; - static const float LOW = 0.25f; - static const float MEDIUM = 0.5f; - static const float HIGH = 0.75f; - auto getter = []()->float { - auto lodManager = DependencyManager::get(); - bool inHMD = qApp->isHMDMode(); - - float increaseFPS = 0; - if (inHMD) { - increaseFPS = lodManager->getHMDLODDecreaseFPS(); - } else { - increaseFPS = lodManager->getDesktopLODDecreaseFPS(); - } - float maxFPS = inHMD ? MAX_HMD_FPS : MAX_DESKTOP_FPS; - float percentage = increaseFPS / maxFPS; - - if (percentage >= HIGH) { - return LOW; - } else if (percentage >= LOW) { - return MEDIUM; - } - return HIGH; - }; - - auto setter = [](float value) { - static const float THRASHING_DIFFERENCE = 10; - auto lodManager = DependencyManager::get(); - - bool isLowestValue = value == LOW; - bool isHMDMode = qApp->isHMDMode(); - - float maxFPS = isHMDMode ? MAX_HMD_FPS : MAX_DESKTOP_FPS; - float desiredFPS = maxFPS - THRASHING_DIFFERENCE; - - if (!isLowestValue) { - float calculatedFPS = (maxFPS - (maxFPS * value)) - THRASHING_DIFFERENCE; - desiredFPS = calculatedFPS < MIN_FPS ? MIN_FPS : calculatedFPS; - } - - if (isHMDMode) { - lodManager->setHMDLODDecreaseFPS(desiredFPS); - } else { - lodManager->setDesktopLODDecreaseFPS(desiredFPS); - } - };*/ auto getter = []()->float { return DependencyManager::get()->getWorldDetailQuality(); }; diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index 589945e9c7..dd061c0092 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -73,16 +73,16 @@ namespace render { Args(const gpu::ContextPointer& context, float sizeScale = 1.0f, int boundaryLevelAdjust = 0, - float solidAngleHalfTan = 0.1f, + float lodAngleHalfTan = 0.1f, RenderMode renderMode = DEFAULT_RENDER_MODE, DisplayMode displayMode = MONO, DebugFlags debugFlags = RENDER_DEBUG_NONE, gpu::Batch* batch = nullptr) : _context(context), _sizeScale(sizeScale), - _solidAngleHalfTan(solidAngleHalfTan), - _solidAngleHalfTanSq(solidAngleHalfTan * solidAngleHalfTan), _boundaryLevelAdjust(boundaryLevelAdjust), + _lodAngleHalfTan(lodAngleHalfTan), + _lodAngleHalfTanSq(lodAngleHalfTan * lodAngleHalfTan), _renderMode(renderMode), _displayMode(displayMode), _debugFlags(debugFlags), @@ -111,8 +111,8 @@ namespace render { float _sizeScale { 1.0f }; int _boundaryLevelAdjust { 0 }; - float _solidAngleHalfTan{ 0.1f }; - float _solidAngleHalfTanSq{ _solidAngleHalfTan * _solidAngleHalfTan }; + float _lodAngleHalfTan{ 0.1f }; + float _lodAngleHalfTanSq{ _lodAngleHalfTan * _lodAngleHalfTan }; RenderMode _renderMode { DEFAULT_RENDER_MODE }; DisplayMode _displayMode { MONO }; diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index 7d03f67d3f..b2930032a3 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -155,7 +155,7 @@ void FetchSpatialTree::run(const RenderContextPointer& renderContext, const Inpu // Octree selection! float threshold = 0.0f; if (queryFrustum.isPerspective()) { - threshold = getPerspectiveAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust); + threshold = args->_lodAngleHalfTan; if (frustumResolution.y > 0) { threshold = glm::max(queryFrustum.getFieldOfView() / frustumResolution.y, threshold); } diff --git a/scripts/developer/utilities/render/lod.qml b/scripts/developer/utilities/render/lod.qml index 28cf744394..889d8db836 100644 --- a/scripts/developer/utilities/render/lod.qml +++ b/scripts/developer/utilities/render/lod.qml @@ -217,24 +217,19 @@ Item { valueUnit: "Hz" plots: [ { - prop: "lodIncreaseFPS", - label: "LOD++", + prop: "lodTargetFPS", + label: "target", color: "#66FF66" }, { - prop: "fps", + prop: "nowRenderFPS", label: "FPS", color: "#FFFF55" }, { - prop: "smoothFPS", + prop: "smoothRenderFPS", label: "Smooth FPS", color: "#9999FF" - }, - { - prop: "lodDecreaseFPS", - label: "LOD--", - color: "#FF6666" } ] } From 0ae18febc762753a0b066315f724c7968b388623 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 30 Aug 2018 22:09:48 -0700 Subject: [PATCH 15/24] Removing cruft and warnings --- interface/src/LODManager.cpp | 7 ------- interface/src/ui/Stats.cpp | 36 +++++++++++++++++++----------------- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 738c3dd9fb..48fd44438f 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -36,12 +36,6 @@ LODManager::LODManager() { // faster than the runningAverage is computed, the error between the value and its runningAverage will be // reduced by 1/e every timescale of real-time that passes. const float LOD_ADJUST_RUNNING_AVG_TIMESCALE = 0.08f; // sec -// -// Assuming the measured value is affected by logic invoked by the runningAverage bumping up against its -// thresholds, we expect the adjustment to introduce a step-function. We want the runningAverage to settle -// to the new value BEFORE we test it aginst its thresholds again. Hence we test on a period that is a few -// multiples of the running average timescale: -const uint64_t LOD_AUTO_ADJUST_PERIOD = 4 * (uint64_t)(LOD_ADJUST_RUNNING_AVG_TIMESCALE * (float)USECS_PER_MSEC); // usec // batchTIme is always contained in presentTime. // We favor using batchTime instead of presentTime as a representative value for rendering duration (on present thread) @@ -220,7 +214,6 @@ float LODManager::getPidO() const { } void LODManager::resetLODAdjust() { - // _decreaseFPSExpiry = _increaseFPSExpiry = usecTimestampNow() + LOD_AUTO_ADJUST_PERIOD; } void LODManager::setAutomaticLODAdjust(bool value) { diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 3fa712d267..1b26c9b621 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -370,27 +370,29 @@ void Stats::updateStats(bool force) { STAT_UPDATE(engineFrameTime, (float) config->getCPURunTime()); STAT_UPDATE(avatarSimulationTime, (float)avatarManager->getAvatarSimulationTime()); - STAT_UPDATE(gpuBuffers, (int)gpu::Context::getBufferGPUCount()); - STAT_UPDATE(gpuBufferMemory, (int)BYTES_TO_MB(gpu::Context::getBufferGPUMemSize())); - STAT_UPDATE(gpuTextures, (int)gpu::Context::getTextureGPUCount()); + if (_expanded) { + STAT_UPDATE(gpuBuffers, (int)gpu::Context::getBufferGPUCount()); + STAT_UPDATE(gpuBufferMemory, (int)BYTES_TO_MB(gpu::Context::getBufferGPUMemSize())); + STAT_UPDATE(gpuTextures, (int)gpu::Context::getTextureGPUCount()); - STAT_UPDATE(glContextSwapchainMemory, (int)BYTES_TO_MB(gl::Context::getSwapchainMemoryUsage())); + STAT_UPDATE(glContextSwapchainMemory, (int)BYTES_TO_MB(gl::Context::getSwapchainMemoryUsage())); - STAT_UPDATE(qmlTextureMemory, (int)BYTES_TO_MB(OffscreenQmlSurface::getUsedTextureMemory())); - STAT_UPDATE(texturePendingTransfers, (int)BYTES_TO_MB(gpu::Context::getTexturePendingGPUTransferMemSize())); - STAT_UPDATE(gpuTextureMemory, (int)BYTES_TO_MB(gpu::Context::getTextureGPUMemSize())); - STAT_UPDATE(gpuTextureResidentMemory, (int)BYTES_TO_MB(gpu::Context::getTextureResidentGPUMemSize())); - STAT_UPDATE(gpuTextureFramebufferMemory, (int)BYTES_TO_MB(gpu::Context::getTextureFramebufferGPUMemSize())); - STAT_UPDATE(gpuTextureResourceMemory, (int)BYTES_TO_MB(gpu::Context::getTextureResourceGPUMemSize())); - STAT_UPDATE(gpuTextureResourceIdealMemory, (int)BYTES_TO_MB(gpu::Context::getTextureResourceIdealGPUMemSize())); - STAT_UPDATE(gpuTextureResourcePopulatedMemory, (int)BYTES_TO_MB(gpu::Context::getTextureResourcePopulatedGPUMemSize())); - STAT_UPDATE(gpuTextureExternalMemory, (int)BYTES_TO_MB(gpu::Context::getTextureExternalGPUMemSize())); + STAT_UPDATE(qmlTextureMemory, (int)BYTES_TO_MB(OffscreenQmlSurface::getUsedTextureMemory())); + STAT_UPDATE(texturePendingTransfers, (int)BYTES_TO_MB(gpu::Context::getTexturePendingGPUTransferMemSize())); + STAT_UPDATE(gpuTextureMemory, (int)BYTES_TO_MB(gpu::Context::getTextureGPUMemSize())); + STAT_UPDATE(gpuTextureResidentMemory, (int)BYTES_TO_MB(gpu::Context::getTextureResidentGPUMemSize())); + STAT_UPDATE(gpuTextureFramebufferMemory, (int)BYTES_TO_MB(gpu::Context::getTextureFramebufferGPUMemSize())); + STAT_UPDATE(gpuTextureResourceMemory, (int)BYTES_TO_MB(gpu::Context::getTextureResourceGPUMemSize())); + STAT_UPDATE(gpuTextureResourceIdealMemory, (int)BYTES_TO_MB(gpu::Context::getTextureResourceIdealGPUMemSize())); + STAT_UPDATE(gpuTextureResourcePopulatedMemory, (int)BYTES_TO_MB(gpu::Context::getTextureResourcePopulatedGPUMemSize())); + STAT_UPDATE(gpuTextureExternalMemory, (int)BYTES_TO_MB(gpu::Context::getTextureExternalGPUMemSize())); #if !defined(Q_OS_ANDROID) - STAT_UPDATE(gpuTextureMemoryPressureState, getTextureMemoryPressureModeString()); + STAT_UPDATE(gpuTextureMemoryPressureState, getTextureMemoryPressureModeString()); #endif - STAT_UPDATE(gpuFreeMemory, (int)BYTES_TO_MB(gpu::Context::getFreeGPUMemSize())); - STAT_UPDATE(rectifiedTextureCount, (int)RECTIFIED_TEXTURE_COUNT.load()); - STAT_UPDATE(decimatedTextureCount, (int)DECIMATED_TEXTURE_COUNT.load()); + STAT_UPDATE(gpuFreeMemory, (int)BYTES_TO_MB(gpu::Context::getFreeGPUMemSize())); + STAT_UPDATE(rectifiedTextureCount, (int)RECTIFIED_TEXTURE_COUNT.load()); + STAT_UPDATE(decimatedTextureCount, (int)DECIMATED_TEXTURE_COUNT.load()); + } gpu::ContextStats gpuFrameStats; gpuContext->getFrameStats(gpuFrameStats); From 371105d0c44e8fd04a4ae7375bf0f64c0dda3b75 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 30 Aug 2018 22:18:34 -0700 Subject: [PATCH 16/24] Removing cruft and warnings --- interface/src/ui/Stats.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index ed88f4fc6b..a0453a09c5 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -93,7 +93,6 @@ private: \ * @property {number} processing - Read-only. * @property {number} processingPending - Read-only. * @property {number} triangles - Read-only. - * @property {number} quads - Read-only. * @property {number} materialSwitches - Read-only. * @property {number} itemConsidered - Read-only. * @property {number} itemOutOfView - Read-only. @@ -250,7 +249,6 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, processingPending, 0) STATS_PROPERTY(int, triangles, 0) STATS_PROPERTY(int, drawcalls, 0) - // STATS_PROPERTY(int, quads, 0) STATS_PROPERTY(int, materialSwitches, 0) STATS_PROPERTY(int, itemConsidered, 0) STATS_PROPERTY(int, itemOutOfView, 0) @@ -743,13 +741,6 @@ signals: */ void drawcallsChanged(); - /**jsdoc - * Triggered when the value of the quads property changes. - * @function Stats.quadsChanged - * @returns {Signal} - */ - // void quadsChanged(); - /**jsdoc * Triggered when the value of the materialSwitches property changes. * @function Stats.materialSwitchesChanged From 969d16262f046606469e89f0bcf0421c3082e90c Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 30 Aug 2018 22:20:30 -0700 Subject: [PATCH 17/24] Removing cruft and warnings --- scripts/developer/utilities/render/lod.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/scripts/developer/utilities/render/lod.js b/scripts/developer/utilities/render/lod.js index 632f4e50c5..f3e4208034 100644 --- a/scripts/developer/utilities/render/lod.js +++ b/scripts/developer/utilities/render/lod.js @@ -56,7 +56,6 @@ presentationMode: Desktop.PresentationMode.NATIVE, size: {x: 400, y: 600} }); - // window.setPosition(200, 50); window.closed.connect(killWindow); window.fromQml.connect(fromQml); onScreen = true @@ -94,11 +93,7 @@ function onScreenChanged(type, url) { if (onTablet) { - if (url === QMLAPP_URL) { - onAppScreen = true; - } else { - onAppScreen = false; - } + onAppScreen = (url === QMLAPP_URL); button.editProperties({isActive: onAppScreen}); wireEventBridge(onAppScreen); From 764f75c3404472e994dc5c35cba14ef6be8bbe0e Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 30 Aug 2018 22:26:45 -0700 Subject: [PATCH 18/24] including review feedback --- interface/src/LODManager.cpp | 2 +- interface/src/LODManager.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 48fd44438f..c1ff6cfd6a 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -72,7 +72,7 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { float smoothBlend = (realTimeDelta < LOD_ADJUST_RUNNING_AVG_TIMESCALE * _smoothScale) ? realTimeDelta / (LOD_ADJUST_RUNNING_AVG_TIMESCALE * _smoothScale) : 1.0f; _smoothRenderTime = (1.0f - smoothBlend) * _smoothRenderTime + smoothBlend * maxRenderTime; // msec - if (!_automaticLODAdjust || _nowRenderTime == 0.0f) { + if (!_automaticLODAdjust || _nowRenderTime == 0.0f || _smoothRenderTime == 0.0f) { // early exit return; } diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 0af745bcf4..1452c714e9 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -173,13 +173,13 @@ public: void resetLODAdjust(); float getNowRenderTime() const { return _nowRenderTime; }; - float getNowRenderFPS() const { return (float)MSECS_PER_SECOND / _nowRenderTime; }; + float getNowRenderFPS() const { return (_nowRenderTime > 0.0f ? (float)MSECS_PER_SECOND / _nowRenderTime : 0.0f); }; void setSmoothScale(float t); float getSmoothScale() const { return _smoothScale; } float getSmoothRenderTime() const { return _smoothRenderTime; }; - float getSmoothRenderFPS() const { return (float)MSECS_PER_SECOND / _smoothRenderTime; }; + float getSmoothRenderFPS() const { return (_smoothRenderTime > 0.0f ? (float)MSECS_PER_SECOND / _smoothRenderTime : 0.0f); }; void setWorldDetailQuality(float quality); float getWorldDetailQuality() const; From eb5f6c8eb30e4bd8ea997b81d4480b05181f9610 Mon Sep 17 00:00:00 2001 From: sam gateau Date: Fri, 31 Aug 2018 09:07:34 -0700 Subject: [PATCH 19/24] ardressing coding standard --- interface/src/LODManager.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index c1ff6cfd6a..87771f1c6f 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -280,14 +280,11 @@ QString LODManager::getLODFeedbackText() { QString result; if (relativeToDefault > 1.01f) { result = QString("20:%1 or %2 times further than average vision%3").arg(relativeToTwentyTwenty).arg(relativeToDefault, 0, 'f', 2).arg(granularityFeedback); - } - else if (relativeToDefault > 0.99f) { + } else if (relativeToDefault > 0.99f) { result = QString("20:20 or the default distance for average vision%1").arg(granularityFeedback); - } - else if (relativeToDefault > 0.01f) { + } else if (relativeToDefault > 0.01f) { result = QString("20:%1 or %2 of default distance for average vision%3").arg(relativeToTwentyTwenty).arg(relativeToDefault, 0, 'f', 3).arg(granularityFeedback); - } - else { + } else { result = QString("%2 of default distance for average vision%3").arg(relativeToDefault, 0, 'f', 3).arg(granularityFeedback); } return result; From 262fdb3c28ccc76fc788ef69929f0095b11cd0e1 Mon Sep 17 00:00:00 2001 From: sam gateau Date: Fri, 31 Aug 2018 09:09:22 -0700 Subject: [PATCH 20/24] ardressing coding standard --- interface/src/LODManager.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 87771f1c6f..8f1289f9f2 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -350,8 +350,7 @@ void LODManager::setWorldDetailQuality(float quality) { if (isHMDMode) { setHMDLODTargetFPS(desiredFPS); - } - else { + } else { setDesktopLODTargetFPS(desiredFPS); } @@ -377,8 +376,7 @@ float LODManager::getWorldDetailQuality() const { if (percentage <= LOW) { return LOW; - } - else if (percentage <= MEDIUM) { + } else if (percentage <= MEDIUM) { return MEDIUM; } From 6bd1ab5ae05a4296b7ea68b35f6d734d3f3a2ede Mon Sep 17 00:00:00 2001 From: sam gateau Date: Fri, 31 Aug 2018 09:18:33 -0700 Subject: [PATCH 21/24] fixing a bad constant --- interface/src/LODManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 8f1289f9f2..ec50190ddf 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -42,7 +42,7 @@ const float LOD_ADJUST_RUNNING_AVG_TIMESCALE = 0.08f; // sec // if batchTime + cushionTime < presentTime. // since we are shooting for fps around 60, 90Hz, the ideal frames are around 10ms // so we are picking a cushion time of 3ms -const float LOD_BATCH_TO_PRESENT_CUSHION_TIME = 10.0f; // msec +const float LOD_BATCH_TO_PRESENT_CUSHION_TIME = 3.0f; // msec void LODManager::setRenderTimes(float presentTime, float engineRunTime, float batchTime, float gpuTime) { _presentTime = presentTime; From 84ad5c79f9e323760efca6259f5d78fa304abdda Mon Sep 17 00:00:00 2001 From: sam gateau Date: Fri, 31 Aug 2018 11:09:16 -0700 Subject: [PATCH 22/24] fixing a no op --- interface/src/LODManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index ec50190ddf..a64e28bea4 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -385,7 +385,7 @@ float LODManager::getWorldDetailQuality() const { void LODManager::setLODQualityLevel(float quality) { - _lodQualityLevel; + _lodQualityLevel = quality; } float LODManager::getLODQualityLevel() const { From ec18806546f56a6d35ba4cfc21b3808a3997b3f3 Mon Sep 17 00:00:00 2001 From: sam gateau Date: Fri, 31 Aug 2018 12:15:28 -0700 Subject: [PATCH 23/24] INtegrating in the algorithm, not in the public values the overshoot for the target FPS to make it simpler to understand --- interface/src/LODManager.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index a64e28bea4..1947374b1f 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -19,8 +19,8 @@ #include "ui/DialogsManager.h" #include "InterfaceLogging.h" -const float LODManager::DEFAULT_DESKTOP_LOD_DOWN_FPS = LOD_OFFSET_FPS + LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_DESKTOP_FPS; -const float LODManager::DEFAULT_HMD_LOD_DOWN_FPS = LOD_OFFSET_FPS + LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_HMD_FPS; +const float LODManager::DEFAULT_DESKTOP_LOD_DOWN_FPS = LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_DESKTOP_FPS; +const float LODManager::DEFAULT_HMD_LOD_DOWN_FPS = LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_HMD_FPS; Setting::Handle desktopLODDecreaseFPS("desktopLODDecreaseFPS", LODManager::DEFAULT_DESKTOP_LOD_DOWN_FPS); Setting::Handle hmdLODDecreaseFPS("hmdLODDecreaseFPS", LODManager::DEFAULT_HMD_LOD_DOWN_FPS); @@ -81,8 +81,10 @@ void LODManager::autoAdjustLOD(float realTimeDelta) { float oldOctreeSizeScale = getOctreeSizeScale(); float oldLODAngle = getLODAngleDeg(); - // Target fps and current fps based on latest measurments - float targetFPS = getLODTargetFPS(); + // Target fps is slightly overshooted by 5hz + float targetFPS = getLODTargetFPS() + LOD_OFFSET_FPS; + + // Current fps based on latest measurments float currentNowFPS = (float)MSECS_PER_SECOND / _nowRenderTime; float currentSmoothFPS = (float)MSECS_PER_SECOND / _smoothRenderTime; From 5067047e52b169a42ffb373fb764561ffa012052 Mon Sep 17 00:00:00 2001 From: sam gateau Date: Fri, 31 Aug 2018 14:24:52 -0700 Subject: [PATCH 24/24] warnings on ubuntu --- interface/src/LODManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 1947374b1f..2b5ca9ae8c 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -160,7 +160,7 @@ float LODManager::getLODAngleHalfTan() const { return getPerspectiveAccuracyAngleTan(_octreeSizeScale, _boundaryLevelAdjust); } float LODManager::getLODAngle() const { - return 2.0f * atan(getLODAngleHalfTan()); + return 2.0f * atanf(getLODAngleHalfTan()); } float LODManager::getLODAngleDeg() const { return glm::degrees(getLODAngle()); @@ -367,14 +367,14 @@ float LODManager::getWorldDetailQuality() const { bool inHMD = qApp->isHMDMode(); - float targetFPS = 0; + float targetFPS = 0.0f; if (inHMD) { targetFPS = getHMDLODTargetFPS(); } else { targetFPS = getDesktopLODTargetFPS(); } float maxFPS = inHMD ? LOD_MAX_LIKELY_HMD_FPS : LOD_MAX_LIKELY_DESKTOP_FPS; - float percentage = 1.0 - targetFPS / maxFPS; + float percentage = 1.0f - targetFPS / maxFPS; if (percentage <= LOW) { return LOW;