From 473f8d0ca5918bc8b8fc3ff322ec0a527809cc3f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 23 Aug 2018 11:39:47 -0700 Subject: [PATCH 01/46] 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/46] 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/46] 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/46] 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/46] 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/46] 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/46] 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/46] 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/46] 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/46] 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/46] 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/46] 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/46] 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 5f08ed5027a8904242a47b17e994ab4f309e3930 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 30 Aug 2018 15:13:52 -0700 Subject: [PATCH 14/46] misc perf improvements --- .../src/avatars/AvatarMixerSlave.cpp | 6 +- interface/src/avatar/AvatarManager.cpp | 23 +++----- interface/src/avatar/OtherAvatar.cpp | 9 ++- .../src/controllers/UserInputMapper.cpp | 6 +- .../src/EntityTreeRenderer.cpp | 9 ++- .../graphics/src/graphics/BufferViewHelpers.h | 5 +- libraries/shared/src/AABox.cpp | 56 ++++--------------- libraries/shared/src/AABox.h | 17 +++++- libraries/shared/src/GLMHelpers.h | 8 +++ libraries/shared/src/PrioritySortUtil.h | 15 +++-- tests/shared/src/AACubeTests.cpp | 2 +- tests/shared/src/GLMHelpersTests.cpp | 36 ++++++++++++ tests/shared/src/GLMHelpersTests.h | 1 + 13 files changed, 108 insertions(+), 85 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index f347ff1f10..59c6db5dc4 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -429,9 +429,9 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) int remainingAvatars = (int)sortedAvatars.size(); auto traitsPacketList = NLPacketList::create(PacketType::BulkAvatarTraits, QByteArray(), true, true); - while (!sortedAvatars.empty()) { - const auto avatarData = sortedAvatars.top().getAvatar(); - sortedAvatars.pop(); + const auto& sortedAvatarVector = sortedAvatars.getSortedVector(); + for (const auto& sortedAvatar : sortedAvatarVector) { + const auto& avatarData = sortedAvatar.getAvatar(); remainingAvatars--; auto otherNode = avatarDataToNodes[avatarData]; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 9a7d8ef0c8..af9d9ad6b1 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -206,6 +206,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { } ++itr; } + const auto& sortedAvatarVector = sortedAvatars.getSortedVector(); // process in sorted order uint64_t startTime = usecTimestampNow(); @@ -216,8 +217,8 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { render::Transaction renderTransaction; workload::Transaction workloadTransaction; - while (!sortedAvatars.empty()) { - const SortableAvatar& sortData = sortedAvatars.top(); + for (auto it = sortedAvatarVector.begin(); it != sortedAvatarVector.end(); ++it) { + const SortableAvatar& sortData = *it; const auto avatar = std::static_pointer_cast(sortData.getAvatar()); // TODO: to help us scale to more avatars it would be nice to not have to poll orb state here @@ -231,7 +232,6 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { bool ignoring = DependencyManager::get()->isPersonalMutingNode(avatar->getID()); if (ignoring) { - sortedAvatars.pop(); continue; } @@ -260,26 +260,17 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { // --> some avatar velocity measurements may be a little off // no time to simulate, but we take the time to count how many were tragically missed - bool inView = sortData.getPriority() > OUT_OF_VIEW_THRESHOLD; - if (!inView) { - break; - } - if (inView && avatar->hasNewJointData()) { - numAVatarsNotUpdated++; - } - sortedAvatars.pop(); - while (inView && !sortedAvatars.empty()) { - const SortableAvatar& newSortData = sortedAvatars.top(); + while (it != sortedAvatarVector.end()) { + const SortableAvatar& newSortData = *it; const auto newAvatar = std::static_pointer_cast(newSortData.getAvatar()); - inView = newSortData.getPriority() > OUT_OF_VIEW_THRESHOLD; + bool inView = newSortData.getPriority() > OUT_OF_VIEW_THRESHOLD; if (inView && newAvatar->hasNewJointData()) { numAVatarsNotUpdated++; } - sortedAvatars.pop(); + ++it; } break; } - sortedAvatars.pop(); } if (_shouldRender) { diff --git a/interface/src/avatar/OtherAvatar.cpp b/interface/src/avatar/OtherAvatar.cpp index 29ad5aed91..a0fa496c4c 100644 --- a/interface/src/avatar/OtherAvatar.cpp +++ b/interface/src/avatar/OtherAvatar.cpp @@ -29,20 +29,23 @@ OtherAvatar::~OtherAvatar() { } void OtherAvatar::removeOrb() { - if (qApp->getOverlays().isAddedOverlay(_otherAvatarOrbMeshPlaceholderID)) { + if (!_otherAvatarOrbMeshPlaceholderID.isNull()) { qApp->getOverlays().deleteOverlay(_otherAvatarOrbMeshPlaceholderID); + _otherAvatarOrbMeshPlaceholderID = UNKNOWN_OVERLAY_ID; } } void OtherAvatar::updateOrbPosition() { if (_otherAvatarOrbMeshPlaceholder != nullptr) { _otherAvatarOrbMeshPlaceholder->setWorldPosition(getHead()->getPosition()); + if (_otherAvatarOrbMeshPlaceholderID.isNull()) { + _otherAvatarOrbMeshPlaceholderID = qApp->getOverlays().addOverlay(_otherAvatarOrbMeshPlaceholder); + } } } void OtherAvatar::createOrb() { - if (_otherAvatarOrbMeshPlaceholderID == UNKNOWN_OVERLAY_ID || - !qApp->getOverlays().isAddedOverlay(_otherAvatarOrbMeshPlaceholderID)) { + if (_otherAvatarOrbMeshPlaceholderID.isNull()) { _otherAvatarOrbMeshPlaceholder = std::make_shared(); _otherAvatarOrbMeshPlaceholder->setAlpha(1.0f); _otherAvatarOrbMeshPlaceholder->setColor({ 0xFF, 0x00, 0xFF }); diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index 371deec7d5..307064c073 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -527,8 +527,8 @@ bool UserInputMapper::applyRoute(const Route::Pointer& route, bool force) { } // If the source hasn't been written yet, defer processing of this route - auto source = route->source; - auto sourceInput = source->getInput(); + auto& source = route->source; + auto& sourceInput = source->getInput(); if (sourceInput.device == STANDARD_DEVICE && !force && source->writeable()) { if (debugRoutes && route->debug) { qCDebug(controllers) << "Source not yet written, deferring"; @@ -559,7 +559,7 @@ bool UserInputMapper::applyRoute(const Route::Pointer& route, bool force) { return true; } - auto destination = route->destination; + auto& destination = route->destination; // THis could happen if the route destination failed to create // FIXME: Maybe do not create the route if the destination failed and avoid this case ? if (!destination) { diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index c3c4095251..a363093083 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -405,11 +405,14 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene // process the sorted renderables size_t numSorted = sortedRenderables.size(); - while (!sortedRenderables.empty() && usecTimestampNow() < expiry) { - const auto renderable = sortedRenderables.top().getRenderer(); + const auto& sortedRenderablesVector = sortedRenderables.getSortedVector(); + for (const auto& sortedRenderable : sortedRenderablesVector) { + if (usecTimestampNow() > expiry) { + break; + } + const auto& renderable = sortedRenderable.getRenderer(); renderable->updateInScene(scene, transaction); _renderablesToUpdate.erase(renderable->getEntity()->getID()); - sortedRenderables.pop(); } // compute average per-renderable update cost diff --git a/libraries/graphics/src/graphics/BufferViewHelpers.h b/libraries/graphics/src/graphics/BufferViewHelpers.h index a9707c3128..7c37c75163 100644 --- a/libraries/graphics/src/graphics/BufferViewHelpers.h +++ b/libraries/graphics/src/graphics/BufferViewHelpers.h @@ -13,6 +13,7 @@ #include #include "GpuHelpers.h" +#include "GLMHelpers.h" namespace graphics { class Mesh; @@ -55,8 +56,8 @@ namespace buffer_helpers { tangent = glm::clamp(tangent, -1.0f, 1.0f); normal *= 511.0f; tangent *= 511.0f; - normal = glm::round(normal); - tangent = glm::round(tangent); + normal = fastRoundf(normal); + tangent = fastRoundf(tangent); glm::detail::i10i10i10i2 normalStruct; glm::detail::i10i10i10i2 tangentStruct; diff --git a/libraries/shared/src/AABox.cpp b/libraries/shared/src/AABox.cpp index b4384c494f..e537c3e56a 100644 --- a/libraries/shared/src/AABox.cpp +++ b/libraries/shared/src/AABox.cpp @@ -79,33 +79,23 @@ void AABox::setBox(const glm::vec3& corner, const glm::vec3& scale) { glm::vec3 AABox::getFarthestVertex(const glm::vec3& normal) const { glm::vec3 result = _corner; - if (normal.x > 0.0f) { - result.x += _scale.x; - } - if (normal.y > 0.0f) { - result.y += _scale.y; - } - if (normal.z > 0.0f) { - result.z += _scale.z; - } + float blend = (float)(normal.x > 0.0f); + result.x += blend * _scale.x + (1.0f - blend) * 0.0f; + blend = (float)(normal.y > 0.0f); + result.y += blend * _scale.y + (1.0f - blend) * 0.0f; + blend = (float)(normal.z > 0.0f); + result.z += blend * _scale.z + (1.0f - blend) * 0.0f; return result; } glm::vec3 AABox::getNearestVertex(const glm::vec3& normal) const { glm::vec3 result = _corner; - - if (normal.x < 0.0f) { - result.x += _scale.x; - } - - if (normal.y < 0.0f) { - result.y += _scale.y; - } - - if (normal.z < 0.0f) { - result.z += _scale.z; - } - + float blend = (float)(normal.x < 0.0f); + result.x += blend * _scale.x + (1.0f - blend) * 0.0f; + blend = (float)(normal.y < 0.0f); + result.y += blend * _scale.y + (1.0f - blend) * 0.0f; + blend = (float)(normal.z < 0.0f); + result.z += blend * _scale.z + (1.0f - blend) * 0.0f; return result; } @@ -459,28 +449,6 @@ AABox AABox::clamp(float min, float max) const { return AABox(clampedCorner, clampedScale); } -AABox& AABox::operator += (const glm::vec3& point) { - - if (isInvalid()) { - _corner = glm::min(_corner, point); - } else { - glm::vec3 maximum(_corner + _scale); - _corner = glm::min(_corner, point); - maximum = glm::max(maximum, point); - _scale = maximum - _corner; - } - - return (*this); -} - -AABox& AABox::operator += (const AABox& box) { - if (!box.isInvalid()) { - (*this) += box._corner; - (*this) += box.calcTopFarLeft(); - } - return (*this); -} - void AABox::embiggen(float scale) { _corner += scale * (-0.5f * _scale); _scale *= scale; diff --git a/libraries/shared/src/AABox.h b/libraries/shared/src/AABox.h index daad01d7c7..a56615c40e 100644 --- a/libraries/shared/src/AABox.h +++ b/libraries/shared/src/AABox.h @@ -85,8 +85,21 @@ public: AABox clamp(const glm::vec3& min, const glm::vec3& max) const; AABox clamp(float min, float max) const; - AABox& operator += (const glm::vec3& point); - AABox& operator += (const AABox& box); + inline AABox& operator+=(const glm::vec3& point) { + float blend = (float)isInvalid(); + glm::vec3 maximumScale(glm::max(_scale, point - _corner)); + _corner = glm::min(_corner, point); + _scale = blend * _scale + (1.0f - blend) * maximumScale; + return (*this); + } + + inline AABox& operator+=(const AABox& box) { + if (!box.isInvalid()) { + (*this) += box._corner; + (*this) += box.calcTopFarLeft(); + } + return (*this); + } // Translate the AABox just moving the corner void translate(const glm::vec3& translation) { _corner += translation; } diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index 7e6ef4cb28..619f8172d5 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -316,4 +316,12 @@ inline void glm_mat4u_mul(const glm::mat4& m1, const glm::mat4& m2, glm::mat4& r #endif } +inline glm::vec3 fastRoundf(const glm::vec3& vec) { +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + return glm::vec3(_mm_cvt_ss2si(_mm_set_ss(vec.x)), _mm_cvt_ss2si(_mm_set_ss(vec.y)), _mm_cvt_ss2si(_mm_set_ss(vec.z))); +#else + return glm::round(vec); +#endif +} + #endif // hifi_GLMHelpers_h diff --git a/libraries/shared/src/PrioritySortUtil.h b/libraries/shared/src/PrioritySortUtil.h index 34ec074d45..e0137b3d8c 100644 --- a/libraries/shared/src/PrioritySortUtil.h +++ b/libraries/shared/src/PrioritySortUtil.h @@ -12,7 +12,6 @@ #define hifi_PrioritySortUtil_h #include -#include #include "NumericalConstants.h" #include "shared/ConicalViewFrustum.h" @@ -75,7 +74,6 @@ namespace PrioritySortUtil { void setPriority(float priority) { _priority = priority; } float getPriority() const { return _priority; } - bool operator<(const Sortable& other) const { return _priority < other._priority; } private: float _priority { 0.0f }; }; @@ -97,14 +95,15 @@ namespace PrioritySortUtil { _ageWeight = ageWeight; } - size_t size() const { return _queue.size(); } + size_t size() const { return _vector.size(); } void push(T thing) { thing.setPriority(computePriority(thing)); - _queue.push(thing); + _vector.push_back(thing); + } + const std::vector& getSortedVector() { + std::sort(_vector.begin(), _vector.end(), [](const T& left, const T& right) { return left.getPriority() > right.getPriority(); }); + return _vector; } - const T& top() const { return _queue.top(); } - void pop() { return _queue.pop(); } - bool empty() const { return _queue.empty(); } private: @@ -153,7 +152,7 @@ namespace PrioritySortUtil { } ConicalViewFrustums _views; - std::priority_queue _queue; + std::vector _vector; float _angularWeight { DEFAULT_ANGULAR_COEF }; float _centerWeight { DEFAULT_CENTER_COEF }; float _ageWeight { DEFAULT_AGE_COEF }; diff --git a/tests/shared/src/AACubeTests.cpp b/tests/shared/src/AACubeTests.cpp index 95a4d7f9f0..c3c8e3e6f7 100644 --- a/tests/shared/src/AACubeTests.cpp +++ b/tests/shared/src/AACubeTests.cpp @@ -173,7 +173,7 @@ void AACubeTests::rayVsParabolaPerformance() { glm::vec3 normal; auto start = std::chrono::high_resolution_clock::now(); for (auto& cube : cubes) { - if (cube.findRayIntersection(origin, direction, distance, face, normal)) { + if (cube.findRayIntersection(origin, direction, 1.0f / direction, distance, face, normal)) { numRayHits++; } } diff --git a/tests/shared/src/GLMHelpersTests.cpp b/tests/shared/src/GLMHelpersTests.cpp index 93c4735a6d..669bbb8e43 100644 --- a/tests/shared/src/GLMHelpersTests.cpp +++ b/tests/shared/src/GLMHelpersTests.cpp @@ -214,3 +214,39 @@ void GLMHelpersTests::testGenerateBasisVectors() { QCOMPARE_WITH_ABS_ERROR(w, z, EPSILON); } } + +void GLMHelpersTests::roundPerf() { + const int NUM_VECS = 1000000; + const float MAX_VEC = 500.0f; + std::vector vecs; + vecs.reserve(NUM_VECS); + for (int i = 0; i < NUM_VECS; i++) { + vecs.emplace_back(randFloatInRange(-MAX_VEC, MAX_VEC), randFloatInRange(-MAX_VEC, MAX_VEC), randFloatInRange(-MAX_VEC, MAX_VEC)); + } + std::vector vecs2 = vecs; + std::vector originalVecs = vecs; + + auto start = std::chrono::high_resolution_clock::now(); + for (auto& vec : vecs) { + vec = glm::round(vec); + } + + auto glmTime = std::chrono::high_resolution_clock::now() - start; + start = std::chrono::high_resolution_clock::now(); + for (auto& vec : vecs2) { + vec = fastRoundf(vec); + } + auto manualTime = std::chrono::high_resolution_clock::now() - start; + + bool identical = true; + for (int i = 0; i < vecs.size(); i++) { + identical &= vecs[i] == vecs2[i]; + if (vecs[i] != vecs2[i]) { + qDebug() << "glm: " << vecs[i].x << vecs[i].y << vecs[i].z << ", manual: " << vecs2[i].x << vecs2[i].y << vecs2[i].z; + qDebug() << "original: " << originalVecs[i].x << originalVecs[i].y << originalVecs[i].z; + break; + } + } + + qDebug() << "ratio: " << (float)glmTime.count() / (float)manualTime.count() << ", identical: " << identical; +} \ No newline at end of file diff --git a/tests/shared/src/GLMHelpersTests.h b/tests/shared/src/GLMHelpersTests.h index 030f2d477f..4d9bd0bb60 100644 --- a/tests/shared/src/GLMHelpersTests.h +++ b/tests/shared/src/GLMHelpersTests.h @@ -22,6 +22,7 @@ private slots: void testSixByteOrientationCompression(); void testSimd(); void testGenerateBasisVectors(); + void roundPerf(); }; float getErrorDifference(const float& a, const float& b); From 194903692ed5b7cc13e6b939a2bed89ea8c7ee26 Mon Sep 17 00:00:00 2001 From: sam gateau Date: Thu, 30 Aug 2018 18:09:11 -0700 Subject: [PATCH 15/46] 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 16/46] 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 17/46] 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 18/46] 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 19/46] 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 20/46] 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 21/46] 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 22/46] 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 23/46] 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 d01b438cb320a7ccc0aa8a0085e86940bb73c09c Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 31 Aug 2018 11:25:17 -0700 Subject: [PATCH 24/46] CR --- interface/src/avatar/AvatarManager.cpp | 6 ++++-- .../graphics/src/graphics/BufferViewHelpers.h | 14 ++++++------- libraries/shared/src/AABox.cpp | 20 +++++++++++++++++++ libraries/shared/src/AABox.h | 9 +++++++++ libraries/shared/src/GLMHelpers.h | 11 +++++++--- tests/shared/src/AACubeTests.cpp | 3 ++- tests/shared/src/GLMHelpersTests.cpp | 2 +- 7 files changed, 50 insertions(+), 15 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index af9d9ad6b1..bd98549510 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -264,9 +264,11 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { const SortableAvatar& newSortData = *it; const auto newAvatar = std::static_pointer_cast(newSortData.getAvatar()); bool inView = newSortData.getPriority() > OUT_OF_VIEW_THRESHOLD; - if (inView && newAvatar->hasNewJointData()) { - numAVatarsNotUpdated++; + // Once we reach an avatar that's not in view, all avatars after it will also be out of view + if (!inView) { + break; } + numAVatarsNotUpdated += (int)(newAvatar->hasNewJointData()); ++it; } break; diff --git a/libraries/graphics/src/graphics/BufferViewHelpers.h b/libraries/graphics/src/graphics/BufferViewHelpers.h index 7c37c75163..026e7b53a3 100644 --- a/libraries/graphics/src/graphics/BufferViewHelpers.h +++ b/libraries/graphics/src/graphics/BufferViewHelpers.h @@ -56,18 +56,16 @@ namespace buffer_helpers { tangent = glm::clamp(tangent, -1.0f, 1.0f); normal *= 511.0f; tangent *= 511.0f; - normal = fastRoundf(normal); - tangent = fastRoundf(tangent); glm::detail::i10i10i10i2 normalStruct; glm::detail::i10i10i10i2 tangentStruct; - normalStruct.data.x = int(normal.x); - normalStruct.data.y = int(normal.y); - normalStruct.data.z = int(normal.z); + normalStruct.data.x = fastLrintf(normal.x); + normalStruct.data.y = fastLrintf(normal.y); + normalStruct.data.z = fastLrintf(normal.z); normalStruct.data.w = 0; - tangentStruct.data.x = int(tangent.x); - tangentStruct.data.y = int(tangent.y); - tangentStruct.data.z = int(tangent.z); + tangentStruct.data.x = fastLrintf(tangent.x); + tangentStruct.data.y = fastLrintf(tangent.y); + tangentStruct.data.z = fastLrintf(tangent.z); tangentStruct.data.w = 0; packedNormal = normalStruct.pack; packedTangent = tangentStruct.pack; diff --git a/libraries/shared/src/AABox.cpp b/libraries/shared/src/AABox.cpp index e537c3e56a..ff6c2a4e6e 100644 --- a/libraries/shared/src/AABox.cpp +++ b/libraries/shared/src/AABox.cpp @@ -79,6 +79,16 @@ void AABox::setBox(const glm::vec3& corner, const glm::vec3& scale) { glm::vec3 AABox::getFarthestVertex(const glm::vec3& normal) const { glm::vec3 result = _corner; + // This is a branchless version of: + //if (normal.x > 0.0f) { + // result.x += _scale.x; + //} + //if (normal.y > 0.0f) { + // result.y += _scale.y; + //} + //if (normal.z > 0.0f) { + // result.z += _scale.z; + //} float blend = (float)(normal.x > 0.0f); result.x += blend * _scale.x + (1.0f - blend) * 0.0f; blend = (float)(normal.y > 0.0f); @@ -90,6 +100,16 @@ glm::vec3 AABox::getFarthestVertex(const glm::vec3& normal) const { glm::vec3 AABox::getNearestVertex(const glm::vec3& normal) const { glm::vec3 result = _corner; + // This is a branchless version of: + //if (normal.x < 0.0f) { + // result.x += _scale.x; + //} + //if (normal.y < 0.0f) { + // result.y += _scale.y; + //} + //if (normal.z < 0.0f) { + // result.z += _scale.z; + //} float blend = (float)(normal.x < 0.0f); result.x += blend * _scale.x + (1.0f - blend) * 0.0f; blend = (float)(normal.y < 0.0f); diff --git a/libraries/shared/src/AABox.h b/libraries/shared/src/AABox.h index a56615c40e..e0bb1343f8 100644 --- a/libraries/shared/src/AABox.h +++ b/libraries/shared/src/AABox.h @@ -86,6 +86,15 @@ public: AABox clamp(float min, float max) const; inline AABox& operator+=(const glm::vec3& point) { + // Branchless version of: + //if (isInvalid()) { + // _corner = glm::min(_corner, point); + //} else { + // glm::vec3 maximum(_corner + _scale); + // _corner = glm::min(_corner, point); + // maximum = glm::max(maximum, point); + // _scale = maximum - _corner; + //} float blend = (float)isInvalid(); glm::vec3 maximumScale(glm::max(_scale, point - _corner)); _corner = glm::min(_corner, point); diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index 619f8172d5..96219ea48c 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -316,11 +316,16 @@ inline void glm_mat4u_mul(const glm::mat4& m1, const glm::mat4& m2, glm::mat4& r #endif } -inline glm::vec3 fastRoundf(const glm::vec3& vec) { +// convert float to int, using round-to-nearest-even (undefined on overflow) +inline int fastLrintf(float x) { #if GLM_ARCH & GLM_ARCH_SSE2_BIT - return glm::vec3(_mm_cvt_ss2si(_mm_set_ss(vec.x)), _mm_cvt_ss2si(_mm_set_ss(vec.y)), _mm_cvt_ss2si(_mm_set_ss(vec.z))); + return _mm_cvt_ss2si(_mm_set_ss(x)); #else - return glm::round(vec); + // return lrintf(x); + static_assert(std::numeric_limits::is_iec559, "Requires IEEE-754 double precision format"); + union { double d; int64_t i; } bits = { (double)x }; + bits.d += (3ULL << 51); + return (int)bits.i; #endif } diff --git a/tests/shared/src/AACubeTests.cpp b/tests/shared/src/AACubeTests.cpp index c3c8e3e6f7..4ed3ee2813 100644 --- a/tests/shared/src/AACubeTests.cpp +++ b/tests/shared/src/AACubeTests.cpp @@ -168,12 +168,13 @@ void AACubeTests::rayVsParabolaPerformance() { glm::vec3 origin(0.0f); glm::vec3 direction = glm::normalize(glm::vec3(1.0f)); + glm::vec3 invDirection = 1.0f / direction; float distance; BoxFace face; glm::vec3 normal; auto start = std::chrono::high_resolution_clock::now(); for (auto& cube : cubes) { - if (cube.findRayIntersection(origin, direction, 1.0f / direction, distance, face, normal)) { + if (cube.findRayIntersection(origin, direction, invDirection, distance, face, normal)) { numRayHits++; } } diff --git a/tests/shared/src/GLMHelpersTests.cpp b/tests/shared/src/GLMHelpersTests.cpp index 669bbb8e43..71877e89f6 100644 --- a/tests/shared/src/GLMHelpersTests.cpp +++ b/tests/shared/src/GLMHelpersTests.cpp @@ -234,7 +234,7 @@ void GLMHelpersTests::roundPerf() { auto glmTime = std::chrono::high_resolution_clock::now() - start; start = std::chrono::high_resolution_clock::now(); for (auto& vec : vecs2) { - vec = fastRoundf(vec); + vec = glm::vec3(fastLrintf(vec.x), fastLrintf(vec.y), fastLrintf(vec.z)); } auto manualTime = std::chrono::high_resolution_clock::now() - start; From ec18806546f56a6d35ba4cfc21b3808a3997b3f3 Mon Sep 17 00:00:00 2001 From: sam gateau Date: Fri, 31 Aug 2018 12:15:28 -0700 Subject: [PATCH 25/46] 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 26/46] 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; From 48680329ec4b29076179eeb04c882408d575d53f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 29 Aug 2018 21:26:19 -0700 Subject: [PATCH 27/46] mark trait instances needing to be sent on mixer reconnect --- libraries/avatars/src/AvatarData.cpp | 12 +++++++++++- libraries/avatars/src/AvatarData.h | 2 ++ libraries/avatars/src/ClientTraitsHandler.cpp | 6 ++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index b86398501e..ea6dbd7074 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1895,6 +1895,16 @@ qint64 AvatarData::packTraitInstance(AvatarTraits::TraitType traitType, AvatarTr return bytesWritten; } +void AvatarData::prepareResetTraitInstances() { + if (_clientTraitsHandler) { + _avatarEntitiesLock.withReadLock([this]{ + foreach (auto entityID, _avatarEntityData.keys()) { + _clientTraitsHandler->markInstancedTraitUpdated(AvatarTraits::AvatarEntity, entityID); + } + }); + } +} + void AvatarData::processTrait(AvatarTraits::TraitType traitType, QByteArray traitBinaryData) { if (traitType == AvatarTraits::SkeletonModelURL) { // get the URL from the binary data @@ -2792,7 +2802,7 @@ void AvatarData::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) { if (_clientTraitsHandler) { // if we have a client traits handler, flag any updated or created entities // so that we send changes for them next frame - foreach (auto entityID, _avatarEntityData) { + foreach (auto entityID, _avatarEntityData.keys()) { _clientTraitsHandler->markInstancedTraitUpdated(AvatarTraits::AvatarEntity, entityID); } } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 0474d07acd..db2b82b0b7 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -964,6 +964,8 @@ public: qint64 packTraitInstance(AvatarTraits::TraitType traitType, AvatarTraits::TraitInstanceID instanceID, ExtendedIODevice& destination, AvatarTraits::TraitVersion traitVersion = AvatarTraits::NULL_TRAIT_VERSION); + void prepareResetTraitInstances(); + void processTrait(AvatarTraits::TraitType traitType, QByteArray traitBinaryData); void processTraitInstance(AvatarTraits::TraitType traitType, AvatarTraits::TraitInstanceID instanceID, QByteArray traitBinaryData); diff --git a/libraries/avatars/src/ClientTraitsHandler.cpp b/libraries/avatars/src/ClientTraitsHandler.cpp index c4073cb86a..a06b53da7c 100644 --- a/libraries/avatars/src/ClientTraitsHandler.cpp +++ b/libraries/avatars/src/ClientTraitsHandler.cpp @@ -37,6 +37,12 @@ void ClientTraitsHandler::resetForNewMixer() { // mark that all traits should be sent next time _shouldPerformInitialSend = true; + + // reset the trait statuses + _traitStatuses.reset(); + + // pre-fill the instanced statuses that we will need to send next frame + _owningAvatar->prepareResetTraitInstances(); } void ClientTraitsHandler::sendChangedTraitsToMixer() { From 20912349a4f0b8854bda467ee1e1bd04d9bb67ef Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 30 Aug 2018 12:59:28 -0700 Subject: [PATCH 28/46] cycle avatar entity IDs for new avatar mixer --- interface/src/Application.cpp | 1 - .../src/avatars-renderer/Avatar.cpp | 1 - libraries/avatars/src/AvatarData.cpp | 10 ++++++++-- libraries/avatars/src/AvatarData.h | 3 ++- libraries/avatars/src/AvatarTraits.h | 2 +- libraries/avatars/src/ClientTraitsHandler.cpp | 20 ++++++++++++++++++- libraries/avatars/src/ClientTraitsHandler.h | 8 ++++++-- 7 files changed, 36 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6e57311306..2a7abfa2da 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6366,7 +6366,6 @@ void Application::clearDomainOctreeDetails() { } void Application::clearDomainAvatars() { - getMyAvatar()->setAvatarEntityDataChanged(true); // to recreate worn entities DependencyManager::get()->clearOtherAvatars(); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index a9af3b7725..4ffccefe61 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -139,7 +139,6 @@ Avatar::~Avatar() { } }); } - auto geometryCache = DependencyManager::get(); if (geometryCache) { geometryCache->releaseID(_nameRectGeometryID); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index ea6dbd7074..e7aaa18576 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1861,7 +1861,9 @@ qint64 AvatarData::packTrait(AvatarTraits::TraitType traitType, ExtendedIODevice } qint64 AvatarData::packTraitInstance(AvatarTraits::TraitType traitType, AvatarTraits::TraitInstanceID traitInstanceID, - ExtendedIODevice& destination, AvatarTraits::TraitVersion traitVersion) { + ExtendedIODevice& destination, AvatarTraits::TraitVersion traitVersion, + AvatarTraits::TraitInstanceID wireInstanceID) { + qint64 bytesWritten = 0; bytesWritten += destination.writePrimitive(traitType); @@ -1870,7 +1872,11 @@ qint64 AvatarData::packTraitInstance(AvatarTraits::TraitType traitType, AvatarTr bytesWritten += destination.writePrimitive(traitVersion); } - bytesWritten += destination.write(traitInstanceID.toRfc4122()); + if (!wireInstanceID.isNull()) { + bytesWritten += destination.write(wireInstanceID.toRfc4122()); + } else { + bytesWritten += destination.write(traitInstanceID.toRfc4122()); + } if (traitType == AvatarTraits::AvatarEntity) { // grab a read lock on the avatar entities and check for entity data for the given ID diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index db2b82b0b7..b010a9f924 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -962,7 +962,8 @@ public: qint64 packTrait(AvatarTraits::TraitType traitType, ExtendedIODevice& destination, AvatarTraits::TraitVersion traitVersion = AvatarTraits::NULL_TRAIT_VERSION); qint64 packTraitInstance(AvatarTraits::TraitType traitType, AvatarTraits::TraitInstanceID instanceID, - ExtendedIODevice& destination, AvatarTraits::TraitVersion traitVersion = AvatarTraits::NULL_TRAIT_VERSION); + ExtendedIODevice& destination, AvatarTraits::TraitVersion traitVersion = AvatarTraits::NULL_TRAIT_VERSION, + AvatarTraits::TraitInstanceID wireInstanceID = AvatarTraits::TraitInstanceID()); void prepareResetTraitInstances(); diff --git a/libraries/avatars/src/AvatarTraits.h b/libraries/avatars/src/AvatarTraits.h index f0c807a432..5866caf234 100644 --- a/libraries/avatars/src/AvatarTraits.h +++ b/libraries/avatars/src/AvatarTraits.h @@ -41,7 +41,7 @@ namespace AvatarTraits { const TraitWireSize DELETED_TRAIT_SIZE = -1; inline qint64 packInstancedTraitDelete(TraitType traitType, TraitInstanceID instanceID, ExtendedIODevice& destination, - TraitVersion traitVersion = NULL_TRAIT_VERSION) { + TraitVersion traitVersion = NULL_TRAIT_VERSION) { qint64 bytesWritten = 0; bytesWritten += destination.writePrimitive(traitType); diff --git a/libraries/avatars/src/ClientTraitsHandler.cpp b/libraries/avatars/src/ClientTraitsHandler.cpp index a06b53da7c..94823610dc 100644 --- a/libraries/avatars/src/ClientTraitsHandler.cpp +++ b/libraries/avatars/src/ClientTraitsHandler.cpp @@ -43,6 +43,9 @@ void ClientTraitsHandler::resetForNewMixer() { // pre-fill the instanced statuses that we will need to send next frame _owningAvatar->prepareResetTraitInstances(); + + // reset the trait XOR ID since we're resetting for a new avatar mixer + _sessionXORID = QUuid::createUuid().toRfc4122(); } void ClientTraitsHandler::sendChangedTraitsToMixer() { @@ -93,7 +96,11 @@ void ClientTraitsHandler::sendChangedTraitsToMixer() { || instanceIDValuePair.value == Updated) { // this is a changed trait we need to send or we haven't send out trait information yet // ask the owning avatar to pack it - _owningAvatar->packTraitInstance(instancedIt->traitType, instanceIDValuePair.id, *traitsPacketList); + + // since this is going to the mixer, use the XORed instance ID (to anonymize trait instance IDs + // that would typically persist across sessions) + _owningAvatar->packTraitInstance(instancedIt->traitType, instanceIDValuePair.id, *traitsPacketList, + AvatarTraits::NULL_TRAIT_VERSION, xorInstanceID(instanceIDValuePair.id)); } else if (!_shouldPerformInitialSend && instanceIDValuePair.value == Deleted) { // pack delete for this trait instance AvatarTraits::packInstancedTraitDelete(instancedIt->traitType, instanceIDValuePair.id, @@ -111,6 +118,17 @@ void ClientTraitsHandler::sendChangedTraitsToMixer() { } } +AvatarTraits::TraitInstanceID ClientTraitsHandler::xorInstanceID(AvatarTraits::TraitInstanceID localInstanceID) { + QByteArray xorInstanceID { NUM_BYTES_RFC4122_UUID, 0 }; + auto localInstanceIDBytes = localInstanceID.toRfc4122(); + + for (auto i = 0; i < localInstanceIDBytes.size(); ++i) { + xorInstanceID[i] = localInstanceIDBytes[i] ^ _sessionXORID[i]; + } + + return QUuid::fromRfc4122(xorInstanceID); +} + void ClientTraitsHandler::processTraitOverride(QSharedPointer message, SharedNodePointer sendingNode) { if (sendingNode->getType() == NodeType::AvatarMixer) { while (message->getBytesLeftToRead()) { diff --git a/libraries/avatars/src/ClientTraitsHandler.h b/libraries/avatars/src/ClientTraitsHandler.h index 27ba58d46b..2319061502 100644 --- a/libraries/avatars/src/ClientTraitsHandler.h +++ b/libraries/avatars/src/ClientTraitsHandler.h @@ -30,13 +30,15 @@ public: void markTraitUpdated(AvatarTraits::TraitType updatedTrait) { _traitStatuses[updatedTrait] = Updated; _hasChangedTraits = true; } - void markInstancedTraitUpdated(AvatarTraits::TraitType traitType, QUuid updatedInstanceID) + void markInstancedTraitUpdated(AvatarTraits::TraitType traitType, AvatarTraits::TraitInstanceID updatedInstanceID) { _traitStatuses.instanceInsert(traitType, updatedInstanceID, Updated); _hasChangedTraits = true; } - void markInstancedTraitDeleted(AvatarTraits::TraitType traitType, QUuid deleteInstanceID) + void markInstancedTraitDeleted(AvatarTraits::TraitType traitType, AvatarTraits::TraitInstanceID deleteInstanceID) { _traitStatuses.instanceInsert(traitType, deleteInstanceID, Deleted); _hasChangedTraits = true; } void resetForNewMixer(); + AvatarTraits::TraitInstanceID xorInstanceID(AvatarTraits::TraitInstanceID localInstanceID); + public slots: void processTraitOverride(QSharedPointer message, SharedNodePointer sendingNode); @@ -53,6 +55,8 @@ private: AvatarTraits::TraitVersion _currentTraitVersion { AvatarTraits::DEFAULT_TRAIT_VERSION }; AvatarTraits::TraitVersion _currentSkeletonVersion { AvatarTraits::NULL_TRAIT_VERSION }; + + QByteArray _sessionXORID { NUM_BYTES_RFC4122_UUID, 0}; bool _shouldPerformInitialSend { false }; bool _hasChangedTraits { false }; From 9b3d9dd0f319ad2964e54a72bd17934765a91c02 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 31 Aug 2018 16:31:33 -0700 Subject: [PATCH 29/46] XOR incoming trait instance IDs for other avatars --- libraries/avatars/src/AvatarData.h | 5 +++++ libraries/avatars/src/AvatarHashMap.cpp | 20 ++++++++++++++---- libraries/avatars/src/AvatarTraits.h | 21 +++++++++++++++++-- libraries/avatars/src/ClientTraitsHandler.cpp | 21 +++++++------------ libraries/avatars/src/ClientTraitsHandler.h | 4 ---- 5 files changed, 47 insertions(+), 24 deletions(-) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index b010a9f924..e9f1f5f6c3 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -1193,6 +1193,9 @@ public: void setReplicaIndex(int replicaIndex) { _replicaIndex = replicaIndex; } int getReplicaIndex() { return _replicaIndex; } + const AvatarTraits::TraitInstanceID getTraitInstanceXORID() const { return _traitInstanceXORID; } + void cycleTraitInstanceXORID() { _traitInstanceXORID = QUuid::createUuid(); } + signals: /**jsdoc @@ -1499,6 +1502,8 @@ private: // privatize the copy constructor and assignment operator so they cannot be called AvatarData(const AvatarData&); AvatarData& operator= (const AvatarData&); + + AvatarTraits::TraitInstanceID _traitInstanceXORID { QUuid::createUuid() }; }; Q_DECLARE_METATYPE(AvatarData*) diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index c437b56f32..fac2af9ebc 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -335,17 +335,29 @@ void AvatarHashMap::processBulkAvatarTraits(QSharedPointer mess AvatarTraits::TraitInstanceID traitInstanceID = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + // XOR the incoming trait instance ID with this avatar object's personal XOR ID + + // this ensures that we have separate entity instances in the local tree + // if we briefly end up with two Avatar objects for this node + + // (which can occur if the shared pointer for the + // previous instance of an avatar hasn't yet gone out of scope before the + // new instance is created) + + auto xoredInstanceID = AvatarTraits::xoredInstanceID(traitInstanceID, avatar->getTraitInstanceXORID()); + message->readPrimitive(&traitBinarySize); auto& processedInstanceVersion = lastProcessedVersions.getInstanceValueRef(traitType, traitInstanceID); if (packetTraitVersion > processedInstanceVersion) { + // in order to handle re-connections to the avatar mixer when the other if (traitBinarySize == AvatarTraits::DELETED_TRAIT_SIZE) { - avatar->processDeletedTraitInstance(traitType, traitInstanceID); - _replicas.processDeletedTraitInstance(avatarID, traitType, traitInstanceID); + avatar->processDeletedTraitInstance(traitType, xoredInstanceID); + _replicas.processDeletedTraitInstance(avatarID, traitType, xoredInstanceID); } else { auto traitData = message->read(traitBinarySize); - avatar->processTraitInstance(traitType, traitInstanceID, traitData); - _replicas.processTraitInstance(avatarID, traitType, traitInstanceID, traitData); + avatar->processTraitInstance(traitType, xoredInstanceID, traitData); + _replicas.processTraitInstance(avatarID, traitType, xoredInstanceID, traitData); } processedInstanceVersion = packetTraitVersion; } else { diff --git a/libraries/avatars/src/AvatarTraits.h b/libraries/avatars/src/AvatarTraits.h index 5866caf234..47be0d6111 100644 --- a/libraries/avatars/src/AvatarTraits.h +++ b/libraries/avatars/src/AvatarTraits.h @@ -41,7 +41,8 @@ namespace AvatarTraits { const TraitWireSize DELETED_TRAIT_SIZE = -1; inline qint64 packInstancedTraitDelete(TraitType traitType, TraitInstanceID instanceID, ExtendedIODevice& destination, - TraitVersion traitVersion = NULL_TRAIT_VERSION) { + TraitVersion traitVersion = NULL_TRAIT_VERSION, + TraitInstanceID xoredInstanceID = TraitInstanceID()) { qint64 bytesWritten = 0; bytesWritten += destination.writePrimitive(traitType); @@ -50,12 +51,28 @@ namespace AvatarTraits { bytesWritten += destination.writePrimitive(traitVersion); } - bytesWritten += destination.write(instanceID.toRfc4122()); + if (xoredInstanceID.isNull()) { + bytesWritten += destination.write(instanceID.toRfc4122()); + } else { + bytesWritten += destination.write(xoredInstanceID.toRfc4122()); + } bytesWritten += destination.writePrimitive(DELETED_TRAIT_SIZE); return bytesWritten; } + + inline TraitInstanceID xoredInstanceID(TraitInstanceID localInstanceID, TraitInstanceID xorKeyID) { + QByteArray xoredInstanceID { NUM_BYTES_RFC4122_UUID, 0 }; + auto xorKeyIDBytes = xorKeyID.toRfc4122(); + auto localInstanceIDBytes = localInstanceID.toRfc4122(); + + for (auto i = 0; i < localInstanceIDBytes.size(); ++i) { + xoredInstanceID[i] = localInstanceIDBytes[i] ^ xorKeyIDBytes[i]; + } + + return QUuid::fromRfc4122(xoredInstanceID); + } }; #endif // hifi_AvatarTraits_h diff --git a/libraries/avatars/src/ClientTraitsHandler.cpp b/libraries/avatars/src/ClientTraitsHandler.cpp index 94823610dc..479852cf9a 100644 --- a/libraries/avatars/src/ClientTraitsHandler.cpp +++ b/libraries/avatars/src/ClientTraitsHandler.cpp @@ -45,7 +45,7 @@ void ClientTraitsHandler::resetForNewMixer() { _owningAvatar->prepareResetTraitInstances(); // reset the trait XOR ID since we're resetting for a new avatar mixer - _sessionXORID = QUuid::createUuid().toRfc4122(); + _owningAvatar->cycleTraitInstanceXORID(); } void ClientTraitsHandler::sendChangedTraitsToMixer() { @@ -100,11 +100,15 @@ void ClientTraitsHandler::sendChangedTraitsToMixer() { // since this is going to the mixer, use the XORed instance ID (to anonymize trait instance IDs // that would typically persist across sessions) _owningAvatar->packTraitInstance(instancedIt->traitType, instanceIDValuePair.id, *traitsPacketList, - AvatarTraits::NULL_TRAIT_VERSION, xorInstanceID(instanceIDValuePair.id)); + AvatarTraits::NULL_TRAIT_VERSION, + AvatarTraits::xoredInstanceID(instanceIDValuePair.id, + _owningAvatar->getTraitInstanceXORID())); } else if (!_shouldPerformInitialSend && instanceIDValuePair.value == Deleted) { // pack delete for this trait instance AvatarTraits::packInstancedTraitDelete(instancedIt->traitType, instanceIDValuePair.id, - *traitsPacketList); + *traitsPacketList, AvatarTraits::NULL_TRAIT_VERSION, + AvatarTraits::xoredInstanceID(instanceIDValuePair.id, + _owningAvatar->getTraitInstanceXORID())); } } @@ -118,17 +122,6 @@ void ClientTraitsHandler::sendChangedTraitsToMixer() { } } -AvatarTraits::TraitInstanceID ClientTraitsHandler::xorInstanceID(AvatarTraits::TraitInstanceID localInstanceID) { - QByteArray xorInstanceID { NUM_BYTES_RFC4122_UUID, 0 }; - auto localInstanceIDBytes = localInstanceID.toRfc4122(); - - for (auto i = 0; i < localInstanceIDBytes.size(); ++i) { - xorInstanceID[i] = localInstanceIDBytes[i] ^ _sessionXORID[i]; - } - - return QUuid::fromRfc4122(xorInstanceID); -} - void ClientTraitsHandler::processTraitOverride(QSharedPointer message, SharedNodePointer sendingNode) { if (sendingNode->getType() == NodeType::AvatarMixer) { while (message->getBytesLeftToRead()) { diff --git a/libraries/avatars/src/ClientTraitsHandler.h b/libraries/avatars/src/ClientTraitsHandler.h index 2319061502..6d1592ba74 100644 --- a/libraries/avatars/src/ClientTraitsHandler.h +++ b/libraries/avatars/src/ClientTraitsHandler.h @@ -37,8 +37,6 @@ public: void resetForNewMixer(); - AvatarTraits::TraitInstanceID xorInstanceID(AvatarTraits::TraitInstanceID localInstanceID); - public slots: void processTraitOverride(QSharedPointer message, SharedNodePointer sendingNode); @@ -55,8 +53,6 @@ private: AvatarTraits::TraitVersion _currentTraitVersion { AvatarTraits::DEFAULT_TRAIT_VERSION }; AvatarTraits::TraitVersion _currentSkeletonVersion { AvatarTraits::NULL_TRAIT_VERSION }; - - QByteArray _sessionXORID { NUM_BYTES_RFC4122_UUID, 0}; bool _shouldPerformInitialSend { false }; bool _hasChangedTraits { false }; From a37a19da1e4e7657548fb29ad6cf4e130a5eda76 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 31 Aug 2018 16:59:24 -0700 Subject: [PATCH 30/46] use different XORed instance ID for replicas --- libraries/avatars/src/AvatarHashMap.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index fac2af9ebc..c1246866dc 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -85,7 +85,8 @@ void AvatarReplicas::processDeletedTraitInstance(const QUuid& parentID, AvatarTr if (_replicasMap.find(parentID) != _replicasMap.end()) { auto &replicas = _replicasMap[parentID]; for (auto avatar : replicas) { - avatar->processDeletedTraitInstance(traitType, instanceID); + avatar->processDeletedTraitInstance(traitType, + AvatarTraits::xoredInstanceID(instanceID, avatar->getTraitInstanceXORID())); } } } @@ -94,7 +95,9 @@ void AvatarReplicas::processTraitInstance(const QUuid& parentID, AvatarTraits::T if (_replicasMap.find(parentID) != _replicasMap.end()) { auto &replicas = _replicasMap[parentID]; for (auto avatar : replicas) { - avatar->processTraitInstance(traitType, instanceID, traitBinaryData); + avatar->processTraitInstance(traitType, + AvatarTraits::xoredInstanceID(instanceID, avatar->getTraitInstanceXORID()), + traitBinaryData); } } } @@ -353,11 +356,11 @@ void AvatarHashMap::processBulkAvatarTraits(QSharedPointer mess // in order to handle re-connections to the avatar mixer when the other if (traitBinarySize == AvatarTraits::DELETED_TRAIT_SIZE) { avatar->processDeletedTraitInstance(traitType, xoredInstanceID); - _replicas.processDeletedTraitInstance(avatarID, traitType, xoredInstanceID); + _replicas.processDeletedTraitInstance(avatarID, traitType, traitInstanceID); } else { auto traitData = message->read(traitBinarySize); avatar->processTraitInstance(traitType, xoredInstanceID, traitData); - _replicas.processTraitInstance(avatarID, traitType, xoredInstanceID, traitData); + _replicas.processTraitInstance(avatarID, traitType, traitInstanceID, traitData); } processedInstanceVersion = packetTraitVersion; } else { From 06af7b8729595d90ee8dec8dd86d74e7130763a6 Mon Sep 17 00:00:00 2001 From: Flame Soulis Date: Mon, 3 Sep 2018 07:58:39 -0400 Subject: [PATCH 31/46] Fixed typo on DQT_CMAKE_PREFIX_PATH --- BUILD_LINUX.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD_LINUX.md b/BUILD_LINUX.md index 0daef5ae05..55e7260cd1 100644 --- a/BUILD_LINUX.md +++ b/BUILD_LINUX.md @@ -66,7 +66,7 @@ cd hifi/build Prepare makefiles: ```bash -cmake -DQT_CMAKE_PREFIX_PATH=/usr/local/Qt5.10.1/5.10/gcc_64/lib/cmake .. +cmake -DQT_CMAKE_PREFIX_PATH=/usr/local/Qt5.10.1/5.10.1/gcc_64/lib/cmake .. ``` Start compilation and get a cup of coffee: From 229a3bba90e0ed9279e0064067f5353860cfbe2e Mon Sep 17 00:00:00 2001 From: Flame Soulis Date: Mon, 3 Sep 2018 08:00:16 -0400 Subject: [PATCH 32/46] Added zlib1g-dev to required dependencies --- BUILD_LINUX.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BUILD_LINUX.md b/BUILD_LINUX.md index 55e7260cd1..48e5a8efc1 100644 --- a/BUILD_LINUX.md +++ b/BUILD_LINUX.md @@ -6,7 +6,7 @@ Please read the [general build guide](BUILD.md) for information on dependencies Should you choose not to install Qt5 via a package manager that handles dependencies for you, you may be missing some Qt5 dependencies. On Ubuntu, for example, the following additional packages are required: - libasound2 libxmu-dev libxi-dev freeglut3-dev libasound2-dev libjack0 libjack-dev libxrandr-dev libudev-dev libssl-dev + libasound2 libxmu-dev libxi-dev freeglut3-dev libasound2-dev libjack0 libjack-dev libxrandr-dev libudev-dev libssl-dev zlib1g-dev ## Ubuntu 16.04 specific build guide @@ -20,7 +20,7 @@ sudo dpkg -i hifiqt5.10.1_5.10.1_amd64.deb Install build dependencies: ```bash -sudo apt-get install libasound2 libxmu-dev libxi-dev freeglut3-dev libasound2-dev libjack0 libjack-dev libxrandr-dev libudev-dev libssl-dev +sudo apt-get install libasound2 libxmu-dev libxi-dev freeglut3-dev libasound2-dev libjack0 libjack-dev libxrandr-dev libudev-dev libssl-dev zlib1g-dev ``` To compile interface in a server you must install: From f509dc4af4f9ef5c95640cb7bc680c2071166efb Mon Sep 17 00:00:00 2001 From: Flame Soulis Date: Mon, 3 Sep 2018 08:11:15 -0400 Subject: [PATCH 33/46] Added Ubuntu 18.04 step to add universe repository --- BUILD_LINUX.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/BUILD_LINUX.md b/BUILD_LINUX.md index 48e5a8efc1..421e81c8b8 100644 --- a/BUILD_LINUX.md +++ b/BUILD_LINUX.md @@ -8,7 +8,14 @@ Should you choose not to install Qt5 via a package manager that handles dependen libasound2 libxmu-dev libxi-dev freeglut3-dev libasound2-dev libjack0 libjack-dev libxrandr-dev libudev-dev libssl-dev zlib1g-dev -## Ubuntu 16.04 specific build guide +## Ubuntu 16.04/18.04 specific build guide + +### Ubuntu 18.04 only +Add the universe repository (not enabled by default on the server edition): +```bash +sudo add-apt-repository universe +sudo apt-get update +``` ### Prepare environment hifiqt5.10.1 @@ -33,6 +40,7 @@ Install build tools: sudo apt install cmake ``` + ### Get code and checkout the tag you need Clone this repository: From 03051c0916b48814c92664647b69c2b383e66ab1 Mon Sep 17 00:00:00 2001 From: Flame Soulis Date: Mon, 3 Sep 2018 08:16:50 -0400 Subject: [PATCH 34/46] Revised Qt statement and Improved 18.04 step format --- BUILD_LINUX.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/BUILD_LINUX.md b/BUILD_LINUX.md index 421e81c8b8..c7351d4834 100644 --- a/BUILD_LINUX.md +++ b/BUILD_LINUX.md @@ -11,15 +11,15 @@ Should you choose not to install Qt5 via a package manager that handles dependen ## Ubuntu 16.04/18.04 specific build guide ### Ubuntu 18.04 only -Add the universe repository (not enabled by default on the server edition): +Add the universe repository: +_(This is not enabled by default on the server edition)_ ```bash sudo add-apt-repository universe sudo apt-get update ``` ### Prepare environment -hifiqt5.10.1 -Install qt: +Install Qt 5.10.1: ```bash wget http://debian.highfidelity.com/pool/h/hi/hifiqt5.10.1_5.10.1_amd64.deb sudo dpkg -i hifiqt5.10.1_5.10.1_amd64.deb From b0fe721af19902cccb5a22c533d57f57b497e7fb Mon Sep 17 00:00:00 2001 From: Flame Soulis Date: Mon, 3 Sep 2018 08:22:58 -0400 Subject: [PATCH 35/46] Revised checkout tag and removed download page mention --- BUILD_LINUX.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/BUILD_LINUX.md b/BUILD_LINUX.md index c7351d4834..8b1f77e538 100644 --- a/BUILD_LINUX.md +++ b/BUILD_LINUX.md @@ -56,12 +56,7 @@ git tags Then checkout last tag with: ```bash -git checkout tags/RELEASE-6819 -``` - -Or go to the highfidelity download page (https://highfidelity.com/download) to get the release version. For example, if there is a BETA 6731 type: -```bash -git checkout tags/RELEASE-6731 +git checkout tags/v0.71.0 ``` ### Compiling From 143b4a61dd2821699249ffd8faca60abd88a00a5 Mon Sep 17 00:00:00 2001 From: Flame Soulis Date: Mon, 3 Sep 2018 08:25:45 -0400 Subject: [PATCH 36/46] Revised server compilation statement and grammer error --- BUILD_LINUX.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/BUILD_LINUX.md b/BUILD_LINUX.md index 8b1f77e538..e95ee2f4d4 100644 --- a/BUILD_LINUX.md +++ b/BUILD_LINUX.md @@ -72,12 +72,17 @@ Prepare makefiles: cmake -DQT_CMAKE_PREFIX_PATH=/usr/local/Qt5.10.1/5.10.1/gcc_64/lib/cmake .. ``` -Start compilation and get a cup of coffee: +Start compilation of the server and get a cup of coffee: ```bash -make domain-server assignment-client interface +make domain-server assignment-client ``` -In a server does not make sense to compile interface +To compile interferace: +```bash +make interface +``` + +In a server, it does not make sense to compile interface ### Running the software From 26cb2409b95bafe86e5766b61ca9729bdebcef0d Mon Sep 17 00:00:00 2001 From: Flame Soulis Date: Mon, 3 Sep 2018 08:53:20 -0400 Subject: [PATCH 37/46] Added additional export QT_CMAKE_PREFIX_PATH related to BUILD_LINUX.md --- BUILD.md | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILD.md b/BUILD.md index 4a0274cea6..df3f18cf51 100644 --- a/BUILD.md +++ b/BUILD.md @@ -46,6 +46,7 @@ This can either be entered directly into your shell session before you build or The path it needs to be set to will depend on where and how Qt5 was installed. e.g. + export QT_CMAKE_PREFIX_PATH=/usr/local/Qt5.10.1/5.10.1/gcc_64/lib/cmake export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.10.1/clang_64/lib/cmake/ export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.10.1/lib/cmake export QT_CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake From 8314386426cf494d6cfe6d0ebd378adc8bde0e84 Mon Sep 17 00:00:00 2001 From: Flame Soulis Date: Mon, 3 Sep 2018 08:55:15 -0400 Subject: [PATCH 38/46] Revised all apt statements to apt-get for consistency --- BUILD_LINUX.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/BUILD_LINUX.md b/BUILD_LINUX.md index e95ee2f4d4..019b19ff8c 100644 --- a/BUILD_LINUX.md +++ b/BUILD_LINUX.md @@ -32,12 +32,12 @@ sudo apt-get install libasound2 libxmu-dev libxi-dev freeglut3-dev libasound2-de To compile interface in a server you must install: ```bash -sudo apt -y install libpulse0 libnss3 libnspr4 libfontconfig1 libxcursor1 libxcomposite1 libxtst6 libxslt1.1 +sudo apt-get -y install libpulse0 libnss3 libnspr4 libfontconfig1 libxcursor1 libxcomposite1 libxtst6 libxslt1.1 ``` Install build tools: ```bash -sudo apt install cmake +sudo apt-get install cmake ``` @@ -101,4 +101,4 @@ Running interface: ./interface/interface ``` -Go to localhost in running interface. +Go to localhost in the running interface. From b5f1c82e61ca6994736dd7f3f04a089f6c241d1b Mon Sep 17 00:00:00 2001 From: Flame Soulis Date: Mon, 3 Sep 2018 18:21:04 -0400 Subject: [PATCH 39/46] Corrected interferace to interface --- BUILD_LINUX.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD_LINUX.md b/BUILD_LINUX.md index 019b19ff8c..1ee3d2b7c8 100644 --- a/BUILD_LINUX.md +++ b/BUILD_LINUX.md @@ -77,7 +77,7 @@ Start compilation of the server and get a cup of coffee: make domain-server assignment-client ``` -To compile interferace: +To compile interface: ```bash make interface ``` From c081fd75f7713abce64dbe6e1570428a8e86cf11 Mon Sep 17 00:00:00 2001 From: Liv Erickson Date: Tue, 4 Sep 2018 09:08:35 -0700 Subject: [PATCH 40/46] update serverless content --- cmake/externals/serverless-content/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/externals/serverless-content/CMakeLists.txt b/cmake/externals/serverless-content/CMakeLists.txt index b4cacd8f90..12e2b7a4c6 100644 --- a/cmake/externals/serverless-content/CMakeLists.txt +++ b/cmake/externals/serverless-content/CMakeLists.txt @@ -4,8 +4,8 @@ set(EXTERNAL_NAME serverless-content) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC72.zip - URL_MD5 b1d8faf9266bfbff88274a484911eb99 + URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC73.zip + URL_MD5 0c5edfb63cafb042311d3cf25261fbf2 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" From 3a034fdf66a4311d1e7231cdde608f2fef69d8f2 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Fri, 31 Aug 2018 13:14:15 -0700 Subject: [PATCH 41/46] HMD mode bug fix for avatars with no eyes Previously getCenterEyeCalibrationMat() would return the average eye position for an avatar, if the eyes are missing. Now we fall back to using the HeadCalibrationMat() and adding an offset from the head to the center of the eyes. This is more accurate for characters that don't quite have human proportions. --- interface/src/avatar/MyAvatar.cpp | 4 +++- libraries/shared/src/AvatarConstants.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 640c9821a0..930a1b9f81 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -4313,7 +4313,8 @@ glm::mat4 MyAvatar::getCenterEyeCalibrationMat() const { auto centerEyeRot = Quaternions::Y_180; return createMatFromQuatAndPos(centerEyeRot, centerEyePos / getSensorToWorldScale()); } else { - return createMatFromQuatAndPos(DEFAULT_AVATAR_MIDDLE_EYE_ROT, DEFAULT_AVATAR_MIDDLE_EYE_POS / getSensorToWorldScale()); + glm::mat4 headMat = getHeadCalibrationMat(); + return createMatFromQuatAndPos(DEFAULT_AVATAR_MIDDLE_EYE_ROT, extractTranslation(headMat) + (DEFAULT_AVATAR_HEAD_TO_MIDDLE_EYE_OFFSET / getSensorToWorldScale())); } } @@ -4323,6 +4324,7 @@ glm::mat4 MyAvatar::getHeadCalibrationMat() const { if (headIndex >= 0) { auto headPos = getAbsoluteDefaultJointTranslationInObjectFrame(headIndex); auto headRot = getAbsoluteDefaultJointRotationInObjectFrame(headIndex); + return createMatFromQuatAndPos(headRot, headPos / getSensorToWorldScale()); } else { return createMatFromQuatAndPos(DEFAULT_AVATAR_HEAD_ROT, DEFAULT_AVATAR_HEAD_POS / getSensorToWorldScale()); diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index c3e8a3f173..986d39e94d 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -44,7 +44,7 @@ const float DEFAULT_AVATAR_RIGHTHAND_MASS = 2.0f; // Used when avatar is missing joints... (avatar space) const glm::quat DEFAULT_AVATAR_MIDDLE_EYE_ROT { Quaternions::Y_180 }; -const glm::vec3 DEFAULT_AVATAR_MIDDLE_EYE_POS { 0.0f, 0.6f, 0.0f }; +const glm::vec3 DEFAULT_AVATAR_HEAD_TO_MIDDLE_EYE_OFFSET = { 0.0f, 0.06f, -0.09f }; const glm::vec3 DEFAULT_AVATAR_HEAD_POS { 0.0f, 0.53f, 0.0f }; const glm::quat DEFAULT_AVATAR_HEAD_ROT { Quaternions::Y_180 }; const glm::vec3 DEFAULT_AVATAR_RIGHTARM_POS { -0.134824f, 0.396348f, -0.0515777f }; From ade58a52cc97fe06c2f4bb88c4b9d097636fd4b9 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 4 Sep 2018 10:33:01 -0700 Subject: [PATCH 42/46] reserve priority sort util vectors --- assignment-client/src/avatars/AvatarMixerSlave.cpp | 1 + interface/src/avatar/AvatarManager.cpp | 5 +++-- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 1 + libraries/shared/src/PrioritySortUtil.h | 3 +++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 59c6db5dc4..c434d82116 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -329,6 +329,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) AvatarData::_avatarSortCoefficientSize, AvatarData::_avatarSortCoefficientCenter, AvatarData::_avatarSortCoefficientAge); + sortedAvatars.reserve(avatarsToSort.size()); // ignore or sort const AvatarSharedPointer& thisAvatar = nodeData->getAvatarSharedPointer(); diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index bd98549510..e9486b9def 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -187,16 +187,17 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { AvatarSharedPointer _avatar; }; + auto avatarMap = getHashCopy(); + AvatarHash::iterator itr = avatarMap.begin(); const auto& views = qApp->getConicalViews(); PrioritySortUtil::PriorityQueue sortedAvatars(views, AvatarData::_avatarSortCoefficientSize, AvatarData::_avatarSortCoefficientCenter, AvatarData::_avatarSortCoefficientAge); + sortedAvatars.reserve(avatarMap.size() - 1); // don't include MyAvatar // sort - auto avatarMap = getHashCopy(); - AvatarHash::iterator itr = avatarMap.begin(); while (itr != avatarMap.end()) { const auto& avatar = std::static_pointer_cast(*itr); // DO NOT update _myAvatar! Its update has already been done earlier in the main loop. diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index a363093083..3d782f69a7 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -382,6 +382,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene const auto& views = _viewState->getConicalViews(); PrioritySortUtil::PriorityQueue sortedRenderables(views); + sortedRenderables.reserve(_renderablesToUpdate.size()); { PROFILE_RANGE_EX(simulation_physics, "SortRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size()); std::unordered_map::iterator itr = _renderablesToUpdate.begin(); diff --git a/libraries/shared/src/PrioritySortUtil.h b/libraries/shared/src/PrioritySortUtil.h index e0137b3d8c..8ded047212 100644 --- a/libraries/shared/src/PrioritySortUtil.h +++ b/libraries/shared/src/PrioritySortUtil.h @@ -100,6 +100,9 @@ namespace PrioritySortUtil { thing.setPriority(computePriority(thing)); _vector.push_back(thing); } + void reserve(size_t num) { + _vector.reserve(num); + } const std::vector& getSortedVector() { std::sort(_vector.begin(), _vector.end(), [](const T& left, const T& right) { return left.getPriority() > right.getPriority(); }); return _vector; From b21fa1037f1ff54fcec00af5026238a8c19a4b20 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Tue, 4 Sep 2018 11:55:52 -0700 Subject: [PATCH 43/46] Code review feedback and bug fixes for calibraiton matrices --- interface/src/avatar/MyAvatar.cpp | 21 +++++++++---------- interface/src/avatar/MyAvatar.h | 2 +- libraries/controllers/src/controllers/Input.h | 20 +++++++++--------- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 930a1b9f81..e4503b4e78 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -4314,7 +4314,7 @@ glm::mat4 MyAvatar::getCenterEyeCalibrationMat() const { return createMatFromQuatAndPos(centerEyeRot, centerEyePos / getSensorToWorldScale()); } else { glm::mat4 headMat = getHeadCalibrationMat(); - return createMatFromQuatAndPos(DEFAULT_AVATAR_MIDDLE_EYE_ROT, extractTranslation(headMat) + (DEFAULT_AVATAR_HEAD_TO_MIDDLE_EYE_OFFSET / getSensorToWorldScale())); + return createMatFromQuatAndPos(DEFAULT_AVATAR_MIDDLE_EYE_ROT, extractTranslation(headMat) + DEFAULT_AVATAR_HEAD_TO_MIDDLE_EYE_OFFSET); } } @@ -4327,7 +4327,7 @@ glm::mat4 MyAvatar::getHeadCalibrationMat() const { return createMatFromQuatAndPos(headRot, headPos / getSensorToWorldScale()); } else { - return createMatFromQuatAndPos(DEFAULT_AVATAR_HEAD_ROT, DEFAULT_AVATAR_HEAD_POS / getSensorToWorldScale()); + return createMatFromQuatAndPos(DEFAULT_AVATAR_HEAD_ROT, DEFAULT_AVATAR_HEAD_POS); } } @@ -4339,7 +4339,7 @@ glm::mat4 MyAvatar::getSpine2CalibrationMat() const { auto spine2Rot = getAbsoluteDefaultJointRotationInObjectFrame(spine2Index); return createMatFromQuatAndPos(spine2Rot, spine2Pos / getSensorToWorldScale()); } else { - return createMatFromQuatAndPos(DEFAULT_AVATAR_SPINE2_ROT, DEFAULT_AVATAR_SPINE2_POS / getSensorToWorldScale()); + return createMatFromQuatAndPos(DEFAULT_AVATAR_SPINE2_ROT, DEFAULT_AVATAR_SPINE2_POS); } } @@ -4351,7 +4351,7 @@ glm::mat4 MyAvatar::getHipsCalibrationMat() const { auto hipsRot = getAbsoluteDefaultJointRotationInObjectFrame(hipsIndex); return createMatFromQuatAndPos(hipsRot, hipsPos / getSensorToWorldScale()); } else { - return createMatFromQuatAndPos(DEFAULT_AVATAR_HIPS_ROT, DEFAULT_AVATAR_HIPS_POS / getSensorToWorldScale()); + return createMatFromQuatAndPos(DEFAULT_AVATAR_HIPS_ROT, DEFAULT_AVATAR_HIPS_POS); } } @@ -4363,7 +4363,7 @@ glm::mat4 MyAvatar::getLeftFootCalibrationMat() const { auto leftFootRot = getAbsoluteDefaultJointRotationInObjectFrame(leftFootIndex); return createMatFromQuatAndPos(leftFootRot, leftFootPos / getSensorToWorldScale()); } else { - return createMatFromQuatAndPos(DEFAULT_AVATAR_LEFTFOOT_ROT, DEFAULT_AVATAR_LEFTFOOT_POS / getSensorToWorldScale()); + return createMatFromQuatAndPos(DEFAULT_AVATAR_LEFTFOOT_ROT, DEFAULT_AVATAR_LEFTFOOT_POS); } } @@ -4375,11 +4375,10 @@ glm::mat4 MyAvatar::getRightFootCalibrationMat() const { auto rightFootRot = getAbsoluteDefaultJointRotationInObjectFrame(rightFootIndex); return createMatFromQuatAndPos(rightFootRot, rightFootPos / getSensorToWorldScale()); } else { - return createMatFromQuatAndPos(DEFAULT_AVATAR_RIGHTFOOT_ROT, DEFAULT_AVATAR_RIGHTFOOT_POS / getSensorToWorldScale()); + return createMatFromQuatAndPos(DEFAULT_AVATAR_RIGHTFOOT_ROT, DEFAULT_AVATAR_RIGHTFOOT_POS); } } - glm::mat4 MyAvatar::getRightArmCalibrationMat() const { int rightArmIndex = _skeletonModel->getRig().indexOfJoint("RightArm"); if (rightArmIndex >= 0) { @@ -4387,7 +4386,7 @@ glm::mat4 MyAvatar::getRightArmCalibrationMat() const { auto rightArmRot = getAbsoluteDefaultJointRotationInObjectFrame(rightArmIndex); return createMatFromQuatAndPos(rightArmRot, rightArmPos / getSensorToWorldScale()); } else { - return createMatFromQuatAndPos(DEFAULT_AVATAR_RIGHTARM_ROT, DEFAULT_AVATAR_RIGHTARM_POS / getSensorToWorldScale()); + return createMatFromQuatAndPos(DEFAULT_AVATAR_RIGHTARM_ROT, DEFAULT_AVATAR_RIGHTARM_POS); } } @@ -4398,7 +4397,7 @@ glm::mat4 MyAvatar::getLeftArmCalibrationMat() const { auto leftArmRot = getAbsoluteDefaultJointRotationInObjectFrame(leftArmIndex); return createMatFromQuatAndPos(leftArmRot, leftArmPos / getSensorToWorldScale()); } else { - return createMatFromQuatAndPos(DEFAULT_AVATAR_LEFTARM_ROT, DEFAULT_AVATAR_LEFTARM_POS / getSensorToWorldScale()); + return createMatFromQuatAndPos(DEFAULT_AVATAR_LEFTARM_ROT, DEFAULT_AVATAR_LEFTARM_POS); } } @@ -4409,7 +4408,7 @@ glm::mat4 MyAvatar::getRightHandCalibrationMat() const { auto rightHandRot = getAbsoluteDefaultJointRotationInObjectFrame(rightHandIndex); return createMatFromQuatAndPos(rightHandRot, rightHandPos / getSensorToWorldScale()); } else { - return createMatFromQuatAndPos(DEFAULT_AVATAR_RIGHTHAND_ROT, DEFAULT_AVATAR_RIGHTHAND_POS / getSensorToWorldScale()); + return createMatFromQuatAndPos(DEFAULT_AVATAR_RIGHTHAND_ROT, DEFAULT_AVATAR_RIGHTHAND_POS); } } @@ -4420,7 +4419,7 @@ glm::mat4 MyAvatar::getLeftHandCalibrationMat() const { auto leftHandRot = getAbsoluteDefaultJointRotationInObjectFrame(leftHandIndex); return createMatFromQuatAndPos(leftHandRot, leftHandPos / getSensorToWorldScale()); } else { - return createMatFromQuatAndPos(DEFAULT_AVATAR_LEFTHAND_ROT, DEFAULT_AVATAR_LEFTHAND_POS / getSensorToWorldScale()); + return createMatFromQuatAndPos(DEFAULT_AVATAR_LEFTHAND_ROT, DEFAULT_AVATAR_LEFTHAND_POS); } } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 8121b99e55..06267b3819 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1034,7 +1034,7 @@ public: virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; - // all calibration matrices are in absolute avatar space. + // all calibration matrices are in absolute sensor space. glm::mat4 getCenterEyeCalibrationMat() const; glm::mat4 getHeadCalibrationMat() const; glm::mat4 getSpine2CalibrationMat() const; diff --git a/libraries/controllers/src/controllers/Input.h b/libraries/controllers/src/controllers/Input.h index 3ca4076de2..3c01ee0942 100644 --- a/libraries/controllers/src/controllers/Input.h +++ b/libraries/controllers/src/controllers/Input.h @@ -19,16 +19,16 @@ struct InputCalibrationData { glm::mat4 sensorToWorldMat; // sensor to world glm::mat4 avatarMat; // avatar to world glm::mat4 hmdSensorMat; // hmd pos and orientation in sensor space - glm::mat4 defaultCenterEyeMat; // default pose for the center of the eyes in avatar space. - glm::mat4 defaultHeadMat; // default pose for head joint in avatar space - glm::mat4 defaultSpine2; // default pose for spine2 joint in avatar space - glm::mat4 defaultHips; // default pose for hips joint in avatar space - glm::mat4 defaultLeftFoot; // default pose for leftFoot joint in avatar space - glm::mat4 defaultRightFoot; // default pose for rightFoot joint in avatar space - glm::mat4 defaultRightArm; // default pose for rightArm joint in avatar space - glm::mat4 defaultLeftArm; // default pose for leftArm joint in avatar space - glm::mat4 defaultRightHand; // default pose for rightHand joint in avatar space - glm::mat4 defaultLeftHand; // default pose for leftHand joint in avatar space + glm::mat4 defaultCenterEyeMat; // default pose for the center of the eyes in sensor space. + glm::mat4 defaultHeadMat; // default pose for head joint in sensor space + glm::mat4 defaultSpine2; // default pose for spine2 joint in sensor space + glm::mat4 defaultHips; // default pose for hips joint in sensor space + glm::mat4 defaultLeftFoot; // default pose for leftFoot joint in sensor space + glm::mat4 defaultRightFoot; // default pose for rightFoot joint in sensor space + glm::mat4 defaultRightArm; // default pose for rightArm joint in sensor space + glm::mat4 defaultLeftArm; // default pose for leftArm joint in sensor space + glm::mat4 defaultRightHand; // default pose for rightHand joint in sensor space + glm::mat4 defaultLeftHand; // default pose for leftHand joint in sensor space }; enum class ChannelType { From dff8292216aed7a534b8725fe843ec72af7b88e0 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 4 Sep 2018 12:50:25 -0700 Subject: [PATCH 44/46] fix framebuffer debug --- .../render-utils/src/DebugDeferredBuffer.cpp | 86 +++++++------------ .../src/debug_deferred_buffer.slf | 12 +-- .../src/render-utils/ShaderConstants.h | 20 +---- 3 files changed, 36 insertions(+), 82 deletions(-) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index cab95e50be..0e61b36280 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -38,33 +38,6 @@ void DebugDeferredBufferConfig::setMode(int newMode) { emit dirty(); } -#if 0 -enum TextureSlot { - Albedo = 0, - Normal, - Specular, - Depth, - Lighting, - Shadow, - LinearDepth, - HalfLinearDepth, - HalfNormal, - Curvature, - DiffusedCurvature, - Scattering, - AmbientOcclusion, - AmbientOcclusionBlurred, - Velocity, -}; - -enum ParamSlot { - CameraCorrection = 0, - DeferredFrameTransform, - ShadowTransform, - DebugParametersBuffer -}; -#endif - static const std::string DEFAULT_ALBEDO_SHADER{ "vec4 getFragmentColor() {" " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" @@ -178,19 +151,19 @@ static const std::string DEFAULT_SHADOW_CASCADE_SHADER{ static const std::string DEFAULT_LINEAR_DEPTH_SHADER{ "vec4 getFragmentColor() {" - " return vec4(vec3(1.0 - texture(linearDepthMap, uv).x * 0.01), 1.0);" + " return vec4(vec3(1.0 - texture(debugTexture0, uv).x * 0.01), 1.0);" "}" }; static const std::string DEFAULT_HALF_LINEAR_DEPTH_SHADER{ "vec4 getFragmentColor() {" - " return vec4(vec3(1.0 - texture(halfLinearDepthMap, uv).x * 0.01), 1.0);" + " return vec4(vec3(1.0 - texture(debugTexture0, uv).x * 0.01), 1.0);" " }" }; static const std::string DEFAULT_HALF_NORMAL_SHADER{ "vec4 getFragmentColor() {" - " return vec4(vec3(texture(halfNormalMap, uv).xyz), 1.0);" + " return vec4(vec3(texture(debugTexture0, uv).xyz), 1.0);" " }" }; @@ -240,27 +213,27 @@ static const std::string DEFAULT_CURVATURE_OCCLUSION_SHADER{ static const std::string DEFAULT_DEBUG_SCATTERING_SHADER{ "vec4 getFragmentColor() {" - " return vec4(pow(vec3(texture(scatteringMap, uv).xyz), vec3(1.0 / 2.2)), 1.0);" - // " return vec4(vec3(texture(scatteringMap, uv).xyz), 1.0);" + " return vec4(pow(vec3(texture(debugTexture0, uv).xyz), vec3(1.0 / 2.2)), 1.0);" + // " return vec4(vec3(texture(debugTexture0, uv).xyz), 1.0);" " }" }; static const std::string DEFAULT_AMBIENT_OCCLUSION_SHADER{ "vec4 getFragmentColor() {" " return vec4(vec3(texture(obscuranceMap, uv).x), 1.0);" - // When drawing color " return vec4(vec3(texture(occlusionMap, uv).xyz), 1.0);" - // when drawing normal" return vec4(normalize(texture(occlusionMap, uv).xyz * 2.0 - vec3(1.0)), 1.0);" + // When drawing color " return vec4(vec3(texture(debugTexture0, uv).xyz), 1.0);" + // when drawing normal" return vec4(normalize(texture(debugTexture0, uv).xyz * 2.0 - vec3(1.0)), 1.0);" " }" }; static const std::string DEFAULT_AMBIENT_OCCLUSION_BLURRED_SHADER{ "vec4 getFragmentColor() {" - " return vec4(vec3(texture(occlusionBlurredMap, uv).xyz), 1.0);" + " return vec4(vec3(texture(debugTexture0, uv).xyz), 1.0);" " }" }; static const std::string DEFAULT_VELOCITY_SHADER{ "vec4 getFragmentColor() {" - " return vec4(vec2(texture(velocityMap, uv).xy), 0.0, 1.0);" + " return vec4(vec2(texture(debugTexture0, uv).xy), 0.0, 1.0);" " }" }; @@ -463,13 +436,10 @@ void DebugDeferredBuffer::run(const RenderContextPointer& renderContext, const I batch.setResourceTexture(Textures::DeferredDepth, deferredFramebuffer->getPrimaryDepthTexture()); batch.setResourceTexture(Textures::DeferredLighting, deferredFramebuffer->getLightingTexture()); } - if (velocityFramebuffer) { - batch.setResourceTexture(Textures::DebugVelocity, velocityFramebuffer->getVelocityTexture()); + if (velocityFramebuffer && _mode == VelocityMode) { + batch.setResourceTexture(Textures::DebugTexture0, velocityFramebuffer->getVelocityTexture()); } - // FIXME can't find the corresponding buffer - // batch.setUniformBuffer(UBOs:: DebugParametersBuffer, _parameters); - auto lightStage = renderContext->_scene->getStage(); assert(lightStage); assert(lightStage->getNumLights() > 0); @@ -479,12 +449,17 @@ void DebugDeferredBuffer::run(const RenderContextPointer& renderContext, const I batch.setResourceTexture(Textures::Shadow, globalShadow->map); batch.setUniformBuffer(UBOs::ShadowParams, globalShadow->getBuffer()); batch.setUniformBuffer(UBOs::DeferredFrameTransform, frameTransform->getFrameTransformBuffer()); + batch.setUniformBuffer(UBOs::DebugDeferredParams, _parameters); } if (linearDepthTarget) { - batch.setResourceTexture(Textures::DebugDepth, linearDepthTarget->getLinearDepthTexture()); - batch.setResourceTexture(Textures::DebugHalfDepth, linearDepthTarget->getHalfLinearDepthTexture()); - batch.setResourceTexture(Textures::DebugHalfNormal, linearDepthTarget->getHalfNormalTexture()); + if (_mode == DepthMode) { + batch.setResourceTexture(Textures::DebugTexture0, linearDepthTarget->getLinearDepthTexture()); + } else if (_mode == HalfLinearDepthMode) { + batch.setResourceTexture(Textures::DebugTexture0, linearDepthTarget->getHalfLinearDepthTexture()); + } else if (_mode == HalfNormalMode) { + batch.setResourceTexture(Textures::DebugTexture0, linearDepthTarget->getHalfNormalTexture()); + } } if (surfaceGeometryFramebuffer) { batch.setResourceTexture(Textures::DeferredCurvature, surfaceGeometryFramebuffer->getCurvatureTexture()); @@ -492,9 +467,11 @@ void DebugDeferredBuffer::run(const RenderContextPointer& renderContext, const I surfaceGeometryFramebuffer->getLowCurvatureTexture()); } if (ambientOcclusionFramebuffer) { - batch.setResourceTexture(Textures::DebugOcclusion, ambientOcclusionFramebuffer->getOcclusionTexture()); - batch.setResourceTexture(Textures::DebugOcclusionBlurred, - ambientOcclusionFramebuffer->getOcclusionBlurredTexture()); + if (_mode == AmbientOcclusionMode) { + batch.setResourceTexture(Textures::DebugTexture0, ambientOcclusionFramebuffer->getOcclusionTexture()); + } else if (_mode == AmbientOcclusionBlurredMode) { + batch.setResourceTexture(Textures::DebugTexture0, ambientOcclusionFramebuffer->getOcclusionBlurredTexture()); + } } const glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); const glm::vec2 bottomLeft(_size.x, _size.y); @@ -505,19 +482,14 @@ void DebugDeferredBuffer::run(const RenderContextPointer& renderContext, const I batch.setResourceTexture(Textures::DeferredNormal, nullptr); batch.setResourceTexture(Textures::DeferredSpecular, nullptr); batch.setResourceTexture(Textures::DeferredDepth, nullptr); - batch.setResourceTexture(Textures::DeferredLighting, nullptr); - batch.setResourceTexture(Textures::Shadow, nullptr); - batch.setResourceTexture(Textures::DebugDepth, nullptr); - batch.setResourceTexture(Textures::DebugHalfDepth, nullptr); - batch.setResourceTexture(Textures::DebugHalfNormal, nullptr); - batch.setResourceTexture(Textures::DeferredCurvature, nullptr); batch.setResourceTexture(Textures::DeferredDiffusedCurvature, nullptr); + batch.setResourceTexture(Textures::DeferredLighting, nullptr); - batch.setResourceTexture(Textures::DebugOcclusion, nullptr); - batch.setResourceTexture(Textures::DebugOcclusionBlurred, nullptr); - - batch.setResourceTexture(Textures::DebugVelocity, nullptr); + for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) { + batch.setResourceTexture(Textures::Shadow + i, nullptr); + } + batch.setResourceTexture(Textures::DebugTexture0, nullptr); }); } diff --git a/libraries/render-utils/src/debug_deferred_buffer.slf b/libraries/render-utils/src/debug_deferred_buffer.slf index aee04cba90..013640d910 100644 --- a/libraries/render-utils/src/debug_deferred_buffer.slf +++ b/libraries/render-utils/src/debug_deferred_buffer.slf @@ -16,14 +16,8 @@ <@include gpu/Color.slh@> <$declareColorWheel()$> -layout(binding=RENDER_UTILS_TEXTURE_DEBUG_DEPTH) uniform sampler2D linearDepthMap; -layout(binding=RENDER_UTILS_TEXTURE_DEBUG_HALF_DEPTH) uniform sampler2D halfLinearDepthMap; -layout(binding=RENDER_UTILS_TEXTURE_DEBUG_HALF_NORMAL) uniform sampler2D halfNormalMap; -layout(binding=RENDER_UTILS_TEXTURE_DEBUG_OCCLUSION) uniform sampler2D occlusionMap; -layout(binding=RENDER_UTILS_TEXTURE_DEBUG_OCCLUSION_BLURRED) uniform sampler2D occlusionBlurredMap; -layout(binding=RENDER_UTILS_TEXTURE_DEBUG_SCATTERING) uniform sampler2D scatteringMap; -layout(binding=RENDER_UTILS_TEXTURE_DEBUG_VELOCITY) uniform sampler2D velocityMap; -layout(binding=RENDER_UTILS_TEXTURE_DEBUG_SHADOWS) uniform sampler2DArrayShadow shadowMaps; +layout(binding=RENDER_UTILS_DEBUG_TEXTURE0) uniform sampler2D debugTexture0; +layout(binding=RENDER_UTILS_TEXTURE_SHADOW) uniform sampler2DArrayShadow shadowMaps; <@include ShadowCore.slh@> @@ -31,7 +25,7 @@ layout(binding=RENDER_UTILS_TEXTURE_DEBUG_SHADOWS) uniform sampler2DArrayShadow <@include debug_deferred_buffer_shared.slh@> -layout(std140) uniform parametersBuffer { +layout(std140, binding=RENDER_UTILS_BUFFER_DEBUG_DEFERRED_PARAMS) uniform parametersBuffer { DebugParameters parameters; }; diff --git a/libraries/render-utils/src/render-utils/ShaderConstants.h b/libraries/render-utils/src/render-utils/ShaderConstants.h index afb195c240..6a88a62287 100644 --- a/libraries/render-utils/src/render-utils/ShaderConstants.h +++ b/libraries/render-utils/src/render-utils/ShaderConstants.h @@ -126,14 +126,8 @@ // Debugging #define RENDER_UTILS_BUFFER_DEBUG_SKYBOX 5 -#define RENDER_UTILS_TEXTURE_DEBUG_DEPTH 11 -#define RENDER_UTILS_TEXTURE_DEBUG_HALF_DEPTH 12 -#define RENDER_UTILS_TEXTURE_DEBUG_OCCLUSION 13 -#define RENDER_UTILS_TEXTURE_DEBUG_OCCLUSION_BLURRED 14 -#define RENDER_UTILS_TEXTURE_DEBUG_VELOCITY 15 -#define RENDER_UTILS_TEXTURE_DEBUG_SHADOWS 16 -#define RENDER_UTILS_TEXTURE_DEBUG_HALF_NORMAL 17 -#define RENDER_UTILS_TEXTURE_DEBUG_SCATTERING 18 +#define RENDER_UTILS_DEBUG_TEXTURE0 11 +#define RENDER_UTILS_BUFFER_DEBUG_DEFERRED_PARAMS 1 // @@ -174,6 +168,7 @@ enum Buffer { BloomParams = RENDER_UTILS_BUFFER_BLOOM_PARAMS, ToneMappingParams = RENDER_UTILS_BUFFER_TM_PARAMS, ShadowParams = RENDER_UTILS_BUFFER_SHADOW_PARAMS, + DebugDeferredParams = RENDER_UTILS_BUFFER_DEBUG_DEFERRED_PARAMS, }; } // namespace buffer @@ -212,14 +207,7 @@ enum Texture { BloomColor = RENDER_UTILS_TEXTURE_BLOOM_COLOR, ToneMappingColor = RENDER_UTILS_TEXTURE_TM_COLOR, TextFont = RENDER_UTILS_TEXTURE_TEXT_FONT, - DebugDepth = RENDER_UTILS_TEXTURE_DEBUG_DEPTH, - DebugHalfDepth = RENDER_UTILS_TEXTURE_DEBUG_HALF_DEPTH, - DebugOcclusion = RENDER_UTILS_TEXTURE_DEBUG_OCCLUSION, - DebugOcclusionBlurred = RENDER_UTILS_TEXTURE_DEBUG_OCCLUSION_BLURRED, - DebugVelocity = RENDER_UTILS_TEXTURE_DEBUG_VELOCITY, - DebugShadows = RENDER_UTILS_TEXTURE_DEBUG_SHADOWS, - DebugHalfNormal = RENDER_UTILS_TEXTURE_DEBUG_HALF_NORMAL, - DebugScattering = RENDER_UTILS_TEXTURE_DEBUG_SCATTERING, + DebugTexture0 = RENDER_UTILS_DEBUG_TEXTURE0, }; } // namespace texture From e210fadc7cb599b9f6a72b5dade5398678ca51f7 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Tue, 4 Sep 2018 14:36:56 -0700 Subject: [PATCH 45/46] Fix for glitch when entering inAir state from takeoff. This was due to a frame lag of blend factor used for inAir blending. So the first frame the upward velocity would be 0, followed by 3.5 m/s the next frame. This is fixed by using the workingVelocity instead of _lastVelocity to drive the blend. --- libraries/animation/src/Rig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index c3e679096b..13cf165dac 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -926,7 +926,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos // compute blend based on velocity const float JUMP_SPEED = 3.5f; - float alpha = glm::clamp(-_lastVelocity.y / JUMP_SPEED, -1.0f, 1.0f) + 1.0f; + float alpha = glm::clamp(-workingVelocity.y / JUMP_SPEED, -1.0f, 1.0f) + 1.0f; _animVars.set("inAirAlpha", alpha); } From 9e76c164ac76fcc6dfadb05b79da96a862188d97 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 4 Sep 2018 16:25:47 -0700 Subject: [PATCH 46/46] fix aabox operator+= --- libraries/shared/src/AABox.h | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/libraries/shared/src/AABox.h b/libraries/shared/src/AABox.h index e0bb1343f8..f41bb8a814 100644 --- a/libraries/shared/src/AABox.h +++ b/libraries/shared/src/AABox.h @@ -86,19 +86,12 @@ public: AABox clamp(float min, float max) const; inline AABox& operator+=(const glm::vec3& point) { - // Branchless version of: - //if (isInvalid()) { - // _corner = glm::min(_corner, point); - //} else { - // glm::vec3 maximum(_corner + _scale); - // _corner = glm::min(_corner, point); - // maximum = glm::max(maximum, point); - // _scale = maximum - _corner; - //} - float blend = (float)isInvalid(); - glm::vec3 maximumScale(glm::max(_scale, point - _corner)); + bool valid = !isInvalid(); + glm::vec3 maximum = glm::max(_corner + _scale, point); _corner = glm::min(_corner, point); - _scale = blend * _scale + (1.0f - blend) * maximumScale; + if (valid) { + _scale = maximum - _corner; + } return (*this); } @@ -136,7 +129,7 @@ public: static const glm::vec3 INFINITY_VECTOR; - bool isInvalid() const { return _corner == INFINITY_VECTOR; } + bool isInvalid() const { return _corner.x == std::numeric_limits::infinity(); } void clear() { _corner = INFINITY_VECTOR; _scale = glm::vec3(0.0f); }