Workaround For Dynamic Resolution Artefacts

Aug 23, 2021.Knowledge

[Bug Workaround] Dynamic Resolution Artifacts

Occasionally we see a common bug that pops up in different shaders where artifacts appear at the edge of a screen, such as the example below:

Dynamic resolution works by scaling the viewport at any arbitrary resolution into a fixed size render target. This works on all platforms, and avoids the CPU overhead of reallocating render targets often. This also has the benefit of sharing the engineering efforts of split screen rendering.

However, this requires every rendering algorithm to correctly sample within the viewport, to avoid sampling uninitialized data outside. When one pass of the renderer samples uninitialized data on the edge of the screen, it may create pixel corruption within the viewport, which will be carried forward through the rest of the remaining pass of the renderer. Bloom, for example, is known to be very good at finding this corruption as it can generate from an abnormally bright pixel.

The best solution for this error is a common workaround which involves isolating the render pass in which the artifacts appear, and clamping UV values similar to the changes in CL3632823, to ensure the pixels are initialized.

To isolate the render pass in question, use of a graphics debugging tool such as RenderDoc for Windows and Linux (, PIX for Windows ( or any other platform specific GPU debugger provided by the platform manufacturer is required to discover which pass produces the corruption within the viewport. Once the pass is identified, you need to evaluate the shader code and identify which texture fetch may sample outside the viewport. Once found, you can then clamp the UV within the viewport.

CL CL3632823 is a good example of such a fix (NOTE: this error can happy in any shader, and is not necessarily in PostProcessTonemap, you must find the shader that is causing the error.):


A new float4 shader parameter, SceneUVMinMax, is added and bound to the shader:


The SceneUVMinMax values are calculated, which describes the extended view area that will require clamping:

Note that the +0.5 for Min and -0.5 for Max is required, in order for the clamp to work with ‘Nearest’ texture sampler, but also with a bilinear sampler.

Following that, within the shader, PostProcessTonemapper.usf, the new shader variable is declared:


A new function for clamping the UV values outside of the current area is added, which takes into account the calculation pass from the cpp file.

And this function is placed in the SceneUV calculation path:

Hopefully this gives you guidance for how to fix the issue highlighted. If you have any further questions, please ask them in a new question whilst referencing this article.