It’s hard to cover everything in our game that can influence input latency in a single patch note, so while the following may summarize a few key points, it is by no means the whole picture. With that said, the CoH3 engine operates on a variable-framerate-fixed-timestep-simulation model. This model gives our engine the stability and determinism of running a fixed framerate game state combined with the flexibility of rendering a variable framerate on-screen visual state. The components of this model can be broadly categorized into an input layer, a deterministic game state processor, and a visual state processor. When the player generates an input, it is registered in the input layer and processed through the deterministic game state. Once the new game state containing that input has been generated, it is released to the visual state processor to be interpolated up to 30, 60, 144fps or more.
Let’s look at the changes coming in the 1.6.5 PC patch, and then we’ll go into specifics about what’s going on behind the scenes.
With CoH2, the input layer, game state processor, and the visual state processor all run in a single synchronous CPU processing thread with each system taking its turn in rotation as required for a given processing cycle. This means that an input generated by the player could be immediately followed sequentially by an update to the game state, which in turn could be followed immediately by an update to the visual state. This order of events provided a tight processing flow for inputs that led to a high response rate that we still hope to match with CoH3 today. However, this approach also comes at the cost of visual smoothness. Since each system works in rotation, each one will incur a periodic CPU usage spike resulting in unstable framerates. Being limited to a single processing thread also means that we cannot utilize the processing power of stronger CPUs and as a result this approach does not often scale well to modern hardware.
With CoH3, the deterministic game state processor and the visual state processor are each allocated their own CPU threads. This allows for a much higher and smoother throughput of frames but comes at the cost of having to synchronize data between these threads. Since these threads run independently, the order of events is not guaranteed to be as straightforward. As a result, an input may be left unattended until the game state processor thread is ready to service it. A common colloquialism used to describe this sort of latency is a ‘frame rule’ or ‘bus stop’ delay. If an input arrives just before the game state processor is ready to start processing a new game state, then its response is seen immediately. If it arrives just after processing has already started, then it “just missed the bus” and must wait an entire game state cycle before being processed. Another problem to consider is that the visual state processor cannot interpolate past the most recent game state. This means that if the game state (running asynchronously) takes too long, then the visual state must halt until the new game state is ready. This manifests on screen as a visual hitch or stutter in the game flow. To combat this, we employ a buffer of game states. If the game state (or network server for an online game) takes too long, we can subtly adjust the speed of interpolation for the remaining buffered states to seamlessly hide the visual stutter.
What we found in this update was that the buffering algorithm for game states was acting far too conservatively towards game smoothness. And while this commonly produced impeccable visual clarity, it also did so at the cost of undue input latency. The changes introduced in this patch reduce the weighting on the buffer table regarding network latency and CPU load, which should result in a significant reduction in input latency. However, this may make the game more susceptible to network and CPU usage spikes, so some players may notice a drop in visual smoothness or other artifacts. We will be monitoring this change and be ready to adjust things further as needed.
- The CoH3 Programmer Team