Unity only support FSR 1.0 in the newer URP and HDRP Scriptable Render Pipelines. VRChat uses the Built-In Render Pipeline because it predates the Scriptable Render Pipelines. Unity has not and will not be adding support for FSR to the BIRP, and just simply switching VRChat to use URP instead of BIRP would break all existing content as the materials are incompatible.
Both the SteamOS and OpenVR FSR implementations do not implement FSR properly as directed by AMD. As a result they produce a considerably worse image and degrade the quality of UI rendering. Properly integrating FSR 1.0 according to AMD’s directions requires inserting the upscaling step during post-processing. Specifically after anti-aliasing and tonemapping but before any effects that introduce noise, grain, etc. to avoid FSR’s sharpening pass affecting the noise.
AMD also specifies that upscaling should be done before rendering UI. On PC VRChat renders the Quick Menu and Main Menu separately from the avatars, world, and some UI elements like nameplates. This is to prevent the world’s post-processing from affecting the menus.
The Unity Post Processing Stack has a number of features including anti-aliasing, and various post-processing effects including tone mapping. VRChat already enables MSAA by default so most worlds don’t use the Post Processing Stack for anti-aliasing as it tends to just make things blurry so we’ll ignore that.
This means that the basic process for rendering a frame is:
- Render the world, avatars, and in-world UI like nameplates.
- Apply post-processing which involves:
2. Apply post processing effects
3. Apply Colour Grading & Tone Mapping
- Render Main Menu, Quick Menu, and HUD.
This is where we run into a few problems. AMD specifies that FSR should run after tone mapping but before any effects that add noise, but Unity runs them in the opposite order.
While it is theoretically possible to rewrite Unity’s Post Processing Stack to run these effects in a different order it would be a lot of work and this isn’t actually the biggest problem. In order to upscale using FSR we first need to render at a lower resolution until we upscale to the full resolution, and then render the rest of the frame at the full resolution. The SRPs as the name indicates allow you to “script” your render pipeline in C# either using your own custom code or Unity’s URP or HDRP packages. Since everything is done from C# it’s possible to modify the pipeline to tell it to render part of the pipeline at a lower resolution from the rest. This makes it relatively straightforward to render at a lower resolution until FSR upscales it and then render at the full resolution from that point on. This is what Unity has done to support FSR 1.0 in URP.
However Unity’s BIRP is a lot less flexible than the SRPs, and does not support rendering only part of the frame at a lower resolution. There are some ways to manually approximate the process but they come with additional overhead, had incompatibilities with the Post Processing Stack or some of the other techniques commonly used in VRChat, didn’t support DX11, or some other issue that made it unusable.
In summary there isn’t a technically feasible avenue to integrate FSR 1.0 with VRChat that produces an image of sufficient quality to justify the development time required to implement it and the trade-offs required to make it work, if it is possible to make it work at all without breaking existing content. This will still be the case following the previously mentioned engine upgrade as Unity’s implementation of FSR requires using an SRP which is incompatible with our existing content.
@splitscream In my testing prior to the the Steam Deck’s launch Steam OS FSR upscaling only applies if the application renders at less than the native 1280x800 screen resolution. VRChat always sets the rendered resolution to 1280x800 when it detects it is running on a Steam Deck so the Steam OS upscaling should never apply.