From 693e27716ef90619ca965b765d38c38d5315c183 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 8 Feb 2018 14:19:19 -0800 Subject: [PATCH 001/138] pull task out of render and into its own lib --- tests/render-perf/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/render-perf/CMakeLists.txt b/tests/render-perf/CMakeLists.txt index 7ad38c5795..7e61d9550c 100644 --- a/tests/render-perf/CMakeLists.txt +++ b/tests/render-perf/CMakeLists.txt @@ -13,8 +13,8 @@ set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") # link in the shared libraries link_hifi_libraries( - shared task networking animation - ktx image octree gl gpu gpu-gl + shared task networking animation + ktx image octree gl gpu gpu-gl render render-utils graphics fbx model-networking entities entities-renderer audio avatars script-engine From fea39fbe0382d0d8d8af33364e5b33808bf3e2d0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 12 Feb 2018 16:15:56 -0800 Subject: [PATCH 002/138] JobConfig::isEnabled() should be const --- libraries/task/src/task/Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index 36dfb35f25..d2cc1a8cd8 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -96,7 +96,7 @@ public: JobConfig() = default; JobConfig(bool enabled) : alwaysEnabled{ false }, enabled{ enabled } {} - bool isEnabled() { return alwaysEnabled || enabled; } + bool isEnabled() const { return alwaysEnabled || enabled; } void setEnabled(bool enable) { enabled = alwaysEnabled || enable; emit dirtyEnabled(); } bool alwaysEnabled{ true }; From 4969b8511d9086147ebae26c53478f92e8f77d38 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 12 Feb 2018 16:18:10 -0800 Subject: [PATCH 003/138] cleanup 'workload' dependency on 'task' library --- libraries/workload/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/workload/CMakeLists.txt b/libraries/workload/CMakeLists.txt index 3fcf00e0e9..beaed55734 100644 --- a/libraries/workload/CMakeLists.txt +++ b/libraries/workload/CMakeLists.txt @@ -1,5 +1,3 @@ set(TARGET_NAME workload) setup_hifi_library() - -link_hifi_libraries(shared) - +link_hifi_libraries(shared task) From 7342bc84f52e2f27fd08e3e3a0392acaabade624 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 12 Feb 2018 16:20:33 -0800 Subject: [PATCH 004/138] 'Hello world.' implementation of a Job engine --- libraries/workload/src/workload/Engine.cpp | 57 ++++++++++++++++ libraries/workload/src/workload/Engine.h | 76 ++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 libraries/workload/src/workload/Engine.cpp create mode 100644 libraries/workload/src/workload/Engine.h diff --git a/libraries/workload/src/workload/Engine.cpp b/libraries/workload/src/workload/Engine.cpp new file mode 100644 index 0000000000..7e69731d4e --- /dev/null +++ b/libraries/workload/src/workload/Engine.cpp @@ -0,0 +1,57 @@ +// +// Engine.cpp +// libraries/workload/src/workload +// +// Created by Andrew Meadows 2018.02.08 +// Copyright 2018 High Fidelity, Inc. +// +// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards +// Simple plane class. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "Engine.h" + +#include + +namespace workload { + + // the "real Job" + class HelloWorld { + QString _message; + bool _isEnabled { true }; + public: + using JobModel = Job::Model; + HelloWorld() {} + void configure(const HelloWorldConfig& configuration) { + _isEnabled = configuration.isEnabled(); + _message = configuration.getMessage(); + } + void run(const WorkloadContextPointer& context) { + if (_isEnabled) { + std::cout << _message.toStdString() << std::endl; + } + } + }; + + WorkloadContext::WorkloadContext() : task::JobContext(trace_workload()) {} + + using EngineModel = Task::Model; + + // the 'Builder' is the 'Data' on which the EngineModel templatizes. + // It must implement build() which is called by EngineModel::create(). + class HelloWorldBuilder { + public: + using JobModel = Task::Model; + void build(EngineModel& model, const Varying& in, Varying& out) { + model.addJob("helloWorld"); + } + }; + + Engine::Engine() : Task("Engine", EngineModel::create()), + _context(std::make_shared()) { + } +} // namespace workload + diff --git a/libraries/workload/src/workload/Engine.h b/libraries/workload/src/workload/Engine.h new file mode 100644 index 0000000000..a422c5d715 --- /dev/null +++ b/libraries/workload/src/workload/Engine.h @@ -0,0 +1,76 @@ +// +// Engine.h +// libraries/workload/src/workload +// +// Created by Andrew Meadows 2018.02.08 +// Copyright 2018 High Fidelity, Inc. +// +// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards +// Simple plane class. +// +// 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_workload_Engine_h +#define hifi_workload_Engine_h + +#include +#include + +#include + +namespace workload { + + // How to make an Engine under the task::Task paradigm... + + // (1) Derive class C from task::JobContext + class WorkloadContext : public task::JobContext { + public: + WorkloadContext(); + virtual ~WorkloadContext() {} + }; + using WorkloadContextPointer = std::shared_ptr; + + // (2) Apply a macro which will create local aliases (via "using") for example: + // using Task = task::Task; + Task_DeclareTypeAliases(WorkloadContext) + + // (3) You'll need a 'real Job' but it will need a Config for exposing settings to JS, + // and you should do that here: + class HelloWorldConfig : public Job::Config { + Q_OBJECT + Q_PROPERTY(QString message READ getMessage WRITE setMessage) + QString _message {"Hello World."}; + public: + HelloWorldConfig() : Job::Config(true) {} + QString getMessage() const { return _message; } + void setMessage(const QString& msg) { _message = msg; } + }; + + // (4) In cpp file the 'real Job' will need a 'builder'. The 'builder' is the 'Data' argument + // for the Model template. + // Data must implement Data::build(). + // Data::build() is called when the Model is added (in Engine ctor) as the first child job of the Engine + + // (5) Engine derives from task::Task and will run all the Job's + class Engine : public Task { + public: + Engine(); + ~Engine() = default; + + // (6) The Engine's Context is passed to its Jobs when they are run() + void run() { assert(_context); Task::run(_context); } + + protected: + // (6) Again, the Engine's Context is passed to its Jobs when they are run() + void run(const WorkloadContextPointer& context) override { assert(_context); Task::run(_context); } + + private: + WorkloadContextPointer _context; + }; + using EnginePointer = std::shared_ptr; + +} // namespace workload + +#endif // hifi_workload_Space_h From ba888a14ca87b8cc41cb4547b09ef3561dc4b042 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 12 Feb 2018 16:21:53 -0800 Subject: [PATCH 005/138] give Application a 'workload' engine --- interface/src/Application.cpp | 4 ++++ interface/src/Application.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5a340f471e..8bfb1dfbd4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2209,6 +2209,7 @@ Application::~Application() { // shutdown render engine _main3DScene = nullptr; _renderEngine = nullptr; + _infinityEngine = nullptr; DependencyManager::destroy(); @@ -4097,6 +4098,9 @@ void Application::idle() { qFatal("Unable to make main thread context current"); } + { + _infinityEngine->run(); + } { PerformanceTimer perfTimer("update"); PerformanceWarning warn(showWarnings, "Application::idle()... update()"); diff --git a/interface/src/Application.h b/interface/src/Application.h index d4041aa3be..0435425d5f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -69,6 +69,7 @@ #include "ui/OverlayConductor.h" #include "ui/overlays/Overlays.h" #include "UndoStackScriptingInterface.h" +#include "workload/Engine.h" #include #include @@ -612,6 +613,7 @@ private: render::ScenePointer _main3DScene{ new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) }; render::EnginePointer _renderEngine{ new render::Engine() }; gpu::ContextPointer _gpuContext; // initialized during window creation + workload::EnginePointer _infinityEngine{ new workload::Engine() }; mutable QMutex _renderArgsMutex{ QMutex::Recursive }; struct AppRenderArgs { From f35469c0de6abd38a21b7f10d304bdae01335b38 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 15 Feb 2018 12:57:58 -0800 Subject: [PATCH 006/138] give EntityTree a workload/Space instance --- assignment-client/CMakeLists.txt | 2 +- libraries/avatars-renderer/CMakeLists.txt | 1 + libraries/entities-renderer/CMakeLists.txt | 1 + libraries/entities/CMakeLists.txt | 2 +- libraries/entities/src/EntityItem.cpp | 10 +- libraries/entities/src/EntityItem.h | 3 + libraries/entities/src/EntityTree.cpp | 108 +++++++++++++++------ libraries/entities/src/EntityTree.h | 6 ++ libraries/physics/CMakeLists.txt | 1 + libraries/script-engine/CMakeLists.txt | 1 + libraries/ui/src/OffscreenUi.cpp | 10 +- libraries/workload/src/workload/Space.cpp | 60 +++++++----- libraries/workload/src/workload/Space.h | 7 +- tests/entities/CMakeLists.txt | 2 +- tests/render-perf/CMakeLists.txt | 2 +- 15 files changed, 153 insertions(+), 63 deletions(-) diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index c73e8e1d34..7750c0a105 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -13,7 +13,7 @@ setup_memory_debugger() link_hifi_libraries( audio avatars octree gpu graphics fbx entities networking animation recording shared script-engine embedded-webserver - controllers physics plugins midi image + controllers physics plugins midi image workload ) add_dependencies(${TARGET_NAME} oven) diff --git a/libraries/avatars-renderer/CMakeLists.txt b/libraries/avatars-renderer/CMakeLists.txt index 40e1607b2a..d3d61ea3fa 100644 --- a/libraries/avatars-renderer/CMakeLists.txt +++ b/libraries/avatars-renderer/CMakeLists.txt @@ -14,5 +14,6 @@ include_hifi_library_headers(audio) include_hifi_library_headers(entities) include_hifi_library_headers(octree) include_hifi_library_headers(task) +include_hifi_library_headers(workload) target_bullet() diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index 0f33a73e40..92f78e357e 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -14,6 +14,7 @@ include_hifi_library_headers(entities) include_hifi_library_headers(avatars) include_hifi_library_headers(controllers) include_hifi_library_headers(task) +include_hifi_library_headers(workload) target_bullet() target_polyvox() diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index d6d9058e44..3d43330ebc 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME entities) setup_hifi_library(Network Script) include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") -link_hifi_libraries(shared networking octree avatars graphics) +link_hifi_libraries(shared workload networking octree avatars graphics) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index ed13a46414..503f55e072 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2365,12 +2365,14 @@ QList EntityItem::getActionsOfType(EntityDynamicType typeT void EntityItem::locationChanged(bool tellPhysics) { requiresRecalcBoxes(); - if (tellPhysics) { - _flags |= Simulation::DIRTY_TRANSFORM; - EntityTreePointer tree = getTree(); - if (tree) { + EntityTreePointer tree = getTree(); + if (tree) { + if (tellPhysics) { + _flags |= Simulation::DIRTY_TRANSFORM; tree->entityChanged(getThisPointer()); } + glm::vec4 sphere(getWorldPosition(), 0.5f * glm::length(getScaledDimensions())); + tree->queueUpdateSpaceProxy(_spaceIndex, sphere); } SpatiallyNestable::locationChanged(tellPhysics); // tell all the children, also somethingChangedNotification(); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 5f84bcc311..97ba8b493f 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -477,6 +477,8 @@ public: void setCauterized(bool value) { _cauterized = value; } bool getCauterized() const { return _cauterized; } + void setSpaceIndex(int32_t index) { assert(_spaceIndex == -1); _spaceIndex = index; } + int32_t getSpaceIndex() const { return _spaceIndex; } signals: void requestRenderUpdate(); @@ -630,6 +632,7 @@ protected: quint64 _lastUpdatedAccelerationTimestamp { 0 }; quint64 _lastUpdatedQueryAACubeTimestamp { 0 }; + int32_t _spaceIndex { -1 }; // index to proxy in workload::Space bool _cauterized { false }; // if true, don't draw because it would obscure 1st-person camera }; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 60bcc85575..5854357661 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -560,37 +560,49 @@ void EntityTree::setSimulation(EntitySimulationPointer simulation) { } void EntityTree::deleteEntity(const EntityItemID& entityID, bool force, bool ignoreWarnings) { - EntityTreeElementPointer containingElement = getContainingElement(entityID); - if (!containingElement) { + EntityItemPointer entity; + { + QReadLocker locker(&_entityMapLock); + entity = _entityMap.value(entityID); + } + if (!entity) { if (!ignoreWarnings) { - qCWarning(entities) << "EntityTree::deleteEntity() on non-existent entityID=" << entityID; + qCWarning(entities) << "EntityTree::deleteEntity() on unknown entityID=" << entityID; } return; } - - EntityItemPointer existingEntity = containingElement->getEntityWithEntityItemID(entityID); - if (!existingEntity) { - if (!ignoreWarnings) { - qCWarning(entities) << "EntityTree::deleteEntity() on non-existant entity item with entityID=" << entityID; - } - return; - } - - if (existingEntity->getLocked() && !force) { + if (entity->getLocked() && !force) { if (!ignoreWarnings) { qCDebug(entities) << "ERROR! EntityTree::deleteEntity() trying to delete locked entity. entityID=" << entityID; } return; } + if (!ignoreWarnings) { + if (!entity->getElement()) { + qCWarning(entities) << "EntityTree::deleteEntity() found entity with entityID=" << entityID + << " in map but it doesn't know its containing element"; + } else { + // check for element mismatch + EntityItemPointer otherEntity = entity->getElement()->getEntityWithEntityItemID(entityID); + if (!otherEntity) { + qCWarning(entities) << "EntityTree::deleteEntity() on entity with entityID=" << entityID + << " but the containing element of record cannot find it"; + } else if (otherEntity != entity) { + qCWarning(entities) << "EntityTree::deleteEntity() on entity with entityID=" << entityID + << " but the containing element of record found a different entity"; + } + } + } + unhookChildAvatar(entityID); emit deletingEntity(entityID); - emit deletingEntityPointer(existingEntity.get()); + emit deletingEntityPointer(entity.get()); // NOTE: callers must lock the tree before using this method DeleteEntityOperator theOperator(getThisPointer(), entityID); - existingEntity->forEachDescendant([&](SpatiallyNestablePointer descendant) { + entity->forEachDescendant([&](SpatiallyNestablePointer descendant) { auto descendantID = descendant->getID(); theOperator.addEntityIDToDeleteList(descendantID); emit deletingEntity(descendantID); @@ -620,34 +632,46 @@ void EntityTree::deleteEntities(QSet entityIDs, bool force, bool i // NOTE: callers must lock the tree before using this method DeleteEntityOperator theOperator(getThisPointer()); foreach(const EntityItemID& entityID, entityIDs) { - EntityTreeElementPointer containingElement = getContainingElement(entityID); - if (!containingElement) { + EntityItemPointer entity; + { + QReadLocker locker(&_entityMapLock); + entity = _entityMap.value(entityID); + } + if (!entity) { if (!ignoreWarnings) { - qCWarning(entities) << "EntityTree::deleteEntities() on non-existent entityID=" << entityID; + qCWarning(entities) << "EntityTree::deleteEntities() on unknown entityID=" << entityID; } continue; } - - EntityItemPointer existingEntity = containingElement->getEntityWithEntityItemID(entityID); - if (!existingEntity) { - if (!ignoreWarnings) { - qCWarning(entities) << "EntityTree::deleteEntities() on non-existent entity item with entityID=" << entityID; - } - continue; - } - - if (existingEntity->getLocked() && !force) { + if (entity->getLocked() && !force) { if (!ignoreWarnings) { qCDebug(entities) << "ERROR! EntityTree::deleteEntities() trying to delete locked entity. entityID=" << entityID; } continue; } + if (!ignoreWarnings) { + if (!entity->getElement()) { + qCWarning(entities) << "EntityTree::deleteEntities() found entity with entityID=" << entityID + << " in map but it doesn't know its containing element"; + } else { + // check for element mismatch + EntityItemPointer otherEntity = entity->getElement()->getEntityWithEntityItemID(entityID); + if (!otherEntity) { + qCWarning(entities) << "EntityTree::deleteEntities() on entity with entityID=" << entityID + << " but the containing element of record cannot find it"; + } else if (otherEntity != entity) { + qCWarning(entities) << "EntityTree::deleteEntities() on entity with entityID=" << entityID + << " but the containing element of record found a different entity"; + } + } + } + // tell our delete operator about this entityID unhookChildAvatar(entityID); theOperator.addEntityIDToDeleteList(entityID); emit deletingEntity(entityID); - emit deletingEntityPointer(existingEntity.get()); + emit deletingEntityPointer(entity.get()); } if (theOperator.getEntities().size() > 0) { @@ -1209,6 +1233,10 @@ bool EntityTree::verifyNonce(const QString& certID, const QString& nonce, Entity return verificationSuccess; } +void EntityTree::queueUpdateSpaceProxy(int32_t index, const glm::vec4& sphere) { + _spaceUpdates.push_back(std::pair(index, sphere)); +} + void EntityTree::processChallengeOwnershipRequestPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { int certIDByteArraySize; int textByteArraySize; @@ -1810,6 +1838,12 @@ void EntityTree::update(bool simulate) { } }); } + + // process Space queues + _space.deleteProxies(_spaceDeletes); + _spaceDeletes.clear(); + _space.updateProxies(_spaceUpdates); + _spaceUpdates.clear(); } quint64 EntityTree::getAdjustedConsiderSince(quint64 sinceTime) { @@ -1979,11 +2013,25 @@ void EntityTree::addEntityMapEntry(EntityItemPointer entity) { return; } _entityMap.insert(id, entity); + + // create a proxy for the entity in the workload/Space container + glm::vec4 sphere(entity->getWorldPosition(), 0.5f * glm::length(entity->getScaledDimensions())); + int32_t spaceIndex = _space.createProxy(sphere); + entity->setSpaceIndex(spaceIndex); } void EntityTree::clearEntityMapEntry(const EntityItemID& id) { + // this method only called by DeleteEntityOperator QWriteLocker locker(&_entityMapLock); - _entityMap.remove(id); + QHash::iterator itr = _entityMap.find(id); + if (itr != _entityMap.end()) { + // queue delete from _space BEFORE removing from map + int32_t spaceIndex = itr.value()->getSpaceIndex(); + assert(spaceIndex != -1); + _spaceDeletes.push_back(spaceIndex); + + _entityMap.erase(itr); + } } void EntityTree::debugDumpMap() { diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 90fe342f57..c2d0b229b6 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -17,6 +17,7 @@ #include #include +#include class EntityTree; using EntityTreePointer = std::shared_ptr; @@ -280,6 +281,8 @@ public: void setMyAvatar(std::shared_ptr myAvatar) { _myAvatar = myAvatar; } + void queueUpdateSpaceProxy(int32_t index, const glm::vec4& sphere); + signals: void deletingEntity(const EntityItemID& entityID); void deletingEntityPointer(EntityItem* entityID); @@ -387,6 +390,9 @@ private: void validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation); std::shared_ptr _myAvatar{ nullptr }; + workload::Space _space; + std::vector< std::pair > _spaceUpdates; + std::vector< int32_t > _spaceDeletes; }; #endif // hifi_EntityTree_h diff --git a/libraries/physics/CMakeLists.txt b/libraries/physics/CMakeLists.txt index ad082c1a6e..c9df2dfc77 100644 --- a/libraries/physics/CMakeLists.txt +++ b/libraries/physics/CMakeLists.txt @@ -7,5 +7,6 @@ include_hifi_library_headers(avatars) include_hifi_library_headers(audio) include_hifi_library_headers(octree) include_hifi_library_headers(animation) +include_hifi_library_headers(workload) target_bullet() diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 31436bbf8b..6ef8438bf5 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -20,3 +20,4 @@ endif () link_hifi_libraries(shared networking octree gpu procedural graphics model-networking ktx recording avatars fbx entities controllers animation audio physics image midi) # ui includes gl, but link_hifi_libraries does not use transitive includes, so gl must be explicit include_hifi_library_headers(gl) +include_hifi_library_headers(workload) diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 0e3c15b965..77264a017c 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -27,6 +27,7 @@ #include "VrMenu.h" #include "ui/Logging.h" +#include // adebug #include @@ -619,7 +620,13 @@ class KeyboardFocusHack : public QObject { public: KeyboardFocusHack() { Q_ASSERT(_mainWindow); + std::cout << "adebug _mainWindow = " << (void*)(_mainWindow) << std::endl; // adebug QTimer::singleShot(200, [=] { + _mainWindow = findMainWindow(); + std::cout << "adebug again _mainWindow = " << (void*)(_mainWindow) << std::endl; // adebug + std::cout << "adebug _mainWindow->x() = " << _mainWindow->x() << std::endl; + std::cout << " adebug _mainWindow->y() = " << _mainWindow->y() << std::endl; + std::cout << std::endl; // adebug _hackWindow = new QWindow(); _hackWindow->setFlags(Qt::FramelessWindowHint); _hackWindow->setGeometry(_mainWindow->x(), _mainWindow->y(), 10, 10); @@ -647,10 +654,11 @@ private: break; } } + std::cout << "adebug findMainWindow() result = " << (void*)(result) << std::endl; // adebug return result; } - QWindow* const _mainWindow { findMainWindow() }; + QWindow* _mainWindow { findMainWindow() }; QWindow* _hackWindow { nullptr }; }; diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index 1e2bfb228a..2c38ec9f8b 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -34,38 +34,26 @@ int32_t Space::createProxy(const Space::Sphere& newSphere) { } } -void Space::deleteProxy(int32_t proxyId) { - if (proxyId >= (int32_t)_proxies.size() || _proxies.empty()) { - return; - } - if (proxyId == (int32_t)_proxies.size() - 1) { - // remove proxy on back - _proxies.pop_back(); - if (!_freeIndices.empty()) { - // remove any freeIndices on back - std::sort(_freeIndices.begin(), _freeIndices.end()); - while(!_freeIndices.empty() && _freeIndices.back() == (int32_t)_proxies.size() - 1) { - _freeIndices.pop_back(); - _proxies.pop_back(); - } - } - } else { - _proxies[proxyId].region = Space::REGION_INVALID; - _freeIndices.push_back(proxyId); +void Space::deleteProxies(const std::vector& deadIndices) { + for (uint32_t i = 0; i < deadIndices.size(); ++i) { + deleteProxy(deadIndices[i]); } } -void Space::updateProxy(int32_t proxyId, const Space::Sphere& newSphere) { - if (proxyId >= (int32_t)_proxies.size()) { - return; +void Space::updateProxies(const std::vector >& changedProxies) { + for (uint32_t i = 0; i < changedProxies.size(); ++i) { + int32_t proxyId = changedProxies[i].first; + if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) { + updateProxy(changedProxies[i].first, changedProxies[i].second); + } } - _proxies[proxyId].sphere = newSphere; } void Space::setViews(const std::vector& views) { _views = views; } +// TODO?: move this to an algorithm/job? void Space::categorizeAndGetChanges(std::vector& changes) { uint32_t numProxies = (uint32_t)_proxies.size(); uint32_t numViews = (uint32_t)_views.size(); @@ -92,3 +80,31 @@ void Space::categorizeAndGetChanges(std::vector& changes) { } } +// private +void Space::deleteProxy(int32_t proxyId) { + if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) { + if (proxyId == (int32_t)_proxies.size() - 1) { + // remove proxy on back + _proxies.pop_back(); + if (!_freeIndices.empty()) { + // remove any freeIndices on back + std::sort(_freeIndices.begin(), _freeIndices.end()); + while(!_freeIndices.empty() && _freeIndices.back() == (int32_t)_proxies.size() - 1) { + _freeIndices.pop_back(); + _proxies.pop_back(); + } + } + } else { + _proxies[proxyId].region = Space::REGION_INVALID; + _freeIndices.push_back(proxyId); + } + } +} + +// private +void Space::updateProxy(int32_t proxyId, const Space::Sphere& newSphere) { + if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) { + _proxies[proxyId].sphere = newSphere; + } +} + diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index be47cddc4e..3a8dd3c488 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -60,8 +60,8 @@ public: Space() {} int32_t createProxy(const Sphere& sphere); - void deleteProxy(int32_t proxyId); - void updateProxy(int32_t proxyId, const Sphere& sphere); + void deleteProxies(const std::vector& deadIndices); + void updateProxies(const std::vector >& changedProxies); void setViews(const std::vector& views); uint32_t getNumObjects() const { return (uint32_t)(_proxies.size() - _freeIndices.size()); } @@ -69,6 +69,9 @@ public: void categorizeAndGetChanges(std::vector& changes); private: + void deleteProxy(int32_t proxyId); + void updateProxy(int32_t proxyId, const Sphere& sphere); + std::vector _proxies; std::vector _views; std::vector _freeIndices; diff --git a/tests/entities/CMakeLists.txt b/tests/entities/CMakeLists.txt index 6d0bf9f149..b1bfcfd8a5 100644 --- a/tests/entities/CMakeLists.txt +++ b/tests/entities/CMakeLists.txt @@ -7,7 +7,7 @@ setup_memory_debugger() set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") # link in the shared libraries -link_hifi_libraries(entities avatars shared octree gpu graphics fbx networking animation audio gl) +link_hifi_libraries(entities avatars shared workload octree gpu graphics fbx networking animation audio gl) if (WIN32) add_dependency_external_projects(wasapi) diff --git a/tests/render-perf/CMakeLists.txt b/tests/render-perf/CMakeLists.txt index 7e61d9550c..ed13aadfa3 100644 --- a/tests/render-perf/CMakeLists.txt +++ b/tests/render-perf/CMakeLists.txt @@ -18,7 +18,7 @@ link_hifi_libraries( render render-utils graphics fbx model-networking entities entities-renderer audio avatars script-engine - physics procedural midi qml ui + physics procedural midi qml ui workload ${PLATFORM_GL_BACKEND} ) From 91f01346329c274607bb8aa57931f4e308836875 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 15 Feb 2018 13:10:26 -0800 Subject: [PATCH 007/138] remove linux crash-on-login workaround hackery --- libraries/ui/src/OffscreenUi.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 77264a017c..0e3c15b965 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -27,7 +27,6 @@ #include "VrMenu.h" #include "ui/Logging.h" -#include // adebug #include @@ -620,13 +619,7 @@ class KeyboardFocusHack : public QObject { public: KeyboardFocusHack() { Q_ASSERT(_mainWindow); - std::cout << "adebug _mainWindow = " << (void*)(_mainWindow) << std::endl; // adebug QTimer::singleShot(200, [=] { - _mainWindow = findMainWindow(); - std::cout << "adebug again _mainWindow = " << (void*)(_mainWindow) << std::endl; // adebug - std::cout << "adebug _mainWindow->x() = " << _mainWindow->x() << std::endl; - std::cout << " adebug _mainWindow->y() = " << _mainWindow->y() << std::endl; - std::cout << std::endl; // adebug _hackWindow = new QWindow(); _hackWindow->setFlags(Qt::FramelessWindowHint); _hackWindow->setGeometry(_mainWindow->x(), _mainWindow->y(), 10, 10); @@ -654,11 +647,10 @@ private: break; } } - std::cout << "adebug findMainWindow() result = " << (void*)(result) << std::endl; // adebug return result; } - QWindow* _mainWindow { findMainWindow() }; + QWindow* const _mainWindow { findMainWindow() }; QWindow* _hackWindow { nullptr }; }; From 6d347cf44f3018afbf1172eee5d30f454f706388 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 15 Feb 2018 17:40:15 -0800 Subject: [PATCH 008/138] revert deadlock, remove Space stubbery in EntityTree --- assignment-client/CMakeLists.txt | 2 +- interface/src/Application.cpp | 10 ++ interface/src/Application.h | 3 + libraries/avatars-renderer/CMakeLists.txt | 1 - libraries/entities-renderer/CMakeLists.txt | 1 - libraries/entities/CMakeLists.txt | 2 +- libraries/entities/src/EntityItem.cpp | 11 +-- libraries/entities/src/EntityTree.cpp | 108 ++++++--------------- libraries/entities/src/EntityTree.h | 4 - libraries/physics/CMakeLists.txt | 1 - libraries/script-engine/CMakeLists.txt | 1 - tests/entities/CMakeLists.txt | 2 +- tests/render-perf/CMakeLists.txt | 2 +- 13 files changed, 52 insertions(+), 96 deletions(-) diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 7750c0a105..c73e8e1d34 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -13,7 +13,7 @@ setup_memory_debugger() link_hifi_libraries( audio avatars octree gpu graphics fbx entities networking animation recording shared script-engine embedded-webserver - controllers physics plugins midi image workload + controllers physics plugins midi image ) add_dependencies(${TARGET_NAME} oven) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8bfb1dfbd4..8a3bdfca0e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4477,6 +4477,8 @@ void Application::init() { _physicsEngine->init(); EntityTreePointer tree = getEntities()->getTree(); + connect(tree.get(), &EntityTree::deletingEntity, this, &Application::deletingEntity, Qt::QueuedConnection); + connect(tree.get(), &EntityTree::addingEntity, this, &Application::addingEntity, Qt::QueuedConnection); _entitySimulation->init(tree, _physicsEngine, &_entityEditSender); tree->setSimulation(_entitySimulation); @@ -7606,4 +7608,12 @@ void Application::saveNextPhysicsStats(QString filename) { _physicsEngine->saveNextPhysicsStats(filename); } +void Application::addingEntity(const EntityItemID& entityID) { + // TODO: Andrew to implement this +} + +void Application::deletingEntity(const EntityItemID& entityID) { + // TODO: Andrew to implement this +} + #include "Application.moc" diff --git a/interface/src/Application.h b/interface/src/Application.h index 0435425d5f..3c2dee03e7 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -391,6 +391,9 @@ public slots: const QString getPreferredCursor() const { return _preferredCursor.get(); } void setPreferredCursor(const QString& cursor); + void addingEntity(const EntityItemID& entityID); + void deletingEntity(const EntityItemID& entityID); + private slots: void onDesktopRootItemCreated(QQuickItem* qmlContext); void onDesktopRootContextCreated(QQmlContext* qmlContext); diff --git a/libraries/avatars-renderer/CMakeLists.txt b/libraries/avatars-renderer/CMakeLists.txt index d3d61ea3fa..40e1607b2a 100644 --- a/libraries/avatars-renderer/CMakeLists.txt +++ b/libraries/avatars-renderer/CMakeLists.txt @@ -14,6 +14,5 @@ include_hifi_library_headers(audio) include_hifi_library_headers(entities) include_hifi_library_headers(octree) include_hifi_library_headers(task) -include_hifi_library_headers(workload) target_bullet() diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index 92f78e357e..0f33a73e40 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -14,7 +14,6 @@ include_hifi_library_headers(entities) include_hifi_library_headers(avatars) include_hifi_library_headers(controllers) include_hifi_library_headers(task) -include_hifi_library_headers(workload) target_bullet() target_polyvox() diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index 3d43330ebc..d6d9058e44 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME entities) setup_hifi_library(Network Script) include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") -link_hifi_libraries(shared workload networking octree avatars graphics) +link_hifi_libraries(shared networking octree avatars graphics) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 503f55e072..8ae00dee99 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2365,15 +2365,14 @@ QList EntityItem::getActionsOfType(EntityDynamicType typeT void EntityItem::locationChanged(bool tellPhysics) { requiresRecalcBoxes(); - EntityTreePointer tree = getTree(); - if (tree) { - if (tellPhysics) { - _flags |= Simulation::DIRTY_TRANSFORM; + if (tellPhysics) { + _flags |= Simulation::DIRTY_TRANSFORM; + EntityTreePointer tree = getTree(); + if (tree) { tree->entityChanged(getThisPointer()); } - glm::vec4 sphere(getWorldPosition(), 0.5f * glm::length(getScaledDimensions())); - tree->queueUpdateSpaceProxy(_spaceIndex, sphere); } + // TODO: Andrew to connect this to the Space instance in Application SpatiallyNestable::locationChanged(tellPhysics); // tell all the children, also somethingChangedNotification(); } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 5854357661..60bcc85575 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -560,49 +560,37 @@ void EntityTree::setSimulation(EntitySimulationPointer simulation) { } void EntityTree::deleteEntity(const EntityItemID& entityID, bool force, bool ignoreWarnings) { - EntityItemPointer entity; - { - QReadLocker locker(&_entityMapLock); - entity = _entityMap.value(entityID); - } - if (!entity) { + EntityTreeElementPointer containingElement = getContainingElement(entityID); + if (!containingElement) { if (!ignoreWarnings) { - qCWarning(entities) << "EntityTree::deleteEntity() on unknown entityID=" << entityID; + qCWarning(entities) << "EntityTree::deleteEntity() on non-existent entityID=" << entityID; } return; } - if (entity->getLocked() && !force) { + + EntityItemPointer existingEntity = containingElement->getEntityWithEntityItemID(entityID); + if (!existingEntity) { + if (!ignoreWarnings) { + qCWarning(entities) << "EntityTree::deleteEntity() on non-existant entity item with entityID=" << entityID; + } + return; + } + + if (existingEntity->getLocked() && !force) { if (!ignoreWarnings) { qCDebug(entities) << "ERROR! EntityTree::deleteEntity() trying to delete locked entity. entityID=" << entityID; } return; } - if (!ignoreWarnings) { - if (!entity->getElement()) { - qCWarning(entities) << "EntityTree::deleteEntity() found entity with entityID=" << entityID - << " in map but it doesn't know its containing element"; - } else { - // check for element mismatch - EntityItemPointer otherEntity = entity->getElement()->getEntityWithEntityItemID(entityID); - if (!otherEntity) { - qCWarning(entities) << "EntityTree::deleteEntity() on entity with entityID=" << entityID - << " but the containing element of record cannot find it"; - } else if (otherEntity != entity) { - qCWarning(entities) << "EntityTree::deleteEntity() on entity with entityID=" << entityID - << " but the containing element of record found a different entity"; - } - } - } - unhookChildAvatar(entityID); emit deletingEntity(entityID); - emit deletingEntityPointer(entity.get()); + emit deletingEntityPointer(existingEntity.get()); // NOTE: callers must lock the tree before using this method DeleteEntityOperator theOperator(getThisPointer(), entityID); - entity->forEachDescendant([&](SpatiallyNestablePointer descendant) { + existingEntity->forEachDescendant([&](SpatiallyNestablePointer descendant) { auto descendantID = descendant->getID(); theOperator.addEntityIDToDeleteList(descendantID); emit deletingEntity(descendantID); @@ -632,46 +620,34 @@ void EntityTree::deleteEntities(QSet entityIDs, bool force, bool i // NOTE: callers must lock the tree before using this method DeleteEntityOperator theOperator(getThisPointer()); foreach(const EntityItemID& entityID, entityIDs) { - EntityItemPointer entity; - { - QReadLocker locker(&_entityMapLock); - entity = _entityMap.value(entityID); - } - if (!entity) { + EntityTreeElementPointer containingElement = getContainingElement(entityID); + if (!containingElement) { if (!ignoreWarnings) { - qCWarning(entities) << "EntityTree::deleteEntities() on unknown entityID=" << entityID; + qCWarning(entities) << "EntityTree::deleteEntities() on non-existent entityID=" << entityID; } continue; } - if (entity->getLocked() && !force) { + + EntityItemPointer existingEntity = containingElement->getEntityWithEntityItemID(entityID); + if (!existingEntity) { + if (!ignoreWarnings) { + qCWarning(entities) << "EntityTree::deleteEntities() on non-existent entity item with entityID=" << entityID; + } + continue; + } + + if (existingEntity->getLocked() && !force) { if (!ignoreWarnings) { qCDebug(entities) << "ERROR! EntityTree::deleteEntities() trying to delete locked entity. entityID=" << entityID; } continue; } - if (!ignoreWarnings) { - if (!entity->getElement()) { - qCWarning(entities) << "EntityTree::deleteEntities() found entity with entityID=" << entityID - << " in map but it doesn't know its containing element"; - } else { - // check for element mismatch - EntityItemPointer otherEntity = entity->getElement()->getEntityWithEntityItemID(entityID); - if (!otherEntity) { - qCWarning(entities) << "EntityTree::deleteEntities() on entity with entityID=" << entityID - << " but the containing element of record cannot find it"; - } else if (otherEntity != entity) { - qCWarning(entities) << "EntityTree::deleteEntities() on entity with entityID=" << entityID - << " but the containing element of record found a different entity"; - } - } - } - // tell our delete operator about this entityID unhookChildAvatar(entityID); theOperator.addEntityIDToDeleteList(entityID); emit deletingEntity(entityID); - emit deletingEntityPointer(entity.get()); + emit deletingEntityPointer(existingEntity.get()); } if (theOperator.getEntities().size() > 0) { @@ -1233,10 +1209,6 @@ bool EntityTree::verifyNonce(const QString& certID, const QString& nonce, Entity return verificationSuccess; } -void EntityTree::queueUpdateSpaceProxy(int32_t index, const glm::vec4& sphere) { - _spaceUpdates.push_back(std::pair(index, sphere)); -} - void EntityTree::processChallengeOwnershipRequestPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { int certIDByteArraySize; int textByteArraySize; @@ -1838,12 +1810,6 @@ void EntityTree::update(bool simulate) { } }); } - - // process Space queues - _space.deleteProxies(_spaceDeletes); - _spaceDeletes.clear(); - _space.updateProxies(_spaceUpdates); - _spaceUpdates.clear(); } quint64 EntityTree::getAdjustedConsiderSince(quint64 sinceTime) { @@ -2013,25 +1979,11 @@ void EntityTree::addEntityMapEntry(EntityItemPointer entity) { return; } _entityMap.insert(id, entity); - - // create a proxy for the entity in the workload/Space container - glm::vec4 sphere(entity->getWorldPosition(), 0.5f * glm::length(entity->getScaledDimensions())); - int32_t spaceIndex = _space.createProxy(sphere); - entity->setSpaceIndex(spaceIndex); } void EntityTree::clearEntityMapEntry(const EntityItemID& id) { - // this method only called by DeleteEntityOperator QWriteLocker locker(&_entityMapLock); - QHash::iterator itr = _entityMap.find(id); - if (itr != _entityMap.end()) { - // queue delete from _space BEFORE removing from map - int32_t spaceIndex = itr.value()->getSpaceIndex(); - assert(spaceIndex != -1); - _spaceDeletes.push_back(spaceIndex); - - _entityMap.erase(itr); - } + _entityMap.remove(id); } void EntityTree::debugDumpMap() { diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index c2d0b229b6..3b75929e2a 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -17,7 +17,6 @@ #include #include -#include class EntityTree; using EntityTreePointer = std::shared_ptr; @@ -390,9 +389,6 @@ private: void validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation); std::shared_ptr _myAvatar{ nullptr }; - workload::Space _space; - std::vector< std::pair > _spaceUpdates; - std::vector< int32_t > _spaceDeletes; }; #endif // hifi_EntityTree_h diff --git a/libraries/physics/CMakeLists.txt b/libraries/physics/CMakeLists.txt index c9df2dfc77..ad082c1a6e 100644 --- a/libraries/physics/CMakeLists.txt +++ b/libraries/physics/CMakeLists.txt @@ -7,6 +7,5 @@ include_hifi_library_headers(avatars) include_hifi_library_headers(audio) include_hifi_library_headers(octree) include_hifi_library_headers(animation) -include_hifi_library_headers(workload) target_bullet() diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 6ef8438bf5..31436bbf8b 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -20,4 +20,3 @@ endif () link_hifi_libraries(shared networking octree gpu procedural graphics model-networking ktx recording avatars fbx entities controllers animation audio physics image midi) # ui includes gl, but link_hifi_libraries does not use transitive includes, so gl must be explicit include_hifi_library_headers(gl) -include_hifi_library_headers(workload) diff --git a/tests/entities/CMakeLists.txt b/tests/entities/CMakeLists.txt index b1bfcfd8a5..6d0bf9f149 100644 --- a/tests/entities/CMakeLists.txt +++ b/tests/entities/CMakeLists.txt @@ -7,7 +7,7 @@ setup_memory_debugger() set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") # link in the shared libraries -link_hifi_libraries(entities avatars shared workload octree gpu graphics fbx networking animation audio gl) +link_hifi_libraries(entities avatars shared octree gpu graphics fbx networking animation audio gl) if (WIN32) add_dependency_external_projects(wasapi) diff --git a/tests/render-perf/CMakeLists.txt b/tests/render-perf/CMakeLists.txt index ed13aadfa3..7e61d9550c 100644 --- a/tests/render-perf/CMakeLists.txt +++ b/tests/render-perf/CMakeLists.txt @@ -18,7 +18,7 @@ link_hifi_libraries( render render-utils graphics fbx model-networking entities entities-renderer audio avatars script-engine - physics procedural midi qml ui workload + physics procedural midi qml ui ${PLATFORM_GL_BACKEND} ) From 9441bb477ddcdd116f96da4732ef82180558ccf1 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 16 Feb 2018 17:21:07 -0800 Subject: [PATCH 009/138] Working on adding rendering from the workload --- interface/src/Application.cpp | 7 +++-- interface/src/Application.h | 6 ++-- interface/src/workload/GameWorkload.cpp | 32 +++++++++++++++++++ interface/src/workload/GameWorkload.h | 41 +++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 interface/src/workload/GameWorkload.cpp create mode 100644 interface/src/workload/GameWorkload.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8a3bdfca0e..c5dab90556 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2209,7 +2209,8 @@ Application::~Application() { // shutdown render engine _main3DScene = nullptr; _renderEngine = nullptr; - _infinityEngine = nullptr; + + _gameWorkload.shutdown(); DependencyManager::destroy(); @@ -2332,6 +2333,8 @@ void Application::initializeGL() { DependencyManager::get()->initializeShapePipelines(); }); + _gameWorkload.startup(); + _offscreenContext = new OffscreenGLCanvas(); _offscreenContext->setObjectName("MainThreadContext"); _offscreenContext->create(_glWidget->qglContext()); @@ -4099,7 +4102,7 @@ void Application::idle() { } { - _infinityEngine->run(); + _gameWorkload._engine->run(); } { PerformanceTimer perfTimer("update"); diff --git a/interface/src/Application.h b/interface/src/Application.h index 3c2dee03e7..e04421cb6c 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -69,7 +69,8 @@ #include "ui/OverlayConductor.h" #include "ui/overlays/Overlays.h" #include "UndoStackScriptingInterface.h" -#include "workload/Engine.h" + +#include "workload/GameWorkload.h" #include #include @@ -616,7 +617,8 @@ private: render::ScenePointer _main3DScene{ new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) }; render::EnginePointer _renderEngine{ new render::Engine() }; gpu::ContextPointer _gpuContext; // initialized during window creation - workload::EnginePointer _infinityEngine{ new workload::Engine() }; + + GameWorkload _gameWorkload; mutable QMutex _renderArgsMutex{ QMutex::Recursive }; struct AppRenderArgs { diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp new file mode 100644 index 0000000000..4563f1e060 --- /dev/null +++ b/interface/src/workload/GameWorkload.cpp @@ -0,0 +1,32 @@ +// +// GameWorkload.cpp +// +// Created by Sam Gateau on 2/16/2018. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "GameWorkload.h" + + +GameWorkload::GameWorkload() { +} + +GameWorkload::~GameWorkload() { + shutdown(); +} + +void GameWorkload::startup() { + _engine.reset(new workload::Engine()); + + _engine.addJob(); +} + +void GameWorkload::shutdown() { + _engine.reset(); +} + + +void GameSpaceToRender::run(const workload::WorkloadContextPointer& renderContext, Outputs& outputs) { +} \ No newline at end of file diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h new file mode 100644 index 0000000000..848e01b441 --- /dev/null +++ b/interface/src/workload/GameWorkload.h @@ -0,0 +1,41 @@ +// +// GameWorkload.h +// +// Created by Sam Gateau on 2/16/2018. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_GameWorkload_h +#define hifi_GameWorkload_h + +#include "workload/Space.h" +#include "workload/Engine.h" + +#include "render/Scene.h" + +class GameSpaceToRender { +public: + using Outputs = render::Transaction; + using JobModel = workload::Job::ModelO; + + GameSpaceToRender() {} + void run(const workload::WorkloadContextPointer& renderContext, Outputs& outputs); + +protected: +}; + +class GameWorkload { +public: + GameWorkload(); + ~GameWorkload(); + + void startup(); + void shutdown(); + + workload::EnginePointer _engine{}; + +}; + +#endif \ No newline at end of file From d1b1ae0ea348e5fbf1272ca96a65f3846a2a095b Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 16 Feb 2018 17:22:27 -0800 Subject: [PATCH 010/138] Working on adding rendering from the workload --- interface/src/workload/GameWorkload.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 4563f1e060..7cc9cf5c25 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -20,7 +20,7 @@ GameWorkload::~GameWorkload() { void GameWorkload::startup() { _engine.reset(new workload::Engine()); - _engine.addJob(); + _engine->addJob("SpaceToRender"); } void GameWorkload::shutdown() { From cd14fb65f043b3774606a945032c5fd5ba4db5d7 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 19 Feb 2018 23:44:23 -0800 Subject: [PATCH 011/138] First stp to add a rendering job to debug and display the workload space --- interface/src/Application.cpp | 2 +- interface/src/workload/GameWorkload.cpp | 86 +++++++++++++++++++++- interface/src/workload/GameWorkload.h | 14 +++- libraries/workload/src/workload/Engine.cpp | 6 +- libraries/workload/src/workload/Engine.h | 9 ++- libraries/workload/src/workload/Space.h | 4 + 6 files changed, 110 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c5dab90556..7d9233e17d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2333,7 +2333,7 @@ void Application::initializeGL() { DependencyManager::get()->initializeShapePipelines(); }); - _gameWorkload.startup(); + _gameWorkload.startup(_main3DScene); _offscreenContext = new OffscreenGLCanvas(); _offscreenContext->setObjectName("MainThreadContext"); diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 7cc9cf5c25..f9a0bfa360 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -9,6 +9,12 @@ // #include "GameWorkload.h" +GameWorkloadContext::GameWorkloadContext(const render::ScenePointer& scene) : WorkloadContext(), _scene(scene) { +} + +GameWorkloadContext::~GameWorkloadContext() { +} + GameWorkload::GameWorkload() { } @@ -17,8 +23,8 @@ GameWorkload::~GameWorkload() { shutdown(); } -void GameWorkload::startup() { - _engine.reset(new workload::Engine()); +void GameWorkload::startup(const render::ScenePointer& scene) { + _engine.reset(new workload::Engine(std::make_shared(scene))); _engine->addJob("SpaceToRender"); } @@ -28,5 +34,79 @@ void GameWorkload::shutdown() { } -void GameSpaceToRender::run(const workload::WorkloadContextPointer& renderContext, Outputs& outputs) { + + + +class GameWorkloadRenderItem { +public: + using Payload = render::Payload; + using Pointer = Payload::DataPointer; + + GameWorkloadRenderItem() {} + ~GameWorkloadRenderItem() {} + void render(RenderArgs* args) {} + + render::Item::Bound& editBound() { _needUpdate = true; return _bound; } + const render::Item::Bound& getBound() { return _bound; } + + void setVisible(bool visible) { _isVisible = visible; } + bool isVisible() const { return _isVisible; } + +protected: + render::Item::Bound _bound; + + bool _needUpdate{ true }; + bool _isVisible{ true }; +}; + +namespace render { + template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload); + template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload); + template <> void payloadRender(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args); +} + +namespace render { + template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload) { + auto builder = ItemKey::Builder().withTypeShape(); + return builder.build(); + } + template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload) { + if (payload) { + return payload->getBound(); + } + return Item::Bound(); + } + template <> void payloadRender(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args) { + if (payload) { + payload->render(args); + } + } +} + + +void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, Outputs& outputs) { + auto gameWorkloadContext = std::dynamic_pointer_cast(runContext); + if (!gameWorkloadContext) { + return; + } + + auto scene = gameWorkloadContext->_scene; + + // Valid space, let's display its content + render::Transaction transaction; + if (!render::Item::isValidID(_spaceRenderItemID)) { + _spaceRenderItemID = scene->allocateID(); + auto renderItem = std::make_shared(); + renderItem->editBound().expandedContains(glm::vec3(0.0), 32000.0); + transaction.resetItem(_spaceRenderItemID, std::make_shared(std::make_shared())); + } + + scene->enqueueTransaction(transaction); + + auto space = gameWorkloadContext->_space; + if (!space) { + return; + } + + } \ No newline at end of file diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index 848e01b441..1647056d60 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -24,6 +24,15 @@ public: void run(const workload::WorkloadContextPointer& renderContext, Outputs& outputs); protected: + render::ItemID _spaceRenderItemID{ render::Item::INVALID_ITEM_ID }; +}; + +class GameWorkloadContext : public workload::WorkloadContext { +public: + GameWorkloadContext(const render::ScenePointer& scene); + virtual ~GameWorkloadContext(); + + render::ScenePointer _scene; }; class GameWorkload { @@ -31,11 +40,10 @@ public: GameWorkload(); ~GameWorkload(); - void startup(); + void startup(const render::ScenePointer& scene); void shutdown(); - workload::EnginePointer _engine{}; - + workload::EnginePointer _engine; }; #endif \ No newline at end of file diff --git a/libraries/workload/src/workload/Engine.cpp b/libraries/workload/src/workload/Engine.cpp index 7e69731d4e..e209fbf5d5 100644 --- a/libraries/workload/src/workload/Engine.cpp +++ b/libraries/workload/src/workload/Engine.cpp @@ -33,7 +33,7 @@ namespace workload { if (_isEnabled) { std::cout << _message.toStdString() << std::endl; } - } + } }; WorkloadContext::WorkloadContext() : task::JobContext(trace_workload()) {} @@ -50,8 +50,8 @@ namespace workload { } }; - Engine::Engine() : Task("Engine", EngineModel::create()), - _context(std::make_shared()) { + Engine::Engine(const WorkloadContextPointer& context) : Task("Engine", EngineModel::create()), + _context(context) { } } // namespace workload diff --git a/libraries/workload/src/workload/Engine.h b/libraries/workload/src/workload/Engine.h index a422c5d715..1e69f555c7 100644 --- a/libraries/workload/src/workload/Engine.h +++ b/libraries/workload/src/workload/Engine.h @@ -20,6 +20,8 @@ #include +#include "Space.h" + namespace workload { // How to make an Engine under the task::Task paradigm... @@ -29,6 +31,8 @@ namespace workload { public: WorkloadContext(); virtual ~WorkloadContext() {} + + SpacePointer _space; }; using WorkloadContextPointer = std::shared_ptr; @@ -56,12 +60,15 @@ namespace workload { // (5) Engine derives from task::Task and will run all the Job's class Engine : public Task { public: - Engine(); + Engine(const WorkloadContextPointer& context = std::make_shared()); ~Engine() = default; // (6) The Engine's Context is passed to its Jobs when they are run() void run() { assert(_context); Task::run(_context); } + // Register the Space + void registerSpace(const SpacePointer& space) { _context->_space = space; } + protected: // (6) Again, the Engine's Context is passed to its Jobs when they are run() void run(const WorkloadContextPointer& context) override { assert(_context); Task::run(_context); } diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index 3a8dd3c488..c4e89cda60 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -15,9 +15,11 @@ #ifndef hifi_workload_Space_h #define hifi_workload_Space_h +#include #include #include + namespace workload { class Space { @@ -77,6 +79,8 @@ private: std::vector _freeIndices; }; +using SpacePointer = std::shared_ptr; + } // namespace workload #endif // hifi_workload_Space_h From 76d2e9bc78080a7f23ffec833d6d6a3ea0c857a0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 20 Feb 2018 17:37:07 -0800 Subject: [PATCH 012/138] fix comment --- libraries/entities/src/DeleteEntityOperator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/DeleteEntityOperator.cpp b/libraries/entities/src/DeleteEntityOperator.cpp index 347d40ea49..8e6e545401 100644 --- a/libraries/entities/src/DeleteEntityOperator.cpp +++ b/libraries/entities/src/DeleteEntityOperator.cpp @@ -95,7 +95,7 @@ bool DeleteEntityOperator::preRecursion(const OctreeElementPointer& element) { EntityItemPointer theEntity = details.entity; bool entityDeleted = entityTreeElement->removeEntityItem(theEntity, true); // remove it from the element assert(entityDeleted); - (void)entityDeleted; // quite warning + (void)entityDeleted; // quiet warning about unused variable _tree->clearEntityMapEntry(details.entity->getEntityItemID()); _foundCount++; } From e7495d830b2f18dc5ce57298f4cc91e5fbd0bd1f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 20 Feb 2018 17:37:36 -0800 Subject: [PATCH 013/138] maintain Space proxies for entities --- .../src/entities/EntityTreeHeadlessViewer.cpp | 4 +++ interface/src/Application.cpp | 18 +++------- interface/src/Application.h | 3 -- libraries/avatars-renderer/CMakeLists.txt | 1 + libraries/entities-renderer/CMakeLists.txt | 1 + .../src/EntityTreeRenderer.cpp | 35 +++++++++++++++++-- .../src/EntityTreeRenderer.h | 9 +++++ libraries/entities/src/EntityItem.cpp | 6 +++- libraries/entities/src/EntityItem.h | 4 +++ libraries/entities/src/EntityTree.cpp | 10 ++++-- libraries/entities/src/EntityTree.h | 4 ++- libraries/workload/src/workload/Space.cpp | 2 +- libraries/workload/src/workload/Space.h | 3 +- 13 files changed, 75 insertions(+), 25 deletions(-) diff --git a/assignment-client/src/entities/EntityTreeHeadlessViewer.cpp b/assignment-client/src/entities/EntityTreeHeadlessViewer.cpp index 81c42cda1e..d22055b349 100644 --- a/assignment-client/src/entities/EntityTreeHeadlessViewer.cpp +++ b/assignment-client/src/entities/EntityTreeHeadlessViewer.cpp @@ -35,6 +35,10 @@ void EntityTreeHeadlessViewer::update() { EntityTreePointer tree = std::static_pointer_cast(_tree); tree->withTryWriteLock([&] { tree->update(); + + // flush final EntityTree references to deleted entities + std::vector deletedEntities; + tree->swapRemovedEntities(deletedEntities); }); } } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 85fa533b9c..7080602a22 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4544,8 +4544,6 @@ void Application::init() { _physicsEngine->init(); EntityTreePointer tree = getEntities()->getTree(); - connect(tree.get(), &EntityTree::deletingEntity, this, &Application::deletingEntity, Qt::QueuedConnection); - connect(tree.get(), &EntityTree::addingEntity, this, &Application::addingEntity, Qt::QueuedConnection); _entitySimulation->init(tree, _physicsEngine, &_entityEditSender); tree->setSimulation(_entitySimulation); @@ -4879,14 +4877,16 @@ void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) { auto entityId = _keyboardFocusedEntity.get(); if (entities->wantsKeyboardFocus(entityId)) { entities->setProxyWindow(entityId, _window->windowHandle()); - auto entity = getEntities()->getEntity(entityId); if (_keyboardMouseDevice->isActive()) { _keyboardMouseDevice->pluginFocusOutEvent(); } _lastAcceptedKeyPress = usecTimestampNow(); - setKeyboardFocusHighlight(entity->getWorldPosition(), entity->getWorldOrientation(), - entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR); + auto entity = getEntities()->getEntity(entityId); + if (entity) { + setKeyboardFocusHighlight(entity->getWorldPosition(), entity->getWorldOrientation(), + entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR); + } } } } @@ -7675,12 +7675,4 @@ void Application::saveNextPhysicsStats(QString filename) { _physicsEngine->saveNextPhysicsStats(filename); } -void Application::addingEntity(const EntityItemID& entityID) { - // TODO: Andrew to implement this -} - -void Application::deletingEntity(const EntityItemID& entityID) { - // TODO: Andrew to implement this -} - #include "Application.moc" diff --git a/interface/src/Application.h b/interface/src/Application.h index 3c2dee03e7..0435425d5f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -391,9 +391,6 @@ public slots: const QString getPreferredCursor() const { return _preferredCursor.get(); } void setPreferredCursor(const QString& cursor); - void addingEntity(const EntityItemID& entityID); - void deletingEntity(const EntityItemID& entityID); - private slots: void onDesktopRootItemCreated(QQuickItem* qmlContext); void onDesktopRootContextCreated(QQmlContext* qmlContext); diff --git a/libraries/avatars-renderer/CMakeLists.txt b/libraries/avatars-renderer/CMakeLists.txt index 40e1607b2a..d3d61ea3fa 100644 --- a/libraries/avatars-renderer/CMakeLists.txt +++ b/libraries/avatars-renderer/CMakeLists.txt @@ -14,5 +14,6 @@ include_hifi_library_headers(audio) include_hifi_library_headers(entities) include_hifi_library_headers(octree) include_hifi_library_headers(task) +include_hifi_library_headers(workload) target_bullet() diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index 0f33a73e40..92f78e357e 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -14,6 +14,7 @@ include_hifi_library_headers(entities) include_hifi_library_headers(avatars) include_hifi_library_headers(controllers) include_hifi_library_headers(task) +include_hifi_library_headers(workload) target_bullet() target_polyvox() diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index ba81922979..879dd709e8 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -278,6 +278,13 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r if (!entity->isParentPathComplete()) { continue; } + if (entity->getSpaceIndex() == -1) { + std::unique_lock lock(_spaceLock); + workload::Space::Sphere sphere(entity->getWorldPosition(), entity->getBoundingRadius()); + int32_t spaceIndex = _space.createProxy(sphere); + entity->setSpaceIndex(spaceIndex); + connect(entity.get(), &EntityItem::spaceUpdate, this, &EntityTreeRenderer::handleSpaceUpdate, Qt::QueuedConnection); + } auto entityID = entity->getEntityItemID(); processedIds.insert(entityID); @@ -287,7 +294,6 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r } } - if (!processedIds.empty()) { for (const auto& processedId : processedIds) { _entitiesToAdd.erase(processedId); @@ -407,8 +413,7 @@ void EntityTreeRenderer::update(bool simulate) { // here we update _currentFrame and _lastAnimated and sync with the server properties. tree->update(simulate); - // Update the rendereable entities as needed - { + { // Update the rendereable entities as needed PROFILE_RANGE(simulation_physics, "Scene"); PerformanceTimer sceneTimer("scene"); auto scene = _viewState->getMain3DScene(); @@ -421,6 +426,25 @@ void EntityTreeRenderer::update(bool simulate) { scene->enqueueTransaction(transaction); } } + { // update proxies in the workload::Space + std::unique_lock lock(_spaceLock); + _space.updateProxies(_spaceUpdates); + _spaceUpdates.clear(); + } + { // flush final EntityTree references to removed entities + std::vector deletedEntities; + tree->swapRemovedEntities(deletedEntities); + { // delete proxies from workload::Space + std::vector deadProxies; + std::unique_lock lock(_spaceLock); + for (auto entity : deletedEntities) { + int32_t spaceIndex = entity->getSpaceIndex(); + disconnect(entity.get(), &EntityItem::spaceUpdate, this, &EntityTreeRenderer::handleSpaceUpdate); + deadProxies.push_back(spaceIndex); + } + _space.deleteProxies(deadProxies); + } + } if (simulate) { // Handle enter/leave entity logic @@ -437,6 +461,11 @@ void EntityTreeRenderer::update(bool simulate) { } } +void EntityTreeRenderer::handleSpaceUpdate(std::pair proxyUpdate) { + std::unique_lock lock(_spaceLock); + _spaceUpdates.push_back(proxyUpdate); +} + bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QVector* entitiesContainingAvatar) { bool didUpdate = false; float radius = 0.01f; // for now, assume 0.01 meter radius, because we actually check the point inside later diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index f5cedfdd01..9602588dc4 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -24,6 +24,7 @@ #include #include #include +#include class AbstractScriptingServicesInterface; class AbstractViewStateInterface; @@ -139,6 +140,10 @@ public slots: EntityRendererPointer renderableForEntityId(const EntityItemID& id) const; render::ItemID renderableIdForEntityId(const EntityItemID& id) const; + //void handleSpaceUpdate(workload::Space::ProxyUpdate proxyUpdate); + void handleSpaceUpdate(std::pair proxyUpdate); + void testSlot(); + protected: virtual OctreePointer createTree() override { EntityTreePointer newTree = EntityTreePointer(new EntityTree(true)); @@ -261,6 +266,10 @@ private: static std::function _entitiesShouldFadeFunction; static std::function _renderDebugHullsOperator; + + mutable std::mutex _spaceLock; + workload::Space _space; + std::vector _spaceUpdates; }; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index ed902c9f05..b25ec2c10e 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2364,14 +2364,18 @@ void EntityItem::locationChanged(bool tellPhysics) { tree->entityChanged(getThisPointer()); } } - // TODO: Andrew to connect this to the Space instance in Application SpatiallyNestable::locationChanged(tellPhysics); // tell all the children, also + std::pair data(_spaceIndex, glm::vec4(getWorldPosition(), _boundingRadius)); + emit spaceUpdate(data); somethingChangedNotification(); } void EntityItem::dimensionsChanged() { requiresRecalcBoxes(); SpatiallyNestable::dimensionsChanged(); // Do what you have to do + _boundingRadius = 0.5f * glm::length(getScaledDimensions()); + std::pair data(_spaceIndex, glm::vec4(getWorldPosition(), _boundingRadius)); + emit spaceUpdate(data); somethingChangedNotification(); } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index dbdb762c16..497e1b7836 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -464,6 +464,7 @@ public: virtual bool getMeshes(MeshProxyList& result) { return true; } virtual void locationChanged(bool tellPhysics = true) override; + //void wtf(int32_t i) override; virtual bool getScalesWithParent() const override; @@ -478,6 +479,7 @@ public: void setCauterized(bool value) { _cauterized = value; } bool getCauterized() const { return _cauterized; } + float getBoundingRadius() const { return _boundingRadius; } void setSpaceIndex(int32_t index) { assert(_spaceIndex == -1); _spaceIndex = index; } int32_t getSpaceIndex() const { return _spaceIndex; } @@ -490,6 +492,7 @@ public: signals: void requestRenderUpdate(); + void spaceUpdate(std::pair data); protected: QHash _changeHandlers; @@ -641,6 +644,7 @@ protected: quint64 _lastUpdatedAccelerationTimestamp { 0 }; quint64 _lastUpdatedQueryAACubeTimestamp { 0 }; + float _boundingRadius { 0.0f }; int32_t _spaceIndex { -1 }; // index to proxy in workload::Space bool _cauterized { false }; // if true, don't draw because it would obscure 1st-person camera diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index ad0066af4a..6afe7cc574 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -260,7 +260,7 @@ void EntityTree::postAddEntity(EntityItemPointer entity) { return; } } - + // check to see if we need to simulate this entity.. if (_simulation) { _simulation->addEntity(entity); @@ -271,10 +271,11 @@ void EntityTree::postAddEntity(EntityItemPointer entity) { } _isDirty = true; - emit addingEntity(entity->getEntityItemID()); // find and hook up any entities with this entity as a (previously) missing parent fixupNeedsParentFixups(); + + emit addingEntity(entity->getEntityItemID()); } bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties, const SharedNodePointer& senderNode) { @@ -695,6 +696,11 @@ void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator) if (_simulation) { _simulation->prepareEntityForDelete(theEntity); } + + // We save a pointer to theEntity for external contexts that need it + // but this means: external contexts that remove entities from the tree + // must occasionally swapRemovedEntities() to flush these references. + _removedEntities.push_back(theEntity); } } diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 4eb0e15a94..f6130430a2 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -280,7 +280,7 @@ public: void setMyAvatar(std::shared_ptr myAvatar) { _myAvatar = myAvatar; } - void queueUpdateSpaceProxy(int32_t index, const glm::vec4& sphere); + void swapRemovedEntities(std::vector& entities) { entities.swap(_removedEntities); } static void setAddMaterialToEntityOperator(std::function addMaterialToEntityOperator) { _addMaterialToEntityOperator = addMaterialToEntityOperator; } static void setRemoveMaterialFromEntityOperator(std::function removeMaterialFromEntityOperator) { _removeMaterialFromEntityOperator = removeMaterialFromEntityOperator; } @@ -411,6 +411,8 @@ private: static std::function _removeMaterialFromAvatarOperator; static std::function _addMaterialToOverlayOperator; static std::function _removeMaterialFromOverlayOperator; + + std::vector _removedEntities; }; #endif // hifi_EntityTree_h diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index 2c38ec9f8b..3e8b61992e 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -40,7 +40,7 @@ void Space::deleteProxies(const std::vector& deadIndices) { } } -void Space::updateProxies(const std::vector >& changedProxies) { +void Space::updateProxies(const std::vector& changedProxies) { for (uint32_t i = 0; i < changedProxies.size(); ++i) { int32_t proxyId = changedProxies[i].first; if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) { diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index 3a8dd3c488..3706d45434 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -29,6 +29,7 @@ public: static const uint8_t REGION_INVALID = 4; using Sphere = glm::vec4; // = center, w = radius + using ProxyUpdate = std::pair; class Proxy { public: @@ -61,7 +62,7 @@ public: int32_t createProxy(const Sphere& sphere); void deleteProxies(const std::vector& deadIndices); - void updateProxies(const std::vector >& changedProxies); + void updateProxies(const std::vector& changedProxies); void setViews(const std::vector& views); uint32_t getNumObjects() const { return (uint32_t)(_proxies.size() - _freeIndices.size()); } From c3d08d06ff3681208c5e9c784a542446dd2127eb Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 20 Feb 2018 17:50:12 -0800 Subject: [PATCH 014/138] remove cruft --- libraries/entities-renderer/src/EntityTreeRenderer.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 9602588dc4..f034353347 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -140,9 +140,7 @@ public slots: EntityRendererPointer renderableForEntityId(const EntityItemID& id) const; render::ItemID renderableIdForEntityId(const EntityItemID& id) const; - //void handleSpaceUpdate(workload::Space::ProxyUpdate proxyUpdate); void handleSpaceUpdate(std::pair proxyUpdate); - void testSlot(); protected: virtual OctreePointer createTree() override { From f1dcfeb25e9a8a872e26b022bd6570819390fb6b Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 20 Feb 2018 18:20:12 -0800 Subject: [PATCH 015/138] Adding shaders and means to render the proxies contained in the workload SPace --- interface/src/Application.cpp | 2 +- interface/src/Application.h | 1 + interface/src/workload/GameWorkload.cpp | 82 +----------- interface/src/workload/GameWorkload.h | 16 +-- .../src/workload/GameWorkloadRenderer.cpp | 121 ++++++++++++++++++ interface/src/workload/GameWorkloadRenderer.h | 64 +++++++++ .../render-utils/src/drawWorkloadProxy.slf | 28 ++++ .../render-utils/src/drawWorkloadProxy.slv | 102 +++++++++++++++ libraries/workload/src/workload/Engine.cpp | 2 +- libraries/workload/src/workload/Engine.h | 7 +- libraries/workload/src/workload/Space.cpp | 9 ++ libraries/workload/src/workload/Space.h | 2 + 12 files changed, 336 insertions(+), 100 deletions(-) create mode 100644 interface/src/workload/GameWorkloadRenderer.cpp create mode 100644 interface/src/workload/GameWorkloadRenderer.h create mode 100644 libraries/render-utils/src/drawWorkloadProxy.slf create mode 100644 libraries/render-utils/src/drawWorkloadProxy.slv diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0abb43692d..4da50ca0b0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2400,7 +2400,7 @@ void Application::initializeGL() { DependencyManager::get()->initializeShapePipelines(); }); - _gameWorkload.startup(_main3DScene); + _gameWorkload.startup(_workloadSpace, _main3DScene); _offscreenContext = new OffscreenGLCanvas(); _offscreenContext->setObjectName("MainThreadContext"); diff --git a/interface/src/Application.h b/interface/src/Application.h index e04421cb6c..2af1d4678a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -619,6 +619,7 @@ private: gpu::ContextPointer _gpuContext; // initialized during window creation GameWorkload _gameWorkload; + workload::SpacePointer _workloadSpace{ new workload::Space() }; mutable QMutex _renderArgsMutex{ QMutex::Recursive }; struct AppRenderArgs { diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index f9a0bfa360..0113e0568d 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -8,8 +8,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "GameWorkload.h" +#include "GameWorkloadRenderer.h" -GameWorkloadContext::GameWorkloadContext(const render::ScenePointer& scene) : WorkloadContext(), _scene(scene) { +GameWorkloadContext::GameWorkloadContext(const workload::SpacePointer& space, const render::ScenePointer& scene) : WorkloadContext(space), _scene(scene) { } GameWorkloadContext::~GameWorkloadContext() { @@ -23,8 +24,8 @@ GameWorkload::~GameWorkload() { shutdown(); } -void GameWorkload::startup(const render::ScenePointer& scene) { - _engine.reset(new workload::Engine(std::make_shared(scene))); +void GameWorkload::startup(const workload::SpacePointer& space, const render::ScenePointer& scene) { + _engine.reset(new workload::Engine(std::make_shared(space, scene))); _engine->addJob("SpaceToRender"); } @@ -35,78 +36,3 @@ void GameWorkload::shutdown() { - - -class GameWorkloadRenderItem { -public: - using Payload = render::Payload; - using Pointer = Payload::DataPointer; - - GameWorkloadRenderItem() {} - ~GameWorkloadRenderItem() {} - void render(RenderArgs* args) {} - - render::Item::Bound& editBound() { _needUpdate = true; return _bound; } - const render::Item::Bound& getBound() { return _bound; } - - void setVisible(bool visible) { _isVisible = visible; } - bool isVisible() const { return _isVisible; } - -protected: - render::Item::Bound _bound; - - bool _needUpdate{ true }; - bool _isVisible{ true }; -}; - -namespace render { - template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload); - template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload); - template <> void payloadRender(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args); -} - -namespace render { - template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload) { - auto builder = ItemKey::Builder().withTypeShape(); - return builder.build(); - } - template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload) { - if (payload) { - return payload->getBound(); - } - return Item::Bound(); - } - template <> void payloadRender(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args) { - if (payload) { - payload->render(args); - } - } -} - - -void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, Outputs& outputs) { - auto gameWorkloadContext = std::dynamic_pointer_cast(runContext); - if (!gameWorkloadContext) { - return; - } - - auto scene = gameWorkloadContext->_scene; - - // Valid space, let's display its content - render::Transaction transaction; - if (!render::Item::isValidID(_spaceRenderItemID)) { - _spaceRenderItemID = scene->allocateID(); - auto renderItem = std::make_shared(); - renderItem->editBound().expandedContains(glm::vec3(0.0), 32000.0); - transaction.resetItem(_spaceRenderItemID, std::make_shared(std::make_shared())); - } - - scene->enqueueTransaction(transaction); - - auto space = gameWorkloadContext->_space; - if (!space) { - return; - } - - -} \ No newline at end of file diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index 1647056d60..fe48d0fe92 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -15,21 +15,9 @@ #include "render/Scene.h" -class GameSpaceToRender { -public: - using Outputs = render::Transaction; - using JobModel = workload::Job::ModelO; - - GameSpaceToRender() {} - void run(const workload::WorkloadContextPointer& renderContext, Outputs& outputs); - -protected: - render::ItemID _spaceRenderItemID{ render::Item::INVALID_ITEM_ID }; -}; - class GameWorkloadContext : public workload::WorkloadContext { public: - GameWorkloadContext(const render::ScenePointer& scene); + GameWorkloadContext(const workload::SpacePointer& space, const render::ScenePointer& scene); virtual ~GameWorkloadContext(); render::ScenePointer _scene; @@ -40,7 +28,7 @@ public: GameWorkload(); ~GameWorkload(); - void startup(const render::ScenePointer& scene); + void startup(const workload::SpacePointer& space, const render::ScenePointer& scene); void shutdown(); workload::EnginePointer _engine; diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp new file mode 100644 index 0000000000..dcc55e54b3 --- /dev/null +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -0,0 +1,121 @@ +// +// GameWorkloadRender.cpp +// +// Created by Sam Gateau on 2/20/2018. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "GameWorkloadRenderer.h" + +#include + + +#include "render-utils/drawWorkloadProxy_vert.h" +#include "render-utils/drawWorkloadProxy_frag.h" + +void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, Outputs& outputs) { + auto gameWorkloadContext = std::dynamic_pointer_cast(runContext); + if (!gameWorkloadContext) { + return; + } + + auto scene = gameWorkloadContext->_scene; + + // Valid space, let's display its content + render::Transaction transaction; + if (!render::Item::isValidID(_spaceRenderItemID)) { + _spaceRenderItemID = scene->allocateID(); + auto renderItem = std::make_shared(); + renderItem->editBound().expandedContains(glm::vec3(0.0), 32000.0); + transaction.resetItem(_spaceRenderItemID, std::make_shared(std::make_shared())); + } + + scene->enqueueTransaction(transaction); + + auto space = gameWorkloadContext->_space; + if (!space) { + return; + } + + space->getNumObjects(); + +} + +namespace render { + template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload) { + auto builder = ItemKey::Builder().opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); + return builder.build(); + } + template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload) { + if (payload) { + return payload->getBound(); + } + return Item::Bound(); + } + template <> void payloadRender(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args) { + if (payload) { + payload->render(args); + } + } +} + + + +void GameWorkloadRenderItem::setAllProxies(const std::vector& proxies) { + static const uint32_t sizeOfProxy = sizeof(workload::Space::Proxy); + if (!_allProxiesBuffer) { + _allProxiesBuffer = std::make_shared(sizeOfProxy); + } + + _allProxiesBuffer->setData(proxies.size() * sizeOfProxy, (const gpu::Byte*) proxies.data()); + _numAllProxies = (uint32_t) proxies.size(); +} + +const gpu::PipelinePointer GameWorkloadRenderItem::getPipeline() { + if (!_drawAllProxiesPipeline) { + auto vs = drawWorkloadProxy_vert::getShader(); + auto ps = drawWorkloadProxy_frag::getShader(); + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + auto state = std::make_shared(); + state->setDepthTest(true, false, gpu::LESS_EQUAL); + state->setBlendFunction(true, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); + + _drawAllProxiesPipeline = gpu::Pipeline::create(program, state); + } + return _drawAllProxiesPipeline; +} + +void GameWorkloadRenderItem::render(RenderArgs* args) { + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + args->_batch = &batch; + + // Setup projection + glm::mat4 projMat; + Transform viewMat; + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + batch.setModelTransform(Transform()); + + // Bind program + batch.setPipeline(getPipeline()); + + batch.setResourceBuffer(0, _allProxiesBuffer); + + static const int NUM_VERTICES_PER_QUAD = 4; + batch.draw(gpu::LINES, NUM_VERTICES_PER_QUAD * _numAllProxies, 0); + }); + +} + + + diff --git a/interface/src/workload/GameWorkloadRenderer.h b/interface/src/workload/GameWorkloadRenderer.h new file mode 100644 index 0000000000..969c85a195 --- /dev/null +++ b/interface/src/workload/GameWorkloadRenderer.h @@ -0,0 +1,64 @@ +// +// GameWorkloadRender.h +// +// Created by Sam Gateau on 2/20/2018. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_GameWorkloadRenderer_h +#define hifi_GameWorkloadRenderer_h + +#include "GameWorkload.h" + +class GameSpaceToRender { +public: + using Outputs = render::Transaction; + using JobModel = workload::Job::ModelO; + + GameSpaceToRender() {} + void run(const workload::WorkloadContextPointer& renderContext, Outputs& outputs); + +protected: + render::ItemID _spaceRenderItemID{ render::Item::INVALID_ITEM_ID }; +}; + + +class GameWorkloadRenderItem { +public: + using Payload = render::Payload; + using Pointer = Payload::DataPointer; + + GameWorkloadRenderItem() {} + ~GameWorkloadRenderItem() {} + void render(RenderArgs* args); + + render::Item::Bound& editBound() { _needUpdate = true; return _bound; } + const render::Item::Bound& getBound() { return _bound; } + + void setVisible(bool visible) { _isVisible = visible; } + bool isVisible() const { return _isVisible; } + + void setAllProxies(const std::vector& proxies); + +protected: + render::Item::Bound _bound; + + gpu::BufferPointer _allProxiesBuffer; + uint32_t _numAllProxies{ 0 }; + + gpu::PipelinePointer _drawAllProxiesPipeline; + const gpu::PipelinePointer getPipeline(); + + bool _needUpdate{ true }; + bool _isVisible{ true }; +}; + +namespace render { + template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload); + template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload); + template <> void payloadRender(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args); +} + +#endif \ No newline at end of file diff --git a/libraries/render-utils/src/drawWorkloadProxy.slf b/libraries/render-utils/src/drawWorkloadProxy.slf new file mode 100644 index 0000000000..84c47d0933 --- /dev/null +++ b/libraries/render-utils/src/drawWorkloadProxy.slf @@ -0,0 +1,28 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// drawItemBounds.frag +// fragment shader +// +// Created by Sam Gateau on 6/29/15. +// Copyright 2015 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 +// + +in vec4 varColor; +in vec2 varTexcoord; +out vec4 outFragColor; + +void main(void) { + float var = step(fract(varTexcoord.x * varTexcoord.y * 1.0), 0.5); + + if (varColor.a == 0.0) { + outFragColor = vec4(mix(vec3(0.0), varColor.xyz, var), mix(0.0, 1.0, var)); + + } else { + outFragColor = vec4(mix(vec3(1.0), varColor.xyz, var), varColor.a); + } + +} diff --git a/libraries/render-utils/src/drawWorkloadProxy.slv b/libraries/render-utils/src/drawWorkloadProxy.slv new file mode 100644 index 0000000000..0bb2b795bd --- /dev/null +++ b/libraries/render-utils/src/drawWorkloadProxy.slv @@ -0,0 +1,102 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// drawItemBounds.slv +// vertex shader +// +// Created by Sam Gateau on 6/29/2015. +// Copyright 2015 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 gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include gpu/Color.slh@> +<$declareColorWheel()$> + +uniform vec4 inColor; + + +struct ItemBound { + vec4 id_boundPos; + vec4 boundDim_s; +}; + +#if defined(GPU_GL410) +uniform samplerBuffer ssbo0Buffer; +ItemBound getItemBound(int i) { + int offset = 2 * i; + ItemBound bound; + bound.id_boundPos = texelFetch(ssbo0Buffer, offset); + bound.boundDim_s = texelFetch(ssbo0Buffer, offset + 1); + return bound; +} +#else +layout(std140) buffer ssbo0Buffer { + ItemBound bounds[]; +}; +ItemBound getItemBound(int i) { + ItemBound bound = bounds[i]; + return bound; +} +#endif + + + +out vec4 varColor; +out vec2 varTexcoord; + +void main(void) { + const vec4 UNIT_BOX[8] = vec4[8]( + vec4(0.0, 0.0, 0.0, 0.0), + vec4(1.0, 0.0, 0.0, 1.0), + vec4(0.0, 1.0, 0.0, 1.0), + vec4(1.0, 1.0, 0.0, 2.0), + vec4(0.0, 0.0, 1.0, 1.0), + vec4(1.0, 0.0, 1.0, 2.0), + vec4(0.0, 1.0, 1.0, 2.0), + vec4(1.0, 1.0, 1.0, 3.0) + ); + const int UNIT_BOX_LINE_INDICES[24] = int[24]( + 0, 1, + 1, 3, + 3, 2, + 2, 0, + 4, 5, + 5, 7, + 7, 6, + 6, 4, + 2, 6, + 3, 7, + 0, 4, + 1, 5 + ); + + int boundID = gl_VertexID / 24; + int vertexID = gl_VertexID - boundID * 24; + + vec4 cubeVec = UNIT_BOX[UNIT_BOX_LINE_INDICES[vertexID]]; + + ItemBound bound = getItemBound(boundID); + vec3 boundPos = bound.id_boundPos.yzw; + vec3 boundDim = bound.boundDim_s.xyz; + + vec4 pos = vec4(boundPos + boundDim * cubeVec.xyz, 1.0); + + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, pos, gl_Position)$> + + if (inColor.w < 0.0) { + varColor = vec4(colorWheel(float(boundID)/(-inColor.w)), 1.0); + } else { + varColor = vec4(colorWheel(float(inColor.w)), 1.0); + } + varTexcoord = vec2(cubeVec.w, length(boundDim)); + +} \ No newline at end of file diff --git a/libraries/workload/src/workload/Engine.cpp b/libraries/workload/src/workload/Engine.cpp index e209fbf5d5..3cf31bd879 100644 --- a/libraries/workload/src/workload/Engine.cpp +++ b/libraries/workload/src/workload/Engine.cpp @@ -36,7 +36,7 @@ namespace workload { } }; - WorkloadContext::WorkloadContext() : task::JobContext(trace_workload()) {} + WorkloadContext::WorkloadContext(const SpacePointer& space) : task::JobContext(trace_workload()), _space(space) {} using EngineModel = Task::Model; diff --git a/libraries/workload/src/workload/Engine.h b/libraries/workload/src/workload/Engine.h index 1e69f555c7..365461a4a3 100644 --- a/libraries/workload/src/workload/Engine.h +++ b/libraries/workload/src/workload/Engine.h @@ -29,7 +29,7 @@ namespace workload { // (1) Derive class C from task::JobContext class WorkloadContext : public task::JobContext { public: - WorkloadContext(); + WorkloadContext(const SpacePointer& space); virtual ~WorkloadContext() {} SpacePointer _space; @@ -66,12 +66,7 @@ namespace workload { // (6) The Engine's Context is passed to its Jobs when they are run() void run() { assert(_context); Task::run(_context); } - // Register the Space - void registerSpace(const SpacePointer& space) { _context->_space = space; } - protected: - // (6) Again, the Engine's Context is passed to its Jobs when they are run() - void run(const WorkloadContextPointer& context) override { assert(_context); Task::run(_context); } private: WorkloadContextPointer _context; diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index 2c38ec9f8b..e37211b611 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -101,6 +101,15 @@ void Space::deleteProxy(int32_t proxyId) { } } +uint32_t Space::copyProxyValues(Proxy* proxies, uint32_t numDestProxies) { + + auto numCopied = std::min(numDestProxies, (uint32_t)_proxies.size()); + memcpy(proxies, _proxies.data(), numCopied * sizeof(Proxy)); + + return numCopied; +} + + // private void Space::updateProxy(int32_t proxyId, const Space::Sphere& newSphere) { if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) { diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index c4e89cda60..fb288a060c 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -70,6 +70,8 @@ public: void categorizeAndGetChanges(std::vector& changes); + uint32_t copyProxyValues(Proxy* proxies, uint32_t numDestProxies); + private: void deleteProxy(int32_t proxyId); void updateProxy(int32_t proxyId, const Sphere& sphere); From 9246f6c24a3f279f7bf4399075eb3964788d57af Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 20 Feb 2018 19:15:54 -0800 Subject: [PATCH 016/138] render-perf depdends on workload library --- libraries/entities-renderer/CMakeLists.txt | 3 +-- tests/render-perf/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index 92f78e357e..083a1716ce 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -1,7 +1,7 @@ set(TARGET_NAME entities-renderer) AUTOSCRIBE_SHADER_LIB(gpu graphics procedural render render-utils) setup_hifi_library(Network Script) -link_hifi_libraries(shared gpu procedural graphics model-networking script-engine render render-utils image qml ui pointers) +link_hifi_libraries(shared workload gpu procedural graphics model-networking script-engine render render-utils image qml ui pointers) include_hifi_library_headers(networking) include_hifi_library_headers(gl) include_hifi_library_headers(ktx) @@ -14,7 +14,6 @@ include_hifi_library_headers(entities) include_hifi_library_headers(avatars) include_hifi_library_headers(controllers) include_hifi_library_headers(task) -include_hifi_library_headers(workload) target_bullet() target_polyvox() diff --git a/tests/render-perf/CMakeLists.txt b/tests/render-perf/CMakeLists.txt index 7e61d9550c..80b9b0eb85 100644 --- a/tests/render-perf/CMakeLists.txt +++ b/tests/render-perf/CMakeLists.txt @@ -13,7 +13,7 @@ set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") # link in the shared libraries link_hifi_libraries( - shared task networking animation + shared task workload networking animation ktx image octree gl gpu gpu-gl render render-utils graphics fbx model-networking From 33b47f9ae29d0b7979f793e6b04b81459dcafa81 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 21 Feb 2018 10:34:58 -0800 Subject: [PATCH 017/138] Merging with the actual worloadspace managed from the EntityTreeRenderer --- interface/src/Application.cpp | 2 +- interface/src/Application.h | 1 - interface/src/workload/GameWorkloadRenderer.cpp | 10 ++++++++-- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 6 +++--- libraries/entities-renderer/src/EntityTreeRenderer.h | 5 ++++- libraries/workload/src/workload/Space.h | 2 ++ 6 files changed, 18 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e1d5ed7e29..0c654e9196 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2400,7 +2400,7 @@ void Application::initializeGL() { DependencyManager::get()->initializeShapePipelines(); }); - _gameWorkload.startup(_workloadSpace, _main3DScene); + _gameWorkload.startup(getEntities()->getWorkloadSpace(), _main3DScene); _offscreenContext = new OffscreenGLCanvas(); _offscreenContext->setObjectName("MainThreadContext"); diff --git a/interface/src/Application.h b/interface/src/Application.h index 5617d0895d..8028dc8c68 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -616,7 +616,6 @@ private: gpu::ContextPointer _gpuContext; // initialized during window creation GameWorkload _gameWorkload; - workload::SpacePointer _workloadSpace{ new workload::Space() }; mutable QMutex _renderArgsMutex{ QMutex::Recursive }; struct AppRenderArgs { diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index dcc55e54b3..e10c28c36c 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -30,17 +30,23 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, auto renderItem = std::make_shared(); renderItem->editBound().expandedContains(glm::vec3(0.0), 32000.0); transaction.resetItem(_spaceRenderItemID, std::make_shared(std::make_shared())); + scene->enqueueTransaction(transaction); } - scene->enqueueTransaction(transaction); auto space = gameWorkloadContext->_space; if (!space) { return; } - space->getNumObjects(); + std::vector proxies(space->getNumAllocatedProxies()); + space->copyProxyValues(proxies.data(), proxies.size()); + + transaction.updateItem(_spaceRenderItemID, [proxies](GameWorkloadRenderItem& item) { + item.setAllProxies(proxies); + }); + scene->enqueueTransaction(transaction); } namespace render { diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 879dd709e8..eecd21e5ac 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -281,7 +281,7 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r if (entity->getSpaceIndex() == -1) { std::unique_lock lock(_spaceLock); workload::Space::Sphere sphere(entity->getWorldPosition(), entity->getBoundingRadius()); - int32_t spaceIndex = _space.createProxy(sphere); + int32_t spaceIndex = _space->createProxy(sphere); entity->setSpaceIndex(spaceIndex); connect(entity.get(), &EntityItem::spaceUpdate, this, &EntityTreeRenderer::handleSpaceUpdate, Qt::QueuedConnection); } @@ -428,7 +428,7 @@ void EntityTreeRenderer::update(bool simulate) { } { // update proxies in the workload::Space std::unique_lock lock(_spaceLock); - _space.updateProxies(_spaceUpdates); + _space->updateProxies(_spaceUpdates); _spaceUpdates.clear(); } { // flush final EntityTree references to removed entities @@ -442,7 +442,7 @@ void EntityTreeRenderer::update(bool simulate) { disconnect(entity.get(), &EntityItem::spaceUpdate, this, &EntityTreeRenderer::handleSpaceUpdate); deadProxies.push_back(spaceIndex); } - _space.deleteProxies(deadProxies); + _space->deleteProxies(deadProxies); } } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index f034353347..5840dc6832 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -120,6 +120,9 @@ public: static void setRenderDebugHullsOperator(std::function renderDebugHullsOperator) { _renderDebugHullsOperator = renderDebugHullsOperator; } static bool shouldRenderDebugHulls() { return _renderDebugHullsOperator(); } + // Access the workload Space + const workload::SpacePointer getWorkloadSpace() const { return _space; } + signals: void enterEntity(const EntityItemID& entityItemID); void leaveEntity(const EntityItemID& entityItemID); @@ -266,7 +269,7 @@ private: static std::function _renderDebugHullsOperator; mutable std::mutex _spaceLock; - workload::Space _space; + workload::SpacePointer _space{ new workload::Space() }; std::vector _spaceUpdates; }; diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index 4b8510ebae..d7478b6066 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -35,6 +35,7 @@ public: class Proxy { public: + Proxy() : sphere(0.0f) {} Proxy(const Sphere& s) : sphere(s) {} Sphere sphere; uint8_t region { REGION_UNKNOWN }; @@ -68,6 +69,7 @@ public: void setViews(const std::vector& views); uint32_t getNumObjects() const { return (uint32_t)(_proxies.size() - _freeIndices.size()); } + uint32_t getNumAllocatedProxies() const { return (uint32_t)(_proxies.size()); } void categorizeAndGetChanges(std::vector& changes); From 1c3bc0aa67a903736b01d1e1246d2b66d02f74c9 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 21 Feb 2018 11:18:41 -0800 Subject: [PATCH 018/138] addressing review and warnings --- interface/src/workload/GameWorkloadRenderer.cpp | 5 +++-- libraries/workload/src/workload/Engine.h | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index e10c28c36c..99a784a511 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -9,6 +9,7 @@ // #include "GameWorkloadRenderer.h" +#include #include @@ -28,7 +29,7 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, if (!render::Item::isValidID(_spaceRenderItemID)) { _spaceRenderItemID = scene->allocateID(); auto renderItem = std::make_shared(); - renderItem->editBound().expandedContains(glm::vec3(0.0), 32000.0); + renderItem->editBound().expandedContains(glm::vec3(0.0f), 32000.0f); transaction.resetItem(_spaceRenderItemID, std::make_shared(std::make_shared())); scene->enqueueTransaction(transaction); } @@ -41,7 +42,7 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, std::vector proxies(space->getNumAllocatedProxies()); - space->copyProxyValues(proxies.data(), proxies.size()); + space->copyProxyValues(proxies.data(), (uint32_t) proxies.size()); transaction.updateItem(_spaceRenderItemID, [proxies](GameWorkloadRenderItem& item) { item.setAllProxies(proxies); diff --git a/libraries/workload/src/workload/Engine.h b/libraries/workload/src/workload/Engine.h index 365461a4a3..08abe23e35 100644 --- a/libraries/workload/src/workload/Engine.h +++ b/libraries/workload/src/workload/Engine.h @@ -47,7 +47,7 @@ namespace workload { Q_PROPERTY(QString message READ getMessage WRITE setMessage) QString _message {"Hello World."}; public: - HelloWorldConfig() : Job::Config(true) {} + HelloWorldConfig() : Job::Config(true) {} QString getMessage() const { return _message; } void setMessage(const QString& msg) { _message = msg; } }; @@ -64,9 +64,11 @@ namespace workload { ~Engine() = default; // (6) The Engine's Context is passed to its Jobs when they are run() - void run() { assert(_context); Task::run(_context); } + void run() { assert(_context); run(_context); } protected: + // (6) Again, the Engine's Context is passed to its Jobs when they are run() + void run(const WorkloadContextPointer& context) override { assert(_context); Task::run(_context); } private: WorkloadContextPointer _context; From 85a17f1301f1f3ad31c13fdfa9d4c53a2c6d5d95 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 21 Feb 2018 11:21:43 -0800 Subject: [PATCH 019/138] missing cstring for the memcpy in Space.cpp --- libraries/workload/src/workload/Space.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index fa49d9209d..e9745e0916 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -13,7 +13,7 @@ // #include "Space.h" - +#include #include #include From db4e280e95bb3f004e2d1d168ac46c7433f8eeb6 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 21 Feb 2018 12:04:41 -0800 Subject: [PATCH 020/138] Adding the stub of the ClassificationTracker class --- .../src/workload/ClassificationTracker.cpp | 24 ++++++++++ .../src/workload/ClassificationTracker.h | 45 +++++++++++++++++++ libraries/workload/src/workload/Engine.cpp | 6 ++- libraries/workload/src/workload/Engine.h | 2 +- libraries/workload/src/workload/Space.h | 2 + 5 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 libraries/workload/src/workload/ClassificationTracker.cpp create mode 100644 libraries/workload/src/workload/ClassificationTracker.h diff --git a/libraries/workload/src/workload/ClassificationTracker.cpp b/libraries/workload/src/workload/ClassificationTracker.cpp new file mode 100644 index 0000000000..009549737f --- /dev/null +++ b/libraries/workload/src/workload/ClassificationTracker.cpp @@ -0,0 +1,24 @@ +// +// ClassificationTracker.cpp +// libraries/workload/src/workload +// +// Created by Andrew Meadows 2018.02.21 +// Copyright 2018 High Fidelity, Inc. +// +// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards +// Simple plane class. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "ClassificationTracker.h" + +using namespace workload; + +void ClassificationTracker::configure(const Config& config) { +} + +void ClassificationTracker::run(const workload::WorkloadContextPointer& renderContext, Outputs& outputs) { + +} + diff --git a/libraries/workload/src/workload/ClassificationTracker.h b/libraries/workload/src/workload/ClassificationTracker.h new file mode 100644 index 0000000000..ca7a919769 --- /dev/null +++ b/libraries/workload/src/workload/ClassificationTracker.h @@ -0,0 +1,45 @@ +// +// ClassificationTracker.h +// libraries/workload/src/workload +// +// Created by Andrew Meadows 2018.02.21 +// Copyright 2018 High Fidelity, Inc. +// +// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards +// Simple plane class. +// +// 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_workload_ClassificationTracker_h +#define hifi_workload_ClassificationTracker_h + +#include "Space.h" +#include "Engine.h" + +namespace workload { + + class ClassificationTrackerConfig : public Job::Config { + Q_OBJECT + public: + ClassificationTrackerConfig() : Job::Config(true) {} + }; + + class ClassificationTracker { + public: + using Config = ClassificationTrackerConfig; + using Outputs = Classifications; + using JobModel = workload::Job::ModelO; + + ClassificationTracker() {} + + void configure(const Config& config); + void run(const workload::WorkloadContextPointer& renderContext, Outputs& outputs); + + protected: + }; + +} // namespace workload + +#endif // hifi_workload_ClassificationTracker_h diff --git a/libraries/workload/src/workload/Engine.cpp b/libraries/workload/src/workload/Engine.cpp index 7e69731d4e..ba3e7706ca 100644 --- a/libraries/workload/src/workload/Engine.cpp +++ b/libraries/workload/src/workload/Engine.cpp @@ -16,6 +16,8 @@ #include +#include "ClassificationTracker.h" + namespace workload { // the "real Job" @@ -33,7 +35,7 @@ namespace workload { if (_isEnabled) { std::cout << _message.toStdString() << std::endl; } - } + } }; WorkloadContext::WorkloadContext() : task::JobContext(trace_workload()) {} @@ -47,6 +49,8 @@ namespace workload { using JobModel = Task::Model; void build(EngineModel& model, const Varying& in, Varying& out) { model.addJob("helloWorld"); + + auto classifications = model.addJob("classificationTracker"); } }; diff --git a/libraries/workload/src/workload/Engine.h b/libraries/workload/src/workload/Engine.h index a422c5d715..7a4a5d428f 100644 --- a/libraries/workload/src/workload/Engine.h +++ b/libraries/workload/src/workload/Engine.h @@ -43,7 +43,7 @@ namespace workload { Q_PROPERTY(QString message READ getMessage WRITE setMessage) QString _message {"Hello World."}; public: - HelloWorldConfig() : Job::Config(true) {} + HelloWorldConfig() : Job::Config(true) {} QString getMessage() const { return _message; } void setMessage(const QString& msg) { _message = msg; } }; diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index 3706d45434..f071c658a7 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -78,6 +78,8 @@ private: std::vector _freeIndices; }; +using Classifications = std::vector; + } // namespace workload #endif // hifi_workload_Space_h From 7267f2a62943dd651da375746e2ec622d19a880b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 21 Feb 2018 12:36:49 -0800 Subject: [PATCH 021/138] fix linux compile error --- libraries/workload/src/workload/Engine.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/workload/src/workload/Engine.h b/libraries/workload/src/workload/Engine.h index 08abe23e35..fdcb49b863 100644 --- a/libraries/workload/src/workload/Engine.h +++ b/libraries/workload/src/workload/Engine.h @@ -60,7 +60,7 @@ namespace workload { // (5) Engine derives from task::Task and will run all the Job's class Engine : public Task { public: - Engine(const WorkloadContextPointer& context = std::make_shared()); + Engine(const WorkloadContextPointer& context); ~Engine() = default; // (6) The Engine's Context is passed to its Jobs when they are run() From 7a684058b5c5d0471748ca641d1068b817e82a08 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 21 Feb 2018 15:25:16 -0800 Subject: [PATCH 022/138] fix link errors on linux build --- interface/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 85007f5f15..151e95900a 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -204,14 +204,13 @@ endif() # link required hifi libraries link_hifi_libraries( - shared task octree ktx gpu gl procedural graphics render + shared workload task octree ktx gpu gl procedural graphics render pointers recording fbx networking model-networking entities avatars trackers audio audio-client animation script-engine physics render-utils entities-renderer avatars-renderer ui qml auto-updater midi controllers plugins image trackers ui-plugins display-plugins input-plugins - workload ${PLATFORM_GL_BACKEND} ) From b512f7e1ba98985176f998eeeca95c981f47054e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 21 Feb 2018 15:25:38 -0800 Subject: [PATCH 023/138] remove 'HelloWorld' stubbery --- libraries/workload/src/workload/Engine.cpp | 26 ++------------------- libraries/workload/src/workload/Engine.h | 27 +--------------------- 2 files changed, 3 insertions(+), 50 deletions(-) diff --git a/libraries/workload/src/workload/Engine.cpp b/libraries/workload/src/workload/Engine.cpp index ab4634cb97..70566fe704 100644 --- a/libraries/workload/src/workload/Engine.cpp +++ b/libraries/workload/src/workload/Engine.cpp @@ -20,36 +20,14 @@ namespace workload { - // the "real Job" - class HelloWorld { - QString _message; - bool _isEnabled { true }; - public: - using JobModel = Job::Model; - HelloWorld() {} - void configure(const HelloWorldConfig& configuration) { - _isEnabled = configuration.isEnabled(); - _message = configuration.getMessage(); - } - void run(const WorkloadContextPointer& context) { - if (_isEnabled) { - std::cout << _message.toStdString() << std::endl; - } - } - }; - WorkloadContext::WorkloadContext(const SpacePointer& space) : task::JobContext(trace_workload()), _space(space) {} - using EngineModel = Task::Model; + using EngineModel = Task::Model; - // the 'Builder' is the 'Data' on which the EngineModel templatizes. - // It must implement build() which is called by EngineModel::create(). - class HelloWorldBuilder { + class EngineBuilder { public: using JobModel = Task::Model; void build(EngineModel& model, const Varying& in, Varying& out) { - model.addJob("helloWorld"); - auto classifications = model.addJob("classificationTracker"); } }; diff --git a/libraries/workload/src/workload/Engine.h b/libraries/workload/src/workload/Engine.h index fdcb49b863..aa45b03a20 100644 --- a/libraries/workload/src/workload/Engine.h +++ b/libraries/workload/src/workload/Engine.h @@ -24,9 +24,6 @@ namespace workload { - // How to make an Engine under the task::Task paradigm... - - // (1) Derive class C from task::JobContext class WorkloadContext : public task::JobContext { public: WorkloadContext(const SpacePointer& space); @@ -34,40 +31,18 @@ namespace workload { SpacePointer _space; }; - using WorkloadContextPointer = std::shared_ptr; - // (2) Apply a macro which will create local aliases (via "using") for example: - // using Task = task::Task; + using WorkloadContextPointer = std::shared_ptr; Task_DeclareTypeAliases(WorkloadContext) - // (3) You'll need a 'real Job' but it will need a Config for exposing settings to JS, - // and you should do that here: - class HelloWorldConfig : public Job::Config { - Q_OBJECT - Q_PROPERTY(QString message READ getMessage WRITE setMessage) - QString _message {"Hello World."}; - public: - HelloWorldConfig() : Job::Config(true) {} - QString getMessage() const { return _message; } - void setMessage(const QString& msg) { _message = msg; } - }; - - // (4) In cpp file the 'real Job' will need a 'builder'. The 'builder' is the 'Data' argument - // for the Model template. - // Data must implement Data::build(). - // Data::build() is called when the Model is added (in Engine ctor) as the first child job of the Engine - - // (5) Engine derives from task::Task and will run all the Job's class Engine : public Task { public: Engine(const WorkloadContextPointer& context); ~Engine() = default; - // (6) The Engine's Context is passed to its Jobs when they are run() void run() { assert(_context); run(_context); } protected: - // (6) Again, the Engine's Context is passed to its Jobs when they are run() void run(const WorkloadContextPointer& context) override { assert(_context); Task::run(_context); } private: From 9c136e7dac4ce8a00bd6f8ca1d84c2eda24628b4 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 21 Feb 2018 17:31:53 -0800 Subject: [PATCH 024/138] Trying to render the proxies without success --- .../src/workload/GameWorkloadRenderer.cpp | 45 +++++++++++-------- interface/src/workload/GameWorkloadRenderer.h | 2 + .../render-utils/src/drawWorkloadProxy.slf | 4 +- .../render-utils/src/drawWorkloadProxy.slv | 42 +++++++++-------- libraries/workload/src/workload/Space.h | 2 + 5 files changed, 53 insertions(+), 42 deletions(-) diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index 99a784a511..569f95364a 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -52,7 +52,7 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, namespace render { template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload) { - auto builder = ItemKey::Builder().opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); + auto builder = ItemKey::Builder().transparentShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); return builder.build(); } template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload) { @@ -66,6 +66,12 @@ namespace render { payload->render(args); } } + template <> const ShapeKey shapeGetShapeKey(const GameWorkloadRenderItem::Pointer& payload) { + if (payload) { + return ShapeKey::Builder::ownPipeline(); + } + return ShapeKey::Builder::ownPipeline(); + } } @@ -87,40 +93,41 @@ const gpu::PipelinePointer GameWorkloadRenderItem::getPipeline() { gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding("ssbo0Buffer", 0)); gpu::Shader::makeProgram(*program, slotBindings); auto state = std::make_shared(); - state->setDepthTest(true, false, gpu::LESS_EQUAL); + /* state->setDepthTest(true, false, gpu::LESS_EQUAL); state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); - +*/ _drawAllProxiesPipeline = gpu::Pipeline::create(program, state); } return _drawAllProxiesPipeline; } void GameWorkloadRenderItem::render(RenderArgs* args) { - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - args->_batch = &batch; + gpu::Batch& batch = *(args->_batch); - // Setup projection - glm::mat4 projMat; - Transform viewMat; - args->getViewFrustum().evalProjectionMatrix(projMat); - args->getViewFrustum().evalViewTransform(viewMat); - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - batch.setModelTransform(Transform()); + // Setup projection + // glm::mat4 projMat; + // Transform viewMat; + // args->getViewFrustum().evalProjectionMatrix(projMat); + // args->getViewFrustum().evalViewTransform(viewMat); + // batch.setProjectionTransform(projMat); + // batch.setViewTransform(viewMat); + batch.setModelTransform(Transform()); - // Bind program - batch.setPipeline(getPipeline()); + // Bind program + batch.setPipeline(getPipeline()); - batch.setResourceBuffer(0, _allProxiesBuffer); + batch.setResourceBuffer(0, _allProxiesBuffer); - static const int NUM_VERTICES_PER_QUAD = 4; - batch.draw(gpu::LINES, NUM_VERTICES_PER_QUAD * _numAllProxies, 0); - }); + static const int NUM_VERTICES_PER_QUAD = 24; + batch.draw(gpu::LINES, NUM_VERTICES_PER_QUAD * _numAllProxies, 0); + + batch.setResourceBuffer(0, nullptr); } diff --git a/interface/src/workload/GameWorkloadRenderer.h b/interface/src/workload/GameWorkloadRenderer.h index 969c85a195..74e19825b5 100644 --- a/interface/src/workload/GameWorkloadRenderer.h +++ b/interface/src/workload/GameWorkloadRenderer.h @@ -59,6 +59,8 @@ namespace render { template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload); template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload); template <> void payloadRender(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args); + template <> const ShapeKey shapeGetShapeKey(const GameWorkloadRenderItem::Pointer& payload); + } #endif \ No newline at end of file diff --git a/libraries/render-utils/src/drawWorkloadProxy.slf b/libraries/render-utils/src/drawWorkloadProxy.slf index 84c47d0933..36606b8afc 100644 --- a/libraries/render-utils/src/drawWorkloadProxy.slf +++ b/libraries/render-utils/src/drawWorkloadProxy.slf @@ -16,6 +16,8 @@ in vec2 varTexcoord; out vec4 outFragColor; void main(void) { + outFragColor = vec4(1.0); + /* float var = step(fract(varTexcoord.x * varTexcoord.y * 1.0), 0.5); if (varColor.a == 0.0) { @@ -23,6 +25,6 @@ void main(void) { } else { outFragColor = vec4(mix(vec3(1.0), varColor.xyz, var), varColor.a); - } + }*/ } diff --git a/libraries/render-utils/src/drawWorkloadProxy.slv b/libraries/render-utils/src/drawWorkloadProxy.slv index 0bb2b795bd..444f4c0917 100644 --- a/libraries/render-utils/src/drawWorkloadProxy.slv +++ b/libraries/render-utils/src/drawWorkloadProxy.slv @@ -21,27 +21,27 @@ uniform vec4 inColor; -struct ItemBound { - vec4 id_boundPos; - vec4 boundDim_s; +struct WorkloadProxy { + vec4 sphere; + vec4 region; }; #if defined(GPU_GL410) uniform samplerBuffer ssbo0Buffer; -ItemBound getItemBound(int i) { +WorkloadProxy getWorkloadProxy(int i) { int offset = 2 * i; - ItemBound bound; - bound.id_boundPos = texelFetch(ssbo0Buffer, offset); - bound.boundDim_s = texelFetch(ssbo0Buffer, offset + 1); - return bound; + WorkloadProxy proxy; + proxy.sphere = texelFetch(ssbo0Buffer, offset); + proxy.region = texelFetch(ssbo0Buffer, offset + 1); + return proxy; } #else layout(std140) buffer ssbo0Buffer { - ItemBound bounds[]; + WorkloadProxy proxies[]; }; -ItemBound getItemBound(int i) { - ItemBound bound = bounds[i]; - return bound; +WorkloadProxy getWorkloadProxy(int i) { + WorkloadProxy proxy = proxies[i]; + return proxy; } #endif @@ -76,14 +76,15 @@ void main(void) { 1, 5 ); - int boundID = gl_VertexID / 24; - int vertexID = gl_VertexID - boundID * 24; + int proxyID = gl_VertexID / 24; + int vertexID = gl_VertexID - proxyID * 24; vec4 cubeVec = UNIT_BOX[UNIT_BOX_LINE_INDICES[vertexID]]; - ItemBound bound = getItemBound(boundID); - vec3 boundPos = bound.id_boundPos.yzw; - vec3 boundDim = bound.boundDim_s.xyz; + WorkloadProxy proxy = getWorkloadProxy(proxyID); + vec3 boundPos = proxy.sphere.xyz; + // vec3 boundDim = vec3(proxy.sphere.w); + vec3 boundDim = vec3(0.5); vec4 pos = vec4(boundPos + boundDim * cubeVec.xyz, 1.0); @@ -92,11 +93,8 @@ void main(void) { TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, pos, gl_Position)$> - if (inColor.w < 0.0) { - varColor = vec4(colorWheel(float(boundID)/(-inColor.w)), 1.0); - } else { - varColor = vec4(colorWheel(float(inColor.w)), 1.0); - } + varColor = vec4(colorWheel(float(proxyID)/(-inColor.w)), 1.0); + varTexcoord = vec2(cubeVec.w, length(boundDim)); } \ No newline at end of file diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index d7478b6066..a805d8bacd 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -40,6 +40,8 @@ public: Sphere sphere; uint8_t region { REGION_UNKNOWN }; uint8_t prevRegion { REGION_UNKNOWN }; + uint16_t _padding; + uint32_t _paddings[3]; }; class View { From 1e71e819f4a66146124ec9cc71d3fc0b1254f643 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 22 Feb 2018 12:04:25 -0800 Subject: [PATCH 025/138] update space view according to main ViewFrustum --- interface/src/Application.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0c654e9196..00c4b06378 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4169,6 +4169,14 @@ void Application::idle() { } { + // TEMP HACK: one view with static radiuses + float r0 = 10.0f; + float r1 = 20.0f; + float r2 = 30.0f; + workload::Space::View view(_viewFrustum.getPosition(), r0, r1, r2); + std::vector views; + views.push_back(view); + getEntities()->getWorkloadSpace()->setViews(views); _gameWorkload._engine->run(); } { From c1b8f12b7f81d7d6b08901faf539007668228270 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 22 Feb 2018 13:06:39 -0800 Subject: [PATCH 026/138] compute Space changes --- .../src/workload/ClassificationTracker.cpp | 14 ++++- .../src/workload/ClassificationTracker.h | 2 +- libraries/workload/src/workload/Space.h | 53 ++++++++++++++++--- 3 files changed, 60 insertions(+), 9 deletions(-) diff --git a/libraries/workload/src/workload/ClassificationTracker.cpp b/libraries/workload/src/workload/ClassificationTracker.cpp index 009549737f..15066b1050 100644 --- a/libraries/workload/src/workload/ClassificationTracker.cpp +++ b/libraries/workload/src/workload/ClassificationTracker.cpp @@ -18,7 +18,17 @@ using namespace workload; void ClassificationTracker::configure(const Config& config) { } -void ClassificationTracker::run(const workload::WorkloadContextPointer& renderContext, Outputs& outputs) { - +void ClassificationTracker::run(const WorkloadContextPointer& context, Outputs& outputs) { + auto space = context->_space; + if (space) { + Changes changes; + space->categorizeAndGetChanges(changes); + outputs.resize(workload::Space::NUM_TRANSITIONS); + for (uint32_t i = 0; i < changes.size(); ++i) { + int32_t j = Space::computeTransitionIndex(changes[i].prevRegion, changes[i].region); + assert(j >= 0 && j < workload::Space::NUM_TRANSITIONS); + outputs[j].push_back(changes[i].proxyId); + } + } } diff --git a/libraries/workload/src/workload/ClassificationTracker.h b/libraries/workload/src/workload/ClassificationTracker.h index ca7a919769..e3364950da 100644 --- a/libraries/workload/src/workload/ClassificationTracker.h +++ b/libraries/workload/src/workload/ClassificationTracker.h @@ -29,7 +29,7 @@ namespace workload { class ClassificationTracker { public: using Config = ClassificationTrackerConfig; - using Outputs = Classifications; + using Outputs = SortedChanges; using JobModel = workload::Job::ModelO; ClassificationTracker() {} diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index ee06383288..eef1fc17cd 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -24,6 +24,11 @@ namespace workload { class Space { public: + static const int32_t NUM_CLASSIFICATIONS = 4; + static const int32_t NUM_TRANSITIONS = NUM_CLASSIFICATIONS * (NUM_CLASSIFICATIONS - 1); + + static int32_t computeTransitionIndex(int32_t prevIndex, int32_t newIndex); + static const uint8_t REGION_NEAR = 0; static const uint8_t REGION_MIDDLE = 1; static const uint8_t REGION_FAR = 2; @@ -45,12 +50,12 @@ public: class View { public: View(const glm::vec3& pos, float nearRadius, float midRadius, float farRadius) : center(pos) { - radiuses[0] = nearRadius; - radiuses[1] = midRadius; - radiuses[2] = farRadius; + radiuses[REGION_NEAR] = nearRadius; + radiuses[REGION_MIDDLE] = midRadius; + radiuses[REGION_FAR] = farRadius; } - glm::vec3 center { 0.0f, 0.0f, 0.0f }; - float radiuses[3] { 0.0f, 0.0f, 0.0f }; + glm::vec3 center; + float radiuses[NUM_CLASSIFICATIONS - 1]; }; class Change { @@ -84,8 +89,44 @@ private: std::vector _freeIndices; }; +inline int32_t Space::computeTransitionIndex(int32_t prevIndex, int32_t newIndex) { + // given prevIndex and newIndex compute an index into the transition list, + // where the lists between unchanged indices don't exist (signaled by index = -1). + // + // Given an NxN array + // let p = i + N * j + // + // then k = -1 when i == j + // = p - (1 + p/(N+1)) when i != j + // + // i 0 1 2 3 + // j +-------+-------+-------+-------+ + // |p = 0 | 1 | 2 | 3 | + // 0 | | | | | + // |k = -1 | 0 | 1 | 2 | + // +-------+-------+-------+-------+ + // | 4 | 5 | 6 | 7 | + // 1 | | | | | + // | 3 | -1 | 4 | 5 | + // +-------+-------+-------+-------+ + // | 8 | 9 | 10 | 11 | + // 2 | | | | | + // | 6 | 7 | -1 | 8 | + // +-------+-------+-------+-------+ + // | 12 | 13 | 14 | 15 | + // 3 | | | | | + // | 9 | 10 | 11 | -1 | + // +-------+-------+-------+-------+ + int32_t p = prevIndex + Space::NUM_CLASSIFICATIONS * newIndex; + if (0 == (p % (Space::NUM_CLASSIFICATIONS + 1))) { + return -1; + } + return p - (1 + p / (Space::NUM_CLASSIFICATIONS + 1)); +} + using SpacePointer = std::shared_ptr; -using Classifications = std::vector; +using Changes = std::vector; +using SortedChanges = std::vector>; } // namespace workload From a4442828bef673cc92842e1610b04cf6a72ed6ef Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 22 Feb 2018 14:39:13 -0800 Subject: [PATCH 027/138] fix workoad unit tests --- tests/workload/src/SpaceTests.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/tests/workload/src/SpaceTests.cpp b/tests/workload/src/SpaceTests.cpp index 1c6b0491a7..23e12074ea 100644 --- a/tests/workload/src/SpaceTests.cpp +++ b/tests/workload/src/SpaceTests.cpp @@ -55,7 +55,9 @@ void SpaceTests::testOverlaps() { float newRadius = 1.0f; glm::vec3 newPosition = viewCenter + glm::vec3(0.0f, 0.0f, far + newRadius - DELTA); workload::Space::Sphere newSphere(newPosition, newRadius); - space.updateProxy(proxyId, newSphere); + std::vector updates; + updates.push_back(workload::Space::ProxyUpdate(proxyId, newSphere)); + space.updateProxies(updates); Changes changes; space.categorizeAndGetChanges(changes); QVERIFY(changes.size() == 1); @@ -68,7 +70,9 @@ void SpaceTests::testOverlaps() { float newRadius = 1.0f; glm::vec3 newPosition = viewCenter + glm::vec3(0.0f, 0.0f, mid + newRadius - DELTA); workload::Space::Sphere newSphere(newPosition, newRadius); - space.updateProxy(proxyId, newSphere); + std::vector updates; + updates.push_back(workload::Space::ProxyUpdate(proxyId, newSphere)); + space.updateProxies(updates); Changes changes; space.categorizeAndGetChanges(changes); QVERIFY(changes.size() == 1); @@ -81,7 +85,9 @@ void SpaceTests::testOverlaps() { float newRadius = 1.0f; glm::vec3 newPosition = viewCenter + glm::vec3(0.0f, 0.0f, near + newRadius - DELTA); workload::Space::Sphere newSphere(newPosition, newRadius); - space.updateProxy(proxyId, newSphere); + std::vector updates; + updates.push_back(workload::Space::ProxyUpdate(proxyId, newSphere)); + space.updateProxies(updates); Changes changes; space.categorizeAndGetChanges(changes); QVERIFY(changes.size() == 1); @@ -92,7 +98,9 @@ void SpaceTests::testOverlaps() { { // delete proxy // NOTE: atm deleting a proxy doesn't result in a "Change" - space.deleteProxy(proxyId); + std::vector deadProxies; + deadProxies.push_back(proxyId); + space.deleteProxies(deadProxies); Changes changes; space.categorizeAndGetChanges(changes); QVERIFY(changes.size() == 0); @@ -145,9 +153,9 @@ void SpaceTests::benchmark() { uint32_t numProxies[] = { 100, 1000, 10000, 100000 }; uint32_t numTests = 4; std::vector timeToAddAll; - std::vector timeToRemoveAll; std::vector timeToMoveView; std::vector timeToMoveProxies; + std::vector timeToRemoveAll; for (uint32_t i = 0; i < numTests; ++i) { workload::Space space; From 101872abce79b3f0e15615a3db5742111c283cad Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 22 Feb 2018 16:44:35 -0800 Subject: [PATCH 028/138] Still marinating how to represent the proxy values... --- .../src/workload/GameWorkloadRenderer.cpp | 89 +++++++++++-------- interface/src/workload/GameWorkloadRenderer.h | 3 + .../render-utils/src/drawWorkloadProxy.slf | 12 ++- .../render-utils/src/drawWorkloadProxy.slv | 14 ++- 4 files changed, 77 insertions(+), 41 deletions(-) diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index 569f95364a..b73c6fe309 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -12,6 +12,8 @@ #include #include +#include +#include #include "render-utils/drawWorkloadProxy_vert.h" #include "render-utils/drawWorkloadProxy_frag.h" @@ -21,6 +23,14 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, if (!gameWorkloadContext) { return; } + auto space = gameWorkloadContext->_space; + if (!space) { + return; + } + + std::vector proxies(space->getNumAllocatedProxies()); + space->copyProxyValues(proxies.data(), (uint32_t)proxies.size()); + auto scene = gameWorkloadContext->_scene; @@ -29,31 +39,20 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, if (!render::Item::isValidID(_spaceRenderItemID)) { _spaceRenderItemID = scene->allocateID(); auto renderItem = std::make_shared(); - renderItem->editBound().expandedContains(glm::vec3(0.0f), 32000.0f); - transaction.resetItem(_spaceRenderItemID, std::make_shared(std::make_shared())); - scene->enqueueTransaction(transaction); + renderItem->editBound().setBox(glm::vec3(-100.0f), 200.0f); + renderItem->setAllProxies(proxies); + transaction.resetItem(_spaceRenderItemID, std::make_shared(renderItem)); + } else { + transaction.updateItem(_spaceRenderItemID, [proxies](GameWorkloadRenderItem& item) { + item.setAllProxies(proxies); + }); } - - - auto space = gameWorkloadContext->_space; - if (!space) { - return; - } - - std::vector proxies(space->getNumAllocatedProxies()); - - space->copyProxyValues(proxies.data(), (uint32_t) proxies.size()); - - transaction.updateItem(_spaceRenderItemID, [proxies](GameWorkloadRenderItem& item) { - item.setAllProxies(proxies); - }); scene->enqueueTransaction(transaction); } namespace render { template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload) { - auto builder = ItemKey::Builder().transparentShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); - return builder.build(); + return ItemKey::Builder::opaqueShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); } template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload) { if (payload) { @@ -67,16 +66,18 @@ namespace render { } } template <> const ShapeKey shapeGetShapeKey(const GameWorkloadRenderItem::Pointer& payload) { - if (payload) { - return ShapeKey::Builder::ownPipeline(); - } return ShapeKey::Builder::ownPipeline(); } + template <> int payloadGetLayer(const GameWorkloadRenderItem::Pointer& payloadData) { + return render::Item::LAYER_3D_FRONT; + } + } void GameWorkloadRenderItem::setAllProxies(const std::vector& proxies) { + _myOwnProxies = proxies; static const uint32_t sizeOfProxy = sizeof(workload::Space::Proxy); if (!_allProxiesBuffer) { _allProxiesBuffer = std::make_shared(sizeOfProxy); @@ -97,11 +98,13 @@ const gpu::PipelinePointer GameWorkloadRenderItem::getPipeline() { gpu::Shader::makeProgram(*program, slotBindings); auto state = std::make_shared(); - /* state->setDepthTest(true, false, gpu::LESS_EQUAL); - state->setBlendFunction(true, + state->setDepthTest(true, false, gpu::LESS_EQUAL); + /* state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); -*/ + gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO);*/ + + PrepareStencil::testMaskDrawShape(*state); + state->setCullMode(gpu::State::CULL_NONE); _drawAllProxiesPipeline = gpu::Pipeline::create(program, state); } return _drawAllProxiesPipeline; @@ -111,23 +114,39 @@ void GameWorkloadRenderItem::render(RenderArgs* args) { gpu::Batch& batch = *(args->_batch); // Setup projection - // glm::mat4 projMat; - // Transform viewMat; - // args->getViewFrustum().evalProjectionMatrix(projMat); - // args->getViewFrustum().evalViewTransform(viewMat); - // batch.setProjectionTransform(projMat); - // batch.setViewTransform(viewMat); + glm::mat4 projMat; + Transform viewMat; + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); batch.setModelTransform(Transform()); - + // Bind program batch.setPipeline(getPipeline()); batch.setResourceBuffer(0, _allProxiesBuffer); - static const int NUM_VERTICES_PER_QUAD = 24; - batch.draw(gpu::LINES, NUM_VERTICES_PER_QUAD * _numAllProxies, 0); + static const int NUM_VERTICES_PER_QUAD = 6; + batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_QUAD * _numAllProxies, 0); batch.setResourceBuffer(0, nullptr); + + +/* + auto geometryCache = DependencyManager::get(); + GeometryCache::Shape geometryShape; + glm::vec4 outColor; + geometryShape = GeometryCache::Sphere; +// geometryCache->renderShape(batch, geometryShape, outColor); + + auto pipeline = geometryCache->getOpaqueShapePipeline(); + + for (int i = 0; i < _numAllProxies; i++) { + auto sphere = _myOwnProxies[i].sphere; + batch.setModelTransform(Transform(glm::quat(), glm::vec3(1.0), glm::vec3(sphere.x, sphere.y, sphere.z))); + geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline); + }*/ } diff --git a/interface/src/workload/GameWorkloadRenderer.h b/interface/src/workload/GameWorkloadRenderer.h index 74e19825b5..10c5c088f2 100644 --- a/interface/src/workload/GameWorkloadRenderer.h +++ b/interface/src/workload/GameWorkloadRenderer.h @@ -45,6 +45,7 @@ public: protected: render::Item::Bound _bound; + std::vector _myOwnProxies; gpu::BufferPointer _allProxiesBuffer; uint32_t _numAllProxies{ 0 }; @@ -60,6 +61,8 @@ namespace render { template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload); template <> void payloadRender(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args); template <> const ShapeKey shapeGetShapeKey(const GameWorkloadRenderItem::Pointer& payload); + template <> int payloadGetLayer(const GameWorkloadRenderItem::Pointer& payloadData); + } diff --git a/libraries/render-utils/src/drawWorkloadProxy.slf b/libraries/render-utils/src/drawWorkloadProxy.slf index 36606b8afc..2342f2d21b 100644 --- a/libraries/render-utils/src/drawWorkloadProxy.slf +++ b/libraries/render-utils/src/drawWorkloadProxy.slf @@ -10,14 +10,15 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include DeferredBufferWrite.slh@> in vec4 varColor; in vec2 varTexcoord; -out vec4 outFragColor; +//out vec4 outFragColor; void main(void) { - outFragColor = vec4(1.0); - /* + /* outFragColor = vec4(1.0); + float var = step(fract(varTexcoord.x * varTexcoord.y * 1.0), 0.5); if (varColor.a == 0.0) { @@ -27,4 +28,9 @@ void main(void) { outFragColor = vec4(mix(vec3(1.0), varColor.xyz, var), varColor.a); }*/ + + packDeferredFragmentUnlit( + vec3(0.0, 1.0, 0.0), + 1.0, + vec3(1.0)); } diff --git a/libraries/render-utils/src/drawWorkloadProxy.slv b/libraries/render-utils/src/drawWorkloadProxy.slv index 444f4c0917..a5b7f371f4 100644 --- a/libraries/render-utils/src/drawWorkloadProxy.slv +++ b/libraries/render-utils/src/drawWorkloadProxy.slv @@ -61,7 +61,7 @@ void main(void) { vec4(0.0, 1.0, 1.0, 2.0), vec4(1.0, 1.0, 1.0, 3.0) ); - const int UNIT_BOX_LINE_INDICES[24] = int[24]( +/* const int UNIT_BOX_LINE_INDICES[24] = int[24]( 0, 1, 1, 3, 3, 2, @@ -77,7 +77,15 @@ void main(void) { ); int proxyID = gl_VertexID / 24; - int vertexID = gl_VertexID - proxyID * 24; + int vertexID = gl_VertexID - proxyID * 24;*/ + + const int UNIT_BOX_LINE_INDICES[6] = int[6]( + 0, 1, 2, + 2, 1, 3 + ); + + int proxyID = gl_VertexID / 6; + int vertexID = gl_VertexID - proxyID * 6; vec4 cubeVec = UNIT_BOX[UNIT_BOX_LINE_INDICES[vertexID]]; @@ -97,4 +105,4 @@ void main(void) { varTexcoord = vec2(cubeVec.w, length(boundDim)); -} \ No newline at end of file +} From 3360c5a968ab8f2df429eec039850aaafaea6f29 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 27 Feb 2018 18:46:12 -0800 Subject: [PATCH 029/138] Debugging the ssbo bug --- interface/src/workload/GameWorkloadRenderer.cpp | 13 +++++++------ libraries/render-utils/src/drawWorkloadProxy.slv | 14 ++++++++++---- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index b73c6fe309..e3e58139df 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -94,7 +94,7 @@ const gpu::PipelinePointer GameWorkloadRenderItem::getPipeline() { gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding("ssbo0Buffer", 0)); + slotBindings.insert(gpu::Shader::Binding("ssbo0Buffer", 11)); gpu::Shader::makeProgram(*program, slotBindings); auto state = std::make_shared(); @@ -121,17 +121,18 @@ void GameWorkloadRenderItem::render(RenderArgs* args) { batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); batch.setModelTransform(Transform()); - + // Bind program batch.setPipeline(getPipeline()); - batch.setResourceBuffer(0, _allProxiesBuffer); + // batch.setResourceBuffer(11, _allProxiesBuffer); + batch.setUniformBuffer(11, _allProxiesBuffer); - static const int NUM_VERTICES_PER_QUAD = 6; + static const int NUM_VERTICES_PER_QUAD = 3; batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_QUAD * _numAllProxies, 0); - batch.setResourceBuffer(0, nullptr); - + // batch.setResourceBuffer(11, nullptr); + batch.setUniformBuffer(11, nullptr); /* auto geometryCache = DependencyManager::get(); diff --git a/libraries/render-utils/src/drawWorkloadProxy.slv b/libraries/render-utils/src/drawWorkloadProxy.slv index a5b7f371f4..db0f04ce63 100644 --- a/libraries/render-utils/src/drawWorkloadProxy.slv +++ b/libraries/render-utils/src/drawWorkloadProxy.slv @@ -25,7 +25,7 @@ struct WorkloadProxy { vec4 sphere; vec4 region; }; - +/* #if defined(GPU_GL410) uniform samplerBuffer ssbo0Buffer; WorkloadProxy getWorkloadProxy(int i) { @@ -44,7 +44,13 @@ WorkloadProxy getWorkloadProxy(int i) { return proxy; } #endif - +*/ +uniform ssbo0Buffer { + WorkloadProxy proxies[1024]; +}; +WorkloadProxy getWorkloadProxy(int index) { + return proxies[index]; +} out vec4 varColor; @@ -84,8 +90,8 @@ void main(void) { 2, 1, 3 ); - int proxyID = gl_VertexID / 6; - int vertexID = gl_VertexID - proxyID * 6; + int proxyID = gl_VertexID / 3; + int vertexID = gl_VertexID - proxyID * 3; vec4 cubeVec = UNIT_BOX[UNIT_BOX_LINE_INDICES[vertexID]]; From 31462a87c3ea9f31cff2d48fb0cb6315f5c1edba Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 28 Feb 2018 10:13:13 -0800 Subject: [PATCH 030/138] now identifying the issue with ResourceBUffer --- interface/src/workload/GameWorkloadRenderer.cpp | 8 ++++---- libraries/render-utils/src/drawWorkloadProxy.slv | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index e3e58139df..9d0fce9713 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -125,14 +125,14 @@ void GameWorkloadRenderItem::render(RenderArgs* args) { // Bind program batch.setPipeline(getPipeline()); - // batch.setResourceBuffer(11, _allProxiesBuffer); - batch.setUniformBuffer(11, _allProxiesBuffer); + batch.setResourceBuffer(11, _allProxiesBuffer); + // batch.setUniformBuffer(11, _allProxiesBuffer); static const int NUM_VERTICES_PER_QUAD = 3; batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_QUAD * _numAllProxies, 0); - // batch.setResourceBuffer(11, nullptr); - batch.setUniformBuffer(11, nullptr); + batch.setResourceBuffer(11, nullptr); + // batch.setUniformBuffer(11, nullptr); /* auto geometryCache = DependencyManager::get(); diff --git a/libraries/render-utils/src/drawWorkloadProxy.slv b/libraries/render-utils/src/drawWorkloadProxy.slv index db0f04ce63..486f5ab2f2 100644 --- a/libraries/render-utils/src/drawWorkloadProxy.slv +++ b/libraries/render-utils/src/drawWorkloadProxy.slv @@ -25,7 +25,7 @@ struct WorkloadProxy { vec4 sphere; vec4 region; }; -/* + #if defined(GPU_GL410) uniform samplerBuffer ssbo0Buffer; WorkloadProxy getWorkloadProxy(int i) { @@ -44,13 +44,13 @@ WorkloadProxy getWorkloadProxy(int i) { return proxy; } #endif -*/ +/* uniform ssbo0Buffer { WorkloadProxy proxies[1024]; }; WorkloadProxy getWorkloadProxy(int index) { return proxies[index]; -} +}*/ out vec4 varColor; From d91fb543f33a37cb9489bed0d0779032fbf21895 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 28 Feb 2018 17:15:40 -0800 Subject: [PATCH 031/138] Fix the ssbo in GL4.5 and represent the workload proxies of the space and expose the workload engine to the JS api --- interface/src/Application.cpp | 2 + interface/src/workload/GameWorkload.cpp | 2 + .../src/workload/GameWorkloadRenderer.cpp | 55 ++++++------ interface/src/workload/GameWorkloadRenderer.h | 18 +++- .../gpu-gl/src/gpu/gl45/GL45BackendShader.cpp | 4 +- .../render-utils/src/drawWorkloadProxy.slf | 20 ++--- .../render-utils/src/drawWorkloadProxy.slv | 83 +++++++------------ 7 files changed, 88 insertions(+), 96 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eedf541086..400c135b78 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2701,6 +2701,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) { surfaceContext->setContextProperty("HMD", DependencyManager::get().data()); surfaceContext->setContextProperty("Scene", DependencyManager::get().data()); surfaceContext->setContextProperty("Render", _renderEngine->getConfiguration().get()); + surfaceContext->setContextProperty("Workload", _gameWorkload._engine->getConfiguration().get()); surfaceContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface()); surfaceContext->setContextProperty("Snapshot", DependencyManager::get().data()); @@ -6109,6 +6110,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe scriptEngine->registerGlobalObject("Scene", DependencyManager::get().data()); scriptEngine->registerGlobalObject("Render", _renderEngine->getConfiguration().get()); + scriptEngine->registerGlobalObject("Workload", _gameWorkload._engine->getConfiguration().get()); GraphicsScriptingInterface::registerMetaTypes(scriptEngine.data()); scriptEngine->registerGlobalObject("Graphics", DependencyManager::get().data()); diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 0113e0568d..7fc7a38fc7 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -28,6 +28,8 @@ void GameWorkload::startup(const workload::SpacePointer& space, const render::Sc _engine.reset(new workload::Engine(std::make_shared(space, scene))); _engine->addJob("SpaceToRender"); + + } void GameWorkload::shutdown() { diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index 9d0fce9713..09235d71ea 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -18,6 +18,11 @@ #include "render-utils/drawWorkloadProxy_vert.h" #include "render-utils/drawWorkloadProxy_frag.h" + +void GameSpaceToRender::configure(const Config& config) { + _showAllWorkspace = config.showAllWorkspace; +} + void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, Outputs& outputs) { auto gameWorkloadContext = std::dynamic_pointer_cast(runContext); if (!gameWorkloadContext) { @@ -28,6 +33,19 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, return; } + auto visible = _showAllWorkspace; + render::Transaction transaction; + + // Nothing really needed, early exit + if (!visible) { + if (render::Item::isValidID(_spaceRenderItemID)) { + transaction.updateItem(_spaceRenderItemID, [](GameWorkloadRenderItem& item) { + item.setVisible(false); + }); + } + return; + } + std::vector proxies(space->getNumAllocatedProxies()); space->copyProxyValues(proxies.data(), (uint32_t)proxies.size()); @@ -35,15 +53,16 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, auto scene = gameWorkloadContext->_scene; // Valid space, let's display its content - render::Transaction transaction; if (!render::Item::isValidID(_spaceRenderItemID)) { _spaceRenderItemID = scene->allocateID(); auto renderItem = std::make_shared(); renderItem->editBound().setBox(glm::vec3(-100.0f), 200.0f); + renderItem->setVisible(visible); renderItem->setAllProxies(proxies); transaction.resetItem(_spaceRenderItemID, std::make_shared(renderItem)); } else { - transaction.updateItem(_spaceRenderItemID, [proxies](GameWorkloadRenderItem& item) { + transaction.updateItem(_spaceRenderItemID, [visible, proxies](GameWorkloadRenderItem& item) { + item.setVisible(visible); item.setAllProxies(proxies); }); } @@ -52,7 +71,11 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, namespace render { template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload) { - return ItemKey::Builder::opaqueShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); + auto key = ItemKey::Builder::opaqueShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); + if (!payload->isVisible()) { + key.withInvisible(); + } + return key; } template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload) { if (payload) { @@ -74,8 +97,6 @@ namespace render { } - - void GameWorkloadRenderItem::setAllProxies(const std::vector& proxies) { _myOwnProxies = proxies; static const uint32_t sizeOfProxy = sizeof(workload::Space::Proxy); @@ -94,11 +115,11 @@ const gpu::PipelinePointer GameWorkloadRenderItem::getPipeline() { gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding("ssbo0Buffer", 11)); + slotBindings.insert(gpu::Shader::Binding("workloadProxiesBuffer", 0)); gpu::Shader::makeProgram(*program, slotBindings); auto state = std::make_shared(); - state->setDepthTest(true, false, gpu::LESS_EQUAL); + state->setDepthTest(true, true, gpu::LESS_EQUAL); /* state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO);*/ @@ -125,30 +146,12 @@ void GameWorkloadRenderItem::render(RenderArgs* args) { // Bind program batch.setPipeline(getPipeline()); - batch.setResourceBuffer(11, _allProxiesBuffer); - // batch.setUniformBuffer(11, _allProxiesBuffer); + batch.setResourceBuffer(0, _allProxiesBuffer); static const int NUM_VERTICES_PER_QUAD = 3; batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_QUAD * _numAllProxies, 0); batch.setResourceBuffer(11, nullptr); - // batch.setUniformBuffer(11, nullptr); - -/* - auto geometryCache = DependencyManager::get(); - GeometryCache::Shape geometryShape; - glm::vec4 outColor; - geometryShape = GeometryCache::Sphere; -// geometryCache->renderShape(batch, geometryShape, outColor); - - auto pipeline = geometryCache->getOpaqueShapePipeline(); - - for (int i = 0; i < _numAllProxies; i++) { - auto sphere = _myOwnProxies[i].sphere; - batch.setModelTransform(Transform(glm::quat(), glm::vec3(1.0), glm::vec3(sphere.x, sphere.y, sphere.z))); - geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline); - }*/ - } diff --git a/interface/src/workload/GameWorkloadRenderer.h b/interface/src/workload/GameWorkloadRenderer.h index 10c5c088f2..dd568eadec 100644 --- a/interface/src/workload/GameWorkloadRenderer.h +++ b/interface/src/workload/GameWorkloadRenderer.h @@ -12,16 +12,32 @@ #include "GameWorkload.h" +class GameSpaceToRenderConfig : public workload::Job::Config { + Q_OBJECT + Q_PROPERTY(bool showAllWorkspace MEMBER showAllWorkspace NOTIFY dirty) +public: + + bool showAllWorkspace{ false }; +signals: + void dirty(); + +protected: +}; + class GameSpaceToRender { public: + using Config = GameSpaceToRenderConfig; using Outputs = render::Transaction; - using JobModel = workload::Job::ModelO; + using JobModel = workload::Job::ModelO; GameSpaceToRender() {} + + void configure(const Config& config); void run(const workload::WorkloadContextPointer& renderContext, Outputs& outputs); protected: render::ItemID _spaceRenderItemID{ render::Item::INVALID_ITEM_ID }; + bool _showAllWorkspace{ false }; }; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendShader.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendShader.cpp index c2490524ae..80860edcbd 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendShader.cpp @@ -70,7 +70,7 @@ int GL45Backend::makeResourceBufferSlots(GLuint glprogram, const Shader::Binding auto requestedBinding = slotBindings.find(info.name); if (requestedBinding != slotBindings.end()) { info.binding = (*requestedBinding)._location; - glUniformBlockBinding(glprogram, info.index, info.binding); + glShaderStorageBlockBinding(glprogram, info.index, info.binding); resourceBufferSlotMap[info.binding] = info.index; } } @@ -86,7 +86,7 @@ int GL45Backend::makeResourceBufferSlots(GLuint glprogram, const Shader::Binding auto slotIt = std::find_if(resourceBufferSlotMap.begin(), resourceBufferSlotMap.end(), GLBackend::isUnusedSlot); if (slotIt != resourceBufferSlotMap.end()) { info.binding = slotIt - resourceBufferSlotMap.begin(); - glUniformBlockBinding(glprogram, info.index, info.binding); + glShaderStorageBlockBinding(glprogram, info.index, info.binding); } else { // This should never happen, an active ssbo cannot find an available slot among the max available?! info.binding = -1; diff --git a/libraries/render-utils/src/drawWorkloadProxy.slf b/libraries/render-utils/src/drawWorkloadProxy.slf index 2342f2d21b..cd02066caf 100644 --- a/libraries/render-utils/src/drawWorkloadProxy.slf +++ b/libraries/render-utils/src/drawWorkloadProxy.slf @@ -11,26 +11,20 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // <@include DeferredBufferWrite.slh@> +<@include gpu/Paint.slh@> in vec4 varColor; in vec2 varTexcoord; -//out vec4 outFragColor; void main(void) { - /* outFragColor = vec4(1.0); + float r = sqrt(dot(varTexcoord.xy,varTexcoord.xy)); + float a = paintStripe(r * varColor.w, 0.0, 1.0 / varColor.w, 0.05 / varColor.w); + if (a <= 0.1 || r > 1.1) { + discard; + } - float var = step(fract(varTexcoord.x * varTexcoord.y * 1.0), 0.5); - - if (varColor.a == 0.0) { - outFragColor = vec4(mix(vec3(0.0), varColor.xyz, var), mix(0.0, 1.0, var)); - - } else { - outFragColor = vec4(mix(vec3(1.0), varColor.xyz, var), varColor.a); - }*/ - - packDeferredFragmentUnlit( vec3(0.0, 1.0, 0.0), 1.0, - vec3(1.0)); + varColor.rgb); } diff --git a/libraries/render-utils/src/drawWorkloadProxy.slv b/libraries/render-utils/src/drawWorkloadProxy.slv index 486f5ab2f2..aaa9073fdc 100644 --- a/libraries/render-utils/src/drawWorkloadProxy.slv +++ b/libraries/render-utils/src/drawWorkloadProxy.slv @@ -27,88 +27,63 @@ struct WorkloadProxy { }; #if defined(GPU_GL410) -uniform samplerBuffer ssbo0Buffer; +uniform samplerBuffer workloadProxiesBuffer; WorkloadProxy getWorkloadProxy(int i) { int offset = 2 * i; WorkloadProxy proxy; - proxy.sphere = texelFetch(ssbo0Buffer, offset); - proxy.region = texelFetch(ssbo0Buffer, offset + 1); + proxy.sphere = texelFetch(workloadProxiesBuffer, offset); + proxy.region = texelFetch(workloadProxiesBuffer, offset + 1); return proxy; } #else -layout(std140) buffer ssbo0Buffer { - WorkloadProxy proxies[]; +layout(std140) buffer workloadProxiesBuffer { + WorkloadProxy _proxies[]; }; WorkloadProxy getWorkloadProxy(int i) { - WorkloadProxy proxy = proxies[i]; + WorkloadProxy proxy = _proxies[i]; return proxy; } #endif -/* -uniform ssbo0Buffer { - WorkloadProxy proxies[1024]; -}; -WorkloadProxy getWorkloadProxy(int index) { - return proxies[index]; -}*/ + out vec4 varColor; out vec2 varTexcoord; void main(void) { - const vec4 UNIT_BOX[8] = vec4[8]( - vec4(0.0, 0.0, 0.0, 0.0), - vec4(1.0, 0.0, 0.0, 1.0), - vec4(0.0, 1.0, 0.0, 1.0), - vec4(1.0, 1.0, 0.0, 2.0), - vec4(0.0, 0.0, 1.0, 1.0), - vec4(1.0, 0.0, 1.0, 2.0), - vec4(0.0, 1.0, 1.0, 2.0), - vec4(1.0, 1.0, 1.0, 3.0) + const vec4 UNIT_SPRITE[3] = vec4[3]( + vec4(-1.0, -1.0, 0.0, 1.0), + vec4(3.0, -1.0, 0.0, 1.0), + vec4(-1.0, 3.0, 0.0, 1.0) ); -/* const int UNIT_BOX_LINE_INDICES[24] = int[24]( - 0, 1, - 1, 3, - 3, 2, - 2, 0, - 4, 5, - 5, 7, - 7, 6, - 6, 4, - 2, 6, - 3, 7, - 0, 4, - 1, 5 + const int UNIT_SPRITE_INDICES[3] = int[3]( + 0, 1, 2 ); - - int proxyID = gl_VertexID / 24; - int vertexID = gl_VertexID - proxyID * 24;*/ - - const int UNIT_BOX_LINE_INDICES[6] = int[6]( - 0, 1, 2, - 2, 1, 3 - ); - int proxyID = gl_VertexID / 3; int vertexID = gl_VertexID - proxyID * 3; - vec4 cubeVec = UNIT_BOX[UNIT_BOX_LINE_INDICES[vertexID]]; + vec4 spriteVert = UNIT_SPRITE[UNIT_SPRITE_INDICES[vertexID]]; WorkloadProxy proxy = getWorkloadProxy(proxyID); - vec3 boundPos = proxy.sphere.xyz; - // vec3 boundDim = vec3(proxy.sphere.w); - vec3 boundDim = vec3(0.5); + vec4 proxyPosWorld = vec4(proxy.sphere.xyz, 1.0); - vec4 pos = vec4(boundPos + boundDim * cubeVec.xyz, 1.0); - - // standard transform + // standard transform, bring proxy in view space TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, pos, gl_Position)$> + vec4 proxyPosEye; + <$transformModelToEyePos(cam, obj, proxyPosWorld, proxyPosEye)$> - varColor = vec4(colorWheel(float(proxyID)/(-inColor.w)), 1.0); + // Define the billboarded space + vec3 dirZ = -normalize(proxyPosEye.xyz); + vec3 dirX = normalize(cross(vec3(0.0, 1.0, 0.0), dirZ)); + vec3 dirY = vec3(0.0, 1.0, 0.0); + // vec3 dirY = normalize(cross(dirZ, vec3(1.0, 0.0, 0.0))); - varTexcoord = vec2(cubeVec.w, length(boundDim)); + vec4 pos = vec4(proxyPosEye.xyz + proxy.sphere.w * ( dirX * spriteVert.x + dirY * spriteVert.y /* + dirZ * spriteVert.z*/), 1.0); + varTexcoord = spriteVert.xy; + <$transformEyeToClipPos(cam, pos, gl_Position)$> + // Convert region to color + + varColor = vec4(colorWheel(proxy.region.x), proxy.sphere.w); } From b1b539e07a062d62ffb3d1c083808634b20bf163 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 28 Feb 2018 17:56:37 -0800 Subject: [PATCH 032/138] Adding debug color of the region --- libraries/render-utils/src/drawWorkloadProxy.slv | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/drawWorkloadProxy.slv b/libraries/render-utils/src/drawWorkloadProxy.slv index aaa9073fdc..2f14045d3a 100644 --- a/libraries/render-utils/src/drawWorkloadProxy.slv +++ b/libraries/render-utils/src/drawWorkloadProxy.slv @@ -84,6 +84,8 @@ void main(void) { <$transformEyeToClipPos(cam, pos, gl_Position)$> // Convert region to color + int region = floatBitsToInt(proxy.region.x); + region = (0x000000FF & region); - varColor = vec4(colorWheel(proxy.region.x), proxy.sphere.w); + varColor = vec4(float(region) / 4.0, proxy.sphere.w); } From 94fa2ef6a0f86b83a458c7a3540abc2c7cec938e Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 28 Feb 2018 17:59:59 -0800 Subject: [PATCH 033/138] Adding debug color of the region --- libraries/render-utils/src/drawWorkloadProxy.slv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/drawWorkloadProxy.slv b/libraries/render-utils/src/drawWorkloadProxy.slv index 2f14045d3a..ac83e7761a 100644 --- a/libraries/render-utils/src/drawWorkloadProxy.slv +++ b/libraries/render-utils/src/drawWorkloadProxy.slv @@ -87,5 +87,5 @@ void main(void) { int region = floatBitsToInt(proxy.region.x); region = (0x000000FF & region); - varColor = vec4(float(region) / 4.0, proxy.sphere.w); + varColor = vec4(colorWheel(float(region) / 4.0), proxy.sphere.w); } From 67c78a2df128c841f6f37f8445e6878c73a44476 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 1 Mar 2018 09:26:52 -0800 Subject: [PATCH 034/138] remember list of stale proxies --- .../src/entities/EntityTreeHeadlessViewer.cpp | 4 ---- .../entities-renderer/src/EntityTreeRenderer.cpp | 16 +++++----------- libraries/entities/src/EntityTree.cpp | 11 ++++++----- libraries/entities/src/EntityTree.h | 4 ++-- 4 files changed, 13 insertions(+), 22 deletions(-) diff --git a/assignment-client/src/entities/EntityTreeHeadlessViewer.cpp b/assignment-client/src/entities/EntityTreeHeadlessViewer.cpp index d22055b349..81c42cda1e 100644 --- a/assignment-client/src/entities/EntityTreeHeadlessViewer.cpp +++ b/assignment-client/src/entities/EntityTreeHeadlessViewer.cpp @@ -35,10 +35,6 @@ void EntityTreeHeadlessViewer::update() { EntityTreePointer tree = std::static_pointer_cast(_tree); tree->withTryWriteLock([&] { tree->update(); - - // flush final EntityTree references to deleted entities - std::vector deletedEntities; - tree->swapRemovedEntities(deletedEntities); }); } } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index eecd21e5ac..78279fbec8 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -431,18 +431,12 @@ void EntityTreeRenderer::update(bool simulate) { _space->updateProxies(_spaceUpdates); _spaceUpdates.clear(); } - { // flush final EntityTree references to removed entities - std::vector deletedEntities; - tree->swapRemovedEntities(deletedEntities); - { // delete proxies from workload::Space - std::vector deadProxies; + { + std::vector staleProxies; + tree->swapStaleProxies(staleProxies); + { std::unique_lock lock(_spaceLock); - for (auto entity : deletedEntities) { - int32_t spaceIndex = entity->getSpaceIndex(); - disconnect(entity.get(), &EntityItem::spaceUpdate, this, &EntityTreeRenderer::handleSpaceUpdate); - deadProxies.push_back(spaceIndex); - } - _space->deleteProxies(deadProxies); + _space->deleteProxies(staleProxies); } } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 27ec868fcf..7fd1625cd5 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -697,10 +697,11 @@ void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator) _simulation->prepareEntityForDelete(theEntity); } - // We save a pointer to theEntity for external contexts that need it - // but this means: external contexts that remove entities from the tree - // must occasionally swapRemovedEntities() to flush these references. - _removedEntities.push_back(theEntity); + // keep a record of valid stale spaceIndices so they can be removed from the Space + int32_t spaceIndex = theEntity->getSpaceIndex(); + if (spaceIndex != -1) { + _staleProxies.push_back(spaceIndex); + } } } @@ -2476,4 +2477,4 @@ bool EntityTree::removeMaterialFromOverlay(const QUuid& overlayID, graphics::Mat return _removeMaterialFromOverlayOperator(overlayID, material, parentMaterialName); } return false; -} \ No newline at end of file +} diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 17eb360f86..330717bac0 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -283,7 +283,7 @@ public: void setMyAvatar(std::shared_ptr myAvatar) { _myAvatar = myAvatar; } - void swapRemovedEntities(std::vector& entities) { entities.swap(_removedEntities); } + void swapStaleProxies(std::vector& proxies) { proxies.swap(_staleProxies); } static void setAddMaterialToEntityOperator(std::function addMaterialToEntityOperator) { _addMaterialToEntityOperator = addMaterialToEntityOperator; } static void setRemoveMaterialFromEntityOperator(std::function removeMaterialFromEntityOperator) { _removeMaterialFromEntityOperator = removeMaterialFromEntityOperator; } @@ -415,7 +415,7 @@ private: static std::function _addMaterialToOverlayOperator; static std::function _removeMaterialFromOverlayOperator; - std::vector _removedEntities; + std::vector _staleProxies; }; #endif // hifi_EntityTree_h From 18a6ac057a773ac2dd131f5ced33534ccafc7304 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 1 Mar 2018 12:09:28 -0800 Subject: [PATCH 035/138] add Space::clear() method --- libraries/workload/src/workload/Space.cpp | 5 +++++ libraries/workload/src/workload/Space.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index e9745e0916..016b246725 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -20,6 +20,11 @@ using namespace workload; +void Space::clear() { + _proxies.clear(); + _freeIndices.clear(); +} + int32_t Space::createProxy(const Space::Sphere& newSphere) { if (_freeIndices.empty()) { _proxies.emplace_back(Space::Proxy(newSphere)); diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index fb102d49a0..46ea8651bf 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -70,6 +70,7 @@ public: Space() {} + void clear(); int32_t createProxy(const Sphere& sphere); void deleteProxies(const std::vector& deadIndices); void updateProxies(const std::vector& changedProxies); @@ -79,7 +80,6 @@ public: uint32_t getNumAllocatedProxies() const { return (uint32_t)(_proxies.size()); } void categorizeAndGetChanges(std::vector& changes); - uint32_t copyProxyValues(Proxy* proxies, uint32_t numDestProxies); private: From 7a852a0e31655d8d75de965ff91b0c64a7b6d910 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 1 Mar 2018 12:11:30 -0800 Subject: [PATCH 036/138] clear the Space --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 78279fbec8..04e8c9a414 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -194,6 +194,7 @@ void EntityTreeRenderer::clear() { } // remove all entities from the scene + _space->clear(); auto scene = _viewState->getMain3DScene(); if (scene) { render::Transaction transaction; From 1e1d9907a4840835834d37321e30513c7f3f1850 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 1 Mar 2018 12:22:42 -0800 Subject: [PATCH 037/138] also clear _staleProxies when clearing all else --- libraries/entities/src/EntityTree.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 7fd1625cd5..da80924184 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -98,6 +98,7 @@ void EntityTree::eraseAllOctreeElements(bool createNewRoot) { if (_simulation) { _simulation->clearEntities(); } + _staleProxies.clear(); QHash localMap; localMap.swap(_entityMap); this->withWriteLock([&] { From 3a9a93f502bd3e32d316c2f2acbfa0ddc94357bc Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 1 Mar 2018 13:40:58 -0800 Subject: [PATCH 038/138] Introducing a ui app for debugging the workload and fixing the vissible/invisisble behavior of the render item --- .../src/workload/GameWorkloadRenderer.cpp | 28 +++++-- interface/src/workload/GameWorkloadRenderer.h | 14 ++-- libraries/render/src/render/Item.h | 1 + .../developer/utilities/workload/workload.js | 83 +++++++++++++++++++ .../developer/utilities/workload/workload.qml | 40 +++++++++ 5 files changed, 152 insertions(+), 14 deletions(-) create mode 100644 scripts/developer/utilities/workload/workload.js create mode 100644 scripts/developer/utilities/workload/workload.qml diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index 09235d71ea..bb6aa35257 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -20,7 +20,7 @@ void GameSpaceToRender::configure(const Config& config) { - _showAllWorkspace = config.showAllWorkspace; + _showAllProxies = config.showAllProxies; } void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, Outputs& outputs) { @@ -33,8 +33,9 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, return; } - auto visible = _showAllWorkspace; + auto visible = _showAllProxies; render::Transaction transaction; + auto scene = gameWorkloadContext->_scene; // Nothing really needed, early exit if (!visible) { @@ -42,6 +43,7 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, transaction.updateItem(_spaceRenderItemID, [](GameWorkloadRenderItem& item) { item.setVisible(false); }); + scene->enqueueTransaction(transaction); } return; } @@ -50,7 +52,6 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, space->copyProxyValues(proxies.data(), (uint32_t)proxies.size()); - auto scene = gameWorkloadContext->_scene; // Valid space, let's display its content if (!render::Item::isValidID(_spaceRenderItemID)) { @@ -71,11 +72,7 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, namespace render { template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload) { - auto key = ItemKey::Builder::opaqueShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); - if (!payload->isVisible()) { - key.withInvisible(); - } - return key; + return payload->getKey(); } template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload) { if (payload) { @@ -97,6 +94,21 @@ namespace render { } +GameWorkloadRenderItem::GameWorkloadRenderItem() : _key(render::ItemKey::Builder::opaqueShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1)) { +} + +render::ItemKey GameWorkloadRenderItem::getKey() const { + return _key; +} + +void GameWorkloadRenderItem::setVisible(bool isVisible) { + if (isVisible) { + _key = render::ItemKey::Builder(_key).withVisible(); + } else { + _key = render::ItemKey::Builder(_key).withInvisible(); + } +} + void GameWorkloadRenderItem::setAllProxies(const std::vector& proxies) { _myOwnProxies = proxies; static const uint32_t sizeOfProxy = sizeof(workload::Space::Proxy); diff --git a/interface/src/workload/GameWorkloadRenderer.h b/interface/src/workload/GameWorkloadRenderer.h index dd568eadec..dc0fb9f3a1 100644 --- a/interface/src/workload/GameWorkloadRenderer.h +++ b/interface/src/workload/GameWorkloadRenderer.h @@ -14,10 +14,10 @@ class GameSpaceToRenderConfig : public workload::Job::Config { Q_OBJECT - Q_PROPERTY(bool showAllWorkspace MEMBER showAllWorkspace NOTIFY dirty) + Q_PROPERTY(bool showAllProxies MEMBER showAllProxies NOTIFY dirty) public: - bool showAllWorkspace{ false }; + bool showAllProxies{ false }; signals: void dirty(); @@ -37,7 +37,7 @@ public: protected: render::ItemID _spaceRenderItemID{ render::Item::INVALID_ITEM_ID }; - bool _showAllWorkspace{ false }; + bool _showAllProxies{ false }; }; @@ -46,18 +46,19 @@ public: using Payload = render::Payload; using Pointer = Payload::DataPointer; - GameWorkloadRenderItem() {} + GameWorkloadRenderItem(); ~GameWorkloadRenderItem() {} void render(RenderArgs* args); render::Item::Bound& editBound() { _needUpdate = true; return _bound; } const render::Item::Bound& getBound() { return _bound; } - void setVisible(bool visible) { _isVisible = visible; } - bool isVisible() const { return _isVisible; } + void setVisible(bool visible); void setAllProxies(const std::vector& proxies); + render::ItemKey getKey() const; + protected: render::Item::Bound _bound; @@ -68,6 +69,7 @@ protected: gpu::PipelinePointer _drawAllProxiesPipeline; const gpu::PipelinePointer getPipeline(); + render::ItemKey _key; bool _needUpdate{ true }; bool _isVisible{ true }; }; diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index e4dcc7ee03..b8a3fbf0f8 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -122,6 +122,7 @@ public: Builder& withDynamic() { _flags.set(DYNAMIC); return (*this); } Builder& withDeformed() { _flags.set(DEFORMED); return (*this); } Builder& withInvisible() { _flags.set(INVISIBLE); return (*this); } + Builder& withVisible() { _flags.reset(INVISIBLE); return (*this); } Builder& withShadowCaster() { _flags.set(SHADOW_CASTER); return (*this); } Builder& withLayered() { _flags.set(LAYERED); return (*this); } Builder& withMetaCullGroup() { _flags.set(META_CULL_GROUP); return (*this); } diff --git a/scripts/developer/utilities/workload/workload.js b/scripts/developer/utilities/workload/workload.js new file mode 100644 index 0000000000..10ca43821f --- /dev/null +++ b/scripts/developer/utilities/workload/workload.js @@ -0,0 +1,83 @@ +"use strict"; + +// +// Workload.js +// tablet-workload-engine app +// +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { + var TABLET_BUTTON_NAME = "Workload"; + var QMLAPP_URL = Script.resolvePath("./workload.qml"); + var ICON_URL = Script.resolvePath("../../../system/assets/images/luci-i.svg"); + var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/luci-a.svg"); + + + var onAppScreen = false; + + function onClicked() { + if (onAppScreen) { + tablet.gotoHomeScreen(); + } else { + tablet.loadQMLSource(QMLAPP_URL); + } + } + + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + text: TABLET_BUTTON_NAME, + icon: ICON_URL, + activeIcon: ACTIVE_ICON_URL + }); + + var hasEventBridge = false; + + function wireEventBridge(on) { + if (!tablet) { + print("Warning in wireEventBridge(): 'tablet' undefined!"); + return; + } + if (on) { + if (!hasEventBridge) { + tablet.fromQml.connect(fromQml); + hasEventBridge = true; + } + } else { + if (hasEventBridge) { + tablet.fromQml.disconnect(fromQml); + hasEventBridge = false; + } + } + } + + function onScreenChanged(type, url) { + if (url === QMLAPP_URL) { + onAppScreen = true; + } else { + onAppScreen = false; + } + + button.editProperties({isActive: onAppScreen}); + wireEventBridge(onAppScreen); + } + + function fromQml(message) { + } + + button.clicked.connect(onClicked); + tablet.screenChanged.connect(onScreenChanged); + + Script.scriptEnding.connect(function () { + if (onAppScreen) { + tablet.gotoHomeScreen(); + } + button.clicked.disconnect(onClicked); + tablet.screenChanged.disconnect(onScreenChanged); + tablet.removeButton(button); + }); + +}()); \ No newline at end of file diff --git a/scripts/developer/utilities/workload/workload.qml b/scripts/developer/utilities/workload/workload.qml new file mode 100644 index 0000000000..e514e9b28a --- /dev/null +++ b/scripts/developer/utilities/workload/workload.qml @@ -0,0 +1,40 @@ +// +// workload.qml +// +// Created by Sam Gateau on 3/1/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +import "qrc:///qml/styles-uit" +import "qrc:///qml/controls-uit" as HifiControls +import "../render/configSlider" + +Rectangle { + HifiConstants { id: hifi;} + id: workload; + anchors.margins: hifi.dimensions.contentMargin.x + + color: hifi.colors.baseGray; + property var spaceToRender: Workload.getConfig("SpaceToRender") + + Column { + spacing: 5 + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: hifi.dimensions.contentMargin.x + //padding: hifi.dimensions.contentMargin.x + + HifiControls.CheckBox { + boxSize: 20 + text: "Show All Proxies" + checked: workload.spaceToRender["showAllProxies"] + onCheckedChanged: { workload.spaceToRender["showAllProxies"] = checked } + } + } +} From 5b8e18f15d78ceaa6fa943cd4375dd30ba4e9ec5 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 1 Mar 2018 17:57:44 -0800 Subject: [PATCH 039/138] Adding the pipeline to render the view spheres --- .../src/workload/GameWorkloadRenderer.cpp | 97 ++++++++++++++++--- interface/src/workload/GameWorkloadRenderer.h | 25 +++-- .../render-utils/src/drawWorkloadView.slv | 94 ++++++++++++++++++ libraries/workload/src/workload/Space.cpp | 6 +- libraries/workload/src/workload/Space.h | 11 ++- .../developer/utilities/workload/workload.qml | 20 +++- 6 files changed, 225 insertions(+), 28 deletions(-) create mode 100644 libraries/render-utils/src/drawWorkloadView.slv diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index bb6aa35257..4a6cca118e 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -16,11 +16,13 @@ #include #include "render-utils/drawWorkloadProxy_vert.h" +#include "render-utils/drawWorkloadView_vert.h" #include "render-utils/drawWorkloadProxy_frag.h" void GameSpaceToRender::configure(const Config& config) { - _showAllProxies = config.showAllProxies; + _showAllProxies = config.showProxies; + _showAllViews = config.showViews; } void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, Outputs& outputs) { @@ -33,7 +35,10 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, return; } - auto visible = _showAllProxies; + auto visible = _showAllProxies || _showAllViews; + auto showProxies = _showAllProxies; + auto showViews = _showAllViews; + render::Transaction transaction; auto scene = gameWorkloadContext->_scene; @@ -51,22 +56,26 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, std::vector proxies(space->getNumAllocatedProxies()); space->copyProxyValues(proxies.data(), (uint32_t)proxies.size()); - + std::vector views(space->getNumViews()); + space->copyViews(views); // Valid space, let's display its content if (!render::Item::isValidID(_spaceRenderItemID)) { _spaceRenderItemID = scene->allocateID(); auto renderItem = std::make_shared(); renderItem->editBound().setBox(glm::vec3(-100.0f), 200.0f); - renderItem->setVisible(visible); renderItem->setAllProxies(proxies); transaction.resetItem(_spaceRenderItemID, std::make_shared(renderItem)); - } else { - transaction.updateItem(_spaceRenderItemID, [visible, proxies](GameWorkloadRenderItem& item) { - item.setVisible(visible); - item.setAllProxies(proxies); - }); } + + transaction.updateItem(_spaceRenderItemID, [visible, showProxies, proxies, showViews, views](GameWorkloadRenderItem& item) { + item.setVisible(visible); + item.showProxies(showProxies); + item.setAllProxies(proxies); + item.showViews(showViews); + item.setAllViews(views); + }); + scene->enqueueTransaction(transaction); } @@ -109,6 +118,15 @@ void GameWorkloadRenderItem::setVisible(bool isVisible) { } } +void GameWorkloadRenderItem::showProxies(bool show) { + _showProxies = show; +} + +void GameWorkloadRenderItem::showViews(bool show) { + _showViews = show; +} + + void GameWorkloadRenderItem::setAllProxies(const std::vector& proxies) { _myOwnProxies = proxies; static const uint32_t sizeOfProxy = sizeof(workload::Space::Proxy); @@ -120,7 +138,18 @@ void GameWorkloadRenderItem::setAllProxies(const std::vector& views) { + _myOwnViews = views; + static const uint32_t sizeOfView = sizeof(workload::Space::View); + if (!_allViewsBuffer) { + _allViewsBuffer = std::make_shared(sizeOfView); + } + + _allViewsBuffer->setData(views.size() * sizeOfView, (const gpu::Byte*) views.data()); + _numAllViews = (uint32_t)views.size(); +} + +const gpu::PipelinePointer GameWorkloadRenderItem::getProxiesPipeline() { if (!_drawAllProxiesPipeline) { auto vs = drawWorkloadProxy_vert::getShader(); auto ps = drawWorkloadProxy_frag::getShader(); @@ -143,6 +172,29 @@ const gpu::PipelinePointer GameWorkloadRenderItem::getPipeline() { return _drawAllProxiesPipeline; } + +const gpu::PipelinePointer GameWorkloadRenderItem::getViewsPipeline() { + if (!_drawAllViewsPipeline) { + auto vs = drawWorkloadView_vert::getShader(); + auto ps = drawWorkloadProxy_frag::getShader(); + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding("workloadViewsBuffer", 1)); + gpu::Shader::makeProgram(*program, slotBindings); + + auto state = std::make_shared(); + state->setDepthTest(true, true, gpu::LESS_EQUAL); + /* state->setBlendFunction(true, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO);*/ + + PrepareStencil::testMaskDrawShape(*state); + state->setCullMode(gpu::State::CULL_NONE); + _drawAllViewsPipeline = gpu::Pipeline::create(program, state); + } + return _drawAllViewsPipeline; +} void GameWorkloadRenderItem::render(RenderArgs* args) { gpu::Batch& batch = *(args->_batch); @@ -155,15 +207,28 @@ void GameWorkloadRenderItem::render(RenderArgs* args) { batch.setViewTransform(viewMat); batch.setModelTransform(Transform()); - // Bind program - batch.setPipeline(getPipeline()); - batch.setResourceBuffer(0, _allProxiesBuffer); + batch.setResourceBuffer(1, _allViewsBuffer); - static const int NUM_VERTICES_PER_QUAD = 3; - batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_QUAD * _numAllProxies, 0); + // Show Proxies + if (_showProxies) { + batch.setPipeline(getProxiesPipeline()); + + static const int NUM_VERTICES_PER_QUAD = 3; + batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_QUAD * _numAllProxies, 0); + } + + // Show Views + if (_showViews) { + batch.setPipeline(getViewsPipeline()); + + static const int NUM_VERTICES_PER_QUAD = 3; + batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_QUAD * 3 * _numAllViews, 0); + } + + batch.setResourceBuffer(0, nullptr); + batch.setResourceBuffer(1, nullptr); - batch.setResourceBuffer(11, nullptr); } diff --git a/interface/src/workload/GameWorkloadRenderer.h b/interface/src/workload/GameWorkloadRenderer.h index dc0fb9f3a1..0c2b521a01 100644 --- a/interface/src/workload/GameWorkloadRenderer.h +++ b/interface/src/workload/GameWorkloadRenderer.h @@ -14,10 +14,12 @@ class GameSpaceToRenderConfig : public workload::Job::Config { Q_OBJECT - Q_PROPERTY(bool showAllProxies MEMBER showAllProxies NOTIFY dirty) + Q_PROPERTY(bool showProxies MEMBER showProxies NOTIFY dirty) + Q_PROPERTY(bool showViews MEMBER showViews NOTIFY dirty) public: - bool showAllProxies{ false }; + bool showProxies{ false }; + bool showViews{ false }; signals: void dirty(); @@ -38,6 +40,7 @@ public: protected: render::ItemID _spaceRenderItemID{ render::Item::INVALID_ITEM_ID }; bool _showAllProxies{ false }; + bool _showAllViews{ false }; }; @@ -50,12 +53,15 @@ public: ~GameWorkloadRenderItem() {} void render(RenderArgs* args); - render::Item::Bound& editBound() { _needUpdate = true; return _bound; } + render::Item::Bound& editBound() { return _bound; } const render::Item::Bound& getBound() { return _bound; } void setVisible(bool visible); + void showProxies(bool show); + void showViews(bool show); void setAllProxies(const std::vector& proxies); + void setAllViews(const std::vector& views); render::ItemKey getKey() const; @@ -66,12 +72,19 @@ protected: gpu::BufferPointer _allProxiesBuffer; uint32_t _numAllProxies{ 0 }; + std::vector _myOwnViews; + gpu::BufferPointer _allViewsBuffer; + uint32_t _numAllViews{ 0 }; + gpu::PipelinePointer _drawAllProxiesPipeline; - const gpu::PipelinePointer getPipeline(); + const gpu::PipelinePointer getProxiesPipeline(); + + gpu::PipelinePointer _drawAllViewsPipeline; + const gpu::PipelinePointer getViewsPipeline(); render::ItemKey _key; - bool _needUpdate{ true }; - bool _isVisible{ true }; + bool _showProxies{ true }; + bool _showViews{ true }; }; namespace render { diff --git a/libraries/render-utils/src/drawWorkloadView.slv b/libraries/render-utils/src/drawWorkloadView.slv new file mode 100644 index 0000000000..c1a272a66c --- /dev/null +++ b/libraries/render-utils/src/drawWorkloadView.slv @@ -0,0 +1,94 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// drawItemBounds.slv +// vertex shader +// +// Created by Sam Gateau on 6/29/2015. +// Copyright 2015 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 gpu/Transform.slh@> +<$declareStandardTransform()$> + +<@include gpu/Color.slh@> +<$declareColorWheel()$> + +uniform vec4 inColor; + + +struct WorkloadView { + vec4 origin; + vec4 radiuses; +}; + +#if defined(GPU_GL410) +uniform samplerBuffer workloadViewsBuffer; +WorkloadView getWorkloadView(int i) { + int offset = 2 * i; + WorkloadView view; + view.origin = texelFetch(workloadViewsBuffer, offset); + view.radiuses = texelFetch(workloadViewsBuffer, offset + 1); + return view; +} +#else +layout(std140) buffer workloadViewsBuffer { + WorkloadView _views[]; +}; +WorkloadView getWorkloadView(int i) { + WorkloadView view = _views[i]; + return view; +} +#endif + + + +out vec4 varColor; +out vec2 varTexcoord; + +void main(void) { + const vec4 UNIT_SPRITE[3] = vec4[3]( + vec4(-1.0, -1.0, 0.0, 1.0), + vec4(3.0, -1.0, 0.0, 1.0), + vec4(-1.0, 3.0, 0.0, 1.0) + ); + const int UNIT_SPRITE_INDICES[3] = int[3]( + 0, 1, 2 + ); + + int viewID = gl_VertexID / 9; + int reminder = gl_VertexID - viewID * 9; + int regionID = reminder / 3; + reminder = reminder - regionID * 3; + int vertexID = reminder; + + vec4 spriteVert = UNIT_SPRITE[UNIT_SPRITE_INDICES[vertexID]]; + + WorkloadView view = getWorkloadView(viewID); + vec4 proxyPosWorld = vec4(view.origin.xyz, 1.0); + + // standard transform, bring proxy in view space + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + vec4 proxyPosEye; + <$transformModelToEyePos(cam, obj, proxyPosWorld, proxyPosEye)$> + + // Define the billboarded space + vec3 dirZ = -normalize(proxyPosEye.xyz); + vec3 dirX = normalize(cross(vec3(0.0, 1.0, 0.0), dirZ)); + vec3 dirY = vec3(0.0, 1.0, 0.0); + // vec3 dirY = normalize(cross(dirZ, vec3(1.0, 0.0, 0.0))); + + float regionRadius = view.radiuses[regionID]; + + vec4 pos = vec4(proxyPosEye.xyz + regionRadius * ( dirX * spriteVert.x + dirY * spriteVert.y /* + dirZ * spriteVert.z*/), 1.0); + varTexcoord = spriteVert.xy; + <$transformEyeToClipPos(cam, pos, gl_Position)$> + + // Convert region to color + varColor = vec4(colorWheel(float(regionID) / 4.0), regionRadius); +} diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index 016b246725..c5881ab756 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -58,6 +58,10 @@ void Space::setViews(const std::vector& views) { _views = views; } +void Space::copyViews(std::vector& copy) const { + copy = _views; +} + // TODO?: move this to an algorithm/job? void Space::categorizeAndGetChanges(std::vector& changes) { uint32_t numProxies = (uint32_t)_proxies.size(); @@ -106,7 +110,7 @@ void Space::deleteProxy(int32_t proxyId) { } } -uint32_t Space::copyProxyValues(Proxy* proxies, uint32_t numDestProxies) { +uint32_t Space::copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const { auto numCopied = std::min(numDestProxies, (uint32_t)_proxies.size()); memcpy(proxies, _proxies.data(), numCopied * sizeof(Proxy)); diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index 46ea8651bf..34c74af2eb 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -51,13 +51,16 @@ public: class View { public: + View() = default; View(const glm::vec3& pos, float nearRadius, float midRadius, float farRadius) : center(pos) { radiuses[REGION_NEAR] = nearRadius; radiuses[REGION_MIDDLE] = midRadius; radiuses[REGION_FAR] = farRadius; } - glm::vec3 center; + glm::vec3 center; + float _padding0; float radiuses[NUM_CLASSIFICATIONS - 1]; + float _padding1; }; class Change { @@ -76,11 +79,15 @@ public: void updateProxies(const std::vector& changedProxies); void setViews(const std::vector& views); + uint32_t getNumViews() const { return (uint32_t)(_views.size()); } + void copyViews(std::vector& copy) const; + + uint32_t getNumObjects() const { return (uint32_t)(_proxies.size() - _freeIndices.size()); } uint32_t getNumAllocatedProxies() const { return (uint32_t)(_proxies.size()); } void categorizeAndGetChanges(std::vector& changes); - uint32_t copyProxyValues(Proxy* proxies, uint32_t numDestProxies); + uint32_t copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const; private: void deleteProxy(int32_t proxyId); diff --git a/scripts/developer/utilities/workload/workload.qml b/scripts/developer/utilities/workload/workload.qml index e514e9b28a..530707b076 100644 --- a/scripts/developer/utilities/workload/workload.qml +++ b/scripts/developer/utilities/workload/workload.qml @@ -30,11 +30,25 @@ Rectangle { anchors.margins: hifi.dimensions.contentMargin.x //padding: hifi.dimensions.contentMargin.x + HifiControls.Label { + text: "Workload" + } + Separator {} + HifiControls.Label { + text: "Display" + } HifiControls.CheckBox { boxSize: 20 - text: "Show All Proxies" - checked: workload.spaceToRender["showAllProxies"] - onCheckedChanged: { workload.spaceToRender["showAllProxies"] = checked } + text: "Show Proxies" + checked: workload.spaceToRender["showProxies"] + onCheckedChanged: { workload.spaceToRender["showProxies"] = checked } } + HifiControls.CheckBox { + boxSize: 20 + text: "Show Views" + checked: workload.spaceToRender["showViews"] + onCheckedChanged: { workload.spaceToRender["showViews"] = checked } + } + Separator {} } } From 660c4c30e9a9b72d562b53421aeb5cbcf01ec52f Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 2 Mar 2018 18:22:51 -0800 Subject: [PATCH 040/138] Representing the view spheres --- .../src/workload/GameWorkloadRenderer.cpp | 27 +++++----- interface/src/workload/GameWorkloadRenderer.h | 3 ++ .../render-utils/src/drawWorkloadProxy.slf | 4 +- .../render-utils/src/drawWorkloadProxy.slv | 4 +- .../render-utils/src/drawWorkloadView.slv | 52 +++++++++++++------ .../developer/utilities/workload/workload.qml | 6 +++ 6 files changed, 63 insertions(+), 33 deletions(-) diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index 4a6cca118e..f1b4861451 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -21,6 +21,7 @@ void GameSpaceToRender::configure(const Config& config) { + _freezeViews = config.freezeViews; _showAllProxies = config.showProxies; _showAllViews = config.showViews; } @@ -38,6 +39,7 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, auto visible = _showAllProxies || _showAllViews; auto showProxies = _showAllProxies; auto showViews = _showAllViews; + auto freezeViews = _freezeViews; render::Transaction transaction; auto scene = gameWorkloadContext->_scene; @@ -57,7 +59,9 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, space->copyProxyValues(proxies.data(), (uint32_t)proxies.size()); std::vector views(space->getNumViews()); - space->copyViews(views); + if (!freezeViews) { + space->copyViews(views); + } // Valid space, let's display its content if (!render::Item::isValidID(_spaceRenderItemID)) { @@ -68,12 +72,14 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, transaction.resetItem(_spaceRenderItemID, std::make_shared(renderItem)); } - transaction.updateItem(_spaceRenderItemID, [visible, showProxies, proxies, showViews, views](GameWorkloadRenderItem& item) { + transaction.updateItem(_spaceRenderItemID, [visible, showProxies, proxies, freezeViews, showViews, views](GameWorkloadRenderItem& item) { item.setVisible(visible); item.showProxies(showProxies); item.setAllProxies(proxies); item.showViews(showViews); - item.setAllViews(views); + if (!freezeViews) { + item.setAllViews(views); + } }); scene->enqueueTransaction(transaction); @@ -198,13 +204,6 @@ const gpu::PipelinePointer GameWorkloadRenderItem::getViewsPipeline() { void GameWorkloadRenderItem::render(RenderArgs* args) { gpu::Batch& batch = *(args->_batch); - // Setup projection - glm::mat4 projMat; - Transform viewMat; - args->getViewFrustum().evalProjectionMatrix(projMat); - args->getViewFrustum().evalViewTransform(viewMat); - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); batch.setModelTransform(Transform()); batch.setResourceBuffer(0, _allProxiesBuffer); @@ -214,16 +213,16 @@ void GameWorkloadRenderItem::render(RenderArgs* args) { if (_showProxies) { batch.setPipeline(getProxiesPipeline()); - static const int NUM_VERTICES_PER_QUAD = 3; - batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_QUAD * _numAllProxies, 0); + static const int NUM_VERTICES_PER_PROXY = 3; + batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_PROXY * _numAllProxies, 0); } // Show Views if (_showViews) { batch.setPipeline(getViewsPipeline()); - static const int NUM_VERTICES_PER_QUAD = 3; - batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_QUAD * 3 * _numAllViews, 0); + static const int NUM_VERTICES_PER_VIEW = 27; + batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_VIEW * _numAllViews, 0); } batch.setResourceBuffer(0, nullptr); diff --git a/interface/src/workload/GameWorkloadRenderer.h b/interface/src/workload/GameWorkloadRenderer.h index 0c2b521a01..f4c1a813e8 100644 --- a/interface/src/workload/GameWorkloadRenderer.h +++ b/interface/src/workload/GameWorkloadRenderer.h @@ -14,10 +14,12 @@ class GameSpaceToRenderConfig : public workload::Job::Config { Q_OBJECT + Q_PROPERTY(bool freezeViews MEMBER freezeViews NOTIFY dirty) Q_PROPERTY(bool showProxies MEMBER showProxies NOTIFY dirty) Q_PROPERTY(bool showViews MEMBER showViews NOTIFY dirty) public: + bool freezeViews{ false }; bool showProxies{ false }; bool showViews{ false }; signals: @@ -39,6 +41,7 @@ public: protected: render::ItemID _spaceRenderItemID{ render::Item::INVALID_ITEM_ID }; + bool _freezeViews{ false }; bool _showAllProxies{ false }; bool _showAllViews{ false }; }; diff --git a/libraries/render-utils/src/drawWorkloadProxy.slf b/libraries/render-utils/src/drawWorkloadProxy.slf index cd02066caf..d00739cdda 100644 --- a/libraries/render-utils/src/drawWorkloadProxy.slf +++ b/libraries/render-utils/src/drawWorkloadProxy.slf @@ -14,10 +14,10 @@ <@include gpu/Paint.slh@> in vec4 varColor; -in vec2 varTexcoord; +in vec3 varTexcoord; void main(void) { - float r = sqrt(dot(varTexcoord.xy,varTexcoord.xy)); + float r = sqrt(dot(varTexcoord.xyz,varTexcoord.xyz)); float a = paintStripe(r * varColor.w, 0.0, 1.0 / varColor.w, 0.05 / varColor.w); if (a <= 0.1 || r > 1.1) { discard; diff --git a/libraries/render-utils/src/drawWorkloadProxy.slv b/libraries/render-utils/src/drawWorkloadProxy.slv index ac83e7761a..f2673ea9e4 100644 --- a/libraries/render-utils/src/drawWorkloadProxy.slv +++ b/libraries/render-utils/src/drawWorkloadProxy.slv @@ -48,7 +48,7 @@ WorkloadProxy getWorkloadProxy(int i) { out vec4 varColor; -out vec2 varTexcoord; +out vec3 varTexcoord; void main(void) { const vec4 UNIT_SPRITE[3] = vec4[3]( @@ -80,7 +80,7 @@ void main(void) { // vec3 dirY = normalize(cross(dirZ, vec3(1.0, 0.0, 0.0))); vec4 pos = vec4(proxyPosEye.xyz + proxy.sphere.w * ( dirX * spriteVert.x + dirY * spriteVert.y /* + dirZ * spriteVert.z*/), 1.0); - varTexcoord = spriteVert.xy; + varTexcoord = spriteVert.xyz; <$transformEyeToClipPos(cam, pos, gl_Position)$> // Convert region to color diff --git a/libraries/render-utils/src/drawWorkloadView.slv b/libraries/render-utils/src/drawWorkloadView.slv index c1a272a66c..c5e3d0bb5b 100644 --- a/libraries/render-utils/src/drawWorkloadView.slv +++ b/libraries/render-utils/src/drawWorkloadView.slv @@ -48,23 +48,37 @@ WorkloadView getWorkloadView(int i) { out vec4 varColor; -out vec2 varTexcoord; +out vec3 varTexcoord; + +const int NUM_VERTICES_PER_VIEW = 27; +const int NUM_REGIONS_PER_VIEW = 3; +const int NUM_VERTICES_PER_VIEW_REGION = NUM_VERTICES_PER_VIEW / NUM_REGIONS_PER_VIEW; void main(void) { - const vec4 UNIT_SPRITE[3] = vec4[3]( + const vec4 UNIT_SPRITE[NUM_VERTICES_PER_VIEW_REGION] = vec4[NUM_VERTICES_PER_VIEW_REGION]( vec4(-1.0, -1.0, 0.0, 1.0), vec4(3.0, -1.0, 0.0, 1.0), - vec4(-1.0, 3.0, 0.0, 1.0) + vec4(-1.0, 3.0, 0.0, 1.0), + + vec4(-1.0, 0.0, -1.0, 1.0), + vec4(3.0, 0.0, -1.0, 1.0), + vec4(-1.0, 0.0, 3.0, 1.0), + + vec4(0.0, -1.0, -1.0, 1.0), + vec4(0.0, 3.0, -1.0, 1.0), + vec4(0.0, -1.0, 3.0, 1.0) ); - const int UNIT_SPRITE_INDICES[3] = int[3]( - 0, 1, 2 + const int UNIT_SPRITE_INDICES[NUM_VERTICES_PER_VIEW_REGION] = int[NUM_VERTICES_PER_VIEW_REGION]( + 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - int viewID = gl_VertexID / 9; - int reminder = gl_VertexID - viewID * 9; - int regionID = reminder / 3; - reminder = reminder - regionID * 3; - int vertexID = reminder; + int viewID = gl_VertexID / NUM_VERTICES_PER_VIEW; + int viewVertexID = gl_VertexID - viewID * NUM_VERTICES_PER_VIEW; + + int regionID = viewVertexID / NUM_VERTICES_PER_VIEW_REGION; + int regionVertexID = viewVertexID - regionID * NUM_VERTICES_PER_VIEW_REGION; + + int vertexID = regionVertexID; vec4 spriteVert = UNIT_SPRITE[UNIT_SPRITE_INDICES[vertexID]]; @@ -78,15 +92,23 @@ void main(void) { <$transformModelToEyePos(cam, obj, proxyPosWorld, proxyPosEye)$> // Define the billboarded space - vec3 dirZ = -normalize(proxyPosEye.xyz); - vec3 dirX = normalize(cross(vec3(0.0, 1.0, 0.0), dirZ)); + vec3 dirZ = vec3(0.0, 0.0, 1.0); + vec3 dirX = vec3(1.0, 0.0, 0.0); vec3 dirY = vec3(0.0, 1.0, 0.0); - // vec3 dirY = normalize(cross(dirZ, vec3(1.0, 0.0, 0.0))); + /*normalize(cross(vec3(0.0, 1.0, 0.0), dirZ)); + if (dot(proxyPosEye.xyz, proxyPosEye.xyz) > 0.01) { + dirZ = -normalize(proxyPosEye.xyz); + } + vec3 dirX = normalize(cross(vec3(0.0, 1.0, 0.0), dirZ)); + vec3 dirY = normalize(cross(dirZ, dirX)); + */ float regionRadius = view.radiuses[regionID]; - vec4 pos = vec4(proxyPosEye.xyz + regionRadius * ( dirX * spriteVert.x + dirY * spriteVert.y /* + dirZ * spriteVert.z*/), 1.0); - varTexcoord = spriteVert.xy; + vec3 originSpaceVert = dirY * (-0.02) + regionRadius * ( dirX * spriteVert.x + dirY * spriteVert.y + dirZ * spriteVert.z); + + vec4 pos = vec4(proxyPosEye.xyz + originSpaceVert, 1.0); + varTexcoord = spriteVert.xyz; <$transformEyeToClipPos(cam, pos, gl_Position)$> // Convert region to color diff --git a/scripts/developer/utilities/workload/workload.qml b/scripts/developer/utilities/workload/workload.qml index 530707b076..56ea12a2f1 100644 --- a/scripts/developer/utilities/workload/workload.qml +++ b/scripts/developer/utilities/workload/workload.qml @@ -33,6 +33,12 @@ Rectangle { HifiControls.Label { text: "Workload" } + HifiControls.CheckBox { + boxSize: 20 + text: "Freeze Views" + checked: workload.spaceToRender["freezeViews"] + onCheckedChanged: { workload.spaceToRender["freezeViews"] = checked } + } Separator {} HifiControls.Label { text: "Display" From 450786404c6bbd7d9c0b5b555adb68330a120b78 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 5 Mar 2018 18:04:25 -0800 Subject: [PATCH 041/138] Adding more detailed classes and introducing an upfront setupVIew job --- interface/src/Application.cpp | 9 +-- interface/src/workload/GameWorkload.cpp | 12 +++- interface/src/workload/GameWorkload.h | 2 + .../src/workload/GameWorkloadRenderer.cpp | 6 +- interface/src/workload/GameWorkloadRenderer.h | 4 +- libraries/task/src/task/Task.h | 3 + .../src/workload/ClassificationTracker.cpp | 6 +- libraries/workload/src/workload/Engine.cpp | 11 +-- libraries/workload/src/workload/Region.h | 72 +++++++++++++++++++ libraries/workload/src/workload/Space.cpp | 18 ++--- libraries/workload/src/workload/Space.h | 68 ++---------------- libraries/workload/src/workload/View.cpp | 19 +++++ libraries/workload/src/workload/View.h | 50 +++++++++++++ libraries/workload/src/workload/ViewTask.cpp | 24 +++++++ libraries/workload/src/workload/ViewTask.h | 35 +++++++++ 15 files changed, 246 insertions(+), 93 deletions(-) create mode 100644 libraries/workload/src/workload/Region.h create mode 100644 libraries/workload/src/workload/View.cpp create mode 100644 libraries/workload/src/workload/View.h create mode 100644 libraries/workload/src/workload/ViewTask.cpp create mode 100644 libraries/workload/src/workload/ViewTask.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cc167f912d..249effbf0f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4261,14 +4261,7 @@ void Application::idle() { } { - // TEMP HACK: one view with static radiuses - float r0 = 10.0f; - float r1 = 20.0f; - float r2 = 30.0f; - workload::Space::View view(_viewFrustum.getPosition(), r0, r1, r2); - std::vector views; - views.push_back(view); - getEntities()->getWorkloadSpace()->setViews(views); + _gameWorkload.updateViews(_viewFrustum); _gameWorkload._engine->run(); } { diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 7fc7a38fc7..d68889408a 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -9,6 +9,7 @@ // #include "GameWorkload.h" #include "GameWorkloadRenderer.h" +#include GameWorkloadContext::GameWorkloadContext(const workload::SpacePointer& space, const render::ScenePointer& scene) : WorkloadContext(space), _scene(scene) { } @@ -36,5 +37,14 @@ void GameWorkload::shutdown() { _engine.reset(); } - +void GameWorkload::updateViews(const ViewFrustum& frustum) { + // TEMP HACK: one view with static radiuses + float r0 = 10.0f; + float r1 = 20.0f; + float r2 = 30.0f; + workload::View view(frustum.getPosition(), r0, r1, r2); + workload::Views views; + views.push_back(view); + _engine->setInput(views); +} diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index fe48d0fe92..a89f8895c4 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -31,6 +31,8 @@ public: void startup(const workload::SpacePointer& space, const render::ScenePointer& scene); void shutdown(); + void updateViews(const ViewFrustum& frustum); + workload::EnginePointer _engine; }; diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index f1b4861451..155369e430 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -58,7 +58,7 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, std::vector proxies(space->getNumAllocatedProxies()); space->copyProxyValues(proxies.data(), (uint32_t)proxies.size()); - std::vector views(space->getNumViews()); + workload::Views views(space->getNumViews()); if (!freezeViews) { space->copyViews(views); } @@ -144,9 +144,9 @@ void GameWorkloadRenderItem::setAllProxies(const std::vector& views) { +void GameWorkloadRenderItem::setAllViews(const workload::Views& views) { _myOwnViews = views; - static const uint32_t sizeOfView = sizeof(workload::Space::View); + static const uint32_t sizeOfView = sizeof(workload::View); if (!_allViewsBuffer) { _allViewsBuffer = std::make_shared(sizeOfView); } diff --git a/interface/src/workload/GameWorkloadRenderer.h b/interface/src/workload/GameWorkloadRenderer.h index f4c1a813e8..27733ce570 100644 --- a/interface/src/workload/GameWorkloadRenderer.h +++ b/interface/src/workload/GameWorkloadRenderer.h @@ -64,7 +64,7 @@ public: void showViews(bool show); void setAllProxies(const std::vector& proxies); - void setAllViews(const std::vector& views); + void setAllViews(const workload::Views& views); render::ItemKey getKey() const; @@ -75,7 +75,7 @@ protected: gpu::BufferPointer _allProxiesBuffer; uint32_t _numAllProxies{ 0 }; - std::vector _myOwnViews; + workload::Views _myOwnViews; gpu::BufferPointer _allViewsBuffer; uint32_t _numAllViews{ 0 }; diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index 08df55dddd..74af60b231 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -76,6 +76,7 @@ public: JobConcept(QConfigPointer config) : _config(config) {} virtual ~JobConcept() = default; + virtual void setInput(const Varying& input) {} virtual const Varying getInput() const { return Varying(); } virtual const Varying getOutput() const { return Varying(); } @@ -139,6 +140,7 @@ public: Varying _input; Varying _output; + void setInput(const Varying& input) override { _input = input; } const Varying getInput() const override { return _input; } const Varying getOutput() const override { return _output; } @@ -175,6 +177,7 @@ public: Job(std::string name, ConceptPointer concept) : _concept(concept), _name(name) {} + void setInput(const Varying& in) { _concept->setInput(in); } const Varying getInput() const { return _concept->getInput(); } const Varying getOutput() const { return _concept->getOutput(); } QConfigPointer& getConfiguration() const { return _concept->getConfiguration(); } diff --git a/libraries/workload/src/workload/ClassificationTracker.cpp b/libraries/workload/src/workload/ClassificationTracker.cpp index 15066b1050..635fb56527 100644 --- a/libraries/workload/src/workload/ClassificationTracker.cpp +++ b/libraries/workload/src/workload/ClassificationTracker.cpp @@ -23,10 +23,10 @@ void ClassificationTracker::run(const WorkloadContextPointer& context, Outputs& if (space) { Changes changes; space->categorizeAndGetChanges(changes); - outputs.resize(workload::Space::NUM_TRANSITIONS); + outputs.resize(workload::Region::NUM_TRANSITIONS); for (uint32_t i = 0; i < changes.size(); ++i) { - int32_t j = Space::computeTransitionIndex(changes[i].prevRegion, changes[i].region); - assert(j >= 0 && j < workload::Space::NUM_TRANSITIONS); + int32_t j = Region::computeTransitionIndex(changes[i].prevRegion, changes[i].region); + assert(j >= 0 && j < workload::Region::NUM_TRANSITIONS); outputs[j].push_back(changes[i].proxyId); } } diff --git a/libraries/workload/src/workload/Engine.cpp b/libraries/workload/src/workload/Engine.cpp index 70566fe704..9a73ef41f8 100644 --- a/libraries/workload/src/workload/Engine.cpp +++ b/libraries/workload/src/workload/Engine.cpp @@ -16,23 +16,24 @@ #include +#include "ViewTask.h" #include "ClassificationTracker.h" namespace workload { WorkloadContext::WorkloadContext(const SpacePointer& space) : task::JobContext(trace_workload()), _space(space) {} - using EngineModel = Task::Model; - class EngineBuilder { public: - using JobModel = Task::Model; - void build(EngineModel& model, const Varying& in, Varying& out) { + using Input = Views; + using JobModel = Task::ModelI; + void build(JobModel& model, const Varying& in, Varying& out) { + model.addJob("setupViews", in); auto classifications = model.addJob("classificationTracker"); } }; - Engine::Engine(const WorkloadContextPointer& context) : Task("Engine", EngineModel::create()), + Engine::Engine(const WorkloadContextPointer& context) : Task("Engine", EngineBuilder::JobModel::create()), _context(context) { } } // namespace workload diff --git a/libraries/workload/src/workload/Region.h b/libraries/workload/src/workload/Region.h new file mode 100644 index 0000000000..691900f2b1 --- /dev/null +++ b/libraries/workload/src/workload/Region.h @@ -0,0 +1,72 @@ +// +// Region.h +// libraries/workload/src/workload +// +// Created by Sam Gateau 2018.03.05 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_workload_Region_h +#define hifi_workload_Region_h + +namespace workload { + +class Region { +public: + using Type = uint8_t; + + enum Name : uint8_t { + R1 = 0, + R2, + R3, + UNKNOWN, + INVALID, + }; + + static const uint8_t NUM_CLASSIFICATIONS = 4; + static const uint8_t NUM_TRANSITIONS = NUM_CLASSIFICATIONS * (NUM_CLASSIFICATIONS - 1); + + static uint8_t computeTransitionIndex(uint8_t prevIndex, uint8_t newIndex); + +}; + +inline uint8_t Region::computeTransitionIndex(uint8_t prevIndex, uint8_t newIndex) { + // given prevIndex and newIndex compute an index into the transition list, + // where the lists between unchanged indices don't exist (signaled by index = -1). + // + // Given an NxN array + // let p = i + N * j + // + // then k = -1 when i == j + // = p - (1 + p/(N+1)) when i != j + // + // i 0 1 2 3 + // j +-------+-------+-------+-------+ + // |p = 0 | 1 | 2 | 3 | + // 0 | | | | | + // |k = -1 | 0 | 1 | 2 | + // +-------+-------+-------+-------+ + // | 4 | 5 | 6 | 7 | + // 1 | | | | | + // | 3 | -1 | 4 | 5 | + // +-------+-------+-------+-------+ + // | 8 | 9 | 10 | 11 | + // 2 | | | | | + // | 6 | 7 | -1 | 8 | + // +-------+-------+-------+-------+ + // | 12 | 13 | 14 | 15 | + // 3 | | | | | + // | 9 | 10 | 11 | -1 | + // +-------+-------+-------+-------+ + uint8_t p = prevIndex + Region::NUM_CLASSIFICATIONS * newIndex; + if (0 == (p % (Region::NUM_CLASSIFICATIONS + 1))) { + return -1; + } + return p - (1 + p / (Region::NUM_CLASSIFICATIONS + 1)); +} + +} // namespace workload + +#endif // hifi_workload_Region_h \ No newline at end of file diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index c5881ab756..a357c623b6 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -33,8 +33,8 @@ int32_t Space::createProxy(const Space::Sphere& newSphere) { int32_t index = _freeIndices.back(); _freeIndices.pop_back(); _proxies[index].sphere = newSphere; - _proxies[index].region = Space::REGION_UNKNOWN; - _proxies[index].prevRegion = Space::REGION_UNKNOWN; + _proxies[index].region = Region::UNKNOWN; + _proxies[index].prevRegion = Region::UNKNOWN; return index; } } @@ -54,7 +54,7 @@ void Space::updateProxies(const std::vector& changedProxies) { } } -void Space::setViews(const std::vector& views) { +void Space::setViews(const Views& views) { _views = views; } @@ -68,12 +68,14 @@ void Space::categorizeAndGetChanges(std::vector& changes) { uint32_t numViews = (uint32_t)_views.size(); for (uint32_t i = 0; i < numProxies; ++i) { Proxy& proxy = _proxies[i]; - if (proxy.region < Space::REGION_INVALID) { - uint8_t region = Space::REGION_UNKNOWN; + if (proxy.region < Region::INVALID) { + uint8_t region = Region::UNKNOWN; for (uint32_t j = 0; j < numViews; ++j) { - float distance2 = glm::distance2(_views[j].center, glm::vec3(_proxies[i].sphere)); + auto& view = _views[j]; + + float distance2 = glm::distance2(view.origin, glm::vec3(proxy.sphere)); for (uint8_t c = 0; c < region; ++c) { - float touchDistance = _views[j].radiuses[c] + _proxies[i].sphere.w; + float touchDistance = view.regions[c].w + proxy.sphere.w; if (distance2 < touchDistance * touchDistance) { region = c; break; @@ -104,7 +106,7 @@ void Space::deleteProxy(int32_t proxyId) { } } } else { - _proxies[proxyId].region = Space::REGION_INVALID; + _proxies[proxyId].region = Region::INVALID; _freeIndices.push_back(proxyId); } } diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index 34c74af2eb..d331647cf0 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -19,22 +19,13 @@ #include #include +#include "View.h" + namespace workload { class Space { public: - static const int32_t NUM_CLASSIFICATIONS = 4; - static const int32_t NUM_TRANSITIONS = NUM_CLASSIFICATIONS * (NUM_CLASSIFICATIONS - 1); - - static int32_t computeTransitionIndex(int32_t prevIndex, int32_t newIndex); - - static const uint8_t REGION_NEAR = 0; - static const uint8_t REGION_MIDDLE = 1; - static const uint8_t REGION_FAR = 2; - static const uint8_t REGION_UNKNOWN = 3; - static const uint8_t REGION_INVALID = 4; - using Sphere = glm::vec4; // = center, w = radius using ProxyUpdate = std::pair; @@ -43,26 +34,12 @@ public: Proxy() : sphere(0.0f) {} Proxy(const Sphere& s) : sphere(s) {} Sphere sphere; - uint8_t region { REGION_UNKNOWN }; - uint8_t prevRegion { REGION_UNKNOWN }; + uint8_t region { Region::UNKNOWN }; + uint8_t prevRegion { Region::UNKNOWN }; uint16_t _padding; uint32_t _paddings[3]; }; - class View { - public: - View() = default; - View(const glm::vec3& pos, float nearRadius, float midRadius, float farRadius) : center(pos) { - radiuses[REGION_NEAR] = nearRadius; - radiuses[REGION_MIDDLE] = midRadius; - radiuses[REGION_FAR] = farRadius; - } - glm::vec3 center; - float _padding0; - float radiuses[NUM_CLASSIFICATIONS - 1]; - float _padding1; - }; - class Change { public: Change(int32_t i, uint32_t c, uint32_t p) : proxyId(i), region(c), prevRegion(p) {} @@ -94,45 +71,10 @@ private: void updateProxy(int32_t proxyId, const Sphere& sphere); std::vector _proxies; - std::vector _views; + Views _views; std::vector _freeIndices; }; -inline int32_t Space::computeTransitionIndex(int32_t prevIndex, int32_t newIndex) { - // given prevIndex and newIndex compute an index into the transition list, - // where the lists between unchanged indices don't exist (signaled by index = -1). - // - // Given an NxN array - // let p = i + N * j - // - // then k = -1 when i == j - // = p - (1 + p/(N+1)) when i != j - // - // i 0 1 2 3 - // j +-------+-------+-------+-------+ - // |p = 0 | 1 | 2 | 3 | - // 0 | | | | | - // |k = -1 | 0 | 1 | 2 | - // +-------+-------+-------+-------+ - // | 4 | 5 | 6 | 7 | - // 1 | | | | | - // | 3 | -1 | 4 | 5 | - // +-------+-------+-------+-------+ - // | 8 | 9 | 10 | 11 | - // 2 | | | | | - // | 6 | 7 | -1 | 8 | - // +-------+-------+-------+-------+ - // | 12 | 13 | 14 | 15 | - // 3 | | | | | - // | 9 | 10 | 11 | -1 | - // +-------+-------+-------+-------+ - int32_t p = prevIndex + Space::NUM_CLASSIFICATIONS * newIndex; - if (0 == (p % (Space::NUM_CLASSIFICATIONS + 1))) { - return -1; - } - return p - (1 + p / (Space::NUM_CLASSIFICATIONS + 1)); -} - using SpacePointer = std::shared_ptr; using Changes = std::vector; using SortedChanges = std::vector>; diff --git a/libraries/workload/src/workload/View.cpp b/libraries/workload/src/workload/View.cpp new file mode 100644 index 0000000000..c34983e08c --- /dev/null +++ b/libraries/workload/src/workload/View.cpp @@ -0,0 +1,19 @@ +// +// View.cpp +// libraries/workload/src/workload +// +// Created by Sam Gateau 2018.03.05 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "View.h" +#include + +using namespace workload; + +View evalFromFrustum(const ViewFrustum& frustum, float farDistance) { + + return View(); +} diff --git a/libraries/workload/src/workload/View.h b/libraries/workload/src/workload/View.h new file mode 100644 index 0000000000..5c2c5bbbd2 --- /dev/null +++ b/libraries/workload/src/workload/View.h @@ -0,0 +1,50 @@ +// +// View.h +// libraries/workload/src/workload +// +// Created by Sam Gateau 2018.03.05 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_workload_View_h +#define hifi_workload_View_h + +#include +#include +#include + +#include "Region.h" + +class ViewFrustum; + +namespace workload { + +using Sphere = glm::vec4; + +class View { +public: + View() = default; + View(const View& view) = default; + + View(const glm::vec3& pos, float nearRadius, float midRadius, float farRadius) : + origin(pos) { + regions[Region::R1] = Sphere(pos, nearRadius); + regions[Region::R2] = Sphere(pos, midRadius); + regions[Region::R3] = Sphere(pos, farRadius); + } + + glm::vec3 origin; + float _padding { 1.0f }; + Sphere regions[(Region::NUM_CLASSIFICATIONS - 1)]; + + static View evalFromFrustum(const ViewFrustum& frustum, float farDistance); +}; + +using Views = std::vector; + +} // namespace workload + +#endif // hifi_workload_View_h \ No newline at end of file diff --git a/libraries/workload/src/workload/ViewTask.cpp b/libraries/workload/src/workload/ViewTask.cpp new file mode 100644 index 0000000000..70f7406e82 --- /dev/null +++ b/libraries/workload/src/workload/ViewTask.cpp @@ -0,0 +1,24 @@ +// +// ViewTask.cpp +// libraries/workload/src/workload +// +// Created by Sam Gateau 2018.03.05 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "ViewTask.h" + +using namespace workload; + + +void SetupViews::configure(const Config& config) { +} + +void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& inputs) { + + inputs; + +} + diff --git a/libraries/workload/src/workload/ViewTask.h b/libraries/workload/src/workload/ViewTask.h new file mode 100644 index 0000000000..50e8d99bc4 --- /dev/null +++ b/libraries/workload/src/workload/ViewTask.h @@ -0,0 +1,35 @@ +// +// ViewTask.h +// libraries/workload/src/workload +// +// Created by Sam Gateau 2018.03.05 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_workload_ViewTask_h +#define hifi_workload_ViewTask_h + +#include "Engine.h" + +namespace workload { + class SetupViewsConfig : public Job::Config{ + Q_OBJECT + public: + SetupViewsConfig() : Job::Config(true) {} + }; + + class SetupViews { + public: + using Config = SetupViewsConfig; + using Input = Views; + using JobModel = Job::ModelI; + + void configure(const Config& config); + void run(const workload::WorkloadContextPointer& renderContext, const Input& inputs); + }; + +} // namespace workload + +#endif // hifi_workload_ViewTask_h \ No newline at end of file From 7e96608699986b4cd58c98e892a6c208b96ee2e6 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 6 Mar 2018 01:35:16 -0800 Subject: [PATCH 042/138] introducing the first stage of the workload engine to setup view and expand the view definition --- interface/src/workload/GameWorkload.cpp | 9 ++--- .../render-utils/src/drawWorkloadView.slv | 11 ++++-- libraries/task/src/task/Task.h | 11 ++++-- libraries/workload/src/workload/Region.h | 2 ++ libraries/workload/src/workload/View.cpp | 35 ++++++++++++++++-- libraries/workload/src/workload/View.h | 36 +++++++++++++------ libraries/workload/src/workload/ViewTask.cpp | 6 +++- 7 files changed, 83 insertions(+), 27 deletions(-) diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index d68889408a..63fe440fcd 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -38,13 +38,8 @@ void GameWorkload::shutdown() { } void GameWorkload::updateViews(const ViewFrustum& frustum) { - // TEMP HACK: one view with static radiuses - float r0 = 10.0f; - float r1 = 20.0f; - float r2 = 30.0f; - workload::View view(frustum.getPosition(), r0, r1, r2); workload::Views views; - views.push_back(view); - _engine->setInput(views); + views.emplace_back(workload::View::evalFromFrustum(frustum)); + _engine->feedInput(views); } diff --git a/libraries/render-utils/src/drawWorkloadView.slv b/libraries/render-utils/src/drawWorkloadView.slv index c5e3d0bb5b..09dc41e471 100644 --- a/libraries/render-utils/src/drawWorkloadView.slv +++ b/libraries/render-utils/src/drawWorkloadView.slv @@ -22,8 +22,10 @@ uniform vec4 inColor; struct WorkloadView { + vec4 direction_far; + vec4 fov; vec4 origin; - vec4 radiuses; + vec4 regions[3]; }; #if defined(GPU_GL410) @@ -83,7 +85,10 @@ void main(void) { vec4 spriteVert = UNIT_SPRITE[UNIT_SPRITE_INDICES[vertexID]]; WorkloadView view = getWorkloadView(viewID); - vec4 proxyPosWorld = vec4(view.origin.xyz, 1.0); + + vec4 region = view.regions[regionID]; + + vec4 proxyPosWorld = vec4(region.xyz, 1.0); // standard transform, bring proxy in view space TransformCamera cam = getTransformCamera(); @@ -103,7 +108,7 @@ void main(void) { vec3 dirX = normalize(cross(vec3(0.0, 1.0, 0.0), dirZ)); vec3 dirY = normalize(cross(dirZ, dirX)); */ - float regionRadius = view.radiuses[regionID]; + float regionRadius = region.w; vec3 originSpaceVert = dirY * (-0.02) + regionRadius * ( dirX * spriteVert.x + dirY * spriteVert.y + dirZ * spriteVert.z); diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index 74af60b231..7c66cf9810 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -76,9 +76,9 @@ public: JobConcept(QConfigPointer config) : _config(config) {} virtual ~JobConcept() = default; - virtual void setInput(const Varying& input) {} virtual const Varying getInput() const { return Varying(); } virtual const Varying getOutput() const { return Varying(); } + virtual Varying& editInput() = 0; virtual QConfigPointer& getConfiguration() { return _config; } virtual void applyConfiguration() = 0; @@ -140,9 +140,9 @@ public: Varying _input; Varying _output; - void setInput(const Varying& input) override { _input = input; } const Varying getInput() const override { return _input; } const Varying getOutput() const override { return _output; } + Varying& editInput() override { return _input; } template Model(const Varying& input, QConfigPointer config, A&&... args) : @@ -177,9 +177,12 @@ public: Job(std::string name, ConceptPointer concept) : _concept(concept), _name(name) {} - void setInput(const Varying& in) { _concept->setInput(in); } const Varying getInput() const { return _concept->getInput(); } const Varying getOutput() const { return _concept->getOutput(); } + + template void feedInput(const I& in) { _concept->editInput().edit() = in; } + + QConfigPointer& getConfiguration() const { return _concept->getConfiguration(); } void applyConfiguration() { return _concept->applyConfiguration(); } @@ -243,6 +246,8 @@ public: const Varying getInput() const override { return _input; } const Varying getOutput() const override { return _output; } + Varying& editInput() override { return _input; } + typename Jobs::iterator editJob(std::string name) { typename Jobs::iterator jobIt; for (jobIt = _jobs.begin(); jobIt != _jobs.end(); ++jobIt) { diff --git a/libraries/workload/src/workload/Region.h b/libraries/workload/src/workload/Region.h index 691900f2b1..43aed9aef4 100644 --- a/libraries/workload/src/workload/Region.h +++ b/libraries/workload/src/workload/Region.h @@ -28,6 +28,8 @@ public: static const uint8_t NUM_CLASSIFICATIONS = 4; static const uint8_t NUM_TRANSITIONS = NUM_CLASSIFICATIONS * (NUM_CLASSIFICATIONS - 1); + static const uint8_t NUM_VIEW_REGIONS = (NUM_CLASSIFICATIONS - 1); + static uint8_t computeTransitionIndex(uint8_t prevIndex, uint8_t newIndex); }; diff --git a/libraries/workload/src/workload/View.cpp b/libraries/workload/src/workload/View.cpp index c34983e08c..dba4ffed7c 100644 --- a/libraries/workload/src/workload/View.cpp +++ b/libraries/workload/src/workload/View.cpp @@ -13,7 +13,36 @@ using namespace workload; -View evalFromFrustum(const ViewFrustum& frustum, float farDistance) { - - return View(); +void View::setFov(float angleRad) { + float halfAngle = angleRad * 0.5f; + + fov_halfAngle_tan_cos_sin.x = halfAngle; + fov_halfAngle_tan_cos_sin.y = tanf(halfAngle); + fov_halfAngle_tan_cos_sin.z = cosf(halfAngle); + fov_halfAngle_tan_cos_sin.w = sinf(halfAngle); } + +View View::evalFromFrustum(const ViewFrustum& frustum) { + View view; + view.origin = frustum.getPosition(); + view.direction = frustum.getDirection(); + view.setFov(frustum.getFieldOfView()); + + return view; +} + +Sphere View::evalRegionSphere(const View& view, float originRadius, float maxDistance) { + float radius = (maxDistance + originRadius) / 2.0; + float center = radius - originRadius; + return Sphere(view.origin + view.direction * center, radius); +} + +void View::updateRegions(View& view) { + float refFar = 10.0f; + float refClose = 2.0f; + for (int i = 0; i < Region::NUM_VIEW_REGIONS; i++) { + float weight = i + 1.0f; + view.regions[i] = evalRegionSphere(view, refClose * weight, refFar * weight); + refFar *= 2.0f; + } +} \ No newline at end of file diff --git a/libraries/workload/src/workload/View.h b/libraries/workload/src/workload/View.h index 5c2c5bbbd2..7484c46398 100644 --- a/libraries/workload/src/workload/View.h +++ b/libraries/workload/src/workload/View.h @@ -29,18 +29,34 @@ public: View() = default; View(const View& view) = default; - View(const glm::vec3& pos, float nearRadius, float midRadius, float farRadius) : - origin(pos) { - regions[Region::R1] = Sphere(pos, nearRadius); - regions[Region::R2] = Sphere(pos, midRadius); - regions[Region::R3] = Sphere(pos, farRadius); - } + // View attributes: - glm::vec3 origin; - float _padding { 1.0f }; - Sphere regions[(Region::NUM_CLASSIFICATIONS - 1)]; + // direction + glm::vec3 direction{ 0.0f, 0.0f, -1.0f }; - static View evalFromFrustum(const ViewFrustum& frustum, float farDistance); + // Max radius + float maxRadius{ FLT_MAX }; + + // Fov stores the half field of view angle, and tan/cos/sin ready to go, default is fov of 90deg + glm::vec4 fov_halfAngle_tan_cos_sin { M_PI_4, 1.0f, M_SQRT2 * 0.5f, M_SQRT2 * 0.5f }; + + // Origin position + glm::vec3 origin{ 0.0f }; + + // Origin radius + float originRadius{ 0.5f }; + + // N regions spheres + Sphere regions[Region::NUM_VIEW_REGIONS]; + + // Set fov properties from angle + void setFov(float angleRad); + + + static View evalFromFrustum(const ViewFrustum& frustum); + static Sphere evalRegionSphere(const View& view, float originRadius, float maxDistance); + + static void updateRegions(View& view); }; using Views = std::vector; diff --git a/libraries/workload/src/workload/ViewTask.cpp b/libraries/workload/src/workload/ViewTask.cpp index 70f7406e82..451f3c820f 100644 --- a/libraries/workload/src/workload/ViewTask.cpp +++ b/libraries/workload/src/workload/ViewTask.cpp @@ -18,7 +18,11 @@ void SetupViews::configure(const Config& config) { void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& inputs) { - inputs; + Views views = inputs; + for (auto& v : views) { + View::updateRegions(v); + } + renderContext->_space->setViews(views); } From b6b7cb3394daf9618de38505deb7c7d3d2676eab Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 6 Mar 2018 12:39:28 -0800 Subject: [PATCH 043/138] Adressing warnings issue and implementing the independent intersection test per region spheres --- libraries/task/src/task/Task.h | 2 +- libraries/workload/src/workload/Engine.cpp | 27 ++++++++++++++++--- libraries/workload/src/workload/Space.cpp | 19 +++++++++---- libraries/workload/src/workload/View.cpp | 2 +- libraries/workload/src/workload/View.h | 2 +- .../developer/utilities/workload/workload.qml | 3 ++- 6 files changed, 43 insertions(+), 12 deletions(-) diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index 7c66cf9810..3dcb856fc0 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -180,7 +180,7 @@ public: const Varying getInput() const { return _concept->getInput(); } const Varying getOutput() const { return _concept->getOutput(); } - template void feedInput(const I& in) { _concept->editInput().edit() = in; } + template void feedInput(const I& in) { _concept->editInput().template edit() = in; } QConfigPointer& getConfiguration() const { return _concept->getConfiguration(); } diff --git a/libraries/workload/src/workload/Engine.cpp b/libraries/workload/src/workload/Engine.cpp index 9a73ef41f8..ce5ab6cca0 100644 --- a/libraries/workload/src/workload/Engine.cpp +++ b/libraries/workload/src/workload/Engine.cpp @@ -20,16 +20,37 @@ #include "ClassificationTracker.h" namespace workload { + class DebugCout { + public: + using Inputs = SortedChanges; + using JobModel = workload::Job::ModelI; + + DebugCout() {} + + void run(const workload::WorkloadContextPointer& renderContext, const Inputs& inputs) { + qDebug() << "Some message from " << inputs.size(); + int i = 0; + for (auto& b: inputs) { + qDebug() << " Bucket Number" << i << " size is " << b.size(); + i++; + } + } + + protected: + }; + WorkloadContext::WorkloadContext(const SpacePointer& space) : task::JobContext(trace_workload()), _space(space) {} class EngineBuilder { public: - using Input = Views; - using JobModel = Task::ModelI; + using Inputs = Views; + using JobModel = Task::ModelI; void build(JobModel& model, const Varying& in, Varying& out) { model.addJob("setupViews", in); - auto classifications = model.addJob("classificationTracker"); + const auto classifications = model.addJob("classificationTracker"); + // model.addJob("debug", classifications); + } }; diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index a357c623b6..41d573e0bb 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -73,11 +73,20 @@ void Space::categorizeAndGetChanges(std::vector& changes) { for (uint32_t j = 0; j < numViews; ++j) { auto& view = _views[j]; - float distance2 = glm::distance2(view.origin, glm::vec3(proxy.sphere)); - for (uint8_t c = 0; c < region; ++c) { - float touchDistance = view.regions[c].w + proxy.sphere.w; - if (distance2 < touchDistance * touchDistance) { - region = c; + glm::vec3 distance2(glm::distance2(proxy.sphere, view.regions[0]), glm::distance2(proxy.sphere, view.regions[1]), glm::distance2(proxy.sphere, view.regions[2])); + glm::vec3 regionRadii2(view.regions[0].w + proxy.sphere.w, view.regions[1].w + proxy.sphere.w, view.regions[2].w + proxy.sphere.w); + regionRadii2 *= regionRadii2; + auto touchTests = glm::lessThanEqual(distance2, regionRadii2); + + if (glm::any(touchTests)) { + if (touchTests.x) { + region = Region::R1; + break; + } else if (touchTests.y) { + region = Region::R2; + break; + } else { + region = Region::R3; break; } } diff --git a/libraries/workload/src/workload/View.cpp b/libraries/workload/src/workload/View.cpp index dba4ffed7c..f68e7a8436 100644 --- a/libraries/workload/src/workload/View.cpp +++ b/libraries/workload/src/workload/View.cpp @@ -32,7 +32,7 @@ View View::evalFromFrustum(const ViewFrustum& frustum) { } Sphere View::evalRegionSphere(const View& view, float originRadius, float maxDistance) { - float radius = (maxDistance + originRadius) / 2.0; + float radius = (maxDistance + originRadius) / 2.0f; float center = radius - originRadius; return Sphere(view.origin + view.direction * center, radius); } diff --git a/libraries/workload/src/workload/View.h b/libraries/workload/src/workload/View.h index 7484c46398..a237615a7a 100644 --- a/libraries/workload/src/workload/View.h +++ b/libraries/workload/src/workload/View.h @@ -38,7 +38,7 @@ public: float maxRadius{ FLT_MAX }; // Fov stores the half field of view angle, and tan/cos/sin ready to go, default is fov of 90deg - glm::vec4 fov_halfAngle_tan_cos_sin { M_PI_4, 1.0f, M_SQRT2 * 0.5f, M_SQRT2 * 0.5f }; + glm::vec4 fov_halfAngle_tan_cos_sin { (float) M_PI_4, 1.0f, (float) (M_SQRT2 * 0.5), (float) (M_SQRT2 * 0.5) }; // Origin position glm::vec3 origin{ 0.0f }; diff --git a/scripts/developer/utilities/workload/workload.qml b/scripts/developer/utilities/workload/workload.qml index 56ea12a2f1..3b7ca09496 100644 --- a/scripts/developer/utilities/workload/workload.qml +++ b/scripts/developer/utilities/workload/workload.qml @@ -21,6 +21,7 @@ Rectangle { anchors.margins: hifi.dimensions.contentMargin.x color: hifi.colors.baseGray; + property var setupViews: Workload.getConfig("setupViews") property var spaceToRender: Workload.getConfig("SpaceToRender") Column { @@ -37,7 +38,7 @@ Rectangle { boxSize: 20 text: "Freeze Views" checked: workload.spaceToRender["freezeViews"] - onCheckedChanged: { workload.spaceToRender["freezeViews"] = checked } + onCheckedChanged: { workload.spaceToRender["freezeViews"] = checked, workload.setupViews.enabled = !checked; } } Separator {} HifiControls.Label { From 43920b548fcb857cdc6bb31ba86572d7934152ab Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 6 Mar 2018 17:05:49 -0800 Subject: [PATCH 044/138] fix proxy-region distance math --- libraries/workload/src/workload/Space.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index 41d573e0bb..de3da5991e 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -69,12 +69,14 @@ void Space::categorizeAndGetChanges(std::vector& changes) { for (uint32_t i = 0; i < numProxies; ++i) { Proxy& proxy = _proxies[i]; if (proxy.region < Region::INVALID) { + glm::vec3 proxyCenter = glm::vec3(proxy.sphere); + float proxyRadius = proxy.sphere.w; uint8_t region = Region::UNKNOWN; for (uint32_t j = 0; j < numViews; ++j) { auto& view = _views[j]; - glm::vec3 distance2(glm::distance2(proxy.sphere, view.regions[0]), glm::distance2(proxy.sphere, view.regions[1]), glm::distance2(proxy.sphere, view.regions[2])); - glm::vec3 regionRadii2(view.regions[0].w + proxy.sphere.w, view.regions[1].w + proxy.sphere.w, view.regions[2].w + proxy.sphere.w); + glm::vec3 distance2(glm::distance2(proxyCenter, glm::vec3(view.regions[0])), glm::distance2(proxyCenter, glm::vec3(view.regions[1])), glm::distance2(proxyCenter, glm::vec3(view.regions[2]))); + glm::vec3 regionRadii2(view.regions[0].w + proxyRadius, view.regions[1].w + proxyRadius, view.regions[2].w + proxyRadius); regionRadii2 *= regionRadii2; auto touchTests = glm::lessThanEqual(distance2, regionRadii2); From 4a91ac11c99800b941fc9b9d071fa6c44dea0b4d Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 6 Mar 2018 18:19:02 -0800 Subject: [PATCH 045/138] Adding controls of the regions --- .../render-utils/src/RenderDeferredTask.cpp | 6 +-- libraries/workload/src/workload/View.cpp | 15 +++++++- libraries/workload/src/workload/View.h | 2 + libraries/workload/src/workload/ViewTask.cpp | 3 +- libraries/workload/src/workload/ViewTask.h | 38 +++++++++++++++++++ .../developer/utilities/workload/workload.qml | 18 +++++++++ 6 files changed, 76 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index f262307944..af85d9af5d 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -142,12 +142,12 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto ambientOcclusionFramebuffer = ambientOcclusionOutputs.getN(0); const auto ambientOcclusionUniforms = ambientOcclusionOutputs.getN(1); - + // Filter zones from the general metas bucket + const auto zones = task.addJob("ZoneRenderer", metas); + // Draw Lights just add the lights to the current list of lights to deal with. NOt really gpu job for now. task.addJob("DrawLight", lights); - // Filter zones from the general metas bucket - const auto zones = task.addJob("ZoneRenderer", metas); // Light Clustering // Create the cluster grid of lights, cpu job for now diff --git a/libraries/workload/src/workload/View.cpp b/libraries/workload/src/workload/View.cpp index f68e7a8436..684b231245 100644 --- a/libraries/workload/src/workload/View.cpp +++ b/libraries/workload/src/workload/View.cpp @@ -38,11 +38,22 @@ Sphere View::evalRegionSphere(const View& view, float originRadius, float maxDis } void View::updateRegions(View& view) { + std::vector config(Region::NUM_VIEW_REGIONS * 2, 0.0f); + float refFar = 10.0f; float refClose = 2.0f; for (int i = 0; i < Region::NUM_VIEW_REGIONS; i++) { float weight = i + 1.0f; - view.regions[i] = evalRegionSphere(view, refClose * weight, refFar * weight); + config[i * 2] = refClose; + config[i * 2 + 1] = refFar * weight; refFar *= 2.0f; } -} \ No newline at end of file + + updateRegions(view, config.data()); +} + +void View::updateRegions(View& view, const float* configDistances) { + for (int i = 0; i < Region::NUM_VIEW_REGIONS; i++) { + view.regions[i] = evalRegionSphere(view, configDistances[i * 2], configDistances[i * 2 + 1]); + } +} diff --git a/libraries/workload/src/workload/View.h b/libraries/workload/src/workload/View.h index a237615a7a..aea66ef605 100644 --- a/libraries/workload/src/workload/View.h +++ b/libraries/workload/src/workload/View.h @@ -57,6 +57,8 @@ public: static Sphere evalRegionSphere(const View& view, float originRadius, float maxDistance); static void updateRegions(View& view); + + static void updateRegions(View& view, const float* configDistances); }; using Views = std::vector; diff --git a/libraries/workload/src/workload/ViewTask.cpp b/libraries/workload/src/workload/ViewTask.cpp index 451f3c820f..3f7a9b740d 100644 --- a/libraries/workload/src/workload/ViewTask.cpp +++ b/libraries/workload/src/workload/ViewTask.cpp @@ -14,13 +14,14 @@ using namespace workload; void SetupViews::configure(const Config& config) { + data = config.data; } void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& inputs) { Views views = inputs; for (auto& v : views) { - View::updateRegions(v); + View::updateRegions(v, (float*) &data); } renderContext->_space->setViews(views); diff --git a/libraries/workload/src/workload/ViewTask.h b/libraries/workload/src/workload/ViewTask.h index 50e8d99bc4..560efef331 100644 --- a/libraries/workload/src/workload/ViewTask.h +++ b/libraries/workload/src/workload/ViewTask.h @@ -16,8 +16,43 @@ namespace workload { class SetupViewsConfig : public Job::Config{ Q_OBJECT + Q_PROPERTY(float r1Front READ getR1Front WRITE setR1Front NOTIFY dirty) + Q_PROPERTY(float r1Back READ getR1Back WRITE setR1Back NOTIFY dirty) + Q_PROPERTY(float r2Front READ getR2Front WRITE setR2Front NOTIFY dirty) + Q_PROPERTY(float r2Back READ getR2Back WRITE setR2Back NOTIFY dirty) + Q_PROPERTY(float r3Front READ getR3Front WRITE setR3Front NOTIFY dirty) + Q_PROPERTY(float r3Back READ getR3Back WRITE setR3Back NOTIFY dirty) public: SetupViewsConfig() : Job::Config(true) {} + + + float getR1Front() const { return data.r1Front; } + float getR1Back() const { return data.r1Back; } + float getR2Front() const { return data.r2Front; } + float getR2Back() const { return data.r2Back; } + float getR3Front() const { return data.r3Front; } + float getR3Back() const { return data.r3Back; } + + void setR1Front(float d) { data.r1Front = d; emit dirty(); } + void setR1Back(float d) { data.r1Back = d; emit dirty(); } + void setR2Front(float d) { data.r2Front = d; emit dirty(); } + void setR2Back(float d) { data.r2Back = d; emit dirty(); } + void setR3Front(float d) { data.r3Front = d; emit dirty(); } + void setR3Back(float d) { data.r3Back = d; emit dirty(); } + + struct Data { + float r1Front { 10.0f }; + float r1Back { 2.0f }; + + float r2Front{ 30.0f }; + float r2Back{ 5.0f }; + + float r3Front{ 100.0f }; + float r3Back{ 10.0f }; + } data; + + signals: + void dirty(); }; class SetupViews { @@ -28,6 +63,9 @@ namespace workload { void configure(const Config& config); void run(const workload::WorkloadContextPointer& renderContext, const Input& inputs); + + protected: + Config::Data data; }; } // namespace workload diff --git a/scripts/developer/utilities/workload/workload.qml b/scripts/developer/utilities/workload/workload.qml index 3b7ca09496..80061f5ad9 100644 --- a/scripts/developer/utilities/workload/workload.qml +++ b/scripts/developer/utilities/workload/workload.qml @@ -40,6 +40,24 @@ Rectangle { checked: workload.spaceToRender["freezeViews"] onCheckedChanged: { workload.spaceToRender["freezeViews"] = checked, workload.setupViews.enabled = !checked; } } + Repeater { + model: [ + "R1 Front:r1Front:300:1.0", "R1 Back:r1Back:50.0:0.0", + "R2 Front:r2Front:300:1.0", "R2 Back:r2Back:50.0:0.0", + "R3 Front:r3Front:300:1.0", "R3 Back:r3Back:50.0:0.0" + ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + integral: false + config: workload.setupViews + property: modelData.split(":")[1] + max: modelData.split(":")[2] + min: modelData.split(":")[3] + + anchors.left: parent.left + anchors.right: parent.right + } + } Separator {} HifiControls.Label { text: "Display" From 03a5a6f4e09876b6e95563d1542de093c73976c6 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 7 Mar 2018 08:41:01 -0800 Subject: [PATCH 046/138] more correct proxy classification for multiple views --- libraries/workload/src/workload/Space.cpp | 27 ++++++----------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index de3da5991e..7a9f90c5b8 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -62,10 +62,9 @@ void Space::copyViews(std::vector& copy) const { copy = _views; } -// TODO?: move this to an algorithm/job? void Space::categorizeAndGetChanges(std::vector& changes) { - uint32_t numProxies = (uint32_t)_proxies.size(); - uint32_t numViews = (uint32_t)_views.size(); + uint32_t numProxies = _proxies.size(); + uint32_t numViews = _views.size(); for (uint32_t i = 0; i < numProxies; ++i) { Proxy& proxy = _proxies[i]; if (proxy.region < Region::INVALID) { @@ -74,21 +73,11 @@ void Space::categorizeAndGetChanges(std::vector& changes) { uint8_t region = Region::UNKNOWN; for (uint32_t j = 0; j < numViews; ++j) { auto& view = _views[j]; - - glm::vec3 distance2(glm::distance2(proxyCenter, glm::vec3(view.regions[0])), glm::distance2(proxyCenter, glm::vec3(view.regions[1])), glm::distance2(proxyCenter, glm::vec3(view.regions[2]))); - glm::vec3 regionRadii2(view.regions[0].w + proxyRadius, view.regions[1].w + proxyRadius, view.regions[2].w + proxyRadius); - regionRadii2 *= regionRadii2; - auto touchTests = glm::lessThanEqual(distance2, regionRadii2); - - if (glm::any(touchTests)) { - if (touchTests.x) { - region = Region::R1; - break; - } else if (touchTests.y) { - region = Region::R2; - break; - } else { - region = Region::R3; + // for each 'view' we need only increment 'k' below the current value of 'region' + for (uint8_t k = 0; k < region; ++k) { + float touchDistance = proxyRadius + view.regions[k].w; + if (distance2(proxyCenter, glm::vec3(view.regions[k])) < touchDistance * touchDistance) { + region = k; break; } } @@ -124,10 +113,8 @@ void Space::deleteProxy(int32_t proxyId) { } uint32_t Space::copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const { - auto numCopied = std::min(numDestProxies, (uint32_t)_proxies.size()); memcpy(proxies, _proxies.data(), numCopied * sizeof(Proxy)); - return numCopied; } From 0d9b1a7368561cd3fc5518041f87583285dfdeea Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 7 Mar 2018 11:19:47 -0800 Subject: [PATCH 047/138] jobflow: RegionTracker --> RegionState --- .../src/workload/ClassificationTracker.cpp | 34 --------- libraries/workload/src/workload/Engine.cpp | 27 ++------ .../workload/src/workload/RegionState.cpp | 69 +++++++++++++++++++ libraries/workload/src/workload/RegionState.h | 38 ++++++++++ .../workload/src/workload/RegionTracker.cpp | 43 ++++++++++++ ...lassificationTracker.h => RegionTracker.h} | 22 +++--- libraries/workload/src/workload/Space.h | 8 ++- libraries/workload/src/workload/View.cpp | 2 +- libraries/workload/src/workload/View.h | 2 +- 9 files changed, 172 insertions(+), 73 deletions(-) delete mode 100644 libraries/workload/src/workload/ClassificationTracker.cpp create mode 100644 libraries/workload/src/workload/RegionState.cpp create mode 100644 libraries/workload/src/workload/RegionState.h create mode 100644 libraries/workload/src/workload/RegionTracker.cpp rename libraries/workload/src/workload/{ClassificationTracker.h => RegionTracker.h} (56%) diff --git a/libraries/workload/src/workload/ClassificationTracker.cpp b/libraries/workload/src/workload/ClassificationTracker.cpp deleted file mode 100644 index 635fb56527..0000000000 --- a/libraries/workload/src/workload/ClassificationTracker.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// -// ClassificationTracker.cpp -// libraries/workload/src/workload -// -// Created by Andrew Meadows 2018.02.21 -// Copyright 2018 High Fidelity, Inc. -// -// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards -// Simple plane class. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -#include "ClassificationTracker.h" - -using namespace workload; - -void ClassificationTracker::configure(const Config& config) { -} - -void ClassificationTracker::run(const WorkloadContextPointer& context, Outputs& outputs) { - auto space = context->_space; - if (space) { - Changes changes; - space->categorizeAndGetChanges(changes); - outputs.resize(workload::Region::NUM_TRANSITIONS); - for (uint32_t i = 0; i < changes.size(); ++i) { - int32_t j = Region::computeTransitionIndex(changes[i].prevRegion, changes[i].region); - assert(j >= 0 && j < workload::Region::NUM_TRANSITIONS); - outputs[j].push_back(changes[i].proxyId); - } - } -} - diff --git a/libraries/workload/src/workload/Engine.cpp b/libraries/workload/src/workload/Engine.cpp index ce5ab6cca0..525872f190 100644 --- a/libraries/workload/src/workload/Engine.cpp +++ b/libraries/workload/src/workload/Engine.cpp @@ -17,29 +17,10 @@ #include #include "ViewTask.h" -#include "ClassificationTracker.h" +#include "RegionTracker.h" +#include "RegionState.h" namespace workload { - class DebugCout { - public: - using Inputs = SortedChanges; - using JobModel = workload::Job::ModelI; - - DebugCout() {} - - void run(const workload::WorkloadContextPointer& renderContext, const Inputs& inputs) { - qDebug() << "Some message from " << inputs.size(); - int i = 0; - for (auto& b: inputs) { - qDebug() << " Bucket Number" << i << " size is " << b.size(); - i++; - } - } - - protected: - }; - - WorkloadContext::WorkloadContext(const SpacePointer& space) : task::JobContext(trace_workload()), _space(space) {} class EngineBuilder { @@ -48,8 +29,8 @@ namespace workload { using JobModel = Task::ModelI; void build(JobModel& model, const Varying& in, Varying& out) { model.addJob("setupViews", in); - const auto classifications = model.addJob("classificationTracker"); - // model.addJob("debug", classifications); + const auto regionChanges = model.addJob("regionTracker"); + model.addJob("regionState", regionChanges); } }; diff --git a/libraries/workload/src/workload/RegionState.cpp b/libraries/workload/src/workload/RegionState.cpp new file mode 100644 index 0000000000..f779c8d2fc --- /dev/null +++ b/libraries/workload/src/workload/RegionState.cpp @@ -0,0 +1,69 @@ +// +// RegionState.cpp +// libraries/workload/src/workload +// +// Created by Andrew Meadows 2018.03.07 +// Copyright 2018 High Fidelity, Inc. +// +// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards +// Simple plane class. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "RegionState.h" + +using namespace workload; + +void RegionState::run(const workload::WorkloadContextPointer& renderContext, const Inputs& inputs) { + // inputs is a vector of vectors of proxyId's: + // + // inputs[0] = vector of ids exiting region 0 + // inputs[1] = vector of ids entering region 0 + // ... + // inputs[2N] = vector of ids exiting region N + // inputs[2N + 1] = vector of ids entering region N + assert(inputs.size() == 2 * Region::UNKNOWN); + + // The id's in each vector are sorted in ascending order + // because the source vectors are scanned in ascending order. + + for (uint32_t i = 0; i < _state.size(); ++i) { + const IndexVector& going = inputs[2 * i]; + const IndexVector& coming = inputs[2 * i - 1]; + if (coming.size() == 0 && going.size() == 0) { + continue; + } + if (_state[i].empty()) { + assert(going.empty()); + _state[i] = coming; + } else { + // NOTE: all vectors are sorted by proxyId! + // which means we can build the new vector by walking three vectors (going, current, coming) in one pass + IndexVector& oldState = _state[i]; + IndexVector newState; + newState.reserve(oldState.size() - going.size() + coming.size()); + uint32_t goingIndex = 0; + uint32_t comingIndex = 0; + for (uint32_t j = 0; j < oldState.size(); ++j) { + int32_t proxyId = oldState[j]; + while (comingIndex < coming.size() && coming[comingIndex] < proxyId) { + newState.push_back(coming[comingIndex]); + ++comingIndex; + } + if (goingIndex < going.size() && going[goingIndex] == proxyId) { + ++goingIndex; + } else { + newState.push_back(proxyId); + } + } + assert(goingIndex == going.size()); + while (comingIndex < coming.size()) { + newState.push_back(coming[comingIndex]); + ++comingIndex; + } + oldState.swap(newState); + } + } +} diff --git a/libraries/workload/src/workload/RegionState.h b/libraries/workload/src/workload/RegionState.h new file mode 100644 index 0000000000..366d6192d2 --- /dev/null +++ b/libraries/workload/src/workload/RegionState.h @@ -0,0 +1,38 @@ +// +// RegionState.h +// libraries/workload/src/workload +// +// Created by Andrew Meadows 2018.03.07 +// Copyright 2018 High Fidelity, Inc. +// +// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards +// Simple plane class. +// +// 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_workload_RegionState_h +#define hifi_workload_RegionState_h + +#include "Space.h" +#include "Engine.h" + +namespace workload { + + class RegionState { + public: + using Inputs = IndexVectors; + using JobModel = workload::Job::ModelI; + + RegionState() { + _state.resize(Region::UNKNOWN); + } + + void run(const workload::WorkloadContextPointer& renderContext, const Inputs& inputs); + + protected: + IndexVectors _state; + }; +} +#endif // hifi_workload_RegionState_h diff --git a/libraries/workload/src/workload/RegionTracker.cpp b/libraries/workload/src/workload/RegionTracker.cpp new file mode 100644 index 0000000000..c2b14937ad --- /dev/null +++ b/libraries/workload/src/workload/RegionTracker.cpp @@ -0,0 +1,43 @@ +// +// RegionTracker.cpp +// libraries/workload/src/workload +// +// Created by Andrew Meadows 2018.02.21 +// Copyright 2018 High Fidelity, Inc. +// +// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards +// Simple plane class. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "RegionTracker.h" + +#include "Region.h" + +using namespace workload; + +void RegionTracker::configure(const Config& config) { +} + +void RegionTracker::run(const WorkloadContextPointer& context, Outputs& outputs) { + outputs.clear(); + auto space = context->_space; + if (space) { + Changes changes; + space->categorizeAndGetChanges(changes); + // use exit/enter lists for each region less than Region::UNKNOWN + outputs.resize(2 * (workload::Region::NUM_CLASSIFICATIONS - 1)); + for (uint32_t i = 0; i < changes.size(); ++i) { + Space::Change& change = changes[i]; + if (change.prevRegion < Region::UNKNOWN) { + // EXIT list index = 2 * regionIndex + outputs[2 * change.prevRegion].push_back(change.proxyId); + } + if (change.region < Region::UNKNOWN) { + // ENTER list index = 2 * regionIndex + 1 + outputs[2 * change.region + 1].push_back(change.proxyId); + } + } + } +} diff --git a/libraries/workload/src/workload/ClassificationTracker.h b/libraries/workload/src/workload/RegionTracker.h similarity index 56% rename from libraries/workload/src/workload/ClassificationTracker.h rename to libraries/workload/src/workload/RegionTracker.h index e3364950da..e80723a7da 100644 --- a/libraries/workload/src/workload/ClassificationTracker.h +++ b/libraries/workload/src/workload/RegionTracker.h @@ -1,5 +1,5 @@ // -// ClassificationTracker.h +// RegionTracker.h // libraries/workload/src/workload // // Created by Andrew Meadows 2018.02.21 @@ -12,27 +12,27 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_workload_ClassificationTracker_h -#define hifi_workload_ClassificationTracker_h +#ifndef hifi_workload_RegionTracker_h +#define hifi_workload_RegionTracker_h #include "Space.h" #include "Engine.h" namespace workload { - class ClassificationTrackerConfig : public Job::Config { + class RegionTrackerConfig : public Job::Config { Q_OBJECT public: - ClassificationTrackerConfig() : Job::Config(true) {} + RegionTrackerConfig() : Job::Config(true) {} }; - class ClassificationTracker { + class RegionTracker { public: - using Config = ClassificationTrackerConfig; - using Outputs = SortedChanges; - using JobModel = workload::Job::ModelO; + using Config = RegionTrackerConfig; + using Outputs = IndexVectors; + using JobModel = workload::Job::ModelO; - ClassificationTracker() {} + RegionTracker() {} void configure(const Config& config); void run(const workload::WorkloadContextPointer& renderContext, Outputs& outputs); @@ -42,4 +42,4 @@ namespace workload { } // namespace workload -#endif // hifi_workload_ClassificationTracker_h +#endif // hifi_workload_RegionTracker_h diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index d331647cf0..0acd69194b 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -24,6 +24,8 @@ namespace workload { +using IndexVector = std::vector; + class Space { public: using Sphere = glm::vec4; // = center, w = radius @@ -52,7 +54,7 @@ public: void clear(); int32_t createProxy(const Sphere& sphere); - void deleteProxies(const std::vector& deadIndices); + void deleteProxies(const IndexVector& deadIndices); void updateProxies(const std::vector& changedProxies); void setViews(const std::vector& views); @@ -72,12 +74,12 @@ private: std::vector _proxies; Views _views; - std::vector _freeIndices; + IndexVector _freeIndices; }; using SpacePointer = std::shared_ptr; using Changes = std::vector; -using SortedChanges = std::vector>; +using IndexVectors = std::vector; } // namespace workload diff --git a/libraries/workload/src/workload/View.cpp b/libraries/workload/src/workload/View.cpp index f68e7a8436..cba1168669 100644 --- a/libraries/workload/src/workload/View.cpp +++ b/libraries/workload/src/workload/View.cpp @@ -45,4 +45,4 @@ void View::updateRegions(View& view) { view.regions[i] = evalRegionSphere(view, refClose * weight, refFar * weight); refFar *= 2.0f; } -} \ No newline at end of file +} diff --git a/libraries/workload/src/workload/View.h b/libraries/workload/src/workload/View.h index a237615a7a..ea815c919a 100644 --- a/libraries/workload/src/workload/View.h +++ b/libraries/workload/src/workload/View.h @@ -63,4 +63,4 @@ using Views = std::vector; } // namespace workload -#endif // hifi_workload_View_h \ No newline at end of file +#endif // hifi_workload_View_h From 77d0c211df34cee579ac595902614774c48e5cb3 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 7 Mar 2018 15:46:42 -0800 Subject: [PATCH 048/138] fix warnings on windows --- libraries/workload/src/workload/Space.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index 7a9f90c5b8..c2323fc0a1 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -63,8 +63,8 @@ void Space::copyViews(std::vector& copy) const { } void Space::categorizeAndGetChanges(std::vector& changes) { - uint32_t numProxies = _proxies.size(); - uint32_t numViews = _views.size(); + uint32_t numProxies = (uint32_t)_proxies.size(); + uint32_t numViews = (uint32_t)_views.size(); for (uint32_t i = 0; i < numProxies; ++i) { Proxy& proxy = _proxies[i]; if (proxy.region < Region::INVALID) { From 4dc3685e35c1234f0d0e493ff9a35150efce1613 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 8 Mar 2018 14:50:07 -0800 Subject: [PATCH 049/138] Cosmetic change to the ui and adding more feature to the ConfigSlider --- .../render/configSlider/ConfigSlider.qml | 40 ++++++++----- .../developer/utilities/workload/workload.qml | 56 ++++++++++++++++--- 2 files changed, 75 insertions(+), 21 deletions(-) diff --git a/scripts/developer/utilities/render/configSlider/ConfigSlider.qml b/scripts/developer/utilities/render/configSlider/ConfigSlider.qml index 87e0e51726..41de77fb09 100644 --- a/scripts/developer/utilities/render/configSlider/ConfigSlider.qml +++ b/scripts/developer/utilities/render/configSlider/ConfigSlider.qml @@ -23,13 +23,22 @@ Item { anchors.left: parent.left anchors.right: parent.right height: 24 + + property var labelAreaWidthScale: 0.5 + property bool integral: false property var config property string property - property alias label: labelControl.text 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: { @@ -41,20 +50,12 @@ Item { HifiControls.Label { id: labelControl text: root.label - enabled: true + enabled: root.showLabel anchors.left: root.left - anchors.right: root.horizontalCenter + width: root.width * root.labelAreaWidthScale anchors.verticalCenter: root.verticalCenter } - - HifiControls.Label { - id: labelValue - text: sliderControl.value.toFixed(root.integral ? 0 : 2) - anchors.right: root.right - anchors.bottom: root.bottom - anchors.bottomMargin: 0 - } - + Binding { id: bindingControl target: root.config @@ -66,7 +67,7 @@ Item { HifiControls.Slider { id: sliderControl stepSize: root.integral ? 1.0 : 0.0 - anchors.left: root.horizontalCenter + anchors.left: labelControl.right anchors.right: root.right anchors.rightMargin: 0 anchors.top: root.top @@ -74,4 +75,17 @@ Item { onValueChanged: { root.valueChanged(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/workload/workload.qml b/scripts/developer/utilities/workload/workload.qml index 56121d58d5..e4fa244f9d 100644 --- a/scripts/developer/utilities/workload/workload.qml +++ b/scripts/developer/utilities/workload/workload.qml @@ -40,25 +40,65 @@ Rectangle { checked: workload.spaceToRender["freezeViews"] onCheckedChanged: { workload.spaceToRender["freezeViews"] = checked, workload.setupViews.enabled = !checked; } } - Repeater { - model: [ - "R1 Back:r1Back:50.0:0.0", " Front:r1Front:300:1.0", - "R2 Back:r2Back:50.0:0.0", " Front:r2Front:300:1.0", - "R3 Back:r3Back:50.0:0.0", " Front:r3Front:300:1.0" - ] - ConfigSlider { + + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + Column { + anchors.left: parent.left + anchors.right: parent.horizontalCenter + HifiControls.Label { + text: "Back [m]" + anchors.horizontalCenter: parent.horizontalCenter + } + Repeater { + model: [ + "R1:r1Back:50.0:0.0", + "R2:r2Back:50.0:0.0", + "R3:r3Back:50.0:0.0" + ] + ConfigSlider { label: qsTr(modelData.split(":")[0]) - integral: false config: workload.setupViews property: modelData.split(":")[1] max: modelData.split(":")[2] min: modelData.split(":")[3] + integral: true + labelAreaWidthScale: 0.4 anchors.left: parent.left anchors.right: parent.right + } } } + Column { + anchors.left: parent.horizontalCenter + anchors.right: parent.right + HifiControls.Label { + text: "Front [m]" + anchors.horizontalCenter: parent.horizontalCenter + } + Repeater { + model: [ + "r1Front:300:1.0", + "r2Front:300:1.0", + "r3Front:300:1.0" + ] + ConfigSlider { + showLabel: false + config: workload.setupViews + property: modelData.split(":")[0] + max: modelData.split(":")[1] + min: modelData.split(":")[2] + integral: true + labelAreaWidthScale: 0.3 + anchors.left: parent.left + anchors.right: parent.right + } + } + } + } Separator {} HifiControls.Label { text: "Display" From f087bb7623f3dd94fdb7a06744818168b6c95e69 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 9 Mar 2018 01:38:00 -0800 Subject: [PATCH 050/138] Adjust the freeze view and start drawing the views better --- .../src/workload/GameWorkloadRenderer.cpp | 42 +++++++++++++++---- interface/src/workload/GameWorkloadRenderer.h | 4 ++ .../render-utils/src/drawWorkloadView.slv | 39 ++++++++--------- libraries/workload/src/workload/ViewTask.cpp | 13 ++++-- libraries/workload/src/workload/ViewTask.h | 20 +++++---- .../developer/utilities/workload/workload.qml | 4 +- 6 files changed, 80 insertions(+), 42 deletions(-) diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index 155369e430..85b3a03739 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -59,9 +59,7 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, space->copyProxyValues(proxies.data(), (uint32_t)proxies.size()); workload::Views views(space->getNumViews()); - if (!freezeViews) { - space->copyViews(views); - } + space->copyViews(views); // Valid space, let's display its content if (!render::Item::isValidID(_spaceRenderItemID)) { @@ -77,9 +75,7 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, item.showProxies(showProxies); item.setAllProxies(proxies); item.showViews(showViews); - if (!freezeViews) { - item.setAllViews(views); - } + item.setAllViews(views); }); scene->enqueueTransaction(transaction); @@ -187,6 +183,7 @@ const gpu::PipelinePointer GameWorkloadRenderItem::getViewsPipeline() { gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding("workloadViewsBuffer", 1)); + slotBindings.insert(gpu::Shader::Binding("drawMeshBuffer", 0)); gpu::Shader::makeProgram(*program, slotBindings); auto state = std::make_shared(); @@ -201,6 +198,32 @@ const gpu::PipelinePointer GameWorkloadRenderItem::getViewsPipeline() { } return _drawAllViewsPipeline; } + +const gpu::BufferPointer GameWorkloadRenderItem::getDrawViewBuffer() { + if (!_drawViewBuffer) { + int numSegments = 64; + float angleStep = M_PI * 2.0 / (float)numSegments; + + struct Vert { + glm::vec4 p; + }; + std::vector verts(numSegments + 1); + for (int i = 0; i < numSegments; i++) { + float angle = (float)i * angleStep; + verts[i].p.x = cos(angle); + verts[i].p.y = sin(angle); + verts[i].p.z = angle; + verts[i].p.w = 1.0; + } + verts[numSegments] = verts[0]; + verts[numSegments].p.w = 0.0; + + _drawViewBuffer = std::make_shared(verts.size() * sizeof(Vert), (const gpu::Byte*) verts.data()); + _numDrawViewVerts = numSegments + 1; + } + return _drawViewBuffer; +} + void GameWorkloadRenderItem::render(RenderArgs* args) { gpu::Batch& batch = *(args->_batch); @@ -221,8 +244,11 @@ void GameWorkloadRenderItem::render(RenderArgs* args) { if (_showViews) { batch.setPipeline(getViewsPipeline()); - static const int NUM_VERTICES_PER_VIEW = 27; - batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_VIEW * _numAllViews, 0); + batch.setUniformBuffer(0, getDrawViewBuffer()); + // static const int NUM_VERTICES_PER_VIEW = 27; + // batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_VIEW * _numAllViews, 0); + batch.draw(gpu::TRIANGLES, _numDrawViewVerts * 4, 0); + } batch.setResourceBuffer(0, nullptr); diff --git a/interface/src/workload/GameWorkloadRenderer.h b/interface/src/workload/GameWorkloadRenderer.h index 27733ce570..7a0800d40c 100644 --- a/interface/src/workload/GameWorkloadRenderer.h +++ b/interface/src/workload/GameWorkloadRenderer.h @@ -85,6 +85,10 @@ protected: gpu::PipelinePointer _drawAllViewsPipeline; const gpu::PipelinePointer getViewsPipeline(); + uint32_t _numDrawViewVerts{ 0 }; + gpu::BufferPointer _drawViewBuffer; + const gpu::BufferPointer getDrawViewBuffer(); + render::ItemKey _key; bool _showProxies{ true }; bool _showViews{ true }; diff --git a/libraries/render-utils/src/drawWorkloadView.slv b/libraries/render-utils/src/drawWorkloadView.slv index 09dc41e471..d82a47bd7a 100644 --- a/libraries/render-utils/src/drawWorkloadView.slv +++ b/libraries/render-utils/src/drawWorkloadView.slv @@ -49,12 +49,17 @@ WorkloadView getWorkloadView(int i) { + + out vec4 varColor; out vec3 varTexcoord; const int NUM_VERTICES_PER_VIEW = 27; const int NUM_REGIONS_PER_VIEW = 3; const int NUM_VERTICES_PER_VIEW_REGION = NUM_VERTICES_PER_VIEW / NUM_REGIONS_PER_VIEW; +layout(std140) uniform drawMeshBuffer { + vec4 verts[65]; +}; void main(void) { const vec4 UNIT_SPRITE[NUM_VERTICES_PER_VIEW_REGION] = vec4[NUM_VERTICES_PER_VIEW_REGION]( @@ -89,32 +94,24 @@ void main(void) { vec4 region = view.regions[regionID]; vec4 proxyPosWorld = vec4(region.xyz, 1.0); + float regionRadius = region.w; + + // Define the sprite space + vec3 dirZ = vec3(0.0, 0.0, 1.0); + vec3 dirX = vec3(1.0, 0.0, 0.0); + vec3 dirY = vec3(0.0, 1.0, 0.0); + + vec3 originSpaceVert = regionRadius * (dirX * spriteVert.x + dirY * spriteVert.y + dirZ * spriteVert.z); + + vec4 pos = vec4(proxyPosWorld.xyz + originSpaceVert, 1.0); + varTexcoord = spriteVert.xyz; // standard transform, bring proxy in view space TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); vec4 proxyPosEye; - <$transformModelToEyePos(cam, obj, proxyPosWorld, proxyPosEye)$> - - // Define the billboarded space - vec3 dirZ = vec3(0.0, 0.0, 1.0); - vec3 dirX = vec3(1.0, 0.0, 0.0); - vec3 dirY = vec3(0.0, 1.0, 0.0); - - /*normalize(cross(vec3(0.0, 1.0, 0.0), dirZ)); - if (dot(proxyPosEye.xyz, proxyPosEye.xyz) > 0.01) { - dirZ = -normalize(proxyPosEye.xyz); - } - vec3 dirX = normalize(cross(vec3(0.0, 1.0, 0.0), dirZ)); - vec3 dirY = normalize(cross(dirZ, dirX)); - */ - float regionRadius = region.w; - - vec3 originSpaceVert = dirY * (-0.02) + regionRadius * ( dirX * spriteVert.x + dirY * spriteVert.y + dirZ * spriteVert.z); - - vec4 pos = vec4(proxyPosEye.xyz + originSpaceVert, 1.0); - varTexcoord = spriteVert.xyz; - <$transformEyeToClipPos(cam, pos, gl_Position)$> + <$transformModelToEyePos(cam, obj, pos, proxyPosEye)$> + <$transformEyeToClipPos(cam, proxyPosEye, gl_Position)$> // Convert region to color varColor = vec4(colorWheel(float(regionID) / 4.0), regionRadius); diff --git a/libraries/workload/src/workload/ViewTask.cpp b/libraries/workload/src/workload/ViewTask.cpp index 3f7a9b740d..705f517243 100644 --- a/libraries/workload/src/workload/ViewTask.cpp +++ b/libraries/workload/src/workload/ViewTask.cpp @@ -18,12 +18,17 @@ void SetupViews::configure(const Config& config) { } void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& inputs) { - - Views views = inputs; - for (auto& v : views) { + // If views are frozen don't use the input + if (!data.freezeViews) { + _views = inputs; + } + + // Update regions based on the current config + for (auto& v : _views) { View::updateRegions(v, (float*) &data); } - renderContext->_space->setViews(views); + // Views are setup, assign to the Space + renderContext->_space->setViews(_views); } diff --git a/libraries/workload/src/workload/ViewTask.h b/libraries/workload/src/workload/ViewTask.h index b85cb95ded..2b77aaf273 100644 --- a/libraries/workload/src/workload/ViewTask.h +++ b/libraries/workload/src/workload/ViewTask.h @@ -16,14 +16,14 @@ namespace workload { class SetupViewsConfig : public Job::Config{ Q_OBJECT - Q_PROPERTY(float r1Front READ getR1Front WRITE setR1Front NOTIFY dirty) - Q_PROPERTY(float r1Back READ getR1Back WRITE setR1Back NOTIFY dirty) - Q_PROPERTY(float r2Front READ getR2Front WRITE setR2Front NOTIFY dirty) - Q_PROPERTY(float r2Back READ getR2Back WRITE setR2Back NOTIFY dirty) - Q_PROPERTY(float r3Front READ getR3Front WRITE setR3Front NOTIFY dirty) - Q_PROPERTY(float r3Back READ getR3Back WRITE setR3Back NOTIFY dirty) + Q_PROPERTY(float r1Front READ getR1Front WRITE setR1Front NOTIFY dirty) + Q_PROPERTY(float r1Back READ getR1Back WRITE setR1Back NOTIFY dirty) + Q_PROPERTY(float r2Front READ getR2Front WRITE setR2Front NOTIFY dirty) + Q_PROPERTY(float r2Back READ getR2Back WRITE setR2Back NOTIFY dirty) + Q_PROPERTY(float r3Front READ getR3Front WRITE setR3Front NOTIFY dirty) + Q_PROPERTY(float r3Back READ getR3Back WRITE setR3Back NOTIFY dirty) + Q_PROPERTY(bool freezeViews READ getFreezeView WRITE setFreezeView NOTIFY dirty) public: - SetupViewsConfig() : Job::Config(true) {} float getR1Front() const { return data.r1Front; } @@ -40,6 +40,9 @@ namespace workload { void setR3Front(float d) { data.r3Front = d; emit dirty(); } void setR3Back(float d) { data.r3Back = d; emit dirty(); } + bool getFreezeView() const { return data.freezeViews; } + void setFreezeView(bool freeze) { data.freezeViews = freeze; emit dirty(); } + struct Data { float r1Back { 2.0f }; float r1Front { 10.0f }; @@ -49,6 +52,8 @@ namespace workload { float r3Back{ 10.0f }; float r3Front{ 100.0f }; + + bool freezeViews{ false }; } data; signals: @@ -66,6 +71,7 @@ namespace workload { protected: Config::Data data; + Views _views; }; } // namespace workload diff --git a/scripts/developer/utilities/workload/workload.qml b/scripts/developer/utilities/workload/workload.qml index e4fa244f9d..020df0f83a 100644 --- a/scripts/developer/utilities/workload/workload.qml +++ b/scripts/developer/utilities/workload/workload.qml @@ -37,8 +37,8 @@ Rectangle { HifiControls.CheckBox { boxSize: 20 text: "Freeze Views" - checked: workload.spaceToRender["freezeViews"] - onCheckedChanged: { workload.spaceToRender["freezeViews"] = checked, workload.setupViews.enabled = !checked; } + checked: workload.setupViews["freezeViews"] + onCheckedChanged: { workload.spaceToRender["freezeViews"] = checked, workload.setupViews["freezeViews"] = checked; } } RowLayout { From e8b5a875d6aa01c5d5bd0ffe95d29014846f73ec Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 9 Mar 2018 17:40:58 -0800 Subject: [PATCH 051/138] REndering the view rings better --- .../src/workload/GameWorkloadRenderer.cpp | 6 ++-- interface/src/workload/GameWorkloadRenderer.h | 2 +- .../render-utils/src/drawWorkloadView.slv | 33 +++++++++++++++++-- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index 85b3a03739..148454cba8 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -15,6 +15,7 @@ #include #include +#include #include "render-utils/drawWorkloadProxy_vert.h" #include "render-utils/drawWorkloadView_vert.h" #include "render-utils/drawWorkloadProxy_frag.h" @@ -178,7 +179,8 @@ const gpu::PipelinePointer GameWorkloadRenderItem::getProxiesPipeline() { const gpu::PipelinePointer GameWorkloadRenderItem::getViewsPipeline() { if (!_drawAllViewsPipeline) { auto vs = drawWorkloadView_vert::getShader(); - auto ps = drawWorkloadProxy_frag::getShader(); + // auto ps = drawWorkloadProxy_frag::getShader(); + auto ps = DrawWhite_frag::getShader(); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; @@ -247,7 +249,7 @@ void GameWorkloadRenderItem::render(RenderArgs* args) { batch.setUniformBuffer(0, getDrawViewBuffer()); // static const int NUM_VERTICES_PER_VIEW = 27; // batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_VIEW * _numAllViews, 0); - batch.draw(gpu::TRIANGLES, _numDrawViewVerts * 4, 0); + batch.draw(gpu::TRIANGLE_STRIP, _numDrawViewVerts * 3 * 2, 0); } diff --git a/interface/src/workload/GameWorkloadRenderer.h b/interface/src/workload/GameWorkloadRenderer.h index 7a0800d40c..c784857fdf 100644 --- a/interface/src/workload/GameWorkloadRenderer.h +++ b/interface/src/workload/GameWorkloadRenderer.h @@ -21,7 +21,7 @@ public: bool freezeViews{ false }; bool showProxies{ false }; - bool showViews{ false }; + bool showViews{ true }; signals: void dirty(); diff --git a/libraries/render-utils/src/drawWorkloadView.slv b/libraries/render-utils/src/drawWorkloadView.slv index d82a47bd7a..3139072932 100644 --- a/libraries/render-utils/src/drawWorkloadView.slv +++ b/libraries/render-utils/src/drawWorkloadView.slv @@ -54,15 +54,24 @@ WorkloadView getWorkloadView(int i) { out vec4 varColor; out vec3 varTexcoord; -const int NUM_VERTICES_PER_VIEW = 27; +/*const int NUM_VERTICES_PER_VIEW = 27; const int NUM_REGIONS_PER_VIEW = 3; const int NUM_VERTICES_PER_VIEW_REGION = NUM_VERTICES_PER_VIEW / NUM_REGIONS_PER_VIEW; +*/ + +const int NUM_VERTICES_PER_SEGMENT = 2; +const int NUM_SEGMENT_PER_VIEW_REGION = 65; +const int NUM_VERTICES_PER_VIEW_REGION = NUM_SEGMENT_PER_VIEW_REGION * NUM_VERTICES_PER_SEGMENT; +const int NUM_REGIONS_PER_VIEW = 3; +const int NUM_VERTICES_PER_VIEW = NUM_VERTICES_PER_VIEW_REGION * NUM_REGIONS_PER_VIEW; + + layout(std140) uniform drawMeshBuffer { - vec4 verts[65]; + vec4 verts[NUM_SEGMENT_PER_VIEW_REGION]; }; void main(void) { - const vec4 UNIT_SPRITE[NUM_VERTICES_PER_VIEW_REGION] = vec4[NUM_VERTICES_PER_VIEW_REGION]( +/* const vec4 UNIT_SPRITE[NUM_VERTICES_PER_VIEW_REGION] = vec4[NUM_VERTICES_PER_VIEW_REGION]( vec4(-1.0, -1.0, 0.0, 1.0), vec4(3.0, -1.0, 0.0, 1.0), vec4(-1.0, 3.0, 0.0, 1.0), @@ -88,6 +97,23 @@ void main(void) { int vertexID = regionVertexID; vec4 spriteVert = UNIT_SPRITE[UNIT_SPRITE_INDICES[vertexID]]; +*/ + + int viewID = gl_VertexID / NUM_VERTICES_PER_VIEW; + int viewVertexID = gl_VertexID - viewID * NUM_VERTICES_PER_VIEW; + + int regionID = viewVertexID / NUM_VERTICES_PER_VIEW_REGION; + int regionVertexID = viewVertexID - regionID * NUM_VERTICES_PER_VIEW_REGION; + + int segmentID = regionVertexID / NUM_VERTICES_PER_SEGMENT; + int segmentVertexID = regionVertexID / NUM_VERTICES_PER_SEGMENT; + + vec4 segment = verts[segmentID]; + + vec4 spriteVert = vec4(segment.xy, 0.0, 1.0); + + vec3 lateralDir = (-1.0 + 2.0 * float(segmentVertexID)) * vec3(segment.y, -segment.x, 0.0); + WorkloadView view = getWorkloadView(viewID); @@ -101,6 +127,7 @@ void main(void) { vec3 dirX = vec3(1.0, 0.0, 0.0); vec3 dirY = vec3(0.0, 1.0, 0.0); + spriteVert.xyz += 0.2 * lateralDir; vec3 originSpaceVert = regionRadius * (dirX * spriteVert.x + dirY * spriteVert.y + dirZ * spriteVert.z); vec4 pos = vec4(proxyPosWorld.xyz + originSpaceVert, 1.0); From 4a7d3e8e0e6aa7861b79f5770d95817d226c578c Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 9 Mar 2018 17:49:50 -0800 Subject: [PATCH 052/138] REndering the view rings better --- libraries/render-utils/src/drawWorkloadProxy.slf | 10 ++++++---- libraries/render-utils/src/drawWorkloadView.slv | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libraries/render-utils/src/drawWorkloadProxy.slf b/libraries/render-utils/src/drawWorkloadProxy.slf index d00739cdda..1304e68c7f 100644 --- a/libraries/render-utils/src/drawWorkloadProxy.slf +++ b/libraries/render-utils/src/drawWorkloadProxy.slf @@ -17,10 +17,12 @@ in vec4 varColor; in vec3 varTexcoord; void main(void) { - float r = sqrt(dot(varTexcoord.xyz,varTexcoord.xyz)); - float a = paintStripe(r * varColor.w, 0.0, 1.0 / varColor.w, 0.05 / varColor.w); - if (a <= 0.1 || r > 1.1) { - discard; + if (varColor.w > 0.0) { + float r = sqrt(dot(varTexcoord.xyz,varTexcoord.xyz)); + float a = paintStripe(r * varColor.w, 0.0, 1.0 / varColor.w, 0.05 / varColor.w); + if (a <= 0.1 || r > 1.1) { + discard; + } } packDeferredFragmentUnlit( diff --git a/libraries/render-utils/src/drawWorkloadView.slv b/libraries/render-utils/src/drawWorkloadView.slv index 3139072932..15adc92b80 100644 --- a/libraries/render-utils/src/drawWorkloadView.slv +++ b/libraries/render-utils/src/drawWorkloadView.slv @@ -141,5 +141,5 @@ void main(void) { <$transformEyeToClipPos(cam, proxyPosEye, gl_Position)$> // Convert region to color - varColor = vec4(colorWheel(float(regionID) / 4.0), regionRadius); + varColor = vec4(colorWheel(float(regionID) / 4.0), -1.0); } From 9e7260839c8840c52083f4c828f79634c5e845b0 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 12 Mar 2018 01:05:07 -0700 Subject: [PATCH 053/138] Better rendering of the view circles --- .../src/workload/GameWorkloadRenderer.cpp | 7 ++- .../render-utils/src/drawWorkloadView.slf | 32 +++++++++++++ .../render-utils/src/drawWorkloadView.slv | 48 +++++++++++++------ 3 files changed, 68 insertions(+), 19 deletions(-) create mode 100644 libraries/render-utils/src/drawWorkloadView.slf diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index 148454cba8..45aecee1a2 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -19,6 +19,7 @@ #include "render-utils/drawWorkloadProxy_vert.h" #include "render-utils/drawWorkloadView_vert.h" #include "render-utils/drawWorkloadProxy_frag.h" +#include "render-utils/drawWorkloadView_frag.h" void GameSpaceToRender::configure(const Config& config) { @@ -179,8 +180,8 @@ const gpu::PipelinePointer GameWorkloadRenderItem::getProxiesPipeline() { const gpu::PipelinePointer GameWorkloadRenderItem::getViewsPipeline() { if (!_drawAllViewsPipeline) { auto vs = drawWorkloadView_vert::getShader(); - // auto ps = drawWorkloadProxy_frag::getShader(); - auto ps = DrawWhite_frag::getShader(); + auto ps = drawWorkloadView_frag::getShader(); + // auto ps = DrawWhite_frag::getShader(); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; @@ -247,8 +248,6 @@ void GameWorkloadRenderItem::render(RenderArgs* args) { batch.setPipeline(getViewsPipeline()); batch.setUniformBuffer(0, getDrawViewBuffer()); - // static const int NUM_VERTICES_PER_VIEW = 27; - // batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_VIEW * _numAllViews, 0); batch.draw(gpu::TRIANGLE_STRIP, _numDrawViewVerts * 3 * 2, 0); } diff --git a/libraries/render-utils/src/drawWorkloadView.slf b/libraries/render-utils/src/drawWorkloadView.slf new file mode 100644 index 0000000000..1304e68c7f --- /dev/null +++ b/libraries/render-utils/src/drawWorkloadView.slf @@ -0,0 +1,32 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// drawItemBounds.frag +// fragment shader +// +// Created by Sam Gateau on 6/29/15. +// Copyright 2015 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 DeferredBufferWrite.slh@> +<@include gpu/Paint.slh@> + +in vec4 varColor; +in vec3 varTexcoord; + +void main(void) { + if (varColor.w > 0.0) { + float r = sqrt(dot(varTexcoord.xyz,varTexcoord.xyz)); + float a = paintStripe(r * varColor.w, 0.0, 1.0 / varColor.w, 0.05 / varColor.w); + if (a <= 0.1 || r > 1.1) { + discard; + } + } + + packDeferredFragmentUnlit( + vec3(0.0, 1.0, 0.0), + 1.0, + varColor.rgb); +} diff --git a/libraries/render-utils/src/drawWorkloadView.slv b/libraries/render-utils/src/drawWorkloadView.slv index 15adc92b80..75e4dd0a12 100644 --- a/libraries/render-utils/src/drawWorkloadView.slv +++ b/libraries/render-utils/src/drawWorkloadView.slv @@ -106,39 +106,57 @@ void main(void) { int regionVertexID = viewVertexID - regionID * NUM_VERTICES_PER_VIEW_REGION; int segmentID = regionVertexID / NUM_VERTICES_PER_SEGMENT; - int segmentVertexID = regionVertexID / NUM_VERTICES_PER_SEGMENT; + int segmentVertexID = regionVertexID - segmentID * NUM_VERTICES_PER_SEGMENT; vec4 segment = verts[segmentID]; - vec4 spriteVert = vec4(segment.xy, 0.0, 1.0); - - vec3 lateralDir = (-1.0 + 2.0 * float(segmentVertexID)) * vec3(segment.y, -segment.x, 0.0); + vec4 spriteVert = vec4(segment.y, 0.0, segment.x, 1.0); + vec3 spriteTan = vec3(segment.x, 0.0, -segment.y); + vec3 lateralDir = vec3(0.0, -1.0 + 2.0 * float(segmentVertexID), 0.0); WorkloadView view = getWorkloadView(viewID); - vec4 region = view.regions[regionID]; - vec4 proxyPosWorld = vec4(region.xyz, 1.0); float regionRadius = region.w; // Define the sprite space - vec3 dirZ = vec3(0.0, 0.0, 1.0); - vec3 dirX = vec3(1.0, 0.0, 0.0); + // vec3 dirZ = vec3(0.0, 0.0, 1.0); + // vec3 dirX = vec3(1.0, 0.0, 0.0); + // vec3 dirY = vec3(0.0, 1.0, 0.0); + + vec3 dirZ = -normalize(view.direction_far.xyz); vec3 dirY = vec3(0.0, 1.0, 0.0); + vec3 dirX = normalize(cross(dirY, dirZ)); + dirY = normalize(cross(dirZ, dirX)); + + spriteVert.xyz *= regionRadius; + + // spriteVert.xyz += (0.05 * (regionID + 1)) * lateralDir; + + vec3 originSpaceVert = (dirX * spriteVert.x + dirY * spriteVert.y + dirZ * spriteVert.z); + vec3 originSpaceTan = normalize(dirX * spriteTan.x + dirY * spriteTan.y + dirZ * spriteTan.z); - spriteVert.xyz += 0.2 * lateralDir; - vec3 originSpaceVert = regionRadius * (dirX * spriteVert.x + dirY * spriteVert.y + dirZ * spriteVert.z); vec4 pos = vec4(proxyPosWorld.xyz + originSpaceVert, 1.0); - varTexcoord = spriteVert.xyz; - // standard transform, bring proxy in view space + // standard transform, bring pos in view space TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - vec4 proxyPosEye; - <$transformModelToEyePos(cam, obj, pos, proxyPosEye)$> - <$transformEyeToClipPos(cam, proxyPosEye, gl_Position)$> + vec4 posEye; + <$transformModelToEyePos(cam, obj, pos, posEye)$> + vec3 tanEye; + <$transformModelToEyeDir(cam, obj, originSpaceTan, tanEye)$> + + lateralDir = normalize(cross(vec3(0.0, 0.0, 1.0), normalize(tanEye))); + posEye.xyz += (0.05 * (regionID + 1)) * lateralDir; + + + <$transformEyeToClipPos(cam, posEye, gl_Position)$> + + varTexcoord = spriteVert.xyz; + + // Convert region to color varColor = vec4(colorWheel(float(regionID) / 4.0), -1.0); From 69fe1ace0b58ef2be63923cee0626eba13f954ce Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 12 Mar 2018 11:59:03 -0700 Subject: [PATCH 054/138] THe View rings are rendering corectly, let s ship it --- .../render-utils/src/drawWorkloadView.slv | 52 ++----------------- 1 file changed, 4 insertions(+), 48 deletions(-) diff --git a/libraries/render-utils/src/drawWorkloadView.slv b/libraries/render-utils/src/drawWorkloadView.slv index 75e4dd0a12..25e3303a78 100644 --- a/libraries/render-utils/src/drawWorkloadView.slv +++ b/libraries/render-utils/src/drawWorkloadView.slv @@ -54,11 +54,6 @@ WorkloadView getWorkloadView(int i) { out vec4 varColor; out vec3 varTexcoord; -/*const int NUM_VERTICES_PER_VIEW = 27; -const int NUM_REGIONS_PER_VIEW = 3; -const int NUM_VERTICES_PER_VIEW_REGION = NUM_VERTICES_PER_VIEW / NUM_REGIONS_PER_VIEW; -*/ - const int NUM_VERTICES_PER_SEGMENT = 2; const int NUM_SEGMENT_PER_VIEW_REGION = 65; const int NUM_VERTICES_PER_VIEW_REGION = NUM_SEGMENT_PER_VIEW_REGION * NUM_VERTICES_PER_SEGMENT; @@ -71,34 +66,6 @@ layout(std140) uniform drawMeshBuffer { }; void main(void) { -/* const vec4 UNIT_SPRITE[NUM_VERTICES_PER_VIEW_REGION] = vec4[NUM_VERTICES_PER_VIEW_REGION]( - vec4(-1.0, -1.0, 0.0, 1.0), - vec4(3.0, -1.0, 0.0, 1.0), - vec4(-1.0, 3.0, 0.0, 1.0), - - vec4(-1.0, 0.0, -1.0, 1.0), - vec4(3.0, 0.0, -1.0, 1.0), - vec4(-1.0, 0.0, 3.0, 1.0), - - vec4(0.0, -1.0, -1.0, 1.0), - vec4(0.0, 3.0, -1.0, 1.0), - vec4(0.0, -1.0, 3.0, 1.0) - ); - const int UNIT_SPRITE_INDICES[NUM_VERTICES_PER_VIEW_REGION] = int[NUM_VERTICES_PER_VIEW_REGION]( - 0, 1, 2, 3, 4, 5, 6, 7, 8 - ); - - int viewID = gl_VertexID / NUM_VERTICES_PER_VIEW; - int viewVertexID = gl_VertexID - viewID * NUM_VERTICES_PER_VIEW; - - int regionID = viewVertexID / NUM_VERTICES_PER_VIEW_REGION; - int regionVertexID = viewVertexID - regionID * NUM_VERTICES_PER_VIEW_REGION; - - int vertexID = regionVertexID; - - vec4 spriteVert = UNIT_SPRITE[UNIT_SPRITE_INDICES[vertexID]]; -*/ - int viewID = gl_VertexID / NUM_VERTICES_PER_VIEW; int viewVertexID = gl_VertexID - viewID * NUM_VERTICES_PER_VIEW; @@ -121,25 +88,17 @@ void main(void) { float regionRadius = region.w; // Define the sprite space - // vec3 dirZ = vec3(0.0, 0.0, 1.0); - // vec3 dirX = vec3(1.0, 0.0, 0.0); - // vec3 dirY = vec3(0.0, 1.0, 0.0); - vec3 dirZ = -normalize(view.direction_far.xyz); vec3 dirY = vec3(0.0, 1.0, 0.0); vec3 dirX = normalize(cross(dirY, dirZ)); dirY = normalize(cross(dirZ, dirX)); - + spriteVert.xyz *= regionRadius; - - // spriteVert.xyz += (0.05 * (regionID + 1)) * lateralDir; - vec3 originSpaceVert = (dirX * spriteVert.x + dirY * spriteVert.y + dirZ * spriteVert.z); - vec3 originSpaceTan = normalize(dirX * spriteTan.x + dirY * spriteTan.y + dirZ * spriteTan.z); - - vec4 pos = vec4(proxyPosWorld.xyz + originSpaceVert, 1.0); + vec3 originSpaceTan = normalize(dirX * spriteTan.x + dirY * spriteTan.y + dirZ * spriteTan.z); + // standard transform, bring pos in view space TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); @@ -149,15 +108,12 @@ void main(void) { <$transformModelToEyeDir(cam, obj, originSpaceTan, tanEye)$> lateralDir = normalize(cross(vec3(0.0, 0.0, 1.0), normalize(tanEye))); - posEye.xyz += (0.05 * (regionID + 1)) * lateralDir; - + posEye.xyz += (0.05 * (regionID + 1)) * (-1.0 + 2.0 * float(segmentVertexID)) * lateralDir; <$transformEyeToClipPos(cam, posEye, gl_Position)$> varTexcoord = spriteVert.xyz; - - // Convert region to color varColor = vec4(colorWheel(float(regionID) / 4.0), -1.0); } From 3efa92b48eeb5dfb634ea4213085717a134d5420 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 12 Mar 2018 13:07:57 -0700 Subject: [PATCH 055/138] removing comment --- interface/src/workload/GameWorkloadRenderer.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index 45aecee1a2..55d1877145 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -15,7 +15,6 @@ #include #include -#include #include "render-utils/drawWorkloadProxy_vert.h" #include "render-utils/drawWorkloadView_vert.h" #include "render-utils/drawWorkloadProxy_frag.h" @@ -181,7 +180,6 @@ const gpu::PipelinePointer GameWorkloadRenderItem::getViewsPipeline() { if (!_drawAllViewsPipeline) { auto vs = drawWorkloadView_vert::getShader(); auto ps = drawWorkloadView_frag::getShader(); - // auto ps = DrawWhite_frag::getShader(); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; From b922331b0515db5260f94e2d5cb2ba6a144de417 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 12 Mar 2018 13:40:00 -0700 Subject: [PATCH 056/138] Address comments from review --- interface/src/workload/GameWorkloadRenderer.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index 55d1877145..8509405eb0 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -203,7 +203,7 @@ const gpu::PipelinePointer GameWorkloadRenderItem::getViewsPipeline() { const gpu::BufferPointer GameWorkloadRenderItem::getDrawViewBuffer() { if (!_drawViewBuffer) { int numSegments = 64; - float angleStep = M_PI * 2.0 / (float)numSegments; + float angleStep = (float)M_PI * 2.0f / (float)numSegments; struct Vert { glm::vec4 p; @@ -214,10 +214,10 @@ const gpu::BufferPointer GameWorkloadRenderItem::getDrawViewBuffer() { verts[i].p.x = cos(angle); verts[i].p.y = sin(angle); verts[i].p.z = angle; - verts[i].p.w = 1.0; + verts[i].p.w = 1.0f; } verts[numSegments] = verts[0]; - verts[numSegments].p.w = 0.0; + verts[numSegments].p.w = 0.0f; _drawViewBuffer = std::make_shared(verts.size() * sizeof(Vert), (const gpu::Byte*) verts.data()); _numDrawViewVerts = numSegments + 1; @@ -246,7 +246,9 @@ void GameWorkloadRenderItem::render(RenderArgs* args) { batch.setPipeline(getViewsPipeline()); batch.setUniformBuffer(0, getDrawViewBuffer()); - batch.draw(gpu::TRIANGLE_STRIP, _numDrawViewVerts * 3 * 2, 0); + static const int NUM_VERTICES_PER_DRAWVIEWVERT = 2; + static const int NUM_REGIONS = 3; + batch.draw(gpu::TRIANGLE_STRIP, NUM_REGIONS * NUM_VERTICES_PER_DRAWVIEWVERT * _numDrawViewVerts, 0); } From 74be67edb14fe27eff8bf38d5f1d598cf3404c12 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 12 Mar 2018 14:40:09 -0700 Subject: [PATCH 057/138] fixing the default state plus upstream master merged again --- interface/src/workload/GameWorkloadRenderer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/workload/GameWorkloadRenderer.h b/interface/src/workload/GameWorkloadRenderer.h index c784857fdf..7a0800d40c 100644 --- a/interface/src/workload/GameWorkloadRenderer.h +++ b/interface/src/workload/GameWorkloadRenderer.h @@ -21,7 +21,7 @@ public: bool freezeViews{ false }; bool showProxies{ false }; - bool showViews{ true }; + bool showViews{ false }; signals: void dirty(); From ea9dee1286f5fcd361296ecccd02f705f33be145 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 12 Mar 2018 17:49:45 -0700 Subject: [PATCH 058/138] FIrst step introducing the Transaction model to access the Proxy of the space --- libraries/workload/src/workload/Proxy.h | 38 +++ libraries/workload/src/workload/Space.h | 49 ++-- .../workload/src/workload/Transaction.cpp | 235 ++++++++++++++++++ libraries/workload/src/workload/Transaction.h | 166 +++++++++++++ 4 files changed, 468 insertions(+), 20 deletions(-) create mode 100644 libraries/workload/src/workload/Proxy.h create mode 100644 libraries/workload/src/workload/Transaction.cpp create mode 100644 libraries/workload/src/workload/Transaction.h diff --git a/libraries/workload/src/workload/Proxy.h b/libraries/workload/src/workload/Proxy.h new file mode 100644 index 0000000000..bf3de6e4c9 --- /dev/null +++ b/libraries/workload/src/workload/Proxy.h @@ -0,0 +1,38 @@ +// +// Proxy.h +// libraries/workload/src/workload +// +// Created by Andrew Meadows 2018.01.30 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_workload_Proxy_h +#define hifi_workload_Proxy_h + +#include "View.h" + +namespace workload { + +using Index = int32_t; +using ProxyID = Index; + +using IndexVector = std::vector; + +class Proxy { +public: + Proxy() : sphere(0.0f) {} + Proxy(const Sphere& s) : sphere(s) {} + + Sphere sphere; + uint8_t region{ Region::UNKNOWN }; + uint8_t prevRegion{ Region::UNKNOWN }; + uint16_t _padding; + uint32_t _paddings[3]; +}; + + +} // namespace workload + +#endif // hifi_workload_Proxy_h diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index 0acd69194b..699d44f7a1 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -19,29 +19,14 @@ #include #include -#include "View.h" - +#include "Transaction.h" namespace workload { -using IndexVector = std::vector; - class Space { public: - using Sphere = glm::vec4; // = center, w = radius using ProxyUpdate = std::pair; - class Proxy { - public: - Proxy() : sphere(0.0f) {} - Proxy(const Sphere& s) : sphere(s) {} - Sphere sphere; - uint8_t region { Region::UNKNOWN }; - uint8_t prevRegion { Region::UNKNOWN }; - uint16_t _padding; - uint32_t _paddings[3]; - }; - class Change { public: Change(int32_t i, uint32_t c, uint32_t p) : proxyId(i), region(c), prevRegion(p) {} @@ -52,10 +37,27 @@ public: Space() {} - void clear(); - int32_t createProxy(const Sphere& sphere); - void deleteProxies(const IndexVector& deadIndices); - void updateProxies(const std::vector& changedProxies); + // This call is thread safe, can be called from anywhere to allocate a new ID + ProxyID allocateID(); + + // Check that the ID is valid and allocated for this space, this a threadsafe call + bool isAllocatedID(const ProxyID& id) const; + + // THis is the total number of allocated proxies, this a threadsafe call + Index getNumAllocatedProxies() const { return _numAllocatedProxies.load(); } + + // Enqueue transaction to the space + void enqueueTransaction(const Transaction& transaction); + + // Enqueue transaction to the space + void enqueueTransaction(Transaction&& transaction); + + // Enqueue end of frame transactions boundary + uint32_t enqueueFrame(); + + // Process the pending transactions queued + void processTransactionQueue(); + void setViews(const std::vector& views); uint32_t getNumViews() const { return (uint32_t)(_views.size()); } @@ -69,6 +71,13 @@ public: uint32_t copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const; private: + + + void clear(); + int32_t createProxy(const Sphere& sphere); + void deleteProxies(const IndexVector& deadIndices); + void updateProxies(const std::vector& changedProxies); + void deleteProxy(int32_t proxyId); void updateProxy(int32_t proxyId, const Sphere& sphere); diff --git a/libraries/workload/src/workload/Transaction.cpp b/libraries/workload/src/workload/Transaction.cpp new file mode 100644 index 0000000000..3a5e0b31d8 --- /dev/null +++ b/libraries/workload/src/workload/Transaction.cpp @@ -0,0 +1,235 @@ +// +// Transaction.cpp +// libraries/workload/src/workload +// +// Created by Sam Gateau 2018.03.12 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "Transaction.h" + +using namespace workload; + + +void Transaction::resetItem(ItemID id, PayloadPointer& payload) { + if (payload) { + _resetItems.emplace_back(Reset{ id, payload }); + } else { + qCDebug(renderlogging) << "WARNING: Transaction::resetItem with a null payload!"; + removeItem(id); + } +} + +void Transaction::removeItem(ItemID id) { + _removedItems.emplace_back(id); +} + +void Transaction::updateItem(ItemID id, const UpdateFunctorPointer& functor) { + _updatedItems.emplace_back(id, functor); +} + +void Transaction::reserve(const std::vector& transactionContainer) { + size_t resetItemsCount = 0; + size_t removedItemsCount = 0; + size_t updatedItemsCount = 0; + + for (const auto& transaction : transactionContainer) { + resetItemsCount += transaction._resetItems.size(); + removedItemsCount += transaction._removedItems.size(); + updatedItemsCount += transaction._updatedItems.size(); + } + + _resetItems.reserve(resetItemsCount); + _removedItems.reserve(removedItemsCount); + _updatedItems.reserve(updatedItemsCount); +} + +void Transaction::merge(const std::vector& transactionContainer) { + reserve(transactionContainer); + for (const auto& transaction : transactionContainer) { + merge(transaction); + } +} + + +void Transaction::merge(std::vector&& transactionContainer) { + reserve(transactionContainer); + auto begin = std::make_move_iterator(transactionContainer.begin()); + auto end = std::make_move_iterator(transactionContainer.end()); + for (auto itr = begin; itr != end; ++itr) { + merge(*itr); + } + transactionContainer.clear(); +} + + +template +void moveElements(T& target, T& source) { + target.insert(target.end(), std::make_move_iterator(source.begin()), std::make_move_iterator(source.end())); + source.clear(); +} + +template +void copyElements(T& target, const T& source) { + target.insert(target.end(), source.begin(), source.end()); +} + + +void Transaction::merge(Transaction&& transaction) { + moveElements(_resetItems, transaction._resetItems); + moveElements(_removedItems, transaction._removedItems); + moveElements(_updatedItems, transaction._updatedItems); +} + +void Transaction::merge(const Transaction& transaction) { + copyElements(_resetItems, transaction._resetItems); + copyElements(_removedItems, transaction._removedItems); + copyElements(_updatedItems, transaction._updatedItems); +} + +void Transaction::clear() { + _resetItems.clear(); + _removedItems.clear(); + _updatedItems.clear(); +} + + + + +Collection::Collection() { + _items.push_back(Item()); // add the itemID #0 to nothing +} + +Collection::~Collection() { + qCDebug(renderlogging) << "Scene::~Scene()"; +} + +ItemID Collection::allocateID() { + // Just increment and return the proevious value initialized at 0 + return _IDAllocator.fetch_add(1); +} + +bool Collection::isAllocatedID(const ItemID& id) const { + return Item::isValidID(id) && (id < _numAllocatedItems.load()); +} + +/// Enqueue change batch to the scene +void Collection::enqueueTransaction(const Transaction& transaction) { + std::unique_lock lock(_transactionQueueMutex); + _transactionQueue.emplace_back(transaction); +} + +void Collection::enqueueTransaction(Transaction&& transaction) { + std::unique_lock lock(_transactionQueueMutex); + _transactionQueue.emplace_back(std::move(transaction)); +} + +uint32_t Collection::enqueueFrame() { + PROFILE_RANGE(render, __FUNCTION__); + TransactionQueue localTransactionQueue; + { + std::unique_lock lock(_transactionQueueMutex); + localTransactionQueue.swap(_transactionQueue); + } + + Transaction consolidatedTransaction; + consolidatedTransaction.merge(std::move(localTransactionQueue)); + { + std::unique_lock lock(_transactionFramesMutex); + _transactionFrames.push_back(consolidatedTransaction); + } + + return ++_transactionFrameNumber; +} + + +void Collection::processTransactionQueue() { + PROFILE_RANGE(render, __FUNCTION__); + + static TransactionFrames queuedFrames; + { + // capture the queued frames and clear the queue + std::unique_lock lock(_transactionFramesMutex); + queuedFrames.swap(_transactionFrames); + } + + // go through the queue of frames and process them + for (auto& frame : queuedFrames) { + processTransactionFrame(frame); + } + + queuedFrames.clear(); +} + +void Collection::processTransactionFrame(const Transaction& transaction) { + PROFILE_RANGE(render, __FUNCTION__); + { + std::unique_lock lock(_itemsMutex); + // Here we should be able to check the value of last ItemID allocated + // and allocate new items accordingly + ItemID maxID = _IDAllocator.load(); + if (maxID > _items.size()) { + _items.resize(maxID + 100); // allocate the maxId and more + } + // Now we know for sure that we have enough items in the array to + // capture anything coming from the transaction + + // resets and potential NEW items + resetItems(transaction._resetItems); + + // Update the numItemsAtomic counter AFTER the reset changes went through + _numAllocatedItems.exchange(maxID); + + // updates + updateItems(transaction._updatedItems); + + // removes + removeItems(transaction._removedItems); + + // add transitions + transitionItems(transaction._addedTransitions); + reApplyTransitions(transaction._reAppliedTransitions); + queryTransitionItems(transaction._queriedTransitions); + + // Update the numItemsAtomic counter AFTER the pending changes went through + _numAllocatedItems.exchange(maxID); + } +} + +void Collection::resetItems(const Transaction::Resets& transactions) { + for (auto& reset : transactions) { + // Access the true item + auto itemId = std::get<0>(reset); + auto& item = _items[itemId]; + + // Reset the item with a new payload + item.resetPayload(std::get<1>(reset)); + } +} + +void Collection::removeItems(const Transaction::Removes& transactions) { + for (auto removedID : transactions) { + // Access the true item + auto& item = _items[removedID]; + + // Kill it + item.kill(); + } +} + +void Collection::updateItems(const Transaction::Updates& transactions) { + for (auto& update : transactions) { + auto updateID = std::get<0>(update); + if (updateID == Item::INVALID_ITEM_ID) { + continue; + } + + // Access the true item + auto& item = _items[updateID]; + + // Update the item + item.update(std::get<1>(update)); + } +} \ No newline at end of file diff --git a/libraries/workload/src/workload/Transaction.h b/libraries/workload/src/workload/Transaction.h new file mode 100644 index 0000000000..87bf0e4209 --- /dev/null +++ b/libraries/workload/src/workload/Transaction.h @@ -0,0 +1,166 @@ +// +// Transaction.h +// libraries/workload/src/workload +// +// Created by Sam Gateau 2018.03.12 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_workload_Transaction_h +#define hifi_workload_Transaction_h + +#include +#include +#include + +#include "Proxy.h" + + +namespace workload { + +// Transaction is the mechanism to make any change to the Space. +// Whenever a new proxy need to be reset, +// or when an proxy changes its position or its size +// or when an proxy is destroyed +// These changes must be expressed through the corresponding command from the Transaction +// The Transaction is then queued on the Space so all the pending transactions can be consolidated and processed at the time +// of updating the space at the Frame boundary. +// +class Transaction { + friend class Space; +public: + using ProxyPayload = Sphere; + + Transaction() {} + ~Transaction() {} + + // Proxy transactions + void reset(ProxyID id, const ProxyPayload& sphere); + void remove(ProxyID id); + bool hasRemovals() const { return !_removedItems.empty(); } + + void update(ProxyID id, const ProxyPayload& sphere); + + void reserve(const std::vector& transactionContainer); + void merge(const std::vector& transactionContainer); + void merge(std::vector&& transactionContainer); + void merge(const Transaction& transaction); + void merge(Transaction&& transaction); + void clear(); + +protected: + + using Reset = std::tuple; + using Remove = ProxyID; + using Update = std::tuple; + + using Resets = std::vector; + using Removes = std::vector; + using Updates = std::vector; + + Resets _resetItems; + Removes _removedItems; + Updates _updatedItems; +}; +typedef std::vector TransactionQueue; + +namespace indexed_container { + + using Index = int32_t; + const Index MAXIMUM_INDEX{ 1 << 30 }; + const Index INVALID_INDEX{ -1 }; + using Indices = std::vector< Index >; + + template + class Allocator { + public: + Allocator() {} + Indices _freeIndices; + std::atomic _nextNewIndex{ 0 }; + std::atomic _numFreeIndices{ 0 }; + + bool checkIndex(Index index) const { return ((index >= 0) && (index < _nextNewIndex.load())); } + Index getNumIndices() const { return _nextNewIndex - (Index)_freeIndices.size(); } + Index getNumFreeIndices() const { return (Index)_freeIndices.size(); } + Index getNumAllocatedIndices() const { return _nextNewIndex.load(); } + + Index allocateIndex() { + if (_freeIndices.empty()) { + Index index = _nextNewIndex; + if (index >= MaxNumElements) { + // abort! we are trying to go overboard with the total number of allocated elements + assert(false); + // This should never happen because Bricks are allocated along with the cells and there + // is already a cap on the cells allocation + return INVALID_INDEX; + } + _nextNewIndex++; + return index; + } else { + Index index = _freeIndices.back(); + _freeIndices.pop_back(); + return index; + } + } + + void freeIndex(Index index) { + if (checkIndex(index)) { + _freeIndices.push_back(index); + } + } + + void clear() { + _freeIndices.clear(); + _nextNewIndex = 0; + } + }; +} + +class Collection { +public: + + // This call is thread safe, can be called from anywhere to allocate a new ID + ProxyID allocateID(); + + // Check that the ID is valid and allocated for this space, this a threadsafe call + bool isAllocatedID(const ProxyID& id) const; + + // THis is the total number of allocated proxies, this a threadsafe call + Index getNumAllocatedProxies() const { return _numAllocatedProxies.load(); } + + // Enqueue transaction to the space + void enqueueTransaction(const Transaction& transaction); + + // Enqueue transaction to the space + void enqueueTransaction(Transaction&& transaction); + + // Enqueue end of frame transactions boundary + uint32_t enqueueFrame(); + + // Process the pending transactions queued + void processTransactionQueue(); + +protected: + + // Thread safe elements that can be accessed from anywhere + std::atomic _IDAllocator{ 1 }; // first valid itemID will be One + std::atomic _numAllocatedItems{ 1 }; // num of allocated items, matching the _items.size() + std::mutex _transactionQueueMutex; + TransactionQueue _transactionQueue; + + + std::mutex _transactionFramesMutex; + using TransactionFrames = std::vector; + TransactionFrames _transactionFrames; + uint32_t _transactionFrameNumber{ 0 }; + + // Process one transaction frame + void processTransactionFrame(const Transaction& transaction); +}; + +} // namespace workload + +#endif // hifi_workload_Transaction_h \ No newline at end of file From 1af139a4d42f6d5aa8f0f575029aebdd7d68da0d Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 12 Mar 2018 18:01:22 -0700 Subject: [PATCH 059/138] FIrst step introducing the Transaction model to access the Proxy of the space --- libraries/workload/src/workload/Proxy.h | 5 - libraries/workload/src/workload/Transaction.h | 120 ++++++++++-------- 2 files changed, 65 insertions(+), 60 deletions(-) diff --git a/libraries/workload/src/workload/Proxy.h b/libraries/workload/src/workload/Proxy.h index bf3de6e4c9..b7f8094b00 100644 --- a/libraries/workload/src/workload/Proxy.h +++ b/libraries/workload/src/workload/Proxy.h @@ -15,11 +15,6 @@ namespace workload { -using Index = int32_t; -using ProxyID = Index; - -using IndexVector = std::vector; - class Proxy { public: Proxy() : sphere(0.0f) {} diff --git a/libraries/workload/src/workload/Transaction.h b/libraries/workload/src/workload/Transaction.h index 87bf0e4209..098e953f36 100644 --- a/libraries/workload/src/workload/Transaction.h +++ b/libraries/workload/src/workload/Transaction.h @@ -12,6 +12,8 @@ #ifndef hifi_workload_Transaction_h #define hifi_workload_Transaction_h +#include +#include #include #include #include @@ -21,6 +23,64 @@ namespace workload { + namespace indexed_container { + + using Index = int32_t; + const Index MAXIMUM_INDEX{ 1 << 30 }; + const Index INVALID_INDEX{ -1 }; + using Indices = std::vector< Index >; + + template + class Allocator { + public: + Allocator() {} + Indices _freeIndices; + Index _nextNewIndex{ 0 }; + + bool checkIndex(Index index) const { return ((index >= 0) && (index < _nextNewIndex)); } + Index getNumIndices() const { return _nextNewIndex - (Index)_freeIndices.size(); } + Index getNumFreeIndices() const { return (Index)_freeIndices.size(); } + Index getNumAllocatedIndices() const { return _nextNewIndex; } + + Index allocateIndex() { + if (_freeIndices.empty()) { + Index index = _nextNewIndex; + if (index >= MaxNumElements) { + // abort! we are trying to go overboard with the total number of allocated elements + assert(false); + // This should never happen because Bricks are allocated along with the cells and there + // is already a cap on the cells allocation + return INVALID_INDEX; + } + _nextNewIndex++; + return index; + } else { + Index index = _freeIndices.back(); + _freeIndices.pop_back(); + return index; + } + } + + void freeIndex(Index index) { + if (checkIndex(index)) { + _freeIndices.push_back(index); + } + } + + void clear() { + _freeIndices.clear(); + _nextNewIndex = 0; + } + }; + } + + + using Index = indexed_container::Index; + using IndexVector = indexed_container::Indices; + + using ProxyID = Index; + + // Transaction is the mechanism to make any change to the Space. // Whenever a new proxy need to be reset, // or when an proxy changes its position or its size @@ -67,58 +127,6 @@ protected: }; typedef std::vector TransactionQueue; -namespace indexed_container { - - using Index = int32_t; - const Index MAXIMUM_INDEX{ 1 << 30 }; - const Index INVALID_INDEX{ -1 }; - using Indices = std::vector< Index >; - - template - class Allocator { - public: - Allocator() {} - Indices _freeIndices; - std::atomic _nextNewIndex{ 0 }; - std::atomic _numFreeIndices{ 0 }; - - bool checkIndex(Index index) const { return ((index >= 0) && (index < _nextNewIndex.load())); } - Index getNumIndices() const { return _nextNewIndex - (Index)_freeIndices.size(); } - Index getNumFreeIndices() const { return (Index)_freeIndices.size(); } - Index getNumAllocatedIndices() const { return _nextNewIndex.load(); } - - Index allocateIndex() { - if (_freeIndices.empty()) { - Index index = _nextNewIndex; - if (index >= MaxNumElements) { - // abort! we are trying to go overboard with the total number of allocated elements - assert(false); - // This should never happen because Bricks are allocated along with the cells and there - // is already a cap on the cells allocation - return INVALID_INDEX; - } - _nextNewIndex++; - return index; - } else { - Index index = _freeIndices.back(); - _freeIndices.pop_back(); - return index; - } - } - - void freeIndex(Index index) { - if (checkIndex(index)) { - _freeIndices.push_back(index); - } - } - - void clear() { - _freeIndices.clear(); - _nextNewIndex = 0; - } - }; -} - class Collection { public: @@ -129,7 +137,7 @@ public: bool isAllocatedID(const ProxyID& id) const; // THis is the total number of allocated proxies, this a threadsafe call - Index getNumAllocatedProxies() const { return _numAllocatedProxies.load(); } + Index getNumAllocatedProxies() const { return _IDAllocator.getNumAllocatedIndices(); } // Enqueue transaction to the space void enqueueTransaction(const Transaction& transaction); @@ -146,8 +154,10 @@ public: protected: // Thread safe elements that can be accessed from anywhere - std::atomic _IDAllocator{ 1 }; // first valid itemID will be One - std::atomic _numAllocatedItems{ 1 }; // num of allocated items, matching the _items.size() + indexed_container::Allocator<> _IDAllocator; + + //std::atomic _IDAllocator{ 1 }; // first valid itemID will be One + //std::atomic _numAllocatedItems{ 1 }; // num of allocated items, matching the _items.size() std::mutex _transactionQueueMutex; TransactionQueue _transactionQueue; From a2993c7cdb7bda77b60bf9cc7adc39452b241a51 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 13 Mar 2018 01:45:21 -0700 Subject: [PATCH 060/138] First version wof space working with Transaction & Collection --- .../src/workload/GameWorkloadRenderer.cpp | 6 +- interface/src/workload/GameWorkloadRenderer.h | 4 +- .../src/EntityTreeRenderer.cpp | 15 ++- .../src/EntityTreeRenderer.h | 2 +- libraries/workload/src/workload/Engine.cpp | 11 ++ libraries/workload/src/workload/Engine.h | 18 +++ libraries/workload/src/workload/Proxy.h | 6 +- libraries/workload/src/workload/Space.cpp | 116 +++++++++++++++--- libraries/workload/src/workload/Space.h | 55 +++------ .../workload/src/workload/Transaction.cpp | 86 ++++++------- libraries/workload/src/workload/Transaction.h | 31 +++-- 11 files changed, 229 insertions(+), 121 deletions(-) diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index 8509405eb0..c21f93d764 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -56,7 +56,7 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, return; } - std::vector proxies(space->getNumAllocatedProxies()); + workload::Proxy::Vector proxies(space->getNumAllocatedProxies()); space->copyProxyValues(proxies.data(), (uint32_t)proxies.size()); workload::Views views(space->getNumViews()); @@ -130,9 +130,9 @@ void GameWorkloadRenderItem::showViews(bool show) { } -void GameWorkloadRenderItem::setAllProxies(const std::vector& proxies) { +void GameWorkloadRenderItem::setAllProxies(const workload::Proxy::Vector& proxies) { _myOwnProxies = proxies; - static const uint32_t sizeOfProxy = sizeof(workload::Space::Proxy); + static const uint32_t sizeOfProxy = sizeof(workload::Proxy); if (!_allProxiesBuffer) { _allProxiesBuffer = std::make_shared(sizeOfProxy); } diff --git a/interface/src/workload/GameWorkloadRenderer.h b/interface/src/workload/GameWorkloadRenderer.h index 7a0800d40c..36cb32f152 100644 --- a/interface/src/workload/GameWorkloadRenderer.h +++ b/interface/src/workload/GameWorkloadRenderer.h @@ -63,7 +63,7 @@ public: void showProxies(bool show); void showViews(bool show); - void setAllProxies(const std::vector& proxies); + void setAllProxies(const workload::Proxy::Vector& proxies); void setAllViews(const workload::Views& views); render::ItemKey getKey() const; @@ -71,7 +71,7 @@ public: protected: render::Item::Bound _bound; - std::vector _myOwnProxies; + workload::Proxy::Vector _myOwnProxies; gpu::BufferPointer _allProxiesBuffer; uint32_t _numAllProxies{ 0 }; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 04e8c9a414..dfb888f9cb 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -281,8 +281,11 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r } if (entity->getSpaceIndex() == -1) { std::unique_lock lock(_spaceLock); - workload::Space::Sphere sphere(entity->getWorldPosition(), entity->getBoundingRadius()); - int32_t spaceIndex = _space->createProxy(sphere); + auto spaceIndex = _space->allocateID(); + workload::Sphere sphere(entity->getWorldPosition(), entity->getBoundingRadius()); + workload::Transaction transaction; + transaction.reset(spaceIndex, sphere); + _space->enqueueTransaction(transaction); entity->setSpaceIndex(spaceIndex); connect(entity.get(), &EntityItem::spaceUpdate, this, &EntityTreeRenderer::handleSpaceUpdate, Qt::QueuedConnection); } @@ -427,17 +430,19 @@ void EntityTreeRenderer::update(bool simulate) { scene->enqueueTransaction(transaction); } } + workload::Transaction spaceTransaction; { // update proxies in the workload::Space std::unique_lock lock(_spaceLock); - _space->updateProxies(_spaceUpdates); + spaceTransaction.update(_spaceUpdates); _spaceUpdates.clear(); } { std::vector staleProxies; tree->swapStaleProxies(staleProxies); + spaceTransaction.remove(staleProxies); { std::unique_lock lock(_spaceLock); - _space->deleteProxies(staleProxies); + _space->enqueueTransaction(spaceTransaction); } } @@ -458,7 +463,7 @@ void EntityTreeRenderer::update(bool simulate) { void EntityTreeRenderer::handleSpaceUpdate(std::pair proxyUpdate) { std::unique_lock lock(_spaceLock); - _spaceUpdates.push_back(proxyUpdate); + _spaceUpdates.emplace_back(proxyUpdate.first, proxyUpdate.second); } bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QVector* entitiesContainingAvatar) { diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 5840dc6832..fa9c2ac6d2 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -270,7 +270,7 @@ private: mutable std::mutex _spaceLock; workload::SpacePointer _space{ new workload::Space() }; - std::vector _spaceUpdates; + workload::Transaction::Updates _spaceUpdates; }; diff --git a/libraries/workload/src/workload/Engine.cpp b/libraries/workload/src/workload/Engine.cpp index 525872f190..0bb9c73fa0 100644 --- a/libraries/workload/src/workload/Engine.cpp +++ b/libraries/workload/src/workload/Engine.cpp @@ -29,6 +29,7 @@ namespace workload { using JobModel = Task::ModelI; void build(JobModel& model, const Varying& in, Varying& out) { model.addJob("setupViews", in); + model.addJob("updateSpace"); const auto regionChanges = model.addJob("regionTracker"); model.addJob("regionState", regionChanges); @@ -38,5 +39,15 @@ namespace workload { Engine::Engine(const WorkloadContextPointer& context) : Task("Engine", EngineBuilder::JobModel::create()), _context(context) { } + + + void PerformSpaceTransaction::configure(const Config& config) { + + } + void PerformSpaceTransaction::run(const WorkloadContextPointer& context) { + context->_space->enqueueFrame(); + context->_space->processTransactionQueue(); + } + } // namespace workload diff --git a/libraries/workload/src/workload/Engine.h b/libraries/workload/src/workload/Engine.h index aa45b03a20..773cfcb752 100644 --- a/libraries/workload/src/workload/Engine.h +++ b/libraries/workload/src/workload/Engine.h @@ -50,6 +50,24 @@ namespace workload { }; using EnginePointer = std::shared_ptr; + class PerformSpaceTransactionConfig : public Job::Config { + Q_OBJECT + public: + signals : + void dirty(); + + protected: + }; + + class PerformSpaceTransaction { + public: + using Config = PerformSpaceTransactionConfig; + using JobModel = Job::Model; + + void configure(const Config& config); + void run(const WorkloadContextPointer& context); + protected: + }; } // namespace workload #endif // hifi_workload_Space_h diff --git a/libraries/workload/src/workload/Proxy.h b/libraries/workload/src/workload/Proxy.h index b7f8094b00..9248c2bb31 100644 --- a/libraries/workload/src/workload/Proxy.h +++ b/libraries/workload/src/workload/Proxy.h @@ -21,10 +21,12 @@ public: Proxy(const Sphere& s) : sphere(s) {} Sphere sphere; - uint8_t region{ Region::UNKNOWN }; - uint8_t prevRegion{ Region::UNKNOWN }; + uint8_t region{ Region::INVALID }; + uint8_t prevRegion{ Region::INVALID }; uint16_t _padding; uint32_t _paddings[3]; + + using Vector = std::vector; }; diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index c2323fc0a1..45192b2a10 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -20,11 +20,80 @@ using namespace workload; -void Space::clear() { - _proxies.clear(); - _freeIndices.clear(); +Space::Space() : Collection() { + } + +void Space::processTransactionFrame(const Transaction& transaction) { + std::unique_lock lock(_proxiesMutex); + // Here we should be able to check the value of last ProxyID allocated + // and allocate new proxies accordingly + ProxyID maxID = _IDAllocator.getNumAllocatedIndices(); + if (maxID > _proxies.size()) { + _proxies.resize(maxID + 100); // allocate the maxId and more + } + // Now we know for sure that we have enough items in the array to + // capture anything coming from the transaction + + // resets and potential NEW items + processResets(transaction._resetItems); + + // Update the numItemsAtomic counter AFTER the reset changes went through + // _numAllocatedItems.exchange(maxID); + + // updates + processUpdates(transaction._updatedItems); + + // removes + processRemoves(transaction._removedItems); + + + // Update the numItemsAtomic counter AFTER the pending changes went through + // _numAllocatedItems.exchange(maxID); +} + +void Space::processResets(const Transaction::Resets& transactions) { + for (auto& reset : transactions) { + // Access the true item + auto ProxyID = std::get<0>(reset); + auto& item = _proxies[ProxyID]; + + // Reset the item with a new payload + item.sphere = (std::get<1>(reset)); + item.prevRegion = item.region = Region::UNKNOWN; + } +} + +void Space::processRemoves(const Transaction::Removes& transactions) { + for (auto removedID : transactions) { + _IDAllocator.freeIndex(removedID); + + // Access the true item + auto& item = _proxies[removedID]; + + // Kill it + item.prevRegion = item.region = Region::INVALID; + } +} + +void Space::processUpdates(const Transaction::Updates& transactions) { + for (auto& update : transactions) { + auto updateID = std::get<0>(update); + if (updateID == INVALID_PROXY_ID) { + continue; + } + + // Access the true item + auto& item = _proxies[updateID]; + + // Update the item + // item.update(std::get<1>(update)); + item.sphere = (std::get<1>(update)); + item.prevRegion = item.region = Region::UNKNOWN; + } +} +/* int32_t Space::createProxy(const Space::Sphere& newSphere) { if (_freeIndices.empty()) { _proxies.emplace_back(Space::Proxy(newSphere)); @@ -37,32 +106,25 @@ int32_t Space::createProxy(const Space::Sphere& newSphere) { _proxies[index].prevRegion = Region::UNKNOWN; return index; } -} - +}*/ +/* void Space::deleteProxies(const std::vector& deadIndices) { for (uint32_t i = 0; i < deadIndices.size(); ++i) { deleteProxy(deadIndices[i]); } } - -void Space::updateProxies(const std::vector& changedProxies) { +*/ +/*void Space::updateProxies(const std::vector& changedProxies) { for (uint32_t i = 0; i < changedProxies.size(); ++i) { int32_t proxyId = changedProxies[i].first; if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) { updateProxy(changedProxies[i].first, changedProxies[i].second); } } -} - -void Space::setViews(const Views& views) { - _views = views; -} - -void Space::copyViews(std::vector& copy) const { - copy = _views; -} +}*/ void Space::categorizeAndGetChanges(std::vector& changes) { + std::unique_lock lock(_proxiesMutex); uint32_t numProxies = (uint32_t)_proxies.size(); uint32_t numViews = (uint32_t)_views.size(); for (uint32_t i = 0; i < numProxies; ++i) { @@ -92,7 +154,7 @@ void Space::categorizeAndGetChanges(std::vector& changes) { } // private -void Space::deleteProxy(int32_t proxyId) { +/*void Space::deleteProxy(int32_t proxyId) { if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) { if (proxyId == (int32_t)_proxies.size() - 1) { // remove proxy on back @@ -110,9 +172,10 @@ void Space::deleteProxy(int32_t proxyId) { _freeIndices.push_back(proxyId); } } -} +}*/ uint32_t Space::copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const { + std::unique_lock lock(_proxiesMutex); auto numCopied = std::min(numDestProxies, (uint32_t)_proxies.size()); memcpy(proxies, _proxies.data(), numCopied * sizeof(Proxy)); return numCopied; @@ -120,9 +183,24 @@ uint32_t Space::copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const { // private -void Space::updateProxy(int32_t proxyId, const Space::Sphere& newSphere) { +/*void Space::updateProxy(int32_t proxyId, const Space::Sphere& newSphere) { if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) { _proxies[proxyId].sphere = newSphere; } +}*/ + +void Space::clear() { + std::unique_lock lock(_proxiesMutex); + _IDAllocator.clear(); + _proxies.clear(); + _views.clear(); } + +void Space::setViews(const Views& views) { + _views = views; +} + +void Space::copyViews(std::vector& copy) const { + copy = _views; +} diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index 699d44f7a1..200d8d9ac3 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -23,7 +23,7 @@ namespace workload { -class Space { +class Space : public Collection { public: using ProxyUpdate = std::pair; @@ -35,55 +35,40 @@ public: uint8_t prevRegion { 0 }; }; - Space() {} + Space(); - // This call is thread safe, can be called from anywhere to allocate a new ID - ProxyID allocateID(); - - // Check that the ID is valid and allocated for this space, this a threadsafe call - bool isAllocatedID(const ProxyID& id) const; - - // THis is the total number of allocated proxies, this a threadsafe call - Index getNumAllocatedProxies() const { return _numAllocatedProxies.load(); } - - // Enqueue transaction to the space - void enqueueTransaction(const Transaction& transaction); - - // Enqueue transaction to the space - void enqueueTransaction(Transaction&& transaction); - - // Enqueue end of frame transactions boundary - uint32_t enqueueFrame(); - - // Process the pending transactions queued - void processTransactionQueue(); - - void setViews(const std::vector& views); + void setViews(const Views& views); uint32_t getNumViews() const { return (uint32_t)(_views.size()); } void copyViews(std::vector& copy) const; - - uint32_t getNumObjects() const { return (uint32_t)(_proxies.size() - _freeIndices.size()); } - uint32_t getNumAllocatedProxies() const { return (uint32_t)(_proxies.size()); } + uint32_t getNumObjects() const { return _IDAllocator.getNumLiveIndices(); } // (uint32_t)(_proxies.size() - _freeIndices.size()); } + uint32_t getNumAllocatedProxies() const { return (uint32_t)(_IDAllocator.getNumAllocatedIndices()); } void categorizeAndGetChanges(std::vector& changes); uint32_t copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const; + void clear(); private: + virtual void processTransactionFrame(const Transaction& transaction); + void processResets(const Transaction::Resets& transactions); + void processRemoves(const Transaction::Removes& transactions); + void processUpdates(const Transaction::Updates& transactions); - void clear(); - int32_t createProxy(const Sphere& sphere); - void deleteProxies(const IndexVector& deadIndices); - void updateProxies(const std::vector& changedProxies); + // int32_t createProxy(const Sphere& sphere); + // void deleteProxies(const IndexVector& deadIndices); + // void updateProxies(const std::vector& changedProxies); - void deleteProxy(int32_t proxyId); - void updateProxy(int32_t proxyId, const Sphere& sphere); + // void deleteProxy(int32_t proxyId); + // void updateProxy(int32_t proxyId, const Sphere& sphere); + + + // The database of proxies is protected for editing by a mutex + mutable std::mutex _proxiesMutex; + Proxy::Vector _proxies; - std::vector _proxies; Views _views; - IndexVector _freeIndices; }; using SpacePointer = std::shared_ptr; diff --git a/libraries/workload/src/workload/Transaction.cpp b/libraries/workload/src/workload/Transaction.cpp index 3a5e0b31d8..063551763a 100644 --- a/libraries/workload/src/workload/Transaction.cpp +++ b/libraries/workload/src/workload/Transaction.cpp @@ -13,21 +13,16 @@ using namespace workload; -void Transaction::resetItem(ItemID id, PayloadPointer& payload) { - if (payload) { - _resetItems.emplace_back(Reset{ id, payload }); - } else { - qCDebug(renderlogging) << "WARNING: Transaction::resetItem with a null payload!"; - removeItem(id); - } +void Transaction::reset(ProxyID id, const ProxyPayload& payload) { + _resetItems.emplace_back(Reset{ id, payload }); } -void Transaction::removeItem(ItemID id) { +void Transaction::remove(ProxyID id) { _removedItems.emplace_back(id); } -void Transaction::updateItem(ItemID id, const UpdateFunctorPointer& functor) { - _updatedItems.emplace_back(id, functor); +void Transaction::update(ProxyID id, const ProxyPayload& payload) { + _updatedItems.emplace_back(id, payload); } void Transaction::reserve(const std::vector& transactionContainer) { @@ -77,6 +72,18 @@ void copyElements(T& target, const T& source) { } +void Transaction::reset(const Resets& resets) { + copyElements(_resetItems, resets); +} + +void Transaction::remove(const Removes& removes) { + copyElements(_removedItems, removes); +} + +void Transaction::update(const Updates& updates) { + copyElements(_updatedItems, updates); +} + void Transaction::merge(Transaction&& transaction) { moveElements(_resetItems, transaction._resetItems); moveElements(_removedItems, transaction._removedItems); @@ -99,23 +106,22 @@ void Transaction::clear() { Collection::Collection() { - _items.push_back(Item()); // add the itemID #0 to nothing + //_items.push_back(Item()); // add the ProxyID #0 to nothing } Collection::~Collection() { - qCDebug(renderlogging) << "Scene::~Scene()"; } -ItemID Collection::allocateID() { - // Just increment and return the proevious value initialized at 0 - return _IDAllocator.fetch_add(1); +ProxyID Collection::allocateID() { + // Just increment and return the previous value initialized at 0 + return _IDAllocator.allocateIndex(); } -bool Collection::isAllocatedID(const ItemID& id) const { - return Item::isValidID(id) && (id < _numAllocatedItems.load()); +bool Collection::isAllocatedID(const ProxyID& id) const { + return _IDAllocator.checkIndex(id); } -/// Enqueue change batch to the scene +/// Enqueue change batch to the Collection void Collection::enqueueTransaction(const Transaction& transaction) { std::unique_lock lock(_transactionQueueMutex); _transactionQueue.emplace_back(transaction); @@ -127,7 +133,6 @@ void Collection::enqueueTransaction(Transaction&& transaction) { } uint32_t Collection::enqueueFrame() { - PROFILE_RANGE(render, __FUNCTION__); TransactionQueue localTransactionQueue; { std::unique_lock lock(_transactionQueueMutex); @@ -146,8 +151,6 @@ uint32_t Collection::enqueueFrame() { void Collection::processTransactionQueue() { - PROFILE_RANGE(render, __FUNCTION__); - static TransactionFrames queuedFrames; { // capture the queued frames and clear the queue @@ -163,13 +166,12 @@ void Collection::processTransactionQueue() { queuedFrames.clear(); } -void Collection::processTransactionFrame(const Transaction& transaction) { - PROFILE_RANGE(render, __FUNCTION__); - { +//void Collection::processTransactionFrame(const Transaction& transaction) { + /** std::unique_lock lock(_itemsMutex); - // Here we should be able to check the value of last ItemID allocated + // Here we should be able to check the value of last ProxyID allocated // and allocate new items accordingly - ItemID maxID = _IDAllocator.load(); + ProxyID maxID = _IDAllocator.getNumAllocatedIndices(); if (maxID > _items.size()) { _items.resize(maxID + 100); // allocate the maxId and more } @@ -195,32 +197,32 @@ void Collection::processTransactionFrame(const Transaction& transaction) { // Update the numItemsAtomic counter AFTER the pending changes went through _numAllocatedItems.exchange(maxID); - } -} + }*/ +//} -void Collection::resetItems(const Transaction::Resets& transactions) { - for (auto& reset : transactions) { +//void Collection::resetItems(const Transaction::Resets& transactions) { + /* for (auto& reset : transactions) { // Access the true item - auto itemId = std::get<0>(reset); - auto& item = _items[itemId]; + auto ProxyID = std::get<0>(reset); + auto& item = _items[ProxyID]; // Reset the item with a new payload item.resetPayload(std::get<1>(reset)); - } -} + }*/ +//} -void Collection::removeItems(const Transaction::Removes& transactions) { - for (auto removedID : transactions) { +//void Collection::removeItems(const Transaction::Removes& transactions) { + /* for (auto removedID : transactions) { // Access the true item auto& item = _items[removedID]; // Kill it item.kill(); - } -} + }*/ +//} -void Collection::updateItems(const Transaction::Updates& transactions) { - for (auto& update : transactions) { +//void Collection::updateItems(const Transaction::Updates& transactions) { + /* for (auto& update : transactions) { auto updateID = std::get<0>(update); if (updateID == Item::INVALID_ITEM_ID) { continue; @@ -231,5 +233,5 @@ void Collection::updateItems(const Transaction::Updates& transactions) { // Update the item item.update(std::get<1>(update)); - } -} \ No newline at end of file + }*/ +//} \ No newline at end of file diff --git a/libraries/workload/src/workload/Transaction.h b/libraries/workload/src/workload/Transaction.h index 098e953f36..d078989f48 100644 --- a/libraries/workload/src/workload/Transaction.h +++ b/libraries/workload/src/workload/Transaction.h @@ -38,7 +38,7 @@ namespace workload { Index _nextNewIndex{ 0 }; bool checkIndex(Index index) const { return ((index >= 0) && (index < _nextNewIndex)); } - Index getNumIndices() const { return _nextNewIndex - (Index)_freeIndices.size(); } + Index getNumLiveIndices() const { return _nextNewIndex - (Index)_freeIndices.size(); } Index getNumFreeIndices() const { return (Index)_freeIndices.size(); } Index getNumAllocatedIndices() const { return _nextNewIndex; } @@ -64,6 +64,7 @@ namespace workload { void freeIndex(Index index) { if (checkIndex(index)) { _freeIndices.push_back(index); + //std::sort(_freeIndices.begin(), _freeIndices.end()); } } @@ -79,7 +80,7 @@ namespace workload { using IndexVector = indexed_container::Indices; using ProxyID = Index; - + const ProxyID INVALID_PROXY_ID{ indexed_container ::INVALID_INDEX }; // Transaction is the mechanism to make any change to the Space. // Whenever a new proxy need to be reset, @@ -94,16 +95,27 @@ class Transaction { public: using ProxyPayload = Sphere; + using Reset = std::tuple; + using Remove = ProxyID; + using Update = std::tuple; + + using Resets = std::vector; + using Removes = std::vector; + using Updates = std::vector; + Transaction() {} ~Transaction() {} // Proxy transactions void reset(ProxyID id, const ProxyPayload& sphere); + void reset(const Resets& resets); void remove(ProxyID id); + void remove(const Removes& removes); bool hasRemovals() const { return !_removedItems.empty(); } void update(ProxyID id, const ProxyPayload& sphere); - + void update(const Updates& updates); + void reserve(const std::vector& transactionContainer); void merge(const std::vector& transactionContainer); void merge(std::vector&& transactionContainer); @@ -113,13 +125,6 @@ public: protected: - using Reset = std::tuple; - using Remove = ProxyID; - using Update = std::tuple; - - using Resets = std::vector; - using Removes = std::vector; - using Updates = std::vector; Resets _resetItems; Removes _removedItems; @@ -129,6 +134,8 @@ typedef std::vector TransactionQueue; class Collection { public: + Collection(); + ~Collection(); // This call is thread safe, can be called from anywhere to allocate a new ID ProxyID allocateID(); @@ -149,7 +156,7 @@ public: uint32_t enqueueFrame(); // Process the pending transactions queued - void processTransactionQueue(); + virtual void processTransactionQueue(); protected: @@ -168,7 +175,7 @@ protected: uint32_t _transactionFrameNumber{ 0 }; // Process one transaction frame - void processTransactionFrame(const Transaction& transaction); + virtual void processTransactionFrame(const Transaction& transaction) = 0; }; } // namespace workload From 727ac91fb331f2dbae58b8a04bfa48ea72e38ff1 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 14 Mar 2018 16:11:41 -0700 Subject: [PATCH 061/138] fix warnings and comments --- libraries/workload/src/workload/Space.cpp | 2 +- libraries/workload/src/workload/Space.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index 45192b2a10..0e7b9a5ebc 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -30,7 +30,7 @@ void Space::processTransactionFrame(const Transaction& transaction) { // Here we should be able to check the value of last ProxyID allocated // and allocate new proxies accordingly ProxyID maxID = _IDAllocator.getNumAllocatedIndices(); - if (maxID > _proxies.size()) { + if (maxID > (Index) _proxies.size()) { _proxies.resize(maxID + 100); // allocate the maxId and more } // Now we know for sure that we have enough items in the array to diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index 200d8d9ac3..bed013cce9 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -51,7 +51,7 @@ public: void clear(); private: - virtual void processTransactionFrame(const Transaction& transaction); + void processTransactionFrame(const Transaction& transaction) override; void processResets(const Transaction::Resets& transactions); void processRemoves(const Transaction::Removes& transactions); void processUpdates(const Transaction::Updates& transactions); From dada0b9024c2ade743dd0128dde15c79b213d381 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 2 Apr 2018 01:09:35 -0700 Subject: [PATCH 062/138] Exploring better task job config api that work --- interface/src/workload/GameWorkload.cpp | 1 + libraries/task/src/task/Config.cpp | 2 + libraries/task/src/task/Config.h | 47 ++++-- .../developer/utilities/lib/jet/TaskList.qml | 150 ++++++++++++++++++ scripts/developer/utilities/lib/jet/jet.js | 119 ++++++++++++++ .../developer/utilities/lib/jet/jet_qml.js | 72 +++++++++ .../utilities/workload/inspectEngine.js | 40 +++++ .../developer/utilities/workload/workload.qml | 15 +- 8 files changed, 431 insertions(+), 15 deletions(-) create mode 100644 scripts/developer/utilities/lib/jet/TaskList.qml create mode 100644 scripts/developer/utilities/lib/jet/jet.js create mode 100644 scripts/developer/utilities/lib/jet/jet_qml.js create mode 100644 scripts/developer/utilities/workload/inspectEngine.js diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 63fe440fcd..e71463d85a 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -19,6 +19,7 @@ GameWorkloadContext::~GameWorkloadContext() { GameWorkload::GameWorkload() { + } GameWorkload::~GameWorkload() { diff --git a/libraries/task/src/task/Config.cpp b/libraries/task/src/task/Config.cpp index b378237c9c..b63165adbe 100644 --- a/libraries/task/src/task/Config.cpp +++ b/libraries/task/src/task/Config.cpp @@ -18,6 +18,8 @@ using namespace task; +int nakedJobConfigPointerTypeId = qRegisterMetaType(); + void JobConfig::setPresetList(const QJsonObject& object) { for (auto it = object.begin(); it != object.end(); it++) { JobConfig* child = findChild(it.key(), Qt::FindDirectChildrenOnly); diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index d2cc1a8cd8..adb8a60c8e 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -86,17 +86,19 @@ protected: // A default Config is always on; to create an enableable Config, use the ctor JobConfig(bool enabled) class JobConfig : public QObject { Q_OBJECT - Q_PROPERTY(double cpuRunTime READ getCPURunTime NOTIFY newStats()) //ms - Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY dirtyEnabled()) + Q_PROPERTY(double cpuRunTime READ getCPURunTime NOTIFY newStats()) //ms + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY dirtyEnabled()) - double _msCPURunTime{ 0.0 }; + double _msCPURunTime{ 0.0 }; public: using Persistent = PersistentConfig; + using QConfigList = QList; JobConfig() = default; + // JobConfig(const JobConfig& src) = default; JobConfig(bool enabled) : alwaysEnabled{ false }, enabled{ enabled } {} - bool isEnabled() const { return alwaysEnabled || enabled; } + bool isEnabled() { return alwaysEnabled || enabled; } void setEnabled(bool enable) { enabled = alwaysEnabled || enable; emit dirtyEnabled(); } bool alwaysEnabled{ true }; @@ -113,7 +115,12 @@ public: void setCPURunTime(double mstime) { _msCPURunTime = mstime; emit newStats(); } double getCPURunTime() const { return _msCPURunTime; } -public slots: + Q_INVOKABLE virtual bool isTask() const { return false; } + Q_INVOKABLE virtual QConfigList getSubConfigs() const { return QConfigList(); } + Q_INVOKABLE virtual int getNumSubs() const { return 0; } + Q_INVOKABLE virtual JobConfig* getSubConfig(int i) const { return nullptr; } + + public slots: void load(const QJsonObject& val) { qObjectFromJsonValue(val, *this); emit loaded(); } signals: @@ -122,6 +129,8 @@ signals: void dirtyEnabled(); }; +using QConfigPointer = std::shared_ptr; + class TConfigProxy { public: using Config = JobConfig; @@ -130,11 +139,12 @@ public: class TaskConfig : public JobConfig { Q_OBJECT public: - using QConfigPointer = std::shared_ptr; + using QConfigList = QList; using Persistent = PersistentConfig; - TaskConfig() = default ; + TaskConfig() = default; + // TaskConfig(const TaskConfig& src) = default; TaskConfig(bool enabled) : JobConfig(enabled) {} @@ -156,7 +166,8 @@ public: if (tokens.empty()) { tokens.push_back(QString()); - } else { + } + else { while (tokens.size() > 1) { auto name = tokens.front(); tokens.pop_front(); @@ -170,6 +181,22 @@ public: return root->findChild(tokens.front()); } + Q_INVOKABLE bool isTask() const override { return true; } + Q_INVOKABLE QConfigList getSubConfigs() const override { + auto list = findChildren(QRegExp(".*"), Qt::FindDirectChildrenOnly); + QConfigList returned; + for (int i = 0; i < list.size(); i++) { + returned.push_back(list[i]); + } + return returned; + } + + Q_INVOKABLE int getNumSubs() const override { return getSubConfigs().size(); } + Q_INVOKABLE JobConfig* getSubConfig(int i) const override { + auto subs = getSubConfigs(); + return ((i < 0 || i >= subs.size()) ? nullptr : subs[i] ); + } + void connectChildConfig(QConfigPointer childConfig, const std::string& name); void transferChildrenConfigs(QConfigPointer source); @@ -179,8 +206,8 @@ public slots: void refresh(); }; -using QConfigPointer = std::shared_ptr; - } +Q_DECLARE_METATYPE(task::JobConfig*); + #endif // hifi_task_Config_h diff --git a/scripts/developer/utilities/lib/jet/TaskList.qml b/scripts/developer/utilities/lib/jet/TaskList.qml new file mode 100644 index 0000000000..04e6184fc0 --- /dev/null +++ b/scripts/developer/utilities/lib/jet/TaskList.qml @@ -0,0 +1,150 @@ +// +// jet/TaskList.qml +// +// Created by Sam Gateau, 2018/03/28 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +//import QtQuick 2.7 +//import QtQuick.Controls 1.4 as Original +//import QtQuick.Controls.Styles 1.4 + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +//import Hifi 1.0 as Hifi + +//import "qrc:///qml/styles-uit" +//import "qrc:///qml/controls-uit" as HifiControls + +import "jet_qml.js" as Jet + +Rectangle { + id: root + width: parent ? parent.width : 100 + height: parent ? parent.height : 100 + property var config + + property var renderConfig : Render + + TextArea { + id: textArea + width: parent.width + height: parent.height + text: "" + } + + Component.onCompleted: { + // Connect the signal from Selection when any selection content change and use it to refresh the current selection view + // Selection.selectedItemsListChanged.connect(resetSelectionView) + var message = "On Completed: \n" + var functor = Jet.job_print_functor(function (line) { message += line + "\n"; }); + // Jet.task_traverseTree(Render, functor); + var lroot = Workload; + functor(lroot,0,0) + // message += Workload["getSubConfigs"]() + '\n' + + //var subs = Workload; + message += " subs size = " + lroot.getNumSubs() + for (var i = 0; i < lroot.getNumSubs(); i++) { + if (functor(lroot.getSubConfig(i), depth, i)) { + // task_traverse(subs[i], functor, depth) + } + } + textArea.append(message); + } + function fromScript(mope) { + //print(message) + //var message = mope + '\n'; + var message ='\n'; + + // Jet.task_traverseTree(Render, Jet.job_print_functor(function (line) { message += line + "\n"; }) ); + /* + + Render.findChildren();*/ + + // message += (Render.getSubConfigs()) + // Render.getConfig("").findChildren(); +/**//* + var job = Render; + message +=(job.objectName + " " + (job.enabled ? "on" : "off")) + '\n'; + var keys = Jet.job_propKeys(job); + for (var p=0; p < keys.length;p++) { + var prop = job[keys[p]] + message += (typeof prop + " " + keys[p] + " " + prop) + '\n'; + }*/ +/* +function task_traverse(root, functor, depth) { + if (root.isTask()) { + var subs = root.getSubConfigs() + depth++; + for (var i = 0; i Date: Mon, 2 Apr 2018 17:59:28 -0700 Subject: [PATCH 063/138] GOing over the jet lib ui and the nightmare that is the js/qml family --- libraries/task/src/task/Config.cpp | 2 - libraries/task/src/task/Config.h | 19 +-- .../developer/utilities/lib/jet/TaskList.qml | 133 +++--------------- scripts/developer/utilities/lib/jet/jet.js | 105 ++++---------- .../developer/utilities/lib/jet/jet_qml.js | 72 ---------- .../utilities/workload/inspectEngine.js | 14 +- .../developer/utilities/workload/workload.js | 2 +- .../{workload.qml => workloadInspector.qml} | 13 +- 8 files changed, 69 insertions(+), 291 deletions(-) delete mode 100644 scripts/developer/utilities/lib/jet/jet_qml.js rename scripts/developer/utilities/workload/{workload.qml => workloadInspector.qml} (93%) diff --git a/libraries/task/src/task/Config.cpp b/libraries/task/src/task/Config.cpp index b63165adbe..b378237c9c 100644 --- a/libraries/task/src/task/Config.cpp +++ b/libraries/task/src/task/Config.cpp @@ -18,8 +18,6 @@ using namespace task; -int nakedJobConfigPointerTypeId = qRegisterMetaType(); - void JobConfig::setPresetList(const QJsonObject& object) { for (auto it = object.begin(); it != object.end(); it++) { JobConfig* child = findChild(it.key(), Qt::FindDirectChildrenOnly); diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index adb8a60c8e..8548812d65 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -92,10 +92,8 @@ class JobConfig : public QObject { double _msCPURunTime{ 0.0 }; public: using Persistent = PersistentConfig; - using QConfigList = QList; JobConfig() = default; - // JobConfig(const JobConfig& src) = default; JobConfig(bool enabled) : alwaysEnabled{ false }, enabled{ enabled } {} bool isEnabled() { return alwaysEnabled || enabled; } @@ -110,15 +108,17 @@ public: Q_INVOKABLE QString toJSON() { return QJsonDocument(toJsonValue(*this).toObject()).toJson(QJsonDocument::Compact); } Q_INVOKABLE void load(const QVariantMap& map) { qObjectFromJsonValue(QJsonObject::fromVariantMap(map), *this); emit loaded(); } + Q_INVOKABLE QObject* getConfig(const QString& name) { return nullptr; } + // Running Time measurement // The new stats signal is emitted once per run time of a job when stats (cpu runtime) are updated void setCPURunTime(double mstime) { _msCPURunTime = mstime; emit newStats(); } double getCPURunTime() const { return _msCPURunTime; } Q_INVOKABLE virtual bool isTask() const { return false; } - Q_INVOKABLE virtual QConfigList getSubConfigs() const { return QConfigList(); } + Q_INVOKABLE virtual QObjectList getSubConfigs() const { return QObjectList(); } Q_INVOKABLE virtual int getNumSubs() const { return 0; } - Q_INVOKABLE virtual JobConfig* getSubConfig(int i) const { return nullptr; } + Q_INVOKABLE virtual QObject* getSubConfig(int i) const { return nullptr; } public slots: void load(const QJsonObject& val) { qObjectFromJsonValue(val, *this); emit loaded(); } @@ -139,12 +139,9 @@ public: class TaskConfig : public JobConfig { Q_OBJECT public: - using QConfigList = QList; - using Persistent = PersistentConfig; TaskConfig() = default; - // TaskConfig(const TaskConfig& src) = default; TaskConfig(bool enabled) : JobConfig(enabled) {} @@ -182,9 +179,9 @@ public: } Q_INVOKABLE bool isTask() const override { return true; } - Q_INVOKABLE QConfigList getSubConfigs() const override { + Q_INVOKABLE QObjectList getSubConfigs() const override { auto list = findChildren(QRegExp(".*"), Qt::FindDirectChildrenOnly); - QConfigList returned; + QObjectList returned; for (int i = 0; i < list.size(); i++) { returned.push_back(list[i]); } @@ -192,7 +189,7 @@ public: } Q_INVOKABLE int getNumSubs() const override { return getSubConfigs().size(); } - Q_INVOKABLE JobConfig* getSubConfig(int i) const override { + Q_INVOKABLE QObject* getSubConfig(int i) const override { auto subs = getSubConfigs(); return ((i < 0 || i >= subs.size()) ? nullptr : subs[i] ); } @@ -208,6 +205,4 @@ public slots: } -Q_DECLARE_METATYPE(task::JobConfig*); - #endif // hifi_task_Config_h diff --git a/scripts/developer/utilities/lib/jet/TaskList.qml b/scripts/developer/utilities/lib/jet/TaskList.qml index 04e6184fc0..baa579b4a3 100644 --- a/scripts/developer/utilities/lib/jet/TaskList.qml +++ b/scripts/developer/utilities/lib/jet/TaskList.qml @@ -8,28 +8,33 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +import QtQuick 2.7 +import QtQuick.Controls 1.4 as Original +import QtQuick.Controls.Styles 1.4 + +import "qrc:///qml/styles-uit" +import "qrc:///qml/controls-uit" as HifiControls + //import QtQuick 2.7 //import QtQuick.Controls 1.4 as Original //import QtQuick.Controls.Styles 1.4 -import QtQuick 2.5 -import QtQuick.Controls 1.4 +//import QtQuick 2.5 +//import QtQuick.Controls 1.4 //import Hifi 1.0 as Hifi //import "qrc:///qml/styles-uit" //import "qrc:///qml/controls-uit" as HifiControls -import "jet_qml.js" as Jet +import "jet.js" as Jet Rectangle { id: root - width: parent ? parent.width : 100 - height: parent ? parent.height : 100 - property var config + width: parent ? parent.width : 200 + height: parent ? parent.height : 400 + property var rootConfig - property var renderConfig : Render - - TextArea { + Original.TextArea { id: textArea width: parent.width height: parent.height @@ -37,114 +42,18 @@ Rectangle { } Component.onCompleted: { - // Connect the signal from Selection when any selection content change and use it to refresh the current selection view - // Selection.selectedItemsListChanged.connect(resetSelectionView) - var message = "On Completed: \n" - var functor = Jet.job_print_functor(function (line) { message += line + "\n"; }); - // Jet.task_traverseTree(Render, functor); - var lroot = Workload; - functor(lroot,0,0) - // message += Workload["getSubConfigs"]() + '\n' - - //var subs = Workload; - message += " subs size = " + lroot.getNumSubs() - for (var i = 0; i < lroot.getNumSubs(); i++) { - if (functor(lroot.getSubConfig(i), depth, i)) { - // task_traverse(subs[i], functor, depth) - } - } + var message = "" + var functor = Jet.job_print_functor(function (line) { message += line + "\n"; }); + Jet.task_traverseTree(Workload, functor); textArea.append(message); } function fromScript(mope) { - //print(message) - //var message = mope + '\n'; - var message ='\n'; - - // Jet.task_traverseTree(Render, Jet.job_print_functor(function (line) { message += line + "\n"; }) ); - /* - - Render.findChildren();*/ - - // message += (Render.getSubConfigs()) - // Render.getConfig("").findChildren(); -/**//* - var job = Render; - message +=(job.objectName + " " + (job.enabled ? "on" : "off")) + '\n'; - var keys = Jet.job_propKeys(job); - for (var p=0; p < keys.length;p++) { - var prop = job[keys[p]] - message += (typeof prop + " " + keys[p] + " " + prop) + '\n'; - }*/ -/* -function task_traverse(root, functor, depth) { - if (root.isTask()) { - var subs = root.getSubConfigs() - depth++; - for (var i = 0; i Date: Tue, 3 Apr 2018 17:21:37 -0700 Subject: [PATCH 064/138] Starting to buiuild on the jet component and adding the widget to luci and workload inspectors --- scripts/developer/utilities/lib/jet/jet.js | 5 +++-- .../utilities/lib/jet/{ => qml}/TaskList.qml | 21 +++++-------------- .../developer/utilities/lib/jet/qml/qmldir | 1 + .../utilities/render/deferredLighting.qml | 10 +++++++++ .../utilities/workload/inspectEngine.js | 19 ++--------------- .../utilities/workload/workloadInspector.qml | 16 +++++++++++--- 6 files changed, 34 insertions(+), 38 deletions(-) rename scripts/developer/utilities/lib/jet/{ => qml}/TaskList.qml (68%) create mode 100644 scripts/developer/utilities/lib/jet/qml/qmldir diff --git a/scripts/developer/utilities/lib/jet/jet.js b/scripts/developer/utilities/lib/jet/jet.js index dc50e5c653..39da9b6d90 100644 --- a/scripts/developer/utilities/lib/jet/jet.js +++ b/scripts/developer/utilities/lib/jet/jet.js @@ -65,8 +65,9 @@ function job_print_functor(printout, maxDepth) { } // Expose functions for regular js including this files through the 'Jet' object -Jet = {} +/*Jet = {} Jet.task_traverse = task_traverse Jet.task_traverseTree = task_traverseTree Jet.job_propKeys = job_propKeys -Jet.job_print_functor = job_print_functor \ No newline at end of file +Jet.job_print_functor = job_print_functor +*/ \ No newline at end of file diff --git a/scripts/developer/utilities/lib/jet/TaskList.qml b/scripts/developer/utilities/lib/jet/qml/TaskList.qml similarity index 68% rename from scripts/developer/utilities/lib/jet/TaskList.qml rename to scripts/developer/utilities/lib/jet/qml/TaskList.qml index baa579b4a3..fa004627a7 100644 --- a/scripts/developer/utilities/lib/jet/TaskList.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskList.qml @@ -15,24 +15,13 @@ import QtQuick.Controls.Styles 1.4 import "qrc:///qml/styles-uit" import "qrc:///qml/controls-uit" as HifiControls -//import QtQuick 2.7 -//import QtQuick.Controls 1.4 as Original -//import QtQuick.Controls.Styles 1.4 - -//import QtQuick 2.5 -//import QtQuick.Controls 1.4 -//import Hifi 1.0 as Hifi - -//import "qrc:///qml/styles-uit" -//import "qrc:///qml/controls-uit" as HifiControls - -import "jet.js" as Jet +import "../jet.js" as Jet Rectangle { id: root - width: parent ? parent.width : 200 - height: parent ? parent.height : 400 - property var rootConfig + // width: parent ? parent.width : 200 + // height: parent ? parent.height : 400 + property var rootConfig : Workload Original.TextArea { id: textArea @@ -44,7 +33,7 @@ Rectangle { Component.onCompleted: { var message = "" var functor = Jet.job_print_functor(function (line) { message += line + "\n"; }); - Jet.task_traverseTree(Workload, functor); + Jet.task_traverseTree(rootConfig, functor); textArea.append(message); } function fromScript(mope) { diff --git a/scripts/developer/utilities/lib/jet/qml/qmldir b/scripts/developer/utilities/lib/jet/qml/qmldir new file mode 100644 index 0000000000..f926d8cc67 --- /dev/null +++ b/scripts/developer/utilities/lib/jet/qml/qmldir @@ -0,0 +1 @@ +TaskList 1.0 TaskList.qml \ No newline at end of file diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index 189d23c44f..160ec26be0 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -14,6 +14,7 @@ import QtQuick.Layouts 1.3 import "qrc:///qml/styles-uit" import "qrc:///qml/controls-uit" as HifiControls import "configSlider" +import "../lib/jet/qml" as Jet Rectangle { HifiConstants { id: hifi;} @@ -274,6 +275,15 @@ Rectangle { } } } + Separator {} + + Jet.TaskList { + rootConfig: Render + anchors.left: parent.left + anchors.right: parent.right + + height: 200 + } } //} } diff --git a/scripts/developer/utilities/workload/inspectEngine.js b/scripts/developer/utilities/workload/inspectEngine.js index 37280037da..6d79ba41a1 100644 --- a/scripts/developer/utilities/workload/inspectEngine.js +++ b/scripts/developer/utilities/workload/inspectEngine.js @@ -1,27 +1,12 @@ -Script.include('../lib/jet/jet.js'); - - - - (function() { // BEGIN LOCAL_SCOPE - //jet.task_traverseTree(Render, printJob); - var message = "test"; - var functor = Jet.job_print_functor(function (line) { message += line + "\n"; }); - - Jet.task_traverseTree(Render, functor); - - // print(message)*/ - -var qml = Script.resolvePath('../lib/jet/TaskList.qml'); +var qml = Script.resolvePath('./workloadInspector.qml'); var window = new OverlayWindow({ title: 'Inspect Engine', source: qml, width: 400, - height: 500 + height: 600 }); -window.sendToQml(message) - window.closed.connect(function () { Script.stop(); }); Script.scriptEnding.connect(function () { /* var geometry = JSON.stringify({ diff --git a/scripts/developer/utilities/workload/workloadInspector.qml b/scripts/developer/utilities/workload/workloadInspector.qml index 27b85b9a92..ca8f11355a 100644 --- a/scripts/developer/utilities/workload/workloadInspector.qml +++ b/scripts/developer/utilities/workload/workloadInspector.qml @@ -13,14 +13,16 @@ import QtQuick.Layouts 1.3 import "qrc:///qml/styles-uit" import "qrc:///qml/controls-uit" as HifiControls -import "../render/configSlider" - -//import "../lib/jet"; +import "../render/configSlider" +import "../lib/jet/qml" as Jet Rectangle { HifiConstants { id: hifi;} id: _workload; + + width: parent ? parent.width : 400 + height: parent ? parent.height : 600 anchors.margins: hifi.dimensions.contentMargin.x color: hifi.colors.baseGray; @@ -118,5 +120,13 @@ Rectangle { onCheckedChanged: { Workload.getConfig("SpaceToRender")["showViews"] = checked } } Separator {} + + Jet.TaskList { + rootConfig: Workload + anchors.left: parent.left + anchors.right: parent.right + + height: 300 + } } } From a7040854447105e9eb2582a76517783df0344910 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 4 Apr 2018 09:18:19 -0700 Subject: [PATCH 065/138] Fix typos --- libraries/task/src/task/Config.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index 8548812d65..eaa87f53af 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -86,10 +86,10 @@ protected: // A default Config is always on; to create an enableable Config, use the ctor JobConfig(bool enabled) class JobConfig : public QObject { Q_OBJECT - Q_PROPERTY(double cpuRunTime READ getCPURunTime NOTIFY newStats()) //ms - Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY dirtyEnabled()) + Q_PROPERTY(double cpuRunTime READ getCPURunTime NOTIFY newStats()) //ms + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY dirtyEnabled()) - double _msCPURunTime{ 0.0 }; + double _msCPURunTime{ 0.0 }; public: using Persistent = PersistentConfig; @@ -120,7 +120,7 @@ public: Q_INVOKABLE virtual int getNumSubs() const { return 0; } Q_INVOKABLE virtual QObject* getSubConfig(int i) const { return nullptr; } - public slots: +public slots: void load(const QJsonObject& val) { qObjectFromJsonValue(val, *this); emit loaded(); } signals: From d9ab166aacbaf162bb9dedc4c4ba9bcab4d1c4a8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 5 Apr 2018 12:10:46 -0700 Subject: [PATCH 066/138] initial PhysicsBoundary job implementation --- interface/src/workload/PhysicsBoundary.h | 89 ++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 interface/src/workload/PhysicsBoundary.h diff --git a/interface/src/workload/PhysicsBoundary.h b/interface/src/workload/PhysicsBoundary.h new file mode 100644 index 0000000000..130b1267b7 --- /dev/null +++ b/interface/src/workload/PhysicsBoundary.h @@ -0,0 +1,89 @@ +// +// PhysicsBoundary.h +// +// Created by Sam Gateau on 2/16/2018. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_PhysicsGatekeeper_h +#define hifi_PhysicsGatekeeper_h + +#include "workload/Space.h" +#include "workload/Engine.h" + +#include "render/Scene.h" + +/* +class FooJobConfig : public workload::Job::Config { + Q_OBJECT + Q_PROPERTY(bool fubar MEMBER fubar NOTIFY dirty) +public: + bool fubar{ false }; +signals: + void dirty(); +protected: +}; +*/ + +#include // adebug +#include +#include +#include "PhysicalEntitySimulation.h" + +class PhysicsBoundary { +public: + using Config = workload::Job::Config; + using Inputs = workload::RegionTracker::Outputs; + using Outputs = bool; + using JobModel = workload::Job::ModelI; // this doesn't work + + PhysicsBoundary() {} + + void configure(const Config& config) { + } + + void run(const workload::WorkloadContextPointer& context, const Inputs& inputs) { + auto space = context->_space; + if (!space) { + return; + } + uint32_t listSize = inputs.size(); + uint32_t totalTransitions = 0; + for (uint32_t i = 0; i < listSize; ++i) { + totalTransitions += inputs[i].size(); + } + // we're interested in things entering/leaving R3 + uint32_t regionIndex = workload::Region::R3; + uint32_t exitIndex = 2 * regionIndex; + uint32_t numExits = inputs[exitIndex].size(); + for (uint32_t i = 0; i < numExits; ++i) { + int32_t proxyID = inputs[exitIndex][i]; + void* owner = space->getOwner(proxyID).get(); + if (owner) { + EntityItem* entity = static_cast(owner); + std::cout << "adebug - " + //<< owner + << " '" << entity->getName().toStdString() << "'" + << std::endl; // adebug + } + } + + uint32_t enterIndex = exitIndex + 1; + uint32_t numEntries = inputs[enterIndex].size(); + for (uint32_t i = 0; i < numEntries; ++i) { + int32_t proxyID = inputs[enterIndex][i]; + void* owner = space->getOwner(proxyID).get(); + if (owner) { + EntityItem* entity = static_cast(owner); + std::cout << "adebug + " + //<< owner + << " '" << entity->getName().toStdString() << "'" + << std::endl; // adebug + } + } + } +}; + +#endif // hifi_PhysicsGatekeeper_h From 4f0980b94b78accaf480abb9888d931a49799cbd Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 5 Apr 2018 12:11:57 -0700 Subject: [PATCH 067/138] hook up prototype PhysicsBoundary job --- interface/src/Application.cpp | 4 +- interface/src/workload/GameWorkload.cpp | 20 +++-- interface/src/workload/GameWorkload.h | 18 ++-- .../src/EntityTreeRenderer.cpp | 2 +- libraries/workload/src/workload/Engine.cpp | 8 +- libraries/workload/src/workload/Proxy.h | 12 +++ libraries/workload/src/workload/Space.cpp | 84 +++---------------- libraries/workload/src/workload/Space.h | 11 +-- .../workload/src/workload/Transaction.cpp | 6 +- libraries/workload/src/workload/Transaction.h | 12 +-- 10 files changed, 68 insertions(+), 109 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6576e035d1..1b85563969 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2495,8 +2495,6 @@ void Application::initializeGL() { DependencyManager::get()->initializeShapePipelines(); }); - _gameWorkload.startup(getEntities()->getWorkloadSpace(), _main3DScene); - _offscreenContext = new OffscreenGLCanvas(); _offscreenContext->setObjectName("MainThreadContext"); _offscreenContext->create(_glWidget->qglContext()); @@ -4705,6 +4703,8 @@ void Application::init() { avatar->setCollisionSound(sound); } }, Qt::QueuedConnection); + + _gameWorkload.startup(getEntities()->getWorkloadSpace(), _main3DScene, _entitySimulation); } void Application::updateLOD(float deltaTime) const { diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index e71463d85a..86f6db7148 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -10,8 +10,15 @@ #include "GameWorkload.h" #include "GameWorkloadRenderer.h" #include +#include -GameWorkloadContext::GameWorkloadContext(const workload::SpacePointer& space, const render::ScenePointer& scene) : WorkloadContext(space), _scene(scene) { +#include "PhysicsBoundary.h" + +GameWorkloadContext::GameWorkloadContext(const workload::SpacePointer& space, + const render::ScenePointer& scene, + const PhysicalEntitySimulationPointer& simulation) +: WorkloadContext(space), _scene(scene), _simulation(simulation) +{ } GameWorkloadContext::~GameWorkloadContext() { @@ -19,19 +26,22 @@ GameWorkloadContext::~GameWorkloadContext() { GameWorkload::GameWorkload() { - } GameWorkload::~GameWorkload() { shutdown(); } -void GameWorkload::startup(const workload::SpacePointer& space, const render::ScenePointer& scene) { - _engine.reset(new workload::Engine(std::make_shared(space, scene))); +void GameWorkload::startup(const workload::SpacePointer& space, + const render::ScenePointer& scene, + const PhysicalEntitySimulationPointer& simulation) { + _engine.reset(new workload::Engine(std::make_shared(space, scene, simulation))); + auto output = _engine->getOutput(); _engine->addJob("SpaceToRender"); - + const auto regionChanges = _engine->getOutput(); + _engine->addJob("PhysicsBoundary", regionChanges); } void GameWorkload::shutdown() { diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index a89f8895c4..60b41c5c38 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -10,17 +10,21 @@ #ifndef hifi_GameWorkload_h #define hifi_GameWorkload_h -#include "workload/Space.h" -#include "workload/Engine.h" +#include +#include -#include "render/Scene.h" +#include +#include "PhysicalEntitySimulation.h" class GameWorkloadContext : public workload::WorkloadContext { public: - GameWorkloadContext(const workload::SpacePointer& space, const render::ScenePointer& scene); + GameWorkloadContext(const workload::SpacePointer& space, + const render::ScenePointer& scene, + const PhysicalEntitySimulationPointer& simulation); virtual ~GameWorkloadContext(); render::ScenePointer _scene; + PhysicalEntitySimulationPointer _simulation; }; class GameWorkload { @@ -28,7 +32,9 @@ public: GameWorkload(); ~GameWorkload(); - void startup(const workload::SpacePointer& space, const render::ScenePointer& scene); + void startup(const workload::SpacePointer& space, + const render::ScenePointer& scene, + const PhysicalEntitySimulationPointer& simulation); void shutdown(); void updateViews(const ViewFrustum& frustum); @@ -36,4 +42,4 @@ public: workload::EnginePointer _engine; }; -#endif \ No newline at end of file +#endif // hifi_GameWorkload_h diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index dfb888f9cb..ac3afb3e2b 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -284,7 +284,7 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r auto spaceIndex = _space->allocateID(); workload::Sphere sphere(entity->getWorldPosition(), entity->getBoundingRadius()); workload::Transaction transaction; - transaction.reset(spaceIndex, sphere); + transaction.reset(spaceIndex, sphere, workload::Owner(entity.get())); _space->enqueueTransaction(transaction); entity->setSpaceIndex(spaceIndex); connect(entity.get(), &EntityItem::spaceUpdate, this, &EntityTreeRenderer::handleSpaceUpdate, Qt::QueuedConnection); diff --git a/libraries/workload/src/workload/Engine.cpp b/libraries/workload/src/workload/Engine.cpp index 0bb9c73fa0..03c04e6632 100644 --- a/libraries/workload/src/workload/Engine.cpp +++ b/libraries/workload/src/workload/Engine.cpp @@ -5,9 +5,6 @@ // Created by Andrew Meadows 2018.02.08 // Copyright 2018 High Fidelity, Inc. // -// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards -// Simple plane class. -// // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // @@ -26,13 +23,14 @@ namespace workload { class EngineBuilder { public: using Inputs = Views; - using JobModel = Task::ModelI; + using Outputs = RegionTracker::Outputs; + using JobModel = Task::ModelIO; void build(JobModel& model, const Varying& in, Varying& out) { model.addJob("setupViews", in); model.addJob("updateSpace"); const auto regionChanges = model.addJob("regionTracker"); model.addJob("regionState", regionChanges); - + out = regionChanges; } }; diff --git a/libraries/workload/src/workload/Proxy.h b/libraries/workload/src/workload/Proxy.h index 9248c2bb31..0c1c7363cd 100644 --- a/libraries/workload/src/workload/Proxy.h +++ b/libraries/workload/src/workload/Proxy.h @@ -15,6 +15,18 @@ namespace workload { +class Owner { +public: + Owner() = default; + Owner(void* data) : _data(data) {} + Owner(const Owner& other) = default; + Owner& operator=(const Owner& other) = default; + ~Owner() {} + void* get() const { return _data; } +private: + void* _data { nullptr }; +}; + class Proxy { public: Proxy() : sphere(0.0f) {} diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index 0e7b9a5ebc..ea18385c93 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -21,10 +21,8 @@ using namespace workload; Space::Space() : Collection() { - } - void Space::processTransactionFrame(const Transaction& transaction) { std::unique_lock lock(_proxiesMutex); // Here we should be able to check the value of last ProxyID allocated @@ -32,25 +30,14 @@ void Space::processTransactionFrame(const Transaction& transaction) { ProxyID maxID = _IDAllocator.getNumAllocatedIndices(); if (maxID > (Index) _proxies.size()) { _proxies.resize(maxID + 100); // allocate the maxId and more + _owners.resize(maxID + 100); } // Now we know for sure that we have enough items in the array to // capture anything coming from the transaction - // resets and potential NEW items processResets(transaction._resetItems); - - // Update the numItemsAtomic counter AFTER the reset changes went through - // _numAllocatedItems.exchange(maxID); - - // updates processUpdates(transaction._updatedItems); - - // removes processRemoves(transaction._removedItems); - - - // Update the numItemsAtomic counter AFTER the pending changes went through - // _numAllocatedItems.exchange(maxID); } void Space::processResets(const Transaction::Resets& transactions) { @@ -62,6 +49,8 @@ void Space::processResets(const Transaction::Resets& transactions) { // Reset the item with a new payload item.sphere = (std::get<1>(reset)); item.prevRegion = item.region = Region::UNKNOWN; + + _owners[ProxyID] = (std::get<2>(reset)); } } @@ -74,6 +63,7 @@ void Space::processRemoves(const Transaction::Removes& transactions) { // Kill it item.prevRegion = item.region = Region::INVALID; + _owners[removedID] = Owner(); } } @@ -88,40 +78,9 @@ void Space::processUpdates(const Transaction::Updates& transactions) { auto& item = _proxies[updateID]; // Update the item - // item.update(std::get<1>(update)); item.sphere = (std::get<1>(update)); - item.prevRegion = item.region = Region::UNKNOWN; } } -/* -int32_t Space::createProxy(const Space::Sphere& newSphere) { - if (_freeIndices.empty()) { - _proxies.emplace_back(Space::Proxy(newSphere)); - return (int32_t)_proxies.size() - 1; - } else { - int32_t index = _freeIndices.back(); - _freeIndices.pop_back(); - _proxies[index].sphere = newSphere; - _proxies[index].region = Region::UNKNOWN; - _proxies[index].prevRegion = Region::UNKNOWN; - return index; - } -}*/ -/* -void Space::deleteProxies(const std::vector& deadIndices) { - for (uint32_t i = 0; i < deadIndices.size(); ++i) { - deleteProxy(deadIndices[i]); - } -} -*/ -/*void Space::updateProxies(const std::vector& changedProxies) { - for (uint32_t i = 0; i < changedProxies.size(); ++i) { - int32_t proxyId = changedProxies[i].first; - if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) { - updateProxy(changedProxies[i].first, changedProxies[i].second); - } - } -}*/ void Space::categorizeAndGetChanges(std::vector& changes) { std::unique_lock lock(_proxiesMutex); @@ -153,27 +112,6 @@ void Space::categorizeAndGetChanges(std::vector& changes) { } } -// private -/*void Space::deleteProxy(int32_t proxyId) { - if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) { - if (proxyId == (int32_t)_proxies.size() - 1) { - // remove proxy on back - _proxies.pop_back(); - if (!_freeIndices.empty()) { - // remove any freeIndices on back - std::sort(_freeIndices.begin(), _freeIndices.end()); - while(!_freeIndices.empty() && _freeIndices.back() == (int32_t)_proxies.size() - 1) { - _freeIndices.pop_back(); - _proxies.pop_back(); - } - } - } else { - _proxies[proxyId].region = Region::INVALID; - _freeIndices.push_back(proxyId); - } - } -}*/ - uint32_t Space::copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const { std::unique_lock lock(_proxiesMutex); auto numCopied = std::min(numDestProxies, (uint32_t)_proxies.size()); @@ -181,22 +119,22 @@ uint32_t Space::copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const { return numCopied; } - -// private -/*void Space::updateProxy(int32_t proxyId, const Space::Sphere& newSphere) { - if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) { - _proxies[proxyId].sphere = newSphere; +const Owner Space::getOwner(int32_t proxyID) const { + std::unique_lock lock(_proxiesMutex); + if (_IDAllocator.checkIndex(proxyID)) { + return _owners[proxyID]; } -}*/ + return Owner(); +} void Space::clear() { std::unique_lock lock(_proxiesMutex); _IDAllocator.clear(); _proxies.clear(); + _owners.clear(); _views.clear(); } - void Space::setViews(const Views& views) { _views = views; } diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index bed013cce9..d8d1659751 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -48,6 +48,8 @@ public: void categorizeAndGetChanges(std::vector& changes); uint32_t copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const; + const Owner getOwner(int32_t proxyID) const; + void clear(); private: @@ -56,17 +58,10 @@ private: void processRemoves(const Transaction::Removes& transactions); void processUpdates(const Transaction::Updates& transactions); - // int32_t createProxy(const Sphere& sphere); - // void deleteProxies(const IndexVector& deadIndices); - // void updateProxies(const std::vector& changedProxies); - - // void deleteProxy(int32_t proxyId); - // void updateProxy(int32_t proxyId, const Sphere& sphere); - - // The database of proxies is protected for editing by a mutex mutable std::mutex _proxiesMutex; Proxy::Vector _proxies; + std::vector _owners; Views _views; }; diff --git a/libraries/workload/src/workload/Transaction.cpp b/libraries/workload/src/workload/Transaction.cpp index 063551763a..7dc7e7a3d2 100644 --- a/libraries/workload/src/workload/Transaction.cpp +++ b/libraries/workload/src/workload/Transaction.cpp @@ -13,8 +13,8 @@ using namespace workload; -void Transaction::reset(ProxyID id, const ProxyPayload& payload) { - _resetItems.emplace_back(Reset{ id, payload }); +void Transaction::reset(ProxyID id, const ProxyPayload& payload, const Owner& owner) { + _resetItems.emplace_back(Reset{ id, payload, owner }); } void Transaction::remove(ProxyID id) { @@ -234,4 +234,4 @@ void Collection::processTransactionQueue() { // Update the item item.update(std::get<1>(update)); }*/ -//} \ No newline at end of file +//} diff --git a/libraries/workload/src/workload/Transaction.h b/libraries/workload/src/workload/Transaction.h index d078989f48..506e3359e6 100644 --- a/libraries/workload/src/workload/Transaction.h +++ b/libraries/workload/src/workload/Transaction.h @@ -89,13 +89,13 @@ namespace workload { // These changes must be expressed through the corresponding command from the Transaction // The Transaction is then queued on the Space so all the pending transactions can be consolidated and processed at the time // of updating the space at the Frame boundary. -// +// class Transaction { friend class Space; public: using ProxyPayload = Sphere; - using Reset = std::tuple; + using Reset = std::tuple; using Remove = ProxyID; using Update = std::tuple; @@ -107,7 +107,7 @@ public: ~Transaction() {} // Proxy transactions - void reset(ProxyID id, const ProxyPayload& sphere); + void reset(ProxyID id, const ProxyPayload& sphere, const Owner& owner); void reset(const Resets& resets); void remove(ProxyID id); void remove(const Removes& removes); @@ -122,7 +122,7 @@ public: void merge(const Transaction& transaction); void merge(Transaction&& transaction); void clear(); - + protected: @@ -174,10 +174,10 @@ protected: TransactionFrames _transactionFrames; uint32_t _transactionFrameNumber{ 0 }; - // Process one transaction frame + // Process one transaction frame virtual void processTransactionFrame(const Transaction& transaction) = 0; }; } // namespace workload -#endif // hifi_workload_Transaction_h \ No newline at end of file +#endif // hifi_workload_Transaction_h From 8035dde5dd9f3abd99e9e92bd772e80f38dade90 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 5 Apr 2018 12:54:43 -0700 Subject: [PATCH 068/138] fix Windows warnings --- interface/src/workload/PhysicsBoundary.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/workload/PhysicsBoundary.h b/interface/src/workload/PhysicsBoundary.h index 130b1267b7..60482c0992 100644 --- a/interface/src/workload/PhysicsBoundary.h +++ b/interface/src/workload/PhysicsBoundary.h @@ -49,15 +49,15 @@ public: if (!space) { return; } - uint32_t listSize = inputs.size(); + uint32_t listSize = (uint32_t)inputs.size(); uint32_t totalTransitions = 0; for (uint32_t i = 0; i < listSize; ++i) { - totalTransitions += inputs[i].size(); + totalTransitions += (uint32_t)inputs[i].size(); } // we're interested in things entering/leaving R3 uint32_t regionIndex = workload::Region::R3; uint32_t exitIndex = 2 * regionIndex; - uint32_t numExits = inputs[exitIndex].size(); + uint32_t numExits = (uint32_t)inputs[exitIndex].size(); for (uint32_t i = 0; i < numExits; ++i) { int32_t proxyID = inputs[exitIndex][i]; void* owner = space->getOwner(proxyID).get(); @@ -71,7 +71,7 @@ public: } uint32_t enterIndex = exitIndex + 1; - uint32_t numEntries = inputs[enterIndex].size(); + uint32_t numEntries = (uint32_t)inputs[enterIndex].size(); for (uint32_t i = 0; i < numEntries; ++i) { int32_t proxyID = inputs[enterIndex][i]; void* owner = space->getOwner(proxyID).get(); From c5b88d55ab2812f14029888e20ab6089684167a9 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 5 Apr 2018 16:05:40 -0700 Subject: [PATCH 069/138] Spliting the creation of the Workload engine from the setup and configuration, changing the output from region tracker --- interface/src/workload/GameWorkload.cpp | 2 +- interface/src/workload/GameWorkload.h | 2 +- interface/src/workload/PhysicsBoundary.h | 13 ++++++----- libraries/workload/src/workload/Engine.cpp | 12 ++++++---- libraries/workload/src/workload/Engine.h | 6 +++-- .../workload/src/workload/RegionTracker.cpp | 23 ++++++++++++------- .../workload/src/workload/RegionTracker.h | 2 +- 7 files changed, 37 insertions(+), 23 deletions(-) diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 86f6db7148..b6e26bcc48 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -35,7 +35,7 @@ GameWorkload::~GameWorkload() { void GameWorkload::startup(const workload::SpacePointer& space, const render::ScenePointer& scene, const PhysicalEntitySimulationPointer& simulation) { - _engine.reset(new workload::Engine(std::make_shared(space, scene, simulation))); + _engine->reset(std::make_shared(space, scene, simulation)); auto output = _engine->getOutput(); _engine->addJob("SpaceToRender"); diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index 60b41c5c38..01d748ba0e 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -39,7 +39,7 @@ public: void updateViews(const ViewFrustum& frustum); - workload::EnginePointer _engine; + workload::EnginePointer _engine { std::make_shared() }; }; #endif // hifi_GameWorkload_h diff --git a/interface/src/workload/PhysicsBoundary.h b/interface/src/workload/PhysicsBoundary.h index 60482c0992..8f5c1a48ff 100644 --- a/interface/src/workload/PhysicsBoundary.h +++ b/interface/src/workload/PhysicsBoundary.h @@ -45,21 +45,22 @@ public: } void run(const workload::WorkloadContextPointer& context, const Inputs& inputs) { + const auto& regionChanges = inputs.get1(); auto space = context->_space; if (!space) { return; } - uint32_t listSize = (uint32_t)inputs.size(); + uint32_t listSize = (uint32_t)regionChanges.size(); uint32_t totalTransitions = 0; for (uint32_t i = 0; i < listSize; ++i) { - totalTransitions += (uint32_t)inputs[i].size(); + totalTransitions += (uint32_t)regionChanges[i].size(); } // we're interested in things entering/leaving R3 uint32_t regionIndex = workload::Region::R3; uint32_t exitIndex = 2 * regionIndex; - uint32_t numExits = (uint32_t)inputs[exitIndex].size(); + uint32_t numExits = (uint32_t)regionChanges[exitIndex].size(); for (uint32_t i = 0; i < numExits; ++i) { - int32_t proxyID = inputs[exitIndex][i]; + int32_t proxyID = regionChanges[exitIndex][i]; void* owner = space->getOwner(proxyID).get(); if (owner) { EntityItem* entity = static_cast(owner); @@ -71,9 +72,9 @@ public: } uint32_t enterIndex = exitIndex + 1; - uint32_t numEntries = (uint32_t)inputs[enterIndex].size(); + uint32_t numEntries = (uint32_t)regionChanges[enterIndex].size(); for (uint32_t i = 0; i < numEntries; ++i) { - int32_t proxyID = inputs[enterIndex][i]; + int32_t proxyID = regionChanges[enterIndex][i]; void* owner = space->getOwner(proxyID).get(); if (owner) { EntityItem* entity = static_cast(owner); diff --git a/libraries/workload/src/workload/Engine.cpp b/libraries/workload/src/workload/Engine.cpp index 03c04e6632..0ede4a6d2d 100644 --- a/libraries/workload/src/workload/Engine.cpp +++ b/libraries/workload/src/workload/Engine.cpp @@ -28,16 +28,20 @@ namespace workload { void build(JobModel& model, const Varying& in, Varying& out) { model.addJob("setupViews", in); model.addJob("updateSpace"); - const auto regionChanges = model.addJob("regionTracker"); + const auto regionTrackerOut = model.addJob("regionTracker"); + const auto regionChanges = regionTrackerOut.getN(1); model.addJob("regionState", regionChanges); - out = regionChanges; + out = regionTrackerOut; } }; - Engine::Engine(const WorkloadContextPointer& context) : Task("Engine", EngineBuilder::JobModel::create()), - _context(context) { + Engine::Engine() : Task("Engine", EngineBuilder::JobModel::create()), + _context(nullptr) { } + void Engine::reset(const WorkloadContextPointer& context) { + _context = context; + } void PerformSpaceTransaction::configure(const Config& config) { diff --git a/libraries/workload/src/workload/Engine.h b/libraries/workload/src/workload/Engine.h index 773cfcb752..3c5215c508 100644 --- a/libraries/workload/src/workload/Engine.h +++ b/libraries/workload/src/workload/Engine.h @@ -37,10 +37,12 @@ namespace workload { class Engine : public Task { public: - Engine(const WorkloadContextPointer& context); + Engine(); ~Engine() = default; - void run() { assert(_context); run(_context); } + void reset(const WorkloadContextPointer& context); + + void run() { if (_context) { run(_context); } } protected: void run(const WorkloadContextPointer& context) override { assert(_context); Task::run(_context); } diff --git a/libraries/workload/src/workload/RegionTracker.cpp b/libraries/workload/src/workload/RegionTracker.cpp index c2b14937ad..381b92c414 100644 --- a/libraries/workload/src/workload/RegionTracker.cpp +++ b/libraries/workload/src/workload/RegionTracker.cpp @@ -21,22 +21,29 @@ void RegionTracker::configure(const Config& config) { } void RegionTracker::run(const WorkloadContextPointer& context, Outputs& outputs) { - outputs.clear(); + auto& outChanges = outputs.edit0(); + auto& outRegionChanges = outputs.edit1(); + + + outChanges.clear(); + outRegionChanges.clear(); + auto space = context->_space; if (space) { - Changes changes; - space->categorizeAndGetChanges(changes); + //Changes changes; + space->categorizeAndGetChanges(outChanges); + // use exit/enter lists for each region less than Region::UNKNOWN - outputs.resize(2 * (workload::Region::NUM_CLASSIFICATIONS - 1)); - for (uint32_t i = 0; i < changes.size(); ++i) { - Space::Change& change = changes[i]; + outRegionChanges.resize(2 * (workload::Region::NUM_CLASSIFICATIONS - 1)); + for (uint32_t i = 0; i < outChanges.size(); ++i) { + Space::Change& change = outChanges[i]; if (change.prevRegion < Region::UNKNOWN) { // EXIT list index = 2 * regionIndex - outputs[2 * change.prevRegion].push_back(change.proxyId); + outRegionChanges[2 * change.prevRegion].push_back(change.proxyId); } if (change.region < Region::UNKNOWN) { // ENTER list index = 2 * regionIndex + 1 - outputs[2 * change.region + 1].push_back(change.proxyId); + outRegionChanges[2 * change.region + 1].push_back(change.proxyId); } } } diff --git a/libraries/workload/src/workload/RegionTracker.h b/libraries/workload/src/workload/RegionTracker.h index e80723a7da..13285bdf07 100644 --- a/libraries/workload/src/workload/RegionTracker.h +++ b/libraries/workload/src/workload/RegionTracker.h @@ -29,7 +29,7 @@ namespace workload { class RegionTracker { public: using Config = RegionTrackerConfig; - using Outputs = IndexVectors; + using Outputs = VaryingSet2; using JobModel = workload::Job::ModelO; RegionTracker() {} From a5ee211dbf0cd6a12cc2eb01f97750422775ec9a Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 5 Apr 2018 18:04:35 -0700 Subject: [PATCH 070/138] Dirty attempt to capture the owner typefor a payload --- interface/src/workload/PhysicsBoundary.h | 12 ++++----- .../src/EntityTreeRenderer.cpp | 2 +- libraries/workload/src/workload/Proxy.h | 25 ++++++++++++++++--- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/interface/src/workload/PhysicsBoundary.h b/interface/src/workload/PhysicsBoundary.h index 8f5c1a48ff..4109418e27 100644 --- a/interface/src/workload/PhysicsBoundary.h +++ b/interface/src/workload/PhysicsBoundary.h @@ -61,12 +61,12 @@ public: uint32_t numExits = (uint32_t)regionChanges[exitIndex].size(); for (uint32_t i = 0; i < numExits; ++i) { int32_t proxyID = regionChanges[exitIndex][i]; - void* owner = space->getOwner(proxyID).get(); + auto owner = space->getOwner(proxyID).get(); if (owner) { - EntityItem* entity = static_cast(owner); + //EntityItem* entity = static_cast(owner); std::cout << "adebug - " //<< owner - << " '" << entity->getName().toStdString() << "'" + << " '" << owner->getName().toStdString() << "'" << std::endl; // adebug } } @@ -75,12 +75,12 @@ public: uint32_t numEntries = (uint32_t)regionChanges[enterIndex].size(); for (uint32_t i = 0; i < numEntries; ++i) { int32_t proxyID = regionChanges[enterIndex][i]; - void* owner = space->getOwner(proxyID).get(); + auto owner = space->getOwner(proxyID).get(); if (owner) { - EntityItem* entity = static_cast(owner); + // EntityItem* entity = static_cast(owner); std::cout << "adebug + " //<< owner - << " '" << entity->getName().toStdString() << "'" + << " '" << owner->getName().toStdString() << "'" << std::endl; // adebug } } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index ac3afb3e2b..8a8b71218c 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -284,7 +284,7 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r auto spaceIndex = _space->allocateID(); workload::Sphere sphere(entity->getWorldPosition(), entity->getBoundingRadius()); workload::Transaction transaction; - transaction.reset(spaceIndex, sphere, workload::Owner(entity.get())); + transaction.reset(spaceIndex, sphere, workload::Owner(entity)); _space->enqueueTransaction(transaction); entity->setSpaceIndex(spaceIndex); connect(entity.get(), &EntityItem::spaceUpdate, this, &EntityTreeRenderer::handleSpaceUpdate, Qt::QueuedConnection); diff --git a/libraries/workload/src/workload/Proxy.h b/libraries/workload/src/workload/Proxy.h index 0c1c7363cd..d204bd8544 100644 --- a/libraries/workload/src/workload/Proxy.h +++ b/libraries/workload/src/workload/Proxy.h @@ -18,13 +18,32 @@ namespace workload { class Owner { public: Owner() = default; - Owner(void* data) : _data(data) {} Owner(const Owner& other) = default; Owner& operator=(const Owner& other) = default; + + template Owner(const T& data) : _concept(std::make_shared>(data)) {} + ~Owner() {} - void* get() const { return _data; } + + template const T get() const { return std::static_pointer_cast>(_concept)->_data; } + +protected: + class Concept { + public: + virtual ~Concept() = default; + + }; + template class Model : public Concept { + public: + using Data = T; + Data _data; + + Model(const Data& data) : _data(data) {} + virtual ~Model() = default; + }; + private: - void* _data { nullptr }; + std::shared_ptr _concept; }; class Proxy { From b96a4ed4be81e7de267f2b6c37429304abc53550 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 6 Apr 2018 07:20:53 -0700 Subject: [PATCH 071/138] add Space::getRegion(id) --- libraries/workload/src/workload/Space.cpp | 4 ++++ libraries/workload/src/workload/Space.h | 1 + 2 files changed, 5 insertions(+) diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index ea18385c93..e5a90503da 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -127,6 +127,10 @@ const Owner Space::getOwner(int32_t proxyID) const { return Owner(); } +uint8_t Space::getRegion(int32_t proxyID) const { + return _IDAllocator.checkIndex(proxyID) ? _proxies[proxyID].region : Region::INVALID; +} + void Space::clear() { std::unique_lock lock(_proxiesMutex); _IDAllocator.clear(); diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index d8d1659751..8ed85e15ab 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -49,6 +49,7 @@ public: uint32_t copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const; const Owner getOwner(int32_t proxyID) const; + uint8_t getRegion(int32_t proxyID) const; void clear(); private: From ed1761945c64d16fb3a42c009c5eeb1c75b3015e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 6 Apr 2018 07:22:05 -0700 Subject: [PATCH 072/138] add/remove entities to physics using workload output --- interface/src/Application.cpp | 1 + interface/src/workload/PhysicsBoundary.h | 56 ++++--------------- .../src/EntityTreeRenderer.h | 2 +- libraries/physics/CMakeLists.txt | 2 +- .../physics/src/PhysicalEntitySimulation.cpp | 6 +- .../physics/src/PhysicalEntitySimulation.h | 3 + libraries/physics/src/PhysicsEngine.cpp | 2 + libraries/workload/src/workload/Proxy.h | 7 --- 8 files changed, 22 insertions(+), 57 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1b85563969..1105e7461c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4705,6 +4705,7 @@ void Application::init() { }, Qt::QueuedConnection); _gameWorkload.startup(getEntities()->getWorkloadSpace(), _main3DScene, _entitySimulation); + _entitySimulation->setWorkloadSpace(getEntities()->getWorkloadSpace()); } void Application::updateLOD(float deltaTime) const { diff --git a/interface/src/workload/PhysicsBoundary.h b/interface/src/workload/PhysicsBoundary.h index 4109418e27..7eb3644375 100644 --- a/interface/src/workload/PhysicsBoundary.h +++ b/interface/src/workload/PhysicsBoundary.h @@ -15,19 +15,6 @@ #include "render/Scene.h" -/* -class FooJobConfig : public workload::Job::Config { - Q_OBJECT - Q_PROPERTY(bool fubar MEMBER fubar NOTIFY dirty) -public: - bool fubar{ false }; -signals: - void dirty(); -protected: -}; -*/ - -#include // adebug #include #include #include "PhysicalEntitySimulation.h" @@ -45,43 +32,20 @@ public: } void run(const workload::WorkloadContextPointer& context, const Inputs& inputs) { - const auto& regionChanges = inputs.get1(); auto space = context->_space; if (!space) { return; } - uint32_t listSize = (uint32_t)regionChanges.size(); - uint32_t totalTransitions = 0; - for (uint32_t i = 0; i < listSize; ++i) { - totalTransitions += (uint32_t)regionChanges[i].size(); - } - // we're interested in things entering/leaving R3 - uint32_t regionIndex = workload::Region::R3; - uint32_t exitIndex = 2 * regionIndex; - uint32_t numExits = (uint32_t)regionChanges[exitIndex].size(); - for (uint32_t i = 0; i < numExits; ++i) { - int32_t proxyID = regionChanges[exitIndex][i]; - auto owner = space->getOwner(proxyID).get(); - if (owner) { - //EntityItem* entity = static_cast(owner); - std::cout << "adebug - " - //<< owner - << " '" << owner->getName().toStdString() << "'" - << std::endl; // adebug - } - } - - uint32_t enterIndex = exitIndex + 1; - uint32_t numEntries = (uint32_t)regionChanges[enterIndex].size(); - for (uint32_t i = 0; i < numEntries; ++i) { - int32_t proxyID = regionChanges[enterIndex][i]; - auto owner = space->getOwner(proxyID).get(); - if (owner) { - // EntityItem* entity = static_cast(owner); - std::cout << "adebug + " - //<< owner - << " '" << owner->getName().toStdString() << "'" - << std::endl; // adebug + GameWorkloadContext* gameContext = static_cast(context.get()); + PhysicalEntitySimulationPointer simulation = gameContext->_simulation; + const auto& regionChanges = inputs.get0(); + for (uint32_t i = 0; i < (uint32_t)regionChanges.size(); ++i) { + const workload::Space::Change& change = regionChanges[i]; + auto entity = space->getOwner(change.proxyId).get(); + if (entity) { + simulation->changeEntity(entity); + qCDebug("physics") << change.proxyId << " : " << "'" << entity->getName() << "' " + << (uint32_t)(change.prevRegion) << " --> " << (uint32_t)(change.region); } } } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index fa9c2ac6d2..a425ad4676 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -121,7 +121,7 @@ public: static bool shouldRenderDebugHulls() { return _renderDebugHullsOperator(); } // Access the workload Space - const workload::SpacePointer getWorkloadSpace() const { return _space; } + workload::SpacePointer getWorkloadSpace() const { return _space; } signals: void enterEntity(const EntityItemID& entityItemID); diff --git a/libraries/physics/CMakeLists.txt b/libraries/physics/CMakeLists.txt index ad082c1a6e..96a55c8477 100644 --- a/libraries/physics/CMakeLists.txt +++ b/libraries/physics/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME physics) setup_hifi_library() -link_hifi_libraries(shared fbx entities graphics) +link_hifi_libraries(shared task workload fbx entities graphics) include_hifi_library_headers(networking) include_hifi_library_headers(gpu) include_hifi_library_headers(avatars) diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index d799577fc2..f05f5a94f5 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -120,8 +120,10 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { QMutexLocker lock(&_mutex); assert(entity); EntityMotionState* motionState = static_cast(entity->getPhysicsInfo()); + uint8_t region = _space->getRegion(entity->getSpaceIndex()); + bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical(); if (motionState) { - if (!entity->shouldBePhysical()) { + if (!shouldBePhysical) { // the entity should be removed from the physical simulation _incomingChanges.remove(motionState); _physicalObjects.remove(motionState); @@ -133,7 +135,7 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { } else { _incomingChanges.insert(motionState); } - } else if (entity->shouldBePhysical()) { + } else if (shouldBePhysical) { // The intent is for this object to be in the PhysicsEngine, but it has no MotionState yet. // Perhaps it's shape has changed and it can now be added? _entitiesToAddToPhysics.insert(entity); diff --git a/libraries/physics/src/PhysicalEntitySimulation.h b/libraries/physics/src/PhysicalEntitySimulation.h index 7b6fe221fb..3f04347f18 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.h +++ b/libraries/physics/src/PhysicalEntitySimulation.h @@ -19,6 +19,7 @@ #include #include +#include #include "PhysicsEngine.h" #include "EntityMotionState.h" @@ -45,6 +46,7 @@ public: ~PhysicalEntitySimulation(); void init(EntityTreePointer tree, PhysicsEnginePointer engine, EntityEditPacketSender* packetSender); + void setWorkloadSpace(const workload::SpacePointer space) { _space = space; } virtual void addDynamic(EntityDynamicPointer dynamic) override; virtual void applyDynamicChanges() override; @@ -102,6 +104,7 @@ private: VectorOfEntityMotionStates _owned; VectorOfEntityMotionStates _bids; + workload::SpacePointer _space; uint64_t _nextBidExpiry; uint32_t _lastStepSendPackets { 0 }; }; diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 1d4c385f07..945b9c86dd 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -72,6 +72,7 @@ uint32_t PhysicsEngine::getNumSubsteps() { // private void PhysicsEngine::addObjectToDynamicsWorld(ObjectMotionState* motionState) { + qCDebug(physics) << "templog addObject" << (void*)(motionState); // TODO: remove this assert(motionState); btVector3 inertia(0.0f, 0.0f, 0.0f); @@ -193,6 +194,7 @@ void PhysicsEngine::removeObjects(const VectorOfMotionStates& objects) { for (auto object : objects) { btRigidBody* body = object->getRigidBody(); if (body) { + qCDebug(physics) << "removeObject" << (void*)(body->getMotionState()); // TODO: remove this removeDynamicsForBody(body); _dynamicsWorld->removeRigidBody(body); diff --git a/libraries/workload/src/workload/Proxy.h b/libraries/workload/src/workload/Proxy.h index d204bd8544..8e0be6f6f7 100644 --- a/libraries/workload/src/workload/Proxy.h +++ b/libraries/workload/src/workload/Proxy.h @@ -20,28 +20,21 @@ public: Owner() = default; Owner(const Owner& other) = default; Owner& operator=(const Owner& other) = default; - template Owner(const T& data) : _concept(std::make_shared>(data)) {} - ~Owner() {} - template const T get() const { return std::static_pointer_cast>(_concept)->_data; } - protected: class Concept { public: virtual ~Concept() = default; - }; template class Model : public Concept { public: using Data = T; Data _data; - Model(const Data& data) : _data(data) {} virtual ~Model() = default; }; - private: std::shared_ptr _concept; }; From da48a5af20c21e41855c47cfc232ad1a4515196b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 6 Apr 2018 11:10:23 -0700 Subject: [PATCH 073/138] fix compile errors and add PhysicsBoundary.cpp file --- interface/src/workload/PhysicsBoundary.cpp | 34 +++++++++++++++++++++ interface/src/workload/PhysicsBoundary.h | 35 ++++------------------ 2 files changed, 40 insertions(+), 29 deletions(-) create mode 100644 interface/src/workload/PhysicsBoundary.cpp diff --git a/interface/src/workload/PhysicsBoundary.cpp b/interface/src/workload/PhysicsBoundary.cpp new file mode 100644 index 0000000000..a62dfcf9f9 --- /dev/null +++ b/interface/src/workload/PhysicsBoundary.cpp @@ -0,0 +1,34 @@ +// +// PhysicsBoundary.h +// +// Created by Andrew Meadows 2018.04.05 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "PhysicsBoundary.h" + +#include +#include + +#include "workload/GameWorkload.h" + +void PhysicsBoundary::run(const workload::WorkloadContextPointer& context, const Inputs& inputs) { + auto space = context->_space; + if (!space) { + return; + } + GameWorkloadContext* gameContext = static_cast(context.get()); + PhysicalEntitySimulationPointer simulation = gameContext->_simulation; + const auto& regionChanges = inputs.get0(); + for (uint32_t i = 0; i < (uint32_t)regionChanges.size(); ++i) { + const workload::Space::Change& change = regionChanges[i]; + auto entity = space->getOwner(change.proxyId).get(); + if (entity) { + simulation->changeEntity(entity); + qCDebug(physics) << change.proxyId << " : " << "'" << entity->getName() << "' " << (uint32_t)(change.prevRegion) << " --> " << (uint32_t)(change.region); + } + } +} diff --git a/interface/src/workload/PhysicsBoundary.h b/interface/src/workload/PhysicsBoundary.h index 7eb3644375..c316fa5686 100644 --- a/interface/src/workload/PhysicsBoundary.h +++ b/interface/src/workload/PhysicsBoundary.h @@ -1,7 +1,7 @@ // // PhysicsBoundary.h // -// Created by Sam Gateau on 2/16/2018. +// Created by Andrew Meadows 2018.04.05 // Copyright 2018 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -10,13 +10,10 @@ #ifndef hifi_PhysicsGatekeeper_h #define hifi_PhysicsGatekeeper_h -#include "workload/Space.h" -#include "workload/Engine.h" - -#include "render/Scene.h" - -#include #include +#include +#include + #include "PhysicalEntitySimulation.h" class PhysicsBoundary { @@ -27,28 +24,8 @@ public: using JobModel = workload::Job::ModelI; // this doesn't work PhysicsBoundary() {} - - void configure(const Config& config) { - } - - void run(const workload::WorkloadContextPointer& context, const Inputs& inputs) { - auto space = context->_space; - if (!space) { - return; - } - GameWorkloadContext* gameContext = static_cast(context.get()); - PhysicalEntitySimulationPointer simulation = gameContext->_simulation; - const auto& regionChanges = inputs.get0(); - for (uint32_t i = 0; i < (uint32_t)regionChanges.size(); ++i) { - const workload::Space::Change& change = regionChanges[i]; - auto entity = space->getOwner(change.proxyId).get(); - if (entity) { - simulation->changeEntity(entity); - qCDebug("physics") << change.proxyId << " : " << "'" << entity->getName() << "' " - << (uint32_t)(change.prevRegion) << " --> " << (uint32_t)(change.region); - } - } - } + void configure(const Config& config) { } + void run(const workload::WorkloadContextPointer& context, const Inputs& inputs); }; #endif // hifi_PhysicsGatekeeper_h From 34426bb033eacf0fc4c0c6d08a7e285b0636eb3b Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 6 Apr 2018 12:17:51 -0700 Subject: [PATCH 074/138] FIxing the compilation on windows with math constants --- libraries/workload/src/workload/View.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/workload/src/workload/View.h b/libraries/workload/src/workload/View.h index 1dadad14ec..5f2be465c3 100644 --- a/libraries/workload/src/workload/View.h +++ b/libraries/workload/src/workload/View.h @@ -15,6 +15,7 @@ #include #include #include +#include #include "Region.h" @@ -38,7 +39,7 @@ public: float maxRadius{ FLT_MAX }; // Fov stores the half field of view angle, and tan/cos/sin ready to go, default is fov of 90deg - glm::vec4 fov_halfAngle_tan_cos_sin { (float) M_PI_4, 1.0f, (float) (M_SQRT2 * 0.5), (float) (M_SQRT2 * 0.5) }; + glm::vec4 fov_halfAngle_tan_cos_sin { glm::quarter_pi(), 1.0f, glm::root_two() * 0.5f, glm::root_two() * 0.5f}; // Origin position glm::vec3 origin{ 0.0f }; From 39fcb762a7d758a539f01faa3570874a2714d1ee Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 6 Apr 2018 13:19:24 -0700 Subject: [PATCH 075/138] fix compile warning on linux --- libraries/workload/src/workload/Space.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index e5a90503da..e254030d68 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -128,7 +128,10 @@ const Owner Space::getOwner(int32_t proxyID) const { } uint8_t Space::getRegion(int32_t proxyID) const { - return _IDAllocator.checkIndex(proxyID) ? _proxies[proxyID].region : Region::INVALID; + if (_IDAllocator.checkIndex(proxyID)) { + return _proxies[proxyID].region; + } + return (uint8_t)Region::INVALID; } void Space::clear() { From 2cfb835b569bb3cff171202dd038fb2b9031946c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 6 Apr 2018 15:26:33 -0700 Subject: [PATCH 076/138] only add to physics simulation that when necessary --- libraries/physics/src/PhysicalEntitySimulation.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index f05f5a94f5..6045b766d9 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -48,7 +48,9 @@ void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) { QMutexLocker lock(&_mutex); assert(entity); assert(!entity->isDead()); - if (entity->shouldBePhysical()) { + uint8_t region = _space->getRegion(entity->getSpaceIndex()); + bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical(); + if (shouldBePhysical) { EntityMotionState* motionState = static_cast(entity->getPhysicsInfo()); if (!motionState) { _entitiesToAddToPhysics.insert(entity); From b523b2a81afc87d9464b8cea37cda04d39a35f4f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 6 Apr 2018 15:35:17 -0700 Subject: [PATCH 077/138] more correct proxyID validation --- libraries/workload/src/workload/Space.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index e254030d68..40491fa21e 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -121,14 +121,15 @@ uint32_t Space::copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const { const Owner Space::getOwner(int32_t proxyID) const { std::unique_lock lock(_proxiesMutex); - if (_IDAllocator.checkIndex(proxyID)) { + if (isAllocatedID(proxyID) && (proxyID < (Index)_proxies.size())) { return _owners[proxyID]; } return Owner(); } uint8_t Space::getRegion(int32_t proxyID) const { - if (_IDAllocator.checkIndex(proxyID)) { + std::unique_lock lock(_proxiesMutex); + if (isAllocatedID(proxyID) && (proxyID < (Index)_proxies.size())) { return _proxies[proxyID].region; } return (uint8_t)Region::INVALID; From 694baa81e802221ab719dce0895093ccd7352346 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 6 Apr 2018 16:12:02 -0700 Subject: [PATCH 078/138] removing logging around physics --- interface/src/workload/PhysicsBoundary.cpp | 2 +- libraries/physics/src/PhysicsEngine.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/workload/PhysicsBoundary.cpp b/interface/src/workload/PhysicsBoundary.cpp index a62dfcf9f9..f239eeb78f 100644 --- a/interface/src/workload/PhysicsBoundary.cpp +++ b/interface/src/workload/PhysicsBoundary.cpp @@ -28,7 +28,7 @@ void PhysicsBoundary::run(const workload::WorkloadContextPointer& context, const auto entity = space->getOwner(change.proxyId).get(); if (entity) { simulation->changeEntity(entity); - qCDebug(physics) << change.proxyId << " : " << "'" << entity->getName() << "' " << (uint32_t)(change.prevRegion) << " --> " << (uint32_t)(change.region); + // qCDebug(physics) << change.proxyId << " : " << "'" << entity->getName() << "' " << (uint32_t)(change.prevRegion) << " --> " << (uint32_t)(change.region); } } } diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 945b9c86dd..abf7f95299 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -72,7 +72,7 @@ uint32_t PhysicsEngine::getNumSubsteps() { // private void PhysicsEngine::addObjectToDynamicsWorld(ObjectMotionState* motionState) { - qCDebug(physics) << "templog addObject" << (void*)(motionState); // TODO: remove this + // qCDebug(physics) << "templog addObject" << (void*)(motionState); // TODO: remove this assert(motionState); btVector3 inertia(0.0f, 0.0f, 0.0f); @@ -194,7 +194,7 @@ void PhysicsEngine::removeObjects(const VectorOfMotionStates& objects) { for (auto object : objects) { btRigidBody* body = object->getRigidBody(); if (body) { - qCDebug(physics) << "removeObject" << (void*)(body->getMotionState()); // TODO: remove this + // qCDebug(physics) << "removeObject" << (void*)(body->getMotionState()); // TODO: remove this removeDynamicsForBody(body); _dynamicsWorld->removeRigidBody(body); From b515fd50fcbb09ec13ed070847eff0fff7168a24 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 6 Apr 2018 16:52:49 -0700 Subject: [PATCH 079/138] remove unused data member --- libraries/entities-renderer/src/RenderableZoneEntityItem.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.h b/libraries/entities-renderer/src/RenderableZoneEntityItem.h index c5824abef0..2f8fd47b79 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.h +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.h @@ -69,7 +69,6 @@ private: graphics::SkyboxPointer editSkybox() { return editBackground()->getSkybox(); } graphics::HazePointer editHaze() { _needHazeUpdate = true; return _haze; } - bool _needsInitialSimulation{ true }; glm::vec3 _lastPosition; glm::vec3 _lastDimensions; glm::quat _lastRotation; From 353afb47b3a3f547234b6cd36d5ffe854b3d10bf Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 6 Apr 2018 16:53:08 -0700 Subject: [PATCH 080/138] more correct needsToCallUpdate() implementations --- libraries/entities/src/MaterialEntityItem.h | 2 +- libraries/entities/src/ModelEntityItem.cpp | 69 +++++++++------------ libraries/entities/src/PolyLineEntityItem.h | 2 - 3 files changed, 30 insertions(+), 43 deletions(-) diff --git a/libraries/entities/src/MaterialEntityItem.h b/libraries/entities/src/MaterialEntityItem.h index f77077a782..88ff7766c4 100644 --- a/libraries/entities/src/MaterialEntityItem.h +++ b/libraries/entities/src/MaterialEntityItem.h @@ -25,7 +25,7 @@ public: ALLOW_INSTANTIATION // This class can be instantiated void update(const quint64& now) override; - bool needsToCallUpdate() const override { return true; } + bool needsToCallUpdate() const override { return _retryApply; } // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index bec7bc1906..92d99ac3fb 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -195,53 +195,43 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit // added update function back for property fix void ModelEntityItem::update(const quint64& now) { + auto currentAnimationProperties = this->getAnimationProperties(); + if (_previousAnimationProperties != currentAnimationProperties) { + withWriteLock([&] { + // if we hit start animation or change the first or last frame then restart the animation + if ((currentAnimationProperties.getFirstFrame() != _previousAnimationProperties.getFirstFrame()) || + (currentAnimationProperties.getLastFrame() != _previousAnimationProperties.getLastFrame()) || + (currentAnimationProperties.getRunning() && !_previousAnimationProperties.getRunning())) { - { - auto currentAnimationProperties = this->getAnimationProperties(); - - if (_previousAnimationProperties != currentAnimationProperties) { - withWriteLock([&] { - // if we hit start animation or change the first or last frame then restart the animation - if ((currentAnimationProperties.getFirstFrame() != _previousAnimationProperties.getFirstFrame()) || - (currentAnimationProperties.getLastFrame() != _previousAnimationProperties.getLastFrame()) || - (currentAnimationProperties.getRunning() && !_previousAnimationProperties.getRunning())) { - - // when we start interface and the property is are set then the current frame is initialized to -1 - if (_currentFrame < 0) { - // don't reset _lastAnimated here because we need the timestamp from the ModelEntityItem constructor for when the properties were set - _currentFrame = currentAnimationProperties.getCurrentFrame(); - setAnimationCurrentFrame(_currentFrame); - } else { - _lastAnimated = usecTimestampNow(); - _currentFrame = currentAnimationProperties.getFirstFrame(); - setAnimationCurrentFrame(currentAnimationProperties.getFirstFrame()); - } - } else if (!currentAnimationProperties.getRunning() && _previousAnimationProperties.getRunning()) { - _currentFrame = currentAnimationProperties.getFirstFrame(); - setAnimationCurrentFrame(_currentFrame); - } else if (currentAnimationProperties.getCurrentFrame() != _previousAnimationProperties.getCurrentFrame()) { - // don't reset _lastAnimated here because the currentFrame was set with the previous setting of _lastAnimated + // when we start interface and the property is are set then the current frame is initialized to -1 + if (_currentFrame < 0) { + // don't reset _lastAnimated here because we need the timestamp from the ModelEntityItem constructor for when the properties were set _currentFrame = currentAnimationProperties.getCurrentFrame(); + setAnimationCurrentFrame(_currentFrame); + } else { + _lastAnimated = usecTimestampNow(); + _currentFrame = currentAnimationProperties.getFirstFrame(); + setAnimationCurrentFrame(currentAnimationProperties.getFirstFrame()); } - - }); - _previousAnimationProperties = this->getAnimationProperties(); - - } - - if (isAnimatingSomething()) { - if (!(getAnimationFirstFrame() < 0) && !(getAnimationFirstFrame() > getAnimationLastFrame())) { - updateFrameCount(); + } else if (!currentAnimationProperties.getRunning() && _previousAnimationProperties.getRunning()) { + _currentFrame = currentAnimationProperties.getFirstFrame(); + setAnimationCurrentFrame(_currentFrame); + } else if (currentAnimationProperties.getCurrentFrame() != _previousAnimationProperties.getCurrentFrame()) { + // don't reset _lastAnimated here because the currentFrame was set with the previous setting of _lastAnimated + _currentFrame = currentAnimationProperties.getCurrentFrame(); } - } - } + }); + _previousAnimationProperties = this->getAnimationProperties(); + } + if (!(getAnimationFirstFrame() < 0) && !(getAnimationFirstFrame() > getAnimationLastFrame())) { + updateFrameCount(); + } EntityItem::update(now); } bool ModelEntityItem::needsToCallUpdate() const { - - return true; + return isAnimatingSomething(); } void ModelEntityItem::updateFrameCount() { @@ -714,11 +704,10 @@ float ModelEntityItem::getAnimationFPS() const { }); } - bool ModelEntityItem::isAnimatingSomething() const { return resultWithReadLock([&] { return !_animationProperties.getURL().isEmpty() && _animationProperties.getRunning() && (_animationProperties.getFPS() != 0.0f); }); -} \ No newline at end of file +} diff --git a/libraries/entities/src/PolyLineEntityItem.h b/libraries/entities/src/PolyLineEntityItem.h index 2dc8befe97..20d7598b9f 100644 --- a/libraries/entities/src/PolyLineEntityItem.h +++ b/libraries/entities/src/PolyLineEntityItem.h @@ -78,8 +78,6 @@ class PolyLineEntityItem : public EntityItem { QString getTextures() const; void setTextures(const QString& textures); - virtual bool needsToCallUpdate() const override { return true; } - virtual ShapeType getShapeType() const override { return SHAPE_TYPE_NONE; } bool pointsChanged() const { return _pointsChanged; } From 9c84f0527527859251834e78f77f8bd1d61788fe Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 6 Apr 2018 17:32:57 -0700 Subject: [PATCH 081/138] rollback change to MaterialEntityItem, we'll fix later --- libraries/entities/src/MaterialEntityItem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/MaterialEntityItem.h b/libraries/entities/src/MaterialEntityItem.h index 88ff7766c4..f77077a782 100644 --- a/libraries/entities/src/MaterialEntityItem.h +++ b/libraries/entities/src/MaterialEntityItem.h @@ -25,7 +25,7 @@ public: ALLOW_INSTANTIATION // This class can be instantiated void update(const quint64& now) override; - bool needsToCallUpdate() const override { return _retryApply; } + bool needsToCallUpdate() const override { return true; } // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; From 72649f5c06ba1820cc2ac24c5689291506591a9d Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 9 Apr 2018 17:27:40 -0700 Subject: [PATCH 082/138] More featuers for the view of the workload and test scrtpts to stress the system) --- interface/src/Application.cpp | 2 +- interface/src/workload/GameWorkload.cpp | 3 +- interface/src/workload/GameWorkload.h | 2 +- .../src/workload/GameWorkloadRenderer.cpp | 2 +- libraries/workload/src/workload/View.cpp | 8 +- libraries/workload/src/workload/View.h | 4 +- libraries/workload/src/workload/ViewTask.cpp | 22 +- libraries/workload/src/workload/ViewTask.h | 8 + .../workload/testSimulationWorkload.js | 92 +++++++++ .../workload/testSimulationWorkload.qml | 61 ++++++ .../workload/test_simulation_scene.js | 194 ++++++++++++++++++ .../utilities/workload/workloadInspector.qml | 26 ++- 12 files changed, 410 insertions(+), 14 deletions(-) create mode 100644 scripts/developer/utilities/workload/testSimulationWorkload.js create mode 100644 scripts/developer/utilities/workload/testSimulationWorkload.qml create mode 100644 scripts/developer/utilities/workload/test_simulation_scene.js diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 394391807f..0445a0dbea 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4291,7 +4291,7 @@ void Application::idle() { } { - _gameWorkload.updateViews(_viewFrustum); + _gameWorkload.updateViews(_viewFrustum, getMyAvatar()->getHeadPosition()); _gameWorkload._engine->run(); } { diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index b6e26bcc48..0fc3e32701 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -48,8 +48,9 @@ void GameWorkload::shutdown() { _engine.reset(); } -void GameWorkload::updateViews(const ViewFrustum& frustum) { +void GameWorkload::updateViews(const ViewFrustum& frustum, const glm::vec3& headPosition) { workload::Views views; + views.emplace_back(workload::View::evalFromFrustum(frustum, headPosition - frustum.getPosition())); views.emplace_back(workload::View::evalFromFrustum(frustum)); _engine->feedInput(views); } diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index 01d748ba0e..023ecab1b8 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -37,7 +37,7 @@ public: const PhysicalEntitySimulationPointer& simulation); void shutdown(); - void updateViews(const ViewFrustum& frustum); + void updateViews(const ViewFrustum& frustum, const glm::vec3& headPosition); workload::EnginePointer _engine { std::make_shared() }; }; diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index c21f93d764..07b6ac23f0 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -66,7 +66,7 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, if (!render::Item::isValidID(_spaceRenderItemID)) { _spaceRenderItemID = scene->allocateID(); auto renderItem = std::make_shared(); - renderItem->editBound().setBox(glm::vec3(-100.0f), 200.0f); + renderItem->editBound().setBox(glm::vec3(0.0f), 32000.0f); renderItem->setAllProxies(proxies); transaction.resetItem(_spaceRenderItemID, std::make_shared(renderItem)); } diff --git a/libraries/workload/src/workload/View.cpp b/libraries/workload/src/workload/View.cpp index 3e27235f5f..3f002da36a 100644 --- a/libraries/workload/src/workload/View.cpp +++ b/libraries/workload/src/workload/View.cpp @@ -22,9 +22,13 @@ void View::setFov(float angleRad) { fov_halfAngle_tan_cos_sin.w = sinf(halfAngle); } -View View::evalFromFrustum(const ViewFrustum& frustum) { +void View::makeHorizontal() { + direction = glm::normalize(glm::vec3(direction.x, 0.0f, direction.z)); +} + +View View::evalFromFrustum(const ViewFrustum& frustum, const glm::vec3& offset) { View view; - view.origin = frustum.getPosition(); + view.origin = frustum.getPosition() + offset; view.direction = frustum.getDirection(); view.setFov(frustum.getFieldOfView()); diff --git a/libraries/workload/src/workload/View.h b/libraries/workload/src/workload/View.h index 5f2be465c3..430ac3a568 100644 --- a/libraries/workload/src/workload/View.h +++ b/libraries/workload/src/workload/View.h @@ -53,8 +53,10 @@ public: // Set fov properties from angle void setFov(float angleRad); + // Helper function to force the direction in the XZ plane + void makeHorizontal(); - static View evalFromFrustum(const ViewFrustum& frustum); + static View evalFromFrustum(const ViewFrustum& frustum, const glm::vec3& offset = glm::vec3()); static Sphere evalRegionSphere(const View& view, float originRadius, float maxDistance); static void updateRegions(View& view); diff --git a/libraries/workload/src/workload/ViewTask.cpp b/libraries/workload/src/workload/ViewTask.cpp index 705f517243..4ab4da5231 100644 --- a/libraries/workload/src/workload/ViewTask.cpp +++ b/libraries/workload/src/workload/ViewTask.cpp @@ -23,12 +23,30 @@ void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& i _views = inputs; } + // Filter the first view centerer on the avatar head if needed + Views usedViews; + if (_views.size() >= 2) { + if (data.useAvatarView) { + usedViews.push_back(_views[0]); + usedViews.insert(usedViews.end(), _views.begin() + 2, _views.end()); + } else { + usedViews.insert(usedViews.end(), _views.begin() + 1, _views.end()); + } + } else { + usedViews = _views; + } + + // Force frutum orientation horizontal if needed + if (usedViews.size() > 0 && data.forceViewHorizontal) { + usedViews[0].makeHorizontal(); + } + // Update regions based on the current config - for (auto& v : _views) { + for (auto& v : usedViews) { View::updateRegions(v, (float*) &data); } // Views are setup, assign to the Space - renderContext->_space->setViews(_views); + renderContext->_space->setViews(usedViews); } diff --git a/libraries/workload/src/workload/ViewTask.h b/libraries/workload/src/workload/ViewTask.h index 2b77aaf273..caba6260db 100644 --- a/libraries/workload/src/workload/ViewTask.h +++ b/libraries/workload/src/workload/ViewTask.h @@ -23,6 +23,8 @@ namespace workload { Q_PROPERTY(float r3Front READ getR3Front WRITE setR3Front NOTIFY dirty) Q_PROPERTY(float r3Back READ getR3Back WRITE setR3Back NOTIFY dirty) Q_PROPERTY(bool freezeViews READ getFreezeView WRITE setFreezeView NOTIFY dirty) + Q_PROPERTY(bool useAvatarView READ useAvatarView WRITE setUseAvatarView NOTIFY dirty) + Q_PROPERTY(bool forceViewHorizontal READ forceViewHorizontal WRITE setForceViewHorizontal NOTIFY dirty) public: @@ -42,6 +44,10 @@ namespace workload { bool getFreezeView() const { return data.freezeViews; } void setFreezeView(bool freeze) { data.freezeViews = freeze; emit dirty(); } + bool useAvatarView() const { return data.useAvatarView; } + void setUseAvatarView(bool use) { data.useAvatarView = use; emit dirty(); } + bool forceViewHorizontal() const { return data.forceViewHorizontal; } + void setForceViewHorizontal(bool use) { data.forceViewHorizontal = use; emit dirty(); } struct Data { float r1Back { 2.0f }; @@ -54,6 +60,8 @@ namespace workload { float r3Front{ 100.0f }; bool freezeViews{ false }; + bool useAvatarView{ false }; + bool forceViewHorizontal{ false }; } data; signals: diff --git a/scripts/developer/utilities/workload/testSimulationWorkload.js b/scripts/developer/utilities/workload/testSimulationWorkload.js new file mode 100644 index 0000000000..b4eb66880c --- /dev/null +++ b/scripts/developer/utilities/workload/testSimulationWorkload.js @@ -0,0 +1,92 @@ +"use strict"; + +// +// testSimulationWorkload.js +// tablet-workload-engine test app +// +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +Script.include("./test_simulation_scene.js") + +(function() { + var TABLET_BUTTON_NAME = "Test Sim"; + var QMLAPP_URL = Script.resolvePath("./testSimulationWorkload.qml"); + var ICON_URL = Script.resolvePath("../../../system/assets/images/luci-i.svg"); + var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/luci-a.svg"); + + var test = { scene:[] } + test.clearScene = function clearScene() { + for (var i = 0; i < this.scene.length; i++) { + Entities.deleteEntity(this.scene[i]); + } + } + + + var onAppScreen = false; + + function onClicked() { + if (onAppScreen) { + tablet.gotoHomeScreen(); + } else { + tablet.loadQMLSource(QMLAPP_URL); + } + } + + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + text: TABLET_BUTTON_NAME, + icon: ICON_URL, + activeIcon: ACTIVE_ICON_URL + }); + + var hasEventBridge = false; + + function wireEventBridge(on) { + if (!tablet) { + print("Warning in wireEventBridge(): 'tablet' undefined!"); + return; + } + if (on) { + if (!hasEventBridge) { + tablet.fromQml.connect(fromQml); + hasEventBridge = true; + } + } else { + if (hasEventBridge) { + tablet.fromQml.disconnect(fromQml); + hasEventBridge = false; + } + } + } + + function onScreenChanged(type, url) { + if (url === QMLAPP_URL) { + onAppScreen = true; + } else { + onAppScreen = false; + } + + button.editProperties({isActive: onAppScreen}); + wireEventBridge(onAppScreen); + } + + function fromQml(message) { + } + + button.clicked.connect(onClicked); + tablet.screenChanged.connect(onScreenChanged); + + Script.scriptEnding.connect(function () { + if (onAppScreen) { + tablet.gotoHomeScreen(); + } + button.clicked.disconnect(onClicked); + tablet.screenChanged.disconnect(onScreenChanged); + tablet.removeButton(button); + clearScene(); + }); + +}()); \ No newline at end of file diff --git a/scripts/developer/utilities/workload/testSimulationWorkload.qml b/scripts/developer/utilities/workload/testSimulationWorkload.qml new file mode 100644 index 0000000000..c71ea18a3d --- /dev/null +++ b/scripts/developer/utilities/workload/testSimulationWorkload.qml @@ -0,0 +1,61 @@ +// +// _workload.qml +// +// Created by Sam Gateau on 3/1/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +import "qrc:///qml/styles-uit" +import "qrc:///qml/controls-uit" as HifiControls +import "../render/configSlider" +import "./test_simulation_scene.js" as Sim + + +Rectangle { + HifiConstants { id: hifi;} + id: _test; + + width: parent ? parent.width : 400 + height: parent ? parent.height : 600 + anchors.margins: hifi.dimensions.contentMargin.x + + color: hifi.colors.baseGray; + + property var scene : [] + + function clearScene() { + for (var i = 0; i < _test.scene.length; i++) { + Entities.deleteEntity(_test.scene[i]); + } + } + Component.onCompleted: { + _test.scene = Sim.setupScene(); + + } + Component.onDestruction: { + clearScene() + } + + Column { + spacing: 5 + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: hifi.dimensions.contentMargin.x + //padding: hifi.dimensions.contentMargin.x + + + + Separator {} + HifiControls.Label { + text: "Display" + } + Separator {} + + } +} diff --git a/scripts/developer/utilities/workload/test_simulation_scene.js b/scripts/developer/utilities/workload/test_simulation_scene.js new file mode 100644 index 0000000000..0517fce680 --- /dev/null +++ b/scripts/developer/utilities/workload/test_simulation_scene.js @@ -0,0 +1,194 @@ + +var DEFAULT_LIFETIME = 120; + +var GRID_WORLD_SIZE = 100.0; +var GRID_WORLD_RESOLUTION = 4.0; + +var BACKDROP_SIZE = GRID_WORLD_SIZE / GRID_WORLD_RESOLUTION; +var BACKDROP_HALFSIZE = BACKDROP_SIZE *0.5; +var BACKDROP_MIN_C = -2; + +var ROOT_Z_OFFSET = -3; +var ROOT_Y_OFFSET = -0.1; + +var TILE_UNIT = GRID_WORLD_RESOLUTION; +var TILE_DIM = { x: TILE_UNIT, y: TILE_UNIT, z: TILE_UNIT}; +var GRID_TILE_OFFSET = Vec3.multiply(0.5, TILE_DIM); + +var OBJECT_DIM = { x: 0.5, y: 0.5, z: 0.5}; + + +var shapeTypes = [ + "none", + "box", + "sphere", + "compound", + "simple-hull", + "simple-compound", + "static-mesh" +]; + +function getTileColor(a, b, c) { + var offset = (Math.abs(a) + ((Math.abs(b) + (Math.abs(c) % 2)) % 2)) % 2; + var intensity = (1 - offset) * 128 + offset * 255; + return { red: intensity * (a % 4), green: intensity, blue: intensity * (b % 4) }; +} + +function addObject(a, b, c, lifetime) { + var center = Vec3.sum(stageTileRoot, Vec3.multiply(a, stageAxisA)); + center = Vec3.sum(center, Vec3.multiply(b, stageAxisB)); + center = Vec3.sum(center, Vec3.multiply(c, stageAxisC)); + + return (Entities.addEntity({ + type: "Shape", + shape: "Sphere", + name: "Backdrop", + color: getTileColor(a, b, c), + position: center, + rotation: stageOrientation, + dimensions: OBJECT_DIM, + lifetime: (lifetime === undefined) ? DEFAULT_LIFETIME : lifetime, + shapeType:shapeTypes[2], + dynamic: true, + gravity:{"x":0,"y":-9.8,"z":0}, + velocity:{"x":0,"y":0.02,"z":0}, + restitution:0.70, + friction:0.001, + damping:0.001, + + })); +} + +function addObjectGrid(backdrop, lifetime) { + for (var i = BACKDROP_HALFSIZE; i > -BACKDROP_HALFSIZE; i--) { + for (var j = -BACKDROP_HALFSIZE; j < BACKDROP_HALFSIZE; j++) { + backdrop.push(addObject(i, j, BACKDROP_MIN_C + 2, lifetime)); + } + } + +} + +function addFloor(lifetime) { + var floorDim = { x:BACKDROP_SIZE * TILE_DIM.x, y:TILE_DIM.y, z:BACKDROP_SIZE *TILE_DIM.x}; + var center = getStagePosOriAt(0, 0, -1).pos; + + return (Entities.addEntity({ + type: "Shape", + shape: "Cube", + name: "Floor", + color: { red: 20, green: 20, blue: 40 }, + position: center, + rotation: stageOrientation, + dimensions: floorDim, + lifetime: (lifetime === undefined) ? DEFAULT_LIFETIME : lifetime, + + shapeType:shapeTypes[1], + // dynamic: true, + // gravity:{"x":0,"y":-9.8,"z":0}, + // velocity:{"x":0,"y":0.01,"z":0}, + restitution:0.999, + friction:0.000, + damping:0.0, + + })); +} + +function addZone(hasKeyLight, hasAmbient, lifetime) { + var zoneDim = Vec3.multiply(BACKDROP_SIZE, TILE_DIM); + var center = getStagePosOriAt(0, 0, 0).pos; + + var lightDir = Vec3.normalize(Vec3.sum(Vec3.multiply(-1, Quat.getUp(stageOrientation)), Vec3.multiply(-1, Quat.getRight(stageOrientation)))) + + return (Entities.addEntity({ + type: "Zone", + name: "Backdrop zone", + + position: center, + rotation: stageOrientation, + dimensions: zoneDim, + lifetime: (lifetime === undefined) ? DEFAULT_LIFETIME : lifetime, + + keyLightMode: "enabled", + skyboxMode: "enabled", + ambientLightMode: "enabled", + + keyLight:{ + intensity: 0.8 * hasKeyLight, + direction: { + "x": 0.037007175385951996, + "y": -0.7071067690849304, + "z": -0.7061376571655273 + }, + castShadows: true, + }, + ambientLight: { + ambientIntensity: 1.0 * hasAmbient, + ambientURL: "https://github.com/highfidelity/hifi_tests/blob/master/assets/skymaps/Sky_Day-Sun-Mid-photo.ktx?raw=true", + }, + + hazeMode:"disabled", + backgroundMode:"skybox", + skybox:{ + color: {"red":2,"green":2,"blue":2}, // Dark grey background + skyboxURL: "https://github.com/highfidelity/hifi_tests/blob/master/assets/skymaps/Sky_Day-Sun-Mid-photo.ktx?raw=true", + } + })); +} + +function addTestScene(name, lifetime) { + var scene = []; + scene.push(addFloor(lifetime)); + scene.push(addZone(true, true, lifetime)); + + addObjectGrid(scene, lifetime); + + return scene; +} + + + +// Stage position and orientation initialised at setup +stageOrientation = Quat.fromPitchYawRollDegrees(0.0, 0.0, 0.0); +stageRoot = {"x":0.0,"y":0.0,"z":0.0}; +stageTileRoot = {"x":0.0,"y":0.0,"z":0.0}; +stageAxisA = Vec3.multiply(TILE_UNIT, Quat.getForward(stageOrientation)); +stageAxisB = Vec3.multiply(TILE_UNIT, Quat.getRight(stageOrientation)); +stageAxisC = Vec3.multiply(TILE_UNIT, Quat.getUp(stageOrientation)); + +setupScene = function (lifetime) { + MyAvatar.orientation = Quat.fromPitchYawRollDegrees(0.0, 0.0, 0.0); + var orientation = MyAvatar.orientation; + orientation = Quat.safeEulerAngles(orientation); + orientation.x = 0; + orientation = Quat.fromVec3Degrees(orientation); + + stageOrientation = orientation; + stageAxisA = Vec3.multiply(TILE_UNIT, Quat.getForward(stageOrientation)); + stageAxisB = Vec3.multiply(TILE_UNIT, Quat.getRight(stageOrientation)); + stageAxisC = Vec3.multiply(TILE_UNIT, Quat.getUp(stageOrientation)); + + stageRoot = Vec3.sum(MyAvatar.position, Vec3.multiply(-ROOT_Z_OFFSET, Quat.getForward(orientation))); + stageRoot = Vec3.sum(stageRoot, Vec3.multiply(ROOT_Y_OFFSET, Quat.getUp(orientation))); + stageTileRoot = Vec3.sum(stageRoot, GRID_TILE_OFFSET); + + return addTestScene("Physics_stage_backdrop", lifetime); +} + +getStagePosOriAt = function (a, b, c) { + var center = Vec3.sum(stageRoot, Vec3.multiply(a, stageAxisA)); + center = Vec3.sum(center, Vec3.multiply(b, stageAxisB)); + center = Vec3.sum(center, Vec3.multiply(c, stageAxisC)); + + return { "pos": center, "ori": stageOrientation}; +} + + +// var scene = setupScene(); + + +// clean up after test +/*Script.scriptEnding.connect(function () { + for (var i = 0; i < scene.length; i++) { + Entities.deleteEntity(scene[i]); + } +});*/ diff --git a/scripts/developer/utilities/workload/workloadInspector.qml b/scripts/developer/utilities/workload/workloadInspector.qml index ca8f11355a..bb3d290392 100644 --- a/scripts/developer/utilities/workload/workloadInspector.qml +++ b/scripts/developer/utilities/workload/workloadInspector.qml @@ -38,11 +38,27 @@ Rectangle { text: "Workload" } - HifiControls.CheckBox { - boxSize: 20 - text: "Freeze Views" - checked: Workload.getConfig("setupViews")["freezeViews"] - onCheckedChanged: { Workload.getConfig("SpaceToRender")["freezeViews"] = checked, Workload.getConfig("setupViews")["freezeViews"] = checked; } + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + HifiControls.CheckBox { + boxSize: 20 + text: "Freeze Views" + checked: Workload.getConfig("setupViews")["freezeViews"] + onCheckedChanged: { Workload.getConfig("SpaceToRender")["freezeViews"] = checked, Workload.getConfig("setupViews")["freezeViews"] = checked; } + } + HifiControls.CheckBox { + boxSize: 20 + text: "Use Avatar View" + checked: Workload.getConfig("setupViews")["useAvatarView"] + onCheckedChanged: { Workload.getConfig("setupViews")["useAvatarView"] = checked; } + } + HifiControls.CheckBox { + boxSize: 20 + text: "force View Horizontal" + checked: Workload.getConfig("setupViews")["forceViewHorizontal"] + onCheckedChanged: { Workload.getConfig("setupViews")["forceViewHorizontal"] = checked; } + } } RowLayout { From 87b3f9bd1f559b691bb4def4907f1286a20c0c41 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 9 Apr 2018 17:27:55 -0700 Subject: [PATCH 083/138] More featuers for the view of the workload and test scrtpts to stress the system) --- .../utilities/workload/test_physics_scene.js | 194 ++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 scripts/developer/utilities/workload/test_physics_scene.js diff --git a/scripts/developer/utilities/workload/test_physics_scene.js b/scripts/developer/utilities/workload/test_physics_scene.js new file mode 100644 index 0000000000..87522df636 --- /dev/null +++ b/scripts/developer/utilities/workload/test_physics_scene.js @@ -0,0 +1,194 @@ + +var DEFAULT_LIFETIME = 120; + +var GRID_WORLD_SIZE = 100.0; +var GRID_WORLD_RESOLUTION = 4.0; + +var BACKDROP_SIZE = GRID_WORLD_SIZE / GRID_WORLD_RESOLUTION; +var BACKDROP_HALFSIZE = BACKDROP_SIZE *0.5; +var BACKDROP_MIN_C = -2; + +var ROOT_Z_OFFSET = -3; +var ROOT_Y_OFFSET = -0.1; + +var TILE_UNIT = GRID_WORLD_RESOLUTION; +var TILE_DIM = { x: TILE_UNIT, y: TILE_UNIT, z: TILE_UNIT}; +var GRID_TILE_OFFSET = Vec3.multiply(0.5, TILE_DIM); + +var OBJECT_DIM = { x: 0.5, y: 0.5, z: 0.5}; + + +var shapeTypes = [ + "none", + "box", + "sphere", + "compound", + "simple-hull", + "simple-compound", + "static-mesh" +]; + +function getTileColor(a, b, c) { + var offset = (Math.abs(a) + ((Math.abs(b) + (Math.abs(c) % 2)) % 2)) % 2; + var intensity = (1 - offset) * 128 + offset * 255; + return { red: intensity * (a % 4), green: intensity, blue: intensity * (b % 4) }; +} + +function addObject(a, b, c, lifetime) { + var center = Vec3.sum(stageTileRoot, Vec3.multiply(a, stageAxisA)); + center = Vec3.sum(center, Vec3.multiply(b, stageAxisB)); + center = Vec3.sum(center, Vec3.multiply(c, stageAxisC)); + + return (Entities.addEntity({ + type: "Shape", + shape: "Sphere", + name: "Backdrop", + color: getTileColor(a, b, c), + position: center, + rotation: stageOrientation, + dimensions: OBJECT_DIM, + lifetime: (lifetime === undefined) ? DEFAULT_LIFETIME : lifetime, + shapeType:shapeTypes[2], + dynamic: true, + gravity:{"x":0,"y":-9.8,"z":0}, + velocity:{"x":0,"y":0.02,"z":0}, + restitution:0.70, + friction:0.001, + damping:0.001, + + })); +} + +function addObjectGrid(backdrop, lifetime) { + for (i = BACKDROP_HALFSIZE; i > -BACKDROP_HALFSIZE; i--) { + for (j = -BACKDROP_HALFSIZE; j < BACKDROP_HALFSIZE; j++) { + backdrop.push(addObject(i, j, BACKDROP_MIN_C + 2, lifetime)); + } + } + +} + +function addFloor(lifetime) { + var floorDim = { x:BACKDROP_SIZE * TILE_DIM.x, y:TILE_DIM.y, z:BACKDROP_SIZE *TILE_DIM.x}; + var center = getStagePosOriAt(0, 0, -1).pos; + + return (Entities.addEntity({ + type: "Shape", + shape: "Cube", + name: "Floor", + color: { red: 20, green: 20, blue: 40 }, + position: center, + rotation: stageOrientation, + dimensions: floorDim, + lifetime: (lifetime === undefined) ? DEFAULT_LIFETIME : lifetime, + + shapeType:shapeTypes[1], + // dynamic: true, + // gravity:{"x":0,"y":-9.8,"z":0}, + // velocity:{"x":0,"y":0.01,"z":0}, + restitution:0.999, + friction:0.000, + damping:0.0, + + })); +} + +function addZone(hasKeyLight, hasAmbient, lifetime) { + var zoneDim = Vec3.multiply(BACKDROP_SIZE, TILE_DIM); + var center = getStagePosOriAt(0, 0, 0).pos; + + var lightDir = Vec3.normalize(Vec3.sum(Vec3.multiply(-1, Quat.getUp(stageOrientation)), Vec3.multiply(-1, Quat.getRight(stageOrientation)))) + + return (Entities.addEntity({ + type: "Zone", + name: "Backdrop zone", + + position: center, + rotation: stageOrientation, + dimensions: zoneDim, + lifetime: (lifetime === undefined) ? DEFAULT_LIFETIME : lifetime, + + keyLightMode: "enabled", + skyboxMode: "enabled", + ambientLightMode: "enabled", + + keyLight:{ + intensity: 0.8 * hasKeyLight, + direction: { + "x": 0.037007175385951996, + "y": -0.7071067690849304, + "z": -0.7061376571655273 + }, + castShadows: true, + }, + ambientLight: { + ambientIntensity: 1.0 * hasAmbient, + ambientURL: "https://github.com/highfidelity/hifi_tests/blob/master/assets/skymaps/Sky_Day-Sun-Mid-photo.ktx?raw=true", + }, + + hazeMode:"disabled", + backgroundMode:"skybox", + skybox:{ + color: {"red":2,"green":2,"blue":2}, // Dark grey background + skyboxURL: "https://github.com/highfidelity/hifi_tests/blob/master/assets/skymaps/Sky_Day-Sun-Mid-photo.ktx?raw=true", + } + })); +} + +function addTestScene(name, lifetime) { + var scene = []; + scene.push(addFloor(lifetime)); + scene.push(addZone(true, true, lifetime)); + + addObjectGrid(scene, lifetime); + + return scene; +} + + + +// Stage position and orientation initialised at setup +stageOrientation = Quat.fromPitchYawRollDegrees(0.0, 0.0, 0.0); +stageRoot = {"x":0.0,"y":0.0,"z":0.0}; +stageTileRoot = {"x":0.0,"y":0.0,"z":0.0}; +stageAxisA = Vec3.multiply(TILE_UNIT, Quat.getForward(stageOrientation)); +stageAxisB = Vec3.multiply(TILE_UNIT, Quat.getRight(stageOrientation)); +stageAxisC = Vec3.multiply(TILE_UNIT, Quat.getUp(stageOrientation)); + +setupScene = function (lifetime) { + MyAvatar.orientation = Quat.fromPitchYawRollDegrees(0.0, 0.0, 0.0); + var orientation = MyAvatar.orientation; + orientation = Quat.safeEulerAngles(orientation); + orientation.x = 0; + orientation = Quat.fromVec3Degrees(orientation); + + stageOrientation = orientation; + stageAxisA = Vec3.multiply(TILE_UNIT, Quat.getForward(stageOrientation)); + stageAxisB = Vec3.multiply(TILE_UNIT, Quat.getRight(stageOrientation)); + stageAxisC = Vec3.multiply(TILE_UNIT, Quat.getUp(stageOrientation)); + + stageRoot = Vec3.sum(MyAvatar.position, Vec3.multiply(-ROOT_Z_OFFSET, Quat.getForward(orientation))); + stageRoot = Vec3.sum(stageRoot, Vec3.multiply(ROOT_Y_OFFSET, Quat.getUp(orientation))); + stageTileRoot = Vec3.sum(stageRoot, GRID_TILE_OFFSET); + + return addTestScene("Physics_stage_backdrop", lifetime); +} + +getStagePosOriAt = function (a, b, c) { + var center = Vec3.sum(stageRoot, Vec3.multiply(a, stageAxisA)); + center = Vec3.sum(center, Vec3.multiply(b, stageAxisB)); + center = Vec3.sum(center, Vec3.multiply(c, stageAxisC)); + + return { "pos": center, "ori": stageOrientation}; +} + + +var scene = setupScene(); + + +// clean up after test +Script.scriptEnding.connect(function () { + for (var i = 0; i < scene.length; i++) { + Entities.deleteEntity(scene[i]); + } +}); \ No newline at end of file From 6acda83f5c423d793374cda335008f98e86a49f4 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 9 Apr 2018 23:13:39 -0700 Subject: [PATCH 084/138] Bringing the test to the workload ui --- .../src/DeferredLightingEffect.cpp | 31 ++- .../workload/testSimulationWorkload.js | 31 +-- .../workload/testSimulationWorkload.qml | 34 ++- .../utilities/workload/test_physics_scene.js | 24 ++- .../workload/test_simulation_scene.js | 194 ------------------ .../developer/utilities/workload/workload.js | 22 ++ .../utilities/workload/workloadInspector.qml | 59 +++++- 7 files changed, 154 insertions(+), 241 deletions(-) delete mode 100644 scripts/developer/utilities/workload/test_simulation_scene.js diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index fc35267ddc..f7f45d5735 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -522,20 +522,11 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, auto lightStage = renderContext->_scene->getStage(); assert(lightStage); assert(lightStage->getNumLights() > 0); - auto lightAndShadow = lightStage->getCurrentKeyLightAndShadow(); - const auto& globalShadow = lightAndShadow.second; - // Bind the shadow buffers - if (globalShadow) { - for (unsigned int i = 0; i < globalShadow->getCascadeCount(); i++) { - batch.setResourceTexture(SHADOW_MAP_UNIT+i, globalShadow->getCascade(i).map); - } - } - - auto& program = deferredLightingEffect->_directionalSkyboxLight; + auto program = deferredLightingEffect->_directionalSkyboxLight; LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations; - auto keyLight = lightAndShadow.first; + // auto keyLight = lightAndShadow.first; graphics::LightPointer ambientLight; if (lightStage && lightStage->_currentFrame._ambientLights.size()) { @@ -556,6 +547,18 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, } if (deferredLightingEffect->_shadowMapEnabled && keyLightCastShadows) { + auto lightAndShadow = lightStage->getCurrentKeyLightAndShadow(); + const auto& globalShadow = lightAndShadow.second; + + // Bind the shadow buffers + if (globalShadow) { + for (unsigned int i = 0; i < globalShadow->getCascadeCount(); i++) { + batch.setResourceTexture(SHADOW_MAP_UNIT + i, globalShadow->getCascade(i).map); + } + if (locations->shadowTransformBuffer >= 0) { + batch.setUniformBuffer(locations->shadowTransformBuffer, globalShadow->getBuffer()); + } + } // If the keylight has an ambient Map then use the Skybox version of the pass // otherwise use the ambient sphere version @@ -578,12 +581,6 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, } } - if (locations->shadowTransformBuffer >= 0) { - if (globalShadow) { - batch.setUniformBuffer(locations->shadowTransformBuffer, globalShadow->getBuffer()); - } - } - batch.setPipeline(program); } diff --git a/scripts/developer/utilities/workload/testSimulationWorkload.js b/scripts/developer/utilities/workload/testSimulationWorkload.js index b4eb66880c..4378dbd5df 100644 --- a/scripts/developer/utilities/workload/testSimulationWorkload.js +++ b/scripts/developer/utilities/workload/testSimulationWorkload.js @@ -9,21 +9,13 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("./test_simulation_scene.js") +Script.include("./test_physics_scene.js") (function() { var TABLET_BUTTON_NAME = "Test Sim"; var QMLAPP_URL = Script.resolvePath("./testSimulationWorkload.qml"); var ICON_URL = Script.resolvePath("../../../system/assets/images/luci-i.svg"); var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/luci-a.svg"); - - var test = { scene:[] } - test.clearScene = function clearScene() { - for (var i = 0; i < this.scene.length; i++) { - Entities.deleteEntity(this.scene[i]); - } - } - var onAppScreen = false; @@ -72,13 +64,11 @@ Script.include("./test_simulation_scene.js") button.editProperties({isActive: onAppScreen}); wireEventBridge(onAppScreen); } - - function fromQml(message) { - } button.clicked.connect(onClicked); tablet.screenChanged.connect(onScreenChanged); + Script.scriptEnding.connect(function () { if (onAppScreen) { tablet.gotoHomeScreen(); @@ -89,4 +79,21 @@ Script.include("./test_simulation_scene.js") clearScene(); }); + + function fromQml(message) { + switch (message.method) { + case "createScene": + createScene(); + break; + case "clearScene": + clearScene(); + break; + } + + } + + function sendToQml(message) { + tablet.sendToQml(message); + } + }()); \ No newline at end of file diff --git a/scripts/developer/utilities/workload/testSimulationWorkload.qml b/scripts/developer/utilities/workload/testSimulationWorkload.qml index c71ea18a3d..bffd695be2 100644 --- a/scripts/developer/utilities/workload/testSimulationWorkload.qml +++ b/scripts/developer/utilities/workload/testSimulationWorkload.qml @@ -14,7 +14,7 @@ import QtQuick.Layouts 1.3 import "qrc:///qml/styles-uit" import "qrc:///qml/controls-uit" as HifiControls import "../render/configSlider" -import "./test_simulation_scene.js" as Sim +//import "./test_simulation_scene.js" as Sim Rectangle { @@ -27,19 +27,22 @@ Rectangle { color: hifi.colors.baseGray; - property var scene : [] - - function clearScene() { - for (var i = 0; i < _test.scene.length; i++) { - Entities.deleteEntity(_test.scene[i]); - } - } Component.onCompleted: { - _test.scene = Sim.setupScene(); - } Component.onDestruction: { - clearScene() + } + + function broadcastCreateScene() { + sendToScript({method: "createScene", params: { count:2 }}); + } + + function broadcastClearScene() { + sendToScript({method: "clearScene", params: { count:2 }}); + } + + function fromScript(message) { + switch (message.method) { + } } Column { @@ -55,6 +58,15 @@ Rectangle { HifiControls.Label { text: "Display" } + + HifiControls.Button { + text: "create scene" + onClicked: { + print("pressed") + _test.broadcastCreateScene() + } + } + Separator {} } diff --git a/scripts/developer/utilities/workload/test_physics_scene.js b/scripts/developer/utilities/workload/test_physics_scene.js index 87522df636..595a13b4b3 100644 --- a/scripts/developer/utilities/workload/test_physics_scene.js +++ b/scripts/developer/utilities/workload/test_physics_scene.js @@ -2,7 +2,7 @@ var DEFAULT_LIFETIME = 120; var GRID_WORLD_SIZE = 100.0; -var GRID_WORLD_RESOLUTION = 4.0; +var GRID_WORLD_RESOLUTION = 2.0; var BACKDROP_SIZE = GRID_WORLD_SIZE / GRID_WORLD_RESOLUTION; var BACKDROP_HALFSIZE = BACKDROP_SIZE *0.5; @@ -183,12 +183,28 @@ getStagePosOriAt = function (a, b, c) { } -var scene = setupScene(); +var scene = [] +createScene = function() { + clearScene(); + scene = setupScene(); +} -// clean up after test -Script.scriptEnding.connect(function () { +clearScene = function() { for (var i = 0; i < scene.length; i++) { Entities.deleteEntity(scene[i]); } +} + +changeResolution = function(res) { + GRID_WORLD_RESOLUTION = res; + + BACKDROP_SIZE = GRID_WORLD_SIZE / GRID_WORLD_RESOLUTION; + BACKDROP_HALFSIZE = BACKDROP_SIZE *0.5; + + TILE_UNIT = GRID_WORLD_RESOLUTION; +} +// clean up after test +Script.scriptEnding.connect(function () { + clearScene() }); \ No newline at end of file diff --git a/scripts/developer/utilities/workload/test_simulation_scene.js b/scripts/developer/utilities/workload/test_simulation_scene.js deleted file mode 100644 index 0517fce680..0000000000 --- a/scripts/developer/utilities/workload/test_simulation_scene.js +++ /dev/null @@ -1,194 +0,0 @@ - -var DEFAULT_LIFETIME = 120; - -var GRID_WORLD_SIZE = 100.0; -var GRID_WORLD_RESOLUTION = 4.0; - -var BACKDROP_SIZE = GRID_WORLD_SIZE / GRID_WORLD_RESOLUTION; -var BACKDROP_HALFSIZE = BACKDROP_SIZE *0.5; -var BACKDROP_MIN_C = -2; - -var ROOT_Z_OFFSET = -3; -var ROOT_Y_OFFSET = -0.1; - -var TILE_UNIT = GRID_WORLD_RESOLUTION; -var TILE_DIM = { x: TILE_UNIT, y: TILE_UNIT, z: TILE_UNIT}; -var GRID_TILE_OFFSET = Vec3.multiply(0.5, TILE_DIM); - -var OBJECT_DIM = { x: 0.5, y: 0.5, z: 0.5}; - - -var shapeTypes = [ - "none", - "box", - "sphere", - "compound", - "simple-hull", - "simple-compound", - "static-mesh" -]; - -function getTileColor(a, b, c) { - var offset = (Math.abs(a) + ((Math.abs(b) + (Math.abs(c) % 2)) % 2)) % 2; - var intensity = (1 - offset) * 128 + offset * 255; - return { red: intensity * (a % 4), green: intensity, blue: intensity * (b % 4) }; -} - -function addObject(a, b, c, lifetime) { - var center = Vec3.sum(stageTileRoot, Vec3.multiply(a, stageAxisA)); - center = Vec3.sum(center, Vec3.multiply(b, stageAxisB)); - center = Vec3.sum(center, Vec3.multiply(c, stageAxisC)); - - return (Entities.addEntity({ - type: "Shape", - shape: "Sphere", - name: "Backdrop", - color: getTileColor(a, b, c), - position: center, - rotation: stageOrientation, - dimensions: OBJECT_DIM, - lifetime: (lifetime === undefined) ? DEFAULT_LIFETIME : lifetime, - shapeType:shapeTypes[2], - dynamic: true, - gravity:{"x":0,"y":-9.8,"z":0}, - velocity:{"x":0,"y":0.02,"z":0}, - restitution:0.70, - friction:0.001, - damping:0.001, - - })); -} - -function addObjectGrid(backdrop, lifetime) { - for (var i = BACKDROP_HALFSIZE; i > -BACKDROP_HALFSIZE; i--) { - for (var j = -BACKDROP_HALFSIZE; j < BACKDROP_HALFSIZE; j++) { - backdrop.push(addObject(i, j, BACKDROP_MIN_C + 2, lifetime)); - } - } - -} - -function addFloor(lifetime) { - var floorDim = { x:BACKDROP_SIZE * TILE_DIM.x, y:TILE_DIM.y, z:BACKDROP_SIZE *TILE_DIM.x}; - var center = getStagePosOriAt(0, 0, -1).pos; - - return (Entities.addEntity({ - type: "Shape", - shape: "Cube", - name: "Floor", - color: { red: 20, green: 20, blue: 40 }, - position: center, - rotation: stageOrientation, - dimensions: floorDim, - lifetime: (lifetime === undefined) ? DEFAULT_LIFETIME : lifetime, - - shapeType:shapeTypes[1], - // dynamic: true, - // gravity:{"x":0,"y":-9.8,"z":0}, - // velocity:{"x":0,"y":0.01,"z":0}, - restitution:0.999, - friction:0.000, - damping:0.0, - - })); -} - -function addZone(hasKeyLight, hasAmbient, lifetime) { - var zoneDim = Vec3.multiply(BACKDROP_SIZE, TILE_DIM); - var center = getStagePosOriAt(0, 0, 0).pos; - - var lightDir = Vec3.normalize(Vec3.sum(Vec3.multiply(-1, Quat.getUp(stageOrientation)), Vec3.multiply(-1, Quat.getRight(stageOrientation)))) - - return (Entities.addEntity({ - type: "Zone", - name: "Backdrop zone", - - position: center, - rotation: stageOrientation, - dimensions: zoneDim, - lifetime: (lifetime === undefined) ? DEFAULT_LIFETIME : lifetime, - - keyLightMode: "enabled", - skyboxMode: "enabled", - ambientLightMode: "enabled", - - keyLight:{ - intensity: 0.8 * hasKeyLight, - direction: { - "x": 0.037007175385951996, - "y": -0.7071067690849304, - "z": -0.7061376571655273 - }, - castShadows: true, - }, - ambientLight: { - ambientIntensity: 1.0 * hasAmbient, - ambientURL: "https://github.com/highfidelity/hifi_tests/blob/master/assets/skymaps/Sky_Day-Sun-Mid-photo.ktx?raw=true", - }, - - hazeMode:"disabled", - backgroundMode:"skybox", - skybox:{ - color: {"red":2,"green":2,"blue":2}, // Dark grey background - skyboxURL: "https://github.com/highfidelity/hifi_tests/blob/master/assets/skymaps/Sky_Day-Sun-Mid-photo.ktx?raw=true", - } - })); -} - -function addTestScene(name, lifetime) { - var scene = []; - scene.push(addFloor(lifetime)); - scene.push(addZone(true, true, lifetime)); - - addObjectGrid(scene, lifetime); - - return scene; -} - - - -// Stage position and orientation initialised at setup -stageOrientation = Quat.fromPitchYawRollDegrees(0.0, 0.0, 0.0); -stageRoot = {"x":0.0,"y":0.0,"z":0.0}; -stageTileRoot = {"x":0.0,"y":0.0,"z":0.0}; -stageAxisA = Vec3.multiply(TILE_UNIT, Quat.getForward(stageOrientation)); -stageAxisB = Vec3.multiply(TILE_UNIT, Quat.getRight(stageOrientation)); -stageAxisC = Vec3.multiply(TILE_UNIT, Quat.getUp(stageOrientation)); - -setupScene = function (lifetime) { - MyAvatar.orientation = Quat.fromPitchYawRollDegrees(0.0, 0.0, 0.0); - var orientation = MyAvatar.orientation; - orientation = Quat.safeEulerAngles(orientation); - orientation.x = 0; - orientation = Quat.fromVec3Degrees(orientation); - - stageOrientation = orientation; - stageAxisA = Vec3.multiply(TILE_UNIT, Quat.getForward(stageOrientation)); - stageAxisB = Vec3.multiply(TILE_UNIT, Quat.getRight(stageOrientation)); - stageAxisC = Vec3.multiply(TILE_UNIT, Quat.getUp(stageOrientation)); - - stageRoot = Vec3.sum(MyAvatar.position, Vec3.multiply(-ROOT_Z_OFFSET, Quat.getForward(orientation))); - stageRoot = Vec3.sum(stageRoot, Vec3.multiply(ROOT_Y_OFFSET, Quat.getUp(orientation))); - stageTileRoot = Vec3.sum(stageRoot, GRID_TILE_OFFSET); - - return addTestScene("Physics_stage_backdrop", lifetime); -} - -getStagePosOriAt = function (a, b, c) { - var center = Vec3.sum(stageRoot, Vec3.multiply(a, stageAxisA)); - center = Vec3.sum(center, Vec3.multiply(b, stageAxisB)); - center = Vec3.sum(center, Vec3.multiply(c, stageAxisC)); - - return { "pos": center, "ori": stageOrientation}; -} - - -// var scene = setupScene(); - - -// clean up after test -/*Script.scriptEnding.connect(function () { - for (var i = 0; i < scene.length; i++) { - Entities.deleteEntity(scene[i]); - } -});*/ diff --git a/scripts/developer/utilities/workload/workload.js b/scripts/developer/utilities/workload/workload.js index 83ce428a69..57e0b12ef4 100644 --- a/scripts/developer/utilities/workload/workload.js +++ b/scripts/developer/utilities/workload/workload.js @@ -80,4 +80,26 @@ tablet.removeButton(button); }); + + Script.include("./test_physics_scene.js") + + function fromQml(message) { + switch (message.method) { + case "createScene": + createScene(); + break; + case "clearScene": + clearScene(); + break; + case "changeResolution": + changeResolution(message.params.count); + break; + } + + } + + function sendToQml(message) { + tablet.sendToQml(message); + } + }()); \ No newline at end of file diff --git a/scripts/developer/utilities/workload/workloadInspector.qml b/scripts/developer/utilities/workload/workloadInspector.qml index bb3d290392..d0a688e81a 100644 --- a/scripts/developer/utilities/workload/workloadInspector.qml +++ b/scripts/developer/utilities/workload/workloadInspector.qml @@ -26,7 +26,24 @@ Rectangle { anchors.margins: hifi.dimensions.contentMargin.x color: hifi.colors.baseGray; - + + function broadcastCreateScene() { + sendToScript({method: "createScene", params: { count:2 }}); + } + + function broadcastClearScene() { + sendToScript({method: "clearScene", params: { count:2 }}); + } + + function broadcastChangeResolution(value) { + sendToScript({method: "changeResolution", params: { count:value }}); + } + + function fromScript(message) { + switch (message.method) { + } + } + Column { spacing: 5 anchors.left: parent.left @@ -136,13 +153,49 @@ Rectangle { onCheckedChanged: { Workload.getConfig("SpaceToRender")["showViews"] = checked } } Separator {} + HifiControls.Label { + text: "Test" + } + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + HifiControls.Button { + text: "create scene" + onClicked: { + print("pressed") + _workload.broadcastCreateScene() + } + } + HifiControls.Button { + text: "clear scene" + onClicked: { + print("pressed") + _workload.broadcastClearScene() + } + } + } + HifiControls.Slider { + id: resolution + stepSize: 1.0 + anchors.left: parent.left + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.top: root.top + anchors.topMargin: 0 + minimumValue: 1 + maximumValue: 10 - Jet.TaskList { + onValueChanged: { _workload.broadcastChangeResolution(value) } + } + + Separator {} + + /*Jet.TaskList { rootConfig: Workload anchors.left: parent.left anchors.right: parent.right height: 300 - } + }*/ } } From 9c4c1bf10fed4d91ad0ebdb19f15e5cb044af653 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 12 Apr 2018 00:03:04 -0700 Subject: [PATCH 085/138] Better experimentation --- .../workload/testSimulationWorkload.js | 99 ------------------- .../workload/testSimulationWorkload.qml | 73 -------------- .../utilities/workload/test_physics_scene.js | 72 +++++++++----- .../developer/utilities/workload/workload.js | 9 +- .../utilities/workload/workloadInspector.qml | 36 ++++++- 5 files changed, 84 insertions(+), 205 deletions(-) delete mode 100644 scripts/developer/utilities/workload/testSimulationWorkload.js delete mode 100644 scripts/developer/utilities/workload/testSimulationWorkload.qml diff --git a/scripts/developer/utilities/workload/testSimulationWorkload.js b/scripts/developer/utilities/workload/testSimulationWorkload.js deleted file mode 100644 index 4378dbd5df..0000000000 --- a/scripts/developer/utilities/workload/testSimulationWorkload.js +++ /dev/null @@ -1,99 +0,0 @@ -"use strict"; - -// -// testSimulationWorkload.js -// tablet-workload-engine test app -// -// Copyright 2018 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -Script.include("./test_physics_scene.js") - -(function() { - var TABLET_BUTTON_NAME = "Test Sim"; - var QMLAPP_URL = Script.resolvePath("./testSimulationWorkload.qml"); - var ICON_URL = Script.resolvePath("../../../system/assets/images/luci-i.svg"); - var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/luci-a.svg"); - - var onAppScreen = false; - - function onClicked() { - if (onAppScreen) { - tablet.gotoHomeScreen(); - } else { - tablet.loadQMLSource(QMLAPP_URL); - } - } - - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - var button = tablet.addButton({ - text: TABLET_BUTTON_NAME, - icon: ICON_URL, - activeIcon: ACTIVE_ICON_URL - }); - - var hasEventBridge = false; - - function wireEventBridge(on) { - if (!tablet) { - print("Warning in wireEventBridge(): 'tablet' undefined!"); - return; - } - if (on) { - if (!hasEventBridge) { - tablet.fromQml.connect(fromQml); - hasEventBridge = true; - } - } else { - if (hasEventBridge) { - tablet.fromQml.disconnect(fromQml); - hasEventBridge = false; - } - } - } - - function onScreenChanged(type, url) { - 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 (onAppScreen) { - tablet.gotoHomeScreen(); - } - button.clicked.disconnect(onClicked); - tablet.screenChanged.disconnect(onScreenChanged); - tablet.removeButton(button); - clearScene(); - }); - - - function fromQml(message) { - switch (message.method) { - case "createScene": - createScene(); - break; - case "clearScene": - clearScene(); - break; - } - - } - - function sendToQml(message) { - tablet.sendToQml(message); - } - -}()); \ No newline at end of file diff --git a/scripts/developer/utilities/workload/testSimulationWorkload.qml b/scripts/developer/utilities/workload/testSimulationWorkload.qml deleted file mode 100644 index bffd695be2..0000000000 --- a/scripts/developer/utilities/workload/testSimulationWorkload.qml +++ /dev/null @@ -1,73 +0,0 @@ -// -// _workload.qml -// -// Created by Sam Gateau on 3/1/2018 -// Copyright 2018 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html -// -import QtQuick 2.7 -import QtQuick.Controls 1.4 -import QtQuick.Layouts 1.3 - -import "qrc:///qml/styles-uit" -import "qrc:///qml/controls-uit" as HifiControls -import "../render/configSlider" -//import "./test_simulation_scene.js" as Sim - - -Rectangle { - HifiConstants { id: hifi;} - id: _test; - - width: parent ? parent.width : 400 - height: parent ? parent.height : 600 - anchors.margins: hifi.dimensions.contentMargin.x - - color: hifi.colors.baseGray; - - Component.onCompleted: { - } - Component.onDestruction: { - } - - function broadcastCreateScene() { - sendToScript({method: "createScene", params: { count:2 }}); - } - - function broadcastClearScene() { - sendToScript({method: "clearScene", params: { count:2 }}); - } - - function fromScript(message) { - switch (message.method) { - } - } - - Column { - spacing: 5 - anchors.left: parent.left - anchors.right: parent.right - anchors.margins: hifi.dimensions.contentMargin.x - //padding: hifi.dimensions.contentMargin.x - - - - Separator {} - HifiControls.Label { - text: "Display" - } - - HifiControls.Button { - text: "create scene" - onClicked: { - print("pressed") - _test.broadcastCreateScene() - } - } - - Separator {} - - } -} diff --git a/scripts/developer/utilities/workload/test_physics_scene.js b/scripts/developer/utilities/workload/test_physics_scene.js index 595a13b4b3..c9daaab741 100644 --- a/scripts/developer/utilities/workload/test_physics_scene.js +++ b/scripts/developer/utilities/workload/test_physics_scene.js @@ -1,22 +1,34 @@ -var DEFAULT_LIFETIME = 120; + var DEFAULT_LIFETIME = 120; + var GRID_WORLD_SIZE = 100.0; + var GRID_WORLD_MARGIN = 5.0; + var GRID_WORLD_RESOLUTION = 30.0; -var GRID_WORLD_SIZE = 100.0; -var GRID_WORLD_RESOLUTION = 2.0; -var BACKDROP_SIZE = GRID_WORLD_SIZE / GRID_WORLD_RESOLUTION; -var BACKDROP_HALFSIZE = BACKDROP_SIZE *0.5; -var BACKDROP_MIN_C = -2; + var BACKDROP_SIZE = GRID_WORLD_RESOLUTION; + var BACKDROP_HALFSIZE = BACKDROP_SIZE *0.5; + var BACKDROP_MIN_C = -2; -var ROOT_Z_OFFSET = -3; -var ROOT_Y_OFFSET = -0.1; + var ROOT_Z_OFFSET = -3; + var ROOT_Y_OFFSET = -0.1; -var TILE_UNIT = GRID_WORLD_RESOLUTION; -var TILE_DIM = { x: TILE_UNIT, y: TILE_UNIT, z: TILE_UNIT}; -var GRID_TILE_OFFSET = Vec3.multiply(0.5, TILE_DIM); + var TILE_UNIT = GRID_WORLD_SIZE / BACKDROP_SIZE; + var TILE_DIM = { x: TILE_UNIT, y: TILE_UNIT, z: TILE_UNIT}; + var GRID_TILE_OFFSET = Vec3.multiply(0.5, TILE_DIM); -var OBJECT_DIM = { x: 0.5, y: 0.5, z: 0.5}; + function updateWorldResolution(res) { + GRID_WORLD_RESOLUTION = res; + + BACKDROP_SIZE = GRID_WORLD_RESOLUTION; + BACKDROP_HALFSIZE = BACKDROP_SIZE *0.5; + + TILE_UNIT = GRID_WORLD_SIZE / BACKDROP_SIZE; + TILE_DIM = { x: TILE_UNIT, y: TILE_UNIT, z: TILE_UNIT}; + GRID_TILE_OFFSET = Vec3.multiply(0.5, TILE_DIM); + } + + var OBJECT_DIM = { x: 0.5, y: 0.5, z: 0.5}; var shapeTypes = [ "none", @@ -69,7 +81,7 @@ function addObjectGrid(backdrop, lifetime) { } function addFloor(lifetime) { - var floorDim = { x:BACKDROP_SIZE * TILE_DIM.x, y:TILE_DIM.y, z:BACKDROP_SIZE *TILE_DIM.x}; + var floorDim = { x:GRID_WORLD_SIZE + 2 * GRID_WORLD_MARGIN, y:TILE_DIM.y, z:GRID_WORLD_SIZE + 2 * GRID_WORLD_MARGIN}; var center = getStagePosOriAt(0, 0, -1).pos; return (Entities.addEntity({ @@ -87,15 +99,15 @@ function addFloor(lifetime) { // gravity:{"x":0,"y":-9.8,"z":0}, // velocity:{"x":0,"y":0.01,"z":0}, restitution:0.999, - friction:0.000, - damping:0.0, + friction:0.001, + damping:0.3, })); } function addZone(hasKeyLight, hasAmbient, lifetime) { - var zoneDim = Vec3.multiply(BACKDROP_SIZE, TILE_DIM); - var center = getStagePosOriAt(0, 0, 0).pos; + var zoneDim = { x:GRID_WORLD_SIZE + 2 * GRID_WORLD_MARGIN, y:GRID_WORLD_SIZE, z:GRID_WORLD_SIZE + 2 * GRID_WORLD_MARGIN}; + var center = getStagePosOriAt(0, 0, -2).pos; var lightDir = Vec3.normalize(Vec3.sum(Vec3.multiply(-1, Quat.getUp(stageOrientation)), Vec3.multiply(-1, Quat.getRight(stageOrientation)))) @@ -197,14 +209,20 @@ clearScene = function() { } changeResolution = function(res) { - GRID_WORLD_RESOLUTION = res; - - BACKDROP_SIZE = GRID_WORLD_SIZE / GRID_WORLD_RESOLUTION; - BACKDROP_HALFSIZE = BACKDROP_SIZE *0.5; - - TILE_UNIT = GRID_WORLD_RESOLUTION; + updateWorldResolution(res); } -// clean up after test -Script.scriptEnding.connect(function () { - clearScene() -}); \ No newline at end of file + +getResolution = function() { + return GRID_WORLD_RESOLUTION; +} + +getNumObjects = function() { + return BACKDROP_SIZE * BACKDROP_SIZE; +} + +bumpUpFloor = function() { + print("bumpUpFloor") + if (scene.length > 0) { + Entities.editEntity(scene[0],{ velocity: {x: 0, y:-2.0,z: 0}}) + } +} \ No newline at end of file diff --git a/scripts/developer/utilities/workload/workload.js b/scripts/developer/utilities/workload/workload.js index 57e0b12ef4..d34aa883c0 100644 --- a/scripts/developer/utilities/workload/workload.js +++ b/scripts/developer/utilities/workload/workload.js @@ -87,19 +87,26 @@ switch (message.method) { case "createScene": createScene(); + sendToQml({method: "objectCount", params: { v: getNumObjects() }}) break; case "clearScene": clearScene(); + sendToQml({method: "objectCount", params: { v: getNumObjects() }}) break; case "changeResolution": changeResolution(message.params.count); + sendToQml({method: "objectCount", params: { v: getNumObjects() }}) + break; + case "bumpUpFloor": + bumpUpFloor(); break; } } + sendToQml({method: "objectCount", params: { v: getNumObjects() }}) + function sendToQml(message) { tablet.sendToQml(message); } - }()); \ No newline at end of file diff --git a/scripts/developer/utilities/workload/workloadInspector.qml b/scripts/developer/utilities/workload/workloadInspector.qml index d0a688e81a..60c71130d1 100644 --- a/scripts/developer/utilities/workload/workloadInspector.qml +++ b/scripts/developer/utilities/workload/workloadInspector.qml @@ -39,8 +39,20 @@ Rectangle { sendToScript({method: "changeResolution", params: { count:value }}); } + function broadcastBumpUpFloor(value) { + sendToScript({method: "bumpUpFloor", params: { count:0 }}); + } + function fromScript(message) { switch (message.method) { + case "resolution": + print("assigned value! " + message.params.v) + resolution.setValue(message.params.v) + break; + case "objectCount": + print("assigned objectCount! " + message.params.v) + objectCount.text = ("Num objects = " + message.params.v) + break; } } @@ -156,7 +168,7 @@ Rectangle { HifiControls.Label { text: "Test" } - RowLayout { + Row { anchors.left: parent.left anchors.right: parent.right HifiControls.Button { @@ -173,6 +185,20 @@ Rectangle { _workload.broadcastClearScene() } } + HifiControls.Button { + text: "bump floor" + onClicked: { + print("pressed") + _workload.broadcastBumpUpFloor() + } + } + } + + HifiControls.Label { + id: objectCount + anchors.left: parent.left + anchors.right: parent.right + text: "Num objects" } HifiControls.Slider { id: resolution @@ -180,14 +206,14 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.rightMargin: 0 - anchors.top: root.top anchors.topMargin: 0 - minimumValue: 1 - maximumValue: 10 + minimumValue: 5 + maximumValue: 50 + value: 3 onValueChanged: { _workload.broadcastChangeResolution(value) } } - + Separator {} /*Jet.TaskList { From d0ed5466be11eac35bd75e94838c34e64f7ea842 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 12 Apr 2018 01:32:20 -0700 Subject: [PATCH 086/138] Better experimentation --- .../utilities/workload/test_physics_scene.js | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/scripts/developer/utilities/workload/test_physics_scene.js b/scripts/developer/utilities/workload/test_physics_scene.js index c9daaab741..0cf0a36225 100644 --- a/scripts/developer/utilities/workload/test_physics_scene.js +++ b/scripts/developer/utilities/workload/test_physics_scene.js @@ -3,29 +3,33 @@ var GRID_WORLD_SIZE = 100.0; var GRID_WORLD_MARGIN = 5.0; var GRID_WORLD_RESOLUTION = 30.0; + var GRID_WORLD_DROP_HEIGHT = 5.0; - - var BACKDROP_SIZE = GRID_WORLD_RESOLUTION; - var BACKDROP_HALFSIZE = BACKDROP_SIZE *0.5; - var BACKDROP_MIN_C = -2; + var GRID_SIZE = GRID_WORLD_RESOLUTION; + var GRID_HALFSIZE = GRID_SIZE *0.5; var ROOT_Z_OFFSET = -3; var ROOT_Y_OFFSET = -0.1; - var TILE_UNIT = GRID_WORLD_SIZE / BACKDROP_SIZE; + var TILE_UNIT = GRID_WORLD_SIZE / GRID_SIZE; var TILE_DIM = { x: TILE_UNIT, y: TILE_UNIT, z: TILE_UNIT}; var GRID_TILE_OFFSET = Vec3.multiply(0.5, TILE_DIM); + var GRID_DROP_C = GRID_WORLD_DROP_HEIGHT / TILE_UNIT; function updateWorldResolution(res) { GRID_WORLD_RESOLUTION = res; - BACKDROP_SIZE = GRID_WORLD_RESOLUTION; - BACKDROP_HALFSIZE = BACKDROP_SIZE *0.5; + GRID_SIZE = GRID_WORLD_RESOLUTION; + GRID_HALFSIZE = GRID_SIZE *0.5; - TILE_UNIT = GRID_WORLD_SIZE / BACKDROP_SIZE; + TILE_UNIT = GRID_WORLD_SIZE / GRID_SIZE; TILE_DIM = { x: TILE_UNIT, y: TILE_UNIT, z: TILE_UNIT}; GRID_TILE_OFFSET = Vec3.multiply(0.5, TILE_DIM); + + GRID_DROP_C = GRID_WORLD_DROP_HEIGHT / TILE_UNIT; + print("TILE_UNIT = " + TILE_UNIT) + print("GRID_DROP_C = " + GRID_DROP_C) } var OBJECT_DIM = { x: 0.5, y: 0.5, z: 0.5}; @@ -47,9 +51,7 @@ function getTileColor(a, b, c) { } function addObject(a, b, c, lifetime) { - var center = Vec3.sum(stageTileRoot, Vec3.multiply(a, stageAxisA)); - center = Vec3.sum(center, Vec3.multiply(b, stageAxisB)); - center = Vec3.sum(center, Vec3.multiply(c, stageAxisC)); + var center = getStagePosOriAt(a, b, v).pos; return (Entities.addEntity({ type: "Shape", @@ -72,17 +74,17 @@ function addObject(a, b, c, lifetime) { } function addObjectGrid(backdrop, lifetime) { - for (i = BACKDROP_HALFSIZE; i > -BACKDROP_HALFSIZE; i--) { - for (j = -BACKDROP_HALFSIZE; j < BACKDROP_HALFSIZE; j++) { - backdrop.push(addObject(i, j, BACKDROP_MIN_C + 2, lifetime)); + for (i = GRID_HALFSIZE; i > -GRID_HALFSIZE; i--) { + for (j = -GRID_HALFSIZE; j < GRID_HALFSIZE; j++) { + backdrop.push(addObject(i, j, GRID_DROP_C, lifetime)); } } } function addFloor(lifetime) { - var floorDim = { x:GRID_WORLD_SIZE + 2 * GRID_WORLD_MARGIN, y:TILE_DIM.y, z:GRID_WORLD_SIZE + 2 * GRID_WORLD_MARGIN}; - var center = getStagePosOriAt(0, 0, -1).pos; + var floorDim = { x:GRID_WORLD_SIZE + 2 * GRID_WORLD_MARGIN, y: TILE_DIM.y, z:GRID_WORLD_SIZE + 2 * GRID_WORLD_MARGIN}; + var center = getStagePosOriAt(0, 0, -0.5).pos; return (Entities.addEntity({ type: "Shape", @@ -107,7 +109,7 @@ function addFloor(lifetime) { function addZone(hasKeyLight, hasAmbient, lifetime) { var zoneDim = { x:GRID_WORLD_SIZE + 2 * GRID_WORLD_MARGIN, y:GRID_WORLD_SIZE, z:GRID_WORLD_SIZE + 2 * GRID_WORLD_MARGIN}; - var center = getStagePosOriAt(0, 0, -2).pos; + var center = getStagePosOriAt(0, 0, -1).pos; var lightDir = Vec3.normalize(Vec3.sum(Vec3.multiply(-1, Quat.getUp(stageOrientation)), Vec3.multiply(-1, Quat.getRight(stageOrientation)))) @@ -162,7 +164,6 @@ function addTestScene(name, lifetime) { // Stage position and orientation initialised at setup stageOrientation = Quat.fromPitchYawRollDegrees(0.0, 0.0, 0.0); stageRoot = {"x":0.0,"y":0.0,"z":0.0}; -stageTileRoot = {"x":0.0,"y":0.0,"z":0.0}; stageAxisA = Vec3.multiply(TILE_UNIT, Quat.getForward(stageOrientation)); stageAxisB = Vec3.multiply(TILE_UNIT, Quat.getRight(stageOrientation)); stageAxisC = Vec3.multiply(TILE_UNIT, Quat.getUp(stageOrientation)); @@ -181,7 +182,6 @@ setupScene = function (lifetime) { stageRoot = Vec3.sum(MyAvatar.position, Vec3.multiply(-ROOT_Z_OFFSET, Quat.getForward(orientation))); stageRoot = Vec3.sum(stageRoot, Vec3.multiply(ROOT_Y_OFFSET, Quat.getUp(orientation))); - stageTileRoot = Vec3.sum(stageRoot, GRID_TILE_OFFSET); return addTestScene("Physics_stage_backdrop", lifetime); } @@ -217,7 +217,7 @@ getResolution = function() { } getNumObjects = function() { - return BACKDROP_SIZE * BACKDROP_SIZE; + return GRID_SIZE * GRID_SIZE; } bumpUpFloor = function() { From 2ca24485e097ca6adda2e542bc778a3f22690b40 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 12 Apr 2018 02:11:47 -0700 Subject: [PATCH 087/138] and again --- .../developer/utilities/workload/test_physics_scene.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/developer/utilities/workload/test_physics_scene.js b/scripts/developer/utilities/workload/test_physics_scene.js index 0cf0a36225..43294786ff 100644 --- a/scripts/developer/utilities/workload/test_physics_scene.js +++ b/scripts/developer/utilities/workload/test_physics_scene.js @@ -33,6 +33,7 @@ } var OBJECT_DIM = { x: 0.5, y: 0.5, z: 0.5}; + var OBJECT_SPIN = { x: 0.5, y: 0.5, z: 0.5}; var shapeTypes = [ "none", @@ -51,7 +52,9 @@ function getTileColor(a, b, c) { } function addObject(a, b, c, lifetime) { - var center = getStagePosOriAt(a, b, v).pos; + var center = getStagePosOriAt(a, b, c).pos; + + return (Entities.addEntity({ type: "Shape", @@ -66,8 +69,9 @@ function addObject(a, b, c, lifetime) { dynamic: true, gravity:{"x":0,"y":-9.8,"z":0}, velocity:{"x":0,"y":0.02,"z":0}, + angularVelocity:OBJECT_SPIN, restitution:0.70, - friction:0.001, + friction:0.01, damping:0.001, })); From 060c391d4707de1d5cb5b2ddbf33af6d5ff0d77d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 12 Apr 2018 13:51:15 -0700 Subject: [PATCH 088/138] more correct stat names --- interface/src/Application.cpp | 16 ++++++++-------- interface/src/ui/Stats.cpp | 6 +++--- libraries/physics/src/EntityMotionState.h | 2 +- libraries/physics/src/PhysicsEngine.cpp | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0445a0dbea..dde66c508b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5272,12 +5272,12 @@ void Application::update(float deltaTime) { QSharedPointer avatarManager = DependencyManager::get(); { - PROFILE_RANGE(simulation_physics, "Physics"); - PerformanceTimer perfTimer("physics"); + PROFILE_RANGE(simulation_physics, "Simulation"); + PerformanceTimer perfTimer("simulation"); if (_physicsEnabled) { { - PROFILE_RANGE(simulation_physics, "PreStep"); - PerformanceTimer perfTimer("preStep)"); + PROFILE_RANGE(simulation_physics, "PrePhysics"); + PerformanceTimer perfTimer("prePhys)"); { const VectorOfMotionStates& motionStates = _entitySimulation->getObjectsToRemoveFromPhysics(); _physicsEngine->removeObjects(motionStates); @@ -5311,15 +5311,15 @@ void Application::update(float deltaTime) { }); } { - PROFILE_RANGE(simulation_physics, "Step"); - PerformanceTimer perfTimer("step"); + PROFILE_RANGE(simulation_physics, "StepPhysics"); + PerformanceTimer perfTimer("stepPhysics"); getEntities()->getTree()->withWriteLock([&] { _physicsEngine->stepSimulation(); }); } { - PROFILE_RANGE(simulation_physics, "PostStep"); - PerformanceTimer perfTimer("postStep"); + PROFILE_RANGE(simulation_physics, "PostPhysics"); + PerformanceTimer perfTimer("postPhysics"); if (_physicsEngine->hasOutgoingChanges()) { // grab the collision events BEFORE handleOutgoingChanges() because at this point // we have a better idea of which objects we own or should own. diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 64ee492716..61de6977bd 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -60,7 +60,7 @@ Stats::Stats(QQuickItem* parent) : QQuickItem(parent) { bool Stats::includeTimingRecord(const QString& name) { if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails)) { if (name.startsWith("/idle/update/")) { - if (name.startsWith("/idle/update/physics/")) { + if (name.startsWith("/idle/update/simulation/")) { return Menu::getInstance()->isOptionChecked(MenuOption::ExpandPhysicsSimulationTiming); } else if (name.startsWith("/idle/update/myAvatar/")) { if (name.startsWith("/idle/update/myAvatar/simulate/")) { @@ -75,7 +75,7 @@ bool Stats::includeTimingRecord(const QString& name) { return Menu::getInstance()->isOptionChecked(MenuOption::ExpandPaintGLTiming); } else if (name.startsWith("/paintGL/")) { return Menu::getInstance()->isOptionChecked(MenuOption::ExpandPaintGLTiming); - } else if (name.startsWith("step/")) { + } else if (name.startsWith("physics/")) { return Menu::getInstance()->isOptionChecked(MenuOption::ExpandPhysicsSimulationTiming); } return true; @@ -479,7 +479,7 @@ void Stats::updateStats(bool force) { float dt = (float)itr.value().getMovingAverage() / (float)USECS_PER_MSEC; _gameUpdateStats = QString("/idle/update = %1 ms").arg(dt); - QVector categories = { "devices", "physics", "otherAvatars", "MyAvatar", "misc" }; + QVector categories = { "devices", "simulation", "otherAvatars", "MyAvatar", "misc" }; for (int32_t j = 0; j < categories.size(); ++j) { QString recordKey = "/idle/update/" + categories[j]; itr = allRecords.find(recordKey); diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 807acbfe80..a542c61d43 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -132,7 +132,7 @@ protected: // // (2) For locally owned simulation: we store the last values sent to the server, integrated forward over time // according to how we think the server doing it. We calculate the error between the true local transform - // and the remote to decide when to send another update. + // and the remote to decide whether to send another update or not. // glm::vec3 _serverPosition; // in simulation-frame (not world-frame) glm::quat _serverRotation; diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index abf7f95299..3be69bba00 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -415,7 +415,7 @@ void PhysicsEngine::harvestPerformanceStats() { if (QString(itr->Get_Current_Name()) == "stepSimulation") { itr->Enter_Child(childIndex); StatsHarvester harvester; - harvester.recurse(itr, "step/"); + harvester.recurse(itr, "physics/"); break; } itr->Next(); From d553f85e83928cd5b743e1a619dec529b3cb4076 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 12 Apr 2018 14:23:06 -0700 Subject: [PATCH 089/138] adding pickManager and pointerManager to stat summary --- interface/src/ui/Stats.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 61de6977bd..ad7585597b 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -479,7 +479,14 @@ void Stats::updateStats(bool force) { float dt = (float)itr.value().getMovingAverage() / (float)USECS_PER_MSEC; _gameUpdateStats = QString("/idle/update = %1 ms").arg(dt); - QVector categories = { "devices", "simulation", "otherAvatars", "MyAvatar", "misc" }; + QVector categories = { + "devices", + "MyAvatar", + "otherAvatars", + "pickManager", + "pointerManager", + "simulation" + }; for (int32_t j = 0; j < categories.size(); ++j) { QString recordKey = "/idle/update/" + categories[j]; itr = allRecords.find(recordKey); From 6633304773049d84dea6826a4d76a9939c94e898 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 12 Apr 2018 15:02:24 -0700 Subject: [PATCH 090/138] fix typo --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dde66c508b..e4227fca13 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5277,7 +5277,7 @@ void Application::update(float deltaTime) { if (_physicsEnabled) { { PROFILE_RANGE(simulation_physics, "PrePhysics"); - PerformanceTimer perfTimer("prePhys)"); + PerformanceTimer perfTimer("prePhysics)"); { const VectorOfMotionStates& motionStates = _entitySimulation->getObjectsToRemoveFromPhysics(); _physicsEngine->removeObjects(motionStates); From 916d8c4522ee1ecbf07355d2f41598b2c77286ea Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 16 Apr 2018 13:24:53 -0700 Subject: [PATCH 091/138] merging with upstream master, adjusting to the new Task constructor --- libraries/workload/src/workload/Engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/workload/src/workload/Engine.cpp b/libraries/workload/src/workload/Engine.cpp index 0ede4a6d2d..fb02b7f826 100644 --- a/libraries/workload/src/workload/Engine.cpp +++ b/libraries/workload/src/workload/Engine.cpp @@ -35,7 +35,7 @@ namespace workload { } }; - Engine::Engine() : Task("Engine", EngineBuilder::JobModel::create()), + Engine::Engine() : Task(EngineBuilder::JobModel::create("Engine")), _context(nullptr) { } From 2008c61368c103f8ecfbb1ebf94f40caac335803 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 16 Apr 2018 17:58:13 -0700 Subject: [PATCH 092/138] more ui test features --- .../src/workload/GameWorkloadRenderer.cpp | 2 +- .../workload/src/workload/RegionState.cpp | 7 +++ libraries/workload/src/workload/RegionState.h | 31 +++++++++++- libraries/workload/src/workload/ViewTask.cpp | 12 +++++ libraries/workload/src/workload/ViewTask.h | 6 +++ .../utilities/workload/test_physics_scene.js | 18 +++++-- .../developer/utilities/workload/workload.js | 18 +++++-- .../utilities/workload/workloadInspector.qml | 47 ++++++++++++++++++- 8 files changed, 128 insertions(+), 13 deletions(-) diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index 07b6ac23f0..38533c39da 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -66,7 +66,7 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, if (!render::Item::isValidID(_spaceRenderItemID)) { _spaceRenderItemID = scene->allocateID(); auto renderItem = std::make_shared(); - renderItem->editBound().setBox(glm::vec3(0.0f), 32000.0f); + renderItem->editBound().setBox(glm::vec3(-16000.0f), 16000.0f); renderItem->setAllProxies(proxies); transaction.resetItem(_spaceRenderItemID, std::make_shared(renderItem)); } diff --git a/libraries/workload/src/workload/RegionState.cpp b/libraries/workload/src/workload/RegionState.cpp index 996b5a5a1d..f693e68904 100644 --- a/libraries/workload/src/workload/RegionState.cpp +++ b/libraries/workload/src/workload/RegionState.cpp @@ -16,6 +16,10 @@ using namespace workload; +void RegionState::configure(const Config& config) { +} + + void RegionState::run(const workload::WorkloadContextPointer& renderContext, const Inputs& inputs) { // inputs is a vector of vectors of proxyId's: // @@ -66,4 +70,7 @@ void RegionState::run(const workload::WorkloadContextPointer& renderContext, con oldState.swap(newState); } } + + auto config = std::static_pointer_cast(renderContext->jobConfig); + config->setNum(0, _state[0].size(), _state[1].size(), _state[2].size()); } diff --git a/libraries/workload/src/workload/RegionState.h b/libraries/workload/src/workload/RegionState.h index 366d6192d2..40db9d4982 100644 --- a/libraries/workload/src/workload/RegionState.h +++ b/libraries/workload/src/workload/RegionState.h @@ -19,16 +19,45 @@ #include "Engine.h" namespace workload { + class RegionStateConfig : public Job::Config{ + Q_OBJECT + Q_PROPERTY(float numR0 READ getNumR0 NOTIFY dirty) + Q_PROPERTY(float numR1 READ getNumR1 NOTIFY dirty) + Q_PROPERTY(float numR2 READ getNumR2 NOTIFY dirty) + Q_PROPERTY(float numR3 READ getNumR3 NOTIFY dirty) + public: + + uint32_t getNumR0() const { return data.numR0; } + uint32_t getNumR1() const { return data.numR1; } + uint32_t getNumR2() const { return data.numR2; } + uint32_t getNumR3() const { return data.numR3; } + + void setNum(const uint32_t r0, const uint32_t r1, const uint32_t r2, const uint32_t r3) { + data.numR0 = r0; data.numR1 = r1; data.numR2 = r2; data.numR3 = r3; emit dirty(); + } + + struct Data { + uint32_t numR0{ 0 }; + uint32_t numR1{ 0 }; + uint32_t numR2{ 0 }; + uint32_t numR3{ 0 }; + } data; + + signals: + void dirty(); + }; class RegionState { public: + using Config = RegionStateConfig; using Inputs = IndexVectors; - using JobModel = workload::Job::ModelI; + using JobModel = workload::Job::ModelI; RegionState() { _state.resize(Region::UNKNOWN); } + void configure(const Config& config); void run(const workload::WorkloadContextPointer& renderContext, const Inputs& inputs); protected: diff --git a/libraries/workload/src/workload/ViewTask.cpp b/libraries/workload/src/workload/ViewTask.cpp index 4ab4da5231..5b056e9806 100644 --- a/libraries/workload/src/workload/ViewTask.cpp +++ b/libraries/workload/src/workload/ViewTask.cpp @@ -41,6 +41,18 @@ void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& i usedViews[0].makeHorizontal(); } + // Force frutum orientation horizontal if needed + if (usedViews.size() > 0 && data.simulateSecondaryCamera) { + auto view = usedViews[0]; + auto secondaryDirectionFlat = glm::normalize(glm::vec3(view.direction.x, 0.0f, view.direction.z)); + auto secondaryDirection = glm::normalize(glm::vec3(secondaryDirectionFlat.z, 0.0f, -secondaryDirectionFlat.x)); + + view.origin += -30.0f * secondaryDirection; + view.direction = -secondaryDirectionFlat; + + usedViews.insert(usedViews.begin() + 1, view); + } + // Update regions based on the current config for (auto& v : usedViews) { View::updateRegions(v, (float*) &data); diff --git a/libraries/workload/src/workload/ViewTask.h b/libraries/workload/src/workload/ViewTask.h index caba6260db..251526b2d9 100644 --- a/libraries/workload/src/workload/ViewTask.h +++ b/libraries/workload/src/workload/ViewTask.h @@ -25,6 +25,8 @@ namespace workload { Q_PROPERTY(bool freezeViews READ getFreezeView WRITE setFreezeView NOTIFY dirty) Q_PROPERTY(bool useAvatarView READ useAvatarView WRITE setUseAvatarView NOTIFY dirty) Q_PROPERTY(bool forceViewHorizontal READ forceViewHorizontal WRITE setForceViewHorizontal NOTIFY dirty) + + Q_PROPERTY(bool simulateSecondaryCamera READ simulateSecondaryCamera WRITE setSimulateSecondaryCamera NOTIFY dirty) public: @@ -49,6 +51,9 @@ namespace workload { bool forceViewHorizontal() const { return data.forceViewHorizontal; } void setForceViewHorizontal(bool use) { data.forceViewHorizontal = use; emit dirty(); } + bool simulateSecondaryCamera() const { return data.simulateSecondaryCamera; } + void setSimulateSecondaryCamera(bool use) { data.simulateSecondaryCamera = use; emit dirty(); } + struct Data { float r1Back { 2.0f }; float r1Front { 10.0f }; @@ -62,6 +67,7 @@ namespace workload { bool freezeViews{ false }; bool useAvatarView{ false }; bool forceViewHorizontal{ false }; + bool simulateSecondaryCamera{ false }; } data; signals: diff --git a/scripts/developer/utilities/workload/test_physics_scene.js b/scripts/developer/utilities/workload/test_physics_scene.js index 43294786ff..8a1b326b1e 100644 --- a/scripts/developer/utilities/workload/test_physics_scene.js +++ b/scripts/developer/utilities/workload/test_physics_scene.js @@ -17,7 +17,8 @@ var GRID_DROP_C = GRID_WORLD_DROP_HEIGHT / TILE_UNIT; - function updateWorldResolution(res) { + function updateWorldSizeAndResolution(size, res) { + GRID_WORLD_SIZE = size GRID_WORLD_RESOLUTION = res; GRID_SIZE = GRID_WORLD_RESOLUTION; @@ -155,8 +156,8 @@ function addZone(hasKeyLight, hasAmbient, lifetime) { function addTestScene(name, lifetime) { var scene = []; - scene.push(addFloor(lifetime)); - scene.push(addZone(true, true, lifetime)); + // scene.push(addFloor(lifetime)); + // scene.push(addZone(true, true, lifetime)); addObjectGrid(scene, lifetime); @@ -213,13 +214,22 @@ clearScene = function() { } changeResolution = function(res) { - updateWorldResolution(res); + updateWorldSizeAndResolution(GRID_WORLD_SIZE, res); } getResolution = function() { return GRID_WORLD_RESOLUTION; } +changeSize = function(size) { + updateWorldSizeAndResolution(size, GRID_WORLD_RESOLUTION); +} + +getSize = function() { + return GRID_WORLD_SIZE; +} + + getNumObjects = function() { return GRID_SIZE * GRID_SIZE; } diff --git a/scripts/developer/utilities/workload/workload.js b/scripts/developer/utilities/workload/workload.js index d34aa883c0..d74eb4e6d5 100644 --- a/scripts/developer/utilities/workload/workload.js +++ b/scripts/developer/utilities/workload/workload.js @@ -87,15 +87,19 @@ switch (message.method) { case "createScene": createScene(); - sendToQml({method: "objectCount", params: { v: getNumObjects() }}) + updateGridInQML() break; case "clearScene": clearScene(); - sendToQml({method: "objectCount", params: { v: getNumObjects() }}) + updateGridInQML() + break; + case "changeSize": + changeSize(message.params.count); + updateGridInQML() break; case "changeResolution": changeResolution(message.params.count); - sendToQml({method: "objectCount", params: { v: getNumObjects() }}) + updateGridInQML() break; case "bumpUpFloor": bumpUpFloor(); @@ -103,10 +107,14 @@ } } - - sendToQml({method: "objectCount", params: { v: getNumObjects() }}) + function updateGridInQML() { + sendToQml({method: "gridSize", params: { v: getSize() }}) + sendToQml({method: "objectCount", params: { v: getNumObjects() }}) + } function sendToQml(message) { tablet.sendToQml(message); } + + updateGridInQML() }()); \ No newline at end of file diff --git a/scripts/developer/utilities/workload/workloadInspector.qml b/scripts/developer/utilities/workload/workloadInspector.qml index abe7141747..06e5edd046 100644 --- a/scripts/developer/utilities/workload/workloadInspector.qml +++ b/scripts/developer/utilities/workload/workloadInspector.qml @@ -35,6 +35,10 @@ Rectangle { sendToScript({method: "clearScene", params: { count:2 }}); } + function broadcastChangeSize(value) { + sendToScript({method: "changeSize", params: { count:value }}); + } + function broadcastChangeResolution(value) { sendToScript({method: "changeResolution", params: { count:value }}); } @@ -45,10 +49,15 @@ Rectangle { function fromScript(message) { switch (message.method) { + case "gridSize": + print("assigned value! " + message.params.v) + gridSizeLabel.text = ("Grid size [m] = " + message.params.v) + gridSize.setValue(message.params.v) + break; case "resolution": print("assigned value! " + message.params.v) resolution.setValue(message.params.v) - break; + break; case "objectCount": print("assigned objectCount! " + message.params.v) objectCount.text = ("Num objects = " + message.params.v) @@ -90,6 +99,17 @@ Rectangle { } } + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + HifiControls.CheckBox { + boxSize: 20 + text: "Simulate Secondary" + checked: Workload.getConfig("setupViews")["simulateSecondaryCamera"] + onCheckedChanged: { Workload.getConfig("setupViews")["simulateSecondaryCamera"] = checked; } + } + } + RowLayout { anchors.left: parent.left anchors.right: parent.right @@ -148,6 +168,10 @@ Rectangle { } } } + Separator {} + HifiControls.Label { + text: "Numbers: R2= " + Workload.getConfig("regionState")["numR2"]; + } Separator {} HifiControls.Label { text: "Display" @@ -193,7 +217,26 @@ Rectangle { } } } - + HifiControls.Label { + id: gridSizeLabel + anchors.left: parent.left + anchors.right: parent.right + text: "Grid side size [m]" + } + HifiControls.Slider { + id: gridSize + stepSize: 1.0 + anchors.left: parent.left + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.topMargin: 0 + minimumValue: 1 + maximumValue: 200 + value: 100 + + onValueChanged: { _workload.broadcastChangeSize(value) } + } + HifiControls.Label { id: objectCount anchors.left: parent.left From fd752a07c1a49b3d6dc96850350b2c5ca2f30efb Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 17 Apr 2018 02:05:35 -0700 Subject: [PATCH 093/138] Proposing a more flexible design for the engine --- interface/src/workload/GameWorkload.cpp | 22 +++++---- interface/src/workload/GameWorkload.h | 3 +- libraries/workload/src/workload/Engine.cpp | 32 ------------- libraries/workload/src/workload/Engine.h | 32 ++++--------- .../workload/src/workload/RegionTracker.h | 1 - libraries/workload/src/workload/Space.h | 1 + .../workload/src/workload/SpaceClassifier.cpp | 34 ++++++++++++++ .../workload/src/workload/SpaceClassifier.h | 47 +++++++++++++++++++ .../utilities/workload/workloadInspector.qml | 13 ++++- 9 files changed, 117 insertions(+), 68 deletions(-) create mode 100644 libraries/workload/src/workload/SpaceClassifier.cpp create mode 100644 libraries/workload/src/workload/SpaceClassifier.h diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 0fc3e32701..5f992d0934 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -11,13 +11,14 @@ #include "GameWorkloadRenderer.h" #include #include +#include #include "PhysicsBoundary.h" GameWorkloadContext::GameWorkloadContext(const workload::SpacePointer& space, const render::ScenePointer& scene, - const PhysicalEntitySimulationPointer& simulation) -: WorkloadContext(space), _scene(scene), _simulation(simulation) + const PhysicalEntitySimulationPointer& simulation): WorkloadContext(space), + _scene(scene), _simulation(simulation) { } @@ -25,7 +26,9 @@ GameWorkloadContext::~GameWorkloadContext() { } -GameWorkload::GameWorkload() { +GameWorkload::GameWorkload() : + _engine(std::make_shared(std::make_shared(workload::SpaceClassifierTask::JobModel::create("Engine")))) +{ } GameWorkload::~GameWorkload() { @@ -37,11 +40,11 @@ void GameWorkload::startup(const workload::SpacePointer& space, const PhysicalEntitySimulationPointer& simulation) { _engine->reset(std::make_shared(space, scene, simulation)); - auto output = _engine->getOutput(); - _engine->addJob("SpaceToRender"); + auto output = _engine->_task->getOutput(); + _engine->_task->addJob("SpaceToRender"); - const auto regionChanges = _engine->getOutput(); - _engine->addJob("PhysicsBoundary", regionChanges); + const auto regionChanges = _engine->_task->getOutput(); + _engine->_task->addJob("PhysicsBoundary", regionChanges); } void GameWorkload::shutdown() { @@ -52,6 +55,9 @@ void GameWorkload::updateViews(const ViewFrustum& frustum, const glm::vec3& head workload::Views views; views.emplace_back(workload::View::evalFromFrustum(frustum, headPosition - frustum.getPosition())); views.emplace_back(workload::View::evalFromFrustum(frustum)); - _engine->feedInput(views); + _engine->_task->feedInput(views); } +void GameWorkload::updateSimulationTiming(const workload::Timings& timings) { + // _engine->_task->feedInput(timings); +} diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index 023ecab1b8..1f835686f8 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -38,8 +38,9 @@ public: void shutdown(); void updateViews(const ViewFrustum& frustum, const glm::vec3& headPosition); + void updateSimulationTimings(const workload::Timings& timings); - workload::EnginePointer _engine { std::make_shared() }; + workload::EnginePointer _engine; }; #endif // hifi_GameWorkload_h diff --git a/libraries/workload/src/workload/Engine.cpp b/libraries/workload/src/workload/Engine.cpp index fb02b7f826..0ecae55b72 100644 --- a/libraries/workload/src/workload/Engine.cpp +++ b/libraries/workload/src/workload/Engine.cpp @@ -13,43 +13,11 @@ #include -#include "ViewTask.h" -#include "RegionTracker.h" -#include "RegionState.h" - namespace workload { WorkloadContext::WorkloadContext(const SpacePointer& space) : task::JobContext(trace_workload()), _space(space) {} - class EngineBuilder { - public: - using Inputs = Views; - using Outputs = RegionTracker::Outputs; - using JobModel = Task::ModelIO; - void build(JobModel& model, const Varying& in, Varying& out) { - model.addJob("setupViews", in); - model.addJob("updateSpace"); - const auto regionTrackerOut = model.addJob("regionTracker"); - const auto regionChanges = regionTrackerOut.getN(1); - model.addJob("regionState", regionChanges); - out = regionTrackerOut; - } - }; - - Engine::Engine() : Task(EngineBuilder::JobModel::create("Engine")), - _context(nullptr) { - } - void Engine::reset(const WorkloadContextPointer& context) { _context = context; } - - void PerformSpaceTransaction::configure(const Config& config) { - - } - void PerformSpaceTransaction::run(const WorkloadContextPointer& context) { - context->_space->enqueueFrame(); - context->_space->processTransactionQueue(); - } - } // namespace workload diff --git a/libraries/workload/src/workload/Engine.h b/libraries/workload/src/workload/Engine.h index 3c5215c508..d1628dfc61 100644 --- a/libraries/workload/src/workload/Engine.h +++ b/libraries/workload/src/workload/Engine.h @@ -23,7 +23,6 @@ #include "Space.h" namespace workload { - class WorkloadContext : public task::JobContext { public: WorkloadContext(const SpacePointer& space); @@ -35,41 +34,26 @@ namespace workload { using WorkloadContextPointer = std::shared_ptr; Task_DeclareTypeAliases(WorkloadContext) - class Engine : public Task { + class Engine { public: - Engine(); + Engine(const std::shared_ptr& task) : _task(task), _context(nullptr) { + } ~Engine() = default; void reset(const WorkloadContextPointer& context); - void run() { if (_context) { run(_context); } } + void run() { if (_context) { _task->run(_context); } } + + std::shared_ptr getConfiguration() { return _task->getConfiguration(); } + + std::shared_ptr _task; protected: - void run(const WorkloadContextPointer& context) override { assert(_context); Task::run(_context); } private: WorkloadContextPointer _context; }; using EnginePointer = std::shared_ptr; - - class PerformSpaceTransactionConfig : public Job::Config { - Q_OBJECT - public: - signals : - void dirty(); - - protected: - }; - - class PerformSpaceTransaction { - public: - using Config = PerformSpaceTransactionConfig; - using JobModel = Job::Model; - - void configure(const Config& config); - void run(const WorkloadContextPointer& context); - protected: - }; } // namespace workload #endif // hifi_workload_Space_h diff --git a/libraries/workload/src/workload/RegionTracker.h b/libraries/workload/src/workload/RegionTracker.h index 13285bdf07..29a9af1f84 100644 --- a/libraries/workload/src/workload/RegionTracker.h +++ b/libraries/workload/src/workload/RegionTracker.h @@ -39,7 +39,6 @@ namespace workload { protected: }; - } // namespace workload #endif // hifi_workload_RegionTracker_h diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index 8ed85e15ab..ab7dd02134 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -70,6 +70,7 @@ private: using SpacePointer = std::shared_ptr; using Changes = std::vector; using IndexVectors = std::vector; +using Timings = std::vector; } // namespace workload diff --git a/libraries/workload/src/workload/SpaceClassifier.cpp b/libraries/workload/src/workload/SpaceClassifier.cpp new file mode 100644 index 0000000000..080210714f --- /dev/null +++ b/libraries/workload/src/workload/SpaceClassifier.cpp @@ -0,0 +1,34 @@ +// +// SpaceClassifier.cpp +// libraries/workload/src/workload +// +// Created by Andrew Meadows 2018.02.21 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "SpaceClassifier.h" + +#include "ViewTask.h" +#include "RegionState.h" + +using namespace workload; + +void PerformSpaceTransaction::configure(const Config& config) { + +} +void PerformSpaceTransaction::run(const WorkloadContextPointer& context) { + context->_space->enqueueFrame(); + context->_space->processTransactionQueue(); +} + +void SpaceClassifierTask::build(JobModel& model, const Varying& in, Varying& out) { + model.addJob("setupViews", in); + model.addJob("updateSpace"); + const auto regionTrackerOut = model.addJob("regionTracker"); + const auto regionChanges = regionTrackerOut.getN(1); + model.addJob("regionState", regionChanges); + out = regionTrackerOut; +} + diff --git a/libraries/workload/src/workload/SpaceClassifier.h b/libraries/workload/src/workload/SpaceClassifier.h new file mode 100644 index 0000000000..06ddaee520 --- /dev/null +++ b/libraries/workload/src/workload/SpaceClassifier.h @@ -0,0 +1,47 @@ +// +// SpaceClassifier.h +// libraries/workload/src/workload +// +// Created by Andrew Meadows 2018.02.21 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_workload_SpaceClassifier_h +#define hifi_workload_SpaceClassifier_h + +#include "ViewTask.h" +#include "RegionTracker.h" + +namespace workload { + class SpaceClassifierTask { + public: + using Inputs = Views; + using Outputs = RegionTracker::Outputs; + using JobModel = Task::ModelIO; + void build(JobModel& model, const Varying& in, Varying& out); + }; + + + class PerformSpaceTransactionConfig : public Job::Config { + Q_OBJECT + public: + signals : + void dirty(); + + protected: + }; + + class PerformSpaceTransaction { + public: + using Config = PerformSpaceTransactionConfig; + using JobModel = Job::Model; + + void configure(const Config& config); + void run(const WorkloadContextPointer& context); + protected: + }; +} // namespace workload + +#endif // hifi_workload_SpaceClassifier_h diff --git a/scripts/developer/utilities/workload/workloadInspector.qml b/scripts/developer/utilities/workload/workloadInspector.qml index 06e5edd046..2dc4ad0491 100644 --- a/scripts/developer/utilities/workload/workloadInspector.qml +++ b/scripts/developer/utilities/workload/workloadInspector.qml @@ -170,8 +170,17 @@ Rectangle { } Separator {} HifiControls.Label { - text: "Numbers: R2= " + Workload.getConfig("regionState")["numR2"]; - } + text: "Numbers:"; + } + HifiControls.Label { + text: "R1= " + Workload.getConfig("regionState")["numR1"]; + } + HifiControls.Label { + text: "R2= " + Workload.getConfig("regionState")["numR2"]; + } + HifiControls.Label { + text: "R3= " + Workload.getConfig("regionState")["numR3"]; + } Separator {} HifiControls.Label { text: "Display" From ab04a34ccffa87a1224f5462a6c825cc66ecc842 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 17 Apr 2018 02:06:33 -0700 Subject: [PATCH 094/138] Proposing a more flexible design for the engine --- interface/src/workload/GameWorkload.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 5f992d0934..6cc1d824a1 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -58,6 +58,6 @@ void GameWorkload::updateViews(const ViewFrustum& frustum, const glm::vec3& head _engine->_task->feedInput(views); } -void GameWorkload::updateSimulationTiming(const workload::Timings& timings) { +void GameWorkload::updateSimulationTimings(const workload::Timings& timings) { // _engine->_task->feedInput(timings); } From d6b6645630ef8427edcf14586f9b35ccfb0d454a Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 17 Apr 2018 18:03:45 -0700 Subject: [PATCH 095/138] exposing feedback of timing --- interface/src/Application.cpp | 2 + interface/src/ui/Stats.cpp | 6 +-- interface/src/workload/GameWorkload.cpp | 47 +++++++++++++++---- interface/src/workload/GameWorkload.h | 19 ++++++++ .../src/workload/GameWorkloadRenderer.cpp | 2 +- .../src/EntityTreeRenderer.cpp | 30 +++++++----- libraries/entities/src/EntitySimulation.cpp | 1 + libraries/entities/src/EntityTree.cpp | 1 + libraries/task/src/task/Task.h | 29 +++++++++++- libraries/workload/src/workload/Engine.cpp | 4 -- libraries/workload/src/workload/Engine.h | 21 +-------- .../workload/src/workload/SpaceClassifier.cpp | 2 +- libraries/workload/src/workload/ViewTask.cpp | 39 ++++++++------- libraries/workload/src/workload/ViewTask.h | 13 ++++- 14 files changed, 147 insertions(+), 69 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 456bb54890..66e3ce8d1f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4287,6 +4287,8 @@ void Application::idle() { } { + workload::Timings timings(1, PerformanceTimer::getTimerRecord("/idle/update/simulation").getAverage()); + _gameWorkload.updateSimulationTimings(timings); _gameWorkload.updateViews(_viewFrustum, getMyAvatar()->getHeadPosition()); _gameWorkload._engine->run(); } diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index ad7585597b..b2601ff82c 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -489,9 +489,9 @@ void Stats::updateStats(bool force) { }; for (int32_t j = 0; j < categories.size(); ++j) { QString recordKey = "/idle/update/" + categories[j]; - itr = allRecords.find(recordKey); - if (itr != allRecords.end()) { - float dt = (float)itr.value().getMovingAverage() / (float)USECS_PER_MSEC; + auto record = PerformanceTimer::getTimerRecord(recordKey); + if (record.getCount()) { + float dt = (float) record.getMovingAverage() / (float)USECS_PER_MSEC; QString message = QString("\n %1 = %2").arg(categories[j]).arg(dt); idleUpdateStats.push(SortableStat(message, dt)); } diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 6cc1d824a1..e9f54f0663 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -15,6 +15,41 @@ #include "PhysicsBoundary.h" +void ControlViews::run(const workload::WorkloadContextPointer& renderContext, const Input& inputs, Output& outputs) { + const auto& inViews = inputs.getN<0>(); + const auto& inTimings = inputs[1]; + + outputs = inViews; +} + +class WorkloadEngineBuilder { +public: +public: + using Inputs = workload::VaryingSet2; + using Outputs = workload::RegionTracker::Outputs; + using JobModel = workload::Task::ModelIO; + void build(JobModel& model, const workload::Varying& in, workload::Varying& out) { + + const auto& inViews = in.getN(0); + const auto& inTimings = in.getN(1); + + const auto usedViews = model.addJob("setupViews", inViews); + + ControlViews::Input controlViewsIn; + controlViewsIn[0] = usedViews; + controlViewsIn[1] = inTimings; + const auto fixedViews = model.addJob("controlViews", controlViewsIn); + + const auto regionTrackerOut = model.addJob("spaceClassifier", fixedViews); + + model.addJob("PhysicsBoundary", regionTrackerOut); + + model.addJob("SpaceToRender"); + + out = regionTrackerOut; + } +}; + GameWorkloadContext::GameWorkloadContext(const workload::SpacePointer& space, const render::ScenePointer& scene, const PhysicalEntitySimulationPointer& simulation): WorkloadContext(space), @@ -27,7 +62,7 @@ GameWorkloadContext::~GameWorkloadContext() { GameWorkload::GameWorkload() : - _engine(std::make_shared(std::make_shared(workload::SpaceClassifierTask::JobModel::create("Engine")))) + _engine(std::make_shared(WorkloadEngineBuilder::JobModel::create("Engine"))) { } @@ -39,12 +74,6 @@ void GameWorkload::startup(const workload::SpacePointer& space, const render::ScenePointer& scene, const PhysicalEntitySimulationPointer& simulation) { _engine->reset(std::make_shared(space, scene, simulation)); - - auto output = _engine->_task->getOutput(); - _engine->_task->addJob("SpaceToRender"); - - const auto regionChanges = _engine->_task->getOutput(); - _engine->_task->addJob("PhysicsBoundary", regionChanges); } void GameWorkload::shutdown() { @@ -55,9 +84,9 @@ void GameWorkload::updateViews(const ViewFrustum& frustum, const glm::vec3& head workload::Views views; views.emplace_back(workload::View::evalFromFrustum(frustum, headPosition - frustum.getPosition())); views.emplace_back(workload::View::evalFromFrustum(frustum)); - _engine->_task->feedInput(views); + _engine->feedInput(0, views); } void GameWorkload::updateSimulationTimings(const workload::Timings& timings) { - // _engine->_task->feedInput(timings); + _engine->feedInput(1, timings); } diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index 1f835686f8..5472e5b99c 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -43,4 +43,23 @@ public: workload::EnginePointer _engine; }; +class ControlViewsConfig : public workload::Job::Config { + Q_OBJECT +public: + +signals: + void dirty(); +}; + +class ControlViews { +public: + using Config = ControlViewsConfig; + using Input = workload::VaryingSet2; + using Output = workload::Views; + using JobModel = workload::Job::ModelIO; + + void configure(const Config& config) {} + void run(const workload::WorkloadContextPointer& renderContext, const Input& inputs, Output& outputs); +}; + #endif // hifi_GameWorkload_h diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index 38533c39da..b6d1045e63 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -248,7 +248,7 @@ void GameWorkloadRenderItem::render(RenderArgs* args) { batch.setUniformBuffer(0, getDrawViewBuffer()); static const int NUM_VERTICES_PER_DRAWVIEWVERT = 2; static const int NUM_REGIONS = 3; - batch.draw(gpu::TRIANGLE_STRIP, NUM_REGIONS * NUM_VERTICES_PER_DRAWVIEWVERT * _numDrawViewVerts, 0); + batch.draw(gpu::TRIANGLE_STRIP, NUM_REGIONS * NUM_VERTICES_PER_DRAWVIEWVERT * _numDrawViewVerts * _numAllViews, 0); } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 8a8b71218c..3ffb1f8b92 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -415,7 +415,10 @@ void EntityTreeRenderer::update(bool simulate) { EntityTreePointer tree = std::static_pointer_cast(_tree); // here we update _currentFrame and _lastAnimated and sync with the server properties. - tree->update(simulate); + { + PerformanceTimer perfTimer("tree::update"); + tree->update(simulate); + } { // Update the rendereable entities as needed PROFILE_RANGE(simulation_physics, "Scene"); @@ -430,19 +433,22 @@ void EntityTreeRenderer::update(bool simulate) { scene->enqueueTransaction(transaction); } } - workload::Transaction spaceTransaction; - { // update proxies in the workload::Space - std::unique_lock lock(_spaceLock); - spaceTransaction.update(_spaceUpdates); - _spaceUpdates.clear(); - } { - std::vector staleProxies; - tree->swapStaleProxies(staleProxies); - spaceTransaction.remove(staleProxies); - { + PerformanceTimer perfTimer("workload::transaction"); + workload::Transaction spaceTransaction; + { // update proxies in the workload::Space std::unique_lock lock(_spaceLock); - _space->enqueueTransaction(spaceTransaction); + spaceTransaction.update(_spaceUpdates); + _spaceUpdates.clear(); + } + { + std::vector staleProxies; + tree->swapStaleProxies(staleProxies); + spaceTransaction.remove(staleProxies); + { + std::unique_lock lock(_spaceLock); + _space->enqueueTransaction(spaceTransaction); + } } } diff --git a/libraries/entities/src/EntitySimulation.cpp b/libraries/entities/src/EntitySimulation.cpp index d034ddedbe..420c91f078 100644 --- a/libraries/entities/src/EntitySimulation.cpp +++ b/libraries/entities/src/EntitySimulation.cpp @@ -31,6 +31,7 @@ void EntitySimulation::setEntityTree(EntityTreePointer tree) { void EntitySimulation::updateEntities() { QMutexLocker lock(&_mutex); uint64_t now = usecTimestampNow(); + PerformanceTimer perfTimer("EntitySimulation::updateEntities"); // these methods may accumulate entries in _entitiesToBeDeleted expireMortalEntities(now); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index bf5f7e9da1..244b5d0d7d 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1819,6 +1819,7 @@ void EntityTree::addToNeedsParentFixupList(EntityItemPointer entity) { void EntityTree::update(bool simulate) { PROFILE_RANGE(simulation_physics, "UpdateTree"); + PerformanceTimer perfTimer("UpdateTreen"); withWriteLock([&] { fixupNeedsParentFixups(); if (simulate && _simulation) { diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index fe10cc7714..29553dc68b 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -187,6 +187,7 @@ public: template void feedInput(const I& in) { _concept->editInput().template edit() = in; } + template void feedInput(int index, const S& inS) { (_concept->editInput().template editN(index)).template edit() = inS; } QConfigPointer& getConfiguration() const { return _concept->getConfiguration(); } void applyConfiguration() { return _concept->applyConfiguration(); } @@ -378,8 +379,33 @@ public: protected: }; -} +template +class Engine : public Task { +public: + using Context = JC; + using ContextPointer = std::shared_ptr; + using Config = TaskConfig; + using TaskType = Task; + using ConceptPointer = typename TaskType::ConceptPointer; + + Engine(ConceptPointer concept) : TaskType(concept) {} + ~Engine() = default; + + void reset(const ContextPointer& context) { + _context = context; + } + + void run() { + if (_context) { + TaskType::run(_context); + } + } + +protected: + ContextPointer _context; +}; +} #define Task_DeclareTypeAliases(ContextType) \ using JobConfig = task::JobConfig; \ @@ -387,6 +413,7 @@ protected: template using PersistentConfig = task::PersistentConfig; \ using Job = task::Job; \ using Task = task::Task; \ + using _Engine = task::Engine; \ using Varying = task::Varying; \ template < typename T0, typename T1 > using VaryingSet2 = task::VaryingSet2; \ template < typename T0, typename T1, typename T2 > using VaryingSet3 = task::VaryingSet3; \ diff --git a/libraries/workload/src/workload/Engine.cpp b/libraries/workload/src/workload/Engine.cpp index 0ecae55b72..b3568758ef 100644 --- a/libraries/workload/src/workload/Engine.cpp +++ b/libraries/workload/src/workload/Engine.cpp @@ -15,9 +15,5 @@ namespace workload { WorkloadContext::WorkloadContext(const SpacePointer& space) : task::JobContext(trace_workload()), _space(space) {} - - void Engine::reset(const WorkloadContextPointer& context) { - _context = context; - } } // namespace workload diff --git a/libraries/workload/src/workload/Engine.h b/libraries/workload/src/workload/Engine.h index d1628dfc61..0700080dc8 100644 --- a/libraries/workload/src/workload/Engine.h +++ b/libraries/workload/src/workload/Engine.h @@ -33,26 +33,7 @@ namespace workload { using WorkloadContextPointer = std::shared_ptr; Task_DeclareTypeAliases(WorkloadContext) - - class Engine { - public: - Engine(const std::shared_ptr& task) : _task(task), _context(nullptr) { - } - ~Engine() = default; - - void reset(const WorkloadContextPointer& context); - - void run() { if (_context) { _task->run(_context); } } - - std::shared_ptr getConfiguration() { return _task->getConfiguration(); } - - std::shared_ptr _task; - - protected: - - private: - WorkloadContextPointer _context; - }; + using Engine = _Engine; using EnginePointer = std::shared_ptr; } // namespace workload diff --git a/libraries/workload/src/workload/SpaceClassifier.cpp b/libraries/workload/src/workload/SpaceClassifier.cpp index 080210714f..418a510589 100644 --- a/libraries/workload/src/workload/SpaceClassifier.cpp +++ b/libraries/workload/src/workload/SpaceClassifier.cpp @@ -24,7 +24,7 @@ void PerformSpaceTransaction::run(const WorkloadContextPointer& context) { } void SpaceClassifierTask::build(JobModel& model, const Varying& in, Varying& out) { - model.addJob("setupViews", in); + model.addJob("assignSpaceViews", in); model.addJob("updateSpace"); const auto regionTrackerOut = model.addJob("regionTracker"); const auto regionChanges = regionTrackerOut.getN(1); diff --git a/libraries/workload/src/workload/ViewTask.cpp b/libraries/workload/src/workload/ViewTask.cpp index 5b056e9806..183f26ffbd 100644 --- a/libraries/workload/src/workload/ViewTask.cpp +++ b/libraries/workload/src/workload/ViewTask.cpp @@ -13,52 +13,59 @@ using namespace workload; +void AssignSpaceViews::run(const WorkloadContextPointer& renderContext, const Input& inputs) { + // Just do what it says + renderContext->_space->setViews(inputs); +} + void SetupViews::configure(const Config& config) { data = config.data; } -void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& inputs) { +void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& inputs, Output& outputs) { // If views are frozen don't use the input if (!data.freezeViews) { _views = inputs; } + auto& outViews = outputs; + outViews.clear(); + // Filter the first view centerer on the avatar head if needed - Views usedViews; if (_views.size() >= 2) { if (data.useAvatarView) { - usedViews.push_back(_views[0]); - usedViews.insert(usedViews.end(), _views.begin() + 2, _views.end()); + outViews.push_back(_views[0]); + outViews.insert(outViews.end(), _views.begin() + 2, _views.end()); } else { - usedViews.insert(usedViews.end(), _views.begin() + 1, _views.end()); + outViews.insert(outViews.end(), _views.begin() + 1, _views.end()); } } else { - usedViews = _views; + outViews = _views; } // Force frutum orientation horizontal if needed - if (usedViews.size() > 0 && data.forceViewHorizontal) { - usedViews[0].makeHorizontal(); + if (outViews.size() > 0 && data.forceViewHorizontal) { + outViews[0].makeHorizontal(); } // Force frutum orientation horizontal if needed - if (usedViews.size() > 0 && data.simulateSecondaryCamera) { - auto view = usedViews[0]; + if (outViews.size() > 0 && data.simulateSecondaryCamera) { + auto view = outViews[0]; auto secondaryDirectionFlat = glm::normalize(glm::vec3(view.direction.x, 0.0f, view.direction.z)); auto secondaryDirection = glm::normalize(glm::vec3(secondaryDirectionFlat.z, 0.0f, -secondaryDirectionFlat.x)); - view.origin += -30.0f * secondaryDirection; - view.direction = -secondaryDirectionFlat; + view.origin += -20.0f * secondaryDirection; + view.direction = -secondaryDirection; - usedViews.insert(usedViews.begin() + 1, view); + outViews.insert(outViews.begin() + 1, view); } // Update regions based on the current config - for (auto& v : usedViews) { + for (auto& v : outViews) { View::updateRegions(v, (float*) &data); } - // Views are setup, assign to the Space - renderContext->_space->setViews(usedViews); + // outViews is ready to be used } + diff --git a/libraries/workload/src/workload/ViewTask.h b/libraries/workload/src/workload/ViewTask.h index 251526b2d9..fd22d76715 100644 --- a/libraries/workload/src/workload/ViewTask.h +++ b/libraries/workload/src/workload/ViewTask.h @@ -78,16 +78,25 @@ namespace workload { public: using Config = SetupViewsConfig; using Input = Views; - using JobModel = Job::ModelI; + using Output = Views; + using JobModel = Job::ModelIO; void configure(const Config& config); - void run(const workload::WorkloadContextPointer& renderContext, const Input& inputs); + void run(const workload::WorkloadContextPointer& renderContext, const Input& inputs, Output& outputs); protected: Config::Data data; Views _views; }; + class AssignSpaceViews { + public: + using Input = Views; + using JobModel = Job::ModelI; + + void run(const workload::WorkloadContextPointer& renderContext, const Input& inputs); + }; + } // namespace workload #endif // hifi_workload_ViewTask_h \ No newline at end of file From 52a4224442399329f618e9f2fc3b8a6fcfab6935 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 18 Apr 2018 18:16:06 -0700 Subject: [PATCH 096/138] Arg get me the feedback working!!!! --- interface/src/workload/GameWorkload.cpp | 40 +++++++++++++++---- interface/src/workload/GameWorkload.h | 6 ++- .../render-utils/src/drawWorkloadProxy.slv | 4 ++ .../render-utils/src/drawWorkloadView.slv | 1 + libraries/workload/src/workload/View.cpp | 15 +++++-- libraries/workload/src/workload/View.h | 9 +++-- libraries/workload/src/workload/ViewTask.cpp | 2 +- 7 files changed, 60 insertions(+), 17 deletions(-) diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index e9f54f0663..877e3fb01c 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -14,13 +14,39 @@ #include #include "PhysicsBoundary.h" +#pragma optimize( "[optimization-list]", off ) +float wtf_adjust(float current, float timing) { + float error = (timing * 0.001f) - 2.0f; + if (error < 0.0f) { + current += 0.2f * (error) / 16.0f; + } else { + current += 0.1f * (error) / 16.0f; + } -void ControlViews::run(const workload::WorkloadContextPointer& renderContext, const Input& inputs, Output& outputs) { - const auto& inViews = inputs.getN<0>(); - const auto& inTimings = inputs[1]; - - outputs = inViews; + if (current > 100.0f) { + current = 100.0f; + } else if (current < 5.0f) { + current = 5.0f; + } + return current; } +void ControlViews::run(const workload::WorkloadContextPointer& runContext, const Input& inputs, Output& outputs) { + const auto& inViews = inputs.get0(); + const auto& inTimings = inputs.get1(); + auto& outViews = outputs; + outViews.clear(); + outViews = inViews; + + + int i = 0; + for (auto& outView : outViews) { + auto& current = regionBackFronts[workload::Region::R2].y; + current = wtf_adjust(current, inTimings[0]); + outView.regions[workload::Region::R2].y = current; + workload::View::updateRegionsFromBackFronts(outView); + } +} +#pragma optimize( "[optimization-list]", on ) class WorkloadEngineBuilder { public: @@ -35,9 +61,7 @@ public: const auto usedViews = model.addJob("setupViews", inViews); - ControlViews::Input controlViewsIn; - controlViewsIn[0] = usedViews; - controlViewsIn[1] = inTimings; + const auto controlViewsIn = ControlViews::Input(usedViews, inTimings).asVarying(); const auto fixedViews = model.addJob("controlViews", controlViewsIn); const auto regionTrackerOut = model.addJob("spaceClassifier", fixedViews); diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index 5472e5b99c..219383b974 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -58,8 +58,12 @@ public: using Output = workload::Views; using JobModel = workload::Job::ModelIO; + ControlViews() = default; + void configure(const Config& config) {} - void run(const workload::WorkloadContextPointer& renderContext, const Input& inputs, Output& outputs); + void run(const workload::WorkloadContextPointer& runContext, const Input& inputs, Output& outputs); + glm::vec2 regionBackFronts[workload::Region::NUM_VIEW_REGIONS + 1]; + }; #endif // hifi_GameWorkload_h diff --git a/libraries/render-utils/src/drawWorkloadProxy.slv b/libraries/render-utils/src/drawWorkloadProxy.slv index f2673ea9e4..08e30677e5 100644 --- a/libraries/render-utils/src/drawWorkloadProxy.slv +++ b/libraries/render-utils/src/drawWorkloadProxy.slv @@ -88,4 +88,8 @@ void main(void) { region = (0x000000FF & region); varColor = vec4(colorWheel(float(region) / 4.0), proxy.sphere.w); + + if (region == 4) { + gl_Position = vec4(0.0); + } } diff --git a/libraries/render-utils/src/drawWorkloadView.slv b/libraries/render-utils/src/drawWorkloadView.slv index 25e3303a78..f5497d250c 100644 --- a/libraries/render-utils/src/drawWorkloadView.slv +++ b/libraries/render-utils/src/drawWorkloadView.slv @@ -25,6 +25,7 @@ struct WorkloadView { vec4 direction_far; vec4 fov; vec4 origin; + vec4 backFront[2]; vec4 regions[3]; }; diff --git a/libraries/workload/src/workload/View.cpp b/libraries/workload/src/workload/View.cpp index 3f002da36a..8cb593d2a7 100644 --- a/libraries/workload/src/workload/View.cpp +++ b/libraries/workload/src/workload/View.cpp @@ -41,7 +41,7 @@ Sphere View::evalRegionSphere(const View& view, float originRadius, float maxDis return Sphere(view.origin + view.direction * center, radius); } -void View::updateRegions(View& view) { +void View::updateRegionsDefault(View& view) { std::vector config(Region::NUM_VIEW_REGIONS * 2, 0.0f); float refFar = 10.0f; @@ -52,11 +52,18 @@ void View::updateRegions(View& view) { config[i * 2 + 1] = refFar * weight; refFar *= 2.0f; } - updateRegions(view, config.data()); + updateRegionsFromBackFrontDistances(view, config.data()); } -void View::updateRegions(View& view, const float* configDistances) { +void View::updateRegionsFromBackFronts(View& view) { for (int i = 0; i < Region::NUM_VIEW_REGIONS; i++) { - view.regions[i] = evalRegionSphere(view, configDistances[i * 2], configDistances[i * 2 + 1]); + view.regions[i] = evalRegionSphere(view, view.regionBackFronts[i].x, view.regionBackFronts[i].y); } } + +void View::updateRegionsFromBackFrontDistances(View& view, const float* configDistances) { + for (int i = 0; i < Region::NUM_VIEW_REGIONS; i++) { + view.regionBackFronts[i] = glm::vec2(configDistances[i * 2], configDistances[i * 2 + 1]); + } + updateRegionsFromBackFronts(view); +} diff --git a/libraries/workload/src/workload/View.h b/libraries/workload/src/workload/View.h index 430ac3a568..fa60aaef29 100644 --- a/libraries/workload/src/workload/View.h +++ b/libraries/workload/src/workload/View.h @@ -47,6 +47,9 @@ public: // Origin radius float originRadius{ 0.5f }; + // N regions distances + glm::vec2 regionBackFronts[Region::NUM_VIEW_REGIONS + 1]; + // N regions spheres Sphere regions[Region::NUM_VIEW_REGIONS]; @@ -59,9 +62,9 @@ public: static View evalFromFrustum(const ViewFrustum& frustum, const glm::vec3& offset = glm::vec3()); static Sphere evalRegionSphere(const View& view, float originRadius, float maxDistance); - static void updateRegions(View& view); - - static void updateRegions(View& view, const float* configDistances); + static void updateRegionsDefault(View& view); + static void updateRegionsFromBackFronts(View& view); + static void updateRegionsFromBackFrontDistances(View& view, const float* configDistances); }; using Views = std::vector; diff --git a/libraries/workload/src/workload/ViewTask.cpp b/libraries/workload/src/workload/ViewTask.cpp index 183f26ffbd..672078fb9a 100644 --- a/libraries/workload/src/workload/ViewTask.cpp +++ b/libraries/workload/src/workload/ViewTask.cpp @@ -62,7 +62,7 @@ void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& i // Update regions based on the current config for (auto& v : outViews) { - View::updateRegions(v, (float*) &data); + View::updateRegionsFromBackFrontDistances(v, (float*) &data); } // outViews is ready to be used From 9b3d546dade5b73edaa513db37146cb4ae21a558 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 19 Apr 2018 09:35:57 -0700 Subject: [PATCH 097/138] Exposing the on off to use the distance configs --- interface/src/workload/GameWorkload.cpp | 4 ++-- libraries/workload/src/workload/ViewTask.cpp | 6 +++++- libraries/workload/src/workload/ViewTask.h | 6 ++++++ .../developer/utilities/workload/workloadInspector.qml | 8 ++++++++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 877e3fb01c..b2f4001afa 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -41,8 +41,8 @@ void ControlViews::run(const workload::WorkloadContextPointer& runContext, const int i = 0; for (auto& outView : outViews) { auto& current = regionBackFronts[workload::Region::R2].y; - current = wtf_adjust(current, inTimings[0]); - outView.regions[workload::Region::R2].y = current; + auto newCurrent = wtf_adjust(current, inTimings[0]); + outView.regions[workload::Region::R2].y = newCurrent; workload::View::updateRegionsFromBackFronts(outView); } } diff --git a/libraries/workload/src/workload/ViewTask.cpp b/libraries/workload/src/workload/ViewTask.cpp index 672078fb9a..d817ac6fdd 100644 --- a/libraries/workload/src/workload/ViewTask.cpp +++ b/libraries/workload/src/workload/ViewTask.cpp @@ -62,7 +62,11 @@ void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& i // Update regions based on the current config for (auto& v : outViews) { - View::updateRegionsFromBackFrontDistances(v, (float*) &data); + if (data.applyViewRanges) { + View::updateRegionsFromBackFrontDistances(v, (float*) &data); + } else { + View::updateRegionsFromBackFronts(v); + } } // outViews is ready to be used diff --git a/libraries/workload/src/workload/ViewTask.h b/libraries/workload/src/workload/ViewTask.h index fd22d76715..25fad29f20 100644 --- a/libraries/workload/src/workload/ViewTask.h +++ b/libraries/workload/src/workload/ViewTask.h @@ -27,6 +27,7 @@ namespace workload { Q_PROPERTY(bool forceViewHorizontal READ forceViewHorizontal WRITE setForceViewHorizontal NOTIFY dirty) Q_PROPERTY(bool simulateSecondaryCamera READ simulateSecondaryCamera WRITE setSimulateSecondaryCamera NOTIFY dirty) + Q_PROPERTY(bool applyViewRanges READ applyViewRanges WRITE setApplyViewRanges NOTIFY dirty) public: @@ -54,6 +55,9 @@ namespace workload { bool simulateSecondaryCamera() const { return data.simulateSecondaryCamera; } void setSimulateSecondaryCamera(bool use) { data.simulateSecondaryCamera = use; emit dirty(); } + bool applyViewRanges() const { return data.applyViewRanges; } + void setApplyViewRanges(bool use) { data.applyViewRanges = use; emit dirty(); } + struct Data { float r1Back { 2.0f }; float r1Front { 10.0f }; @@ -68,6 +72,8 @@ namespace workload { bool useAvatarView{ false }; bool forceViewHorizontal{ false }; bool simulateSecondaryCamera{ false }; + bool applyViewRanges{ true }; + } data; signals: diff --git a/scripts/developer/utilities/workload/workloadInspector.qml b/scripts/developer/utilities/workload/workloadInspector.qml index 2dc4ad0491..ffe80f35f4 100644 --- a/scripts/developer/utilities/workload/workloadInspector.qml +++ b/scripts/developer/utilities/workload/workloadInspector.qml @@ -110,6 +110,14 @@ Rectangle { } } + Separator {} + HifiControls.CheckBox { + boxSize: 20 + text: "Apply Front Back Ranges" + checked: Workload.getConfig("setupViews")["applyViewRanges"] + onCheckedChanged: { Workload.getConfig("setupViews")["applyViewRanges"] = checked; } + } + RowLayout { anchors.left: parent.left anchors.right: parent.right From 9b1a8874697dd512f7d09132d5c483b37b5ee526 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 19 Apr 2018 17:43:14 -0700 Subject: [PATCH 098/138] Starting to move dynamically yeah --- interface/src/workload/GameWorkload.cpp | 51 ++++++++++++++----- interface/src/workload/GameWorkload.h | 18 ++++++- .../physics/src/PhysicalEntitySimulation.cpp | 23 +++++---- libraries/workload/src/workload/ViewTask.cpp | 6 +-- libraries/workload/src/workload/ViewTask.h | 7 +-- .../utilities/workload/workloadInspector.qml | 6 +-- 6 files changed, 73 insertions(+), 38 deletions(-) diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index b2f4001afa..22f41669dc 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -15,8 +15,32 @@ #include "PhysicsBoundary.h" #pragma optimize( "[optimization-list]", off ) + +ControlViews::ControlViews() { + regionBackFronts[0] = glm::vec2(2.0f, 10.0f); + regionBackFronts[1] = glm::vec2(5.0f, 30.0f); + regionBackFronts[2] = glm::vec2(10.0f, 100.0f); + +} + +void ControlViews::configure(const Config& config) { + _data = config.data; +} + +void ControlViews::run(const workload::WorkloadContextPointer& runContext, const Input& inputs, Output& outputs) { + const auto& inViews = inputs.get0(); + const auto& inTimings = inputs.get1(); + auto& outViews = outputs; + outViews.clear(); + outViews = inViews; + + if (_data.regulateViewRanges) { + regulateViews(outViews, inTimings); + } +} + float wtf_adjust(float current, float timing) { - float error = (timing * 0.001f) - 2.0f; + float error = -((timing * 0.001f) - 2.0f); if (error < 0.0f) { current += 0.2f * (error) / 16.0f; } else { @@ -30,22 +54,25 @@ float wtf_adjust(float current, float timing) { } return current; } -void ControlViews::run(const workload::WorkloadContextPointer& runContext, const Input& inputs, Output& outputs) { - const auto& inViews = inputs.get0(); - const auto& inTimings = inputs.get1(); - auto& outViews = outputs; - outViews.clear(); - outViews = inViews; - - + +void ControlViews::regulateViews(workload::Views& outViews, const workload::Timings& timings) { + + for (auto& outView : outViews) { + for (int r = 0; r < workload::Region::NUM_VIEW_REGIONS; r++) { + outView.regionBackFronts[r] = regionBackFronts[r]; + } + } + int i = 0; for (auto& outView : outViews) { - auto& current = regionBackFronts[workload::Region::R2].y; - auto newCurrent = wtf_adjust(current, inTimings[0]); - outView.regions[workload::Region::R2].y = newCurrent; + auto current = regionBackFronts[workload::Region::R2].y; + auto newCurrent = wtf_adjust(current, timings[0]); + regionBackFronts[workload::Region::R2].y = newCurrent; + outView.regionBackFronts[workload::Region::R2].y = newCurrent; workload::View::updateRegionsFromBackFronts(outView); } } + #pragma optimize( "[optimization-list]", on ) class WorkloadEngineBuilder { diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index 219383b974..7dffd6ac58 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -45,8 +45,17 @@ public: class ControlViewsConfig : public workload::Job::Config { Q_OBJECT + Q_PROPERTY(bool regulateViewRanges READ regulateViewRanges WRITE setRegulateViewRanges NOTIFY dirty) + public: + bool regulateViewRanges() const { return data.regulateViewRanges; } + void setRegulateViewRanges(bool use) { data.regulateViewRanges = use; emit dirty(); } + + struct Data { + bool regulateViewRanges{ true }; + + } data; signals: void dirty(); }; @@ -58,12 +67,17 @@ public: using Output = workload::Views; using JobModel = workload::Job::ModelIO; - ControlViews() = default; + ControlViews(); - void configure(const Config& config) {} + void configure(const Config& config); void run(const workload::WorkloadContextPointer& runContext, const Input& inputs, Output& outputs); glm::vec2 regionBackFronts[workload::Region::NUM_VIEW_REGIONS + 1]; + + void regulateViews(workload::Views& views, const workload::Timings& timings); + +protected: + Config::Data _data; }; #endif // hifi_GameWorkload_h diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index 27bbfbe0e3..e91d7cfdc6 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -190,18 +190,21 @@ const VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToRemoveFromPhys for (auto entity: _entitiesToRemoveFromPhysics) { EntityMotionState* motionState = static_cast(entity->getPhysicsInfo()); assert(motionState); + // TODO CLEan this, just a n extra check to avoid the crash that shouldn;t happen + if (motionState) { - _entitiesToAddToPhysics.remove(entity); - if (entity->isDead() && entity->getElement()) { - _deadEntities.insert(entity); + _entitiesToAddToPhysics.remove(entity); + if (entity->isDead() && entity->getElement()) { + _deadEntities.insert(entity); + } + + _incomingChanges.remove(motionState); + removeOwnershipData(motionState); + _physicalObjects.remove(motionState); + + // remember this motionState and delete it later (after removing its RigidBody from the PhysicsEngine) + _objectsToDelete.push_back(motionState); } - - _incomingChanges.remove(motionState); - removeOwnershipData(motionState); - _physicalObjects.remove(motionState); - - // remember this motionState and delete it later (after removing its RigidBody from the PhysicsEngine) - _objectsToDelete.push_back(motionState); } _entitiesToRemoveFromPhysics.clear(); return _objectsToDelete; diff --git a/libraries/workload/src/workload/ViewTask.cpp b/libraries/workload/src/workload/ViewTask.cpp index d817ac6fdd..672078fb9a 100644 --- a/libraries/workload/src/workload/ViewTask.cpp +++ b/libraries/workload/src/workload/ViewTask.cpp @@ -62,11 +62,7 @@ void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& i // Update regions based on the current config for (auto& v : outViews) { - if (data.applyViewRanges) { - View::updateRegionsFromBackFrontDistances(v, (float*) &data); - } else { - View::updateRegionsFromBackFronts(v); - } + View::updateRegionsFromBackFrontDistances(v, (float*) &data); } // outViews is ready to be used diff --git a/libraries/workload/src/workload/ViewTask.h b/libraries/workload/src/workload/ViewTask.h index 25fad29f20..dd1b60890c 100644 --- a/libraries/workload/src/workload/ViewTask.h +++ b/libraries/workload/src/workload/ViewTask.h @@ -27,7 +27,7 @@ namespace workload { Q_PROPERTY(bool forceViewHorizontal READ forceViewHorizontal WRITE setForceViewHorizontal NOTIFY dirty) Q_PROPERTY(bool simulateSecondaryCamera READ simulateSecondaryCamera WRITE setSimulateSecondaryCamera NOTIFY dirty) - Q_PROPERTY(bool applyViewRanges READ applyViewRanges WRITE setApplyViewRanges NOTIFY dirty) + public: @@ -55,9 +55,6 @@ namespace workload { bool simulateSecondaryCamera() const { return data.simulateSecondaryCamera; } void setSimulateSecondaryCamera(bool use) { data.simulateSecondaryCamera = use; emit dirty(); } - bool applyViewRanges() const { return data.applyViewRanges; } - void setApplyViewRanges(bool use) { data.applyViewRanges = use; emit dirty(); } - struct Data { float r1Back { 2.0f }; float r1Front { 10.0f }; @@ -72,8 +69,6 @@ namespace workload { bool useAvatarView{ false }; bool forceViewHorizontal{ false }; bool simulateSecondaryCamera{ false }; - bool applyViewRanges{ true }; - } data; signals: diff --git a/scripts/developer/utilities/workload/workloadInspector.qml b/scripts/developer/utilities/workload/workloadInspector.qml index ffe80f35f4..885d8ddb66 100644 --- a/scripts/developer/utilities/workload/workloadInspector.qml +++ b/scripts/developer/utilities/workload/workloadInspector.qml @@ -113,9 +113,9 @@ Rectangle { Separator {} HifiControls.CheckBox { boxSize: 20 - text: "Apply Front Back Ranges" - checked: Workload.getConfig("setupViews")["applyViewRanges"] - onCheckedChanged: { Workload.getConfig("setupViews")["applyViewRanges"] = checked; } + text: "Regulate View Ranges" + checked: Workload.getConfig("controlViews")["regulateViewRanges"] + onCheckedChanged: { Workload.getConfig("controlViews")["regulateViewRanges"] = checked; } } RowLayout { From cfaf75e196fb22407563e96eb7b61f7561447f7e Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 19 Apr 2018 23:28:32 -0700 Subject: [PATCH 099/138] Using the std::chrono to measure the physics time --- interface/src/Application.cpp | 10 ++++++++-- interface/src/workload/GameWorkload.cpp | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 65f7badd8c..59cb880ccb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4295,8 +4295,8 @@ void Application::idle() { } { - workload::Timings timings(1, PerformanceTimer::getTimerRecord("/idle/update/simulation").getAverage()); - _gameWorkload.updateSimulationTimings(timings); + // workload::Timings timings(1, PerformanceTimer::getTimerRecord("/idle/update/simulation").getAverage()); + // _gameWorkload.updateSimulationTimings(timings); _gameWorkload.updateViews(_viewFrustum, getMyAvatar()->getHeadPosition()); _gameWorkload._engine->run(); } @@ -5277,7 +5277,9 @@ void Application::update(float deltaTime) { { PROFILE_RANGE(simulation_physics, "Simulation"); PerformanceTimer perfTimer("simulation"); + if (_physicsEnabled) { + auto t0 = std::chrono::high_resolution_clock::now(); { PROFILE_RANGE(simulation_physics, "PrePhysics"); PerformanceTimer perfTimer("prePhysics)"); @@ -5365,6 +5367,10 @@ void Application::update(float deltaTime) { // NOTE: the PhysicsEngine stats are written to stdout NOT to Qt log framework _physicsEngine->dumpStatsIfNecessary(); } + auto t1 = std::chrono::high_resolution_clock::now(); + workload::Timings timings(1); + timings[0] = float(std::chrono::nanoseconds(t1 - t0).count() * 0.000001); + _gameWorkload.updateSimulationTimings(timings); if (!_aboutToQuit) { // NOTE: the getEntities()->update() call below will wait for lock diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 22f41669dc..332cc9fb5c 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -34,13 +34,13 @@ void ControlViews::run(const workload::WorkloadContextPointer& runContext, const outViews.clear(); outViews = inViews; - if (_data.regulateViewRanges) { + if (_data.regulateViewRanges && inTimings.size()) { regulateViews(outViews, inTimings); } } float wtf_adjust(float current, float timing) { - float error = -((timing * 0.001f) - 2.0f); + float error = -((timing) - 2.0f); if (error < 0.0f) { current += 0.2f * (error) / 16.0f; } else { From 3858e7b43c88d12976b3ef63950e5761b8a7d69a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 20 Apr 2018 15:08:51 -0700 Subject: [PATCH 100/138] update workload::Engine to agree with new API --- libraries/workload/src/workload/Engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/workload/src/workload/Engine.cpp b/libraries/workload/src/workload/Engine.cpp index 0ede4a6d2d..fb02b7f826 100644 --- a/libraries/workload/src/workload/Engine.cpp +++ b/libraries/workload/src/workload/Engine.cpp @@ -35,7 +35,7 @@ namespace workload { } }; - Engine::Engine() : Task("Engine", EngineBuilder::JobModel::create()), + Engine::Engine() : Task(EngineBuilder::JobModel::create("Engine")), _context(nullptr) { } From b554aec317fa3c499c29e0b3e6bc6f6c99a46c69 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 20 Apr 2018 17:53:24 -0700 Subject: [PATCH 101/138] Trying more drastic changes and learnign to use std::chrono the right way --- interface/src/Application.cpp | 11 ++++-- interface/src/workload/GameWorkload.cpp | 36 ++++++++++--------- interface/src/workload/GameWorkload.h | 18 +++++++++- .../physics/src/PhysicalEntitySimulation.cpp | 8 +++-- libraries/workload/src/workload/Space.h | 2 +- 5 files changed, 50 insertions(+), 25 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e8a91fb08b..9a51b102dc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5369,15 +5369,20 @@ void Application::update(float deltaTime) { _physicsEngine->dumpStatsIfNecessary(); } auto t1 = std::chrono::high_resolution_clock::now(); - workload::Timings timings(1); - timings[0] = float(std::chrono::nanoseconds(t1 - t0).count() * 0.000001); - _gameWorkload.updateSimulationTimings(timings); if (!_aboutToQuit) { // NOTE: the getEntities()->update() call below will wait for lock // and will provide non-physical entity motion getEntities()->update(true); // update the models... } + + auto t2 = std::chrono::high_resolution_clock::now(); + + workload::Timings timings(2); + timings[0] = (t1 - t0); + timings[1] = (t2 - t1); + _gameWorkload.updateSimulationTimings(timings); + } } } else { diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 332cc9fb5c..16a7098aa3 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -39,20 +39,18 @@ void ControlViews::run(const workload::WorkloadContextPointer& runContext, const } } -float wtf_adjust(float current, float timing) { - float error = -((timing) - 2.0f); - if (error < 0.0f) { - current += 0.2f * (error) / 16.0f; - } else { - current += 0.1f * (error) / 16.0f; - } +glm::vec2 Regulator::run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current) { + glm::vec2 next = current; - if (current > 100.0f) { - current = 100.0f; - } else if (current < 5.0f) { - current = 5.0f; - } - return current; + // Regulate next value based on current moving toward the goal budget + float error_ms = std::chrono::duration(_budget - measured).count(); + float coef = error_ms / std::chrono::duration(regulationDuration).count(); + next += coef * (error_ms < 0.0 ? _speedDown : _speedUp); + + // Clamp to min max + next = glm::clamp(next, _minRange, _maxRange); + + return next; } void ControlViews::regulateViews(workload::Views& outViews, const workload::Timings& timings) { @@ -63,12 +61,16 @@ void ControlViews::regulateViews(workload::Views& outViews, const workload::Timi } } + auto loopDuration = std::chrono::nanoseconds{ std::chrono::milliseconds(16) }; + regionBackFronts[workload::Region::R2] = regionRegulators[workload::Region::R2].run(loopDuration, timings[0], regionBackFronts[workload::Region::R2]); + regionBackFronts[workload::Region::R3] = regionRegulators[workload::Region::R3].run(loopDuration, timings[1], regionBackFronts[workload::Region::R3]); + int i = 0; for (auto& outView : outViews) { - auto current = regionBackFronts[workload::Region::R2].y; - auto newCurrent = wtf_adjust(current, timings[0]); - regionBackFronts[workload::Region::R2].y = newCurrent; - outView.regionBackFronts[workload::Region::R2].y = newCurrent; + outView.regionBackFronts[workload::Region::R1] = regionBackFronts[workload::Region::R1]; + outView.regionBackFronts[workload::Region::R2] = regionBackFronts[workload::Region::R2]; + outView.regionBackFronts[workload::Region::R3] = regionBackFronts[workload::Region::R3]; + workload::View::updateRegionsFromBackFronts(outView); } } diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index 7dffd6ac58..e3c050afc9 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -60,6 +60,21 @@ signals: void dirty(); }; +struct Regulator { + using Timing_ns = std::chrono::nanoseconds; + Timing_ns _budget{ std::chrono::milliseconds(2) }; + glm::vec2 _minRange{ 2.0f, 5.0f }; + glm::vec2 _maxRange{ 50.0f, 100.0f }; + + glm::vec2 _speedDown{ 0.2f }; + glm::vec2 _speedUp{ 0.1f }; + + + Regulator() {} + + glm::vec2 run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current); +}; + class ControlViews { public: using Config = ControlViewsConfig; @@ -71,8 +86,9 @@ public: void configure(const Config& config); void run(const workload::WorkloadContextPointer& runContext, const Input& inputs, Output& outputs); - glm::vec2 regionBackFronts[workload::Region::NUM_VIEW_REGIONS + 1]; + std::array regionBackFronts; + std::array regionRegulators; void regulateViews(workload::Views& views, const workload::Timings& timings); diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index e91d7cfdc6..22737afe30 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -50,12 +50,13 @@ void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) { assert(!entity->isDead()); uint8_t region = _space->getRegion(entity->getSpaceIndex()); bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical(); + bool canBeKinematic = region <= workload::Region::R3; if (shouldBePhysical) { EntityMotionState* motionState = static_cast(entity->getPhysicsInfo()); if (!motionState) { _entitiesToAddToPhysics.insert(entity); } - } else if (entity->isMovingRelativeToParent()) { + } else if (canBeKinematic && entity->isMovingRelativeToParent()) { _simpleKinematicEntities.insert(entity); } } @@ -124,6 +125,7 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { EntityMotionState* motionState = static_cast(entity->getPhysicsInfo()); uint8_t region = _space->getRegion(entity->getSpaceIndex()); bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical(); + bool canBeKinematic = region <= workload::Region::R3; if (motionState) { if (!shouldBePhysical) { // the entity should be removed from the physical simulation @@ -131,7 +133,7 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { _physicalObjects.remove(motionState); removeOwnershipData(motionState); _entitiesToRemoveFromPhysics.insert(entity); - if (entity->isMovingRelativeToParent()) { + if (canBeKinematic && entity->isMovingRelativeToParent()) { _simpleKinematicEntities.insert(entity); } } else { @@ -142,7 +144,7 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { // Perhaps it's shape has changed and it can now be added? _entitiesToAddToPhysics.insert(entity); _simpleKinematicEntities.remove(entity); // just in case it's non-physical-kinematic - } else if (entity->isMovingRelativeToParent()) { + } else if (canBeKinematic && entity->isMovingRelativeToParent()) { _simpleKinematicEntities.insert(entity); } else { _simpleKinematicEntities.remove(entity); // just in case it's non-physical-kinematic diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index ab7dd02134..960c905f7c 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -70,7 +70,7 @@ private: using SpacePointer = std::shared_ptr; using Changes = std::vector; using IndexVectors = std::vector; -using Timings = std::vector; +using Timings = std::vector; } // namespace workload From ec569b0e51c5e69e0cf5f33e61fcdf85f41f0df1 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sat, 21 Apr 2018 12:05:27 -0700 Subject: [PATCH 102/138] adjusting the bounding box for debug rendering --- interface/src/workload/GameWorkloadRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index b6d1045e63..9fdbe3b44d 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -66,7 +66,7 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, if (!render::Item::isValidID(_spaceRenderItemID)) { _spaceRenderItemID = scene->allocateID(); auto renderItem = std::make_shared(); - renderItem->editBound().setBox(glm::vec3(-16000.0f), 16000.0f); + renderItem->editBound().setBox(glm::vec3(-16000.0f), 32000.0f); renderItem->setAllProxies(proxies); transaction.resetItem(_spaceRenderItemID, std::make_shared(renderItem)); } From 97934fe563970abfca700d4fb2a1985e780eef79 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 23 Apr 2018 00:07:00 -0700 Subject: [PATCH 103/138] Adjusting the regulators and moving task to use chrono nad interesting tests --- interface/src/workload/GameWorkload.cpp | 11 ++-- interface/src/workload/GameWorkload.h | 2 + .../render-utils/src/SubsurfaceScattering.h | 2 +- libraries/task/src/task/Config.h | 4 +- libraries/task/src/task/Task.h | 7 +- .../utilities/workload/test_physics_scene.js | 65 ++++++++++++------- 6 files changed, 60 insertions(+), 31 deletions(-) diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 16a7098aa3..d8b7fb5819 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -17,10 +17,12 @@ #pragma optimize( "[optimization-list]", off ) ControlViews::ControlViews() { - regionBackFronts[0] = glm::vec2(2.0f, 10.0f); - regionBackFronts[1] = glm::vec2(5.0f, 30.0f); - regionBackFronts[2] = glm::vec2(10.0f, 100.0f); - + regionBackFronts[0] = glm::vec2(1.0f, 3.0f); + regionBackFronts[1] = glm::vec2(2.0f, 10.0f); + regionBackFronts[2] = glm::vec2(4.0f, 20.0f); + regionRegulators[0] = Regulator(std::chrono::milliseconds(2), regionBackFronts[0], 5.0f * regionBackFronts[0], glm::vec2(0.3f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); + regionRegulators[1] = Regulator(std::chrono::milliseconds(2), regionBackFronts[1], 5.0f * regionBackFronts[1], glm::vec2(0.3f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); + regionRegulators[2] = Regulator(std::chrono::milliseconds(2), regionBackFronts[2], 5.0f * regionBackFronts[2], glm::vec2(0.3f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); } void ControlViews::configure(const Config& config) { @@ -62,6 +64,7 @@ void ControlViews::regulateViews(workload::Views& outViews, const workload::Timi } auto loopDuration = std::chrono::nanoseconds{ std::chrono::milliseconds(16) }; + regionBackFronts[workload::Region::R1] = regionRegulators[workload::Region::R1].run(loopDuration, timings[0], regionBackFronts[workload::Region::R1]); regionBackFronts[workload::Region::R2] = regionRegulators[workload::Region::R2].run(loopDuration, timings[0], regionBackFronts[workload::Region::R2]); regionBackFronts[workload::Region::R3] = regionRegulators[workload::Region::R3].run(loopDuration, timings[1], regionBackFronts[workload::Region::R3]); diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index e3c050afc9..6e75491824 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -71,6 +71,8 @@ struct Regulator { Regulator() {} + Regulator(const Timing_ns& budget_ns, const glm::vec2& minRange, const glm::vec2& maxRange, const glm::vec2& speedDown, const glm::vec2& speedUp) : + _budget(budget_ns), _minRange(minRange), _maxRange(maxRange), _speedDown(speedDown), _speedUp(speedUp) {} glm::vec2 run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current); }; diff --git a/libraries/render-utils/src/SubsurfaceScattering.h b/libraries/render-utils/src/SubsurfaceScattering.h index 30021fae40..780ce34d7f 100644 --- a/libraries/render-utils/src/SubsurfaceScattering.h +++ b/libraries/render-utils/src/SubsurfaceScattering.h @@ -149,7 +149,7 @@ class DebugSubsurfaceScatteringConfig : public render::Job::Config { Q_PROPERTY(bool showCursorPixel MEMBER showCursorPixel NOTIFY dirty) Q_PROPERTY(glm::vec2 debugCursorTexcoord MEMBER debugCursorTexcoord NOTIFY dirty) public: - DebugSubsurfaceScatteringConfig() : render::Job::Config(true) {} + DebugSubsurfaceScatteringConfig() : render::Job::Config(false) {} bool showProfile{ false }; bool showLUT{ false }; diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index eaa87f53af..b36f9fb40d 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -12,6 +12,8 @@ #ifndef hifi_task_Config_h #define hifi_task_Config_h +#include + #include #include #include @@ -112,7 +114,7 @@ public: // Running Time measurement // The new stats signal is emitted once per run time of a job when stats (cpu runtime) are updated - void setCPURunTime(double mstime) { _msCPURunTime = mstime; emit newStats(); } + void setCPURunTime(const std::chrono::nanoseconds& runtime) { _msCPURunTime = runtime.count() / 1000000.0; emit newStats(); } double getCPURunTime() const { return _msCPURunTime; } Q_INVOKABLE virtual bool isTask() const { return false; } diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index 29553dc68b..b528802947 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -84,7 +84,7 @@ public: virtual QConfigPointer& getConfiguration() { return _config; } virtual void applyConfiguration() = 0; - void setCPURunTime(double mstime) { std::static_pointer_cast(_config)->setCPURunTime(mstime); } + void setCPURunTime(const std::chrono::nanoseconds& runtime) { std::static_pointer_cast(_config)->setCPURunTime(runtime); } QConfigPointer _config; protected: @@ -208,11 +208,12 @@ public: PerformanceTimer perfTimer(getName().c_str()); // NOTE: rather than use the PROFILE_RANGE macro, we create a Duration manually Duration profileRange(jobContext->profileCategory, ("run::" + getName()).c_str()); - auto start = usecTimestampNow(); + + auto startTime = std::chrono::high_resolution_clock::now(); _concept->run(jobContext); - _concept->setCPURunTime((double)(usecTimestampNow() - start) / 1000.0); + _concept->setCPURunTime((std::chrono::high_resolution_clock::now() - startTime)); } protected: diff --git a/scripts/developer/utilities/workload/test_physics_scene.js b/scripts/developer/utilities/workload/test_physics_scene.js index 8a1b326b1e..bbb9f3d7ea 100644 --- a/scripts/developer/utilities/workload/test_physics_scene.js +++ b/scripts/developer/utilities/workload/test_physics_scene.js @@ -3,7 +3,7 @@ var GRID_WORLD_SIZE = 100.0; var GRID_WORLD_MARGIN = 5.0; var GRID_WORLD_RESOLUTION = 30.0; - var GRID_WORLD_DROP_HEIGHT = 5.0; + var GRID_WORLD_DROP_HEIGHT = 4.0; var GRID_SIZE = GRID_WORLD_RESOLUTION; var GRID_HALFSIZE = GRID_SIZE *0.5; @@ -34,6 +34,7 @@ } var OBJECT_DIM = { x: 0.5, y: 0.5, z: 0.5}; + var CONE_DIM = { x: 0.3104, y: 0.3336, z: 0.3104}; var OBJECT_SPIN = { x: 0.5, y: 0.5, z: 0.5}; var shapeTypes = [ @@ -53,29 +54,49 @@ function getTileColor(a, b, c) { } function addObject(a, b, c, lifetime) { - var center = getStagePosOriAt(a, b, c).pos; - - + var center = getStagePosOriAt(a, b, c).pos; + var offset = (Math.abs(a) + (Math.abs(b) % 2)) % 2; + var makePrim = (offset > 0 ? true : false) ; + if (makePrim) { + return (Entities.addEntity({ + type: "Shape", + shape: "Sphere", + name: "object-" + a + b + c, + color: getTileColor(a, b, c), + position: center, + rotation: stageOrientation, + dimensions: OBJECT_DIM, + lifetime: (lifetime === undefined) ? DEFAULT_LIFETIME : lifetime, + shapeType:shapeTypes[2], + dynamic: true, + gravity:{"x":0,"y":-9.8,"z":0}, + velocity:{"x":0,"y":0.02,"z":0}, + angularVelocity:OBJECT_SPIN, + restitution:0.70, + friction:0.01, + damping:0.001, - return (Entities.addEntity({ - type: "Shape", - shape: "Sphere", - name: "Backdrop", - color: getTileColor(a, b, c), - position: center, - rotation: stageOrientation, - dimensions: OBJECT_DIM, - lifetime: (lifetime === undefined) ? DEFAULT_LIFETIME : lifetime, - shapeType:shapeTypes[2], - dynamic: true, - gravity:{"x":0,"y":-9.8,"z":0}, - velocity:{"x":0,"y":0.02,"z":0}, - angularVelocity:OBJECT_SPIN, - restitution:0.70, - friction:0.01, - damping:0.001, + })); + } else { + return (Entities.addEntity({ + type: "Model", + name: "object-" + a + b + c, + position: center, + rotation: stageOrientation, + dimensions: OBJECT_DIM, + lifetime: (lifetime === undefined) ? DEFAULT_LIFETIME : lifetime, + modelURL: "https://hifi-content.s3.amazonaws.com/jimi/props/cones/trafficCone.fbx", + shapeType:shapeTypes[4], + dynamic: true, + gravity:{"x":0,"y":-9.8,"z":0}, + velocity:{"x":0,"y":0.02,"z":0}, + angularVelocity:OBJECT_SPIN, + restitution:0.70, + friction:0.01, + damping:0.01, - })); + })); + } } function addObjectGrid(backdrop, lifetime) { From f686ef1f25d01ab9675475c4aa9d948c05e8d225 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 23 Apr 2018 18:02:09 -0700 Subject: [PATCH 104/138] Exposing more uniforms to ui for refining the controller --- interface/src/workload/GameWorkload.cpp | 10 ++--- interface/src/workload/GameWorkload.h | 60 +++++++++++++++++++++++++ libraries/entities/src/EntityItem.cpp | 6 +-- 3 files changed, 68 insertions(+), 8 deletions(-) diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index d8b7fb5819..70b17485c2 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -18,11 +18,11 @@ ControlViews::ControlViews() { regionBackFronts[0] = glm::vec2(1.0f, 3.0f); - regionBackFronts[1] = glm::vec2(2.0f, 10.0f); - regionBackFronts[2] = glm::vec2(4.0f, 20.0f); - regionRegulators[0] = Regulator(std::chrono::milliseconds(2), regionBackFronts[0], 5.0f * regionBackFronts[0], glm::vec2(0.3f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); - regionRegulators[1] = Regulator(std::chrono::milliseconds(2), regionBackFronts[1], 5.0f * regionBackFronts[1], glm::vec2(0.3f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); - regionRegulators[2] = Regulator(std::chrono::milliseconds(2), regionBackFronts[2], 5.0f * regionBackFronts[2], glm::vec2(0.3f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); + regionBackFronts[1] = glm::vec2(1.0f, 5.0f); + regionBackFronts[2] = glm::vec2(1.0f, 10.0f); + regionRegulators[0] = Regulator(std::chrono::milliseconds(2), regionBackFronts[0], 5.0f * regionBackFronts[0], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); + regionRegulators[1] = Regulator(std::chrono::milliseconds(2), regionBackFronts[1], 8.0f * regionBackFronts[1], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); + regionRegulators[2] = Regulator(std::chrono::milliseconds(2), regionBackFronts[2], 10.0f * regionBackFronts[2], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); } void ControlViews::configure(const Config& config) { diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index 6e75491824..702e0029d0 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -47,12 +47,72 @@ class ControlViewsConfig : public workload::Job::Config { Q_OBJECT Q_PROPERTY(bool regulateViewRanges READ regulateViewRanges WRITE setRegulateViewRanges NOTIFY dirty) + Q_PROPERTY(float r1Timing READ r1Timing) + Q_PROPERTY(float r2Timing READ r2Timing) + Q_PROPERTY(float r3Timing READ r3Timing) + + Q_PROPERTY(float r1RangeBack READ r1RangeBack) + Q_PROPERTY(float r2RangeBack READ r2RangeBack) + Q_PROPERTY(float r3RangeBack READ r3RangeBack) + + Q_PROPERTY(float r1RangeFront READ r1RangeFront) + Q_PROPERTY(float r2RangeFront READ r2RangeFront) + Q_PROPERTY(float r3RangeFront READ r3RangeFront) + + Q_PROPERTY(float r1MinRangeBack READ r1MinRangeBack WRITE setR1MinRangeBack NOTIFY dirty) + Q_PROPERTY(float r2MinRangeBack READ r2MinRangeBack WRITE setR2MinRangeBack NOTIFY dirty) + Q_PROPERTY(float r3MinRangeBack READ r3MinRangeBack WRITE setR3MinRangeBack NOTIFY dirty) + + Q_PROPERTY(float r1MinRangeFront READ r1MinRangeFront WRITE setR1MinRangeFront NOTIFY dirty) + Q_PROPERTY(float r2MinRangeFront READ r2MinRangeFront WRITE setR2MinRangeFront NOTIFY dirty) + Q_PROPERTY(float r3MinRangeFront READ r3MinRangeFront WRITE setR3MinRangeFront NOTIFY dirty) + + Q_PROPERTY(float r1MaxRangeBack READ r1MaxRangeBack WRITE setR1MaxRangeBack NOTIFY dirty) + Q_PROPERTY(float r2MaxRangeBack READ r2MaxRangeBack WRITE setR2MaxRangeBack NOTIFY dirty) + Q_PROPERTY(float r3MaxRangeBack READ r3MaxRangeBack WRITE setR3MaxRangeBack NOTIFY dirty) + + Q_PROPERTY(float r1MaxRangeFront READ r1MaxRangeFront WRITE setR1MaxRangeFront NOTIFY dirty) + Q_PROPERTY(float r2MaxRangeFront READ r2MaxRangeFront WRITE setR2MaxRangeFront NOTIFY dirty) + Q_PROPERTY(float r3MaxRangeFront READ r3MaxRangeFront WRITE setR3MaxRangeFront NOTIFY dirty) + + Q_PROPERTY(float r1SpeedDownBack READ r1SpeedDownBack WRITE setR1SpeedDownBack NOTIFY dirty) + Q_PROPERTY(float r2SpeedDownBack READ r2SpeedDownBack WRITE setR2SpeedDownBack NOTIFY dirty) + Q_PROPERTY(float r3SpeedDownBack READ r3SpeedDownBack WRITE setR3SpeedDownBack NOTIFY dirty) + + Q_PROPERTY(float r1SpeedDownFront READ r1SpeedDownFront WRITE setR1SpeedDownFront NOTIFY dirty) + Q_PROPERTY(float r2SpeedDownFront READ r2SpeedDownFront WRITE setR2SpeedDownFront NOTIFY dirty) + Q_PROPERTY(float r3SpeedDownFront READ r3SpeedDownFront WRITE setR3SpeedDownFront NOTIFY dirty) + + Q_PROPERTY(float r1SpeedUpBack READ r1SpeedUpBack WRITE setR1SpeedUpBack NOTIFY dirty) + Q_PROPERTY(float r2SpeedUpBack READ r2SpeedUpBack WRITE setR2SpeedUpBack NOTIFY dirty) + Q_PROPERTY(float r3SpeedUpBack READ r3SpeedUpBack WRITE setR3SpeedUpBack NOTIFY dirty) + + Q_PROPERTY(float r1SpeedUpFront READ r1SpeedUpFront WRITE setR1SpeedUpFront NOTIFY dirty) + Q_PROPERTY(float r2SpeedUpFront READ r2SpeedUpFront WRITE setR2SpeedUpFront NOTIFY dirty) + Q_PROPERTY(float r3SpeedUpFront READ r3SpeedUpFront WRITE setR3SpeedUpFront NOTIFY dirty) + public: bool regulateViewRanges() const { return data.regulateViewRanges; } void setRegulateViewRanges(bool use) { data.regulateViewRanges = use; emit dirty(); } + float r1Timing() const { return data.r1Timing; } + float r2Timing() const { return data.r2Timing; } + float r3Timing() const { return data.r3Timing; } + + float r1RangeBack() const { return data.r1RangeBack; } + float r2RangeBack() const { return data.r2RangeBack; } + float r3RangeBack() const { return data.r3RangeBack; } + + float r1RangeFront() const { return data.r1RangeFront; } + float r2RangeFront() const { return data.r2RangeFront; } + float r3RangeFront() const { return data.r3RangeFront; } + struct Data { + float r1Timing + float r2Timing + float r3Timing + bool regulateViewRanges{ true }; } data; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index e3e8ffbf4e..a64d10ca9c 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1070,9 +1070,9 @@ bool EntityItem::stepKinematicMotion(float timeElapsed) { } const float MAX_TIME_ELAPSED = 1.0f; // seconds - if (timeElapsed > MAX_TIME_ELAPSED) { - qCWarning(entities) << "kinematic timestep = " << timeElapsed << " truncated to " << MAX_TIME_ELAPSED; - } +// if (timeElapsed > MAX_TIME_ELAPSED) { +// qCWarning(entities) << "kinematic timestep = " << timeElapsed << " truncated to " << MAX_TIME_ELAPSED; +// } timeElapsed = glm::min(timeElapsed, MAX_TIME_ELAPSED); if (isSpinning) { From f50b2fab2bf7cae4551fd6fc720205d997b2b06f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 23 Apr 2018 22:38:50 -0700 Subject: [PATCH 105/138] Exposing timing and regulated radiuses --- interface/src/workload/GameWorkload.cpp | 16 +++- interface/src/workload/GameWorkload.h | 58 +++++++------ .../utilities/workload/workloadInspector.qml | 86 ++++++++++++++++++- 3 files changed, 129 insertions(+), 31 deletions(-) diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 70b17485c2..1f07d2e734 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -38,7 +38,13 @@ void ControlViews::run(const workload::WorkloadContextPointer& runContext, const if (_data.regulateViewRanges && inTimings.size()) { regulateViews(outViews, inTimings); + + auto config = std::static_pointer_cast(runContext->jobConfig); + config->dataExport = _dataExport; + config->emitDirty(); } + + } glm::vec2 Regulator::run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current) { @@ -64,9 +70,13 @@ void ControlViews::regulateViews(workload::Views& outViews, const workload::Timi } auto loopDuration = std::chrono::nanoseconds{ std::chrono::milliseconds(16) }; - regionBackFronts[workload::Region::R1] = regionRegulators[workload::Region::R1].run(loopDuration, timings[0], regionBackFronts[workload::Region::R1]); - regionBackFronts[workload::Region::R2] = regionRegulators[workload::Region::R2].run(loopDuration, timings[0], regionBackFronts[workload::Region::R2]); - regionBackFronts[workload::Region::R3] = regionRegulators[workload::Region::R3].run(loopDuration, timings[1], regionBackFronts[workload::Region::R3]); + _dataExport.ranges[workload::Region::R1] = regionBackFronts[workload::Region::R1] = regionRegulators[workload::Region::R1].run(loopDuration, timings[0], regionBackFronts[workload::Region::R1]); + _dataExport.ranges[workload::Region::R2] = regionBackFronts[workload::Region::R2] = regionRegulators[workload::Region::R2].run(loopDuration, timings[0], regionBackFronts[workload::Region::R2]); + _dataExport.ranges[workload::Region::R3] = regionBackFronts[workload::Region::R3] = regionRegulators[workload::Region::R3].run(loopDuration, timings[1], regionBackFronts[workload::Region::R3]); + + _dataExport.timings[workload::Region::R1] = std::chrono::duration(timings[0]).count(); + _dataExport.timings[workload::Region::R2] = _dataExport.timings[workload::Region::R1]; + _dataExport.timings[workload::Region::R3] = std::chrono::duration(timings[1]).count(); int i = 0; for (auto& outView : outViews) { diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index 702e0029d0..6a297964cf 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -47,18 +47,18 @@ class ControlViewsConfig : public workload::Job::Config { Q_OBJECT Q_PROPERTY(bool regulateViewRanges READ regulateViewRanges WRITE setRegulateViewRanges NOTIFY dirty) - Q_PROPERTY(float r1Timing READ r1Timing) - Q_PROPERTY(float r2Timing READ r2Timing) - Q_PROPERTY(float r3Timing READ r3Timing) + Q_PROPERTY(float r1Timing READ r1Timing NOTIFY dirty) + Q_PROPERTY(float r2Timing READ r2Timing NOTIFY dirty) + Q_PROPERTY(float r3Timing READ r3Timing NOTIFY dirty) - Q_PROPERTY(float r1RangeBack READ r1RangeBack) - Q_PROPERTY(float r2RangeBack READ r2RangeBack) - Q_PROPERTY(float r3RangeBack READ r3RangeBack) - - Q_PROPERTY(float r1RangeFront READ r1RangeFront) - Q_PROPERTY(float r2RangeFront READ r2RangeFront) - Q_PROPERTY(float r3RangeFront READ r3RangeFront) + Q_PROPERTY(float r1RangeBack READ r1RangeBack NOTIFY dirty) + Q_PROPERTY(float r2RangeBack READ r2RangeBack NOTIFY dirty) + Q_PROPERTY(float r3RangeBack READ r3RangeBack NOTIFY dirty) + Q_PROPERTY(float r1RangeFront READ r1RangeFront NOTIFY dirty) + Q_PROPERTY(float r2RangeFront READ r2RangeFront NOTIFY dirty) + Q_PROPERTY(float r3RangeFront READ r3RangeFront NOTIFY dirty) +/* Q_PROPERTY(float r1MinRangeBack READ r1MinRangeBack WRITE setR1MinRangeBack NOTIFY dirty) Q_PROPERTY(float r2MinRangeBack READ r2MinRangeBack WRITE setR2MinRangeBack NOTIFY dirty) Q_PROPERTY(float r3MinRangeBack READ r3MinRangeBack WRITE setR3MinRangeBack NOTIFY dirty) @@ -89,33 +89,36 @@ class ControlViewsConfig : public workload::Job::Config { Q_PROPERTY(float r1SpeedUpFront READ r1SpeedUpFront WRITE setR1SpeedUpFront NOTIFY dirty) Q_PROPERTY(float r2SpeedUpFront READ r2SpeedUpFront WRITE setR2SpeedUpFront NOTIFY dirty) - Q_PROPERTY(float r3SpeedUpFront READ r3SpeedUpFront WRITE setR3SpeedUpFront NOTIFY dirty) + Q_PROPERTY(float r3SpeedUpFront READ r3SpeedUpFront WRITE setR3SpeedUpFront NOTIFY dirty)*/ public: bool regulateViewRanges() const { return data.regulateViewRanges; } void setRegulateViewRanges(bool use) { data.regulateViewRanges = use; emit dirty(); } - float r1Timing() const { return data.r1Timing; } - float r2Timing() const { return data.r2Timing; } - float r3Timing() const { return data.r3Timing; } + float r1Timing() const { return dataExport.timings[workload::Region::R1]; } + float r2Timing() const { return dataExport.timings[workload::Region::R2]; } + float r3Timing() const { return dataExport.timings[workload::Region::R3]; } - float r1RangeBack() const { return data.r1RangeBack; } - float r2RangeBack() const { return data.r2RangeBack; } - float r3RangeBack() const { return data.r3RangeBack; } + float r1RangeBack() const { return dataExport.ranges[workload::Region::R1].x; } + float r2RangeBack() const { return dataExport.ranges[workload::Region::R2].x; } + float r3RangeBack() const { return dataExport.ranges[workload::Region::R3].x; } - float r1RangeFront() const { return data.r1RangeFront; } - float r2RangeFront() const { return data.r2RangeFront; } - float r3RangeFront() const { return data.r3RangeFront; } + float r1RangeFront() const { return dataExport.ranges[workload::Region::R1].y; } + float r2RangeFront() const { return dataExport.ranges[workload::Region::R2].y; } + float r3RangeFront() const { return dataExport.ranges[workload::Region::R3].y; } struct Data { - float r1Timing - float r2Timing - float r3Timing - bool regulateViewRanges{ true }; - } data; + + struct DataExport { + static const int SIZE{ workload::Region::NUM_VIEW_REGIONS }; + float timings[SIZE]; + glm::vec2 ranges[SIZE]; + } dataExport; + + void emitDirty() { emit dirty(); } signals: void dirty(); }; @@ -149,13 +152,14 @@ public: void configure(const Config& config); void run(const workload::WorkloadContextPointer& runContext, const Input& inputs, Output& outputs); - std::array regionBackFronts; - std::array regionRegulators; + std::array regionBackFronts; + std::array regionRegulators; void regulateViews(workload::Views& views, const workload::Timings& timings); protected: Config::Data _data; + Config::DataExport _dataExport; }; #endif // hifi_GameWorkload_h diff --git a/scripts/developer/utilities/workload/workloadInspector.qml b/scripts/developer/utilities/workload/workloadInspector.qml index 885d8ddb66..03bf5f640a 100644 --- a/scripts/developer/utilities/workload/workloadInspector.qml +++ b/scripts/developer/utilities/workload/workloadInspector.qml @@ -15,6 +15,7 @@ import "qrc:///qml/styles-uit" import "qrc:///qml/controls-uit" as HifiControls import "../render/configSlider" import "../lib/jet/qml" as Jet +import "../lib/plotperf" Rectangle { @@ -66,6 +67,7 @@ Rectangle { } Column { + id: stats spacing: 5 anchors.left: parent.left anchors.right: parent.right @@ -119,6 +121,7 @@ Rectangle { } RowLayout { + visible: !Workload.getConfig("controlViews")["regulateViewRanges"] anchors.left: parent.left anchors.right: parent.right Column { @@ -176,6 +179,86 @@ Rectangle { } } } + RowLayout { + visible: Workload.getConfig("controlViews")["regulateViewRanges"] + anchors.left: parent.left + anchors.right: parent.right + Column { + anchors.left: parent.left + anchors.right: parent.horizontalCenter + HifiControls.Label { + text: "Back [m]" + anchors.horizontalCenter: parent.horizontalCenter + } + Repeater { + model: [ + "R1:r1RangeBack:50.0:0.0", + "R2:r2RangeBack:50.0:0.0", + "R3:r3RangeBack:50.0:0.0" + ] + ConfigSlider { + label: qsTr(modelData.split(":")[0]) + config: Workload.getConfig("controlViews") + property: modelData.split(":")[1] + max: modelData.split(":")[2] + min: modelData.split(":")[3] + integral: true + + labelAreaWidthScale: 0.4 + anchors.left: parent.left + anchors.right: parent.right + } + } + } + Column { + anchors.left: parent.horizontalCenter + anchors.right: parent.right + HifiControls.Label { + text: "Front [m]" + anchors.horizontalCenter: parent.horizontalCenter + } + Repeater { + model: [ + "r1RangeFront:300:1.0", + "r2RangeFront:300:1.0", + "r3RangeFront:300:1.0" + ] + ConfigSlider { + showLabel: false + config: Workload.getConfig("controlViews") + property: modelData.split(":")[0] + max: modelData.split(":")[1] + min: modelData.split(":")[2] + integral: true + + labelAreaWidthScale: 0.3 + anchors.left: parent.left + anchors.right: parent.right + } + } + } + } + property var controlViews: Workload.getConfig("controlViews") + + PlotPerf { + title: "Timings" + height: 100 + object: stats.controlViews + valueScale: 1.0 + valueUnit: "ms" + plots: [ + { + prop: "r2Timing", + label: "Physics + Collisions", + color: "#1AC567" + }, + { + prop: "r3Timing", + label: "Kinematic + Update", + color: "#1A67C5" + } + ] + } Separator {} HifiControls.Label { text: "Numbers:"; @@ -188,7 +271,8 @@ Rectangle { } HifiControls.Label { text: "R3= " + Workload.getConfig("regionState")["numR3"]; - } + } + Separator {} HifiControls.Label { text: "Display" From 32e83c256a09f9e32112c70c23c1ce5453aab336 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 25 Apr 2018 12:23:30 -0700 Subject: [PATCH 106/138] Adjusting the task::Engine run signature to appease gcc gods and other warnings --- interface/src/workload/GameWorkload.cpp | 6 +----- libraries/task/src/task/Task.h | 6 +++++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 1f07d2e734..68e3998210 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -14,7 +14,6 @@ #include #include "PhysicsBoundary.h" -#pragma optimize( "[optimization-list]", off ) ControlViews::ControlViews() { regionBackFronts[0] = glm::vec2(1.0f, 3.0f); @@ -53,7 +52,7 @@ glm::vec2 Regulator::run(const Timing_ns& regulationDuration, const Timing_ns& m // Regulate next value based on current moving toward the goal budget float error_ms = std::chrono::duration(_budget - measured).count(); float coef = error_ms / std::chrono::duration(regulationDuration).count(); - next += coef * (error_ms < 0.0 ? _speedDown : _speedUp); + next += coef * (error_ms < 0.0f ? _speedDown : _speedUp); // Clamp to min max next = glm::clamp(next, _minRange, _maxRange); @@ -78,7 +77,6 @@ void ControlViews::regulateViews(workload::Views& outViews, const workload::Timi _dataExport.timings[workload::Region::R2] = _dataExport.timings[workload::Region::R1]; _dataExport.timings[workload::Region::R3] = std::chrono::duration(timings[1]).count(); - int i = 0; for (auto& outView : outViews) { outView.regionBackFronts[workload::Region::R1] = regionBackFronts[workload::Region::R1]; outView.regionBackFronts[workload::Region::R2] = regionBackFronts[workload::Region::R2]; @@ -88,8 +86,6 @@ void ControlViews::regulateViews(workload::Views& outViews, const workload::Timi } } -#pragma optimize( "[optimization-list]", on ) - class WorkloadEngineBuilder { public: public: diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index b528802947..6979815cd2 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -399,11 +399,15 @@ public: void run() { if (_context) { - TaskType::run(_context); + run(_context); } } protected: + void run(const ContextPointer& jobContext) override { + TaskType::run(_context); + } + ContextPointer _context; }; } From 17f8e789fcdabc762717985f261183183f68f43c Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 25 Apr 2018 15:53:50 -0700 Subject: [PATCH 107/138] less warning maybe ? --- libraries/workload/src/workload/RegionState.cpp | 2 +- .../developer/utilities/workload/test_physics_scene.js | 4 ++-- .../developer/utilities/workload/workloadInspector.qml | 9 +++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/libraries/workload/src/workload/RegionState.cpp b/libraries/workload/src/workload/RegionState.cpp index f693e68904..47179ad6f7 100644 --- a/libraries/workload/src/workload/RegionState.cpp +++ b/libraries/workload/src/workload/RegionState.cpp @@ -72,5 +72,5 @@ void RegionState::run(const workload::WorkloadContextPointer& renderContext, con } auto config = std::static_pointer_cast(renderContext->jobConfig); - config->setNum(0, _state[0].size(), _state[1].size(), _state[2].size()); + config->setNum(0, (uint32_t) _state[0].size(), (uint32_t) _state[1].size(), (uint32_t) _state[2].size()); } diff --git a/scripts/developer/utilities/workload/test_physics_scene.js b/scripts/developer/utilities/workload/test_physics_scene.js index bbb9f3d7ea..e923bd0fea 100644 --- a/scripts/developer/utilities/workload/test_physics_scene.js +++ b/scripts/developer/utilities/workload/test_physics_scene.js @@ -56,8 +56,8 @@ function getTileColor(a, b, c) { function addObject(a, b, c, lifetime) { var center = getStagePosOriAt(a, b, c).pos; var offset = (Math.abs(a) + (Math.abs(b) % 2)) % 2; - var makePrim = (offset > 0 ? true : false) ; - if (makePrim) { + var makePrim = (offset == 0 ? true : false) ; + if (makePrim == true) { return (Entities.addEntity({ type: "Shape", shape: "Sphere", diff --git a/scripts/developer/utilities/workload/workloadInspector.qml b/scripts/developer/utilities/workload/workloadInspector.qml index 03bf5f640a..06d59eea16 100644 --- a/scripts/developer/utilities/workload/workloadInspector.qml +++ b/scripts/developer/utilities/workload/workloadInspector.qml @@ -179,7 +179,7 @@ Rectangle { } } } - RowLayout { + /*RowLayout { visible: Workload.getConfig("controlViews")["regulateViewRanges"] anchors.left: parent.left anchors.right: parent.right @@ -237,7 +237,7 @@ Rectangle { } } } - } + }*/ property var controlViews: Workload.getConfig("controlViews") PlotPerf { @@ -294,6 +294,7 @@ Rectangle { text: "Test" } Row { + spacing: 5 anchors.left: parent.left anchors.right: parent.right HifiControls.Button { @@ -310,13 +311,13 @@ Rectangle { _workload.broadcastClearScene() } } - HifiControls.Button { + /*HifiControls.Button { text: "bump floor" onClicked: { print("pressed") _workload.broadcastBumpUpFloor() } - } + }*/ } HifiControls.Label { id: gridSizeLabel From ba29ebaeb0640e787bfe147262b9dff3fd7fe9bf Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 26 Apr 2018 13:08:26 -0700 Subject: [PATCH 108/138] Moving the view controller up into workload and exposing timings --- interface/src/workload/GameWorkload.cpp | 75 +----------- libraries/workload/src/workload/ViewTask.cpp | 74 ++++++++++++ libraries/workload/src/workload/ViewTask.h | 120 +++++++++++++++++++ 3 files changed, 196 insertions(+), 73 deletions(-) diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 68e3998210..c177cfb7cf 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -15,77 +15,6 @@ #include "PhysicsBoundary.h" -ControlViews::ControlViews() { - regionBackFronts[0] = glm::vec2(1.0f, 3.0f); - regionBackFronts[1] = glm::vec2(1.0f, 5.0f); - regionBackFronts[2] = glm::vec2(1.0f, 10.0f); - regionRegulators[0] = Regulator(std::chrono::milliseconds(2), regionBackFronts[0], 5.0f * regionBackFronts[0], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); - regionRegulators[1] = Regulator(std::chrono::milliseconds(2), regionBackFronts[1], 8.0f * regionBackFronts[1], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); - regionRegulators[2] = Regulator(std::chrono::milliseconds(2), regionBackFronts[2], 10.0f * regionBackFronts[2], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); -} - -void ControlViews::configure(const Config& config) { - _data = config.data; -} - -void ControlViews::run(const workload::WorkloadContextPointer& runContext, const Input& inputs, Output& outputs) { - const auto& inViews = inputs.get0(); - const auto& inTimings = inputs.get1(); - auto& outViews = outputs; - outViews.clear(); - outViews = inViews; - - if (_data.regulateViewRanges && inTimings.size()) { - regulateViews(outViews, inTimings); - - auto config = std::static_pointer_cast(runContext->jobConfig); - config->dataExport = _dataExport; - config->emitDirty(); - } - - -} - -glm::vec2 Regulator::run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current) { - glm::vec2 next = current; - - // Regulate next value based on current moving toward the goal budget - float error_ms = std::chrono::duration(_budget - measured).count(); - float coef = error_ms / std::chrono::duration(regulationDuration).count(); - next += coef * (error_ms < 0.0f ? _speedDown : _speedUp); - - // Clamp to min max - next = glm::clamp(next, _minRange, _maxRange); - - return next; -} - -void ControlViews::regulateViews(workload::Views& outViews, const workload::Timings& timings) { - - for (auto& outView : outViews) { - for (int r = 0; r < workload::Region::NUM_VIEW_REGIONS; r++) { - outView.regionBackFronts[r] = regionBackFronts[r]; - } - } - - auto loopDuration = std::chrono::nanoseconds{ std::chrono::milliseconds(16) }; - _dataExport.ranges[workload::Region::R1] = regionBackFronts[workload::Region::R1] = regionRegulators[workload::Region::R1].run(loopDuration, timings[0], regionBackFronts[workload::Region::R1]); - _dataExport.ranges[workload::Region::R2] = regionBackFronts[workload::Region::R2] = regionRegulators[workload::Region::R2].run(loopDuration, timings[0], regionBackFronts[workload::Region::R2]); - _dataExport.ranges[workload::Region::R3] = regionBackFronts[workload::Region::R3] = regionRegulators[workload::Region::R3].run(loopDuration, timings[1], regionBackFronts[workload::Region::R3]); - - _dataExport.timings[workload::Region::R1] = std::chrono::duration(timings[0]).count(); - _dataExport.timings[workload::Region::R2] = _dataExport.timings[workload::Region::R1]; - _dataExport.timings[workload::Region::R3] = std::chrono::duration(timings[1]).count(); - - for (auto& outView : outViews) { - outView.regionBackFronts[workload::Region::R1] = regionBackFronts[workload::Region::R1]; - outView.regionBackFronts[workload::Region::R2] = regionBackFronts[workload::Region::R2]; - outView.regionBackFronts[workload::Region::R3] = regionBackFronts[workload::Region::R3]; - - workload::View::updateRegionsFromBackFronts(outView); - } -} - class WorkloadEngineBuilder { public: public: @@ -99,8 +28,8 @@ public: const auto usedViews = model.addJob("setupViews", inViews); - const auto controlViewsIn = ControlViews::Input(usedViews, inTimings).asVarying(); - const auto fixedViews = model.addJob("controlViews", controlViewsIn); + const auto controlViewsIn = workload::ControlViews::Input(usedViews, inTimings).asVarying(); + const auto fixedViews = model.addJob("controlViews", controlViewsIn); const auto regionTrackerOut = model.addJob("spaceClassifier", fixedViews); diff --git a/libraries/workload/src/workload/ViewTask.cpp b/libraries/workload/src/workload/ViewTask.cpp index 672078fb9a..0c3f2cc873 100644 --- a/libraries/workload/src/workload/ViewTask.cpp +++ b/libraries/workload/src/workload/ViewTask.cpp @@ -69,3 +69,77 @@ void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& i } + +ControlViews::ControlViews() { + regionBackFronts[0] = glm::vec2(1.0f, 3.0f); + regionBackFronts[1] = glm::vec2(1.0f, 5.0f); + regionBackFronts[2] = glm::vec2(1.0f, 10.0f); + regionRegulators[0] = Regulator(std::chrono::milliseconds(2), regionBackFronts[0], 5.0f * regionBackFronts[0], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); + regionRegulators[1] = Regulator(std::chrono::milliseconds(2), regionBackFronts[1], 8.0f * regionBackFronts[1], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); + regionRegulators[2] = Regulator(std::chrono::milliseconds(2), regionBackFronts[2], 10.0f * regionBackFronts[2], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); +} + +void ControlViews::configure(const Config& config) { + _data = config.data; +} + +void ControlViews::run(const workload::WorkloadContextPointer& runContext, const Input& inputs, Output& outputs) { + const auto& inViews = inputs.get0(); + const auto& inTimings = inputs.get1(); + auto& outViews = outputs; + outViews.clear(); + outViews = inViews; + + if (_data.regulateViewRanges && inTimings.size()) { + regulateViews(outViews, inTimings); + } + + // Export the timings for debuging + if (inTimings.size()) { + _dataExport.timings[workload::Region::R1] = std::chrono::duration(inTimings[0]).count(); + _dataExport.timings[workload::Region::R2] = _dataExport.timings[workload::Region::R1]; + _dataExport.timings[workload::Region::R3] = std::chrono::duration(inTimings[1]).count(); + + auto config = std::static_pointer_cast(runContext->jobConfig); + config->dataExport = _dataExport; + config->emitDirty(); + } +} + +glm::vec2 Regulator::run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current) { + glm::vec2 next = current; + + // Regulate next value based on current moving toward the goal budget + float error_ms = std::chrono::duration(_budget - measured).count(); + float coef = error_ms / std::chrono::duration(regulationDuration).count(); + next += coef * (error_ms < 0.0f ? _speedDown : _speedUp); + + // Clamp to min max + next = glm::clamp(next, _minRange, _maxRange); + + return next; +} + +void ControlViews::regulateViews(workload::Views& outViews, const workload::Timings& timings) { + + for (auto& outView : outViews) { + for (int r = 0; r < workload::Region::NUM_VIEW_REGIONS; r++) { + outView.regionBackFronts[r] = regionBackFronts[r]; + } + } + + auto loopDuration = std::chrono::nanoseconds{ std::chrono::milliseconds(16) }; + _dataExport.ranges[workload::Region::R1] = regionBackFronts[workload::Region::R1] = regionRegulators[workload::Region::R1].run(loopDuration, timings[0], regionBackFronts[workload::Region::R1]); + _dataExport.ranges[workload::Region::R2] = regionBackFronts[workload::Region::R2] = regionRegulators[workload::Region::R2].run(loopDuration, timings[0], regionBackFronts[workload::Region::R2]); + _dataExport.ranges[workload::Region::R3] = regionBackFronts[workload::Region::R3] = regionRegulators[workload::Region::R3].run(loopDuration, timings[1], regionBackFronts[workload::Region::R3]); + + for (auto& outView : outViews) { + outView.regionBackFronts[workload::Region::R1] = regionBackFronts[workload::Region::R1]; + outView.regionBackFronts[workload::Region::R2] = regionBackFronts[workload::Region::R2]; + outView.regionBackFronts[workload::Region::R3] = regionBackFronts[workload::Region::R3]; + + workload::View::updateRegionsFromBackFronts(outView); + } +} + + diff --git a/libraries/workload/src/workload/ViewTask.h b/libraries/workload/src/workload/ViewTask.h index dd1b60890c..75223292f3 100644 --- a/libraries/workload/src/workload/ViewTask.h +++ b/libraries/workload/src/workload/ViewTask.h @@ -98,6 +98,126 @@ namespace workload { void run(const workload::WorkloadContextPointer& renderContext, const Input& inputs); }; + + class ControlViewsConfig : public workload::Job::Config { + Q_OBJECT + Q_PROPERTY(bool regulateViewRanges READ regulateViewRanges WRITE setRegulateViewRanges NOTIFY dirty) + + Q_PROPERTY(float r1Timing READ r1Timing NOTIFY dirty) + Q_PROPERTY(float r2Timing READ r2Timing NOTIFY dirty) + Q_PROPERTY(float r3Timing READ r3Timing NOTIFY dirty) + + Q_PROPERTY(float r1RangeBack READ r1RangeBack NOTIFY dirty) + Q_PROPERTY(float r2RangeBack READ r2RangeBack NOTIFY dirty) + Q_PROPERTY(float r3RangeBack READ r3RangeBack NOTIFY dirty) + + Q_PROPERTY(float r1RangeFront READ r1RangeFront NOTIFY dirty) + Q_PROPERTY(float r2RangeFront READ r2RangeFront NOTIFY dirty) + Q_PROPERTY(float r3RangeFront READ r3RangeFront NOTIFY dirty) + /* + Q_PROPERTY(float r1MinRangeBack READ r1MinRangeBack WRITE setR1MinRangeBack NOTIFY dirty) + Q_PROPERTY(float r2MinRangeBack READ r2MinRangeBack WRITE setR2MinRangeBack NOTIFY dirty) + Q_PROPERTY(float r3MinRangeBack READ r3MinRangeBack WRITE setR3MinRangeBack NOTIFY dirty) + + Q_PROPERTY(float r1MinRangeFront READ r1MinRangeFront WRITE setR1MinRangeFront NOTIFY dirty) + Q_PROPERTY(float r2MinRangeFront READ r2MinRangeFront WRITE setR2MinRangeFront NOTIFY dirty) + Q_PROPERTY(float r3MinRangeFront READ r3MinRangeFront WRITE setR3MinRangeFront NOTIFY dirty) + + Q_PROPERTY(float r1MaxRangeBack READ r1MaxRangeBack WRITE setR1MaxRangeBack NOTIFY dirty) + Q_PROPERTY(float r2MaxRangeBack READ r2MaxRangeBack WRITE setR2MaxRangeBack NOTIFY dirty) + Q_PROPERTY(float r3MaxRangeBack READ r3MaxRangeBack WRITE setR3MaxRangeBack NOTIFY dirty) + + Q_PROPERTY(float r1MaxRangeFront READ r1MaxRangeFront WRITE setR1MaxRangeFront NOTIFY dirty) + Q_PROPERTY(float r2MaxRangeFront READ r2MaxRangeFront WRITE setR2MaxRangeFront NOTIFY dirty) + Q_PROPERTY(float r3MaxRangeFront READ r3MaxRangeFront WRITE setR3MaxRangeFront NOTIFY dirty) + + Q_PROPERTY(float r1SpeedDownBack READ r1SpeedDownBack WRITE setR1SpeedDownBack NOTIFY dirty) + Q_PROPERTY(float r2SpeedDownBack READ r2SpeedDownBack WRITE setR2SpeedDownBack NOTIFY dirty) + Q_PROPERTY(float r3SpeedDownBack READ r3SpeedDownBack WRITE setR3SpeedDownBack NOTIFY dirty) + + Q_PROPERTY(float r1SpeedDownFront READ r1SpeedDownFront WRITE setR1SpeedDownFront NOTIFY dirty) + Q_PROPERTY(float r2SpeedDownFront READ r2SpeedDownFront WRITE setR2SpeedDownFront NOTIFY dirty) + Q_PROPERTY(float r3SpeedDownFront READ r3SpeedDownFront WRITE setR3SpeedDownFront NOTIFY dirty) + + Q_PROPERTY(float r1SpeedUpBack READ r1SpeedUpBack WRITE setR1SpeedUpBack NOTIFY dirty) + Q_PROPERTY(float r2SpeedUpBack READ r2SpeedUpBack WRITE setR2SpeedUpBack NOTIFY dirty) + Q_PROPERTY(float r3SpeedUpBack READ r3SpeedUpBack WRITE setR3SpeedUpBack NOTIFY dirty) + + Q_PROPERTY(float r1SpeedUpFront READ r1SpeedUpFront WRITE setR1SpeedUpFront NOTIFY dirty) + Q_PROPERTY(float r2SpeedUpFront READ r2SpeedUpFront WRITE setR2SpeedUpFront NOTIFY dirty) + Q_PROPERTY(float r3SpeedUpFront READ r3SpeedUpFront WRITE setR3SpeedUpFront NOTIFY dirty)*/ + + public: + + bool regulateViewRanges() const { return data.regulateViewRanges; } + void setRegulateViewRanges(bool use) { data.regulateViewRanges = use; emit dirty(); } + + float r1Timing() const { return dataExport.timings[workload::Region::R1]; } + float r2Timing() const { return dataExport.timings[workload::Region::R2]; } + float r3Timing() const { return dataExport.timings[workload::Region::R3]; } + + float r1RangeBack() const { return dataExport.ranges[workload::Region::R1].x; } + float r2RangeBack() const { return dataExport.ranges[workload::Region::R2].x; } + float r3RangeBack() const { return dataExport.ranges[workload::Region::R3].x; } + + float r1RangeFront() const { return dataExport.ranges[workload::Region::R1].y; } + float r2RangeFront() const { return dataExport.ranges[workload::Region::R2].y; } + float r3RangeFront() const { return dataExport.ranges[workload::Region::R3].y; } + + struct Data { + bool regulateViewRanges{ true }; + } data; + + struct DataExport { + static const int SIZE{ workload::Region::NUM_VIEW_REGIONS }; + float timings[SIZE]; + glm::vec2 ranges[SIZE]; + } dataExport; + + void emitDirty() { emit dirty(); } + signals: + void dirty(); + }; + + struct Regulator { + using Timing_ns = std::chrono::nanoseconds; + Timing_ns _budget{ std::chrono::milliseconds(2) }; + glm::vec2 _minRange{ 2.0f, 5.0f }; + glm::vec2 _maxRange{ 50.0f, 100.0f }; + + glm::vec2 _speedDown{ 0.2f }; + glm::vec2 _speedUp{ 0.1f }; + + + Regulator() {} + Regulator(const Timing_ns& budget_ns, const glm::vec2& minRange, const glm::vec2& maxRange, const glm::vec2& speedDown, const glm::vec2& speedUp) : + _budget(budget_ns), _minRange(minRange), _maxRange(maxRange), _speedDown(speedDown), _speedUp(speedUp) {} + + glm::vec2 run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current); + }; + + class ControlViews { + public: + using Config = ControlViewsConfig; + using Input = workload::VaryingSet2; + using Output = workload::Views; + using JobModel = workload::Job::ModelIO; + + ControlViews(); + + void configure(const Config& config); + void run(const workload::WorkloadContextPointer& runContext, const Input& inputs, Output& outputs); + + std::array regionBackFronts; + std::array regionRegulators; + + void regulateViews(workload::Views& views, const workload::Timings& timings); + + protected: + Config::Data _data; + Config::DataExport _dataExport; + }; + } // namespace workload #endif // hifi_workload_ViewTask_h \ No newline at end of file From 3ab0458d3a54e4a5208a1e89c4c3aa7d409a4105 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 26 Apr 2018 17:45:48 -0700 Subject: [PATCH 109/138] Trying to expose an array to js --- interface/src/Application.cpp | 20 +++- interface/src/workload/GameWorkload.h | 119 --------------------- libraries/workload/src/workload/ViewTask.h | 7 ++ 3 files changed, 22 insertions(+), 124 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f19422c442..83e588e8c3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5315,6 +5315,7 @@ void Application::update(float deltaTime) { if (_physicsEnabled) { auto t0 = std::chrono::high_resolution_clock::now(); + auto t1 = t0; { PROFILE_RANGE(simulation_physics, "PrePhysics"); PerformanceTimer perfTimer("prePhysics)"); @@ -5338,6 +5339,8 @@ void Application::update(float deltaTime) { _entitySimulation->applyDynamicChanges(); + t1 = std::chrono::high_resolution_clock::now(); + avatarManager->getObjectsToRemoveFromPhysics(motionStates); _physicsEngine->removeObjects(motionStates); avatarManager->getObjectsToAddToPhysics(motionStates); @@ -5350,6 +5353,7 @@ void Application::update(float deltaTime) { dynamic->prepareForPhysicsSimulation(); }); } + auto t2 = std::chrono::high_resolution_clock::now(); { PROFILE_RANGE(simulation_physics, "StepPhysics"); PerformanceTimer perfTimer("stepPhysics"); @@ -5357,6 +5361,7 @@ void Application::update(float deltaTime) { _physicsEngine->stepSimulation(); }); } + auto t3 = std::chrono::high_resolution_clock::now(); { if (_physicsEngine->hasOutgoingChanges()) { { @@ -5402,7 +5407,7 @@ void Application::update(float deltaTime) { // NOTE: the PhysicsEngine stats are written to stdout NOT to Qt log framework _physicsEngine->dumpStatsIfNecessary(); } - auto t1 = std::chrono::high_resolution_clock::now(); + auto t4 = std::chrono::high_resolution_clock::now(); if (!_aboutToQuit) { // NOTE: the getEntities()->update() call below will wait for lock @@ -5410,11 +5415,16 @@ void Application::update(float deltaTime) { getEntities()->update(true); // update the models... } - auto t2 = std::chrono::high_resolution_clock::now(); + auto t5 = std::chrono::high_resolution_clock::now(); + + workload::Timings timings(6); + timings[0] = (t4 - t0); + timings[1] = (t5 - t4); + timings[2] = (t4 - t3); + timings[3] = (t3 - t2); + timings[4] = (t2 - t1); + timings[5] = (t1 - t0); - workload::Timings timings(2); - timings[0] = (t1 - t0); - timings[1] = (t2 - t1); _gameWorkload.updateSimulationTimings(timings); } diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index 6a297964cf..1f835686f8 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -43,123 +43,4 @@ public: workload::EnginePointer _engine; }; -class ControlViewsConfig : public workload::Job::Config { - Q_OBJECT - Q_PROPERTY(bool regulateViewRanges READ regulateViewRanges WRITE setRegulateViewRanges NOTIFY dirty) - - Q_PROPERTY(float r1Timing READ r1Timing NOTIFY dirty) - Q_PROPERTY(float r2Timing READ r2Timing NOTIFY dirty) - Q_PROPERTY(float r3Timing READ r3Timing NOTIFY dirty) - - Q_PROPERTY(float r1RangeBack READ r1RangeBack NOTIFY dirty) - Q_PROPERTY(float r2RangeBack READ r2RangeBack NOTIFY dirty) - Q_PROPERTY(float r3RangeBack READ r3RangeBack NOTIFY dirty) - - Q_PROPERTY(float r1RangeFront READ r1RangeFront NOTIFY dirty) - Q_PROPERTY(float r2RangeFront READ r2RangeFront NOTIFY dirty) - Q_PROPERTY(float r3RangeFront READ r3RangeFront NOTIFY dirty) -/* - Q_PROPERTY(float r1MinRangeBack READ r1MinRangeBack WRITE setR1MinRangeBack NOTIFY dirty) - Q_PROPERTY(float r2MinRangeBack READ r2MinRangeBack WRITE setR2MinRangeBack NOTIFY dirty) - Q_PROPERTY(float r3MinRangeBack READ r3MinRangeBack WRITE setR3MinRangeBack NOTIFY dirty) - - Q_PROPERTY(float r1MinRangeFront READ r1MinRangeFront WRITE setR1MinRangeFront NOTIFY dirty) - Q_PROPERTY(float r2MinRangeFront READ r2MinRangeFront WRITE setR2MinRangeFront NOTIFY dirty) - Q_PROPERTY(float r3MinRangeFront READ r3MinRangeFront WRITE setR3MinRangeFront NOTIFY dirty) - - Q_PROPERTY(float r1MaxRangeBack READ r1MaxRangeBack WRITE setR1MaxRangeBack NOTIFY dirty) - Q_PROPERTY(float r2MaxRangeBack READ r2MaxRangeBack WRITE setR2MaxRangeBack NOTIFY dirty) - Q_PROPERTY(float r3MaxRangeBack READ r3MaxRangeBack WRITE setR3MaxRangeBack NOTIFY dirty) - - Q_PROPERTY(float r1MaxRangeFront READ r1MaxRangeFront WRITE setR1MaxRangeFront NOTIFY dirty) - Q_PROPERTY(float r2MaxRangeFront READ r2MaxRangeFront WRITE setR2MaxRangeFront NOTIFY dirty) - Q_PROPERTY(float r3MaxRangeFront READ r3MaxRangeFront WRITE setR3MaxRangeFront NOTIFY dirty) - - Q_PROPERTY(float r1SpeedDownBack READ r1SpeedDownBack WRITE setR1SpeedDownBack NOTIFY dirty) - Q_PROPERTY(float r2SpeedDownBack READ r2SpeedDownBack WRITE setR2SpeedDownBack NOTIFY dirty) - Q_PROPERTY(float r3SpeedDownBack READ r3SpeedDownBack WRITE setR3SpeedDownBack NOTIFY dirty) - - Q_PROPERTY(float r1SpeedDownFront READ r1SpeedDownFront WRITE setR1SpeedDownFront NOTIFY dirty) - Q_PROPERTY(float r2SpeedDownFront READ r2SpeedDownFront WRITE setR2SpeedDownFront NOTIFY dirty) - Q_PROPERTY(float r3SpeedDownFront READ r3SpeedDownFront WRITE setR3SpeedDownFront NOTIFY dirty) - - Q_PROPERTY(float r1SpeedUpBack READ r1SpeedUpBack WRITE setR1SpeedUpBack NOTIFY dirty) - Q_PROPERTY(float r2SpeedUpBack READ r2SpeedUpBack WRITE setR2SpeedUpBack NOTIFY dirty) - Q_PROPERTY(float r3SpeedUpBack READ r3SpeedUpBack WRITE setR3SpeedUpBack NOTIFY dirty) - - Q_PROPERTY(float r1SpeedUpFront READ r1SpeedUpFront WRITE setR1SpeedUpFront NOTIFY dirty) - Q_PROPERTY(float r2SpeedUpFront READ r2SpeedUpFront WRITE setR2SpeedUpFront NOTIFY dirty) - Q_PROPERTY(float r3SpeedUpFront READ r3SpeedUpFront WRITE setR3SpeedUpFront NOTIFY dirty)*/ - -public: - - bool regulateViewRanges() const { return data.regulateViewRanges; } - void setRegulateViewRanges(bool use) { data.regulateViewRanges = use; emit dirty(); } - - float r1Timing() const { return dataExport.timings[workload::Region::R1]; } - float r2Timing() const { return dataExport.timings[workload::Region::R2]; } - float r3Timing() const { return dataExport.timings[workload::Region::R3]; } - - float r1RangeBack() const { return dataExport.ranges[workload::Region::R1].x; } - float r2RangeBack() const { return dataExport.ranges[workload::Region::R2].x; } - float r3RangeBack() const { return dataExport.ranges[workload::Region::R3].x; } - - float r1RangeFront() const { return dataExport.ranges[workload::Region::R1].y; } - float r2RangeFront() const { return dataExport.ranges[workload::Region::R2].y; } - float r3RangeFront() const { return dataExport.ranges[workload::Region::R3].y; } - - struct Data { - bool regulateViewRanges{ true }; - } data; - - struct DataExport { - static const int SIZE{ workload::Region::NUM_VIEW_REGIONS }; - float timings[SIZE]; - glm::vec2 ranges[SIZE]; - } dataExport; - - void emitDirty() { emit dirty(); } -signals: - void dirty(); -}; - -struct Regulator { - using Timing_ns = std::chrono::nanoseconds; - Timing_ns _budget{ std::chrono::milliseconds(2) }; - glm::vec2 _minRange{ 2.0f, 5.0f }; - glm::vec2 _maxRange{ 50.0f, 100.0f }; - - glm::vec2 _speedDown{ 0.2f }; - glm::vec2 _speedUp{ 0.1f }; - - - Regulator() {} - Regulator(const Timing_ns& budget_ns, const glm::vec2& minRange, const glm::vec2& maxRange, const glm::vec2& speedDown, const glm::vec2& speedUp) : - _budget(budget_ns), _minRange(minRange), _maxRange(maxRange), _speedDown(speedDown), _speedUp(speedUp) {} - - glm::vec2 run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current); -}; - -class ControlViews { -public: - using Config = ControlViewsConfig; - using Input = workload::VaryingSet2; - using Output = workload::Views; - using JobModel = workload::Job::ModelIO; - - ControlViews(); - - void configure(const Config& config); - void run(const workload::WorkloadContextPointer& runContext, const Input& inputs, Output& outputs); - - std::array regionBackFronts; - std::array regionRegulators; - - void regulateViews(workload::Views& views, const workload::Timings& timings); - -protected: - Config::Data _data; - Config::DataExport _dataExport; -}; - #endif // hifi_GameWorkload_h diff --git a/libraries/workload/src/workload/ViewTask.h b/libraries/workload/src/workload/ViewTask.h index 75223292f3..e226c70d09 100644 --- a/libraries/workload/src/workload/ViewTask.h +++ b/libraries/workload/src/workload/ViewTask.h @@ -103,6 +103,7 @@ namespace workload { Q_OBJECT Q_PROPERTY(bool regulateViewRanges READ regulateViewRanges WRITE setRegulateViewRanges NOTIFY dirty) + Q_PROPERTY(float r1Timing READ r1Timing NOTIFY dirty) Q_PROPERTY(float r2Timing READ r2Timing NOTIFY dirty) Q_PROPERTY(float r3Timing READ r3Timing NOTIFY dirty) @@ -164,6 +165,7 @@ namespace workload { float r2RangeFront() const { return dataExport.ranges[workload::Region::R2].y; } float r3RangeFront() const { return dataExport.ranges[workload::Region::R3].y; } + struct Data { bool regulateViewRanges{ true }; } data; @@ -172,9 +174,14 @@ namespace workload { static const int SIZE{ workload::Region::NUM_VIEW_REGIONS }; float timings[SIZE]; glm::vec2 ranges[SIZE]; + QVector _timings { 6, 2.0 }; + } dataExport; void emitDirty() { emit dirty(); } + + public slots: + Q_INVOKABLE QVector getTimings() const { return dataExport._timings; } signals: void dirty(); }; From b4682b31df4abf8a3230f78170301e5a2957bb68 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 26 Apr 2018 23:53:11 -0700 Subject: [PATCH 110/138] Getting the variant list out to js right --- libraries/workload/src/workload/ViewTask.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libraries/workload/src/workload/ViewTask.h b/libraries/workload/src/workload/ViewTask.h index e226c70d09..481d833a0b 100644 --- a/libraries/workload/src/workload/ViewTask.h +++ b/libraries/workload/src/workload/ViewTask.h @@ -13,6 +13,16 @@ #include "Engine.h" +template +QVariantList toVariantList(const QList &list) +{ + QVariantList newList; + foreach(const T &item, list) + newList << item; + + return newList; +} + namespace workload { class SetupViewsConfig : public Job::Config{ Q_OBJECT @@ -174,14 +184,14 @@ namespace workload { static const int SIZE{ workload::Region::NUM_VIEW_REGIONS }; float timings[SIZE]; glm::vec2 ranges[SIZE]; - QVector _timings { 6, 2.0 }; + QList _timings { 6, 2.0 }; } dataExport; void emitDirty() { emit dirty(); } public slots: - Q_INVOKABLE QVector getTimings() const { return dataExport._timings; } + Q_INVOKABLE QVariantList getTimings() const { return toVariantList(dataExport._timings); } signals: void dirty(); }; From 26db9ec09e95e6a4fecfcea73af2e15839089cd3 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 30 Apr 2018 10:55:56 -0700 Subject: [PATCH 111/138] yield ownership outside workload R1 --- libraries/entities/src/EntityTree.cpp | 10 ++- libraries/entities/src/SimulationOwner.h | 10 +-- libraries/physics/src/EntityMotionState.cpp | 84 +++++++++++-------- libraries/physics/src/EntityMotionState.h | 11 ++- .../physics/src/PhysicalEntitySimulation.cpp | 5 +- 5 files changed, 75 insertions(+), 45 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 8fd240aca2..5a4a2fe3dc 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -360,7 +360,12 @@ bool EntityTree::updateEntity(EntityItemPointer entity, const EntityItemProperti // the sender is trying to take or continue ownership if (entity->getSimulatorID().isNull()) { // the sender is taking ownership - properties.promoteSimulationPriority(RECRUIT_SIMULATION_PRIORITY); + SimulationOwner owner = properties.getSimulationOwner(); + if (owner.getPriority() == VOLUNTEER_SIMULATION_PRIORITY) { + // the entity-server always promotes VOLUNTEER to RECRUIT to avoid ownership thrash + // when dynamic objects first activate and multiple participants bid simultaneously + properties.promoteSimulationPriority(RECRUIT_SIMULATION_PRIORITY); + } simulationBlocked = false; } else if (entity->getSimulatorID() == senderID) { // the sender is asserting ownership, maybe changing priority @@ -392,6 +397,7 @@ bool EntityTree::updateEntity(EntityItemPointer entity, const EntityItemProperti } if (simulationBlocked) { // squash ownership and physics-related changes. + // TODO? replace these eight calls with just one? properties.setSimulationOwnerChanged(false); properties.setPositionChanged(false); properties.setRotationChanged(false); @@ -1795,7 +1801,7 @@ void EntityTree::addToNeedsParentFixupList(EntityItemPointer entity) { void EntityTree::update(bool simulate) { PROFILE_RANGE(simulation_physics, "UpdateTree"); - PerformanceTimer perfTimer("UpdateTreen"); + PerformanceTimer perfTimer("updateTree"); withWriteLock([&] { fixupNeedsParentFixups(); if (simulate && _simulation) { diff --git a/libraries/entities/src/SimulationOwner.h b/libraries/entities/src/SimulationOwner.h index cc2069dcc8..f2621e2f87 100644 --- a/libraries/entities/src/SimulationOwner.h +++ b/libraries/entities/src/SimulationOwner.h @@ -76,11 +76,11 @@ // (12) When entityA, locally owned at priority = N, collides with an unowned entityB the owner will // also bid for entityB at priority = N-1 (or VOLUNTEER, whichever is larger). // -// (13) When an entity comes to rest and is deactivated in the physics simulation the owner will -// send an update to: clear their ownerhsip, set priority to zero, and set the object's -// velocities to be zero. As per a normal bid, the owner does NOT assume that its ownership -// has been cleared until it hears from the entity-server. This, if the packet is lost the -// owner will re-send after some period. +// (13) When an entity comes to rest and is deactivated in the physics simulation the owner will send +// an update to: clear their ownerhsip, set priority to zero, and set the object's velocities to +// zero. As per a normal bid, the owner does NOT assume that its ownership has been cleared until +// it hears from the entity-server. Thus, if the packet is lost the owner will re-send after some +// period. // // (14) When an entity's ownership priority drops below VOLUNTEER other participants may bid for it // immediately at priority = VOLUNTEER. diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index c2bacd4949..df5e16233c 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -139,6 +139,7 @@ void EntityMotionState::handleEasyChanges(uint32_t& flags) { if (_entity->getSimulatorID().isNull()) { // simulation ownership has been removed if (glm::length2(_entity->getWorldVelocity()) == 0.0f) { + // TODO: also check angularVelocity // this object is coming to rest --> clear the ACTIVATION flag and _bidPriority flags &= ~Simulation::DIRTY_PHYSICS_ACTIVATION; _body->setActivationState(WANTS_DEACTIVATION); @@ -148,19 +149,21 @@ void EntityMotionState::handleEasyChanges(uint32_t& flags) { } else { // disowned object is still moving --> start timer for ownership bid // TODO? put a delay in here proportional to distance from object? - upgradeBidPriority(VOLUNTEER_SIMULATION_PRIORITY); + computeNewBidPriority(VOLUNTEER_SIMULATION_PRIORITY); _nextBidExpiry = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS; } _loopsWithoutOwner = 0; _numInactiveUpdates = 0; } else if (isLocallyOwned()) { - // we just inherited ownership, make sure our desired priority matches what we have - upgradeBidPriority(_entity->getSimulationPriority()); + // we just received ownership, or the priority of our existing ownership has changed + computeNewBidPriority(_entity->getSimulationPriority()); } else { - // the entity is owned by someone else, so we clear _bidPriority here - // but _bidPriority may be updated to non-zero value if this object interacts with locally owned simulation - // in which case we may try to bid again - _bidPriority = 0; + // the entity is owned by someone else + // we are always willing to volunteer for nearby objects + // otherwise we zero _bidPriority here + // (it's possible _bidPriority will be promoted in subsequent frames + // when local scripts or owned simulation interact with it) + _bidPriority = (_region == workload::Region::R1) ? VOLUNTEER_SIMULATION_PRIORITY : 0; _nextBidExpiry = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS; _numInactiveUpdates = 0; } @@ -170,7 +173,7 @@ void EntityMotionState::handleEasyChanges(uint32_t& flags) { // (1) we own it but may need to change the priority OR... // (2) we don't own it but should bid (because a local script has been changing physics properties) uint8_t newPriority = isLocallyOwned() ? _entity->getSimulationOwner().getPriority() : _entity->getSimulationOwner().getPendingPriority(); - upgradeBidPriority(newPriority); + computeNewBidPriority(newPriority); // reset bid expiry so that we bid ASAP _nextBidExpiry = 0; @@ -299,7 +302,7 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) { if (_entity->getSimulatorID().isNull()) { _loopsWithoutOwner++; if (_loopsWithoutOwner > LOOPS_FOR_SIMULATION_ORPHAN && usecTimestampNow() > _nextBidExpiry) { - upgradeBidPriority(VOLUNTEER_SIMULATION_PRIORITY); + computeNewBidPriority(VOLUNTEER_SIMULATION_PRIORITY); } } } @@ -326,21 +329,26 @@ void EntityMotionState::setShape(const btCollisionShape* shape) { } bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { - // NOTE: we only get here if we think we own the simulation + // NOTE: this method is only ever called when the entity simulation is locally owned DETAILED_PROFILE_RANGE(simulation_physics, "CheckOutOfSync"); // Since we own the simulation: make sure _bidPriority is not less than current owned priority - // because: an _bidPriority of zero indicates that we should drop ownership when we have it. - upgradeBidPriority(_entity->getSimulationPriority()); + // because: a _bidPriority of zero indicates that we should drop ownership in the send. + // TODO: need to be able to detect when logic dictates we *decrease* priority + // WIP: print info whenever _bidPriority mismatches what is known to the entity + + if (_entity->dynamicDataNeedsTransmit()) { + uint8_t priority = _entity->hasActions() ? SCRIPT_GRAB_SIMULATION_PRIORITY : SCRIPT_POKE_SIMULATION_PRIORITY; + computeNewBidPriority(priority); + return true; + } + computeNewBidPriority(_entity->getSimulationPriority()); bool parentTransformSuccess; Transform localToWorld = _entity->getParentTransform(parentTransformSuccess); Transform worldToLocal; - Transform worldVelocityToLocal; if (parentTransformSuccess) { localToWorld.evalInverse(worldToLocal); - worldVelocityToLocal = worldToLocal; - worldVelocityToLocal.setTranslation(glm::vec3(0.0f)); } int numSteps = simulationStep - _lastStep; @@ -389,12 +397,6 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { } } - if (_entity->dynamicDataNeedsTransmit()) { - uint8_t priority = _entity->hasActions() ? SCRIPT_GRAB_SIMULATION_PRIORITY : SCRIPT_POKE_SIMULATION_PRIORITY; - upgradeBidPriority(priority); - return true; - } - // Else we measure the error between current and extrapolated transform (according to expected behavior // of remote EntitySimulation) and return true if the error is significant. @@ -439,6 +441,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { } bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) { + // NOTE: this method is only ever called when the entity simulation is locally owned DETAILED_PROFILE_RANGE(simulation_physics, "ShouldSend"); // NOTE: we expect _entity and _body to be valid in this context, since shouldSendUpdate() is only called // after doesNotNeedToSendUpdate() returns false and that call should return 'true' if _entity or _body are NULL. @@ -447,7 +450,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) { // this case is prevented by setting _ownershipState to UNOWNABLE in EntityMotionState::ctor assert(!(_entity->getClientOnly() && _entity->getOwningAvatarID() != Physics::getSessionUUID())); - if (_entity->dynamicDataNeedsTransmit() || _entity->queryAACubeNeedsUpdate()) { + if (_entity->dynamicDataNeedsTransmit() || (!_entity->getDynamic() && _entity->queryAACubeNeedsUpdate())) { return true; } @@ -548,10 +551,10 @@ void EntityMotionState::sendBid(OctreeEditPacketSender* packetSender, uint32_t s _lastStep = step; _nextBidExpiry = now + USECS_BETWEEN_OWNERSHIP_BIDS; - // finally: clear _bidPriority - // which will may get promoted before next bid - // or maybe we'll win simulation ownership - _bidPriority = 0; + // after sending the bid we try to clear _bidPriority + // which might get promoted again next frame (after local script or simulation interaction) + // or we might win the bid + computeNewBidPriority(0); } void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_t step) { @@ -686,7 +689,7 @@ uint8_t EntityMotionState::getSimulationPriority() const { } void EntityMotionState::slaveBidPriority() { - upgradeBidPriority(_entity->getSimulationPriority()); + computeNewBidPriority(_entity->getSimulationPriority()); } // virtual @@ -697,7 +700,7 @@ QUuid EntityMotionState::getSimulatorID() const { void EntityMotionState::bump(uint8_t priority) { assert(priority != 0); - upgradeBidPriority(glm::max(VOLUNTEER_SIMULATION_PRIORITY, --priority)); + computeNewBidPriority(glm::max(VOLUNTEER_SIMULATION_PRIORITY, --priority)); } void EntityMotionState::resetMeasuredBodyAcceleration() { @@ -776,11 +779,12 @@ void EntityMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& ma } bool EntityMotionState::shouldSendBid() { - if (_bidPriority >= glm::max(_entity->getSimulationPriority(), VOLUNTEER_SIMULATION_PRIORITY)) { + // NOTE: this method is only ever called when the entity simulation is NOT locally owned + if (_bidPriority > glm::max(_entity->getSimulationPriority(), YIELD_SIMULATION_PRIORITY)) { return true; } else { // NOTE: this 'else' case has a side-effect: it clears _bidPriority - // which may be updated next simulation step (via collision or script event) + // which might get promoted again next frame (after local script or simulation interaction) _bidPriority = 0; return false; } @@ -791,10 +795,19 @@ bool EntityMotionState::isLocallyOwned() const { } bool EntityMotionState::isLocallyOwnedOrShouldBe() const { - return (_bidPriority > VOLUNTEER_SIMULATION_PRIORITY && _bidPriority > _entity->getSimulationPriority()) || + // this method could also be called "shouldGenerateCollisionEventForLocalScripts()" + // because that is the only reason it's used + return (_bidPriority > VOLUNTEER_SIMULATION_PRIORITY && _bidPriority >= _entity->getSimulationPriority()) || _entity->getSimulatorID() == Physics::getSessionUUID(); } +void EntityMotionState::setRegion(uint8_t region) { + _region = region; + if (_region == workload::Region::R1 && _bidPriority < VOLUNTEER_SIMULATION_PRIORITY && !isLocallyOwned()) { + _bidPriority = VOLUNTEER_SIMULATION_PRIORITY; + } +} + void EntityMotionState::initForBid() { assert(_ownershipState != EntityMotionState::OwnershipState::Unownable); _ownershipState = EntityMotionState::OwnershipState::PendingBid; @@ -805,8 +818,13 @@ void EntityMotionState::initForOwned() { _ownershipState = EntityMotionState::OwnershipState::LocallyOwned; } -void EntityMotionState::upgradeBidPriority(uint8_t priority) { - _bidPriority = glm::max(_bidPriority, priority); +void EntityMotionState::computeNewBidPriority(uint8_t newPriority) { + uint8_t oldPriority = _bidPriority; + if (_region == workload::Region::R1) { + _bidPriority = glm::max(VOLUNTEER_SIMULATION_PRIORITY, glm::max(_bidPriority, newPriority)); + } else { + _bidPriority = glm::min(YIELD_SIMULATION_PRIORITY, newPriority); + } } void EntityMotionState::clearObjectVelocities() const { diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index a542c61d43..21ade734a8 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -14,6 +14,7 @@ #include #include +#include #include "ObjectMotionState.h" @@ -93,6 +94,8 @@ public: friend class PhysicalEntitySimulation; OwnershipState getOwnershipState() const { return _ownershipState; } + void setRegion(uint8_t region); + protected: void updateSendVelocities(); uint64_t getNextBidExpiry() const { return _nextBidExpiry; } @@ -102,11 +105,10 @@ protected: void updateServerPhysicsVariables(); bool remoteSimulationOutOfSync(uint32_t simulationStep); - // changes _bidPriority only if priority is larger - void upgradeBidPriority(uint8_t priority); + // computes _bidPriority using newPriority and special case rules + void computeNewBidPriority(uint8_t newPriority); - // upgradeBidPriority to value stored in _entity - void slaveBidPriority(); + void slaveBidPriority(); // computeNewBidPriority() with value stored in _entity void clearObjectVelocities() const; @@ -155,6 +157,7 @@ protected: mutable uint8_t _accelerationNearlyGravityCount; uint8_t _numInactiveUpdates { 1 }; uint8_t _bidPriority { 0 }; + uint8_t _region { workload::Region::INVALID }; bool _serverVariablesSet { false }; }; diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index c680c60c39..8e2695fbfd 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -53,7 +53,9 @@ void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) { bool canBeKinematic = region <= workload::Region::R3; if (shouldBePhysical) { EntityMotionState* motionState = static_cast(entity->getPhysicsInfo()); - if (!motionState) { + if (motionState) { + motionState->setRegion(region); + } else { _entitiesToAddToPhysics.insert(entity); } } else if (canBeKinematic && entity->isMovingRelativeToParent()) { @@ -139,6 +141,7 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { } else { _incomingChanges.insert(motionState); } + motionState->setRegion(region); } else if (shouldBePhysical) { // The intent is for this object to be in the PhysicsEngine, but it has no MotionState yet. // Perhaps it's shape has changed and it can now be added? From 003ea5ae3609d10b943e4afedb902c7377ac3566 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 30 Apr 2018 14:19:40 -0700 Subject: [PATCH 112/138] remove unused crufty debug variable --- libraries/physics/src/EntityMotionState.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index df5e16233c..199e8b3d0f 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -819,7 +819,6 @@ void EntityMotionState::initForOwned() { } void EntityMotionState::computeNewBidPriority(uint8_t newPriority) { - uint8_t oldPriority = _bidPriority; if (_region == workload::Region::R1) { _bidPriority = glm::max(VOLUNTEER_SIMULATION_PRIORITY, glm::max(_bidPriority, newPriority)); } else { From af85642ad4bd1295759e400ed7cc4820fa01125f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 2 May 2018 09:10:10 -0700 Subject: [PATCH 113/138] editorial pass on simulation ownership overview --- libraries/entities/src/SimulationOwner.h | 79 ++++++++++++------------ 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/libraries/entities/src/SimulationOwner.h b/libraries/entities/src/SimulationOwner.h index f2621e2f87..3d47b3c5dc 100644 --- a/libraries/entities/src/SimulationOwner.h +++ b/libraries/entities/src/SimulationOwner.h @@ -19,74 +19,75 @@ #include // HighFidelity uses a distributed physics simulation where multiple "participants" simulate portions -// of the same world. When portions overlap only one participant is allowed to be the authority for any -// particular object. For a simulated entity the authoritative participant is called the simulation "owner" and -// their duty is to send transform/velocity updates for the entity to the central entity-server. -// The entity-server relays updates to other participants who apply them as "state synchronization" -// to their own simulation. +// of the same domain. Even when portions overlap only one participant is allowed to be the current +// authority for any particular object's physical simulation. The authoritative participant is called the +// "simulation owner" and its duty is to send "state synchronization" (transform/velocity) updates for an +// entity to the entity-server. The entity-server relays updates to other participants who apply them to +// their own simulation. // // Participants acquire ownership by sending a "bid" to the entity-server. The bid is a properties update: -// { -// "simulationOwner": { "ownerID" : sessionID, "priority" : priority }, +// { "simulationOwner": { "ownerID" : sessionID, "priority" : priority }, // transform/velocity properties // } // -// The entity-server is the authority as to who owns what and may reject a bid. -// The rules for handling a bid are as follows: +// The entity-server is the authority as to who owns what and may reject a bid. The rules for handling a +// bid are as follows: // // (1) A bid may be refused for special ownership restrictions, but otherwise... // // (2) A bid at higher priority is accepted // -// (3) A bid at equal priority is rejected if receieved within a grace-period (200msec) -// of the last ownership transition, otherwise it is accepted +// (3) A bid at equal priority is accepted unless it was received shortly after (within 200msec) of the +// last ownership change. This to avoid rapid ownership transitions should multiple participants +// bid simultaneously. // -// (4) The current owner is the only participant allowed to clear ownership (entity-server can override). +// (4) The current owner is the only participant allowed to clear their ownership or adjust priority. // -// (5) The current owner is the only participant allowed to adjust priority (entity-server can override). -// -// (6) If an owner does not update the transform or velocities of an owned entity within some period +// (5) If an owner does not update the transform or velocities of an owned entity within some period // (5 seconds) then ownership is cleared and the entity's velocities are zeroed. This to handle // the case when an owner drops off the network. // // The priority of a participant's bid depends on how "interested" it is in the entity's motion. The rules // for bidding are as follows: // -// (7) A participant (almost) never assumes that a bid is accepted by the entity-server. It packs the -// simulation owner and priority as if they really did change but doesn't actually modify them -// locally. Thus, if the bid packet is lost the participant will re-send after some period. -// The participant only updates its knowledge of who owns what when it recieves an update from the -// entity-server. An exception is when the participant creates a moving entity: it assumes it starts -// off owning any moving entities it creates. +// (6) A participant (almost) never assumes its bid is accepted by the entity-server. It packs the +// simulation owner properties as if they really did change but doesn't actually modify them +// locally. Instead it waits to hear back from the entity-server for bid acceptance. If the entity +// remains unowned the participant will resend the bid (assuming the bid pakcet was lost). The +// exception is when the participant creates a moving entity: it assumes it starts off owning any +// moving entities it creates. // -// (8) When an unowned entity becomes active in the physics simulation the participant will -// start a timer and if the entity is still unowned after some period (0.5 seconds) -// it will bid at priority = VOLUNTEER (=2). The entity-server never grants ownership at VOLUNTEER +// (7) When an entity becomes active in the physics simulation but is not owned the participant will +// start a timer and if it is still unowned after expiry (0.5 seconds) the participant will +// bid at priority = VOLUNTEER (=2). The entity-server never grants ownership at VOLUNTEER // priority: when a VOLUNTEER bid is accepted the entity-server always promotes the priority to -// RECRUIT (VOLUNTEER + 1); this to avoid a race-condition which might rapidly transition ownership +// RECRUIT (=VOLUNTEER + 1); this to avoid a race-condition which might rapidly transition ownership // when multiple participants (with variable ping-times to the server) bid simultaneously for a // recently activated entity. // -// (9) When a participant changes an entity's transform/velocity it will bid at priority = POKE (=127) +// (8) When a participant's script changes an entity's transform/velocity the participant will bid at +// priority = POKE (=127) // -// (10) When an entity touches MyAvatar the participant it will bid at priority = POKE. +// (9) When an entity collides against MyAvatar the participant will bid at priority = POKE. // -// (11) When a participant grabs an entity it will bid at priority = GRAB (=128). +// (10) When a participant grabs an entity it will bid at priority = GRAB (=128). This to allow UserA +// to whack UserB with a "sword" without losing ownership, since UserB will bid at POKE. If UserB +// wants to contest for ownership they must also GRAB it. // -// (12) When entityA, locally owned at priority = N, collides with an unowned entityB the owner will -// also bid for entityB at priority = N-1 (or VOLUNTEER, whichever is larger). +// (11) When EntityA, locally owned at priority = N, collides with an unowned EntityB the owner will +// also bid for EntityB at priority = N-1 (or VOLUNTEER, whichever is larger). // -// (13) When an entity comes to rest and is deactivated in the physics simulation the owner will send -// an update to: clear their ownerhsip, set priority to zero, and set the object's velocities to -// zero. As per a normal bid, the owner does NOT assume that its ownership has been cleared until -// it hears from the entity-server. Thus, if the packet is lost the owner will re-send after some -// period. +// (12) When an entity comes to rest and is deactivated in the physics simulation the owner will send +// an update to: clear their ownerhsip, set priority to zero, and set the entity's velocities to +// zero. As per a normal bid, the owner does NOT assume its ownership has been cleared until +// it hears back from the entity-server. Thus, if the packet is lost the owner will re-send after +// expiry. // -// (14) When an entity's ownership priority drops below VOLUNTEER other participants may bid for it -// immediately at priority = VOLUNTEER. +// (13) When an entity is still active but the owner no longer wants to own it, the owner will drop its +// priority to YIELD (=1, below VOLUNTEER) thereby signalling to other participants to bid for it. // -// (15) When an entity is still active but the owner no longer wants to own it, it will drop its priority -// to YIELD (=1, less than VOLUNTEER) thereby signalling to other participants to bid for it. +// (14) When an entity's ownership priority drops to YIELD (=1, below VOLUNTEER) other participants may +// bid for it immediately at VOLUNTEER. // const uint8_t YIELD_SIMULATION_PRIORITY = 1; const uint8_t VOLUNTEER_SIMULATION_PRIORITY = YIELD_SIMULATION_PRIORITY + 1; From 3d16c9014f308f8b2947b4a5343828796d0eb98d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 3 May 2018 16:22:36 -0700 Subject: [PATCH 114/138] remove unowned 'dynamic' objects from kinematic integration --- .../entities/src/SimpleEntitySimulation.cpp | 97 +++++++++++++------ 1 file changed, 65 insertions(+), 32 deletions(-) diff --git a/libraries/entities/src/SimpleEntitySimulation.cpp b/libraries/entities/src/SimpleEntitySimulation.cpp index cf42e93821..3ed84035ac 100644 --- a/libraries/entities/src/SimpleEntitySimulation.cpp +++ b/libraries/entities/src/SimpleEntitySimulation.cpp @@ -53,20 +53,29 @@ void SimpleEntitySimulation::updateEntitiesInternal(uint64_t now) { } void SimpleEntitySimulation::addEntityInternal(EntityItemPointer entity) { - if (entity->isMovingRelativeToParent() && !entity->getPhysicsInfo()) { + if (entity->getSimulatorID().isNull()) { QMutexLocker lock(&_mutex); - _simpleKinematicEntities.insert(entity); - entity->setLastSimulated(usecTimestampNow()); - } - if (!entity->getSimulatorID().isNull()) { + if (entity->getDynamic()) { + // we don't allow dynamic objects to move without an owner so nothing to do here + } else if (entity->isMovingRelativeToParent()) { + SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); + if (itr != _simpleKinematicEntities.end()) { + _simpleKinematicEntities.insert(entity); + entity->setLastSimulated(usecTimestampNow()); + } + } + } else { QMutexLocker lock(&_mutex); _entitiesWithSimulationOwner.insert(entity); _nextStaleOwnershipExpiry = glm::min(_nextStaleOwnershipExpiry, entity->getSimulationOwnershipExpiry()); - } else if (entity->getDynamic() && entity->hasLocalVelocity()) { - QMutexLocker lock(&_mutex); - _entitiesThatNeedSimulationOwner.insert(entity); - uint64_t expiry = entity->getLastChangedOnServer() + MAX_OWNERLESS_PERIOD; - _nextOwnerlessExpiry = glm::min(_nextOwnerlessExpiry, expiry); + + if (entity->isMovingRelativeToParent()) { + SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); + if (itr != _simpleKinematicEntities.end()) { + _simpleKinematicEntities.insert(entity); + entity->setLastSimulated(usecTimestampNow()); + } + } } } @@ -77,32 +86,50 @@ void SimpleEntitySimulation::removeEntityInternal(EntityItemPointer entity) { } void SimpleEntitySimulation::changeEntityInternal(EntityItemPointer entity) { - { - QMutexLocker lock(&_mutex); - if (entity->isMovingRelativeToParent() && !entity->getPhysicsInfo()) { - int numKinematicEntities = _simpleKinematicEntities.size(); - _simpleKinematicEntities.insert(entity); - if (numKinematicEntities != _simpleKinematicEntities.size()) { - entity->setLastSimulated(usecTimestampNow()); + uint32_t flags = entity->getDirtyFlags(); + if ((flags & Simulation::DIRTY_SIMULATOR_ID) || (flags & Simulation::DIRTY_VELOCITIES)) { + if (entity->getSimulatorID().isNull()) { + QMutexLocker lock(&_mutex); + _entitiesWithSimulationOwner.remove(entity); + + if (entity->getDynamic()) { + // we don't allow dynamic objects to move without an owner + SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); + if (itr != _simpleKinematicEntities.end()) { + _simpleKinematicEntities.erase(itr); + } + } else if (entity->isMovingRelativeToParent()) { + SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); + if (itr != _simpleKinematicEntities.end()) { + _simpleKinematicEntities.insert(entity); + entity->setLastSimulated(usecTimestampNow()); + } + } else { + SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); + if (itr != _simpleKinematicEntities.end()) { + _simpleKinematicEntities.erase(itr); + } } } else { - _simpleKinematicEntities.remove(entity); + QMutexLocker lock(&_mutex); + _entitiesWithSimulationOwner.insert(entity); + _nextStaleOwnershipExpiry = glm::min(_nextStaleOwnershipExpiry, entity->getSimulationOwnershipExpiry()); + _entitiesThatNeedSimulationOwner.remove(entity); + + if (entity->isMovingRelativeToParent()) { + SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); + if (itr != _simpleKinematicEntities.end()) { + _simpleKinematicEntities.insert(entity); + entity->setLastSimulated(usecTimestampNow()); + } + } else { + SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); + if (itr != _simpleKinematicEntities.end()) { + _simpleKinematicEntities.erase(itr); + } + } } } - if (entity->getSimulatorID().isNull()) { - QMutexLocker lock(&_mutex); - _entitiesWithSimulationOwner.remove(entity); - if (entity->getDynamic() && entity->hasLocalVelocity()) { - _entitiesThatNeedSimulationOwner.insert(entity); - uint64_t expiry = entity->getLastChangedOnServer() + MAX_OWNERLESS_PERIOD; - _nextOwnerlessExpiry = glm::min(_nextOwnerlessExpiry, expiry); - } - } else { - QMutexLocker lock(&_mutex); - _entitiesWithSimulationOwner.insert(entity); - _nextStaleOwnershipExpiry = glm::min(_nextStaleOwnershipExpiry, entity->getSimulationOwnershipExpiry()); - _entitiesThatNeedSimulationOwner.remove(entity); - } entity->clearDirtyFlags(); } @@ -131,6 +158,12 @@ void SimpleEntitySimulation::expireStaleOwnerships(uint64_t now) { uint64_t expiry = entity->getSimulationOwnershipExpiry(); if (now > expiry) { itemItr = _entitiesWithSimulationOwner.erase(itemItr); + if (entity->getDynamic()) { + SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); + if (itr != _simpleKinematicEntities.end()) { + _simpleKinematicEntities.erase(itr); + } + } // remove ownership and dirty all the tree elements that contain the it entity->clearSimulationOwnership(); From b1fcb43246047e113d56ce2fca784a66bba6d191 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 3 May 2018 16:23:13 -0700 Subject: [PATCH 115/138] send ownership removal packet when dynamic object leaves bullet --- .../physics/src/PhysicalEntitySimulation.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index 8e2695fbfd..4f8e8342c8 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -130,7 +130,21 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { bool canBeKinematic = region <= workload::Region::R3; if (motionState) { if (!shouldBePhysical) { - // the entity should be removed from the physical simulation + if (motionState->isLocallyOwned()) { + // zero velocities by first deactivating the RigidBody + btRigidBody* body = motionState->getRigidBody(); + if (body) { + body->forceActivationState(ISLAND_SLEEPING); + motionState->updateSendVelocities(); // has side-effect of zeroing entity velocities for inactive body + } + + // send packet to remove ownership + // NOTE: this packet will NOT be resent if lost, but the good news is: + // the entity-server will eventually clear velocity and ownership for timeout + motionState->sendUpdate(_entityPacketSender, _physicsEngine->getNumSubsteps()); + } + + // remove from the physical simulation _incomingChanges.remove(motionState); _physicalObjects.remove(motionState); removeOwnershipData(motionState); From 2cf6e9007b37c17ec75784c35268a1a31c026ba1 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 16 May 2018 13:57:51 -0700 Subject: [PATCH 116/138] remove unsused data member --- libraries/physics/src/EntityMotionState.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 21ade734a8..b66f0f8e31 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -158,7 +158,6 @@ protected: uint8_t _numInactiveUpdates { 1 }; uint8_t _bidPriority { 0 }; uint8_t _region { workload::Region::INVALID }; - bool _serverVariablesSet { false }; }; #endif // hifi_EntityMotionState_h From 926014b43f445a703d3c8952b4a54bca932c32d9 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 17 May 2018 17:24:24 -0700 Subject: [PATCH 117/138] entity-server always promotes VOLUNTEER to RECRUIT --- libraries/entities/src/EntityTree.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 3ae4002760..fa5c45de70 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -360,26 +360,34 @@ bool EntityTree::updateEntity(EntityItemPointer entity, const EntityItemProperti // the sender is trying to take or continue ownership if (entity->getSimulatorID().isNull()) { // the sender is taking ownership - SimulationOwner owner = properties.getSimulationOwner(); - if (owner.getPriority() == VOLUNTEER_SIMULATION_PRIORITY) { + if (properties.getSimulationOwner().getPriority() == VOLUNTEER_SIMULATION_PRIORITY) { // the entity-server always promotes VOLUNTEER to RECRUIT to avoid ownership thrash // when dynamic objects first activate and multiple participants bid simultaneously - properties.promoteSimulationPriority(RECRUIT_SIMULATION_PRIORITY); + properties.setSimulationPriority(RECRUIT_SIMULATION_PRIORITY); } simulationBlocked = false; } else if (entity->getSimulatorID() == senderID) { // the sender is asserting ownership, maybe changing priority simulationBlocked = false; + // the entity-server always promotes VOLUNTEER to RECRUIT to avoid ownership thrash + // when dynamic objects first activate and multiple participants bid simultaneously + if (properties.getSimulationOwner().getPriority() == VOLUNTEER_SIMULATION_PRIORITY) { + properties.setSimulationPriority(RECRUIT_SIMULATION_PRIORITY); + } } else { // the sender is trying to steal ownership from another simulator // so we apply the rules for ownership change: // (1) higher priority wins - // (2) equal priority wins if ownership filter has expired except... + // (2) equal priority wins if ownership filter has expired + // (3) VOLUNTEER priority is promoted to RECRUIT uint8_t oldPriority = entity->getSimulationPriority(); uint8_t newPriority = properties.getSimulationOwner().getPriority(); if (newPriority > oldPriority || (newPriority == oldPriority && properties.getSimulationOwner().hasExpired())) { simulationBlocked = false; + if (properties.getSimulationOwner().getPriority() == VOLUNTEER_SIMULATION_PRIORITY) { + properties.setSimulationPriority(RECRUIT_SIMULATION_PRIORITY); + } } } if (!simulationBlocked) { From 00e360aff048ed2632504ac4eedc0579baa9420d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 17 May 2018 17:25:07 -0700 Subject: [PATCH 118/138] reduce sim ownership priority when releasing grab --- interface/src/AvatarBookmarks.cpp | 2 +- libraries/entities/src/EntityItem.cpp | 105 +++++++++++++---- libraries/entities/src/EntityItem.h | 25 +++- libraries/entities/src/EntityItemProperties.h | 2 +- .../entities/src/EntityScriptingInterface.cpp | 10 +- libraries/entities/src/SimulationOwner.cpp | 36 +----- libraries/entities/src/SimulationOwner.h | 9 -- libraries/physics/src/EntityMotionState.cpp | 110 ++++++++---------- libraries/physics/src/EntityMotionState.h | 7 +- 9 files changed, 160 insertions(+), 146 deletions(-) diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index 7845158a80..75c56bd6e7 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -76,7 +76,7 @@ void addAvatarEntities(const QVariantList& avatarEntities) { entity->setLastBroadcast(usecTimestampNow()); // since we're creating this object we will immediately volunteer to own its simulation - entity->flagForOwnershipBid(VOLUNTEER_SIMULATION_PRIORITY); + entity->setScriptSimulationPriority(VOLUNTEER_SIMULATION_PRIORITY); entityProperties.setLastEdited(entity->getLastEdited()); } else { qCDebug(entities) << "AvatarEntitiesBookmark failed to add new Entity to local Octree"; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 295126c2e7..875ba2b547 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -353,6 +353,10 @@ int EntityItem::expectedBytes() { return MINIMUM_HEADER_BYTES; } +const uint8_t PENDING_STATE_NOTHING = 0; +const uint8_t PENDING_STATE_TAKE = 1; +const uint8_t PENDING_STATE_RELEASE = 2; + // clients use this method to unpack FULL updates from entity-server int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) { setSourceUUID(args.sourceUUID); @@ -664,7 +668,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef // setters to ignore what the server says. filterRejection = newSimOwner.getID().isNull(); if (weOwnSimulation) { - if (newSimOwner.getID().isNull() && !_simulationOwner.pendingRelease(lastEditedFromBufferAdjusted)) { + if (newSimOwner.getID().isNull() && !pendingRelease(lastEditedFromBufferAdjusted)) { // entity-server is trying to clear our ownership (probably at our own request) // but we actually want to own it, therefore we ignore this clear event // and pretend that we own it (e.g. we assume we'll receive ownership soon) @@ -679,32 +683,53 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef // recompute weOwnSimulation for later weOwnSimulation = _simulationOwner.matchesValidID(myNodeID); } - } else if (_simulationOwner.pendingTake(now - maxPingRoundTrip)) { - // we sent a bid already but maybe before this packet was sent from the server - weOwnSimulation = true; + } else if (_pendingOwnershipState == PENDING_STATE_TAKE) { + // we're waiting to receive acceptance of a bid + // this ownership data either satisifies our bid or does not + bool bidIsSatisfied = newSimOwner.getID() == myNodeID && + (newSimOwner.getPriority() == _pendingOwnershipPriority || + (_pendingOwnershipPriority == VOLUNTEER_SIMULATION_PRIORITY && + newSimOwner.getPriority() == RECRUIT_SIMULATION_PRIORITY)); + if (newSimOwner.getID().isNull()) { - // the entity-server is trying to clear someone else's ownership + // the entity-server is clearing someone else's ownership if (!_simulationOwner.isNull()) { markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); somethingChanged = true; _simulationOwner.clearCurrentOwner(); } - } else if (newSimOwner.getID() == myNodeID) { - // the entity-server is awarding us ownership which is what we want - _simulationOwner.set(newSimOwner); + } else { + if (newSimOwner.getID() != _simulationOwner.getID()) { + markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); + } + if (_simulationOwner.set(newSimOwner)) { + // the entity-server changed ownership + somethingChanged = true; + } + } + if (bidIsSatisfied || _pendingOwnershipTimestamp < now - maxPingRoundTrip) { + // the bid has been satisfied, or it has been invalidated by data sent AFTER the bid should have been received + // in either case: accept our fate and clear pending state + _pendingOwnershipState = PENDING_STATE_NOTHING; + _pendingOwnershipPriority = 0; + } + weOwnSimulation = bidIsSatisfied || (_simulationOwner.getID() == myNodeID); + } else { + // we are not waiting to take ownership + if (newSimOwner.getID() != _simulationOwner.getID()) { + markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); + } + if (_simulationOwner.set(newSimOwner)) { + // the entity-server changed ownership... + somethingChanged = true; + if (newSimOwner.getID() == myNodeID) { + // we have recieved ownership + weOwnSimulation = true; + // accept our fate and clear pendingState (just in case) + _pendingOwnershipState = PENDING_STATE_NOTHING; + _pendingOwnershipPriority = 0; + } } - } else if (newSimOwner.matchesValidID(myNodeID) && !_simulationOwner.pendingTake(now)) { - // entity-server tells us that we have simulation ownership while we never requested this for this EntityItem, - // this could happen when the user reloads the cache and entity tree. - markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); - somethingChanged = true; - _simulationOwner.clearCurrentOwner(); - weOwnSimulation = false; - } else if (_simulationOwner.set(newSimOwner)) { - markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); - somethingChanged = true; - // recompute weOwnSimulation for later - weOwnSimulation = _simulationOwner.matchesValidID(myNodeID); } } @@ -1305,6 +1330,7 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c properties._accelerationChanged = true; } +/* void EntityItem::flagForOwnershipBid(uint8_t priority) { markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY); auto nodeList = DependencyManager::get(); @@ -1316,6 +1342,40 @@ void EntityItem::flagForOwnershipBid(uint8_t priority) { _simulationOwner.setPendingPriority(priority, usecTimestampNow()); } } +*/ + +void EntityItem::setScriptSimulationPriority(uint8_t priority) { + uint8_t newPriority = stillHasGrabActions() ? glm::max(priority, SCRIPT_GRAB_SIMULATION_PRIORITY) : priority; + if (newPriority != _scriptSimulationPriority) { + // set the dirty flag to trigger a bid or ownership update + markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY); + _scriptSimulationPriority = newPriority; + } +} + +void EntityItem::clearScriptSimulationPriority() { + // DO NOT markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY) here, because this + // is only ever called from the code that actually handles the dirty flags, and it knows best. + _scriptSimulationPriority = stillHasGrabActions() ? SCRIPT_GRAB_SIMULATION_PRIORITY : 0; +} + +void EntityItem::setPendingOwnershipPriority(uint8_t priority) { + _pendingOwnershipTimestamp = usecTimestampNow(); + _pendingOwnershipPriority = priority; + _pendingOwnershipState = (_pendingOwnershipPriority == 0) ? PENDING_STATE_RELEASE : PENDING_STATE_TAKE; +} + +bool EntityItem::pendingRelease(uint64_t timestamp) const { + return _pendingOwnershipPriority == 0 && + _pendingOwnershipState == PENDING_STATE_RELEASE && + _pendingOwnershipTimestamp >= timestamp; +} + +bool EntityItem::stillWaitingToTakeOwnership(uint64_t timestamp) const { + return _pendingOwnershipPriority > 0 && + _pendingOwnershipState == PENDING_STATE_TAKE && + _pendingOwnershipTimestamp >= timestamp; +} bool EntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = false; @@ -1941,10 +2001,6 @@ void EntityItem::clearSimulationOwnership() { } -void EntityItem::setPendingOwnershipPriority(uint8_t priority, const quint64& timestamp) { - _simulationOwner.setPendingPriority(priority, timestamp); -} - QString EntityItem::actionsToDebugString() { QString result; QVector serializedActions; @@ -2040,6 +2096,7 @@ bool EntityItem::updateAction(EntitySimulationPointer simulation, const QUuid& a } bool EntityItem::removeAction(EntitySimulationPointer simulation, const QUuid& actionID) { + // TODO: some action bool success = false; withWriteLock([&] { checkWaitingToRemove(simulation); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 3a3176e285..f7c3dab646 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -308,14 +308,21 @@ public: const SimulationOwner& getSimulationOwner() const { return _simulationOwner; } void setSimulationOwner(const QUuid& id, uint8_t priority); void setSimulationOwner(const SimulationOwner& owner); - void promoteSimulationPriority(uint8_t priority); uint8_t getSimulationPriority() const { return _simulationOwner.getPriority(); } QUuid getSimulatorID() const { return _simulationOwner.getID(); } void clearSimulationOwnership(); - void setPendingOwnershipPriority(uint8_t priority, const quint64& timestamp); - uint8_t getPendingOwnershipPriority() const { return _simulationOwner.getPendingPriority(); } - void rememberHasSimulationOwnershipBid() const; + + // TODO: move this "ScriptSimulationPriority" and "PendingOwnership" stuff into EntityMotionState + // but first would need to do some other cleanup. In the meantime these live here as "scratch space" + // to allow libs that don't know about each other to communicate. + void setScriptSimulationPriority(uint8_t priority); + void clearScriptSimulationPriority(); + uint8_t getScriptSimulationPriority() const { return _scriptSimulationPriority; } + void setPendingOwnershipPriority(uint8_t priority); + uint8_t getPendingOwnershipPriority() const { return _pendingOwnershipPriority; } + bool pendingRelease(uint64_t timestamp) const; + bool stillWaitingToTakeOwnership(uint64_t timestamp) const; // Certifiable Properties QString getItemName() const; @@ -395,7 +402,6 @@ public: void getAllTerseUpdateProperties(EntityItemProperties& properties) const; - void flagForOwnershipBid(uint8_t priority); void flagForMotionStateChange() { _flags |= Simulation::DIRTY_MOTION_TYPE; } QString actionsToDebugString(); @@ -654,6 +660,15 @@ protected: float _boundingRadius { 0.0f }; int32_t _spaceIndex { -1 }; // index to proxy in workload::Space + + // TODO: move this "scriptSimulationPriority" and "pendingOwnership" stuff into EntityMotionState + // but first would need to do some other cleanup. In the meantime these live here as "scratch space" + // to allow libs that don't know about each other to communicate. + uint64_t _pendingOwnershipTimestamp { 0 }; // timestamp of last owenership change request + uint8_t _pendingOwnershipPriority { 0 }; // priority of last ownership change request + uint8_t _pendingOwnershipState { 0 }; // TAKE or RELEASE + uint8_t _scriptSimulationPriority { 0 }; // target priority based on script operations + bool _cauterized { false }; // if true, don't draw because it would obscure 1st-person camera private: diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 38e4f0c8c0..24dba71d40 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -327,7 +327,7 @@ public: void clearSimulationOwner(); void setSimulationOwner(const QUuid& id, uint8_t priority); void setSimulationOwner(const QByteArray& data); - void promoteSimulationPriority(uint8_t priority) { _simulationOwner.promotePriority(priority); } + void setSimulationPriority(uint8_t priority) { _simulationOwner.setPriority(priority); } void setActionDataDirty() { _actionDataChanged = true; } diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 7c16214a78..1d7eebeee9 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -277,7 +277,7 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties entity->setLastBroadcast(usecTimestampNow()); // since we're creating this object we will immediately volunteer to own its simulation - entity->flagForOwnershipBid(VOLUNTEER_SIMULATION_PRIORITY); + entity->setScriptSimulationPriority(VOLUNTEER_SIMULATION_PRIORITY); propertiesWithSimID.setLastEdited(entity->getLastEdited()); } else { qCDebug(entities) << "script failed to add new Entity to local Octree"; @@ -465,7 +465,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& } else { // we make a bid for simulation ownership properties.setSimulationOwner(myNodeID, SCRIPT_POKE_SIMULATION_PRIORITY); - entity->flagForOwnershipBid(SCRIPT_POKE_SIMULATION_PRIORITY); + entity->setScriptSimulationPriority(SCRIPT_POKE_SIMULATION_PRIORITY); } } if (properties.queryAACubeRelatedPropertyChanged()) { @@ -1334,7 +1334,7 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString, } action->setIsMine(true); success = entity->addAction(simulation, action); - entity->flagForOwnershipBid(SCRIPT_GRAB_SIMULATION_PRIORITY); + entity->setScriptSimulationPriority(SCRIPT_GRAB_SIMULATION_PRIORITY); return false; // Physics will cause a packet to be sent, so don't send from here. }); if (success) { @@ -1350,7 +1350,7 @@ bool EntityScriptingInterface::updateAction(const QUuid& entityID, const QUuid& return actionWorker(entityID, [&](EntitySimulationPointer simulation, EntityItemPointer entity) { bool success = entity->updateAction(simulation, actionID, arguments); if (success) { - entity->flagForOwnershipBid(SCRIPT_GRAB_SIMULATION_PRIORITY); + entity->setScriptSimulationPriority(SCRIPT_GRAB_SIMULATION_PRIORITY); } return success; }); @@ -1364,7 +1364,7 @@ bool EntityScriptingInterface::deleteAction(const QUuid& entityID, const QUuid& success = entity->removeAction(simulation, actionID); if (success) { // reduce from grab to poke - entity->flagForOwnershipBid(SCRIPT_POKE_SIMULATION_PRIORITY); + entity->setScriptSimulationPriority(SCRIPT_POKE_SIMULATION_PRIORITY); } return false; // Physics will cause a packet to be sent, so don't send from here. }); diff --git a/libraries/entities/src/SimulationOwner.cpp b/libraries/entities/src/SimulationOwner.cpp index b312c6deb9..69fbf0ae16 100644 --- a/libraries/entities/src/SimulationOwner.cpp +++ b/libraries/entities/src/SimulationOwner.cpp @@ -16,29 +16,20 @@ #include -const uint8_t PENDING_STATE_NOTHING = 0; -const uint8_t PENDING_STATE_TAKE = 1; -const uint8_t PENDING_STATE_RELEASE = 2; - // static const int SimulationOwner::NUM_BYTES_ENCODED = NUM_BYTES_RFC4122_UUID + 1; SimulationOwner::SimulationOwner() : _id(), _expiry(0), - _pendingBidTimestamp(0), - _priority(0), - _pendingBidPriority(0), - _pendingState(PENDING_STATE_NOTHING) + _priority(0) { } SimulationOwner::SimulationOwner(const QUuid& id, uint8_t priority) : _id(id), _expiry(0), - _pendingBidTimestamp(0), - _priority(priority), - _pendingBidPriority(0) + _priority(priority) { } @@ -61,22 +52,13 @@ bool SimulationOwner::fromByteArray(const QByteArray& data) { void SimulationOwner::clear() { _id = QUuid(); _expiry = 0; - _pendingBidTimestamp = 0; _priority = 0; - _pendingBidPriority = 0; - _pendingState = PENDING_STATE_NOTHING; } void SimulationOwner::setPriority(uint8_t priority) { _priority = priority; } -void SimulationOwner::promotePriority(uint8_t priority) { - if (priority > _priority) { - _priority = priority; - } -} - bool SimulationOwner::setID(const QUuid& id) { if (_id != id) { _id = id; @@ -101,25 +83,11 @@ bool SimulationOwner::set(const SimulationOwner& owner) { return setID(owner._id) || oldPriority != _priority; } -void SimulationOwner::setPendingPriority(uint8_t priority, uint64_t timestamp) { - _pendingBidPriority = priority; - _pendingBidTimestamp = timestamp; - _pendingState = (_pendingBidPriority == 0) ? PENDING_STATE_RELEASE : PENDING_STATE_TAKE; -} - void SimulationOwner::updateExpiry() { const uint64_t OWNERSHIP_LOCKOUT_EXPIRY = 200 * USECS_PER_MSEC; _expiry = usecTimestampNow() + OWNERSHIP_LOCKOUT_EXPIRY; } -bool SimulationOwner::pendingRelease(uint64_t timestamp) { - return _pendingBidPriority == 0 && _pendingState == PENDING_STATE_RELEASE && _pendingBidTimestamp >= timestamp; -} - -bool SimulationOwner::pendingTake(uint64_t timestamp) { - return _pendingBidPriority > 0 && _pendingState == PENDING_STATE_TAKE && _pendingBidTimestamp >= timestamp; -} - void SimulationOwner::clearCurrentOwner() { _id = QUuid(); _expiry = 0; diff --git a/libraries/entities/src/SimulationOwner.h b/libraries/entities/src/SimulationOwner.h index 3d47b3c5dc..353255728c 100644 --- a/libraries/entities/src/SimulationOwner.h +++ b/libraries/entities/src/SimulationOwner.h @@ -120,24 +120,18 @@ public: void clear(); void setPriority(uint8_t priority); - void promotePriority(uint8_t priority); // return true if id is changed bool setID(const QUuid& id); bool set(const QUuid& id, uint8_t priority); bool set(const SimulationOwner& owner); - void setPendingPriority(uint8_t priority, uint64_t timestamp); bool isNull() const { return _id.isNull(); } bool matchesValidID(const QUuid& id) const { return _id == id && !_id.isNull(); } void updateExpiry(); - bool hasExpired() const { return usecTimestampNow() > _expiry; } - uint8_t getPendingPriority() const { return _pendingBidPriority; } - bool pendingRelease(uint64_t timestamp); // return true if valid pending RELEASE - bool pendingTake(uint64_t timestamp); // return true if valid pending TAKE void clearCurrentOwner(); bool operator>=(uint8_t priority) const { return _priority >= priority; } @@ -154,10 +148,7 @@ public: private: QUuid _id; // owner uint64_t _expiry; // time when ownership can transition at equal priority - uint64_t _pendingBidTimestamp; // time when pending bid was set uint8_t _priority; // priority of current owner - uint8_t _pendingBidPriority; // priority at which we'd like to own it - uint8_t _pendingState; // NOTHING, TAKE, or RELEASE }; diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 0a8f2b6f20..4ec475e48a 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -79,7 +79,6 @@ EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItemPointer // rather than pass the legit shape pointer to the ObjectMotionState ctor above. setShape(shape); - _bidPriority = _entity->getPendingOwnershipPriority(); if (_entity->getClientOnly() && _entity->getOwningAvatarID() != Physics::getSessionUUID()) { // client-only entities are always thus, so we cache this fact in _ownershipState _ownershipState = EntityMotionState::OwnershipState::Unownable; @@ -140,30 +139,21 @@ void EntityMotionState::handleEasyChanges(uint32_t& flags) { // simulation ownership has been removed if (glm::length2(_entity->getWorldVelocity()) == 0.0f) { // TODO: also check angularVelocity - // this object is coming to rest --> clear the ACTIVATION flag and _bidPriority + // this object is coming to rest flags &= ~Simulation::DIRTY_PHYSICS_ACTIVATION; _body->setActivationState(WANTS_DEACTIVATION); - _bidPriority = 0; const float ACTIVATION_EXPIRY = 3.0f; // something larger than the 2.0 hard coded in Bullet _body->setDeactivationTime(ACTIVATION_EXPIRY); } else { // disowned object is still moving --> start timer for ownership bid // TODO? put a delay in here proportional to distance from object? - computeNewBidPriority(VOLUNTEER_SIMULATION_PRIORITY); + _bumpedPriority = glm::max(_bumpedPriority, VOLUNTEER_SIMULATION_PRIORITY); _nextBidExpiry = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS; } _loopsWithoutOwner = 0; _numInactiveUpdates = 0; - } else if (isLocallyOwned()) { - // we just received ownership, or the priority of our existing ownership has changed - computeNewBidPriority(_entity->getSimulationPriority()); - } else { + } else if (!isLocallyOwned()) { // the entity is owned by someone else - // we are always willing to volunteer for nearby objects - // otherwise we zero _bidPriority here - // (it's possible _bidPriority will be promoted in subsequent frames - // when local scripts or owned simulation interact with it) - _bidPriority = (_region == workload::Region::R1) ? VOLUNTEER_SIMULATION_PRIORITY : 0; _nextBidExpiry = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS; _numInactiveUpdates = 0; } @@ -172,9 +162,6 @@ void EntityMotionState::handleEasyChanges(uint32_t& flags) { // The DIRTY_SIMULATOR_OWNERSHIP_PRIORITY bit means one of the following: // (1) we own it but may need to change the priority OR... // (2) we don't own it but should bid (because a local script has been changing physics properties) - uint8_t newPriority = isLocallyOwned() ? _entity->getSimulationOwner().getPriority() : _entity->getSimulationOwner().getPendingPriority(); - computeNewBidPriority(newPriority); - // reset bid expiry so that we bid ASAP _nextBidExpiry = 0; } @@ -302,7 +289,7 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) { if (_entity->getSimulatorID().isNull()) { _loopsWithoutOwner++; if (_loopsWithoutOwner > LOOPS_FOR_SIMULATION_ORPHAN && usecTimestampNow() > _nextBidExpiry) { - computeNewBidPriority(VOLUNTEER_SIMULATION_PRIORITY); + _bumpedPriority = glm::max(_bumpedPriority, VOLUNTEER_SIMULATION_PRIORITY); } } } @@ -338,11 +325,8 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { // WIP: print info whenever _bidPriority mismatches what is known to the entity if (_entity->dynamicDataNeedsTransmit()) { - uint8_t priority = _entity->hasActions() ? SCRIPT_GRAB_SIMULATION_PRIORITY : SCRIPT_POKE_SIMULATION_PRIORITY; - computeNewBidPriority(priority); return true; } - computeNewBidPriority(_entity->getSimulationPriority()); bool parentTransformSuccess; Transform localToWorld = _entity->getParentTransform(parentTransformSuccess); @@ -470,6 +454,7 @@ void EntityMotionState::updateSendVelocities() { if (!_body->isActive()) { // make sure all derivatives are zero clearObjectVelocities(); + // we pretend we sent the inactive update for this object _numInactiveUpdates = 1; } else { glm::vec3 gravity = _entity->getGravity(); @@ -534,10 +519,10 @@ void EntityMotionState::sendBid(OctreeEditPacketSender* packetSender, uint32_t s properties.setLastEdited(now); // we don't own the simulation for this entity yet, but we're sending a bid for it - uint8_t bidPriority = glm::max(_bidPriority, VOLUNTEER_SIMULATION_PRIORITY); - properties.setSimulationOwner(Physics::getSessionUUID(), bidPriority); - // copy _bidPriority into pendingPriority... - _entity->setPendingOwnershipPriority(_bidPriority, now); + uint8_t finalBidPriority = computeFinalBidPriority(); + _entity->clearScriptSimulationPriority(); + properties.setSimulationOwner(Physics::getSessionUUID(), finalBidPriority); + _entity->setPendingOwnershipPriority(finalBidPriority); EntityTreeElementPointer element = _entity->getElement(); EntityTreePointer tree = element ? element->getTree() : nullptr; @@ -556,10 +541,10 @@ void EntityMotionState::sendBid(OctreeEditPacketSender* packetSender, uint32_t s _lastStep = step; _nextBidExpiry = now + USECS_BETWEEN_OWNERSHIP_BIDS; - // after sending the bid we try to clear _bidPriority + // after sending a bid/update we clear _bumpedPriority // which might get promoted again next frame (after local script or simulation interaction) // or we might win the bid - computeNewBidPriority(0); + _bumpedPriority = 0; } void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_t step) { @@ -598,22 +583,26 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ properties.setLastEdited(now); _entity->setSimulationOwnershipExpiry(now + MAX_OUTGOING_SIMULATION_UPDATE_PERIOD); - if (_numInactiveUpdates > 0) { + if (_numInactiveUpdates > 0 && _entity->getScriptSimulationPriority() == 0) { // the entity is stopped and inactive so we tell the server we're clearing simulatorID // but we remember we do still own it... and rely on the server to tell us we don't properties.clearSimulationOwner(); - _bidPriority = 0; - _entity->setPendingOwnershipPriority(_bidPriority, now); - } else if (_bidPriority != _entity->getSimulationPriority()) { - // our desired priority has changed - if (_bidPriority == 0) { - // we should release ownership - properties.clearSimulationOwner(); - } else { - // we just need to change the priority - properties.setSimulationOwner(Physics::getSessionUUID(), _bidPriority); + _entity->setPendingOwnershipPriority(0); + } else { + uint8_t finalBidPriority = computeFinalBidPriority(); + _entity->clearScriptSimulationPriority(); + if (finalBidPriority != _entity->getSimulationPriority() && + !(finalBidPriority == VOLUNTEER_SIMULATION_PRIORITY && _entity->getSimulationPriority() == RECRUIT_SIMULATION_PRIORITY)) { + // our desired priority has changed + if (finalBidPriority == 0) { + // we should release ownership + properties.clearSimulationOwner(); + } else { + // we just need to change the priority + properties.setSimulationOwner(Physics::getSessionUUID(), finalBidPriority); + } + _entity->setPendingOwnershipPriority(finalBidPriority); } - _entity->setPendingOwnershipPriority(_bidPriority, now); } EntityItemID id(_entity->getID()); @@ -648,6 +637,11 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ }); _lastStep = step; + + // after sending a bid/update we clear _bumpedPriority + // which might get promoted again next frame (after local script or simulation interaction) + // or we might win the bid + _bumpedPriority = 0; } uint32_t EntityMotionState::getIncomingDirtyFlags() { @@ -694,7 +688,7 @@ uint8_t EntityMotionState::getSimulationPriority() const { } void EntityMotionState::slaveBidPriority() { - computeNewBidPriority(_entity->getSimulationPriority()); + _bumpedPriority = glm::max(_bumpedPriority, _entity->getSimulationPriority()); } // virtual @@ -705,7 +699,7 @@ QUuid EntityMotionState::getSimulatorID() const { void EntityMotionState::bump(uint8_t priority) { assert(priority != 0); - computeNewBidPriority(glm::max(VOLUNTEER_SIMULATION_PRIORITY, --priority)); + _bumpedPriority = glm::max(_bumpedPriority, --priority); } void EntityMotionState::resetMeasuredBodyAcceleration() { @@ -771,7 +765,6 @@ void EntityMotionState::setMotionType(PhysicsMotionType motionType) { resetMeasuredBodyAcceleration(); } - // virtual QString EntityMotionState::getName() const { assert(entityTreeIsLocked()); @@ -784,15 +777,14 @@ void EntityMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& ma } bool EntityMotionState::shouldSendBid() { - // NOTE: this method is only ever called when the entity simulation is NOT locally owned - if (_bidPriority > glm::max(_entity->getSimulationPriority(), YIELD_SIMULATION_PRIORITY)) { - return true; - } else { - // NOTE: this 'else' case has a side-effect: it clears _bidPriority - // which might get promoted again next frame (after local script or simulation interaction) - _bidPriority = 0; - return false; - } + // NOTE: this method is only ever called when the entity's simulation is NOT locally owned + return _body->isActive() && (_region == workload::Region::R1) && + glm::max(glm::max(VOLUNTEER_SIMULATION_PRIORITY, _bumpedPriority), _entity->getScriptSimulationPriority()) >= _entity->getSimulationPriority(); +} + +uint8_t EntityMotionState::computeFinalBidPriority() const { + return (_region == workload::Region::R1) ? + glm::max(glm::max(VOLUNTEER_SIMULATION_PRIORITY, _bumpedPriority), _entity->getScriptSimulationPriority()) : 0; } bool EntityMotionState::isLocallyOwned() const { @@ -802,15 +794,15 @@ bool EntityMotionState::isLocallyOwned() const { bool EntityMotionState::isLocallyOwnedOrShouldBe() const { // this method could also be called "shouldGenerateCollisionEventForLocalScripts()" // because that is the only reason it's used - return (_bidPriority > VOLUNTEER_SIMULATION_PRIORITY && _bidPriority >= _entity->getSimulationPriority()) || - _entity->getSimulatorID() == Physics::getSessionUUID(); + if (_entity->getSimulatorID() == Physics::getSessionUUID()) { + return true; + } else { + return computeFinalBidPriority() > glm::max(VOLUNTEER_SIMULATION_PRIORITY, _entity->getSimulationPriority()); + } } void EntityMotionState::setRegion(uint8_t region) { _region = region; - if (_region == workload::Region::R1 && _bidPriority < VOLUNTEER_SIMULATION_PRIORITY && !isLocallyOwned()) { - _bidPriority = VOLUNTEER_SIMULATION_PRIORITY; - } } void EntityMotionState::initForBid() { @@ -823,14 +815,6 @@ void EntityMotionState::initForOwned() { _ownershipState = EntityMotionState::OwnershipState::LocallyOwned; } -void EntityMotionState::computeNewBidPriority(uint8_t newPriority) { - if (_region == workload::Region::R1) { - _bidPriority = glm::max(VOLUNTEER_SIMULATION_PRIORITY, glm::max(_bidPriority, newPriority)); - } else { - _bidPriority = glm::min(YIELD_SIMULATION_PRIORITY, newPriority); - } -} - void EntityMotionState::clearObjectVelocities() const { // If transform or velocities are flagged as dirty it means a network or scripted change // occured between the beginning and end of the stepSimulation() and we DON'T want to apply diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index b66f0f8e31..877eb68d3f 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -88,6 +88,8 @@ public: virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override; bool shouldSendBid(); + uint8_t computeFinalBidPriority() const; + bool isLocallyOwned() const override; bool isLocallyOwnedOrShouldBe() const override; // aka shouldEmitCollisionEvents() @@ -105,9 +107,6 @@ protected: void updateServerPhysicsVariables(); bool remoteSimulationOutOfSync(uint32_t simulationStep); - // computes _bidPriority using newPriority and special case rules - void computeNewBidPriority(uint8_t newPriority); - void slaveBidPriority(); // computeNewBidPriority() with value stored in _entity void clearObjectVelocities() const; @@ -156,7 +155,7 @@ protected: uint8_t _loopsWithoutOwner; mutable uint8_t _accelerationNearlyGravityCount; uint8_t _numInactiveUpdates { 1 }; - uint8_t _bidPriority { 0 }; + uint8_t _bumpedPriority { 0 }; // the target simulation priority according to collision history uint8_t _region { workload::Region::INVALID }; }; From 063c2564d1c173480acde8a0a403096669560323 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 18 May 2018 10:28:45 -0700 Subject: [PATCH 119/138] only clear bid state when ownership actually changed --- libraries/entities/src/EntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 85432eb0be..60827a00dd 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -707,7 +707,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef somethingChanged = true; } } - if (bidIsSatisfied || _pendingOwnershipTimestamp < now - maxPingRoundTrip) { + if (bidIsSatisfied || (somethingChanged && _pendingOwnershipTimestamp < now - maxPingRoundTrip)) { // the bid has been satisfied, or it has been invalidated by data sent AFTER the bid should have been received // in either case: accept our fate and clear pending state _pendingOwnershipState = PENDING_STATE_NOTHING; From c8b8d0f1c42fa59051d670586ff13d9b6b9adcd1 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 18 May 2018 10:31:08 -0700 Subject: [PATCH 120/138] remove commented out cruft --- libraries/entities/src/EntityItem.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 60827a00dd..5f1ef30353 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1330,20 +1330,6 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c properties._accelerationChanged = true; } -/* -void EntityItem::flagForOwnershipBid(uint8_t priority) { - markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_PRIORITY); - auto nodeList = DependencyManager::get(); - if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) { - // we already own it - _simulationOwner.promotePriority(priority); - } else { - // we don't own it yet - _simulationOwner.setPendingPriority(priority, usecTimestampNow()); - } -} -*/ - void EntityItem::setScriptSimulationPriority(uint8_t priority) { uint8_t newPriority = stillHasGrabActions() ? glm::max(priority, SCRIPT_GRAB_SIMULATION_PRIORITY) : priority; if (newPriority != _scriptSimulationPriority) { From 84a2e5e4433bcc414247b32019a7096833dc324c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 18 May 2018 11:23:56 -0700 Subject: [PATCH 121/138] fix yeild behavior for owned things outside of R1 --- libraries/physics/src/EntityMotionState.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 5e2286e7d3..4690b11db3 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -590,19 +590,23 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ properties.clearSimulationOwner(); _entity->setPendingOwnershipPriority(0); } else { - uint8_t finalBidPriority = computeFinalBidPriority(); + uint8_t newPriority = computeFinalBidPriority(); _entity->clearScriptSimulationPriority(); - if (finalBidPriority != _entity->getSimulationPriority() && - !(finalBidPriority == VOLUNTEER_SIMULATION_PRIORITY && _entity->getSimulationPriority() == RECRUIT_SIMULATION_PRIORITY)) { + // if we get here then we own the simulation and the object is NOT going inactive + // if newPriority is zero, then it must be outside of R1, which means we should really set it to YIELD + // which we achive by just setting it to the max of the two + newPriority = glm::max(newPriority, YIELD_SIMULATION_PRIORITY); + if (newPriority != _entity->getSimulationPriority() && + !(newPriority == VOLUNTEER_SIMULATION_PRIORITY && _entity->getSimulationPriority() == RECRUIT_SIMULATION_PRIORITY)) { // our desired priority has changed - if (finalBidPriority == 0) { + if (newPriority == 0) { // we should release ownership properties.clearSimulationOwner(); } else { - // we just need to change the priority - properties.setSimulationOwner(Physics::getSessionUUID(), finalBidPriority); + // we just need to inform the entity-server + properties.setSimulationOwner(Physics::getSessionUUID(), newPriority); } - _entity->setPendingOwnershipPriority(finalBidPriority); + _entity->setPendingOwnershipPriority(newPriority); } } From c29b93b986c755b4e8735254feb394c58e16c2c9 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 23 May 2018 17:49:10 -0700 Subject: [PATCH 122/138] Merging with latest master and bringin low hanging fruits from Andrews pr --- libraries/workload/src/workload/ViewTask.cpp | 28 ++++++++++++-------- libraries/workload/src/workload/ViewTask.h | 17 +++++++----- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/libraries/workload/src/workload/ViewTask.cpp b/libraries/workload/src/workload/ViewTask.cpp index 0c3f2cc873..1f8ea883ed 100644 --- a/libraries/workload/src/workload/ViewTask.cpp +++ b/libraries/workload/src/workload/ViewTask.cpp @@ -71,9 +71,9 @@ void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& i ControlViews::ControlViews() { - regionBackFronts[0] = glm::vec2(1.0f, 3.0f); - regionBackFronts[1] = glm::vec2(1.0f, 5.0f); - regionBackFronts[2] = glm::vec2(1.0f, 10.0f); + regionBackFronts[0] = DEFAULT_R1_BACK_FRONT; + regionBackFronts[1] = DEFAULT_R2_BACK_FRONT; + regionBackFronts[2] = DEFAULT_R3_BACK_FRONT; regionRegulators[0] = Regulator(std::chrono::milliseconds(2), regionBackFronts[0], 5.0f * regionBackFronts[0], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); regionRegulators[1] = Regulator(std::chrono::milliseconds(2), regionBackFronts[1], 8.0f * regionBackFronts[1], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); regionRegulators[2] = Regulator(std::chrono::milliseconds(2), regionBackFronts[2], 10.0f * regionBackFronts[2], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); @@ -114,12 +114,15 @@ glm::vec2 Regulator::run(const Timing_ns& regulationDuration, const Timing_ns& m float coef = error_ms / std::chrono::duration(regulationDuration).count(); next += coef * (error_ms < 0.0f ? _speedDown : _speedUp); - // Clamp to min max - next = glm::clamp(next, _minRange, _maxRange); - return next; } +glm::vec2 Regulator::clamp(const glm::vec2& backFront) const { + // Clamp to min max + return glm::clamp(backFront, _minRange, _maxRange); +} + + void ControlViews::regulateViews(workload::Views& outViews, const workload::Timings& timings) { for (auto& outView : outViews) { @@ -129,9 +132,14 @@ void ControlViews::regulateViews(workload::Views& outViews, const workload::Timi } auto loopDuration = std::chrono::nanoseconds{ std::chrono::milliseconds(16) }; - _dataExport.ranges[workload::Region::R1] = regionBackFronts[workload::Region::R1] = regionRegulators[workload::Region::R1].run(loopDuration, timings[0], regionBackFronts[workload::Region::R1]); - _dataExport.ranges[workload::Region::R2] = regionBackFronts[workload::Region::R2] = regionRegulators[workload::Region::R2].run(loopDuration, timings[0], regionBackFronts[workload::Region::R2]); - _dataExport.ranges[workload::Region::R3] = regionBackFronts[workload::Region::R3] = regionRegulators[workload::Region::R3].run(loopDuration, timings[1], regionBackFronts[workload::Region::R3]); + regionBackFronts[workload::Region::R1] = regionRegulators[workload::Region::R1].clamp(regionRegulators[workload::Region::R1].run(loopDuration, timings[0], regionBackFronts[workload::Region::R1])); + regionBackFronts[workload::Region::R2] = regionRegulators[workload::Region::R2].clamp(regionRegulators[workload::Region::R2].run(loopDuration, timings[0], regionBackFronts[workload::Region::R2])); + regionBackFronts[workload::Region::R3] = regionRegulators[workload::Region::R3].clamp(regionRegulators[workload::Region::R3].run(loopDuration, timings[1], regionBackFronts[workload::Region::R3])); + + // Export data config + _dataExport.ranges[workload::Region::R1] = regionBackFronts[workload::Region::R1]; + _dataExport.ranges[workload::Region::R2] = regionBackFronts[workload::Region::R2]; + _dataExport.ranges[workload::Region::R3] = regionBackFronts[workload::Region::R3]; for (auto& outView : outViews) { outView.regionBackFronts[workload::Region::R1] = regionBackFronts[workload::Region::R1]; @@ -141,5 +149,3 @@ void ControlViews::regulateViews(workload::Views& outViews, const workload::Timi workload::View::updateRegionsFromBackFronts(outView); } } - - diff --git a/libraries/workload/src/workload/ViewTask.h b/libraries/workload/src/workload/ViewTask.h index 481d833a0b..93035503c7 100644 --- a/libraries/workload/src/workload/ViewTask.h +++ b/libraries/workload/src/workload/ViewTask.h @@ -24,6 +24,10 @@ QVariantList toVariantList(const QList &list) } namespace workload { + const glm::vec2 DEFAULT_R1_BACK_FRONT = { 50.0f, 100.0f }; + const glm::vec2 DEFAULT_R2_BACK_FRONT = { 75.0f, 150.0f }; + const glm::vec2 DEFAULT_R3_BACK_FRONT = { 100.0f, 250.0f }; + class SetupViewsConfig : public Job::Config{ Q_OBJECT Q_PROPERTY(float r1Front READ getR1Front WRITE setR1Front NOTIFY dirty) @@ -66,14 +70,14 @@ namespace workload { void setSimulateSecondaryCamera(bool use) { data.simulateSecondaryCamera = use; emit dirty(); } struct Data { - float r1Back { 2.0f }; - float r1Front { 10.0f }; + float r1Back { DEFAULT_R1_BACK_FRONT.x }; + float r1Front { DEFAULT_R1_BACK_FRONT.y }; - float r2Back{ 5.0f }; - float r2Front{ 30.0f }; + float r2Back{ DEFAULT_R2_BACK_FRONT.x }; + float r2Front{ DEFAULT_R2_BACK_FRONT.y }; - float r3Back{ 10.0f }; - float r3Front{ 100.0f }; + float r3Back{ DEFAULT_R3_BACK_FRONT.x }; + float r3Front{ DEFAULT_R3_BACK_FRONT.y }; bool freezeViews{ false }; bool useAvatarView{ false }; @@ -211,6 +215,7 @@ namespace workload { _budget(budget_ns), _minRange(minRange), _maxRange(maxRange), _speedDown(speedDown), _speedUp(speedUp) {} glm::vec2 run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current); + glm::vec2 clamp(const glm::vec2& backFront) const; }; class ControlViews { From 55ec0d3e844109ad0b929cc765951168e2a593be Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 24 May 2018 17:25:00 -0700 Subject: [PATCH 123/138] Fixing the merge conflicts and repairing the regulation values --- libraries/workload/src/workload/ViewTask.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/workload/src/workload/ViewTask.cpp b/libraries/workload/src/workload/ViewTask.cpp index 1f8ea883ed..4562f06aa9 100644 --- a/libraries/workload/src/workload/ViewTask.cpp +++ b/libraries/workload/src/workload/ViewTask.cpp @@ -71,9 +71,9 @@ void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& i ControlViews::ControlViews() { - regionBackFronts[0] = DEFAULT_R1_BACK_FRONT; - regionBackFronts[1] = DEFAULT_R2_BACK_FRONT; - regionBackFronts[2] = DEFAULT_R3_BACK_FRONT; + regionBackFronts[0] = glm::vec2(1.0f, 3.0f); + regionBackFronts[1] = glm::vec2(1.0f, 5.0f); + regionBackFronts[2] = glm::vec2(1.0f, 10.0f); regionRegulators[0] = Regulator(std::chrono::milliseconds(2), regionBackFronts[0], 5.0f * regionBackFronts[0], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); regionRegulators[1] = Regulator(std::chrono::milliseconds(2), regionBackFronts[1], 8.0f * regionBackFronts[1], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); regionRegulators[2] = Regulator(std::chrono::milliseconds(2), regionBackFronts[2], 10.0f * regionBackFronts[2], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); From 85beca6b6705cf954f0cd3e03870a8b13cfa39b6 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 May 2018 16:00:27 -0700 Subject: [PATCH 124/138] tweak to dynamic workload regions regulation --- interface/src/workload/GameWorkload.cpp | 103 ++++++++++++++++++++ interface/src/workload/GameWorkload.h | 122 ++++++++++++++++++++++++ 2 files changed, 225 insertions(+) diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 87bf093224..a7d3a9ab52 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -15,6 +15,109 @@ #include "PhysicsBoundary.h" +const glm::vec2 DEFAULT_R1_BACK_FRONT = { 50.0f, 100.0f }; +const glm::vec2 DEFAULT_R2_BACK_FRONT = { 75.0f, 150.0f }; +const glm::vec2 DEFAULT_R3_BACK_FRONT = { 100.0f, 250.0f }; + +ControlViews::ControlViews() { + regionBackFronts[0] = DEFAULT_R1_BACK_FRONT; + regionBackFronts[1] = DEFAULT_R2_BACK_FRONT; + regionBackFronts[2] = DEFAULT_R3_BACK_FRONT; + + const int32_t TIME_BUDGET_MSEC = 2; + const float MIN_BACK_FRONT_SCALE_FACTOR = 0.05f; + const float MAX_BACK_FRONT_SCALE_FACTOR = 2.0f; + const float MIN_NUM_STEPS_DOWN = 250.0f; + const float MIN_NUM_STEPS_UP = 375.0f; + + for (int32_t i = 0; i < workload::Region::NUM_VIEW_REGIONS; ++i) { + glm::vec2 minBackFront = MIN_BACK_FRONT_SCALE_FACTOR * regionBackFronts[i]; + glm::vec2 maxBackFront = MAX_BACK_FRONT_SCALE_FACTOR * regionBackFronts[i]; + glm::vec2 stepDown = (maxBackFront - minBackFront) / MIN_NUM_STEPS_DOWN; + glm::vec2 stepUp = (maxBackFront - minBackFront) / MIN_NUM_STEPS_UP; + regionRegulators[i] = Regulator(std::chrono::milliseconds(TIME_BUDGET_MSEC), minBackFront, maxBackFront, stepDown, stepUp); + } +} + +void ControlViews::configure(const Config& config) { + _data = config.data; +} + +void ControlViews::run(const workload::WorkloadContextPointer& runContext, const Input& inputs, Output& outputs) { + const auto& inViews = inputs.get0(); + const auto& inTimings = inputs.get1(); + auto& outViews = outputs; + outViews.clear(); + outViews = inViews; + + if (_data.regulateViewRanges && inTimings.size()) { + regulateViews(outViews, inTimings); + + auto config = std::static_pointer_cast(runContext->jobConfig); + config->dataExport = _dataExport; + config->emitDirty(); + } +} + +glm::vec2 Regulator::run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current) { + // Regulate next value based on current moving toward the goal budget + float error_ms = std::chrono::duration(_budget - measured).count(); + float coef = error_ms / std::chrono::duration(regulationDuration).count(); + return current + coef * (error_ms < 0.0f ? _stepDown : _stepUp); +} + +glm::vec2 Regulator::clamp(const glm::vec2& backFront) const { + return glm::clamp(backFront, _minRange, _maxRange); +} + +void ControlViews::regulateViews(workload::Views& outViews, const workload::Timings& timings) { + + for (auto& outView : outViews) { + for (int32_t r = 0; r < workload::Region::NUM_VIEW_REGIONS; r++) { + outView.regionBackFronts[r] = regionBackFronts[r]; + } + } + + auto loopDuration = std::chrono::nanoseconds{ std::chrono::milliseconds(16) }; + regionBackFronts[workload::Region::R1] = regionRegulators[workload::Region::R1].run(loopDuration, timings[0], regionBackFronts[workload::Region::R1]); + regionBackFronts[workload::Region::R2] = regionRegulators[workload::Region::R2].run(loopDuration, timings[0], regionBackFronts[workload::Region::R2]); + regionBackFronts[workload::Region::R3] = regionRegulators[workload::Region::R3].run(loopDuration, timings[1], regionBackFronts[workload::Region::R3]); + + enforceRegionContainment(); + + _dataExport.ranges[workload::Region::R1] = regionBackFronts[workload::Region::R1]; + _dataExport.ranges[workload::Region::R2] = regionBackFronts[workload::Region::R2]; + _dataExport.ranges[workload::Region::R3] = regionBackFronts[workload::Region::R3]; + + _dataExport.timings[workload::Region::R1] = std::chrono::duration(timings[0]).count(); + _dataExport.timings[workload::Region::R2] = _dataExport.timings[workload::Region::R1]; + _dataExport.timings[workload::Region::R3] = std::chrono::duration(timings[1]).count(); + + for (auto& outView : outViews) { + outView.regionBackFronts[workload::Region::R1] = regionBackFronts[workload::Region::R1]; + outView.regionBackFronts[workload::Region::R2] = regionBackFronts[workload::Region::R2]; + outView.regionBackFronts[workload::Region::R3] = regionBackFronts[workload::Region::R3]; + + workload::View::updateRegionsFromBackFronts(outView); + } +} + +void ControlViews::enforceRegionContainment() { + // inner regions should never overreach outer + // and each region should never exceed its min/max limits + const glm::vec2 MIN_REGION_GAP = { 1.0f, 2.0f }; + // enforce outside --> in + for (int32_t i = workload::Region::NUM_VIEW_REGIONS - 2; i >= 0; --i) { + int32_t j = i + 1; + regionBackFronts[i] = regionRegulators[i].clamp(glm::min(regionBackFronts[i], regionBackFronts[j] - MIN_REGION_GAP)); + } + // enforce inside --> out + for (int32_t i = 1; i < workload::Region::NUM_VIEW_REGIONS; ++i) { + int32_t j = i - 1; + regionBackFronts[i] = regionRegulators[i].clamp(glm::max(regionBackFronts[i], regionBackFronts[j] + MIN_REGION_GAP)); + } +} + class WorkloadEngineBuilder { public: public: diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index 1f835686f8..fc25e6681c 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -43,4 +43,126 @@ public: workload::EnginePointer _engine; }; +class ControlViewsConfig : public workload::Job::Config { + Q_OBJECT + Q_PROPERTY(bool regulateViewRanges READ regulateViewRanges WRITE setRegulateViewRanges NOTIFY dirty) + + Q_PROPERTY(float r1Timing READ r1Timing NOTIFY dirty) + Q_PROPERTY(float r2Timing READ r2Timing NOTIFY dirty) + Q_PROPERTY(float r3Timing READ r3Timing NOTIFY dirty) + + Q_PROPERTY(float r1RangeBack READ r1RangeBack NOTIFY dirty) + Q_PROPERTY(float r2RangeBack READ r2RangeBack NOTIFY dirty) + Q_PROPERTY(float r3RangeBack READ r3RangeBack NOTIFY dirty) + + Q_PROPERTY(float r1RangeFront READ r1RangeFront NOTIFY dirty) + Q_PROPERTY(float r2RangeFront READ r2RangeFront NOTIFY dirty) + Q_PROPERTY(float r3RangeFront READ r3RangeFront NOTIFY dirty) +/* + Q_PROPERTY(float r1MinRangeBack READ r1MinRangeBack WRITE setR1MinRangeBack NOTIFY dirty) + Q_PROPERTY(float r2MinRangeBack READ r2MinRangeBack WRITE setR2MinRangeBack NOTIFY dirty) + Q_PROPERTY(float r3MinRangeBack READ r3MinRangeBack WRITE setR3MinRangeBack NOTIFY dirty) + + Q_PROPERTY(float r1MinRangeFront READ r1MinRangeFront WRITE setR1MinRangeFront NOTIFY dirty) + Q_PROPERTY(float r2MinRangeFront READ r2MinRangeFront WRITE setR2MinRangeFront NOTIFY dirty) + Q_PROPERTY(float r3MinRangeFront READ r3MinRangeFront WRITE setR3MinRangeFront NOTIFY dirty) + + Q_PROPERTY(float r1MaxRangeBack READ r1MaxRangeBack WRITE setR1MaxRangeBack NOTIFY dirty) + Q_PROPERTY(float r2MaxRangeBack READ r2MaxRangeBack WRITE setR2MaxRangeBack NOTIFY dirty) + Q_PROPERTY(float r3MaxRangeBack READ r3MaxRangeBack WRITE setR3MaxRangeBack NOTIFY dirty) + + Q_PROPERTY(float r1MaxRangeFront READ r1MaxRangeFront WRITE setR1MaxRangeFront NOTIFY dirty) + Q_PROPERTY(float r2MaxRangeFront READ r2MaxRangeFront WRITE setR2MaxRangeFront NOTIFY dirty) + Q_PROPERTY(float r3MaxRangeFront READ r3MaxRangeFront WRITE setR3MaxRangeFront NOTIFY dirty) + + Q_PROPERTY(float r1SpeedDownBack READ r1SpeedDownBack WRITE setR1SpeedDownBack NOTIFY dirty) + Q_PROPERTY(float r2SpeedDownBack READ r2SpeedDownBack WRITE setR2SpeedDownBack NOTIFY dirty) + Q_PROPERTY(float r3SpeedDownBack READ r3SpeedDownBack WRITE setR3SpeedDownBack NOTIFY dirty) + + Q_PROPERTY(float r1SpeedDownFront READ r1SpeedDownFront WRITE setR1SpeedDownFront NOTIFY dirty) + Q_PROPERTY(float r2SpeedDownFront READ r2SpeedDownFront WRITE setR2SpeedDownFront NOTIFY dirty) + Q_PROPERTY(float r3SpeedDownFront READ r3SpeedDownFront WRITE setR3SpeedDownFront NOTIFY dirty) + + Q_PROPERTY(float r1SpeedUpBack READ r1SpeedUpBack WRITE setR1SpeedUpBack NOTIFY dirty) + Q_PROPERTY(float r2SpeedUpBack READ r2SpeedUpBack WRITE setR2SpeedUpBack NOTIFY dirty) + Q_PROPERTY(float r3SpeedUpBack READ r3SpeedUpBack WRITE setR3SpeedUpBack NOTIFY dirty) + + Q_PROPERTY(float r1SpeedUpFront READ r1SpeedUpFront WRITE setR1SpeedUpFront NOTIFY dirty) + Q_PROPERTY(float r2SpeedUpFront READ r2SpeedUpFront WRITE setR2SpeedUpFront NOTIFY dirty) + Q_PROPERTY(float r3SpeedUpFront READ r3SpeedUpFront WRITE setR3SpeedUpFront NOTIFY dirty)*/ + +public: + + bool regulateViewRanges() const { return data.regulateViewRanges; } + void setRegulateViewRanges(bool use) { data.regulateViewRanges = use; emit dirty(); } + + float r1Timing() const { return dataExport.timings[workload::Region::R1]; } + float r2Timing() const { return dataExport.timings[workload::Region::R2]; } + float r3Timing() const { return dataExport.timings[workload::Region::R3]; } + + float r1RangeBack() const { return dataExport.ranges[workload::Region::R1].x; } + float r2RangeBack() const { return dataExport.ranges[workload::Region::R2].x; } + float r3RangeBack() const { return dataExport.ranges[workload::Region::R3].x; } + + float r1RangeFront() const { return dataExport.ranges[workload::Region::R1].y; } + float r2RangeFront() const { return dataExport.ranges[workload::Region::R2].y; } + float r3RangeFront() const { return dataExport.ranges[workload::Region::R3].y; } + + struct Data { + bool regulateViewRanges{ true }; + } data; + + struct DataExport { + static const int SIZE{ workload::Region::NUM_VIEW_REGIONS }; + float timings[SIZE]; + glm::vec2 ranges[SIZE]; + } dataExport; + + void emitDirty() { emit dirty(); } +signals: + void dirty(); +}; + +struct Regulator { + using Timing_ns = std::chrono::nanoseconds; + Timing_ns _budget{ std::chrono::milliseconds(2) }; + glm::vec2 _minRange{ 2.0f, 5.0f }; + glm::vec2 _maxRange{ 50.0f, 100.0f }; + + glm::vec2 _stepDown{ 0.2f }; + glm::vec2 _stepUp{ 0.1f }; + + + Regulator() {} + Regulator(const Timing_ns& budget_ns, const glm::vec2& minRange, const glm::vec2& maxRange, const glm::vec2& stepDown, const glm::vec2& speedUp) : + _budget(budget_ns), _minRange(minRange), _maxRange(maxRange), _stepDown(stepDown), _stepUp(speedUp) {} + + glm::vec2 run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current); + glm::vec2 clamp(const glm::vec2& backFront) const; +}; + +class ControlViews { +public: + using Config = ControlViewsConfig; + using Input = workload::VaryingSet2; + using Output = workload::Views; + using JobModel = workload::Job::ModelIO; + + ControlViews(); + + void configure(const Config& config); + void run(const workload::WorkloadContextPointer& runContext, const Input& inputs, Output& outputs); + + std::array regionBackFronts; + std::array regionRegulators; + + void regulateViews(workload::Views& views, const workload::Timings& timings); + +protected: + void enforceRegionContainment(); + + Config::Data _data; + Config::DataExport _dataExport; +}; + #endif // hifi_GameWorkload_h From cd568867b2d179c1a71b8d5170f2db3cf1ed52f9 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 May 2018 16:28:18 -0700 Subject: [PATCH 125/138] disable regulation of workload views by default --- interface/src/workload/GameWorkload.cpp | 7 +++++++ interface/src/workload/GameWorkload.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index a7d3a9ab52..c609eb7bff 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -56,6 +56,13 @@ void ControlViews::run(const workload::WorkloadContextPointer& runContext, const auto config = std::static_pointer_cast(runContext->jobConfig); config->dataExport = _dataExport; config->emitDirty(); + } else { + for (auto& outView : outViews) { + outView.regionBackFronts[workload::Region::R1] = regionBackFronts[workload::Region::R1]; + outView.regionBackFronts[workload::Region::R2] = regionBackFronts[workload::Region::R2]; + outView.regionBackFronts[workload::Region::R3] = regionBackFronts[workload::Region::R3]; + workload::View::updateRegionsFromBackFronts(outView); + } } } diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index fc25e6681c..37cd0f4a2f 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -109,7 +109,7 @@ public: float r3RangeFront() const { return dataExport.ranges[workload::Region::R3].y; } struct Data { - bool regulateViewRanges{ true }; + bool regulateViewRanges{ false }; } data; struct DataExport { From 57138b5fb742487e6a73984525a05ffa3801bd90 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 29 May 2018 14:21:16 -0700 Subject: [PATCH 126/138] disable workload region regulation by default also set default region radiuses large --- interface/src/workload/GameWorkload.cpp | 110 ----------------- interface/src/workload/GameWorkload.h | 123 ------------------- libraries/workload/src/workload/View.h | 2 +- libraries/workload/src/workload/ViewTask.cpp | 47 ++++--- libraries/workload/src/workload/ViewTask.h | 48 +++++--- 5 files changed, 59 insertions(+), 271 deletions(-) diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index c609eb7bff..87bf093224 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -15,116 +15,6 @@ #include "PhysicsBoundary.h" -const glm::vec2 DEFAULT_R1_BACK_FRONT = { 50.0f, 100.0f }; -const glm::vec2 DEFAULT_R2_BACK_FRONT = { 75.0f, 150.0f }; -const glm::vec2 DEFAULT_R3_BACK_FRONT = { 100.0f, 250.0f }; - -ControlViews::ControlViews() { - regionBackFronts[0] = DEFAULT_R1_BACK_FRONT; - regionBackFronts[1] = DEFAULT_R2_BACK_FRONT; - regionBackFronts[2] = DEFAULT_R3_BACK_FRONT; - - const int32_t TIME_BUDGET_MSEC = 2; - const float MIN_BACK_FRONT_SCALE_FACTOR = 0.05f; - const float MAX_BACK_FRONT_SCALE_FACTOR = 2.0f; - const float MIN_NUM_STEPS_DOWN = 250.0f; - const float MIN_NUM_STEPS_UP = 375.0f; - - for (int32_t i = 0; i < workload::Region::NUM_VIEW_REGIONS; ++i) { - glm::vec2 minBackFront = MIN_BACK_FRONT_SCALE_FACTOR * regionBackFronts[i]; - glm::vec2 maxBackFront = MAX_BACK_FRONT_SCALE_FACTOR * regionBackFronts[i]; - glm::vec2 stepDown = (maxBackFront - minBackFront) / MIN_NUM_STEPS_DOWN; - glm::vec2 stepUp = (maxBackFront - minBackFront) / MIN_NUM_STEPS_UP; - regionRegulators[i] = Regulator(std::chrono::milliseconds(TIME_BUDGET_MSEC), minBackFront, maxBackFront, stepDown, stepUp); - } -} - -void ControlViews::configure(const Config& config) { - _data = config.data; -} - -void ControlViews::run(const workload::WorkloadContextPointer& runContext, const Input& inputs, Output& outputs) { - const auto& inViews = inputs.get0(); - const auto& inTimings = inputs.get1(); - auto& outViews = outputs; - outViews.clear(); - outViews = inViews; - - if (_data.regulateViewRanges && inTimings.size()) { - regulateViews(outViews, inTimings); - - auto config = std::static_pointer_cast(runContext->jobConfig); - config->dataExport = _dataExport; - config->emitDirty(); - } else { - for (auto& outView : outViews) { - outView.regionBackFronts[workload::Region::R1] = regionBackFronts[workload::Region::R1]; - outView.regionBackFronts[workload::Region::R2] = regionBackFronts[workload::Region::R2]; - outView.regionBackFronts[workload::Region::R3] = regionBackFronts[workload::Region::R3]; - workload::View::updateRegionsFromBackFronts(outView); - } - } -} - -glm::vec2 Regulator::run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current) { - // Regulate next value based on current moving toward the goal budget - float error_ms = std::chrono::duration(_budget - measured).count(); - float coef = error_ms / std::chrono::duration(regulationDuration).count(); - return current + coef * (error_ms < 0.0f ? _stepDown : _stepUp); -} - -glm::vec2 Regulator::clamp(const glm::vec2& backFront) const { - return glm::clamp(backFront, _minRange, _maxRange); -} - -void ControlViews::regulateViews(workload::Views& outViews, const workload::Timings& timings) { - - for (auto& outView : outViews) { - for (int32_t r = 0; r < workload::Region::NUM_VIEW_REGIONS; r++) { - outView.regionBackFronts[r] = regionBackFronts[r]; - } - } - - auto loopDuration = std::chrono::nanoseconds{ std::chrono::milliseconds(16) }; - regionBackFronts[workload::Region::R1] = regionRegulators[workload::Region::R1].run(loopDuration, timings[0], regionBackFronts[workload::Region::R1]); - regionBackFronts[workload::Region::R2] = regionRegulators[workload::Region::R2].run(loopDuration, timings[0], regionBackFronts[workload::Region::R2]); - regionBackFronts[workload::Region::R3] = regionRegulators[workload::Region::R3].run(loopDuration, timings[1], regionBackFronts[workload::Region::R3]); - - enforceRegionContainment(); - - _dataExport.ranges[workload::Region::R1] = regionBackFronts[workload::Region::R1]; - _dataExport.ranges[workload::Region::R2] = regionBackFronts[workload::Region::R2]; - _dataExport.ranges[workload::Region::R3] = regionBackFronts[workload::Region::R3]; - - _dataExport.timings[workload::Region::R1] = std::chrono::duration(timings[0]).count(); - _dataExport.timings[workload::Region::R2] = _dataExport.timings[workload::Region::R1]; - _dataExport.timings[workload::Region::R3] = std::chrono::duration(timings[1]).count(); - - for (auto& outView : outViews) { - outView.regionBackFronts[workload::Region::R1] = regionBackFronts[workload::Region::R1]; - outView.regionBackFronts[workload::Region::R2] = regionBackFronts[workload::Region::R2]; - outView.regionBackFronts[workload::Region::R3] = regionBackFronts[workload::Region::R3]; - - workload::View::updateRegionsFromBackFronts(outView); - } -} - -void ControlViews::enforceRegionContainment() { - // inner regions should never overreach outer - // and each region should never exceed its min/max limits - const glm::vec2 MIN_REGION_GAP = { 1.0f, 2.0f }; - // enforce outside --> in - for (int32_t i = workload::Region::NUM_VIEW_REGIONS - 2; i >= 0; --i) { - int32_t j = i + 1; - regionBackFronts[i] = regionRegulators[i].clamp(glm::min(regionBackFronts[i], regionBackFronts[j] - MIN_REGION_GAP)); - } - // enforce inside --> out - for (int32_t i = 1; i < workload::Region::NUM_VIEW_REGIONS; ++i) { - int32_t j = i - 1; - regionBackFronts[i] = regionRegulators[i].clamp(glm::max(regionBackFronts[i], regionBackFronts[j] + MIN_REGION_GAP)); - } -} - class WorkloadEngineBuilder { public: public: diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index 37cd0f4a2f..4b08be8a56 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -42,127 +42,4 @@ public: workload::EnginePointer _engine; }; - -class ControlViewsConfig : public workload::Job::Config { - Q_OBJECT - Q_PROPERTY(bool regulateViewRanges READ regulateViewRanges WRITE setRegulateViewRanges NOTIFY dirty) - - Q_PROPERTY(float r1Timing READ r1Timing NOTIFY dirty) - Q_PROPERTY(float r2Timing READ r2Timing NOTIFY dirty) - Q_PROPERTY(float r3Timing READ r3Timing NOTIFY dirty) - - Q_PROPERTY(float r1RangeBack READ r1RangeBack NOTIFY dirty) - Q_PROPERTY(float r2RangeBack READ r2RangeBack NOTIFY dirty) - Q_PROPERTY(float r3RangeBack READ r3RangeBack NOTIFY dirty) - - Q_PROPERTY(float r1RangeFront READ r1RangeFront NOTIFY dirty) - Q_PROPERTY(float r2RangeFront READ r2RangeFront NOTIFY dirty) - Q_PROPERTY(float r3RangeFront READ r3RangeFront NOTIFY dirty) -/* - Q_PROPERTY(float r1MinRangeBack READ r1MinRangeBack WRITE setR1MinRangeBack NOTIFY dirty) - Q_PROPERTY(float r2MinRangeBack READ r2MinRangeBack WRITE setR2MinRangeBack NOTIFY dirty) - Q_PROPERTY(float r3MinRangeBack READ r3MinRangeBack WRITE setR3MinRangeBack NOTIFY dirty) - - Q_PROPERTY(float r1MinRangeFront READ r1MinRangeFront WRITE setR1MinRangeFront NOTIFY dirty) - Q_PROPERTY(float r2MinRangeFront READ r2MinRangeFront WRITE setR2MinRangeFront NOTIFY dirty) - Q_PROPERTY(float r3MinRangeFront READ r3MinRangeFront WRITE setR3MinRangeFront NOTIFY dirty) - - Q_PROPERTY(float r1MaxRangeBack READ r1MaxRangeBack WRITE setR1MaxRangeBack NOTIFY dirty) - Q_PROPERTY(float r2MaxRangeBack READ r2MaxRangeBack WRITE setR2MaxRangeBack NOTIFY dirty) - Q_PROPERTY(float r3MaxRangeBack READ r3MaxRangeBack WRITE setR3MaxRangeBack NOTIFY dirty) - - Q_PROPERTY(float r1MaxRangeFront READ r1MaxRangeFront WRITE setR1MaxRangeFront NOTIFY dirty) - Q_PROPERTY(float r2MaxRangeFront READ r2MaxRangeFront WRITE setR2MaxRangeFront NOTIFY dirty) - Q_PROPERTY(float r3MaxRangeFront READ r3MaxRangeFront WRITE setR3MaxRangeFront NOTIFY dirty) - - Q_PROPERTY(float r1SpeedDownBack READ r1SpeedDownBack WRITE setR1SpeedDownBack NOTIFY dirty) - Q_PROPERTY(float r2SpeedDownBack READ r2SpeedDownBack WRITE setR2SpeedDownBack NOTIFY dirty) - Q_PROPERTY(float r3SpeedDownBack READ r3SpeedDownBack WRITE setR3SpeedDownBack NOTIFY dirty) - - Q_PROPERTY(float r1SpeedDownFront READ r1SpeedDownFront WRITE setR1SpeedDownFront NOTIFY dirty) - Q_PROPERTY(float r2SpeedDownFront READ r2SpeedDownFront WRITE setR2SpeedDownFront NOTIFY dirty) - Q_PROPERTY(float r3SpeedDownFront READ r3SpeedDownFront WRITE setR3SpeedDownFront NOTIFY dirty) - - Q_PROPERTY(float r1SpeedUpBack READ r1SpeedUpBack WRITE setR1SpeedUpBack NOTIFY dirty) - Q_PROPERTY(float r2SpeedUpBack READ r2SpeedUpBack WRITE setR2SpeedUpBack NOTIFY dirty) - Q_PROPERTY(float r3SpeedUpBack READ r3SpeedUpBack WRITE setR3SpeedUpBack NOTIFY dirty) - - Q_PROPERTY(float r1SpeedUpFront READ r1SpeedUpFront WRITE setR1SpeedUpFront NOTIFY dirty) - Q_PROPERTY(float r2SpeedUpFront READ r2SpeedUpFront WRITE setR2SpeedUpFront NOTIFY dirty) - Q_PROPERTY(float r3SpeedUpFront READ r3SpeedUpFront WRITE setR3SpeedUpFront NOTIFY dirty)*/ - -public: - - bool regulateViewRanges() const { return data.regulateViewRanges; } - void setRegulateViewRanges(bool use) { data.regulateViewRanges = use; emit dirty(); } - - float r1Timing() const { return dataExport.timings[workload::Region::R1]; } - float r2Timing() const { return dataExport.timings[workload::Region::R2]; } - float r3Timing() const { return dataExport.timings[workload::Region::R3]; } - - float r1RangeBack() const { return dataExport.ranges[workload::Region::R1].x; } - float r2RangeBack() const { return dataExport.ranges[workload::Region::R2].x; } - float r3RangeBack() const { return dataExport.ranges[workload::Region::R3].x; } - - float r1RangeFront() const { return dataExport.ranges[workload::Region::R1].y; } - float r2RangeFront() const { return dataExport.ranges[workload::Region::R2].y; } - float r3RangeFront() const { return dataExport.ranges[workload::Region::R3].y; } - - struct Data { - bool regulateViewRanges{ false }; - } data; - - struct DataExport { - static const int SIZE{ workload::Region::NUM_VIEW_REGIONS }; - float timings[SIZE]; - glm::vec2 ranges[SIZE]; - } dataExport; - - void emitDirty() { emit dirty(); } -signals: - void dirty(); -}; - -struct Regulator { - using Timing_ns = std::chrono::nanoseconds; - Timing_ns _budget{ std::chrono::milliseconds(2) }; - glm::vec2 _minRange{ 2.0f, 5.0f }; - glm::vec2 _maxRange{ 50.0f, 100.0f }; - - glm::vec2 _stepDown{ 0.2f }; - glm::vec2 _stepUp{ 0.1f }; - - - Regulator() {} - Regulator(const Timing_ns& budget_ns, const glm::vec2& minRange, const glm::vec2& maxRange, const glm::vec2& stepDown, const glm::vec2& speedUp) : - _budget(budget_ns), _minRange(minRange), _maxRange(maxRange), _stepDown(stepDown), _stepUp(speedUp) {} - - glm::vec2 run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current); - glm::vec2 clamp(const glm::vec2& backFront) const; -}; - -class ControlViews { -public: - using Config = ControlViewsConfig; - using Input = workload::VaryingSet2; - using Output = workload::Views; - using JobModel = workload::Job::ModelIO; - - ControlViews(); - - void configure(const Config& config); - void run(const workload::WorkloadContextPointer& runContext, const Input& inputs, Output& outputs); - - std::array regionBackFronts; - std::array regionRegulators; - - void regulateViews(workload::Views& views, const workload::Timings& timings); - -protected: - void enforceRegionContainment(); - - Config::Data _data; - Config::DataExport _dataExport; -}; - #endif // hifi_GameWorkload_h diff --git a/libraries/workload/src/workload/View.h b/libraries/workload/src/workload/View.h index fa60aaef29..972caf5101 100644 --- a/libraries/workload/src/workload/View.h +++ b/libraries/workload/src/workload/View.h @@ -41,7 +41,7 @@ public: // Fov stores the half field of view angle, and tan/cos/sin ready to go, default is fov of 90deg glm::vec4 fov_halfAngle_tan_cos_sin { glm::quarter_pi(), 1.0f, glm::root_two() * 0.5f, glm::root_two() * 0.5f}; - // Origin position + // Origin position glm::vec3 origin{ 0.0f }; // Origin radius diff --git a/libraries/workload/src/workload/ViewTask.cpp b/libraries/workload/src/workload/ViewTask.cpp index 4562f06aa9..4b77733c52 100644 --- a/libraries/workload/src/workload/ViewTask.cpp +++ b/libraries/workload/src/workload/ViewTask.cpp @@ -69,14 +69,11 @@ void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& i } - ControlViews::ControlViews() { - regionBackFronts[0] = glm::vec2(1.0f, 3.0f); - regionBackFronts[1] = glm::vec2(1.0f, 5.0f); - regionBackFronts[2] = glm::vec2(1.0f, 10.0f); - regionRegulators[0] = Regulator(std::chrono::milliseconds(2), regionBackFronts[0], 5.0f * regionBackFronts[0], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); - regionRegulators[1] = Regulator(std::chrono::milliseconds(2), regionBackFronts[1], 8.0f * regionBackFronts[1], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); - regionRegulators[2] = Regulator(std::chrono::milliseconds(2), regionBackFronts[2], 10.0f * regionBackFronts[2], glm::vec2(0.4f, 0.2f), 0.5f * glm::vec2(0.3f, 0.2f)); + for (int32_t i = 0; i < workload::Region::NUM_VIEW_REGIONS; i++) { + regionBackFronts[i] = MIN_VIEW_BACK_FRONTS[i]; + regionRegulators[i] = Regulator(std::chrono::milliseconds(2), MIN_VIEW_BACK_FRONTS[i], MAX_VIEW_BACK_FRONTS[i], glm::vec2(RELATIVE_STEP_DOWN), glm::vec2(RELATIVE_STEP_UP)); + } } void ControlViews::configure(const Config& config) { @@ -107,14 +104,10 @@ void ControlViews::run(const workload::WorkloadContextPointer& runContext, const } glm::vec2 Regulator::run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current) { - glm::vec2 next = current; - // Regulate next value based on current moving toward the goal budget float error_ms = std::chrono::duration(_budget - measured).count(); - float coef = error_ms / std::chrono::duration(regulationDuration).count(); - next += coef * (error_ms < 0.0f ? _speedDown : _speedUp); - - return next; + float coef = glm::clamp(error_ms / std::chrono::duration(regulationDuration).count(), -1.0f, 1.0f); + return current * (1.0f + coef * (error_ms < 0.0f ? _relativeStepDown : _relativeStepUp)); } glm::vec2 Regulator::clamp(const glm::vec2& backFront) const { @@ -122,21 +115,21 @@ glm::vec2 Regulator::clamp(const glm::vec2& backFront) const { return glm::clamp(backFront, _minRange, _maxRange); } - void ControlViews::regulateViews(workload::Views& outViews, const workload::Timings& timings) { for (auto& outView : outViews) { - for (int r = 0; r < workload::Region::NUM_VIEW_REGIONS; r++) { + for (int32_t r = 0; r < workload::Region::NUM_VIEW_REGIONS; r++) { outView.regionBackFronts[r] = regionBackFronts[r]; } } auto loopDuration = std::chrono::nanoseconds{ std::chrono::milliseconds(16) }; - regionBackFronts[workload::Region::R1] = regionRegulators[workload::Region::R1].clamp(regionRegulators[workload::Region::R1].run(loopDuration, timings[0], regionBackFronts[workload::Region::R1])); - regionBackFronts[workload::Region::R2] = regionRegulators[workload::Region::R2].clamp(regionRegulators[workload::Region::R2].run(loopDuration, timings[0], regionBackFronts[workload::Region::R2])); - regionBackFronts[workload::Region::R3] = regionRegulators[workload::Region::R3].clamp(regionRegulators[workload::Region::R3].run(loopDuration, timings[1], regionBackFronts[workload::Region::R3])); + regionBackFronts[workload::Region::R1] = regionRegulators[workload::Region::R1].run(loopDuration, timings[0], regionBackFronts[workload::Region::R1]); + regionBackFronts[workload::Region::R2] = regionRegulators[workload::Region::R2].run(loopDuration, timings[0], regionBackFronts[workload::Region::R2]); + regionBackFronts[workload::Region::R3] = regionRegulators[workload::Region::R3].run(loopDuration, timings[1], regionBackFronts[workload::Region::R3]); + + enforceRegionContainment(); - // Export data config _dataExport.ranges[workload::Region::R1] = regionBackFronts[workload::Region::R1]; _dataExport.ranges[workload::Region::R2] = regionBackFronts[workload::Region::R2]; _dataExport.ranges[workload::Region::R3] = regionBackFronts[workload::Region::R3]; @@ -149,3 +142,19 @@ void ControlViews::regulateViews(workload::Views& outViews, const workload::Timi workload::View::updateRegionsFromBackFronts(outView); } } + +void ControlViews::enforceRegionContainment() { + // inner regions should never overreach outer + // and each region should never exceed its min/max limits + const glm::vec2 MIN_REGION_GAP = { 1.0f, 2.0f }; + // enforce outside --> in + for (int32_t i = workload::Region::NUM_VIEW_REGIONS - 2; i >= 0; --i) { + int32_t j = i + 1; + regionBackFronts[i] = regionRegulators[i].clamp(glm::min(regionBackFronts[i], regionBackFronts[j] - MIN_REGION_GAP)); + } + // enforce inside --> out + for (int32_t i = 1; i < workload::Region::NUM_VIEW_REGIONS; ++i) { + int32_t j = i - 1; + regionBackFronts[i] = regionRegulators[i].clamp(glm::max(regionBackFronts[i], regionBackFronts[j] + MIN_REGION_GAP)); + } +} diff --git a/libraries/workload/src/workload/ViewTask.h b/libraries/workload/src/workload/ViewTask.h index 93035503c7..867f22d534 100644 --- a/libraries/workload/src/workload/ViewTask.h +++ b/libraries/workload/src/workload/ViewTask.h @@ -24,9 +24,21 @@ QVariantList toVariantList(const QList &list) } namespace workload { - const glm::vec2 DEFAULT_R1_BACK_FRONT = { 50.0f, 100.0f }; - const glm::vec2 DEFAULT_R2_BACK_FRONT = { 75.0f, 150.0f }; - const glm::vec2 DEFAULT_R3_BACK_FRONT = { 100.0f, 250.0f }; + + const std::vector MIN_VIEW_BACK_FRONTS = { + { 3.0f, 4.0f }, + { 6.0f, 8.0f }, + { 9.0f, 12.0f } + }; + + const std::vector MAX_VIEW_BACK_FRONTS = { + { 100.0f, 200.0f }, + { 150.0f, 300.0f }, + { 250.0f, 500.0f } + }; + + const float RELATIVE_STEP_DOWN = 0.05f; + const float RELATIVE_STEP_UP = 0.04f; class SetupViewsConfig : public Job::Config{ Q_OBJECT @@ -44,7 +56,6 @@ namespace workload { public: - float getR1Front() const { return data.r1Front; } float getR1Back() const { return data.r1Back; } float getR2Front() const { return data.r2Front; } @@ -70,14 +81,14 @@ namespace workload { void setSimulateSecondaryCamera(bool use) { data.simulateSecondaryCamera = use; emit dirty(); } struct Data { - float r1Back { DEFAULT_R1_BACK_FRONT.x }; - float r1Front { DEFAULT_R1_BACK_FRONT.y }; + float r1Back { MAX_VIEW_BACK_FRONTS[0].x }; + float r1Front { MAX_VIEW_BACK_FRONTS[0].y }; - float r2Back{ DEFAULT_R2_BACK_FRONT.x }; - float r2Front{ DEFAULT_R2_BACK_FRONT.y }; + float r2Back{ MAX_VIEW_BACK_FRONTS[1].x }; + float r2Front{ MAX_VIEW_BACK_FRONTS[1].y }; - float r3Back{ DEFAULT_R3_BACK_FRONT.x }; - float r3Front{ DEFAULT_R3_BACK_FRONT.y }; + float r3Back{ MAX_VIEW_BACK_FRONTS[2].x }; + float r3Front{ MAX_VIEW_BACK_FRONTS[2].y }; bool freezeViews{ false }; bool useAvatarView{ false }; @@ -181,7 +192,7 @@ namespace workload { struct Data { - bool regulateViewRanges{ true }; + bool regulateViewRanges{ false }; } data; struct DataExport { @@ -203,16 +214,16 @@ namespace workload { struct Regulator { using Timing_ns = std::chrono::nanoseconds; Timing_ns _budget{ std::chrono::milliseconds(2) }; - glm::vec2 _minRange{ 2.0f, 5.0f }; - glm::vec2 _maxRange{ 50.0f, 100.0f }; + glm::vec2 _minRange{ MIN_VIEW_BACK_FRONTS[0] }; + glm::vec2 _maxRange{ MAX_VIEW_BACK_FRONTS[0] }; - glm::vec2 _speedDown{ 0.2f }; - glm::vec2 _speedUp{ 0.1f }; + glm::vec2 _relativeStepDown{ RELATIVE_STEP_DOWN }; + glm::vec2 _relativeStepUp{ RELATIVE_STEP_UP }; Regulator() {} - Regulator(const Timing_ns& budget_ns, const glm::vec2& minRange, const glm::vec2& maxRange, const glm::vec2& speedDown, const glm::vec2& speedUp) : - _budget(budget_ns), _minRange(minRange), _maxRange(maxRange), _speedDown(speedDown), _speedUp(speedUp) {} + Regulator(const Timing_ns& budget_ns, const glm::vec2& minRange, const glm::vec2& maxRange, const glm::vec2& relativeStepDown, const glm::vec2& relativeStepUp) : + _budget(budget_ns), _minRange(minRange), _maxRange(maxRange), _relativeStepDown(relativeStepDown), _relativeStepUp(relativeStepUp) {} glm::vec2 run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current); glm::vec2 clamp(const glm::vec2& backFront) const; @@ -234,6 +245,7 @@ namespace workload { std::array regionRegulators; void regulateViews(workload::Views& views, const workload::Timings& timings); + void enforceRegionContainment(); protected: Config::Data _data; @@ -242,4 +254,4 @@ namespace workload { } // namespace workload -#endif // hifi_workload_ViewTask_h \ No newline at end of file +#endif // hifi_workload_ViewTask_h From c2f5d19ddbb70e1d8928bdf52a3b3c30a0dc898a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 31 May 2018 10:21:14 -0700 Subject: [PATCH 127/138] add TODO about optimizing character ray tracing --- libraries/physics/src/CharacterGhostObject.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/physics/src/CharacterGhostObject.cpp b/libraries/physics/src/CharacterGhostObject.cpp index a771a52384..c2f85d5a50 100755 --- a/libraries/physics/src/CharacterGhostObject.cpp +++ b/libraries/physics/src/CharacterGhostObject.cpp @@ -69,6 +69,7 @@ bool CharacterGhostObject::rayTest(const btVector3& start, const btVector3& end, CharacterRayResult& result) const { if (_world && _inWorld) { + // TODO: we need to call btGhostObject::rayTest() here to reap the benefit of btGhostObject's optimizations _world->rayTest(start, end, result); } return result.hasHit(); From 7fc75e5af0e39cf2785654f1bca7227b2494c910 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 31 May 2018 10:21:46 -0700 Subject: [PATCH 128/138] more correct comments --- libraries/workload/src/workload/Transaction.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/workload/src/workload/Transaction.h b/libraries/workload/src/workload/Transaction.h index 506e3359e6..f7041859b6 100644 --- a/libraries/workload/src/workload/Transaction.h +++ b/libraries/workload/src/workload/Transaction.h @@ -140,16 +140,16 @@ public: // This call is thread safe, can be called from anywhere to allocate a new ID ProxyID allocateID(); - // Check that the ID is valid and allocated for this space, this a threadsafe call + // Check that the ID is valid and allocated for this collection, this a threadsafe call bool isAllocatedID(const ProxyID& id) const; // THis is the total number of allocated proxies, this a threadsafe call Index getNumAllocatedProxies() const { return _IDAllocator.getNumAllocatedIndices(); } - // Enqueue transaction to the space + // Enqueue transaction to the collection void enqueueTransaction(const Transaction& transaction); - // Enqueue transaction to the space + // Enqueue transaction to the collection void enqueueTransaction(Transaction&& transaction); // Enqueue end of frame transactions boundary From feacb1829054024d04e87c424d59ed81fdc048b3 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 31 May 2018 10:22:06 -0700 Subject: [PATCH 129/138] more correct variable name and optimization --- libraries/workload/src/workload/Space.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index 40491fa21e..ada5e49ebb 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -43,14 +43,14 @@ void Space::processTransactionFrame(const Transaction& transaction) { void Space::processResets(const Transaction::Resets& transactions) { for (auto& reset : transactions) { // Access the true item - auto ProxyID = std::get<0>(reset); - auto& item = _proxies[ProxyID]; + auto proxyID = std::get<0>(reset); + auto& item = _proxies[proxyID]; // Reset the item with a new payload item.sphere = (std::get<1>(reset)); item.prevRegion = item.region = Region::UNKNOWN; - _owners[ProxyID] = (std::get<2>(reset)); + _owners[proxyID] = (std::get<2>(reset)); } } @@ -84,9 +84,9 @@ void Space::processUpdates(const Transaction::Updates& transactions) { void Space::categorizeAndGetChanges(std::vector& changes) { std::unique_lock lock(_proxiesMutex); - uint32_t numProxies = (uint32_t)_proxies.size(); + uint32_t maxID = (uint32_t)(_IDAllocator.getNumAllocatedIndices()); uint32_t numViews = (uint32_t)_views.size(); - for (uint32_t i = 0; i < numProxies; ++i) { + for (uint32_t i = 0; i < maxID; ++i) { Proxy& proxy = _proxies[i]; if (proxy.region < Region::INVALID) { glm::vec3 proxyCenter = glm::vec3(proxy.sphere); From 62df4999ef926e8a419f99b085e311f7f8388cd4 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 31 May 2018 10:22:22 -0700 Subject: [PATCH 130/138] declare method const --- libraries/physics/src/EntityMotionState.cpp | 2 +- libraries/physics/src/EntityMotionState.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 9718c636bc..a2ac78806a 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -781,7 +781,7 @@ void EntityMotionState::computeCollisionGroupAndMask(int32_t& group, int32_t& ma _entity->computeCollisionGroupAndFinalMask(group, mask); } -bool EntityMotionState::shouldSendBid() { +bool EntityMotionState::shouldSendBid() const { // NOTE: this method is only ever called when the entity's simulation is NOT locally owned return _body->isActive() && (_region == workload::Region::R1) && glm::max(glm::max(VOLUNTEER_SIMULATION_PRIORITY, _bumpedPriority), _entity->getScriptSimulationPriority()) >= _entity->getSimulationPriority(); diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 96c307a85a..c2d4f8d87e 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -87,7 +87,7 @@ public: virtual void computeCollisionGroupAndMask(int32_t& group, int32_t& mask) const override; - bool shouldSendBid(); + bool shouldSendBid() const; uint8_t computeFinalBidPriority() const; bool isLocallyOwned() const override; From addbb597fc5da5888676301574d72de206fb0fd3 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 31 May 2018 10:22:39 -0700 Subject: [PATCH 131/138] move setSpaceIndex() to cpp file for easier debugging in future --- libraries/entities/src/EntityItem.cpp | 5 +++++ libraries/entities/src/EntityItem.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index bb085796d3..ecf05d694e 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -3037,6 +3037,11 @@ void EntityItem::retrieveMarketplacePublicKey() { }); } +void EntityItem::setSpaceIndex(int32_t index) { + assert(_spaceIndex == -1); + _spaceIndex = index; +} + void EntityItem::preDelete() { } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 43a69b1761..d38366c2a0 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -505,7 +505,7 @@ public: bool getCauterized() const { return _cauterized; } float getBoundingRadius() const { return _boundingRadius; } - void setSpaceIndex(int32_t index) { assert(_spaceIndex == -1); _spaceIndex = index; } + void setSpaceIndex(int32_t index); int32_t getSpaceIndex() const { return _spaceIndex; } virtual void preDelete(); From 7e44b9b3ae282f4fac7a1c4d75c675c3a09eef2d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 31 May 2018 10:23:49 -0700 Subject: [PATCH 132/138] motionState needs correct region when adding to physics --- libraries/physics/src/PhysicalEntitySimulation.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index 0ab757df51..ab6c543b17 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -275,6 +275,9 @@ void PhysicalEntitySimulation::getObjectsToAddToPhysics(VectorOfMotionStates& re _physicalObjects.insert(motionState); result.push_back(motionState); entityItr = _entitiesToAddToPhysics.erase(entityItr); + + // make sure the motionState's region is up-to-date before it is actually added to physics + motionState->setRegion(_space->getRegion(entity->getSpaceIndex())); } else { //qWarning() << "Failed to generate new shape for entity." << entity->getName(); ++entityItr; From b23f44168dec57738dae10e9477a9422b894a4bd Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 31 May 2018 12:01:07 -0700 Subject: [PATCH 133/138] revert bad optimization --- libraries/workload/src/workload/Space.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index ada5e49ebb..27a8639f3a 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -84,9 +84,9 @@ void Space::processUpdates(const Transaction::Updates& transactions) { void Space::categorizeAndGetChanges(std::vector& changes) { std::unique_lock lock(_proxiesMutex); - uint32_t maxID = (uint32_t)(_IDAllocator.getNumAllocatedIndices()); + uint32_t numProxies = (uint32_t)_proxies.size(); uint32_t numViews = (uint32_t)_views.size(); - for (uint32_t i = 0; i < maxID; ++i) { + for (uint32_t i = 0; i < numProxies; ++i) { Proxy& proxy = _proxies[i]; if (proxy.region < Region::INVALID) { glm::vec3 proxyCenter = glm::vec3(proxy.sphere); From 8eedf83f7066c62c19f78269305b5df165c9f119 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 4 Jun 2018 15:23:31 -0700 Subject: [PATCH 134/138] increment packet version for workload logic --- libraries/networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index b69733c18d..3a593c6403 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -33,7 +33,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return static_cast(EntityVersion::CollisionMask16Bytes); + return static_cast(EntityVersion::YieldSimulationOwnership); case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::ConicalFrustums); case PacketType::AvatarIdentity: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 5203a9d178..d04d607cd3 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -236,7 +236,8 @@ enum class EntityVersion : PacketVersion { ShadowControl, MaterialData, CloneableData, - CollisionMask16Bytes + CollisionMask16Bytes, + YieldSimulationOwnership }; enum class EntityScriptCallMethodVersion : PacketVersion { From d220d437cc1bf68f6af5b39320e82263041ee5be Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 4 Jun 2018 16:39:29 -0700 Subject: [PATCH 135/138] remove payloadGetLayer() from GameWorkloadRenderer --- interface/src/workload/GameWorkloadRenderer.cpp | 4 ---- interface/src/workload/GameWorkloadRenderer.h | 5 +---- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index 9fdbe3b44d..8cf19b56dd 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -100,10 +100,6 @@ namespace render { template <> const ShapeKey shapeGetShapeKey(const GameWorkloadRenderItem::Pointer& payload) { return ShapeKey::Builder::ownPipeline(); } - template <> int payloadGetLayer(const GameWorkloadRenderItem::Pointer& payloadData) { - return render::Item::LAYER_3D_FRONT; - } - } GameWorkloadRenderItem::GameWorkloadRenderItem() : _key(render::ItemKey::Builder::opaqueShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1)) { diff --git a/interface/src/workload/GameWorkloadRenderer.h b/interface/src/workload/GameWorkloadRenderer.h index 36cb32f152..a25598821e 100644 --- a/interface/src/workload/GameWorkloadRenderer.h +++ b/interface/src/workload/GameWorkloadRenderer.h @@ -99,9 +99,6 @@ namespace render { template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload); template <> void payloadRender(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args); template <> const ShapeKey shapeGetShapeKey(const GameWorkloadRenderItem::Pointer& payload); - template <> int payloadGetLayer(const GameWorkloadRenderItem::Pointer& payloadData); - - } -#endif \ No newline at end of file +#endif From 222756371e774bae949aa1492c7ac855f1e5a6ae Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 18 Jun 2018 10:31:41 -0700 Subject: [PATCH 136/138] set max region radiuses in workload UI --- .../utilities/workload/workloadInspector.qml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/developer/utilities/workload/workloadInspector.qml b/scripts/developer/utilities/workload/workloadInspector.qml index 06d59eea16..8076f5c1c2 100644 --- a/scripts/developer/utilities/workload/workloadInspector.qml +++ b/scripts/developer/utilities/workload/workloadInspector.qml @@ -133,9 +133,9 @@ Rectangle { } Repeater { model: [ - "R1:r1Back:50.0:0.0", - "R2:r2Back:50.0:0.0", - "R3:r3Back:50.0:0.0" + "R1:r1Back:250.0:0.0", + "R2:r2Back:250.0:0.0", + "R3:r3Back:250.0:0.0" ] ConfigSlider { label: qsTr(modelData.split(":")[0]) @@ -160,9 +160,9 @@ Rectangle { } Repeater { model: [ - "r1Front:300:1.0", - "r2Front:300:1.0", - "r3Front:300:1.0" + "r1Front:500:1.0", + "r2Front:500:1.0", + "r3Front:500:1.0" ] ConfigSlider { showLabel: false From 44c3620b6e54efbbb5877bfeaa5ec399cd4cb53a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 18 Jun 2018 17:45:58 -0700 Subject: [PATCH 137/138] remove cruft --- interface/src/Application.cpp | 2 - interface/src/workload/GameWorkload.cpp | 1 - interface/src/workload/PhysicsBoundary.cpp | 1 - libraries/entities/src/EntityItem.h | 1 - libraries/physics/src/PhysicsEngine.cpp | 2 - .../render-utils/src/drawWorkloadProxy.slv | 1 - .../workload/src/workload/SpaceClassifier.h | 4 +- .../workload/src/workload/Transaction.cpp | 71 ------------------- libraries/workload/src/workload/Transaction.h | 2 - 9 files changed, 2 insertions(+), 83 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0c45e1609b..3732d2cfd1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4533,8 +4533,6 @@ void Application::idle() { } { - // workload::Timings timings(1, PerformanceTimer::getTimerRecord("/idle/update/simulation").getAverage()); - // _gameWorkload.updateSimulationTimings(timings); _gameWorkload.updateViews(_viewFrustum, getMyAvatar()->getHeadPosition()); _gameWorkload._engine->run(); } diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 87bf093224..afbd166c89 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -16,7 +16,6 @@ #include "PhysicsBoundary.h" class WorkloadEngineBuilder { -public: public: using Inputs = workload::VaryingSet2; using Outputs = workload::RegionTracker::Outputs; diff --git a/interface/src/workload/PhysicsBoundary.cpp b/interface/src/workload/PhysicsBoundary.cpp index f239eeb78f..927121ac04 100644 --- a/interface/src/workload/PhysicsBoundary.cpp +++ b/interface/src/workload/PhysicsBoundary.cpp @@ -28,7 +28,6 @@ void PhysicsBoundary::run(const workload::WorkloadContextPointer& context, const auto entity = space->getOwner(change.proxyId).get(); if (entity) { simulation->changeEntity(entity); - // qCDebug(physics) << change.proxyId << " : " << "'" << entity->getName() << "' " << (uint32_t)(change.prevRegion) << " --> " << (uint32_t)(change.region); } } } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index d815edbfca..a9dc617a6c 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -492,7 +492,6 @@ public: virtual bool getMeshes(MeshProxyList& result) { return true; } virtual void locationChanged(bool tellPhysics = true) override; - //void wtf(int32_t i) override; virtual bool getScalesWithParent() const override; diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 070a5d4b3d..ee87cab8e8 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -77,7 +77,6 @@ uint32_t PhysicsEngine::getNumSubsteps() const { // private void PhysicsEngine::addObjectToDynamicsWorld(ObjectMotionState* motionState) { - // qCDebug(physics) << "templog addObject" << (void*)(motionState); // TODO: remove this assert(motionState); btVector3 inertia(0.0f, 0.0f, 0.0f); @@ -203,7 +202,6 @@ void PhysicsEngine::removeObjects(const VectorOfMotionStates& objects) { for (auto object : objects) { btRigidBody* body = object->getRigidBody(); if (body) { - // qCDebug(physics) << "removeObject" << (void*)(body->getMotionState()); // TODO: remove this removeDynamicsForBody(body); _dynamicsWorld->removeRigidBody(body); diff --git a/libraries/render-utils/src/drawWorkloadProxy.slv b/libraries/render-utils/src/drawWorkloadProxy.slv index 08e30677e5..64fb335fd6 100644 --- a/libraries/render-utils/src/drawWorkloadProxy.slv +++ b/libraries/render-utils/src/drawWorkloadProxy.slv @@ -77,7 +77,6 @@ void main(void) { vec3 dirZ = -normalize(proxyPosEye.xyz); vec3 dirX = normalize(cross(vec3(0.0, 1.0, 0.0), dirZ)); vec3 dirY = vec3(0.0, 1.0, 0.0); - // vec3 dirY = normalize(cross(dirZ, vec3(1.0, 0.0, 0.0))); vec4 pos = vec4(proxyPosEye.xyz + proxy.sphere.w * ( dirX * spriteVert.x + dirY * spriteVert.y /* + dirZ * spriteVert.z*/), 1.0); varTexcoord = spriteVert.xyz; diff --git a/libraries/workload/src/workload/SpaceClassifier.h b/libraries/workload/src/workload/SpaceClassifier.h index 06ddaee520..b6231a91ff 100644 --- a/libraries/workload/src/workload/SpaceClassifier.h +++ b/libraries/workload/src/workload/SpaceClassifier.h @@ -27,8 +27,8 @@ namespace workload { class PerformSpaceTransactionConfig : public Job::Config { Q_OBJECT public: - signals : - void dirty(); + signals : + void dirty(); protected: }; diff --git a/libraries/workload/src/workload/Transaction.cpp b/libraries/workload/src/workload/Transaction.cpp index 7dc7e7a3d2..31c28cdf22 100644 --- a/libraries/workload/src/workload/Transaction.cpp +++ b/libraries/workload/src/workload/Transaction.cpp @@ -106,7 +106,6 @@ void Transaction::clear() { Collection::Collection() { - //_items.push_back(Item()); // add the ProxyID #0 to nothing } Collection::~Collection() { @@ -165,73 +164,3 @@ void Collection::processTransactionQueue() { queuedFrames.clear(); } - -//void Collection::processTransactionFrame(const Transaction& transaction) { - /** - std::unique_lock lock(_itemsMutex); - // Here we should be able to check the value of last ProxyID allocated - // and allocate new items accordingly - ProxyID maxID = _IDAllocator.getNumAllocatedIndices(); - if (maxID > _items.size()) { - _items.resize(maxID + 100); // allocate the maxId and more - } - // Now we know for sure that we have enough items in the array to - // capture anything coming from the transaction - - // resets and potential NEW items - resetItems(transaction._resetItems); - - // Update the numItemsAtomic counter AFTER the reset changes went through - _numAllocatedItems.exchange(maxID); - - // updates - updateItems(transaction._updatedItems); - - // removes - removeItems(transaction._removedItems); - - // add transitions - transitionItems(transaction._addedTransitions); - reApplyTransitions(transaction._reAppliedTransitions); - queryTransitionItems(transaction._queriedTransitions); - - // Update the numItemsAtomic counter AFTER the pending changes went through - _numAllocatedItems.exchange(maxID); - }*/ -//} - -//void Collection::resetItems(const Transaction::Resets& transactions) { - /* for (auto& reset : transactions) { - // Access the true item - auto ProxyID = std::get<0>(reset); - auto& item = _items[ProxyID]; - - // Reset the item with a new payload - item.resetPayload(std::get<1>(reset)); - }*/ -//} - -//void Collection::removeItems(const Transaction::Removes& transactions) { - /* for (auto removedID : transactions) { - // Access the true item - auto& item = _items[removedID]; - - // Kill it - item.kill(); - }*/ -//} - -//void Collection::updateItems(const Transaction::Updates& transactions) { - /* for (auto& update : transactions) { - auto updateID = std::get<0>(update); - if (updateID == Item::INVALID_ITEM_ID) { - continue; - } - - // Access the true item - auto& item = _items[updateID]; - - // Update the item - item.update(std::get<1>(update)); - }*/ -//} diff --git a/libraries/workload/src/workload/Transaction.h b/libraries/workload/src/workload/Transaction.h index f7041859b6..39dbf65c29 100644 --- a/libraries/workload/src/workload/Transaction.h +++ b/libraries/workload/src/workload/Transaction.h @@ -163,8 +163,6 @@ protected: // Thread safe elements that can be accessed from anywhere indexed_container::Allocator<> _IDAllocator; - //std::atomic _IDAllocator{ 1 }; // first valid itemID will be One - //std::atomic _numAllocatedItems{ 1 }; // num of allocated items, matching the _items.size() std::mutex _transactionQueueMutex; TransactionQueue _transactionQueue; From 92e98438d32b287251f5d99b5cf39bf95be543a0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 19 Jun 2018 16:22:10 -0700 Subject: [PATCH 138/138] remove cruft --- libraries/workload/src/workload/Transaction.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/workload/src/workload/Transaction.h b/libraries/workload/src/workload/Transaction.h index 39dbf65c29..aa2a427127 100644 --- a/libraries/workload/src/workload/Transaction.h +++ b/libraries/workload/src/workload/Transaction.h @@ -55,6 +55,7 @@ namespace workload { _nextNewIndex++; return index; } else { + // TODO: sort _freeIndices when neccessary to help keep used allocated indices more tightly packed Index index = _freeIndices.back(); _freeIndices.pop_back(); return index; @@ -64,7 +65,6 @@ namespace workload { void freeIndex(Index index) { if (checkIndex(index)) { _freeIndices.push_back(index); - //std::sort(_freeIndices.begin(), _freeIndices.end()); } }