gamescope

repository·master·Indexed 26 days ago

https://github.com/valvesoftware/gamescope

A micro-compositor designed for low-latency game execution that can run as an embedded session or nested on a desktop. It provides a sandboxed Xwayland environment with features including FSR/NIS upscaling, integer scaling, frame-rate limiting, and Reshade effect support. Includes a Lua-based configuration and scripting system for display overrides and lifecycle hooks.

Tokens
6.4K
Snippets
11
Records
31
Agent score
90%

What's inside gamescope

  1. Integrate NVIDIA Image Scaling SDK (NVScaler/NVSharpen)

    master

    The NVIDIA Image Scaling SDK provides two compute shader algorithms:

    • NVScaler: A spatial scaling and sharpening algorithm (6-tap scaling + 4 directional scaling + adaptive sharpening).
    • NVSharpen: An adaptive directional sharpening-only algorithm for cases where no scaling is required.

    Note: If you integrate NVScaler, do NOT integrate NVSharpen, as NVScaler already includes a sharpening pass.

    Pipeline Placement

    Shaders must be called during the post-processing phase after tone-mapping.

    • Before NVScaler/NVSharpen: Apply low-pass filters like motion blur or light bloom to avoid sharpening attenuation.
    • After NVScaler/NVSharpen: Apply effects like film grain to prevent sharpening noisy/grainy regions.
  2. Use local scripts for development

    master
    To develop scripts without overriding your system installation, set the script_use_local_scripts convar. This prevents Gamescope from reading /usr/share/gamescope and /etc/gamescope, and instead reads from the ../config directory relative to where Gamescope is executed.
  3. Install and build gamescope from source

    master

    To build gamescope on Debian or Debian-based systems, you must first install the required dependencies using apt. After installing dependencies, initialize submodules, configure the build directory with meson, and compile using ninja.

    1. Install Dependencies

    apt install meson ninja-build pkg-config cmake libpipewire-0.3-dev hwdata libx11-dev libwayland-dev libvulkan-dev wayland-protocols libx11-xcb-dev libxdamage-dev libxcomposite-dev libxcursor-dev libxxf86vm-dev libxtst-dev libxres-dev libxmu-dev libxkbcommon-dev libcap-dev libsdl2-dev libavif-dev libpixman-1-dev liblcms2-dev libseat-dev libinput-dev xwayland libxcb-composite0-dev libxcb-ewmh-dev libxcb-icccm4-dev libxcb-res0-dev glslang-tools libluajit-5.1-dev libcatch2-dev

    2. Build and Run

    git submodule update --init
    meson setup build/
    ninja -C build/
    build/src/gamescope -- <game>

    3. Install

    meson install -C build/ --skip-subprojects
    apt install meson ninja-build pkg-config cmake libpipewire-0.3-dev hwdata libx11-dev libwayland-dev libvulkan-dev wayland-protocols libx11-xcb-dev libxdamage-dev libxcomposite-dev libxcursor-dev libxxf86vm-dev libxtst-dev libxres-dev libxmu-dev libxkbcommon-dev libcap-dev libsdl2-dev libavif-dev libpixman-1-dev liblcms2-dev libseat-dev libinput-dev xwayland libxcb-composite0-dev libxcb-ewmh-dev libxcb-icccm4-dev libxcb-res0-dev glslang-tools libluajit-5.1-dev libcatch2-dev
    
    git submodule update --init
    meson setup build/
    ninja -C build/
    build/src/gamescope -- <game>
    
    meson install -C build/ --skip-subprojects
  4. Build NVIDIA Image Scaling samples

    master

    The samples can be built using CMake. Depending on which sample you want to build, you must pass specific flags to the cmake command.

    Standard Build (DirectX 11/12):

    $> cd samples
    $> mkdir build
    $> cd build
    $> cmake ..

    Vulkan Sample:

    $> cmake .. -DNIS_VK_SAMPLE=ON

    NV12 Sample:

    $> cmake .. -DNIS_NV12_SAMPLE=ON

    Streamline Sample: First, set up the Streamline dependency (requires checking out the NVIDIA Streamline SDK first):

    $> cd samples\third_party
    $> setup_streamline.bat vs2019

    Then build the sample:

    $> cd samples
    $> cmake .. -DNIS_SL_SAMPLE=ON
  5. Configure Gamescope using Lua scripts

    master

    Gamescope uses Lua for its configuration and scripting system. Scripts ending in .lua are executed recursively in alphabetical order from the following directories:

    1. /usr/share/gamescope
    2. /etc/gamescope
    3. $XDG_CONFIG_DIR/gamescope (typically $HOME/.config/gamescope)

    Warning: Scripting/configuration is experimental and subject to change. Errors are output to the terminal without visual indicators in the UI.

  6. Integrate NVSharpen for sharpening only

    master

    If your application only requires sharpening (not upscaling), use NVSharpen. To integrate it, compile the NIS_Main.hlsl shader with NIS_SCALER set to 0 and the isUpscaling argument set to false.

    Note: If you require both upscaling and sharpening, use NVScaler instead, as it is faster and produces better quality by performing both operations in a single step.

    bool isUpscaling = false;
    // Note: NISOptimizer is optional and these values can be cached offline
    NISOptimizer opt(isUpscaling, NISGPUArchitecture::NVIDIA_Generic);
    uint32_t blockWidth = opt.GetOptimalBlockWidth();
    uint32_t blockHeight = opt.GetOptimalBlockHeight();
    uint32_t threadGroupSize = opt.GetOptimalThreadGroupSize();
    
    Defines defines;
    defines.add("NIS_DIRSCALER", isUpscaling);
    defines.add("NIS_HDR_MODE", hdrMode);
    defines.add("NIS_BLOCK_WIDTH", blockWidth);
    defines.add("NIS_BLOCK_HEIGHT", blockHeight);
    defines.add("NIS_THREAD_GROUP_SIZE", threadGroupSize);
    NVSharpenCS = CompileComputeShader(device, "NIS_Main.hlsl", &defines);
  7. Configure Color Space and HDR Modes

    master

    NVIDIA Image Scaling shaders support LDR and HDR with specific requirements:

    1. LDR: Color values in [0, 1] range. Input must be in display-referred color-space after tone-mapping and OETF (gamma-correction).
    2. HDR PQ: Color values in [0, 1] range. Input must be in display-referred color-space after tone-mapping with Rec.2020 PQ OETF applied.
    3. HDR Linear: Recommended range [0, 12.5] (where 1.0 = 80nits and 12.5 = 1000nits). Input can be linear scene-referred or linear display-referred.

    To use HDR, set the NIS_HDR_MODE define to either NIS_HDR_MODE_LINEAR (1) or NIS_HDR_MODE_PQ (2).

  8. Examples: Common gamescope usage patterns

    master

    Upscale a 720p game to 1440p with integer scaling

    gamescope -h 720 -H 1440 -S integer -- %command%

    Limit a vsynced game to 30 FPS

    gamescope -r 30 -- %command%

    Run the game at 1080p, but scale output to a fullscreen 3440×1440 pillarboxed ultrawide window

    gamescope -w 1920 -h 1080 -W 3440 -H 1440 -b -- %command%
  9. Dispatch NVScaler in DX11

    master

    To run the NVScaler compute shader in a DirectX 11 environment, bind the input SRV, the scaler coefficients SRV, the USM coefficients SRV, the output UAV, a linear clamp sampler, and the configuration constant buffer. Dispatch using the calculated block width and height.

    Example Dispatch:

    context->CSSetShaderResources(0, 1, input); // SRV
    context->CSSetShaderResource (1, 1, scalerSRV.GetAddressOf());
    context->CSSetShaderResource (2, 1, usmSRV.GetAddressOf());
    context->CSSetUnorderedAccessViews(0, 1, output, nullptr);
    context->CSSetSamplers(0, 1, linearClampSampler.GetAddressOf());
    context->CSSetConstantBuffers(0, 1, csBuffer.GetAddressOf());
    context->CSSetShader(NVScalerCS.Get(), nullptr, 0);
    
    context->Dispatch(UINT(std::ceil(outputWidth / float(blockWidth))),
                      UINT(std::ceil(outputHeight / float(blockHeight))), 1);
  10. Use Gamescope hooks and convars in Lua

    master

    Gamescope provides a Lua API to interact with configuration variables (convars) and lifecycle hooks.

    • gamescope.convars.<name>.value: Access or modify the value of a convar.
    • gamescope.hook(name, function): Register a callback function for a specific hook.

    Example: A script that enables composite_debug and toggles composite_force every 60 frames using the OnPostPaint hook:

    my_counter = 0
    
    gamescope.convars.composite_debug.value = 3
    
    gamescope.hook("OnPostPaint", function()
        my_counter = my_counter + 1
    
        if my_counter > 60 then
            gamescope.convars.composite_force.value = not gamescope.convars.composite_force.value
            my_counter = 0
            warn("Changed composite_force to "..tostring(gamescope.convars.composite_force.value).".")
        end
    end)
  11. Dispatch NVSharpen in DirectX 11

    master

    To run the NVSharpen compute shader in a DX11 context, bind the input resources, unordered access views (output), samplers, and constant buffers, then call Dispatch using the optimal block dimensions.

    context->CSSetShaderResources(0, 1, input);
    context->CSSetUnorderedAccessViews(0, 1, output, nullptr);
    context->CSSetSamplers(0, 1, linearClampSampler.GetAddressOf());
    context->CSSetConstantBuffers(0, 1, csBuffer.GetAddressOf());
    context->CSSetShader(NVSharpenCS.Get(), nullptr, 0);
    
    context->Dispatch(UINT(std::ceil(outputWidth / float(blockWidth))),
                      UINT(std::ceil(outputHeight / float(blockHeight))), 1);
  12. Override display settings in Gamescope

    master

    To make persistent user-level modifications, create a .lua file in $XDG_CONFIG_DIR/gamescope. You can override display properties by accessing gamescope.config.known_displays.

    Example: To override the Steam Deck LCD colorimetry, create ~/.config/gamescope/my_deck_lcd_colorimetry.lua with the following content:

    local steamdeck_lcd_colorimetry_spec = {
        r = { x = 0.602, y = 0.355 },
        g = { x = 0.340, y = 0.574 },
        b = { x = 0.164, y = 0.121 },
        w = { x = 0.3070, y = 0.3220 }
    }
    
    gamescope.config.known_displays.steamdeck_lcd.colorimetry = steamdeck_lcd_colorimetry_spec