The map keeps drawing when the view gets busy
Two testers reported the map and the countdown clock freezing, one of them only on larger, more complex maps, and one of them until a death. Both details point at the same place. The gauges and the cockpit displays are redrawn in whatever time is left after the 3D view. The background loop is guaranteed a single pass per frame and gets more only while time remains before the frame is due, and one pass drew exactly one gauge. So a full sweep of ninety-odd gauges needed ninety-odd passes - free when there is spare frame, but on a busy map the 3D view eats all of it, the loop drops to its one guaranteed pass, and a sweep takes ninety-odd FRAMES. Seconds. A death makes the renderer skip every static object, the budget frees up, and the backlog drains at once: the display appears to come back to life. Worse, the copy phase that follows ended after a SINGLE display, so the map - one of three - came round only every third sweep. So: draw gauges to a 2ms slice rather than one per pass, which ties the refresh rate to elapsed time instead of to how much spare frame there happened to be; and copy every display before reporting the sweep done. Measured on a deliberately starved frame budget, which reproduces the reported symptom: 0.7 sweeps/s before, 3.1 after. At a normal budget 20/s, against 18-19 before - no cost to the healthy case. RP412GAUGESLICE tunes the slice and 0 restores the old behaviour, which reproduces the 0.7 exactly. RP412GAUGEDIAG=1 logs the rate; watching the screen cannot tell a display that has stopped refreshing from one whose picture simply is not changing, which is what made this hard to see. Also fixes the constructor calling Update() three lines before it initialised mDisplayToUpdate, so the first pass indexed the D3D device and surface arrays with whatever was on the stack. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+46
-1
@@ -21,6 +21,31 @@
|
||||
BitTrace Gauge_Renderer("Gauge Renderer");
|
||||
#endif
|
||||
|
||||
//
|
||||
// How long a single background pass may spend drawing gauges, in
|
||||
// milliseconds. RP412GAUGESLICE tunes it; 0 restores the original
|
||||
// behaviour of exactly one gauge per pass.
|
||||
//
|
||||
static long
|
||||
GaugeSliceMs()
|
||||
{
|
||||
static long
|
||||
slice = -1L;
|
||||
|
||||
if (slice < 0L)
|
||||
{
|
||||
const char
|
||||
*setting = getenv("RP412GAUGESLICE");
|
||||
|
||||
slice = (setting != NULL) ? atol(setting) : 2L;
|
||||
if (slice < 0L)
|
||||
{
|
||||
slice = 0L;
|
||||
}
|
||||
}
|
||||
return slice;
|
||||
}
|
||||
|
||||
//#######################################################################
|
||||
// Miscellaneous utilities
|
||||
//#######################################################################
|
||||
@@ -3683,7 +3708,27 @@ Logical
|
||||
|
||||
case background:
|
||||
{
|
||||
result = ProcessOneActiveGauge();
|
||||
//-----------------------------------------------------------
|
||||
// Draw gauges until the slice is spent, rather than exactly
|
||||
// one per pass.
|
||||
//
|
||||
// The background loop is only guaranteed a single pass per
|
||||
// frame; it gets more only while time remains before the
|
||||
// frame is due. On a busy map the 3D foreground eats the
|
||||
// whole budget, so a cycle of ninety-odd gauges takes
|
||||
// ninety-odd frames to come round and the displays sit
|
||||
// frozen for seconds. Working to a slice makes the refresh
|
||||
// rate depend on elapsed time instead of on how much spare
|
||||
// frame there happened to be.
|
||||
//-----------------------------------------------------------
|
||||
Time slice_end = Now();
|
||||
slice_end += GaugeSliceMs();
|
||||
|
||||
do
|
||||
{
|
||||
result = ProcessOneActiveGauge();
|
||||
}
|
||||
while (result && taskMode == background && Now() < slice_end);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user