mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 15:43:50 +02:00
punish slow scripts and don't send updates while physics is still loading
This commit is contained in:
parent
cb848362ec
commit
83dc9ea6bb
4 changed files with 38 additions and 4 deletions
|
@ -4678,6 +4678,11 @@ void Application::packetSent(quint64 length) {
|
|||
}
|
||||
|
||||
void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) {
|
||||
|
||||
scriptEngine->setPhysicsEnabledFunction([this]() {
|
||||
return isPhysicsEnabled();
|
||||
});
|
||||
|
||||
// setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so
|
||||
// we can use the same ones from the application.
|
||||
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
|
||||
|
|
|
@ -215,6 +215,7 @@ public:
|
|||
qint64 getCurrentSessionRuntime() const { return _sessionRunTimer.elapsed(); }
|
||||
|
||||
bool isAboutToQuit() const { return _aboutToQuit; }
|
||||
bool isPhysicsEnabled() const { return _physicsEnabled; }
|
||||
|
||||
// the isHMDMode is true whenever we use the interface from an HMD and not a standard flat display
|
||||
// rendering of several elements depend on that
|
||||
|
|
|
@ -828,24 +828,42 @@ void ScriptEngine::run() {
|
|||
|
||||
_lastUpdate = usecTimestampNow();
|
||||
|
||||
qint64 totalSleepFor = 0;
|
||||
std::chrono::microseconds totalUpdates;
|
||||
auto lastLoopStart = clock::now();
|
||||
|
||||
// TODO: Integrate this with signals/slots instead of reimplementing throttling for ScriptEngine
|
||||
while (!_isFinished) {
|
||||
auto thisLoopStart = clock::now();
|
||||
|
||||
// Throttle to SCRIPT_FPS
|
||||
const std::chrono::microseconds FRAME_DURATION(USECS_PER_SECOND / SCRIPT_FPS + 1);
|
||||
const std::chrono::microseconds MINIMUM_SLEEP { FRAME_DURATION / 2 };
|
||||
|
||||
auto beforeSleep = clock::now();
|
||||
clock::time_point sleepTime(startTime + thisFrame++ * FRAME_DURATION);
|
||||
auto wouldSleep = (sleepTime - clock::now());
|
||||
auto avgUpdates = totalUpdates / thisFrame;
|
||||
|
||||
if (wouldSleep < avgUpdates) {
|
||||
sleepTime = beforeSleep + avgUpdates;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_until(sleepTime);
|
||||
|
||||
#ifdef SCRIPT_DELAY_DEBUG
|
||||
{
|
||||
auto now = clock::now();
|
||||
uint64_t seconds = std::chrono::duration_cast<std::chrono::seconds>(now - startTime).count();
|
||||
auto sleptTill = clock::now();
|
||||
uint64_t seconds = std::chrono::duration_cast<std::chrono::seconds>(sleptTill - startTime).count();
|
||||
if (seconds > 0) { // avoid division by zero and time travel
|
||||
uint64_t fps = thisFrame / seconds;
|
||||
// Overreporting artificially reduces the reported rate
|
||||
if (thisFrame % SCRIPT_FPS == 0) {
|
||||
qCDebug(scriptengine) <<
|
||||
"Frame:" << thisFrame <<
|
||||
"Slept (us):" << std::chrono::duration_cast<std::chrono::microseconds>(now - sleepTime).count() <<
|
||||
"Slept (us):" << std::chrono::duration_cast<std::chrono::microseconds>(sleptTill - beforeSleep).count() <<
|
||||
"Avg Updates (us):" << avgUpdates.count() <<
|
||||
"Last loop time (us):" << std::chrono::duration_cast<std::chrono::microseconds>(thisLoopStart - lastLoopStart).count() <<
|
||||
"FPS:" << fps;
|
||||
}
|
||||
}
|
||||
|
@ -874,16 +892,21 @@ void ScriptEngine::run() {
|
|||
qint64 now = usecTimestampNow();
|
||||
|
||||
// we check for 'now' in the past in case people set their clock back
|
||||
if (_lastUpdate < now) {
|
||||
if (_isPhysicsEnabledFunc() && _lastUpdate < now) {
|
||||
float deltaTime = (float) (now - _lastUpdate) / (float) USECS_PER_SECOND;
|
||||
if (!_isFinished) {
|
||||
auto preUpdate = clock::now();
|
||||
emit update(deltaTime);
|
||||
auto postUpdate = clock::now();
|
||||
auto elapsed = (postUpdate - preUpdate);
|
||||
totalUpdates += std::chrono::duration_cast<std::chrono::microseconds>(elapsed);
|
||||
}
|
||||
}
|
||||
_lastUpdate = now;
|
||||
|
||||
// Debug and clear exceptions
|
||||
hadUncaughtExceptions(*this, _fileNameString);
|
||||
lastLoopStart = thisLoopStart;
|
||||
}
|
||||
|
||||
qCDebug(scriptengine) << "Script Engine stopping:" << getFilename();
|
||||
|
|
|
@ -168,6 +168,8 @@ public:
|
|||
// NOTE - this is used by the TypedArray implemetation. we need to review this for thread safety
|
||||
ArrayBufferClass* getArrayBufferClass() { return _arrayBufferClass; }
|
||||
|
||||
void setPhysicsEnabledFunction(std::function<bool()> func) { _isPhysicsEnabledFunc = func; }
|
||||
|
||||
public slots:
|
||||
void callAnimationStateHandler(QScriptValue callback, AnimVariantMap parameters, QStringList names, bool useNames, AnimVariantResultHandler resultHandler);
|
||||
void updateMemoryCost(const qint64&);
|
||||
|
@ -236,6 +238,9 @@ protected:
|
|||
QUrl currentSandboxURL {}; // The toplevel url string for the entity script that loaded the code being executed, else empty.
|
||||
void doWithEnvironment(const EntityItemID& entityID, const QUrl& sandboxURL, std::function<void()> operation);
|
||||
void callWithEnvironment(const EntityItemID& entityID, const QUrl& sandboxURL, QScriptValue function, QScriptValue thisObject, QScriptValueList args);
|
||||
|
||||
std::function<bool()> _isPhysicsEnabledFunc{ [](){ return true; } };
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_ScriptEngine_h
|
||||
|
|
Loading…
Reference in a new issue