exposing feedback of timing

This commit is contained in:
samcake 2018-04-17 18:03:45 -07:00
parent ab04a34ccf
commit d6b6645630
14 changed files with 147 additions and 69 deletions

View file

@ -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.updateViews(_viewFrustum, getMyAvatar()->getHeadPosition());
_gameWorkload._engine->run(); _gameWorkload._engine->run();
} }

View file

@ -489,9 +489,9 @@ void Stats::updateStats(bool force) {
}; };
for (int32_t j = 0; j < categories.size(); ++j) { for (int32_t j = 0; j < categories.size(); ++j) {
QString recordKey = "/idle/update/" + categories[j]; QString recordKey = "/idle/update/" + categories[j];
itr = allRecords.find(recordKey); auto record = PerformanceTimer::getTimerRecord(recordKey);
if (itr != allRecords.end()) { if (record.getCount()) {
float dt = (float)itr.value().getMovingAverage() / (float)USECS_PER_MSEC; float dt = (float) record.getMovingAverage() / (float)USECS_PER_MSEC;
QString message = QString("\n %1 = %2").arg(categories[j]).arg(dt); QString message = QString("\n %1 = %2").arg(categories[j]).arg(dt);
idleUpdateStats.push(SortableStat(message, dt)); idleUpdateStats.push(SortableStat(message, dt));
} }

View file

@ -15,6 +15,41 @@
#include "PhysicsBoundary.h" #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<workload::Views, workload::Timings>;
using Outputs = workload::RegionTracker::Outputs;
using JobModel = workload::Task::ModelIO<WorkloadEngineBuilder, Inputs, Outputs>;
void build(JobModel& model, const workload::Varying& in, workload::Varying& out) {
const auto& inViews = in.getN<Inputs>(0);
const auto& inTimings = in.getN<Inputs>(1);
const auto usedViews = model.addJob<workload::SetupViews>("setupViews", inViews);
ControlViews::Input controlViewsIn;
controlViewsIn[0] = usedViews;
controlViewsIn[1] = inTimings;
const auto fixedViews = model.addJob<ControlViews>("controlViews", controlViewsIn);
const auto regionTrackerOut = model.addJob<workload::SpaceClassifierTask>("spaceClassifier", fixedViews);
model.addJob<PhysicsBoundary>("PhysicsBoundary", regionTrackerOut);
model.addJob<GameSpaceToRender>("SpaceToRender");
out = regionTrackerOut;
}
};
GameWorkloadContext::GameWorkloadContext(const workload::SpacePointer& space, GameWorkloadContext::GameWorkloadContext(const workload::SpacePointer& space,
const render::ScenePointer& scene, const render::ScenePointer& scene,
const PhysicalEntitySimulationPointer& simulation): WorkloadContext(space), const PhysicalEntitySimulationPointer& simulation): WorkloadContext(space),
@ -27,7 +62,7 @@ GameWorkloadContext::~GameWorkloadContext() {
GameWorkload::GameWorkload() : GameWorkload::GameWorkload() :
_engine(std::make_shared<workload::Engine>(std::make_shared<workload::Task>(workload::SpaceClassifierTask::JobModel::create("Engine")))) _engine(std::make_shared<workload::Engine>(WorkloadEngineBuilder::JobModel::create("Engine")))
{ {
} }
@ -39,12 +74,6 @@ void GameWorkload::startup(const workload::SpacePointer& space,
const render::ScenePointer& scene, const render::ScenePointer& scene,
const PhysicalEntitySimulationPointer& simulation) { const PhysicalEntitySimulationPointer& simulation) {
_engine->reset(std::make_shared<GameWorkloadContext>(space, scene, simulation)); _engine->reset(std::make_shared<GameWorkloadContext>(space, scene, simulation));
auto output = _engine->_task->getOutput();
_engine->_task->addJob<GameSpaceToRender>("SpaceToRender");
const auto regionChanges = _engine->_task->getOutput();
_engine->_task->addJob<PhysicsBoundary>("PhysicsBoundary", regionChanges);
} }
void GameWorkload::shutdown() { void GameWorkload::shutdown() {
@ -55,9 +84,9 @@ void GameWorkload::updateViews(const ViewFrustum& frustum, const glm::vec3& head
workload::Views views; workload::Views views;
views.emplace_back(workload::View::evalFromFrustum(frustum, headPosition - frustum.getPosition())); views.emplace_back(workload::View::evalFromFrustum(frustum, headPosition - frustum.getPosition()));
views.emplace_back(workload::View::evalFromFrustum(frustum)); views.emplace_back(workload::View::evalFromFrustum(frustum));
_engine->_task->feedInput(views); _engine->feedInput<WorkloadEngineBuilder::Inputs>(0, views);
} }
void GameWorkload::updateSimulationTimings(const workload::Timings& timings) { void GameWorkload::updateSimulationTimings(const workload::Timings& timings) {
// _engine->_task->feedInput(timings); _engine->feedInput<WorkloadEngineBuilder::Inputs>(1, timings);
} }

View file

@ -43,4 +43,23 @@ public:
workload::EnginePointer _engine; 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<workload::Views, workload::Timings>;
using Output = workload::Views;
using JobModel = workload::Job::ModelIO<ControlViews, Input, Output, Config>;
void configure(const Config& config) {}
void run(const workload::WorkloadContextPointer& renderContext, const Input& inputs, Output& outputs);
};
#endif // hifi_GameWorkload_h #endif // hifi_GameWorkload_h

View file

@ -248,7 +248,7 @@ void GameWorkloadRenderItem::render(RenderArgs* args) {
batch.setUniformBuffer(0, getDrawViewBuffer()); batch.setUniformBuffer(0, getDrawViewBuffer());
static const int NUM_VERTICES_PER_DRAWVIEWVERT = 2; static const int NUM_VERTICES_PER_DRAWVIEWVERT = 2;
static const int NUM_REGIONS = 3; 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);
} }

View file

@ -415,7 +415,10 @@ void EntityTreeRenderer::update(bool simulate) {
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree); EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
// here we update _currentFrame and _lastAnimated and sync with the server properties. // 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 { // Update the rendereable entities as needed
PROFILE_RANGE(simulation_physics, "Scene"); PROFILE_RANGE(simulation_physics, "Scene");
@ -430,19 +433,22 @@ void EntityTreeRenderer::update(bool simulate) {
scene->enqueueTransaction(transaction); scene->enqueueTransaction(transaction);
} }
} }
workload::Transaction spaceTransaction;
{ // update proxies in the workload::Space
std::unique_lock<std::mutex> lock(_spaceLock);
spaceTransaction.update(_spaceUpdates);
_spaceUpdates.clear();
}
{ {
std::vector<int32_t> staleProxies; PerformanceTimer perfTimer("workload::transaction");
tree->swapStaleProxies(staleProxies); workload::Transaction spaceTransaction;
spaceTransaction.remove(staleProxies); { // update proxies in the workload::Space
{
std::unique_lock<std::mutex> lock(_spaceLock); std::unique_lock<std::mutex> lock(_spaceLock);
_space->enqueueTransaction(spaceTransaction); spaceTransaction.update(_spaceUpdates);
_spaceUpdates.clear();
}
{
std::vector<int32_t> staleProxies;
tree->swapStaleProxies(staleProxies);
spaceTransaction.remove(staleProxies);
{
std::unique_lock<std::mutex> lock(_spaceLock);
_space->enqueueTransaction(spaceTransaction);
}
} }
} }

View file

@ -31,6 +31,7 @@ void EntitySimulation::setEntityTree(EntityTreePointer tree) {
void EntitySimulation::updateEntities() { void EntitySimulation::updateEntities() {
QMutexLocker lock(&_mutex); QMutexLocker lock(&_mutex);
uint64_t now = usecTimestampNow(); uint64_t now = usecTimestampNow();
PerformanceTimer perfTimer("EntitySimulation::updateEntities");
// these methods may accumulate entries in _entitiesToBeDeleted // these methods may accumulate entries in _entitiesToBeDeleted
expireMortalEntities(now); expireMortalEntities(now);

View file

@ -1819,6 +1819,7 @@ void EntityTree::addToNeedsParentFixupList(EntityItemPointer entity) {
void EntityTree::update(bool simulate) { void EntityTree::update(bool simulate) {
PROFILE_RANGE(simulation_physics, "UpdateTree"); PROFILE_RANGE(simulation_physics, "UpdateTree");
PerformanceTimer perfTimer("UpdateTreen");
withWriteLock([&] { withWriteLock([&] {
fixupNeedsParentFixups(); fixupNeedsParentFixups();
if (simulate && _simulation) { if (simulate && _simulation) {

View file

@ -187,6 +187,7 @@ public:
template <class I> void feedInput(const I& in) { _concept->editInput().template edit<I>() = in; } template <class I> void feedInput(const I& in) { _concept->editInput().template edit<I>() = in; }
template <class I, class S> void feedInput(int index, const S& inS) { (_concept->editInput().template editN<I>(index)).template edit<S>() = inS; }
QConfigPointer& getConfiguration() const { return _concept->getConfiguration(); } QConfigPointer& getConfiguration() const { return _concept->getConfiguration(); }
void applyConfiguration() { return _concept->applyConfiguration(); } void applyConfiguration() { return _concept->applyConfiguration(); }
@ -378,8 +379,33 @@ public:
protected: protected:
}; };
}
template <class JC>
class Engine : public Task<JC> {
public:
using Context = JC;
using ContextPointer = std::shared_ptr<Context>;
using Config = TaskConfig;
using TaskType = Task<JC>;
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) \ #define Task_DeclareTypeAliases(ContextType) \
using JobConfig = task::JobConfig; \ using JobConfig = task::JobConfig; \
@ -387,6 +413,7 @@ protected:
template <class T> using PersistentConfig = task::PersistentConfig<T>; \ template <class T> using PersistentConfig = task::PersistentConfig<T>; \
using Job = task::Job<ContextType>; \ using Job = task::Job<ContextType>; \
using Task = task::Task<ContextType>; \ using Task = task::Task<ContextType>; \
using _Engine = task::Engine<ContextType>; \
using Varying = task::Varying; \ using Varying = task::Varying; \
template < typename T0, typename T1 > using VaryingSet2 = task::VaryingSet2<T0, T1>; \ template < typename T0, typename T1 > using VaryingSet2 = task::VaryingSet2<T0, T1>; \
template < typename T0, typename T1, typename T2 > using VaryingSet3 = task::VaryingSet3<T0, T1, T2>; \ template < typename T0, typename T1, typename T2 > using VaryingSet3 = task::VaryingSet3<T0, T1, T2>; \

View file

@ -15,9 +15,5 @@
namespace workload { namespace workload {
WorkloadContext::WorkloadContext(const SpacePointer& space) : task::JobContext(trace_workload()), _space(space) {} WorkloadContext::WorkloadContext(const SpacePointer& space) : task::JobContext(trace_workload()), _space(space) {}
void Engine::reset(const WorkloadContextPointer& context) {
_context = context;
}
} // namespace workload } // namespace workload

View file

@ -33,26 +33,7 @@ namespace workload {
using WorkloadContextPointer = std::shared_ptr<WorkloadContext>; using WorkloadContextPointer = std::shared_ptr<WorkloadContext>;
Task_DeclareTypeAliases(WorkloadContext) Task_DeclareTypeAliases(WorkloadContext)
using Engine = _Engine;
class Engine {
public:
Engine(const std::shared_ptr<Task>& task) : _task(task), _context(nullptr) {
}
~Engine() = default;
void reset(const WorkloadContextPointer& context);
void run() { if (_context) { _task->run(_context); } }
std::shared_ptr<TaskConfig> getConfiguration() { return _task->getConfiguration(); }
std::shared_ptr<Task> _task;
protected:
private:
WorkloadContextPointer _context;
};
using EnginePointer = std::shared_ptr<Engine>; using EnginePointer = std::shared_ptr<Engine>;
} // namespace workload } // namespace workload

View file

@ -24,7 +24,7 @@ void PerformSpaceTransaction::run(const WorkloadContextPointer& context) {
} }
void SpaceClassifierTask::build(JobModel& model, const Varying& in, Varying& out) { void SpaceClassifierTask::build(JobModel& model, const Varying& in, Varying& out) {
model.addJob<SetupViews>("setupViews", in); model.addJob<AssignSpaceViews >("assignSpaceViews", in);
model.addJob<PerformSpaceTransaction>("updateSpace"); model.addJob<PerformSpaceTransaction>("updateSpace");
const auto regionTrackerOut = model.addJob<RegionTracker>("regionTracker"); const auto regionTrackerOut = model.addJob<RegionTracker>("regionTracker");
const auto regionChanges = regionTrackerOut.getN<RegionTracker::Outputs>(1); const auto regionChanges = regionTrackerOut.getN<RegionTracker::Outputs>(1);

View file

@ -13,52 +13,59 @@
using namespace workload; 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) { void SetupViews::configure(const Config& config) {
data = config.data; 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 views are frozen don't use the input
if (!data.freezeViews) { if (!data.freezeViews) {
_views = inputs; _views = inputs;
} }
auto& outViews = outputs;
outViews.clear();
// Filter the first view centerer on the avatar head if needed // Filter the first view centerer on the avatar head if needed
Views usedViews;
if (_views.size() >= 2) { if (_views.size() >= 2) {
if (data.useAvatarView) { if (data.useAvatarView) {
usedViews.push_back(_views[0]); outViews.push_back(_views[0]);
usedViews.insert(usedViews.end(), _views.begin() + 2, _views.end()); outViews.insert(outViews.end(), _views.begin() + 2, _views.end());
} else { } else {
usedViews.insert(usedViews.end(), _views.begin() + 1, _views.end()); outViews.insert(outViews.end(), _views.begin() + 1, _views.end());
} }
} else { } else {
usedViews = _views; outViews = _views;
} }
// Force frutum orientation horizontal if needed // Force frutum orientation horizontal if needed
if (usedViews.size() > 0 && data.forceViewHorizontal) { if (outViews.size() > 0 && data.forceViewHorizontal) {
usedViews[0].makeHorizontal(); outViews[0].makeHorizontal();
} }
// Force frutum orientation horizontal if needed // Force frutum orientation horizontal if needed
if (usedViews.size() > 0 && data.simulateSecondaryCamera) { if (outViews.size() > 0 && data.simulateSecondaryCamera) {
auto view = usedViews[0]; auto view = outViews[0];
auto secondaryDirectionFlat = glm::normalize(glm::vec3(view.direction.x, 0.0f, view.direction.z)); 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)); auto secondaryDirection = glm::normalize(glm::vec3(secondaryDirectionFlat.z, 0.0f, -secondaryDirectionFlat.x));
view.origin += -30.0f * secondaryDirection; view.origin += -20.0f * secondaryDirection;
view.direction = -secondaryDirectionFlat; view.direction = -secondaryDirection;
usedViews.insert(usedViews.begin() + 1, view); outViews.insert(outViews.begin() + 1, view);
} }
// Update regions based on the current config // Update regions based on the current config
for (auto& v : usedViews) { for (auto& v : outViews) {
View::updateRegions(v, (float*) &data); View::updateRegions(v, (float*) &data);
} }
// Views are setup, assign to the Space // outViews is ready to be used
renderContext->_space->setViews(usedViews);
} }

View file

@ -78,16 +78,25 @@ namespace workload {
public: public:
using Config = SetupViewsConfig; using Config = SetupViewsConfig;
using Input = Views; using Input = Views;
using JobModel = Job::ModelI<SetupViews, Input, Config>; using Output = Views;
using JobModel = Job::ModelIO<SetupViews, Input, Output, Config>;
void configure(const Config& config); 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: protected:
Config::Data data; Config::Data data;
Views _views; Views _views;
}; };
class AssignSpaceViews {
public:
using Input = Views;
using JobModel = Job::ModelI<AssignSpaceViews, Input>;
void run(const workload::WorkloadContextPointer& renderContext, const Input& inputs);
};
} // namespace workload } // namespace workload
#endif // hifi_workload_ViewTask_h #endif // hifi_workload_ViewTask_h