From e109101accf73420c0bf6aaccdec99f43061906a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 13 Oct 2017 14:55:12 -0700 Subject: [PATCH 1/7] update profiling timers --- interface/src/Application.cpp | 39 +++++++++++-------- .../src/EntityTreeRenderer.cpp | 25 ++++++------ .../src/RenderableEntityItem.cpp | 2 + .../src/RenderableModelEntityItem.cpp | 37 +++++++++++------- libraries/entities/src/EntitySimulation.cpp | 16 ++++++-- libraries/entities/src/EntityTree.cpp | 5 ++- 6 files changed, 76 insertions(+), 48 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e5d5e696a1..9170b1eddd 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2383,8 +2383,8 @@ void Application::initializeUi() { } void Application::updateCamera(RenderArgs& renderArgs) { - PROFILE_RANGE(render, "/updateCamera"); - PerformanceTimer perfTimer("CameraUpdates"); + PROFILE_RANGE(render, __FUNCTION__); + PerformanceTimer perfTimer("updateCamera"); glm::vec3 boomOffset; auto myAvatar = getMyAvatar(); @@ -2600,7 +2600,7 @@ void Application::resizeGL() { } void Application::handleSandboxStatus(QNetworkReply* reply) { - PROFILE_RANGE(render, "HandleSandboxStatus"); + PROFILE_RANGE(render, __FUNCTION__); bool sandboxIsRunning = SandboxUtils::readStatus(reply->readAll()); qDebug() << "HandleSandboxStatus" << sandboxIsRunning; @@ -4595,7 +4595,6 @@ void Application::updateDialogs(float deltaTime) const { static bool domainLoadingInProgress = false; void Application::update(float deltaTime) { - PROFILE_RANGE_EX(app, __FUNCTION__, 0xffff0000, (uint64_t)_renderFrameCount + 1); if (!_physicsEnabled) { @@ -4790,11 +4789,11 @@ void Application::update(float deltaTime) { QSharedPointer avatarManager = DependencyManager::get(); { - PROFILE_RANGE_EX(simulation_physics, "Physics", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount()); + PROFILE_RANGE(simulation_physics, "Physics"); PerformanceTimer perfTimer("physics"); if (_physicsEnabled) { { - PROFILE_RANGE_EX(simulation_physics, "UpdateStates", 0xffffff00, (uint64_t)getActiveDisplayPlugin()->presentCount()); + PROFILE_RANGE(simulation_physics, "PreStep"); PerformanceTimer perfTimer("updateStates)"); static VectorOfMotionStates motionStates; @@ -4828,14 +4827,14 @@ void Application::update(float deltaTime) { }); } { - PROFILE_RANGE_EX(simulation_physics, "StepSimulation", 0xffff8000, (uint64_t)getActiveDisplayPlugin()->presentCount()); + PROFILE_RANGE(simulation_physics, "Step"); PerformanceTimer perfTimer("stepSimulation"); getEntities()->getTree()->withWriteLock([&] { _physicsEngine->stepSimulation(); }); } { - PROFILE_RANGE_EX(simulation_physics, "HarvestChanges", 0xffffff00, (uint64_t)getActiveDisplayPlugin()->presentCount()); + PROFILE_RANGE(simulation_physics, "PostStep"); PerformanceTimer perfTimer("harvestChanges"); if (_physicsEngine->hasOutgoingChanges()) { // grab the collision events BEFORE handleOutgoingChanges() because at this point @@ -4843,6 +4842,7 @@ void Application::update(float deltaTime) { auto& collisionEvents = _physicsEngine->getCollisionEvents(); getEntities()->getTree()->withWriteLock([&] { + PROFILE_RANGE(simulation_physics, "Harvest"); PerformanceTimer perfTimer("handleOutgoingChanges"); const VectorOfMotionStates& outgoingChanges = _physicsEngine->getChangedMotionStates(); @@ -4855,18 +4855,25 @@ void Application::update(float deltaTime) { if (!_aboutToQuit) { // handleCollisionEvents() AFTER handleOutgoinChanges() - PerformanceTimer perfTimer("entities"); - avatarManager->handleCollisionEvents(collisionEvents); - // Collision events (and their scripts) must not be handled when we're locked, above. (That would risk - // deadlock.) - _entitySimulation->handleCollisionEvents(collisionEvents); + { + PROFILE_RANGE(simulation_physics, "CollisionEvents"); + PerformanceTimer perfTimer("entities"); + avatarManager->handleCollisionEvents(collisionEvents); + // Collision events (and their scripts) must not be handled when we're locked, above. (That would risk + // deadlock.) + _entitySimulation->handleCollisionEvents(collisionEvents); + } + PROFILE_RANGE(simulation_physics, "UpdateEntities"); // NOTE: the getEntities()->update() call below will wait for lock // and will simulate entity motion (the EntityTree has been given an EntitySimulation). getEntities()->update(true); // update the models... } - myAvatar->harvestResultsFromPhysicsSimulation(deltaTime); + { + PROFILE_RANGE(simulation_physics, "MyAvatar"); + myAvatar->harvestResultsFromPhysicsSimulation(deltaTime); + } if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails) && Menu::getInstance()->isOptionChecked(MenuOption::ExpandPhysicsSimulationTiming)) { @@ -4885,13 +4892,13 @@ void Application::update(float deltaTime) { // AvatarManager update { { + PROFILE_RANGE(simulation, "OtherAvatars"); PerformanceTimer perfTimer("otherAvatars"); - PROFILE_RANGE_EX(simulation, "OtherAvatars", 0xffff00ff, (uint64_t)getActiveDisplayPlugin()->presentCount()); avatarManager->updateOtherAvatars(deltaTime); } { - PROFILE_RANGE_EX(simulation, "MyAvatar", 0xffff00ff, (uint64_t)getActiveDisplayPlugin()->presentCount()); + PROFILE_RANGE(simulation, "MyAvatar"); PerformanceTimer perfTimer("MyAvatar"); qApp->updateMyAvatarLookAtPosition(); avatarManager->updateMyAvatar(deltaTime); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 85916baf60..4238eb4050 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -160,6 +160,8 @@ void EntityTreeRenderer::shutdown() { } void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, render::Transaction& transaction) { + PROFILE_RANGE_EX(simulation_physics, "Add", 0xffff00ff, (uint64_t)_entitiesToAdd.size()); + PerformanceTimer pt("add"); // Clear any expired entities // FIXME should be able to use std::remove_if, but it fails due to some // weird compilation error related to EntityItemID assignment operators @@ -203,6 +205,8 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r } void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene, render::Transaction& transaction) { + PROFILE_RANGE_EX(simulation_physics, "Change", 0xffff00ff, (uint64_t)_changedEntities.size()); + PerformanceTimer pt("change"); std::unordered_set changedEntities; _changedEntitiesGuard.withWriteLock([&] { #if 0 @@ -223,6 +227,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene } if (!_renderablesToUpdate.empty()) { + PROFILE_RANGE_EX(simulation_physics, "UpdateRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size()); for (const auto& entry : _renderablesToUpdate) { const auto& renderable = entry.second; renderable->updateInScene(scene, transaction); @@ -232,6 +237,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene } void EntityTreeRenderer::update(bool simulate) { + PROFILE_RANGE(simulation_physics, "ETR::update"); PerformanceTimer perfTimer("ETRupdate"); if (_tree && !_shuttingDown) { EntityTreePointer tree = std::static_pointer_cast(_tree); @@ -239,22 +245,14 @@ void EntityTreeRenderer::update(bool simulate) { // Update the rendereable entities as needed { + PROFILE_RANGE(simulation_physics, "Scene"); PerformanceTimer sceneTimer("scene"); auto scene = _viewState->getMain3DScene(); if (scene) { render::Transaction transaction; - { - PerformanceTimer pt("add"); - addPendingEntities(scene, transaction); - } - { - PerformanceTimer pt("change"); - updateChangedEntities(scene, transaction); - } - { - PerformanceTimer pt("enqueue"); - scene->enqueueTransaction(transaction); - } + addPendingEntities(scene, transaction); + updateChangedEntities(scene, transaction); + scene->enqueueTransaction(transaction); } } @@ -336,7 +334,8 @@ bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QVectorsetRotation(getRotation()); model->setTranslation(getPosition()); { - PerformanceTimer perfTimer("model->simulate"); model->simulate(0.0f); } _needsInitialSimulation = false; @@ -138,6 +138,7 @@ void RenderableModelEntityItem::autoResizeJointArrays() { } bool RenderableModelEntityItem::needsUpdateModelBounds() const { + PROFILE_RANGE(simulation_physics, __FUNCTION__); ModelPointer model = getModel(); if (!hasModel() || !model) { return false; @@ -182,6 +183,7 @@ bool RenderableModelEntityItem::needsUpdateModelBounds() const { } void RenderableModelEntityItem::updateModelBounds() { + PROFILE_RANGE(simulation_physics, "updateModelBounds"); if (needsUpdateModelBounds()) { doInitialModelSimulation(); _needsJointSimulation = false; @@ -1124,6 +1126,7 @@ bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin } void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { + PROFILE_RANGE(simulation_physics, __FUNCTION__); if (_hasModel != entity->hasModel()) { _hasModel = entity->hasModel(); } @@ -1213,12 +1216,14 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce model->setVisibleInScene(_visible, scene); } - //entity->doInitialModelSimulation(); - if (model->needsFixupInScene()) { - model->removeFromScene(scene, transaction); - render::Item::Status::Getters statusGetters; - makeStatusGetters(entity, statusGetters); - model->addToScene(scene, transaction, statusGetters); + { + PROFILE_RANGE(simulation_physics, "Fixup"); + if (model->needsFixupInScene()) { + model->removeFromScene(scene, transaction); + render::Item::Status::Getters statusGetters; + makeStatusGetters(entity, statusGetters); + model->addToScene(scene, transaction, statusGetters); + } } // When the individual mesh parts of a model finish fading, they will mark their Model as needing updating @@ -1227,16 +1232,20 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce model->updateRenderItems(); } - // make a copy of the animation properites - auto newAnimationProperties = entity->getAnimationProperties(); - if (newAnimationProperties != _renderAnimationProperties) { - withWriteLock([&] { - _renderAnimationProperties = newAnimationProperties; - _currentFrame = _renderAnimationProperties.getCurrentFrame(); - }); + { + PROFILE_RANGE(simulation_physics, "CheckAnimation"); + // make a copy of the animation properites + auto newAnimationProperties = entity->getAnimationProperties(); + if (newAnimationProperties != _renderAnimationProperties) { + withWriteLock([&] { + _renderAnimationProperties = newAnimationProperties; + _currentFrame = _renderAnimationProperties.getCurrentFrame(); + }); + } } if (_animating) { + PROFILE_RANGE(simulation_physics, "Animate"); if (!jointsMapped()) { mapJoints(entity, model->getJointNames()); } diff --git a/libraries/entities/src/EntitySimulation.cpp b/libraries/entities/src/EntitySimulation.cpp index 2e330fdcc5..f91d728d78 100644 --- a/libraries/entities/src/EntitySimulation.cpp +++ b/libraries/entities/src/EntitySimulation.cpp @@ -9,9 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include "EntitySimulation.h" + +#include +#include + #include "EntitiesLogging.h" #include "MovingEntitiesOperator.h" @@ -27,6 +29,7 @@ void EntitySimulation::setEntityTree(EntityTreePointer tree) { } void EntitySimulation::updateEntities() { + PROFILE_RANGE(simulation_physics, "ES::updateEntities"); QMutexLocker lock(&_mutex); quint64 now = usecTimestampNow(); @@ -35,8 +38,12 @@ void EntitySimulation::updateEntities() { callUpdateOnEntitiesThatNeedIt(now); moveSimpleKinematics(now); updateEntitiesInternal(now); - PerformanceTimer perfTimer("sortingEntities"); - sortEntitiesThatMoved(); + + { + PROFILE_RANGE(simulation_physics, "Sort"); + PerformanceTimer perfTimer("sortingEntities"); + sortEntitiesThatMoved(); + } } void EntitySimulation::takeEntitiesToDelete(VectorOfEntities& entitiesToDelete) { @@ -258,6 +265,7 @@ void EntitySimulation::clearEntities() { } void EntitySimulation::moveSimpleKinematics(const quint64& now) { + PROFILE_RANGE_EX(simulation_physics, "Kinematics", 0xffff00ff, (uint64_t)_simpleKinematicEntities.size()); SetOfEntities::iterator itemItr = _simpleKinematicEntities.begin(); while (itemItr != _simpleKinematicEntities.end()) { EntityItemPointer entity = *itemItr; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index d16aeaa6e1..4c7795dc75 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -15,8 +15,9 @@ #include -#include #include +#include +#include #include "EntitySimulation.h" #include "VariantMapToScriptValue.h" @@ -1370,6 +1371,7 @@ void EntityTree::entityChanged(EntityItemPointer entity) { void EntityTree::fixupNeedsParentFixups() { + PROFILE_RANGE(simulation_physics, "FixupParents"); MovingEntitiesOperator moveOperator; QWriteLocker locker(&_needsParentFixupLock); @@ -1459,6 +1461,7 @@ void EntityTree::addToNeedsParentFixupList(EntityItemPointer entity) { } void EntityTree::update(bool simulate) { + PROFILE_RANGE(simulation_physics, "ET::update"); fixupNeedsParentFixups(); if (simulate && _simulation) { withWriteLock([&] { From 23bb8608b14739ee776a9b0b8ef172a88475f885 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 16 Oct 2017 11:52:03 -0700 Subject: [PATCH 2/7] minor optimizations in updateModelBounds() --- .../src/RenderableModelEntityItem.cpp | 66 +++++++++++++++---- .../src/RenderableModelEntityItem.h | 1 - libraries/entities/src/ModelEntityItem.cpp | 14 ++-- libraries/entities/src/ModelEntityItem.h | 5 +- 4 files changed, 60 insertions(+), 26 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index a0c3cde28f..e2afc6eac2 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -124,10 +124,11 @@ void RenderableModelEntityItem::doInitialModelSimulation() { model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); model->setRotation(getRotation()); model->setTranslation(getPosition()); - { + + if (_needsInitialSimulation) { model->simulate(0.0f); + _needsInitialSimulation = false; } - _needsInitialSimulation = false; } void RenderableModelEntityItem::autoResizeJointArrays() { @@ -179,13 +180,59 @@ bool RenderableModelEntityItem::needsUpdateModelBounds() const { } } - return false; + return model->needsReload(); } void RenderableModelEntityItem::updateModelBounds() { PROFILE_RANGE(simulation_physics, "updateModelBounds"); - if (needsUpdateModelBounds()) { - doInitialModelSimulation(); + + if (!_dimensionsInitialized || !hasModel()) { + return; + } + + ModelPointer model = getModel(); + if (!model || !model->isLoaded()) { + return; + } + + /* adebug TODO: figure out if we need to DO anything when isAnimatingSomething() + if (isAnimatingSomething()) { + return true; + } + */ + + if (model->needsReload()) { + model->updateGeometry(); + } + + if (model->getScaleToFitDimensions() != getDimensions() || + model->getRegistrationPoint() != getRegistrationPoint()) { + // The machinery for updateModelBounds will give existing models the opportunity to fix their + // translation/rotation/scale/registration. The first two are straightforward, but the latter two + // have guards to make sure they don't happen after they've already been set. Here we reset those guards. + // This doesn't cause the entity values to change -- it just allows the model to match once it comes in. + model->setScaleToFit(false, getDimensions()); + model->setSnapModelToRegistrationPoint(false, getRegistrationPoint()); + + // now recalculate the bounds and registration + model->setScaleToFit(true, getDimensions()); + model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); + } + + bool success; + auto transform = getTransform(success); + if (success) { + if (model->getTranslation() != transform.getTranslation()) { + model->setTranslation(transform.getTranslation()); + } + if (model->getRotation() != transform.getRotation()) { + model->setRotation(transform.getRotation()); + } + } + + if (_needsInitialSimulation || _needsJointSimulation) { + model->simulate(0.0f); + _needsInitialSimulation = false; _needsJointSimulation = false; } } @@ -899,10 +946,6 @@ void RenderableModelEntityItem::copyAnimationJointDataToModel() { }); } -bool RenderableModelEntityItem::isAnimatingSomething() const { - return !getAnimationURL().isEmpty() && getAnimationIsPlaying() && getAnimationFPS() != 0.0f; -} - using namespace render; using namespace render::entities; @@ -1205,9 +1248,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce } } - if (entity->needsUpdateModelBounds()) { - entity->updateModelBounds(); - } + entity->updateModelBounds(); if (model->isVisible() != _visible) { // FIXME: this seems like it could be optimized if we tracked our last known visible state in @@ -1215,6 +1256,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce // so most of the time we don't do anything in this function. model->setVisibleInScene(_visible, scene); } + // TODO? early exit here when not visible? { PROFILE_RANGE(simulation_physics, "Fixup"); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index d1424316e9..a50ca63382 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -108,7 +108,6 @@ public: private: bool needsUpdateModelBounds() const; - bool isAnimatingSomething() const; void autoResizeJointArrays(); void copyAnimationJointDataToModel(); diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 6af4db154a..a5d259ea87 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -557,12 +557,6 @@ void ModelEntityItem::setAnimationLoop(bool loop) { }); } -bool ModelEntityItem::getAnimationLoop() const { - return resultWithReadLock([&] { - return _animationProperties.getLoop(); - }); -} - void ModelEntityItem::setAnimationHold(bool hold) { withWriteLock([&] { _animationProperties.setHold(hold); @@ -610,8 +604,10 @@ float ModelEntityItem::getAnimationCurrentFrame() const { }); } -float ModelEntityItem::getAnimationFPS() const { +bool ModelEntityItem::isAnimatingSomething() const { return resultWithReadLock([&] { - return _animationProperties.getFPS(); - }); + return !_animationProperties.getURL().isEmpty() && + _animationProperties.getRunning() && + (_animationProperties.getFPS() != 0.0f); + }); } diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 7efb493735..2c3ef3aa2d 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -90,7 +90,6 @@ public: bool getAnimationAllowTranslation() const { return _animationProperties.getAllowTranslation(); }; void setAnimationLoop(bool loop); - bool getAnimationLoop() const; void setAnimationHold(bool hold); bool getAnimationHold() const; @@ -101,10 +100,9 @@ public: void setAnimationLastFrame(float lastFrame); float getAnimationLastFrame() const; - bool getAnimationIsPlaying() const; float getAnimationCurrentFrame() const; - float getAnimationFPS() const; + bool isAnimatingSomething() const; static const QString DEFAULT_TEXTURES; const QString getTextures() const; @@ -123,7 +121,6 @@ public: QVector getJointRotationsSet() const; QVector getJointTranslations() const; QVector getJointTranslationsSet() const; - bool isAnimatingSomething() const; private: void setAnimationSettings(const QString& value); // only called for old bitstream format From fb1c075a1272c5a57ab9fd80fcf051d1a2702160 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 16 Oct 2017 15:55:25 -0700 Subject: [PATCH 3/7] fix animating entities --- .../src/RenderableModelEntityItem.cpp | 32 +++++++++---------- libraries/render-utils/src/Model.cpp | 10 ++++-- libraries/render-utils/src/Model.h | 1 + 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index e2afc6eac2..1e75b3bdf1 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -153,7 +153,7 @@ bool RenderableModelEntityItem::needsUpdateModelBounds() const { return true; } - if (isMovingRelativeToParent() || isAnimatingSomething()) { + if (isAnimatingSomething()) { return true; } @@ -195,14 +195,10 @@ void RenderableModelEntityItem::updateModelBounds() { return; } - /* adebug TODO: figure out if we need to DO anything when isAnimatingSomething() - if (isAnimatingSomething()) { - return true; - } - */ - + bool updateRenderItems = false; if (model->needsReload()) { model->updateGeometry(); + updateRenderItems = true; } if (model->getScaleToFitDimensions() != getDimensions() || @@ -217,23 +213,28 @@ void RenderableModelEntityItem::updateModelBounds() { // now recalculate the bounds and registration model->setScaleToFit(true, getDimensions()); model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); + updateRenderItems = true; } bool success; auto transform = getTransform(success); - if (success) { - if (model->getTranslation() != transform.getTranslation()) { - model->setTranslation(transform.getTranslation()); - } - if (model->getRotation() != transform.getRotation()) { - model->setRotation(transform.getRotation()); - } + if (success && (model->getTranslation() != transform.getTranslation() || + model->getRotation() != transform.getRotation())) { + model->setTransformNoUpdateRenderItems(transform); + updateRenderItems = true; } - if (_needsInitialSimulation || _needsJointSimulation) { + if (_needsInitialSimulation || _needsJointSimulation || isAnimatingSomething()) { + // NOTE: on isAnimatingSomething() we need to call Model::simulate() which calls Rig::updateRig() + // TODO: there is opportunity to further optimize the isAnimatingSomething() case. model->simulate(0.0f); _needsInitialSimulation = false; _needsJointSimulation = false; + updateRenderItems = true; + } + + if (updateRenderItems) { + model->updateRenderItems(); } } @@ -929,7 +930,6 @@ void RenderableModelEntityItem::copyAnimationJointDataToModel() { return; } - // relay any inbound joint changes from scripts/animation/network to the model/rig _jointDataLock.withWriteLock([&] { for (int index = 0; index < _localJointData.size(); ++index) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 4573b5aa78..fcda330f4a 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -121,8 +121,6 @@ bool Model::needsFixupInScene() const { return (_needsFixupInScene || !_addedToScene) && !_needsReload && isLoaded(); } -// TODO?: should we combine translation and rotation into single method to avoid double-work? -// (figure out where we call these) void Model::setTranslation(const glm::vec3& translation) { _translation = translation; updateRenderItems(); @@ -133,6 +131,14 @@ void Model::setRotation(const glm::quat& rotation) { updateRenderItems(); } +// temporary HACK: set transform while avoiding implicit calls to updateRenderItems() +// TODO: make setRotation() and friends set flag to be used later to decide to updateRenderItems() +void Model::setTransformNoUpdateRenderItems(const Transform& transform) { + _translation = transform.getTranslation(); + _rotation = transform.getRotation(); + // DO NOT call updateRenderItems() here! +} + Transform Model::getTransform() const { if (_spatiallyNestableOverride) { bool success; diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 0207a4871a..8bce976b4e 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -206,6 +206,7 @@ public: void setTranslation(const glm::vec3& translation); void setRotation(const glm::quat& rotation); + void setTransformNoUpdateRenderItems(const Transform& transform); // temporary HACK const glm::vec3& getTranslation() const { return _translation; } const glm::quat& getRotation() const { return _rotation; } From 102a1cb36beee5faa15ee4230fa8cafcc683010b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 16 Oct 2017 16:02:11 -0700 Subject: [PATCH 4/7] ifdef out detailed profiling --- .../src/RenderableModelEntityItem.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 1e75b3bdf1..f36525b527 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -34,6 +34,9 @@ #include "EntityTreeRenderer.h" #include "EntitiesRendererLogging.h" +// uncomment WANT_DETAILED_PROFILING to profile the interesting contexts +//#define WANT_DETAILED_PROFILING + static CollisionRenderMeshCache collisionMeshCache; void ModelEntityWrapper::setModel(const ModelPointer& model) { @@ -107,7 +110,9 @@ QVariantMap parseTexturesToMap(QString textures, const QVariantMap& defaultTextu } void RenderableModelEntityItem::doInitialModelSimulation() { +#ifdef WANT_DETAILED_PROFILING PROFILE_RANGE(simulation_physics, __FUNCTION__); +#endif ModelPointer model = getModel(); if (!model) { return; @@ -139,7 +144,9 @@ void RenderableModelEntityItem::autoResizeJointArrays() { } bool RenderableModelEntityItem::needsUpdateModelBounds() const { +#ifdef WANT_DETAILED_PROFILING PROFILE_RANGE(simulation_physics, __FUNCTION__); +#endif ModelPointer model = getModel(); if (!hasModel() || !model) { return false; @@ -184,7 +191,9 @@ bool RenderableModelEntityItem::needsUpdateModelBounds() const { } void RenderableModelEntityItem::updateModelBounds() { +#ifdef WANT_DETAILED_PROFILING PROFILE_RANGE(simulation_physics, "updateModelBounds"); +#endif if (!_dimensionsInitialized || !hasModel()) { return; @@ -1169,7 +1178,9 @@ bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin } void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { +#ifdef WANT_DETAILED_PROFILING PROFILE_RANGE(simulation_physics, __FUNCTION__); +#endif if (_hasModel != entity->hasModel()) { _hasModel = entity->hasModel(); } @@ -1259,7 +1270,9 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce // TODO? early exit here when not visible? { +#ifdef WANT_DETAILED_PROFILING PROFILE_RANGE(simulation_physics, "Fixup"); +#endif if (model->needsFixupInScene()) { model->removeFromScene(scene, transaction); render::Item::Status::Getters statusGetters; @@ -1275,7 +1288,9 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce } { +#ifdef WANT_DETAILED_PROFILING PROFILE_RANGE(simulation_physics, "CheckAnimation"); +#endif // make a copy of the animation properites auto newAnimationProperties = entity->getAnimationProperties(); if (newAnimationProperties != _renderAnimationProperties) { @@ -1287,7 +1302,9 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce } if (_animating) { +#ifdef WANT_DETAILED_PROFILING PROFILE_RANGE(simulation_physics, "Animate"); +#endif if (!jointsMapped()) { mapJoints(entity, model->getJointNames()); } @@ -1298,7 +1315,9 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce // NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items void ModelEntityRenderer::doRender(RenderArgs* args) { +#ifdef WANT_DETAILED_PROFILING PROFILE_RANGE(render_detail, "MetaModelRender"); +#endif PerformanceTimer perfTimer("RMEIrender"); ModelPointer model; From 1f09c10fb15efb5c89f7bf04978eb1174b924fcf Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 16 Oct 2017 16:43:16 -0700 Subject: [PATCH 5/7] comment out more profiling stuff --- libraries/entities-renderer/src/RenderableEntityItem.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 73c900f2b5..ff581f8e8d 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -26,6 +26,9 @@ #include "RenderableWebEntityItem.h" #include "RenderableZoneEntityItem.h" +// uncomment WANT_DETAILED_PROFILING to see some of the interesting profiling contexts +//#define WANT_DETAILED_PROFILING + using namespace render; using namespace render::entities; @@ -271,7 +274,9 @@ void EntityRenderer::removeFromScene(const ScenePointer& scene, Transaction& tra } void EntityRenderer::updateInScene(const ScenePointer& scene, Transaction& transaction) { +#ifdef WANT_DETAILED_PROFILING PROFILE_RANGE(simulation_physics, __FUNCTION__); +#endif if (!isValidRenderItem()) { return; } @@ -331,7 +336,9 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity } void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) { +#ifdef WANT_DETAILED_PROFILING PROFILE_RANGE(simulation_physics, __FUNCTION__); +#endif withWriteLock([&] { auto transparent = isTransparent(); if (_prevIsTransparent && !transparent) { From 339edc67c8efca481754b0147616be527e47ed91 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 16 Oct 2017 17:27:53 -0700 Subject: [PATCH 6/7] ifdef out more per-frame-per-entity profiling --- libraries/animation/src/Rig.cpp | 16 ++++++++++++++-- .../src/RenderableModelEntityItem.cpp | 6 +++++- libraries/render-utils/src/Model.cpp | 9 +++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 0897c26a12..5609baf548 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -32,6 +32,9 @@ #include "AnimUtil.h" #include "IKTarget.h" +// uncomment WANT_DETAILED_PROFILING for profiling that would otherwise impact performance +//#define WANT_DETAILED_PROFILING + static int nextRigId = 1; static std::map rigRegistry; static std::mutex rigRegistryMutex; @@ -999,14 +1002,17 @@ void Rig::updateAnimationStateHandlers() { // called on avatar update thread (wh } void Rig::updateAnimations(float deltaTime, const glm::mat4& rootTransform, const glm::mat4& rigToWorldTransform) { - +#ifdef WANT_DETAILED_PROFILING PROFILE_RANGE_EX(simulation_animation_detail, __FUNCTION__, 0xffff00ff, 0); PerformanceTimer perfTimer("updateAnimations"); +#endif setModelOffset(rootTransform); if (_animNode && _enabledAnimations) { +#ifdef WANT_DETAILED_PROFILING PerformanceTimer perfTimer("handleTriggers"); +#endif updateAnimationStateHandlers(); _animVars.setRigToGeometryTransform(_rigToGeometryTransform); @@ -1658,7 +1664,9 @@ bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const } void Rig::applyOverridePoses() { +#ifdef WANT_DETAILED_PROFILING PerformanceTimer perfTimer("override"); +#endif if (_numOverrides == 0 || !_animSkeleton) { return; } @@ -1675,7 +1683,9 @@ void Rig::applyOverridePoses() { } void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) { +#ifdef WANT_DETAILED_PROFILING PerformanceTimer perfTimer("buildAbsolute"); +#endif if (!_animSkeleton) { return; } @@ -1730,8 +1740,10 @@ void Rig::copyJointsIntoJointData(QVector& jointDataVec) const { } void Rig::copyJointsFromJointData(const QVector& jointDataVec) { - PerformanceTimer perfTimer("copyJoints"); +#ifdef WANT_DETAILED_PROFILING PROFILE_RANGE(simulation_animation_detail, "copyJoints"); + PerformanceTimer perfTimer("copyJoints"); +#endif if (!_animSkeleton) { return; } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index f36525b527..3b7b180f7a 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -352,7 +352,9 @@ bool RenderableModelEntityItem::isReadyToComputeShape() const { // we have both URLs AND both geometries AND they are both fully loaded. if (_needsInitialSimulation) { // the _model's offset will be wrong until _needsInitialSimulation is false +#ifdef WANT_DETAILED_PROFILING PerformanceTimer perfTimer("_model->simulate"); +#endif const_cast(this)->doInitialModelSimulation(); } return true; @@ -898,7 +900,9 @@ void RenderableModelEntityItem::setJointTranslationsSet(const QVector& tra } void RenderableModelEntityItem::locationChanged(bool tellPhysics) { +#ifdef WANT_DETAILED_PROFILING PerformanceTimer pertTimer("locationChanged"); +#endif EntityItem::locationChanged(tellPhysics); auto model = getModel(); if (model && model->isLoaded()) { @@ -1317,8 +1321,8 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce void ModelEntityRenderer::doRender(RenderArgs* args) { #ifdef WANT_DETAILED_PROFILING PROFILE_RANGE(render_detail, "MetaModelRender"); -#endif PerformanceTimer perfTimer("RMEIrender"); +#endif ModelPointer model; withReadLock([&]{ diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index fcda330f4a..616b1554b5 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -32,6 +32,9 @@ #include "RenderUtilsLogging.h" #include +// uncomment WANT_DETAILED_PROFILING to enable profiling that causes measureable performance impact +//#define WANT_DETAILED_PROFILING + using namespace std; int nakedModelPointerTypeId = qRegisterMetaType(); @@ -963,7 +966,9 @@ Blender::Blender(ModelPointer model, int blendNumber, const Geometry::WeakPointe } void Blender::run() { +#ifdef WANT_DETAILED_PROFILING PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xFFFF0000, 0, { { "url", _model->getURL().toString() } }); +#endif QVector vertices, normals; if (_model) { int offset = 0; @@ -1084,8 +1089,10 @@ void Model::snapToRegistrationPoint() { } void Model::simulate(float deltaTime, bool fullUpdate) { +#ifdef WANT_DETAILED_PROFILING PROFILE_RANGE(simulation_detail, __FUNCTION__); PerformanceTimer perfTimer("Model::simulate"); +#endif fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit) || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint); @@ -1123,7 +1130,9 @@ void Model::computeMeshPartLocalBounds() { // virtual void Model::updateClusterMatrices() { +#ifdef WANT_DETAILED_PROFILING PerformanceTimer perfTimer("Model::updateClusterMatrices"); +#endif if (!_needsUpdateClusterMatrices || !isLoaded()) { return; From c79bf3bc042b8e45ba7af8f393a14851f715416b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 19 Oct 2017 14:31:50 -0700 Subject: [PATCH 7/7] cleanup WANT_DETAILED_PROFILING --- BUILD.md | 2 +- libraries/animation/src/Rig.cpp | 27 ++++-------- .../src/RenderableEntityItem.cpp | 10 +---- .../src/RenderableModelEntityItem.cpp | 44 +++++-------------- libraries/render-utils/src/Model.cpp | 16 ++----- libraries/shared/src/PerfStat.h | 7 +++ libraries/shared/src/Profile.h | 10 +++++ 7 files changed, 42 insertions(+), 74 deletions(-) diff --git a/BUILD.md b/BUILD.md index 4d321146c3..feed677828 100644 --- a/BUILD.md +++ b/BUILD.md @@ -25,7 +25,7 @@ The above dependencies will be downloaded, built, linked and included automatica These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. Should you want to force a re-download and re-compile of a specific external, you can simply remove that directory from the appropriate subfolder in `build/ext`. Should you want to force a re-download and re-compile of all externals, just remove the `build/ext` folder. -If you would like to use a specific install of a dependency instead of the version that would be grabbed as a CMake ExternalProject, you can pass -DUSE_LOCAL_$NAME=0 (where $NAME is the name of the subfolder in [cmake/externals](cmake/externals)) when you run CMake to tell it not to get that dependency as an external project. +If you would like to use a specific install of a dependency instead of the version that would be grabbed as a CMake ExternalProject, you can pass -DUSE\_LOCAL\_$NAME=0 (where $NAME is the name of the subfolder in [cmake/externals](cmake/externals)) when you run CMake to tell it not to get that dependency as an external project. ### OS Specific Build Guides diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 5609baf548..0f2bce5ca4 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -32,8 +32,6 @@ #include "AnimUtil.h" #include "IKTarget.h" -// uncomment WANT_DETAILED_PROFILING for profiling that would otherwise impact performance -//#define WANT_DETAILED_PROFILING static int nextRigId = 1; static std::map rigRegistry; @@ -1002,17 +1000,13 @@ void Rig::updateAnimationStateHandlers() { // called on avatar update thread (wh } void Rig::updateAnimations(float deltaTime, const glm::mat4& rootTransform, const glm::mat4& rigToWorldTransform) { -#ifdef WANT_DETAILED_PROFILING - PROFILE_RANGE_EX(simulation_animation_detail, __FUNCTION__, 0xffff00ff, 0); - PerformanceTimer perfTimer("updateAnimations"); -#endif + DETAILED_PROFILE_RANGE_EX(simulation_animation_detail, __FUNCTION__, 0xffff00ff, 0); + DETAILED_PERFORMANCE_TIMER("updateAnimations"); setModelOffset(rootTransform); if (_animNode && _enabledAnimations) { -#ifdef WANT_DETAILED_PROFILING - PerformanceTimer perfTimer("handleTriggers"); -#endif + DETAILED_PERFORMANCE_TIMER("handleTriggers"); updateAnimationStateHandlers(); _animVars.setRigToGeometryTransform(_rigToGeometryTransform); @@ -1664,9 +1658,7 @@ bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const } void Rig::applyOverridePoses() { -#ifdef WANT_DETAILED_PROFILING - PerformanceTimer perfTimer("override"); -#endif + DETAILED_PERFORMANCE_TIMER("override"); if (_numOverrides == 0 || !_animSkeleton) { return; } @@ -1683,9 +1675,7 @@ void Rig::applyOverridePoses() { } void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) { -#ifdef WANT_DETAILED_PROFILING - PerformanceTimer perfTimer("buildAbsolute"); -#endif + DETAILED_PERFORMANCE_TIMER("buildAbsolute"); if (!_animSkeleton) { return; } @@ -1740,10 +1730,9 @@ void Rig::copyJointsIntoJointData(QVector& jointDataVec) const { } void Rig::copyJointsFromJointData(const QVector& jointDataVec) { -#ifdef WANT_DETAILED_PROFILING - PROFILE_RANGE(simulation_animation_detail, "copyJoints"); - PerformanceTimer perfTimer("copyJoints"); -#endif + DETAILED_PROFILE_RANGE(simulation_animation_detail, "copyJoints"); + DETAILED_PERFORMANCE_TIMER("copyJoints"); + if (!_animSkeleton) { return; } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index ff581f8e8d..07c5694a2a 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -26,8 +26,6 @@ #include "RenderableWebEntityItem.h" #include "RenderableZoneEntityItem.h" -// uncomment WANT_DETAILED_PROFILING to see some of the interesting profiling contexts -//#define WANT_DETAILED_PROFILING using namespace render; using namespace render::entities; @@ -274,9 +272,7 @@ void EntityRenderer::removeFromScene(const ScenePointer& scene, Transaction& tra } void EntityRenderer::updateInScene(const ScenePointer& scene, Transaction& transaction) { -#ifdef WANT_DETAILED_PROFILING - PROFILE_RANGE(simulation_physics, __FUNCTION__); -#endif + DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__); if (!isValidRenderItem()) { return; } @@ -336,9 +332,7 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity } void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) { -#ifdef WANT_DETAILED_PROFILING - PROFILE_RANGE(simulation_physics, __FUNCTION__); -#endif + DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__); withWriteLock([&] { auto transparent = isTransparent(); if (_prevIsTransparent && !transparent) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3b7b180f7a..e9fbc43420 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -34,8 +34,6 @@ #include "EntityTreeRenderer.h" #include "EntitiesRendererLogging.h" -// uncomment WANT_DETAILED_PROFILING to profile the interesting contexts -//#define WANT_DETAILED_PROFILING static CollisionRenderMeshCache collisionMeshCache; @@ -110,9 +108,7 @@ QVariantMap parseTexturesToMap(QString textures, const QVariantMap& defaultTextu } void RenderableModelEntityItem::doInitialModelSimulation() { -#ifdef WANT_DETAILED_PROFILING - PROFILE_RANGE(simulation_physics, __FUNCTION__); -#endif + DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__); ModelPointer model = getModel(); if (!model) { return; @@ -144,9 +140,7 @@ void RenderableModelEntityItem::autoResizeJointArrays() { } bool RenderableModelEntityItem::needsUpdateModelBounds() const { -#ifdef WANT_DETAILED_PROFILING - PROFILE_RANGE(simulation_physics, __FUNCTION__); -#endif + DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__); ModelPointer model = getModel(); if (!hasModel() || !model) { return false; @@ -191,9 +185,7 @@ bool RenderableModelEntityItem::needsUpdateModelBounds() const { } void RenderableModelEntityItem::updateModelBounds() { -#ifdef WANT_DETAILED_PROFILING - PROFILE_RANGE(simulation_physics, "updateModelBounds"); -#endif + DETAILED_PROFILE_RANGE(simulation_physics, "updateModelBounds"); if (!_dimensionsInitialized || !hasModel()) { return; @@ -352,9 +344,7 @@ bool RenderableModelEntityItem::isReadyToComputeShape() const { // we have both URLs AND both geometries AND they are both fully loaded. if (_needsInitialSimulation) { // the _model's offset will be wrong until _needsInitialSimulation is false -#ifdef WANT_DETAILED_PROFILING - PerformanceTimer perfTimer("_model->simulate"); -#endif + DETAILED_PERFORMANCE_TIMER("_model->simulate"); const_cast(this)->doInitialModelSimulation(); } return true; @@ -900,9 +890,7 @@ void RenderableModelEntityItem::setJointTranslationsSet(const QVector& tra } void RenderableModelEntityItem::locationChanged(bool tellPhysics) { -#ifdef WANT_DETAILED_PROFILING - PerformanceTimer pertTimer("locationChanged"); -#endif + DETAILED_PERFORMANCE_TIMER("locationChanged"); EntityItem::locationChanged(tellPhysics); auto model = getModel(); if (model && model->isLoaded()) { @@ -1182,9 +1170,7 @@ bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin } void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { -#ifdef WANT_DETAILED_PROFILING - PROFILE_RANGE(simulation_physics, __FUNCTION__); -#endif + DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__); if (_hasModel != entity->hasModel()) { _hasModel = entity->hasModel(); } @@ -1274,9 +1260,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce // TODO? early exit here when not visible? { -#ifdef WANT_DETAILED_PROFILING - PROFILE_RANGE(simulation_physics, "Fixup"); -#endif + DETAILED_PROFILE_RANGE(simulation_physics, "Fixup"); if (model->needsFixupInScene()) { model->removeFromScene(scene, transaction); render::Item::Status::Getters statusGetters; @@ -1292,9 +1276,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce } { -#ifdef WANT_DETAILED_PROFILING - PROFILE_RANGE(simulation_physics, "CheckAnimation"); -#endif + DETAILED_PROFILE_RANGE(simulation_physics, "CheckAnimation"); // make a copy of the animation properites auto newAnimationProperties = entity->getAnimationProperties(); if (newAnimationProperties != _renderAnimationProperties) { @@ -1306,9 +1288,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce } if (_animating) { -#ifdef WANT_DETAILED_PROFILING - PROFILE_RANGE(simulation_physics, "Animate"); -#endif + DETAILED_PROFILE_RANGE(simulation_physics, "Animate"); if (!jointsMapped()) { mapJoints(entity, model->getJointNames()); } @@ -1319,10 +1299,8 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce // NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items void ModelEntityRenderer::doRender(RenderArgs* args) { -#ifdef WANT_DETAILED_PROFILING - PROFILE_RANGE(render_detail, "MetaModelRender"); - PerformanceTimer perfTimer("RMEIrender"); -#endif + DETAILED_PROFILE_RANGE(render_detail, "MetaModelRender"); + DETAILED_PERFORMANCE_TIMER("RMEIrender"); ModelPointer model; withReadLock([&]{ diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 616b1554b5..964a1961d6 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -32,9 +32,6 @@ #include "RenderUtilsLogging.h" #include -// uncomment WANT_DETAILED_PROFILING to enable profiling that causes measureable performance impact -//#define WANT_DETAILED_PROFILING - using namespace std; int nakedModelPointerTypeId = qRegisterMetaType(); @@ -966,9 +963,7 @@ Blender::Blender(ModelPointer model, int blendNumber, const Geometry::WeakPointe } void Blender::run() { -#ifdef WANT_DETAILED_PROFILING - PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xFFFF0000, 0, { { "url", _model->getURL().toString() } }); -#endif + DETAILED_PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xFFFF0000, 0, { { "url", _model->getURL().toString() } }); QVector vertices, normals; if (_model) { int offset = 0; @@ -1089,10 +1084,7 @@ void Model::snapToRegistrationPoint() { } void Model::simulate(float deltaTime, bool fullUpdate) { -#ifdef WANT_DETAILED_PROFILING - PROFILE_RANGE(simulation_detail, __FUNCTION__); - PerformanceTimer perfTimer("Model::simulate"); -#endif + DETAILED_PROFILE_RANGE(simulation_detail, __FUNCTION__); fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit) || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint); @@ -1130,9 +1122,7 @@ void Model::computeMeshPartLocalBounds() { // virtual void Model::updateClusterMatrices() { -#ifdef WANT_DETAILED_PROFILING - PerformanceTimer perfTimer("Model::updateClusterMatrices"); -#endif + DETAILED_PERFORMANCE_TIMER("Model::updateClusterMatrices"); if (!_needsUpdateClusterMatrices || !isLoaded()) { return; diff --git a/libraries/shared/src/PerfStat.h b/libraries/shared/src/PerfStat.h index 785920779e..b09cb38808 100644 --- a/libraries/shared/src/PerfStat.h +++ b/libraries/shared/src/PerfStat.h @@ -97,5 +97,12 @@ private: static QMap _records; }; +// uncomment WANT_DETAILED_PERFORMANCE_TIMERS definition to enable performance timers in high-frequency contexts +//#define WANT_DETAILED_PERFORMANCE_TIMERS +#ifdef WANT_DETAILED_PERFORMANCE_TIMERS + #define DETAILED_PERFORMANCE_TIMER(name) PerformanceTimer detailedPerformanceTimer(name); +#else // WANT_DETAILED_PERFORMANCE_TIMERS + #define DETAILED_PERFORMANCE_TIMER(name) ; // no-op +#endif // WANT_DETAILED_PERFORMANCE_TIMERS #endif // hifi_PerfStat_h diff --git a/libraries/shared/src/Profile.h b/libraries/shared/src/Profile.h index 5de4e8f41a..fc6a2a52cb 100644 --- a/libraries/shared/src/Profile.h +++ b/libraries/shared/src/Profile.h @@ -108,4 +108,14 @@ inline void metadata(const QString& metadataType, const QVariantMap& args) { #define SAMPLE_PROFILE_COUNTER(chance, category, name, ...) if (randFloat() <= chance) { PROFILE_COUNTER(category, name, ##__VA_ARGS__); } #define SAMPLE_PROFILE_INSTANT(chance, category, name, ...) if (randFloat() <= chance) { PROFILE_INSTANT(category, name, ##__VA_ARGS__); } +// uncomment WANT_DETAILED_PROFILING definition to enable profiling in high-frequency contexts +//#define WANT_DETAILED_PROFILING +#ifdef WANT_DETAILED_PROFILING +#define DETAILED_PROFILE_RANGE(category, name) Duration profileRangeThis(trace_##category(), name); +#define DETAILED_PROFILE_RANGE_EX(category, name, argbColor, payload, ...) Duration profileRangeThis(trace_##category(), name, argbColor, (uint64_t)payload, ##__VA_ARGS__); +#else // WANT_DETAILED_PROFILING +#define DETAILED_PROFILE_RANGE(category, name) ; // no-op +#define DETAILED_PROFILE_RANGE_EX(category, name, argbColor, payload, ...) ; // no-op +#endif // WANT_DETAILED_PROFILING + #endif