mirror of
https://github.com/lubosz/overte.git
synced 2025-04-12 13:32:53 +02:00
filter time-cost drivers for region regulation
This commit is contained in:
parent
4ab45e70a4
commit
f9d14e1351
5 changed files with 73 additions and 30 deletions
interface/src
libraries
|
@ -5795,15 +5795,13 @@ void Application::update(float deltaTime) {
|
|||
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);
|
||||
|
||||
timings[0] = t1 - t0; // prePhysics entities
|
||||
timings[1] = t2 - t1; // prePhysics avatars
|
||||
timings[2] = t3 - t2; // stepPhysics
|
||||
timings[3] = t4 - t3; // postPhysics
|
||||
timings[4] = t5 - t4; // non-physical kinematics
|
||||
timings[5] = workload::Timing_ns((int32_t)(NSECS_PER_SECOND * deltaTime)); // game loop duration
|
||||
_gameWorkload.updateSimulationTimings(timings);
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -36,6 +36,7 @@ const float METERS_PER_MILLIMETER = 0.001f;
|
|||
const float MILLIMETERS_PER_METER = 1000.0f;
|
||||
const quint64 NSECS_PER_USEC = 1000;
|
||||
const quint64 NSECS_PER_MSEC = 1000000;
|
||||
const quint64 NSECS_PER_SECOND = 1e9;
|
||||
const quint64 USECS_PER_MSEC = 1000;
|
||||
const quint64 MSECS_PER_SECOND = 1000;
|
||||
const quint64 USECS_PER_SECOND = USECS_PER_MSEC * MSECS_PER_SECOND;
|
||||
|
|
|
@ -70,7 +70,8 @@ private:
|
|||
using SpacePointer = std::shared_ptr<Space>;
|
||||
using Changes = std::vector<Space::Change>;
|
||||
using IndexVectors = std::vector<IndexVector>;
|
||||
using Timings = std::vector<std::chrono::nanoseconds>;
|
||||
using Timing_ns = std::chrono::nanoseconds;
|
||||
using Timings = std::vector<Timing_ns>;
|
||||
|
||||
} // namespace workload
|
||||
|
||||
|
|
|
@ -102,9 +102,16 @@ void ControlViews::run(const workload::WorkloadContextPointer& runContext, const
|
|||
|
||||
// Export the ranges and timings for debuging
|
||||
if (inTimings.size()) {
|
||||
_dataExport.timings[workload::Region::R1] = std::chrono::duration<float, std::milli>(inTimings[0]).count();
|
||||
// NOTE for reference:
|
||||
// inTimings[0] = prePhysics entities
|
||||
// inTimings[1] = prePhysics avatars
|
||||
// inTimings[2] = stepPhysics
|
||||
// inTimings[3] = postPhysics
|
||||
// inTimings[4] = non-physical kinematics
|
||||
// inTimings[5] = game loop
|
||||
_dataExport.timings[workload::Region::R1] = std::chrono::duration<float, std::milli>(inTimings[2] + inTimings[3]).count();
|
||||
_dataExport.timings[workload::Region::R2] = _dataExport.timings[workload::Region::R1];
|
||||
_dataExport.timings[workload::Region::R3] = std::chrono::duration<float, std::milli>(inTimings[1]).count();
|
||||
_dataExport.timings[workload::Region::R3] = std::chrono::duration<float, std::milli>(inTimings[4]).count();
|
||||
doExport = true;
|
||||
}
|
||||
|
||||
|
@ -115,11 +122,29 @@ void ControlViews::run(const workload::WorkloadContextPointer& runContext, const
|
|||
}
|
||||
}
|
||||
|
||||
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<float, std::milli>(_budget - measured).count();
|
||||
float coef = glm::clamp(error_ms / std::chrono::duration<float, std::milli>(regulationDuration).count(), -1.0f, 1.0f);
|
||||
return current * (1.0f + coef * (error_ms < 0.0f ? _relativeStepDown : _relativeStepUp));
|
||||
glm::vec2 Regulator::run(const Timing_ns& deltaTime, const Timing_ns& measuredTime, const glm::vec2& currentFrontBack) {
|
||||
// measure signal: average and noise
|
||||
const float FILTER_TIMESCALE = 0.5f * (float)NSECS_PER_SECOND;
|
||||
float del = deltaTime.count() / FILTER_TIMESCALE;
|
||||
if (del > 1.0f) {
|
||||
del = 1.0f; // clamp for stability
|
||||
}
|
||||
_measuredTimeAverage = (1.0f - del) * _measuredTimeAverage + del * measuredTime.count();
|
||||
float diff = measuredTime.count() - _measuredTimeAverage;
|
||||
_measuredTimeNoiseSquared = (1.0f - del) * _measuredTimeNoiseSquared + del * diff * diff;
|
||||
float noise = sqrtf(_measuredTimeNoiseSquared);
|
||||
|
||||
// check budget
|
||||
float budgetDelta = _budget.count() - _measuredTimeAverage;
|
||||
if (abs(budgetDelta) < noise) {
|
||||
// budget is within the noise
|
||||
return currentFrontBack;
|
||||
}
|
||||
|
||||
// clamp the step factor
|
||||
del = budgetDelta < 0.0f ? -_relativeStepDown: _relativeStepUp;
|
||||
|
||||
return currentFrontBack * (1.0f + del);
|
||||
}
|
||||
|
||||
glm::vec2 Regulator::clamp(const glm::vec2& backFront) const {
|
||||
|
@ -128,17 +153,24 @@ glm::vec2 Regulator::clamp(const glm::vec2& backFront) const {
|
|||
}
|
||||
|
||||
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]);
|
||||
// Note: for reference:
|
||||
// timings[0] = prePhysics entities
|
||||
// timings[1] = prePhysics avatars
|
||||
// timings[2] = stepPhysics
|
||||
// timings[3] = postPhysics
|
||||
// timings[4] = non-physical kinematics
|
||||
// timings[5] = game loop
|
||||
|
||||
auto loopDuration = timings[5];
|
||||
regionBackFronts[workload::Region::R1] = regionRegulators[workload::Region::R1].run(loopDuration, timings[2] + timings[3], regionBackFronts[workload::Region::R1]);
|
||||
regionBackFronts[workload::Region::R2] = regionRegulators[workload::Region::R2].run(loopDuration, timings[2] + timings[3], regionBackFronts[workload::Region::R2]);
|
||||
regionBackFronts[workload::Region::R3] = regionRegulators[workload::Region::R3].run(loopDuration, timings[4], regionBackFronts[workload::Region::R3]);
|
||||
|
||||
enforceRegionContainment();
|
||||
for (auto& outView : outViews) {
|
||||
|
|
|
@ -37,8 +37,8 @@ namespace workload {
|
|||
{ 250.0f, 16000.0f }
|
||||
};
|
||||
|
||||
const float RELATIVE_STEP_DOWN = 0.05f;
|
||||
const float RELATIVE_STEP_UP = 0.04f;
|
||||
const float RELATIVE_STEP_DOWN = 0.11f;
|
||||
const float RELATIVE_STEP_UP = 0.09f;
|
||||
|
||||
class SetupViewsConfig : public Job::Config{
|
||||
Q_OBJECT
|
||||
|
@ -212,20 +212,31 @@ namespace workload {
|
|||
};
|
||||
|
||||
struct Regulator {
|
||||
using Timing_ns = std::chrono::nanoseconds;
|
||||
Timing_ns _budget{ std::chrono::milliseconds(2) };
|
||||
glm::vec2 _minRange{ MIN_VIEW_BACK_FRONTS[0] };
|
||||
glm::vec2 _maxRange{ MAX_VIEW_BACK_FRONTS[0] };
|
||||
|
||||
glm::vec2 _relativeStepDown{ RELATIVE_STEP_DOWN };
|
||||
glm::vec2 _relativeStepUp{ RELATIVE_STEP_UP };
|
||||
|
||||
Timing_ns _budget{ std::chrono::milliseconds(2) };
|
||||
float _measuredTimeAverage { 0.0f };
|
||||
float _measuredTimeNoiseSquared { 0.0f };
|
||||
|
||||
Regulator() {}
|
||||
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) {}
|
||||
Regulator(const Timing_ns& budget_ns,
|
||||
const glm::vec2& minRange,
|
||||
const glm::vec2& maxRange,
|
||||
const glm::vec2& relativeStepDown,
|
||||
const glm::vec2& relativeStepUp) :
|
||||
_minRange(minRange),
|
||||
_maxRange(maxRange),
|
||||
_relativeStepDown(relativeStepDown),
|
||||
_relativeStepUp(relativeStepUp),
|
||||
_budget(budget_ns),
|
||||
_measuredTimeAverage(budget_ns.count()),
|
||||
_measuredTimeNoiseSquared(0.0f)
|
||||
{}
|
||||
|
||||
glm::vec2 run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current);
|
||||
void setBudget(const Timing_ns& budget) { _budget = budget; }
|
||||
glm::vec2 run(const Timing_ns& deltaTime, const Timing_ns& measuredTime, const glm::vec2& currentFrontBack);
|
||||
glm::vec2 clamp(const glm::vec2& backFront) const;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue