Epic talks shop about stuttering in games that use its Unreal Engine and offers solutions to the problem

Mention the words ‘Unreal’ and ‘Engine’ to a PC gaming enthusiast, and they will no doubt immediately think of incredible-looking graphics, as demonstrated in the likes of Black Myth: Wukong, Senua’s Saga: Hellblade II, and A Plague Tale: Requiem. However, there’s probably one other thing that PC gamers associate with Unreal Engine and it is stutter. If you wondering just what that is and why it happens, the maker of UE has explained it all in a new blog and detailed just what it’s doing to prevent it.

Let’s start at the beginning. Shaders are small pieces of code that are used in graphics rendering to do a very specific task. It might be just to move a triangle about a screen or it could be for something such as calculating the colour of a pixel, based on multiple light sources, materials and other effects.

Unreal Engine is a game development tool that you program in C++ or via its built-in code blocks, called blueprints. To make it much easier to code graphics, an API such as Direct3D or Vulkan is used (application protocol interface), where you can issue one instruction and the API will then turn that into multiple other instructions for you.

However, the GPU in your graphics card doesn’t understand anything that the API spits out, so its drivers need to convert the code into a format that it can process. This is generally called shader compilation and in a modern, complex 3D game, there are tens of thousands of shaders that need to be compiled.

If the game tries to do this while you’re playing it, the CPU will be too busy compiling the required shaders to run the game at full speed, albeit somewhat briefly, and the game’s frame rate will suddenly drop. It then bounces back up once the compiling is done, and when this repeatedly happens over and over, you get stuttering. For Unreal Engine, as Epic describes it in more detail:

Rendering an object usually involves several shaders (e.g. a vertex shader and a pixel shader working together), as well as a number of other settings for the GPU: culling mode, blend mode, depth and stencil comparison modes etc. Together, these items describe the configuration, or state, of the GPU pipeline.

Some settings influence the executable shader code, so there are cases when the driver can only start compiling shaders when the draw command is processed. This can take tens of milliseconds or more for a single draw command, resulting in very long frames when a shader is used for the first time—a phenomenon known to most gamers as hitching or stuttering.

Modern APIs require developers to package all the shaders and settings they will use for a draw request into a Pipeline State Object [PSO] and set it as a single unit. Crucially, PSOs can be constructed at any time, so in theory engines can create everything they need sufficiently early (for example during loading), so that compilation has time to finish before rendering.

Epic then goes on to explain that, prior to Unreal Engine v5.2, its recommended best practice was to ‘bundle’ the most commonly required PSOs into a cache that would be created as the game starts up for the first time or when a save game or level is loaded. The problem with that approach, Epic says, is that it’s very resource-intensive and in games with dynamic content, it needs to be constantly updated.

The proposed fix

With the latest versions of Unreal Engine, Epic developed what it calls PSO precaching to counter the above problems.

When an object is loaded, the system examines its materials and uses information from the mesh (e.g. static vs. animated) as well as global state (e.g. video quality settings) to compute a subset of possible PSOs which may be used to render the object.

This subset is still larger than what ends up being used, but much smaller than the full range of possibilities, so it becomes feasible to compile it during loading. For example, Fortnite Battle Royale compiles about 30,000 PSOs for a match and uses about 10,000 of them, but that’s a very small portion of the total combination space, which contains millions.

A screenshot from Black Myth: Wukong, showing the use of maximum graphics settings

Black Myth: Wukong (Image credit: GameScience)

Objects created during map loading precache their PSOs while the loading screen is displayed. Those that stream in or spawn during gameplay can either wait for their PSOs to be ready before being rendered, or use a default material which was already compiled. In most cases, this only delays streaming for a few frames, which is not noticeable. This system has eliminated PSO compilation stuttering for materials and works seamlessly with user-generated content.”

However, the system isn’t perfect, and Epic acknowledges that shaders not associated with materials, called global shaders (used in post-processing effects like motion blur, for example), aren’t able to be fully precached like this. Compute shaders, yes, but not graphics shaders. “These types of PSOs can still cause rare one-time hitches when they are first used. There’s ongoing work to close this remaining gap in precaching coverage,” says Epic.

You might already know that your GPU drivers save compiled PSOs to your SSD or hard disk, so they can be quickly used again, but they can just be stored in the system memory. Unfortunately, the PSO cache can get pretty big and again, this is something that Epic is aware of and working on finding a solution to it: “We are working on solutions for reducing the memory impact and automatically deciding when precached PSOs can be kept alive.

Star Wars Jedi: Survivor fish tank - Skoova Stev

Star Wars Jedi: Survivor (Image credit: miHoYo)

In short, Epic seems to be saying that it knows shader compilation stuttering is a problem in games that use Unreal Engine, but it’s actively working on solutions to it all. But if you’ve reached this point and you’re thinking, ‘Yeah, that’s all fine and dandy, but I play games—I don’t make them,’ then I perfectly understand. After all, there’s nothing we can do to prevent shader compilation.

To that end, Epic has some clear advice to developers about what they can do to reduce the whole stuttering issue, such as using the latest version of UE and regularly profiling PSO hitches during development, but also that devs need to be aware that other things cause stuttering—gamers won’t know whether that’s a shader compilation problem or not, but they’re likely to blame it anyway.

Your next upgrade

Nvidia RTX 5090 Founders Edition graphics card on different backgrounds

(Image credit: Future)

Best CPU for gaming: The top chips from Intel and AMD.
Best gaming motherboard: The right boards.
Best graphics card: Your perfect pixel-pusher awaits.
Best SSD for gaming: Get into the game ahead of the rest.

It also recommends that developers don’t turn to using DirectX 11, pointing out that shader compilation stutter will still happen with that API, and there are fewer ways to reduce the issue in the older tech. As Epic explains, the answer lies in the near-future, not the past: “We are finally reaching a point where we have a viable solution, and there are also good initiatives to address the API shortcomings, such as the graphics pipeline library Vulkan extension.”

It’s great that Epic is recognising that PSO compilation stutter is a serious enough problem to warrant such a detailed blog, but I can’t help but feel that this is a little late in the day. After all, with so many UE games out there stuttering away already, the damage is already done.

Still, if the next generation of big-budget blockbusters is able to be shipped in a stutter-free state, then that’s one less thing to worry about. And the woes of Star Wars Jedi: Survivor will be a thing of the past.

Advertisements

Leave a Reply

Your email address will not be published. Required fields are marked *