Icon of Sin / Baphomet
Register | User Profile | Member List | F.A.Q | Privacy Policy | New Blog | Search Forums | Forums Home
Doomworld Forums : Powered by vBulletin version 2.2.5 Doomworld Forums > Classic Doom > Source Ports > TryRunTics is not aware of screenwipe delay
 
Author
All times are GMT. The time now is 16:31. Post New Thread    Post A Reply
Quasar
Moderator


Posts: 6087
Registered: 08-00


It seems like every time there is a screenwipe, TryRunTics decides that it is really far behind in running the game and decides to run a few dozen gametics all at once.

This normally isn't noticeable except when you transition from playing a map back to the demo sequence (for example, F7 during a demo to drop back to the titlescreen) - then suddenly you notice that the titlescreen lasts about a half or 2/3rds the amount of time that it would normally.

This bug is ancient, going all the way back to the foundations of the engine, and in fact I first noticed it while working on Chocolate Strife.

I think ZDoom fixes this; my question is how precisely its fix works and if it can be adapted into Eternity.

Old Post 09-12-11 01:05 #
Quasar is offline Profile || Blog || PM || Email || Homepage || Search || Add Buddy IP || Edit/Delete || Quote
DaniJ
Senior Member


Posts: 2131
Registered: 08-03


I've got zero experience with the software renderer but I would guess the reason this happens is due to rendering multiple frames while the game timer is still progressing. Naturally a wipe requires quite a few frames so if your game timer is still counting up during the process you're going to get a large delta come next simulation time. Why is the playsim thinking during a screenwipe in any case?

Is your game loop fully decoupled from rendering, or does it block waiting on completion of a "sharp" tic (i.e., 1/35)? There should be both upper and lower bounds on the maximum tics to simulate per cycle.

Here's a good article on the general subject of decoupling the game loop: http://gafferongames.com/game-physi...-your-timestep/

Old Post 09-12-11 04:06 #
DaniJ is offline Profile || Blog || PM || Search || Add Buddy IP || Edit/Delete || Quote
myk
volveré y seré millones


Posts: 15226
Registered: 04-02


Does this bug work in vanilla or does it just happen on modern systems? I blasted myself against the walls in MAP32 for a few minutes to produce the wipe screen tons of times in succession yet when I ended the game the title screen seemed to last about normal.

Old Post 09-12-11 04:29 #
myk is offline Profile || Blog || PM || Email || Homepage || Search || Add Buddy IP || Edit/Delete || Quote
Maes
I like big butts!


Posts: 12653
Registered: 07-06


Hmm... I had an experience or two with that, when trying to get the wiper to work with the rest of the stuff. I always thought that the way it worked was letting at least one frame of the game run (so that there is something to transition to) and then trying to run the wipe in a fixed amount of time, if possible, or skip ahead the wipe itself if it's taking too long.

I didn't really take notice if the tics used in the wiper "count" towards gameplay too, or if it sort of "freezes" the actual game until the wipe is over, also because the wiper "traps" the game in a loop of its own and uses just I_GetTime()...hmm it's worth sorting out.

The solution would be resetting I_GetTime() to whatever value it was before the wiper, or using a separate timer for the wiper altogether, or monitor the "just wiped" condition and hack TryRunTics itself.

Old Post 09-12-11 08:05 #
Maes is offline Profile || Blog || PM || Homepage || Search || Add Buddy IP || Edit/Delete || Quote
Quasar
Moderator


Posts: 6087
Registered: 08-00



myk said:
Does this bug work in vanilla or does it just happen on modern systems? I blasted myself against the walls in MAP32 for a few minutes to produce the wipe screen tons of times in succession yet when I ended the game the title screen seemed to last about normal.


Just a misunderstanding, as the amount of lag-behind does not accumulate between multiple wipes. The only way that would happen is if the wipes ran back-to-back without interruption of even a single main loop iteration, which never happens due to how the engine is programmed (it must see wipegamestate change values before it'll wipe again).

The amount of lag is always small, and is slightly variable, since the asynchronous timer will increment by a slighly different amount every time, depending on such uncontrollable factors as precision drift, process switching, cache misses, disk IO, etc.


Maes said:
The solution would be resetting I_GetTime() to whatever value it was before the wiper, or using a separate timer for the wiper altogether, or monitor the "just wiped" condition and hack TryRunTics itself.

Right and I think that is what ZDoom might be doing with its I_FreezeTimer function, but, as with a lot of stuff in ZDoom, the comments only mention the what and not the why, and it's not exactly self-explanatory code.

Old Post 09-12-11 13:55 #
Quasar is offline Profile || Blog || PM || Email || Homepage || Search || Add Buddy IP || Edit/Delete || Quote
DaniJ
Senior Member


Posts: 2131
Registered: 08-03


As I said; don't progress game time during a screenwipe. You should be able to still perform a game loop iteration if necessary without having the playsim think. Obviously this has implications for any other asynchronous threads like audio (but then thats easily dealt with by deferring music playback to begin on the first tic after the wipe).

Old Post 09-12-11 16:01 #
DaniJ is offline Profile || Blog || PM || Search || Add Buddy IP || Edit/Delete || Quote
Maes
I like big butts!


Posts: 12653
Registered: 07-06


The standard way that I_GetTime() works in most ports is as an "absolute" time from an arbitrary time reference point (usually when the whole source port is first fired up and important stuff is initialized).

Whenever it's queried, it simply does a "currentTime() minus storedTime" calculation and returns the equivalent time in tics.

"Freezing" it would require specifically altering the value of storedTime somehow so that the next time I_GetTime() gets called it starts counting tics from zero all over again or just resumes the tic count from where it was "freezed", as you can't really stop currentTime() from progressing (it's a system specific function).

Old Post 09-12-11 16:52 #
Maes is offline Profile || Blog || PM || Homepage || Search || Add Buddy IP || Edit/Delete || Quote
DaniJ
Senior Member


Posts: 2131
Registered: 08-03


Perhaps I'm simply too used to Doomsday's architecture which already has these mechanisms in place...

Yes you would definitely need to either freeze or run another timer in parallel. You don't need to freeze "real time", its the game time you need to freeze. If the latter is defined entirely as the offset between two real time samples then essentially you don't have a decoupled game loop at all, you have a glorified spin lock.

Old Post 09-12-11 17:07 #
DaniJ is offline Profile || Blog || PM || Search || Add Buddy IP || Edit/Delete || Quote
Maes
I like big butts!


Posts: 12653
Registered: 07-06



DaniJ said:
If the latter is defined entirely as the offset between two real time samples then essentially you don't have a decoupled game loop at all, you have a glorified spin lock.


This very aspect caused a problem with Mocha Doom and some older Athlon Dual Cores, when using the high-precision System.nanoTime() function as the "currentTime()" function: its output was core dependant and could even end up locking the wiper in-place or give fucked up timing problems in other programs, too.

The solution in that case was to either download a patch from AMD that definitively fixed the problem system-wide, or try and come up with some fucked up heuristics that tried to understand whether you were running in an "unstable timer" environment.

Interestingly, using the standard System.getTimeMillis() function (which on Windows maps directly to Win32's GetTickCount, if I recall correctly) caused no such problems, since it was not core-specific, but then you'd be limited to the fugly Win32 15-16 ms timer resolution.

Old Post 09-12-11 17:23 #
Maes is offline Profile || Blog || PM || Homepage || Search || Add Buddy IP || Edit/Delete || Quote
kb1
Member


Posts: 379
Registered: 11-06


MBF had a fix for pausing during the demo in G_Ticker, by creating "basetic":
code:
if (paused && demoplayback) { // For revenant tracers and RNG -- we must maintain sync basetic++; }
I think this could be adapted in a way to also allow you to fix TryRunTics without putting a multi-level demo out-of-sync. You could fudge around with gametic, similarly to what basetic does, possibly by creating "realgametic", but you might have an awful lot of testing to do. You'd have to make the simulation think nothing has changed, and at the same time make TryRunTics think that a wipe didn't occur.

Maybe look at it from another angle: What happens if you just disable the wipe temporarily? Does a multi-level demo actually go out of sync?

An interesting find!

Old Post 09-12-11 20:34 #
kb1 is offline Profile || Blog || PM || Search || Add Buddy IP || Edit/Delete || Quote
Quasar
Moderator


Posts: 6087
Registered: 08-00


No, this isn't like the basetic problem at all.

This problem stems from I_GetTime and TryRunTics thinking that it needs to run a lot of gametics in order to catch up with real time - the same as if the game were running slowly due to having too many monsters - it would run a lot of tics and then the game would only render as often as it could manage between them, which means you are experiencing an FPS drop.

This is not about the gametic counting; it's about the measurement of real time.

Old Post 09-12-11 22:00 #
Quasar is offline Profile || Blog || PM || Email || Homepage || Search || Add Buddy IP || Edit/Delete || Quote
kb1
Member


Posts: 379
Registered: 11-06



Quasar said:
No, this isn't like the basetic problem at all.
This is not about the gametic counting; it's about the measurement of real time.

Well, you could take the wipe loop out of D_Display, and inhibit processing events while the wipe is active. That would keep the tics rolling, but, you'd have to disable this mechanism for old demo sync.

Essentially, those accumulated tics *should be occurring* during the wipe, but the wipe loop temporarily hijacks that ability. So, the trick is to either:

A. Fudge the timing by throwing away those tics.
B. Allow the tics to run while the wipe occurs.

Edit:
I don't think I notice this problem much, becuase I have a setting that prevents new demos from playing for a couple of seconds while menu/function keys are being pressed. I always found it annoying to be messing with options, and have a 2 second delay while waiting for the wipe to occur.

Last edited by kb1 on 09-12-11 at 22:48

Old Post 09-12-11 22:37 #
kb1 is offline Profile || Blog || PM || Search || Add Buddy IP || Edit/Delete || Quote
All times are GMT. The time now is 16:31. Post New Thread    Post A Reply
 
Doomworld Forums : Powered by vBulletin version 2.2.5 Doomworld Forums > Classic Doom > Source Ports > TryRunTics is not aware of screenwipe delay

Show Printable Version | Email this Page | Subscribe to this Thread

 

Forum Rules:
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is OFF
vB code is ON
Smilies are OFF
[IMG] code is ON
 

< Contact Us - Doomworld >

Powered by: vBulletin Version 2.2.5
Copyright ©2000, 2001, Jelsoft Enterprises Limited.