From bbef07172349a785a9fc7913cf981f494db515ee Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 1 Nov 2016 16:23:53 -0700 Subject: [PATCH 01/25] Update interface to default to HMD display plugin --- interface/src/Application.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5fe15fa8e5..f4596f5ea2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5669,13 +5669,22 @@ void Application::updateDisplayMode() { standard.insert(std::end(standard), std::begin(advanced), std::end(advanced)); standard.insert(std::end(standard), std::begin(developer), std::end(developer)); + DisplayPluginPointer defaultDisplayPlugin; + + // Default to the first HMD plugin, otherwise use the first in the list. + auto hmdPluginIt = find_if(standard.begin(), standard.end(), [](DisplayPluginPointer& plugin) { return plugin->isHmd(); }); + if (hmdPluginIt != standard.end()) { + defaultDisplayPlugin = *hmdPluginIt; + } else if (standard.size() > 0) { + defaultDisplayPlugin = standard[0]; + } + foreach(auto displayPlugin, standard) { - addDisplayPluginToMenu(displayPlugin, first); + addDisplayPluginToMenu(displayPlugin, displayPlugin.get() == defaultDisplayPlugin.get()); auto displayPluginName = displayPlugin->getName(); QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, [this](const QSize & size) { resizeGL(); }); - first = false; } // after all plugins have been added to the menu, add a separator to the menu From 26e0d02d6067019e605b8ce3bf600aee5f8be9ad Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 1 Nov 2016 16:40:41 -0700 Subject: [PATCH 02/25] Remove unused 'first' variable --- interface/src/Application.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f4596f5ea2..c6a0bce2f5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5643,8 +5643,6 @@ void Application::updateDisplayMode() { static std::once_flag once; std::call_once(once, [&] { - bool first = true; - // first sort the plugins into groupings: standard, advanced, developer DisplayPluginList standard; DisplayPluginList advanced; From 7655f906f1d17519d706494c05988b4a7bc900b1 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 3 Nov 2016 19:26:30 -0700 Subject: [PATCH 03/25] Starting adding a timer for the frame --- interface/src/Application.cpp | 2 ++ libraries/gpu/src/gpu/Context.cpp | 8 ++++++++ libraries/gpu/src/gpu/Context.h | 8 ++++++++ 3 files changed, 18 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 867761e012..57586d734e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1238,7 +1238,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto glInfo = getGLContextData(); properties["gl_info"] = glInfo; + properties["gpu_used_memory"] = (int)BYTES_TO_MB(gpu::Context::getUsedGPUMemory()); properties["gpu_free_memory"] = (int)BYTES_TO_MB(gpu::Context::getFreeGPUMemory()); + properties["gpu_frame_time"] = (int)(qApp->getRenderEngine()->); properties["ideal_thread_count"] = QThread::idealThreadCount(); auto hmdHeadPose = getHMDSensorPose(); diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index ab6bba178a..f1fc1067c3 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -34,6 +34,10 @@ void Context::beginFrame(const glm::mat4& renderPose) { _frameActive = true; _currentFrame = std::make_shared(); _currentFrame->pose = renderPose; + + if (!_frameRangeTimer) { + _frameRangeTimer = std::make_shared("gpu::Frame"); + } } void Context::appendFrameBatch(Batch& batch) { @@ -183,6 +187,10 @@ Size Context::getFreeGPUMemory() { return _freeGPUMemory.load(); } +Size Context::getUsedGPUMemory() { + return getTextureGPUMemoryUsage() + getBufferGPUMemoryUsage(); +}; + void Context::incrementBufferGPUCount() { static std::atomic max { 0 }; auto total = ++_bufferGPUCount; diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 763e91b3e4..6e3e976034 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -203,12 +203,16 @@ public: void getStats(ContextStats& stats) const; + double getFrameTimerGPUAverage() const; + double getFrameTimerBatchAverage() const; + static uint32_t getBufferGPUCount(); static Size getBufferGPUMemoryUsage(); static uint32_t getTextureGPUCount(); static uint32_t getTextureGPUSparseCount(); static Size getFreeGPUMemory(); + static Size getUsedGPUMemory(); static Size getTextureGPUMemoryUsage(); static Size getTextureGPUVirtualMemoryUsage(); static Size getTextureGPUFramebufferMemoryUsage(); @@ -221,8 +225,12 @@ protected: std::shared_ptr _backend; bool _frameActive { false }; FramePointer _currentFrame; + RangeTimerPointer _frameRangeTimer; StereoState _stereo; + double getGPUAverage() const; + double getBatchAverage() const; + // This function can only be called by "static Shader::makeProgram()" // makeProgramShader(...) make a program shader ready to be used in a Batch. // It compiles the sub shaders, link them and defines the Slots and their bindings. From 76aa541d4aed128201e7ab61cb4b954408ef0629 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 4 Nov 2016 11:49:52 -0700 Subject: [PATCH 04/25] Adding the frame gpu and batch timer --- interface/resources/qml/Stats.qml | 9 +++++++++ interface/src/Application.cpp | 3 ++- interface/src/ui/Stats.cpp | 6 ++++++ interface/src/ui/Stats.h | 4 ++++ libraries/gpu/src/gpu/Context.cpp | 26 +++++++++++++++++++++++++- 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 1c5df5c71d..9c55b1ce2d 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -189,6 +189,15 @@ Item { Column { id: octreeCol spacing: 4; x: 4; y: 4; + StatText { + text: " Frame timing:" + } + StatText { + text: " Batch: " + root.batchFrameTime.toFixed(1) + " ms" + } + StatText { + text: " GPU: " + root.gpuFrameTime.toFixed(1) + " ms" + } StatText { text: "Triangles: " + root.triangles + " / Material Switches: " + root.materialSwitches diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 57586d734e..93a1952212 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1240,7 +1240,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo properties["gl_info"] = glInfo; properties["gpu_used_memory"] = (int)BYTES_TO_MB(gpu::Context::getUsedGPUMemory()); properties["gpu_free_memory"] = (int)BYTES_TO_MB(gpu::Context::getFreeGPUMemory()); - properties["gpu_frame_time"] = (int)(qApp->getRenderEngine()->); + properties["gpu_frame_time"] = (float)(qApp->getGPUContext()->getFrameTimerGPUAverage()); + properties["batch_frame_time"] = (float)(qApp->getGPUContext()->getFrameTimerBatchAverage()); properties["ideal_thread_count"] = QThread::idealThreadCount(); auto hmdHeadPose = getHMDSensorPose(); diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 05632cb1e6..7fc6a3af80 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -290,6 +290,12 @@ void Stats::updateStats(bool force) { STAT_UPDATE(sendingMode, sendingModeResult); } + auto& GPUContext = qApp->getGPUContext(); + + // Update Frame timing (in ms) + STAT_UPDATE(gpuFrameTime, (float) GPUContext->getFrameTimerGPUAverage()); + STAT_UPDATE(batchFrameTime, (float)GPUContext->getFrameTimerBatchAverage()); + STAT_UPDATE(gpuBuffers, (int)gpu::Context::getBufferGPUCount()); STAT_UPDATE(gpuBufferMemory, (int)BYTES_TO_MB(gpu::Context::getBufferGPUMemoryUsage())); STAT_UPDATE(gpuTextures, (int)gpu::Context::getTextureGPUCount()); diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 76c6effed7..ffa5c08bc6 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -101,6 +101,8 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, gpuTextureSparseMemory, 0) STATS_PROPERTY(int, gpuSparseTextureEnabled, 0) STATS_PROPERTY(int, gpuFreeMemory, 0) + STATS_PROPERTY(float, gpuFrameTime, 0) + STATS_PROPERTY(float, batchFrameTime, 0) public: static Stats* getInstance(); @@ -198,6 +200,8 @@ signals: void gpuTextureSparseMemoryChanged(); void gpuSparseTextureEnabledChanged(); void gpuFreeMemoryChanged(); + void gpuFrameTimeChanged(); + void batchFrameTimeChanged(); void rectifiedTextureCountChanged(); void decimatedTextureCountChanged(); diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index f1fc1067c3..4344cd4d2c 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -36,7 +36,7 @@ void Context::beginFrame(const glm::mat4& renderPose) { _currentFrame->pose = renderPose; if (!_frameRangeTimer) { - _frameRangeTimer = std::make_shared("gpu::Frame"); + _frameRangeTimer = std::make_shared(); } } @@ -77,10 +77,18 @@ void Context::executeFrame(const FramePointer& frame) const { consumeFrameUpdates(frame); _backend->setStereoState(frame->stereoState); { + Batch beginBatch; + _frameRangeTimer->begin(beginBatch); + _backend->render(beginBatch); + // Execute the frame rendering commands for (auto& batch : frame->batches) { _backend->render(batch); } + + Batch endBatch; + _frameRangeTimer->end(endBatch); + _backend->render(endBatch); } } @@ -131,6 +139,20 @@ void Context::getStats(ContextStats& stats) const { _backend->getStats(stats); } +double Context::getFrameTimerGPUAverage() const { + if (_frameRangeTimer) { + return _frameRangeTimer->getGPUAverage(); + } + return 0.0; +} + +double Context::getFrameTimerBatchAverage() const { + if (_frameRangeTimer) { + return _frameRangeTimer->getBatchAverage(); + } + return 0.0; +} + const Backend::TransformCamera& Backend::TransformCamera::recomputeDerived(const Transform& xformView) const { _projectionInverse = glm::inverse(_projection); @@ -357,3 +379,5 @@ void Backend::updateTextureGPUFramebufferMemoryUsage(Resource::Size prevObjectSi void Backend::updateTextureGPUSparseMemoryUsage(Resource::Size prevObjectSize, Resource::Size newObjectSize) { Context::updateTextureGPUSparseMemoryUsage(prevObjectSize, newObjectSize); } void Backend::incrementTextureGPUTransferCount() { Context::incrementTextureGPUTransferCount(); } void Backend::decrementTextureGPUTransferCount() { Context::decrementTextureGPUTransferCount(); } + + From 3ad9c1a797761c08b2098102e2cc8cf2af1675c3 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 4 Nov 2016 12:26:20 -0700 Subject: [PATCH 05/25] Add check to go into HMD on first run if available --- interface/src/Application.cpp | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c6a0bce2f5..abcc82d1c3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3362,13 +3362,31 @@ void Application::loadSettings() { // If there is a preferred plugin, we probably messed it up with the menu settings, so fix it. auto pluginManager = PluginManager::getInstance(); auto plugins = pluginManager->getPreferredDisplayPlugins(); - for (auto plugin : plugins) { - auto menu = Menu::getInstance(); - if (auto action = menu->getActionForOption(plugin->getName())) { - action->setChecked(true); - action->trigger(); - // Find and activated highest priority plugin, bail for the rest - break; + auto menu = Menu::getInstance(); + if (plugins.size() > 0) { + for (auto plugin : plugins) { + if (auto action = menu->getActionForOption(plugin->getName())) { + action->setChecked(true); + action->trigger(); + // Find and activated highest priority plugin, bail for the rest + break; + } + } + } else { + // If this is our first run, and no preferred devices were set, default to + // an HMD device if available. + Setting::Handle firstRun { Settings::firstRun, true }; + if (firstRun.get()) { + auto displayPlugins = pluginManager->getDisplayPlugins(); + for (auto& plugin : displayPlugins) { + if (plugin->isHmd()) { + if (auto action = menu->getActionForOption(plugin->getName())) { + action->setChecked(true); + action->trigger(); + break; + } + } + } } } From 0dac2c999eefb758a4b5eadcf32ab028c52b6a58 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 4 Nov 2016 12:27:04 -0700 Subject: [PATCH 06/25] Revert "Remove unused 'first' variable" This reverts commit 26e0d02d6067019e605b8ce3bf600aee5f8be9ad. --- interface/src/Application.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index abcc82d1c3..2594b55370 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5661,6 +5661,8 @@ void Application::updateDisplayMode() { static std::once_flag once; std::call_once(once, [&] { + bool first = true; + // first sort the plugins into groupings: standard, advanced, developer DisplayPluginList standard; DisplayPluginList advanced; From 0cec62b3a3681a21f6de3262c7b13b8442d009f8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 4 Nov 2016 12:27:15 -0700 Subject: [PATCH 07/25] Revert "Update interface to default to HMD display plugin" This reverts commit bbef07172349a785a9fc7913cf981f494db515ee. --- interface/src/Application.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2594b55370..b651926622 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5687,22 +5687,13 @@ void Application::updateDisplayMode() { standard.insert(std::end(standard), std::begin(advanced), std::end(advanced)); standard.insert(std::end(standard), std::begin(developer), std::end(developer)); - DisplayPluginPointer defaultDisplayPlugin; - - // Default to the first HMD plugin, otherwise use the first in the list. - auto hmdPluginIt = find_if(standard.begin(), standard.end(), [](DisplayPluginPointer& plugin) { return plugin->isHmd(); }); - if (hmdPluginIt != standard.end()) { - defaultDisplayPlugin = *hmdPluginIt; - } else if (standard.size() > 0) { - defaultDisplayPlugin = standard[0]; - } - foreach(auto displayPlugin, standard) { - addDisplayPluginToMenu(displayPlugin, displayPlugin.get() == defaultDisplayPlugin.get()); + addDisplayPluginToMenu(displayPlugin, first); auto displayPluginName = displayPlugin->getName(); QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, [this](const QSize & size) { resizeGL(); }); + first = false; } // after all plugins have been added to the menu, add a separator to the menu From 449add6b3452fea62e0df7e890564357206d9183 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 4 Nov 2016 13:29:27 -0700 Subject: [PATCH 08/25] Fix bad variable initialization --- interface/src/ui/Stats.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 7fc6a3af80..edf72d9758 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -290,11 +290,11 @@ void Stats::updateStats(bool force) { STAT_UPDATE(sendingMode, sendingModeResult); } - auto& GPUContext = qApp->getGPUContext(); + auto gpuContext = qApp->getGPUContext(); // Update Frame timing (in ms) - STAT_UPDATE(gpuFrameTime, (float) GPUContext->getFrameTimerGPUAverage()); - STAT_UPDATE(batchFrameTime, (float)GPUContext->getFrameTimerBatchAverage()); + STAT_UPDATE(gpuFrameTime, (float)gpuContext->getFrameTimerGPUAverage()); + STAT_UPDATE(batchFrameTime, (float)gpuContext->getFrameTimerBatchAverage()); STAT_UPDATE(gpuBuffers, (int)gpu::Context::getBufferGPUCount()); STAT_UPDATE(gpuBufferMemory, (int)BYTES_TO_MB(gpu::Context::getBufferGPUMemoryUsage())); @@ -308,7 +308,7 @@ void Stats::updateStats(bool force) { STAT_UPDATE(gpuTextureVirtualMemory, (int)BYTES_TO_MB(gpu::Texture::getTextureGPUVirtualMemoryUsage())); STAT_UPDATE(gpuTextureFramebufferMemory, (int)BYTES_TO_MB(gpu::Texture::getTextureGPUFramebufferMemoryUsage())); STAT_UPDATE(gpuTextureSparseMemory, (int)BYTES_TO_MB(gpu::Texture::getTextureGPUSparseMemoryUsage())); - STAT_UPDATE(gpuSparseTextureEnabled, qApp->getGPUContext()->getBackend()->isTextureManagementSparseEnabled() ? 1 : 0); + STAT_UPDATE(gpuSparseTextureEnabled, gpuContext->getBackend()->isTextureManagementSparseEnabled() ? 1 : 0); STAT_UPDATE(gpuFreeMemory, (int)BYTES_TO_MB(gpu::Context::getFreeGPUMemory())); STAT_UPDATE(rectifiedTextureCount, (int)RECTIFIED_TEXTURE_COUNT.load()); STAT_UPDATE(decimatedTextureCount, (int)DECIMATED_TEXTURE_COUNT.load()); From 1732448d3c3f6bd443ec17a660d995b36d0634b6 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 4 Nov 2016 13:52:16 -0700 Subject: [PATCH 09/25] Added tools/skeleton-dump tool Debug tool that prints out the skeleton hierarchy of fbx files including joint indices, bindPose and defaultPoses. The verbose option also prints the full FBX transformation set, pre/post rotations etc. --- libraries/animation/src/AnimSkeleton.cpp | 42 +++++++------- libraries/animation/src/AnimSkeleton.h | 4 +- tools/CMakeLists.txt | 4 ++ tools/skeleton-dump/CMakeLists.txt | 4 ++ tools/skeleton-dump/src/SkeletonDumpApp.cpp | 63 +++++++++++++++++++++ tools/skeleton-dump/src/SkeletonDumpApp.h | 29 ++++++++++ tools/skeleton-dump/src/main.cpp | 22 +++++++ 7 files changed, 143 insertions(+), 25 deletions(-) create mode 100644 tools/skeleton-dump/CMakeLists.txt create mode 100644 tools/skeleton-dump/src/SkeletonDumpApp.cpp create mode 100644 tools/skeleton-dump/src/SkeletonDumpApp.h create mode 100644 tools/skeleton-dump/src/main.cpp diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index a379ebd80a..0fd8ff595f 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -228,9 +228,7 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints) } } -#ifndef NDEBUG -#define DUMP_FBX_JOINTS -void AnimSkeleton::dump() const { +void AnimSkeleton::dump(bool verbose) const { qCDebug(animation) << "["; for (int i = 0; i < getNumJoints(); i++) { qCDebug(animation) << " {"; @@ -240,24 +238,24 @@ void AnimSkeleton::dump() const { qCDebug(animation) << " relBindPose =" << getRelativeBindPose(i); qCDebug(animation) << " absDefaultPose =" << getAbsoluteDefaultPose(i); qCDebug(animation) << " relDefaultPose =" << getRelativeDefaultPose(i); -#ifdef DUMP_FBX_JOINTS - qCDebug(animation) << " fbxJoint ="; - qCDebug(animation) << " isFree =" << _joints[i].isFree; - qCDebug(animation) << " freeLineage =" << _joints[i].freeLineage; - qCDebug(animation) << " parentIndex =" << _joints[i].parentIndex; - qCDebug(animation) << " translation =" << _joints[i].translation; - qCDebug(animation) << " preTransform =" << _joints[i].preTransform; - qCDebug(animation) << " preRotation =" << _joints[i].preRotation; - qCDebug(animation) << " rotation =" << _joints[i].rotation; - qCDebug(animation) << " postRotation =" << _joints[i].postRotation; - qCDebug(animation) << " postTransform =" << _joints[i].postTransform; - qCDebug(animation) << " transform =" << _joints[i].transform; - qCDebug(animation) << " rotationMin =" << _joints[i].rotationMin << ", rotationMax =" << _joints[i].rotationMax; - qCDebug(animation) << " inverseDefaultRotation" << _joints[i].inverseDefaultRotation; - qCDebug(animation) << " inverseBindRotation" << _joints[i].inverseBindRotation; - qCDebug(animation) << " bindTransform" << _joints[i].bindTransform; - qCDebug(animation) << " isSkeletonJoint" << _joints[i].isSkeletonJoint; -#endif + if (verbose) { + qCDebug(animation) << " fbxJoint ="; + qCDebug(animation) << " isFree =" << _joints[i].isFree; + qCDebug(animation) << " freeLineage =" << _joints[i].freeLineage; + qCDebug(animation) << " parentIndex =" << _joints[i].parentIndex; + qCDebug(animation) << " translation =" << _joints[i].translation; + qCDebug(animation) << " preTransform =" << _joints[i].preTransform; + qCDebug(animation) << " preRotation =" << _joints[i].preRotation; + qCDebug(animation) << " rotation =" << _joints[i].rotation; + qCDebug(animation) << " postRotation =" << _joints[i].postRotation; + qCDebug(animation) << " postTransform =" << _joints[i].postTransform; + qCDebug(animation) << " transform =" << _joints[i].transform; + qCDebug(animation) << " rotationMin =" << _joints[i].rotationMin << ", rotationMax =" << _joints[i].rotationMax; + qCDebug(animation) << " inverseDefaultRotation" << _joints[i].inverseDefaultRotation; + qCDebug(animation) << " inverseBindRotation" << _joints[i].inverseBindRotation; + qCDebug(animation) << " bindTransform" << _joints[i].bindTransform; + qCDebug(animation) << " isSkeletonJoint" << _joints[i].isSkeletonJoint; + } if (getParentIndex(i) >= 0) { qCDebug(animation) << " parent =" << getJointName(getParentIndex(i)); } @@ -284,4 +282,4 @@ void AnimSkeleton::dump(const AnimPoseVec& poses) const { } qCDebug(animation) << "]"; } -#endif + diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index e1c6ae95c8..f588c14f90 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -63,10 +63,8 @@ public: void mirrorRelativePoses(AnimPoseVec& poses) const; void mirrorAbsolutePoses(AnimPoseVec& poses) const; -#ifndef NDEBUG - void dump() const; + void dump(bool verbose) const; void dump(const AnimPoseVec& poses) const; -#endif protected: void buildSkeletonFromJoints(const std::vector& joints); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index cf0e25a757..a85a112bf5 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -13,3 +13,7 @@ set_target_properties(ice-client PROPERTIES FOLDER "Tools") add_subdirectory(ac-client) set_target_properties(ac-client PROPERTIES FOLDER "Tools") + +add_subdirectory(skeleton-dump) +set_target_properties(skeleton-dump PROPERTIES FOLDER "Tools") + diff --git a/tools/skeleton-dump/CMakeLists.txt b/tools/skeleton-dump/CMakeLists.txt new file mode 100644 index 0000000000..04d450d9c2 --- /dev/null +++ b/tools/skeleton-dump/CMakeLists.txt @@ -0,0 +1,4 @@ +set(TARGET_NAME skeleton-dump) +setup_hifi_project(Core Widgets) +link_hifi_libraries(shared fbx model gpu gl animation) + diff --git a/tools/skeleton-dump/src/SkeletonDumpApp.cpp b/tools/skeleton-dump/src/SkeletonDumpApp.cpp new file mode 100644 index 0000000000..23bb8c27f0 --- /dev/null +++ b/tools/skeleton-dump/src/SkeletonDumpApp.cpp @@ -0,0 +1,63 @@ +// +// SkeletonDumpApp.h +// tools/skeleton-dump/src +// +// Created by Anthony Thibault on 11/4/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "SkeletonDumpApp.h" +#include +#include +#include +#include + +SkeletonDumpApp::SkeletonDumpApp(int argc, char* argv[]) : QCoreApplication(argc, argv) { + + // parse command-line + QCommandLineParser parser; + parser.setApplicationDescription("High Fidelity FBX Skeleton Analyzer"); + const QCommandLineOption helpOption = parser.addHelpOption(); + + const QCommandLineOption verboseOutput("v", "verbose output"); + parser.addOption(verboseOutput); + + const QCommandLineOption inputFilenameOption("i", "input file", "filename.fbx"); + parser.addOption(inputFilenameOption); + + if (!parser.parse(QCoreApplication::arguments())) { + qCritical() << parser.errorText() << endl; + parser.showHelp(); + _returnCode = 1; + return; + } + + if (parser.isSet(helpOption)) { + parser.showHelp(); + return; + } + + bool verbose = parser.isSet(verboseOutput); + + QString inputFilename; + if (parser.isSet(inputFilenameOption)) { + inputFilename = parser.value(inputFilenameOption); + } + + QFile file(inputFilename); + if (!file.open(QIODevice::ReadOnly)) { + qCritical() << "Failed to open file " << inputFilename; + _returnCode = 2; + return; + } + QByteArray blob = file.readAll(); + std::unique_ptr fbxGeometry(readFBX(blob, QVariantHash())); + std::unique_ptr skeleton(new AnimSkeleton(*fbxGeometry)); + skeleton->dump(verbose); +} + +SkeletonDumpApp::~SkeletonDumpApp() { +} diff --git a/tools/skeleton-dump/src/SkeletonDumpApp.h b/tools/skeleton-dump/src/SkeletonDumpApp.h new file mode 100644 index 0000000000..b292d4fa2f --- /dev/null +++ b/tools/skeleton-dump/src/SkeletonDumpApp.h @@ -0,0 +1,29 @@ +// +// VHACDUtil.h +// tools/skeleton-dump/src +// +// Created by Anthony Thibault on 11/4/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_SkeletonDumpApp_h +#define hifi_SkeletonDumpApp_h + +#include + +class SkeletonDumpApp : public QCoreApplication { + Q_OBJECT +public: + SkeletonDumpApp(int argc, char* argv[]); + ~SkeletonDumpApp(); + + int getReturnCode() const { return _returnCode; } + +private: + int _returnCode { 0 }; +}; + +#endif //hifi_SkeletonDumpApp_h diff --git a/tools/skeleton-dump/src/main.cpp b/tools/skeleton-dump/src/main.cpp new file mode 100644 index 0000000000..6cf4d41f31 --- /dev/null +++ b/tools/skeleton-dump/src/main.cpp @@ -0,0 +1,22 @@ +// +// main.cpp +// tools/skeleton-dump/src +// +// Created by Anthony Thibault on 11/4/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +#include +#include +#include +#include +#include + +#include "SkeletonDumpApp.h" + +int main(int argc, char * argv[]) { + SkeletonDumpApp app(argc, argv); + return app.getReturnCode(); +} From 69fc048e5ee48571d4aee2f1c84b7ad985a97e9d Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 4 Nov 2016 14:03:59 -0700 Subject: [PATCH 10/25] typo fixes in license comments --- tools/skeleton-dump/src/SkeletonDumpApp.cpp | 2 +- tools/skeleton-dump/src/SkeletonDumpApp.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/skeleton-dump/src/SkeletonDumpApp.cpp b/tools/skeleton-dump/src/SkeletonDumpApp.cpp index 23bb8c27f0..e9d8243e38 100644 --- a/tools/skeleton-dump/src/SkeletonDumpApp.cpp +++ b/tools/skeleton-dump/src/SkeletonDumpApp.cpp @@ -1,5 +1,5 @@ // -// SkeletonDumpApp.h +// SkeletonDumpApp.cpp // tools/skeleton-dump/src // // Created by Anthony Thibault on 11/4/16. diff --git a/tools/skeleton-dump/src/SkeletonDumpApp.h b/tools/skeleton-dump/src/SkeletonDumpApp.h index b292d4fa2f..40df98eb65 100644 --- a/tools/skeleton-dump/src/SkeletonDumpApp.h +++ b/tools/skeleton-dump/src/SkeletonDumpApp.h @@ -1,5 +1,5 @@ // -// VHACDUtil.h +// SkeletonDumpApp.h // tools/skeleton-dump/src // // Created by Anthony Thibault on 11/4/16. From ae29fe8ab24456699ca0bca1f5c2482bb28ed4be Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 27 Oct 2016 18:29:22 -0700 Subject: [PATCH 11/25] Logging improvements --- assignment-client/src/AssignmentClient.cpp | 3 -- assignment-client/src/AssignmentClientApp.cpp | 3 -- .../src/AssignmentClientMonitor.cpp | 3 -- assignment-client/src/main.cpp | 9 ++-- domain-server/src/DomainServer.cpp | 10 +---- domain-server/src/DomainServer.h | 6 --- domain-server/src/main.cpp | 7 +-- ice-server/src/main.cpp | 3 +- interface/src/Application.cpp | 3 +- libraries/shared/src/LogHandler.cpp | 44 +++++++++++-------- libraries/shared/src/LogHandler.h | 2 + .../shared/src/ShutdownEventListener.cpp | 9 ++-- libraries/shared/src/shared/FileLogger.cpp | 3 +- libraries/shared/src/shared/FileLogger.h | 2 +- 14 files changed, 50 insertions(+), 57 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 3b4300b6fd..8fe618b70d 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -175,9 +175,6 @@ AssignmentClient::~AssignmentClient() { void AssignmentClient::aboutToQuit() { stopAssignmentClient(); - - // clear the log handler so that Qt doesn't call the destructor on LogHandler - qInstallMessageHandler(0); } void AssignmentClient::setUpStatusToMonitor() { diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index c425a239dd..68e7b9b997 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -45,9 +45,6 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : setApplicationName("assignment-client"); setApplicationVersion(BuildInfo::VERSION); - // use the verbose message handler in Logging - qInstallMessageHandler(LogHandler::verboseMessageHandler); - // parse command-line QCommandLineParser parser; parser.setApplicationDescription("High Fidelity Assignment Client"); diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 8ba253d549..1ee876ceea 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -126,9 +126,6 @@ void AssignmentClientMonitor::stopChildProcesses() { void AssignmentClientMonitor::aboutToQuit() { stopChildProcesses(); - - // clear the log handler so that Qt doesn't call the destructor on LogHandler - qInstallMessageHandler(0); } void AssignmentClientMonitor::spawnChildClient() { diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 052c4755f8..cf8d9ebe31 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -9,8 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - +#include #include #include "AssignmentClientApp.h" @@ -18,10 +17,14 @@ int main(int argc, char* argv[]) { disableQtBearerPoll(); // Fixes wifi ping spikes + qInstallMessageHandler(LogHandler::verboseMessageHandler); + qInfo() << "Starting."; + AssignmentClientApp app(argc, argv); int acReturn = app.exec(); qDebug() << "assignment-client process" << app.applicationPid() << "exiting with status code" << acReturn; - + + qInfo() << "Quitting."; return acReturn; } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 8b73b851b2..d13f9b883f 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -72,13 +72,10 @@ DomainServer::DomainServer(int argc, char* argv[]) : _iceServerPort(ICE_SERVER_DEFAULT_PORT) { parseCommandLine(); - qInstallMessageHandler(LogHandler::verboseMessageHandler); LogUtils::init(); Setting::init(); - connect(this, &QCoreApplication::aboutToQuit, this, &DomainServer::aboutToQuit); - setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION); setOrganizationDomain("highfidelity.io"); setApplicationName("domain-server"); @@ -211,6 +208,7 @@ void DomainServer::parseCommandLine() { } DomainServer::~DomainServer() { + qInfo() << "Domain Server is shutting down."; // destroy the LimitedNodeList before the DomainServer QCoreApplication is down DependencyManager::destroy(); } @@ -223,12 +221,6 @@ void DomainServer::queuedQuit(QString quitMessage, int exitCode) { QCoreApplication::exit(exitCode); } -void DomainServer::aboutToQuit() { - - // clear the log handler so that Qt doesn't call the destructor on LogHandler - qInstallMessageHandler(0); -} - void DomainServer::restart() { qDebug() << "domain-server is restarting."; diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 6330cf51a5..c14ec5eee0 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -72,8 +72,6 @@ public slots: void processICEServerHeartbeatACK(QSharedPointer message); private slots: - void aboutToQuit(); - void setupPendingAssignmentCredits(); void sendPendingTransactionsToServer(); @@ -150,13 +148,9 @@ private: bool isAuthenticatedRequest(HTTPConnection* connection, const QUrl& url); - void handleTokenRequestFinished(); QNetworkReply* profileRequestGivenTokenReply(QNetworkReply* tokenReply); - void handleProfileRequestFinished(); Headers setupCookieHeadersFromProfileReply(QNetworkReply* profileReply); - void loadExistingSessionsFromSettings(); - QJsonObject jsonForSocket(const HifiSockAddr& socket); QJsonObject jsonObjectForNode(const SharedNodePointer& node); diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index b3b5c8b9be..fdf7a598aa 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -15,8 +15,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include #include @@ -29,6 +27,9 @@ int main(int argc, char* argv[]) { setvbuf(stdout, NULL, _IOLBF, 0); #endif + qInstallMessageHandler(LogHandler::verboseMessageHandler); + qInfo() << "Starting."; + int currentExitCode = 0; // use a do-while to handle domain-server restart @@ -37,7 +38,7 @@ int main(int argc, char* argv[]) { currentExitCode = domainServer.exec(); } while (currentExitCode == DomainServer::EXIT_CODE_REBOOT); - + qInfo() << "Quitting."; return currentExitCode; } diff --git a/ice-server/src/main.cpp b/ice-server/src/main.cpp index 2326984668..ec8b9957cf 100644 --- a/ice-server/src/main.cpp +++ b/ice-server/src/main.cpp @@ -19,8 +19,9 @@ int main(int argc, char* argv[]) { #ifndef WIN32 setvbuf(stdout, NULL, _IOLBF, 0); #endif - + qInstallMessageHandler(LogHandler::verboseMessageHandler); + qInfo() << "Starting."; IceServer iceServer(argc, argv); return iceServer.exec(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 867761e012..ffe62f71de 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1654,7 +1654,8 @@ Application::~Application() { _window->deleteLater(); - qInstallMessageHandler(nullptr); // NOTE: Do this as late as possible so we continue to get our log messages + // Can't log to file passed this point, FileLogger about to be deleted + qInstallMessageHandler(LogHandler::verboseMessageHandler); } void Application::initializeGL() { diff --git a/libraries/shared/src/LogHandler.cpp b/libraries/shared/src/LogHandler.cpp index d142e3f839..35a3361c38 100644 --- a/libraries/shared/src/LogHandler.cpp +++ b/libraries/shared/src/LogHandler.cpp @@ -10,17 +10,18 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - -#include -#include -#include -#include -#include -#include - #include "LogHandler.h" +#include + +#include +#include +#include +#include +#include +#include +#include + QMutex LogHandler::_mutex; LogHandler& LogHandler::getInstance() { @@ -28,16 +29,15 @@ LogHandler& LogHandler::getInstance() { return staticInstance; } -LogHandler::LogHandler() -{ - // setup our timer to flush the verbose logs every 5 seconds - QTimer* logFlushTimer = new QTimer(this); - connect(logFlushTimer, &QTimer::timeout, this, &LogHandler::flushRepeatedMessages); - logFlushTimer->start(VERBOSE_LOG_INTERVAL_SECONDS * 1000); - +LogHandler::LogHandler() { // when the log handler is first setup we should print our timezone QString timezoneString = "Time zone: " + QDateTime::currentDateTime().toString("t"); - printf("%s\n", qPrintable(timezoneString)); + printMessage(LogMsgType::LogInfo, QMessageLogContext(), timezoneString); +} + +LogHandler::~LogHandler() { + flushRepeatedMessages(); + printMessage(LogMsgType::LogDebug, QMessageLogContext(), "LogHandler shutdown."); } const char* stringForLogType(LogMsgType msgType) { @@ -165,7 +165,7 @@ QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& cont stringForLogType(type), context.category); if (_shouldOutputProcessID) { - prefixString.append(QString(" [%1]").arg(QCoreApplication::instance()->applicationPid())); + prefixString.append(QString(" [%1]").arg(QCoreApplication::applicationPid())); } if (_shouldOutputThreadID) { @@ -187,6 +187,14 @@ void LogHandler::verboseMessageHandler(QtMsgType type, const QMessageLogContext& } const QString& LogHandler::addRepeatedMessageRegex(const QString& regexString) { + static std::once_flag once; + std::call_once(once, [&] { + // setup our timer to flush the verbose logs every 5 seconds + QTimer* logFlushTimer = new QTimer(this); + connect(logFlushTimer, &QTimer::timeout, this, &LogHandler::flushRepeatedMessages); + logFlushTimer->start(VERBOSE_LOG_INTERVAL_SECONDS * 1000); + }); + QMutexLocker lock(&_mutex); return *_repeatedMessageRegexes.insert(regexString); } diff --git a/libraries/shared/src/LogHandler.h b/libraries/shared/src/LogHandler.h index 890497b891..f80fad4c6a 100644 --- a/libraries/shared/src/LogHandler.h +++ b/libraries/shared/src/LogHandler.h @@ -52,8 +52,10 @@ public: const QString& addRepeatedMessageRegex(const QString& regexString); const QString& addOnlyOnceMessageRegex(const QString& regexString); + private: LogHandler(); + ~LogHandler(); void flushRepeatedMessages(); diff --git a/libraries/shared/src/ShutdownEventListener.cpp b/libraries/shared/src/ShutdownEventListener.cpp index e640126b7b..6f043cd43e 100644 --- a/libraries/shared/src/ShutdownEventListener.cpp +++ b/libraries/shared/src/ShutdownEventListener.cpp @@ -9,8 +9,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include "ShutdownEventListener.h" #ifdef Q_OS_WIN @@ -19,6 +17,9 @@ #include #endif +#include +#include + ShutdownEventListener& ShutdownEventListener::getInstance() { static ShutdownEventListener staticInstance; return staticInstance; @@ -29,9 +30,7 @@ void signalHandler(int param) { QMetaObject::invokeMethod(qApp, "quit"); } -ShutdownEventListener::ShutdownEventListener(QObject* parent) : - QObject(parent) -{ +ShutdownEventListener::ShutdownEventListener(QObject* parent) : QObject(parent) { #ifndef Q_OS_WIN // be a signal handler for SIGTERM so we can stop our children when we get it signal(SIGTERM, signalHandler); diff --git a/libraries/shared/src/shared/FileLogger.cpp b/libraries/shared/src/shared/FileLogger.cpp index ef3436a8d7..143438ba68 100644 --- a/libraries/shared/src/shared/FileLogger.cpp +++ b/libraries/shared/src/shared/FileLogger.cpp @@ -109,7 +109,8 @@ bool FilePersistThread::processQueueItems(const Queue& messages) { } FileLogger::FileLogger(QObject* parent) : - AbstractLoggerInterface(parent), _fileName(getLogFilename()) + AbstractLoggerInterface(parent), + _fileName(getLogFilename()) { _persistThreadInstance = new FilePersistThread(*this); _persistThreadInstance->initialize(true, QThread::LowestPriority); diff --git a/libraries/shared/src/shared/FileLogger.h b/libraries/shared/src/shared/FileLogger.h index 697b96c6d8..f0f6dd5c09 100644 --- a/libraries/shared/src/shared/FileLogger.h +++ b/libraries/shared/src/shared/FileLogger.h @@ -24,7 +24,7 @@ public: FileLogger(QObject* parent = NULL); virtual ~FileLogger(); - QString getFilename() { return _fileName; } + QString getFilename() const { return _fileName; } virtual void addMessage(const QString&) override; virtual QString getLogData() override; virtual void locateLog() override; From 84eb1721e7272a230fbe3ececd55740be4cffe01 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Fri, 4 Nov 2016 17:02:14 -0700 Subject: [PATCH 12/25] fix numeric keyboard for hmd Window.prompt --- interface/resources/qml/dialogs/QueryDialog.qml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/resources/qml/dialogs/QueryDialog.qml b/interface/resources/qml/dialogs/QueryDialog.qml index a922e6efc7..9a38c3f0d6 100644 --- a/interface/resources/qml/dialogs/QueryDialog.qml +++ b/interface/resources/qml/dialogs/QueryDialog.qml @@ -118,6 +118,9 @@ ModalWindow { } } + property alias keyboardOverride: root.keyboardOverride + property alias keyboardRaised: root.keyboardRaised + property alias punctuationMode: root.punctuationMode Keyboard { id: keyboard raised: keyboardEnabled && keyboardRaised From 3c76dad4549efc5d7378256c6e45b7cf2bbaceca Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 7 Nov 2016 10:42:59 -0800 Subject: [PATCH 13/25] Force sandbox config saves --- server-console/src/main.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server-console/src/main.js b/server-console/src/main.js index 6c82230601..a7855ab063 100644 --- a/server-console/src/main.js +++ b/server-console/src/main.js @@ -623,6 +623,7 @@ function checkNewContent() { } else { // They don't want to update, mark content set as current userConfig.set('homeContentLastModified', new Date()); + userConfig.save(configPath); } }); } @@ -676,6 +677,7 @@ function maybeInstallDefaultContentSet(onComplete) { } log.debug('Copied home content over to: ' + getRootHifiDataDirectory()); userConfig.set('homeContentLastModified', new Date()); + userConfig.save(configPath); onComplete(); }); return; @@ -756,6 +758,7 @@ function maybeInstallDefaultContentSet(onComplete) { // response and decompression complete, return log.debug("Finished unarchiving home content set"); userConfig.set('homeContentLastModified', new Date()); + userConfig.save(configPath); sendStateUpdate('complete'); }); @@ -766,6 +769,7 @@ function maybeInstallDefaultContentSet(onComplete) { }); userConfig.set('hasRun', true); + userConfig.save(configPath); }); } From c4f35bf7bf8dbc62bdf3de45e88852a2a4e82272 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 7 Nov 2016 11:39:23 -0800 Subject: [PATCH 14/25] Fix userData in edit.js sometimes showing wrong value when locked --- scripts/system/html/js/entityProperties.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index d6d9098e21..4fe13196f3 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -445,13 +445,11 @@ function hideUserDataTextArea() { }; function showStaticUserData() { - $('#static-userdata').show(); - $('#static-userdata').css('height', $('#userdata-editor').height()) if (editor !== null) { + $('#static-userdata').show(); + $('#static-userdata').css('height', $('#userdata-editor').height()) $('#static-userdata').text(editor.getText()); } - - }; function removeStaticUserData() { From e3941617c145e16e5183f7f02fc8dcc3ce3bad55 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 7 Nov 2016 11:43:29 -0800 Subject: [PATCH 15/25] Decrease the volume of the tutorial firecracker --- tutorial/tutorial.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorial/tutorial.js b/tutorial/tutorial.js index 3d2b4ce36b..957316734a 100644 --- a/tutorial/tutorial.js +++ b/tutorial/tutorial.js @@ -233,7 +233,7 @@ function playSuccessSound() { function playFirecrackerSound(position) { Audio.playSound(firecrackerSound, { position: position, - volume: 0.7, + volume: 0.5, loop: false }); } From f34cf64f3e4d19eb9c9c48b61c56988e2760d016 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 7 Nov 2016 15:41:43 -0800 Subject: [PATCH 16/25] Disable updater on Steam --- interface/src/Application.cpp | 12 ++++++++---- libraries/networking/src/SandboxUtils.cpp | 9 +++++++-- libraries/networking/src/SandboxUtils.h | 2 +- server-console/src/main.js | 6 +++++- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 867761e012..ea34f9fed5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -599,7 +599,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo qCDebug(interfaceapp) << "Home sandbox does not appear to be running...."; if (wantsSandboxRunning) { QString contentPath = getRunServerPath(); - SandboxUtils::runLocalSandbox(contentPath, true, RUNNING_MARKER_FILENAME); + bool noUpdater = SteamClient::isRunning(); + SandboxUtils::runLocalSandbox(contentPath, true, RUNNING_MARKER_FILENAME, noUpdater); sandboxIsRunning = true; } determinedSandboxState = true; @@ -1119,9 +1120,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo setActiveEyeTracker(); #endif - auto applicationUpdater = DependencyManager::get(); - connect(applicationUpdater.data(), &AutoUpdater::newVersionIsAvailable, dialogsManager.data(), &DialogsManager::showUpdateDialog); - applicationUpdater->checkForUpdate(); + // If launched from Steam, let it handle updates + if (!SteamClient::isRunning()) { + auto applicationUpdater = DependencyManager::get(); + connect(applicationUpdater.data(), &AutoUpdater::newVersionIsAvailable, dialogsManager.data(), &DialogsManager::showUpdateDialog); + applicationUpdater->checkForUpdate(); + } // Now that menu is initialized we can sync myAvatar with it's state. myAvatar->updateMotionBehaviorFromMenu(); diff --git a/libraries/networking/src/SandboxUtils.cpp b/libraries/networking/src/SandboxUtils.cpp index 98c963b793..b16c169baa 100644 --- a/libraries/networking/src/SandboxUtils.cpp +++ b/libraries/networking/src/SandboxUtils.cpp @@ -61,15 +61,16 @@ void SandboxUtils::ifLocalSandboxRunningElse(std::function localSandboxR } -void SandboxUtils::runLocalSandbox(QString contentPath, bool autoShutdown, QString runningMarkerName) { +void SandboxUtils::runLocalSandbox(QString contentPath, bool autoShutdown, QString runningMarkerName, bool noUpdater) { QString applicationDirPath = QFileInfo(QCoreApplication::applicationFilePath()).path(); QString serverPath = applicationDirPath + "/server-console/server-console.exe"; qDebug() << "Application dir path is: " << applicationDirPath; qDebug() << "Server path is: " << serverPath; qDebug() << "autoShutdown: " << autoShutdown; + qDebug() << "noUpdater: " << noUpdater; bool hasContentPath = !contentPath.isEmpty(); - bool passArgs = autoShutdown || hasContentPath; + bool passArgs = autoShutdown || hasContentPath || noUpdater; QStringList args; @@ -87,6 +88,10 @@ void SandboxUtils::runLocalSandbox(QString contentPath, bool autoShutdown, QStri args << "--shutdownWatcher" << interfaceRunningStateFile; } + if (noUpdater) { + args << "--noUpdater"; + } + qDebug() << applicationDirPath; qDebug() << "Launching sandbox with:" << args; qDebug() << QProcess::startDetached(serverPath, args); diff --git a/libraries/networking/src/SandboxUtils.h b/libraries/networking/src/SandboxUtils.h index e40ff71a56..aaceafb9ef 100644 --- a/libraries/networking/src/SandboxUtils.h +++ b/libraries/networking/src/SandboxUtils.h @@ -26,7 +26,7 @@ public: void ifLocalSandboxRunningElse(std::function localSandboxRunningDoThis, std::function localSandboxNotRunningDoThat); - static void runLocalSandbox(QString contentPath, bool autoShutdown, QString runningMarkerName); + static void runLocalSandbox(QString contentPath, bool autoShutdown, QString runningMarkerName, bool noUpdater); }; #endif // hifi_SandboxUtils_h diff --git a/server-console/src/main.js b/server-console/src/main.js index 6c82230601..dce28a667d 100644 --- a/server-console/src/main.js +++ b/server-console/src/main.js @@ -579,6 +579,10 @@ function backupResourceDirectoriesAndRestart() { } function checkNewContent() { + if (argv.noUpdater) { + return; + } + // Start downloading content set var req = request.head({ url: HOME_CONTENT_URL @@ -817,7 +821,7 @@ function onContentLoaded() { // Disable splash window for now. // maybeShowSplash(); - if (buildInfo.releaseType == 'PRODUCTION') { + if (buildInfo.releaseType == 'PRODUCTION' && !argv.noUpdater) { var currentVersion = null; try { currentVersion = parseInt(buildInfo.buildIdentifier); From 3105299670547152d864309b0e2427658a72e0c7 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Mon, 7 Nov 2016 18:13:10 -0800 Subject: [PATCH 17/25] Log snapshot upload and user story creation errors Plus, if the body of the error is empty, put something in there so the script will not think it was successful. --- interface/src/ui/SnapshotUploader.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/SnapshotUploader.cpp b/interface/src/ui/SnapshotUploader.cpp index c36efddc14..86eea2f122 100644 --- a/interface/src/ui/SnapshotUploader.cpp +++ b/interface/src/ui/SnapshotUploader.cpp @@ -64,7 +64,13 @@ void SnapshotUploader::uploadSuccess(QNetworkReply& reply) { } void SnapshotUploader::uploadFailure(QNetworkReply& reply) { - emit DependencyManager::get()->snapshotShared(reply.readAll()); // maybe someday include _inWorldLocation, _filename? + QString replyString = reply.readAll(); + qDebug() << "Error uploading snapshot: " << reply.errorString(); + if (replyString.size() == 0) { + replyString = reply.errorString(); + } + emit DependencyManager::get()->snapshotShared(replyString); // maybe someday include _inWorldLocation, _filename? + delete this; } @@ -74,6 +80,12 @@ void SnapshotUploader::createStorySuccess(QNetworkReply& reply) { } void SnapshotUploader::createStoryFailure(QNetworkReply& reply) { - emit DependencyManager::get()->snapshotShared(reply.readAll()); - delete this; -} \ No newline at end of file + QString replyString = reply.readAll(); + qDebug() << "Error creating user story: " << reply.errorString(); + if (replyString.size() == 0) { + replyString = reply.errorString(); + } + emit DependencyManager::get()->snapshotShared(replyString); + delete this; +} + From 1766ebab2c9374457b5f89a644fe23c36e6cf31e Mon Sep 17 00:00:00 2001 From: David Kelly Date: Tue, 8 Nov 2016 09:08:34 -0800 Subject: [PATCH 18/25] Added a bit more logging --- interface/src/ui/SnapshotUploader.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/SnapshotUploader.cpp b/interface/src/ui/SnapshotUploader.cpp index 86eea2f122..5826c8bd38 100644 --- a/interface/src/ui/SnapshotUploader.cpp +++ b/interface/src/ui/SnapshotUploader.cpp @@ -65,12 +65,11 @@ void SnapshotUploader::uploadSuccess(QNetworkReply& reply) { void SnapshotUploader::uploadFailure(QNetworkReply& reply) { QString replyString = reply.readAll(); - qDebug() << "Error uploading snapshot: " << reply.errorString(); + qDebug() << "Error " << reply.errorString() << " uploading snapshot " << _pathname << " from " << _inWorldLocation; if (replyString.size() == 0) { replyString = reply.errorString(); } emit DependencyManager::get()->snapshotShared(replyString); // maybe someday include _inWorldLocation, _filename? - delete this; } @@ -81,7 +80,7 @@ void SnapshotUploader::createStorySuccess(QNetworkReply& reply) { void SnapshotUploader::createStoryFailure(QNetworkReply& reply) { QString replyString = reply.readAll(); - qDebug() << "Error creating user story: " << reply.errorString(); + qDebug() << "Error " << reply.errorString() << " uploading snapshot " << _pathname << " from " << _inWorldLocation; if (replyString.size() == 0) { replyString = reply.errorString(); } From 7f355c48b1476c5cfe370351adb7336bcf1a9ead Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 4 Nov 2016 21:34:08 +0100 Subject: [PATCH 19/25] saving work progress --- libraries/ui/src/VrMenu.cpp | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/libraries/ui/src/VrMenu.cpp b/libraries/ui/src/VrMenu.cpp index f4b365265d..790ccfd61e 100644 --- a/libraries/ui/src/VrMenu.cpp +++ b/libraries/ui/src/VrMenu.cpp @@ -12,6 +12,7 @@ #include #include +#include #include "OffscreenUi.h" @@ -217,6 +218,7 @@ void VrMenu::insertAction(QAction* before, QAction* action) { } class QQuickMenuBase; +class QQuickMenu1; void VrMenu::removeAction(QAction* action) { if (!action) { @@ -228,10 +230,33 @@ void VrMenu::removeAction(QAction* action) { qWarning("Attempted to remove menu action with no found QML object"); return; } - + + QObject* parent = action->menu(); + QObject* qmlParent = nullptr; + + QMenu* parentMenu = dynamic_cast(parent); + if (parentMenu) { + MenuUserData* MenuUserData = MenuUserData::forObject(parentMenu->menuAction()); + if (!MenuUserData) { + return; + } + qmlParent = findMenuObject(MenuUserData->uuid.toString()); + } else if (dynamic_cast(parent)) { + qmlParent = _rootMenu; + } else { + Q_ASSERT(false); + } + QObject* item = findMenuObject(userData->uuid.toString()); - QObject* menu = item->parent(); - // Proxy QuickItem requests through the QML layer - QQuickMenuBase* qmlItem = reinterpret_cast(item); - QMetaObject::invokeMethod(menu, "removeItem", Qt::DirectConnection, Q_ARG(QQuickMenuBase*, qmlItem)); + + QQuickMenu1* menu = nullptr; + QMetaObject::invokeMethod(item, "parentMenu", Qt::DirectConnection, Q_RETURN_ARG(QQuickMenu1*, menu)); + + if (!menu) { + return; + } + QQuickMenuBase* menuItem = reinterpret_cast(item); + QObject* baseMenu = reinterpret_cast(menu); + + QMetaObject::invokeMethod(baseMenu, "removeItem", Qt::DirectConnection, Q_ARG(QQuickMenuBase*, menuItem)); } From 4b087a271817766a4622a43b246fe4025bd636df Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 8 Nov 2016 19:47:44 +0000 Subject: [PATCH 20/25] fixed unable to remove menus from vrmenu context --- libraries/ui/src/VrMenu.cpp | 42 ++++++++++++------------------------ libraries/ui/src/ui/Menu.cpp | 19 +++++++++------- 2 files changed, 25 insertions(+), 36 deletions(-) diff --git a/libraries/ui/src/VrMenu.cpp b/libraries/ui/src/VrMenu.cpp index 790ccfd61e..552d082aaa 100644 --- a/libraries/ui/src/VrMenu.cpp +++ b/libraries/ui/src/VrMenu.cpp @@ -59,6 +59,18 @@ public: _qml->setProperty("visible", _action->isVisible()); } + void clear() { + _qml->setProperty("checkable", 0); + _qml->setProperty("enabled", 0); + _qml->setProperty("text", 0); + _qml->setProperty("shortcut", 0); + _qml->setProperty("checked", 0); + _qml->setProperty("visible", 0); + + _action->setUserData(USER_DATA_ID, nullptr); + _qml->setUserData(USER_DATA_ID, nullptr); + } + const QUuid uuid{ QUuid::createUuid() }; @@ -231,32 +243,6 @@ void VrMenu::removeAction(QAction* action) { return; } - QObject* parent = action->menu(); - QObject* qmlParent = nullptr; - - QMenu* parentMenu = dynamic_cast(parent); - if (parentMenu) { - MenuUserData* MenuUserData = MenuUserData::forObject(parentMenu->menuAction()); - if (!MenuUserData) { - return; - } - qmlParent = findMenuObject(MenuUserData->uuid.toString()); - } else if (dynamic_cast(parent)) { - qmlParent = _rootMenu; - } else { - Q_ASSERT(false); - } - - QObject* item = findMenuObject(userData->uuid.toString()); - - QQuickMenu1* menu = nullptr; - QMetaObject::invokeMethod(item, "parentMenu", Qt::DirectConnection, Q_RETURN_ARG(QQuickMenu1*, menu)); - - if (!menu) { - return; - } - QQuickMenuBase* menuItem = reinterpret_cast(item); - QObject* baseMenu = reinterpret_cast(menu); - - QMetaObject::invokeMethod(baseMenu, "removeItem", Qt::DirectConnection, Q_ARG(QQuickMenuBase*, menuItem)); + userData->clear(); + delete userData; } diff --git a/libraries/ui/src/ui/Menu.cpp b/libraries/ui/src/ui/Menu.cpp index fcce999839..aee8b40832 100644 --- a/libraries/ui/src/ui/Menu.cpp +++ b/libraries/ui/src/ui/Menu.cpp @@ -84,7 +84,7 @@ void Menu::scanMenu(QMenu& menu, settingsAction modifySetting, Settings& setting groups.pop_back(); } -void Menu::addDisabledActionAndSeparator(MenuWrapper* destinationMenu, const QString& actionName, +void Menu::addDisabledActionAndSeparator(MenuWrapper* destinationMenu, const QString& actionName, int menuItemLocation, const QString& grouping) { QAction* actionBefore = NULL; QAction* separator; @@ -123,7 +123,7 @@ QAction* Menu::addActionToQMenuAndActionHash(MenuWrapper* destinationMenu, const QObject* receiver, const char* member, QAction::MenuRole role, - int menuItemLocation, + int menuItemLocation, const QString& grouping) { QAction* action = NULL; QAction* actionBefore = NULL; @@ -165,7 +165,7 @@ QAction* Menu::addActionToQMenuAndActionHash(MenuWrapper* destinationMenu, const QString& actionName, const QKeySequence& shortcut, QAction::MenuRole role, - int menuItemLocation, + int menuItemLocation, const QString& grouping) { QAction* actionBefore = NULL; @@ -207,7 +207,7 @@ QAction* Menu::addCheckableActionToQMenuAndActionHash(MenuWrapper* destinationMe const bool checked, const QObject* receiver, const char* member, - int menuItemLocation, + int menuItemLocation, const QString& grouping) { QAction* action = addActionToQMenuAndActionHash(destinationMenu, actionName, shortcut, receiver, member, @@ -408,6 +408,10 @@ void Menu::removeMenu(const QString& menuName) { parent->removeAction(action); } else { QMenuBar::removeAction(action); + auto offscreenUi = DependencyManager::get(); + offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { + vrMenu->removeAction(action); + }); } QMenuBar::repaint(); @@ -496,15 +500,15 @@ void Menu::setGroupingIsVisible(const QString& grouping, bool isVisible) { void Menu::addActionGroup(const QString& groupName, const QStringList& actionList, const QString& selected, QObject* receiver, const char* slot) { auto menu = addMenu(groupName); - + QActionGroup* actionGroup = new QActionGroup(menu); actionGroup->setExclusive(true); - + for (auto action : actionList) { auto item = addCheckableActionToQMenuAndActionHash(menu, action, 0, action == selected, receiver, slot); actionGroup->addAction(item); } - + QMenuBar::repaint(); } @@ -582,4 +586,3 @@ void MenuWrapper::insertAction(QAction* before, QAction* action) { vrMenu->insertAction(before, action); }); } - From 9e929ca6292ab6db4eb331d6f033270bcad5cae9 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Fri, 4 Nov 2016 18:00:07 -0700 Subject: [PATCH 21/25] Re-enable downsampling for non-sparse textures --- libraries/gpu-gl/src/gpu/gl/GLTexture.cpp | 2 +- libraries/gpu-gl/src/gpu/gl45/GL45Backend.h | 1 + .../src/gpu/gl45/GL45BackendTexture.cpp | 114 +++++++++++------- libraries/gpu/src/gpu/Texture.cpp | 13 +- libraries/gpu/src/gpu/Texture.h | 7 +- tests/render-perf/src/main.cpp | 2 +- 6 files changed, 91 insertions(+), 48 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp b/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp index 3ce1c8e5c4..1e0dd08ae1 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp @@ -116,7 +116,7 @@ float GLTexture::getMemoryPressure() { } // Return the consumed texture memory divided by the available texture memory. - auto consumedGpuMemory = Context::getTextureGPUSparseMemoryUsage(); + auto consumedGpuMemory = Context::getTextureGPUMemoryUsage() - Context::getTextureGPUFramebufferMemoryUsage(); float memoryPressure = (float)consumedGpuMemory / (float)availableTextureMemory; static Context::Size lastConsumedGpuMemory = 0; if (memoryPressure > 1.0f && lastConsumedGpuMemory != consumedGpuMemory) { diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h index 643d54af6a..438b1e9454 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h +++ b/libraries/gpu-gl/src/gpu/gl45/GL45Backend.h @@ -94,6 +94,7 @@ public: TransferState _transferState; uint32_t _allocatedPages { 0 }; uint32_t _lastMipAllocatedPages { 0 }; + uint16_t _mipOffset { 0 }; friend class GL45Backend; }; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index ac9a84513e..d316116561 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -282,20 +282,22 @@ GL45Texture::~GL45Texture() { if (!_gpuObject.getUsage().isExternal()) { qCDebug(gpugl45logging) << "Destroying texture " << _id << " from source " << _source.c_str(); } - if (_sparseInfo.sparse) { - Backend::decrementTextureGPUSparseCount(); - // Remove this texture from the candidate list of derezzable textures - { - auto mipLevels = usedMipLevels(); - Lock lock(texturesByMipCountsMutex); - if (texturesByMipCounts.count(mipLevels)) { - auto& textures = texturesByMipCounts[mipLevels]; - textures.erase(this); - if (textures.empty()) { - texturesByMipCounts.erase(mipLevels); - } + + // Remove this texture from the candidate list of derezzable textures + if (_transferrable) { + auto mipLevels = usedMipLevels(); + Lock lock(texturesByMipCountsMutex); + if (texturesByMipCounts.count(mipLevels)) { + auto& textures = texturesByMipCounts[mipLevels]; + textures.erase(this); + if (textures.empty()) { + texturesByMipCounts.erase(mipLevels); } } + } + + if (_sparseInfo.sparse) { + Backend::decrementTextureGPUSparseCount(); // Experimenation suggests that allocating sparse textures on one context/thread and deallocating // them on another is buggy. So for sparse textures we need to queue a lambda with the deallocation @@ -355,7 +357,7 @@ void GL45Texture::allocateStorage() const { glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, 0); glTextureParameteri(_id, GL_TEXTURE_MAX_LEVEL, _maxMip - _minMip); // Get the dimensions, accounting for the downgrade level - Vec3u dimensions = _gpuObject.evalMipDimensions(_minMip); + Vec3u dimensions = _gpuObject.evalMipDimensions(_minMip + _mipOffset); glTextureStorage2D(_id, usedMipLevels(), _internalFormat, dimensions.x, dimensions.y); (void)CHECK_GL_ERROR(); } @@ -370,7 +372,7 @@ void GL45Texture::updateSize() const { Backend::updateTextureGPUSparseMemoryUsage(_size, size); setSize(_allocatedPages * _sparseInfo.pageBytes); } else { - setSize(_virtualSize); + setSize(_gpuObject.evalTotalSize(_mipOffset)); } } @@ -481,35 +483,30 @@ void GL45Texture::syncSampler() const { glTextureParameteri(_id, GL_TEXTURE_WRAP_T, WRAP_MODES[sampler.getWrapModeV()]); glTextureParameteri(_id, GL_TEXTURE_WRAP_R, WRAP_MODES[sampler.getWrapModeW()]); glTextureParameterfv(_id, GL_TEXTURE_BORDER_COLOR, (const float*)&sampler.getBorderColor()); + // FIXME account for mip offsets here auto baseMip = std::max(sampler.getMipOffset(), _minMip); glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, baseMip); glTextureParameterf(_id, GL_TEXTURE_MIN_LOD, (float)sampler.getMinMip()); - glTextureParameterf(_id, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip())); + glTextureParameterf(_id, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip() - _mipOffset)); glTextureParameterf(_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, sampler.getMaxAnisotropy()); } void GL45Texture::postTransfer() { Parent::postTransfer(); - if (_sparseInfo.sparse) { - auto mipLevels = usedMipLevels(); - if (mipLevels > 1 && _minMip < _sparseInfo.maxSparseLevel) { - Lock lock(texturesByMipCountsMutex); - texturesByMipCounts[mipLevels].insert(this); - } + auto mipLevels = usedMipLevels(); + if (_transferrable && mipLevels > 1 && _minMip < _sparseInfo.maxSparseLevel) { + Lock lock(texturesByMipCountsMutex); + texturesByMipCounts[mipLevels].insert(this); } } void GL45Texture::stripToMip(uint16_t newMinMip) { - if (!_sparseInfo.sparse) { - return; - } - if (newMinMip < _minMip) { qCWarning(gpugl45logging) << "Cannot decrease the min mip"; return; } - if (newMinMip > _sparseInfo.maxSparseLevel) { + if (_sparseInfo.sparse && newMinMip > _sparseInfo.maxSparseLevel) { qCWarning(gpugl45logging) << "Cannot increase the min mip into the mip tail"; return; } @@ -533,19 +530,53 @@ void GL45Texture::stripToMip(uint16_t newMinMip) { uint8_t maxFace = (uint8_t)((_target == GL_TEXTURE_CUBE_MAP) ? GLTexture::CUBE_NUM_FACES : 1); - for (uint16_t mip = _minMip; mip < newMinMip; ++mip) { - auto id = _id; - auto mipDimensions = _gpuObject.evalMipDimensions(mip); - _textureTransferHelper->queueExecution([id, mip, mipDimensions, maxFace] { - glTexturePageCommitmentEXT(id, mip, 0, 0, 0, mipDimensions.x, mipDimensions.y, maxFace, GL_FALSE); - }); + if (_sparseInfo.sparse) { + for (uint16_t mip = _minMip; mip < newMinMip; ++mip) { + auto id = _id; + auto mipDimensions = _gpuObject.evalMipDimensions(mip); + _textureTransferHelper->queueExecution([id, mip, mipDimensions, maxFace] { + glTexturePageCommitmentEXT(id, mip, 0, 0, 0, mipDimensions.x, mipDimensions.y, maxFace, GL_FALSE); + }); - auto deallocatedPages = _sparseInfo.getPageCount(mipDimensions) * maxFace; - assert(deallocatedPages < _allocatedPages); - _allocatedPages -= deallocatedPages; + auto deallocatedPages = _sparseInfo.getPageCount(mipDimensions) * maxFace; + assert(deallocatedPages < _allocatedPages); + _allocatedPages -= deallocatedPages; + } + _minMip = newMinMip; + } else { + GLuint oldId = _id; + // Find the distance between the old min mip and the new one + uint16 mipDelta = newMinMip - _minMip; + _mipOffset += mipDelta; + const_cast(_maxMip) -= mipDelta; + auto newLevels = usedMipLevels(); + + // Create and setup the new texture (allocate) + glCreateTextures(_target, 1, &const_cast(_id)); + glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, 0); + glTextureParameteri(_id, GL_TEXTURE_MAX_LEVEL, _maxMip - _minMip); + Vec3u newDimensions = _gpuObject.evalMipDimensions(_mipOffset); + glTextureStorage2D(_id, newLevels, _internalFormat, newDimensions.x, newDimensions.y); + + // Copy the contents of the old texture to the new + GLuint fbo { 0 }; + glCreateFramebuffers(1, &fbo); + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + for (uint16 targetMip = _minMip; targetMip <= _maxMip; ++targetMip) { + uint16 sourceMip = targetMip + mipDelta; + Vec3u mipDimensions = _gpuObject.evalMipDimensions(targetMip + _mipOffset); + for (GLenum target : getFaceTargets(_target)) { + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, oldId, sourceMip); + (void)CHECK_GL_ERROR(); + glCopyTextureSubImage2D(_id, targetMip, 0, 0, 0, 0, mipDimensions.x, mipDimensions.y); + (void)CHECK_GL_ERROR(); + } + } + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &fbo); + glDeleteTextures(1, &oldId); } - _minMip = newMinMip; // Re-sync the sampler to force access to the new mip level syncSampler(); updateSize(); @@ -553,7 +584,7 @@ void GL45Texture::stripToMip(uint16_t newMinMip) { // Re-insert into the texture-by-mips map if appropriate mipLevels = usedMipLevels(); - if (_sparseInfo.sparse && mipLevels > 1 && _minMip < _sparseInfo.maxSparseLevel) { + if (mipLevels > 1 && (!_sparseInfo.sparse || _minMip < _sparseInfo.maxSparseLevel)) { Lock lock(texturesByMipCountsMutex); texturesByMipCounts[mipLevels].insert(this); } @@ -570,8 +601,9 @@ void GL45Texture::updateMips() { } void GL45Texture::derez() { - assert(_sparseInfo.sparse); - assert(_minMip < _sparseInfo.maxSparseLevel); + if (_sparseInfo.sparse) { + assert(_minMip < _sparseInfo.maxSparseLevel); + } assert(_minMip < _maxMip); assert(_transferrable); stripToMip(_minMip + 1); @@ -595,7 +627,7 @@ void GL45Backend::derezTextures() const { } qCDebug(gpugl45logging) << "Allowed texture memory " << Texture::getAllowedGPUMemoryUsage(); - qCDebug(gpugl45logging) << "Used texture memory " << Context::getTextureGPUMemoryUsage(); + qCDebug(gpugl45logging) << "Used texture memory " << (Context::getTextureGPUMemoryUsage() - Context::getTextureGPUFramebufferMemoryUsage()); GL45Texture* targetTexture = nullptr; { @@ -605,5 +637,5 @@ void GL45Backend::derezTextures() const { } lock.unlock(); targetTexture->derez(); - qCDebug(gpugl45logging) << "New Used texture memory " << Context::getTextureGPUMemoryUsage(); + qCDebug(gpugl45logging) << "New Used texture memory " << (Context::getTextureGPUMemoryUsage() - Context::getTextureGPUFramebufferMemoryUsage()); } diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 3283f5a4d9..7a13c792cb 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -15,6 +15,7 @@ #include "Texture.h" #include +#include #include @@ -418,12 +419,18 @@ uint16 Texture::evalDimNumMips(uint16 size) { return 1 + (uint16) val; } +static const double LOG_2 = log(2.0); + +uint16 Texture::evalNumMips(const Vec3u& dimensions) { + double largerDim = glm::compMax(dimensions); + double val = log(largerDim) / LOG_2; + return 1 + (uint16)val; +} + // The number mips that the texture could have if all existed // = log2(max(width, height, depth)) uint16 Texture::evalNumMips() const { - double largerDim = std::max(std::max(_width, _height), _depth); - double val = log(largerDim)/log(2.0); - return 1 + (uint16) val; + return evalNumMips({ _width, _height, _depth }); } bool Texture::assignStoredMip(uint16 level, const Element& format, Size size, const Byte* bytes) { diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 1eacb46d77..7233c5b098 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -369,9 +369,12 @@ public: // = 1 + log2(max(width, height, depth)) uint16 evalNumMips() const; + static uint16 evalNumMips(const Vec3u& dimnsions); + // Eval the size that the mips level SHOULD have // not the one stored in the Texture static const uint MIN_DIMENSION = 1; + Vec3u evalMipDimensions(uint16 level) const; uint16 evalMipWidth(uint16 level) const { return std::max(_width >> level, 1); } uint16 evalMipHeight(uint16 level) const { return std::max(_height >> level, 1); } @@ -388,9 +391,9 @@ public: uint32 evalStoredMipFaceSize(uint16 level, const Element& format) const { return evalMipFaceNumTexels(level) * format.getSize(); } uint32 evalStoredMipSize(uint16 level, const Element& format) const { return evalMipNumTexels(level) * format.getSize(); } - uint32 evalTotalSize() const { + uint32 evalTotalSize(uint16 startingMip = 0) const { uint32 size = 0; - uint16 minMipLevel = minMip(); + uint16 minMipLevel = std::max(minMip(), startingMip); uint16 maxMipLevel = maxMip(); for (uint16 l = minMipLevel; l <= maxMipLevel; l++) { size += evalMipSize(l); diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index d4a8322f8a..b152c4b4bf 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -599,7 +599,7 @@ protected: return; case Qt::Key_End: - gpu::Texture::setAllowedGPUMemoryUsage(MB_TO_BYTES(256)); + gpu::Texture::setAllowedGPUMemoryUsage(MB_TO_BYTES(64)); return; From 192c72ff99be46b83a6541945d4d40446fad4ad1 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 8 Nov 2016 09:47:15 -0800 Subject: [PATCH 22/25] Update menu, initial state for texture management --- interface/src/Menu.cpp | 18 ++---------- interface/src/Menu.h | 4 +-- libraries/gpu-gl/src/gpu/gl/GLBackend.h | 2 -- .../src/gpu/gl45/GL45BackendTexture.cpp | 7 +---- libraries/gpu/src/gpu/Context.h | 1 - libraries/gpu/src/gpu/Texture.cpp | 29 ++++++++++++------- libraries/gpu/src/gpu/Texture.h | 2 +- 7 files changed, 26 insertions(+), 37 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index d357713bff..6207ecdb3c 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -387,21 +387,9 @@ Menu::Menu() { }); #ifdef Q_OS_WIN - #define MIN_CORES_FOR_INCREMENTAL_TEXTURES 5 - bool recommendedIncrementalTransfers = (QThread::idealThreadCount() >= MIN_CORES_FOR_INCREMENTAL_TEXTURES); - bool recommendedSparseTextures = recommendedIncrementalTransfers; - - qDebug() << "[TEXTURE TRANSFER SUPPORT]" - << "\n\tidealThreadCount:" << QThread::idealThreadCount() - << "\n\tRECOMMENDED enableSparseTextures:" << recommendedSparseTextures - << "\n\tRECOMMENDED enableIncrementalTextures:" << recommendedIncrementalTransfers; - - gpu::Texture::setEnableIncrementalTextureTransfers(recommendedIncrementalTransfers); - gpu::Texture::setEnableSparseTextures(recommendedSparseTextures); - - // Developer > Render > Enable Dynamic Texture Management + // Developer > Render > Enable Sparse Textures { - auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::EnableDynamicTextureManagement, 0, recommendedSparseTextures); + auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::SparseTextureManagement, 0, gpu::Texture::getEnableSparseTextures()); connect(action, &QAction::triggered, [&](bool checked) { qDebug() << "[TEXTURE TRANSFER SUPPORT] --- Enable Dynamic Texture Management menu option:" << checked; gpu::Texture::setEnableSparseTextures(checked); @@ -410,7 +398,7 @@ Menu::Menu() { // Developer > Render > Enable Incremental Texture Transfer { - auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::EnableIncrementalTextureTransfer, 0, recommendedIncrementalTransfers); + auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::IncrementalTextureTransfer, 0, gpu::Texture::getEnableIncrementalTextureTransfers()); connect(action, &QAction::triggered, [&](bool checked) { qDebug() << "[TEXTURE TRANSFER SUPPORT] --- Enable Incremental Texture Transfer menu option:" << checked; gpu::Texture::setEnableIncrementalTextureTransfers(checked); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 640a3e05d2..87e0e678f1 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -97,8 +97,6 @@ namespace MenuOption { const QString EchoLocalAudio = "Echo Local Audio"; const QString EchoServerAudio = "Echo Server Audio"; const QString EnableCharacterController = "Enable avatar collisions"; - const QString EnableIncrementalTextureTransfer = "Enable Incremental Texture Transfer"; - const QString EnableDynamicTextureManagement = "Enable Dynamic Texture Management"; const QString EnableInverseKinematics = "Enable Inverse Kinematics"; const QString ExpandMyAvatarSimulateTiming = "Expand /myAvatar/simulation"; const QString ExpandMyAvatarTiming = "Expand /myAvatar"; @@ -114,6 +112,7 @@ namespace MenuOption { const QString FrameTimer = "Show Timer"; const QString FullscreenMirror = "Mirror"; const QString Help = "Help..."; + const QString IncrementalTextureTransfer = "Enable Incremental Texture Transfer"; const QString IncreaseAvatarSize = "Increase Avatar Size"; const QString IndependentMode = "Independent Mode"; const QString ActionMotorControl = "Enable Default Motor Control"; @@ -180,6 +179,7 @@ namespace MenuOption { const QString StandingHMDSensorMode = "Standing HMD Sensor Mode"; const QString SimulateEyeTracking = "Simulate"; const QString SMIEyeTracking = "SMI Eye Tracking"; + const QString SparseTextureManagement = "Enable Sparse Texture Management"; const QString Stats = "Stats"; const QString StopAllScripts = "Stop All Scripts"; const QString SuppressShortTimings = "Suppress Timings Less than 10ms"; diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.h b/libraries/gpu-gl/src/gpu/gl/GLBackend.h index 1be279b375..417b090d31 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.h @@ -177,7 +177,6 @@ public: virtual void queueLambda(const std::function lambda) const; bool isTextureManagementSparseEnabled() const override { return (_textureManagement._sparseCapable && Texture::getEnableSparseTextures()); } - bool isTextureManagementIncrementalTransferEnabled() const override { return (_textureManagement._incrementalTransferCapable && Texture::getEnableIncrementalTextureTransfers()); } protected: @@ -369,7 +368,6 @@ protected: struct TextureManagementStageState { bool _sparseCapable { false }; - bool _incrementalTransferCapable { false }; } _textureManagement; virtual void initTextureManagementStage() {} diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index d316116561..275bf654f8 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -148,13 +148,9 @@ uint32_t SparseInfo::getPageCount(const uvec3& dimensions) const { return pageCounts.x * pageCounts.y * pageCounts.z; } - - void GL45Backend::initTextureManagementStage() { - // enable the Sparse Texture on gl45 _textureManagement._sparseCapable = true; - _textureManagement._incrementalTransferCapable = true; // But now let s refine the behavior based on vendor std::string vendor { (const char*)glGetString(GL_VENDOR) }; @@ -383,8 +379,7 @@ void GL45Texture::startTransfer() { } bool GL45Texture::continueTransfer() { - auto backend = _backend.lock(); - if (!backend || !backend->isTextureManagementIncrementalTransferEnabled()) { + if (!Texture::getEnableIncrementalTextureTransfers()) { size_t maxFace = GL_TEXTURE_CUBE_MAP == _target ? CUBE_NUM_FACES : 1; for (uint8_t face = 0; face < maxFace; ++face) { for (uint16_t mipLevel = _minMip; mipLevel <= _maxMip; ++mipLevel) { diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 3564655a3d..19d2ae767f 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -86,7 +86,6 @@ public: void getStats(ContextStats& stats) const { stats = _stats; } virtual bool isTextureManagementSparseEnabled() const = 0; - virtual bool isTextureManagementIncrementalTransferEnabled() const = 0; // These should only be accessed by Backend implementation to repport the buffer and texture allocations, // they are NOT public calls diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 7a13c792cb..33786155db 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -10,13 +10,14 @@ // -#include - #include "Texture.h" #include #include +#include +#include + #include #include "GPULogging.h" @@ -32,16 +33,27 @@ std::atomic Texture::_textureCPUCount{ 0 }; std::atomic Texture::_textureCPUMemoryUsage{ 0 }; std::atomic Texture::_allowedCPUMemoryUsage { 0 }; -std::atomic Texture::_enableSparseTextures { false }; -std::atomic Texture::_enableIncrementalTextureTransfers { false }; + +#define MIN_CORES_FOR_INCREMENTAL_TEXTURES 5 +bool recommendedIncrementalTransfers = (QThread::idealThreadCount() >= MIN_CORES_FOR_INCREMENTAL_TEXTURES); +bool recommendedSparseTextures = recommendedIncrementalTransfers; + +std::atomic Texture::_enableSparseTextures { recommendedIncrementalTransfers }; +std::atomic Texture::_enableIncrementalTextureTransfers { recommendedSparseTextures }; + +struct ReportTextureState { + ReportTextureState() { + qDebug() << "[TEXTURE TRANSFER SUPPORT]" + << "\n\tidealThreadCount:" << QThread::idealThreadCount() + << "\n\tRECOMMENDED enableSparseTextures:" << recommendedSparseTextures + << "\n\tRECOMMENDED enableIncrementalTextures:" << recommendedIncrementalTransfers; + } +} report; void Texture::setEnableSparseTextures(bool enabled) { #ifdef Q_OS_WIN qDebug() << "[TEXTURE TRANSFER SUPPORT] SETTING - Enable Sparse Textures and Dynamic Texture Management:" << enabled; _enableSparseTextures = enabled; - if (!_enableIncrementalTextureTransfers && _enableSparseTextures) { - qDebug() << "[TEXTURE TRANSFER SUPPORT] WARNING - Sparse texture management requires incremental texture transfer enabled."; - } #else qDebug() << "[TEXTURE TRANSFER SUPPORT] Sparse Textures and Dynamic Texture Management not supported on this platform."; #endif @@ -51,9 +63,6 @@ void Texture::setEnableIncrementalTextureTransfers(bool enabled) { #ifdef Q_OS_WIN qDebug() << "[TEXTURE TRANSFER SUPPORT] SETTING - Enable Incremental Texture Transfer:" << enabled; _enableIncrementalTextureTransfers = enabled; - if (!_enableIncrementalTextureTransfers && _enableSparseTextures) { - qDebug() << "[TEXTURE TRANSFER SUPPORT] WARNING - Sparse texture management requires incremental texture transfer enabled."; - } #else qDebug() << "[TEXTURE TRANSFER SUPPORT] Incremental Texture Transfer not supported on this platform."; #endif diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 7233c5b098..2a93ec3066 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -369,7 +369,7 @@ public: // = 1 + log2(max(width, height, depth)) uint16 evalNumMips() const; - static uint16 evalNumMips(const Vec3u& dimnsions); + static uint16 evalNumMips(const Vec3u& dimensions); // Eval the size that the mips level SHOULD have // not the one stored in the Texture From f7d1b3c823fcdfbaa47fca73f391cdd54296d7f6 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 1 Nov 2016 10:05:15 -0700 Subject: [PATCH 23/25] Fix non-incremental transfers when sparse enabled --- libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 275bf654f8..f97364f5c5 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -383,10 +383,14 @@ bool GL45Texture::continueTransfer() { size_t maxFace = GL_TEXTURE_CUBE_MAP == _target ? CUBE_NUM_FACES : 1; for (uint8_t face = 0; face < maxFace; ++face) { for (uint16_t mipLevel = _minMip; mipLevel <= _maxMip; ++mipLevel) { + auto size = _gpuObject.evalMipDimensions(mipLevel); + if (_sparseInfo.sparse && mipLevel <= _sparseInfo.maxSparseLevel) { + glTexturePageCommitmentEXT(_id, mipLevel, 0, 0, face, size.x, size.y, 1, GL_TRUE); + _allocatedPages += _sparseInfo.getPageCount(size); + } if (_gpuObject.isStoredMipFaceAvailable(mipLevel, face)) { auto mip = _gpuObject.accessStoredMipFace(mipLevel, face); GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), mip->getFormat()); - auto size = _gpuObject.evalMipDimensions(mipLevel); if (GL_TEXTURE_2D == _target) { glTextureSubImage2D(_id, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData()); } else if (GL_TEXTURE_CUBE_MAP == _target) { From cf3d1011f463e5d471f2e0500796764fd41a0e14 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 9 Nov 2016 12:26:57 -0800 Subject: [PATCH 24/25] remove scripts from avatar attached entities for other avatars --- interface/src/avatar/Avatar.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 0366d566d2..7114e81b3b 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -235,6 +235,14 @@ void Avatar::updateAvatarEntities() { properties.setParentID(getID()); } + // NOTE: if this avatar entity is not attached to us, strip it's entity script completely... + auto attachedScript = properties.getScript(); + if (!isMyAvatar() && !attachedScript.isEmpty()) { + qCDebug(interfaceapp) << "removing entity script from avatar attached entity:" << entityID << "old script:" << attachedScript; + QString noScript; + properties.setScript(noScript); + } + EntityItemPointer entity = entityTree->findEntityByEntityItemID(EntityItemID(entityID)); if (entity) { From 770bf35d2b57253e1eaba9a63746223ffe068f3f Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 9 Nov 2016 14:31:18 -0800 Subject: [PATCH 25/25] CR feedback --- interface/src/avatar/Avatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 7114e81b3b..872d2af04e 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -235,7 +235,7 @@ void Avatar::updateAvatarEntities() { properties.setParentID(getID()); } - // NOTE: if this avatar entity is not attached to us, strip it's entity script completely... + // NOTE: if this avatar entity is not attached to us, strip its entity script completely... auto attachedScript = properties.getScript(); if (!isMyAvatar() && !attachedScript.isEmpty()) { qCDebug(interfaceapp) << "removing entity script from avatar attached entity:" << entityID << "old script:" << attachedScript;