reckfellENGINE

Variable Rate Shading: setup and limitations

Density maps, current KHR encoding, Viewport updates and quality trade-off checks.

On this page

VRS reduces fragment-shader work in selected regions of a 3D frame. Geometry resolution does not necessarily decrease. It is an optimization that may lose material detail, not a way to improve graphics.

Use VRS when measurements show high fragment-shading cost. It does not remove CPU, geometry or draw-call bottlenecks. For demonstration frames, establish the required quality without VRS first, then compare using the same camera and lighting.

Requirements

  • Forward+ or Mobile and device/driver support for the selected VRS path. Compatibility does not use the RD path described here.
  • Texture mode and a density map for the intended Viewport.
  • Map updates: Once for an unchanged map, Always when its contents change.

VrsMode=Texture alone proves neither GPU support nor reduced frame cost. Run the project with --verbose and inspect driver messages about fragment shading rate or fragment density map. The checked Windows/Vulkan log contained Attachment fragment shading rate. Pipeline fragment shading rate alone is not attachment-map support.

Do not select support from an old GPU list. The actual path depends on device, driver and backend. XR may provide a map through the active XRInterface; XR mode alone neither enables eye tracking nor guarantees a map.

Enable on the main Viewport

Set these exact Project Settings keys:

KeyValue
rendering/vrs/mode1 for Texture; 0 disables VRS, 2 selects XR
rendering/vrs/textureMap path, for example asset://vrs_map.png

At tree startup, the main Viewport receives these settings. In Texture mode the engine reads the image at the path and creates an ImageTexture. An empty path or missing map does not automatically create a useful map; an invalid file produces a load error. Changing ProjectSettings during play does not reconfigure an existing Viewport: update its properties directly.

For a SubViewport, set VrsMode, VrsTexture and VrsUpdateMode on that SubViewport. Main-window settings do not automatically configure every nested Viewport.

Minimal C# example

This helper creates a 16×16 map without mipmaps: a black center and a periphery with R=G≈0.5. It requests VRS on the supplied Viewport. This is a diagnostic map, not a production game-quality preset.

C#
using System;
using Reckfell;

public static class VrsMap
{
    // A small diagnostic map, not an optimal production quality preset.
    // The caller owns the returned resource.
    public static ImageTexture Create()
    {
        using var image = Image.CreateEmpty(16, 16, false, Image.Format.Rgb8);
        image.Fill(new Color(0.5f, 0.5f, 0));
        for (int y = 4; y < 12; y++)
            for (int x = 4; x < 12; x++)
                image.SetPixel(x, y, Colors.Black);
        return ImageTexture.CreateFromImage(image);
    }

    // Requests VRS; property readback does not prove hardware support or a speedup.
    public static void Apply(Viewport viewport, Texture2D map)
    {
        ArgumentNullException.ThrowIfNull(viewport);
        ArgumentNullException.ThrowIfNull(map);
        viewport.VrsTexture = map;
        viewport.VrsMode = Viewport.VrsModeEnum.Texture;
        viewport.VrsUpdateMode = Viewport.VrsUpdateModeEnum.Always;
    }
}

Create the map with VrsMap.Create(), then call VrsMap.Apply(GetViewport(), map). Retain the resource while needed. For an unchanged map, you can select VrsUpdateMode.Once after assignment. To disable it, select VrsMode.Disabled and clear VrsTexture; dispose your own resource after it is no longer used. Do not free the borrowed GetViewport().

Read map channels

R controls horizontal density and G controls vertical density; B is unused by the current conversion. Black preserves maximum density. Avoid JPEG and other lossy processing that changes numeric channel values.

Encoding depends on the VRS method. The current KHR fragment shading rate path applies floor(channel * 2 + 0.1), clamps to 0…2, then limits the axis ratio. For normalized map channels:

R, G in an 8-bit imageEncoded fragment size in the KHR path
0, 01×1
0, 1281×2
128, 02×1
128, 1282×2
128, 2552×4
255, 1284×2
255, 2554×4

This describes the current shader, not a promise of identical supported rates on every GPU. The old 0/85/170/255 table does not apply: for example, 85 does not raise an axis exponent from 0 to 1 under this formula. The current KHR converter does not encode 8×8. Fragment density maps use a different path: R/G inversion with a minimum of 1/255. Do not apply the KHR table to that path.

Do not make the map screen-sized without a reason. The internal attachment size is the Viewport’s internal resolution divided by the device’s VRS texel size, rounded up. A small input map covers the entire Viewport; its size is not the screen-pixel size.

Updates and result checks

VrsUpdateMode.Disabled stops map updates; it is separate from VrsMode.Disabled. Once copies the map once; after changing its contents, request Once again or use Always. Account for generation and copying cost when using a dynamic map.

Comparison procedure:

  1. Fix resolution, camera, lighting, AA and rendering scale. Warm the shader cache.
  2. Measure GPU frame time with VrsMode.Disabled.
  3. Enable the map in the same scene. Inspect fine textures, highlights, thin details and camera movement.
  4. Keep VRS only with a useful gain and acceptable image. Sharp geometry edges do not guarantee preserved material detail.

If there is no effect, check the renderer, support messages, map, VrsMode and VrsUpdateMode. If FPS does not improve, inspect GPU time and the actual bottleneck, frame caps and dynamic-map cost. Other projects’ measurements are not a promise for yours.

The example ran on current Windows/Vulkan with Forward+ and Mobile: map data, Viewport properties, an allocated VRS attachment and disabling. The log also contains a Vulkan-loader warning about finding layer manifests in the Windows registry; the run is not considered fully clean. Attachment bytes, actual shader invocation rate, FPS gain, image quality, XR and other GPUs were not established by this test.

Reckfell Engine documentationBack to top ↑
QUICK LINKSGetting startedEntity hierarchyC# & .NET 10Scenes and prefabs
Reckfell guides and full API K
reckfellENGINE
RECKFELL ACCOUNT

Sign in

Sign in to your Reckfell account.

One account for the entire Reckfell platform.