Building a virtual world means striking a balance between making it vivid, rich with objects in number and details, and render fluidity. The aesthetic research we have been pursuing on Redout started long ago, renovated itself not only once, twice, or even three times, but it’s a continuous process of innovation and emulation to improve every aspect of the visual fidelity of our game. As the first sentence implies, that needs to be balanced with going easy on the hardware so that the best possible experience can emerge. When you are racing faster than the speed of sound, fluidity matters. In light of recent events, to help spread information and data instead of estimates and guessing, we want to cover the methodologies we use to work towards this balance.
When porting games to consoles the standard approach is to benchmark, profile, then pick a resolution that guarantees the best compromise between visual quality and framerate hiccups. That’s a static resolution approach, which doesn’t scale too nicely with the increased performance demands of deferred rendering and most novel techniques attached to it (complex pixel shader, post process effects, screen space effects, etc…).
Most modern game engines support some kind of asymmetry between the frame buffer and the render target, allowing hybrid rendering solutions between different resolutions. More and more 4k games nowadays render the main game at a lower resolution than 4k (typically 2k or 1080p) and UI elements at native 4k. Some other games prefer a more creative approach to hybriding, such as rendering the game at full resolution and applying post process effects onto a downscaled frame buffer (which usually means a separate, specific, texture layer).
Dynamic Resolution Scaling (DRS, or Dynamic Resolution Adaptation, DRA) is a technique that allows to change the frame buffer resolution on the fly. This is a very expensive operation that requires the entire stack of texture buffers to be reallocated at runtime, and therefore is usually avoided in real time operations. Epic Games worked around the issue implementing a method to get rid of the buffers reallocation, picking the texture size needed from the full-resolution one stored in memory.
Alex Vlachos talks extensively about DRS and adaptive rendering in his 2016 GDC talk about Advanced VR Rendering Performance.
Most DRS solutions are online, meaning they dynamically scale resolution or some quality settings depending on a sample of the previous frames (typically a low number, to enhance responsiveness). Online scaling is basically the only possible solutions in most games, because the permutations of the player position, camera position, rotation, field of view and quality settings tend to infinite.
In Redout, you race on a whirling racetrack (*except when you don’t). But still, a racetrack. This means we have some control over the player position and rotation, which can be reasonably predicted.
We came up with a novel approach to the problem, diving into autonomous profiling: we let an AI racer go through all the tracks, sampling frame deltas and track positions. By collecting this data, we are able to know the approximate performances on every track piece (a segment that makes up the entire racetrack) and we can save it offline, meaning we don’t need to spend cpu time analyzing performances nor memory to keep the historical deltas. As a by-product, we can ease up the early pre-pass using precomputed visibility.
The best part of all this system is that its effects are very hard to notice.
This is an example of the earliest public implementation of the screenpercentage method, where the left portion of the screen is rendered at 50% and the right one at 100% (both vertical axis percentage, as mentioned below): https://www.youtube.com/watch?v=Uye_QlIXTe4
And here is a second example: https://www.youtube.com/watch?v=ePfKwmuebcs
Consider that both examples are missing anti-aliasing, which mitigates any downscaling artifacts, or any post-process effect which may actually hide those artifacts, and the cost-benefit ratio of this technique is pretty evident.
This is how the profiling looks on Xbox One X:
Each column identifies a track piece index (typically 150 meters long in-game), which gives us a very cheap (performance-wise) way to check where the player is. Each row identifies a racetrack. The number inside the cells shows the screen percentage we have to downscale to, if we want to keep the 60fps mean. Here is the data for the entire game:
|Screen Percentage||Occurrence||Resolution / Notes|
|100%||0.27%||3840 x 2160|
|90%||11.48%||3456 x 1944|
|80%||59.22%||3072 x 1728|
|70%||18.00%||2688 x 1512|
|60%||4.04%||2304 x 1296|
|50%||1.94%||1920 x 1080|
To underline how confusing this whole topic is, there has been controversy even on the use of percentages (even from sources like Forbes).
Computing the screen percentage by a single axis (specifically, the vertical one) is a standard practice in the industry because it simplifies every operation related to aspect ratio and screen manipulation. We use the same “r.screenpercentage” method as everyone else, properly documented by Unreal Engine devs in the source code (you need to be logged in and granted access by Epic Games to see it). Also, think 4k, 1080p, 720p, etc… They are all one-dimensional measurements of the vertical axis.
Explaining the framerate hiccups
When it comes to profiling and optimization, the first step is segmenting between CPU and GPU issues. GPU issues comes, strictly speaking, by three main parts: geometry rendering, post process, and lighting. In most games, they occupy pretty much the same percentage of the rendering pipeline. There are many ways to optimize all of them while you are building your games and measuring their performance indicators. When these ways aren’t viable and you are pixel-bounded, you have to lower the resolution. Or find an alternative, like the dynamic scaler we discussed above.
The CPU’s workload, on the other hand, gets often simplified to “moving objects around” and similar scope sentences, which are quite far from the truth. While we can agree it’s hard to find CPU-bound games nowadays, they still exist for many reasons.
Unreal Engine has a very intuitive way of displaying debug information on frame profiling: it splits the frame time (the time the entire process took from the end of two frames ago to the closure of the last frame) into the Game Thread time, Draw and GPU time. The Game time shows how long executing the code took; the Draw time shows how long the CPU took to prepare things for the GPU, and the GPU time shows how long the video card took to finalize the rendering. While these tasks run in parallel most of the time, the frame time is not just the longest of the three, as CPU and GPU need to synchronize to avoid very bad things to happen. This visualization gives a quick look at the problem: especially at early stages optimizations, this is enough to get the size and direction of a potential performance issue, before diving into much deeper profiling systems.
Back to the scaler data we collected, you can see there are some black cells. Those are where most of the noticeable framerate dips happen, and that’s because, in these sections we are looking at a CPU problem, mostly due to the sheer number and objects or materials that needs to be drawn. This is exactly where we concentrate all our optimization efforts.
On average, the speed of a Redout ship during a race ranges between 600km/h (372mph) to 1500km/h (932mph), depending on the racing class. At these speeds, crossing the city of Los Angeles latitudinally would take 4:42 mins to 1:52 mins. This should give an idea of what challenge it is to build a game world suitable to these speeds, while not making it look barren, and why the number of objects on screen can sometimes become a problem.
Why console optimizations take time
It’s hard to talk about this topic without breaking NDAs. Nevertheless, someone already did, describing the woes of console patches both from devs and platform holders point of view.
Long story short, releasing content on any console needs to go through a long, difficult and often unpredictable certification process, a form of Quality Assurance by the platform holder, which comes after the QA done by the developer. This creates a sometimes large time gap between when the game developer has completed work, and when the players will get that content.
This is also the reason why you often see less-than-average performing games on consoles improve drastically over time, sometimes several months after release. It’s not that the developers are unaware of performance issues: the whole process is inevitably shifted forward by a certain timespan. For an answer to the obvious question of why developers can’t fully optimize their games before the first console launch, we redirect to the article linked above: it’s a really worthwhile read in all cases, wrote by one of the most important indie devs out there – Rami Ismail.
The future of Redout: non-technical considerations
A Redout Xbox patch is rolling out on January 11th, which will sensibly improve performance for all Xbox users. Announcement of this patch was supposed to come the same day of the release, because that’s the best way to go for a small title like ours, but current things standing, we have no choice but to announce it now. This is optimization work we have concluded months ago. We are currently working on yet another patch, which release date cannot be confirmed yet.
Next time you download an update, it might still happen that Redout won’t be flawless: we’ll keep improving it. Or, it might even be that we already did, and the patch you wish for is already in the submission process tunnel. The team has been working tirelessly on performance improvements since the original release on PC. We have been submitting enhancement patches over patches and we’ll keep doing it for as long as possible.