Last week bugfixing continued as the stable 1.9.7 draws ever nearer. I got a chance to examine and improve the way the engine's main loop calculates time and updates the screen. Also, on Mac OS X, monitor vsync is now used for screen updates, so things should be running quite a bit smoother.
The engine's main loop used to work like this:
- Wait: main thread sleeps.
- Process events and call tickers.
- Render the view.
- Update the screen (GL buffer swap).
Why wait at all, you might wonder? One common reason for waiting is vsync, allowing screen updates to happen without tearing artifacts. Doomsday also lets you limit the maximum refresh rate (refresh-rate-maximum
), in which case more waiting is done in the loop to bring down the framerate to the requested level.
The main loop had a couple of fundamental problems stemming from the fact that waiting is done only after the screen has been updated. Because it is not possible to reliably estimate how long it will take to process events, run tickers, and render the view, screen updates began at an unpredictable point in time. This is very bad because for animations to appear smooth on screen, frame updates have to arrive at fixed intervals. As we've all experienced, fluctuation in the framerate is worse than having a consistent, lower framerate. Another flaw in the old scheme was that the actual frame rate was wildly missing its target value set by the cvar.
Long story short, I moved the waiting to occur just before the screen update, enabling the engine to precisely choose the moment when the update occurs. This makes a big difference when running without vsync (in the near future it will be possible to enable and disable vsync at runtime).
When I added a separate event queue for events that need to be handled only during the 35 Hz "sharp" ticks (to replicate 1.8.6 behavior), 1/35 seconds of latency was effectively added to each key and button event. If you yearn for shorter keyboard input latency, you can now use the input-sharp-lateprocessing
cvar to disallow sharp events from being processed after tickers so that they will become effective immediately on the next sharp 35 Hz tick. Late processing of sharp events is active by default.
Notes about this week's bugfixes:
- I modified the way finale scripts receive input events. Previously the events were passed directly to the finale interpreter, bypassing our event binding system. This meant that some events that should have went only to the menu were handled by the script. Also, the "shortcut" binding context is now available during finales.
- I made a slight modification in the finale script stack to prevent each press of F1 from starting a new "help" finale script instance.
- Fixed the manual panning in the automap. The issues were: the overall speed of the panning was way too small, the speed was not appropriately scaled to the current display resolution, and unnecessary scrolling animation was attempted with the panning (which screwed up the stability of the motion).
- Fixed an oversight where a sound effect was played during busy mode when changing games due to the recently added "view-size" value change notification.
- Fixed a couple of issues in Hexen: when standing on an object and touching another object, it was possible to walk through walls; there was no viewbobbing when walking on mobjs (e.g., barrels); the player falling scream was only being played in client mode.
I'm going to be traveling for most of this week, so I doubt I'll manage much progress with Doomsday.
Work continued last week on bug fixing for the 1.9.7 stable release, here are the highlights:
- I fixed an issue in the resource management which prevented replacement of the game lib's FONT* patches. This issue has been present for quite a while and which was rooted in the resource model. In Doomsday there used to be a special status for resources loaded from a .wad which bore the "IWAD" identification. The logic for whether a resource is considered replaceable, or indeed a replacement was determined by this status. This model had various shortcomings. The issue with the DOOM fonts (in jdoom.pk3) were but one example.
I changed the model so that all resources loaded from files associated with a Game (as registered through the public API) are now marked as not-custom (includes both .wad, .zip and any other type of file). All other resources loaded at any time are now considered to be custom ones.
- Skyjake's implementing support for vsync on Mac OS revealed various issues with Doomsday's GL startup order and default state configuration on all platforms. Effectively the engine was configuring the default state according to the preferred GL setup rather than the actual configuration on the host system. I addressed the issue and now GL startup is working correctly.
- A fatal error would occur on Windows when attempting alt+tab while the engine was in busy mode. This was caused by the Win32 window manager which attempted to modify the "ignore input" state directly, effectively bypassing busy mode and the result was an invalid engine state.
In addition to the bug fixing I also found some time to work on a few things for the homepage:
dengine.net is now able to answer the question "Which is the latest version of Doomsday for my configuration?" if posed in the form of an HTTP GET request, with a response in the form of a JSON formatted object graph.
For example, to query the latest unstable version of Doomsday for Windows one might parse the response from the address; http://dengine.net/latestbuild?platform=win-x86&unstable&graph
This work is the very beginnings of an object graph API which will allow our homepage to act as a data interchange hub between the various client components of the deng project. However to begin with, this means only relatively minor improvements to the homepage itself (e.g., a build repository constructed using AJAX technologies).
This coming week I plan to focus on the remaining items on the 1.9.7