From d6b6645630ef8427edcf14586f9b35ccfb0d454a Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 17 Apr 2018 18:03:45 -0700 Subject: [PATCH] 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