Skip to main content

Overview

Ryujinx’s shader translation system converts NVIDIA Maxwell/Pascal GPU machine code into portable GLSL or SPIR-V shaders that can execute on OpenGL or Vulkan backends. This multi-stage translation pipeline includes decoding, intermediate representation (IR), optimization, and code generation.

Decoding

Parse Maxwell GPU instructions into an abstract syntax tree

Intermediate Representation

Transform into SSA-form IR for optimization

Optimization

Apply optimization passes to improve performance

Code Generation

Generate GLSL or SPIR-V output for host APIs

Translation Pipeline

Shader Decoding

The decoder parses Maxwell GPU binary instructions into structured blocks.

Instruction Decoding

Instruction Format

Maxwell instructions are decoded based on their encoding:

Control Flow Analysis

Instructions are grouped into basic blocks with no internal branches:
Compute dominator tree for optimization:

Intermediate Representation

The IR uses a low-level SSA (Static Single Assignment) form suitable for optimization.

IR Operations

SSA Form

The IR is converted to SSA form where each variable is assigned exactly once:

IR Example

Maxwell instruction to IR transformation:

Optimization Passes

Multiple optimization passes improve the generated code:

Dead Code Elimination

Constant Folding

Common Subexpression Elimination

Additional Passes

Copy Propagation

Replace uses of copied variables with their source

Algebraic Simplification

Apply algebraic identities (e.g., x * 1 = x, x + 0 = x)

Loop Invariant Code Motion

Move calculations outside loops when possible

Register Allocation

Minimize register usage through smart allocation

Code Generation

After optimization, the IR is converted to either GLSL or SPIR-V.

GLSL Generation

GLSL Output Example

SPIR-V Generation

For Vulkan, shaders are compiled to SPIR-V binary:

Instruction Translation

Shader Caching

Ryujinx implements a multi-tier shader cache to avoid redundant translations.

Cache Architecture

Shader Cache Implementation

Disk Cache Format

The disk cache stores:
  • Guest shader code: Original Maxwell binary
  • Host shader binary: Compiled GLSL/SPIR-V
  • Shader metadata: Stage info, bindings, attributes
  • Translation options: Flags used during translation
Location: {UserData}/games/{TitleId}/cache/shader/

Translation Options

Translation behavior is controlled by various options:

Advanced Features

Dual Vertex Shaders

Some games use two vertex shaders that must be combined:

Geometry Shader Passthrough

Optimization for simple geometry shaders:

Transform Feedback Emulation

For hosts without transform feedback support:

Performance Optimization

Shader Specialization

Specialize shaders based on dynamic state to generate more efficient code

Aggressive Inlining

Inline function calls to enable better optimization

Loop Unrolling

Unroll small loops with constant trip counts

Texture Array Flattening

Convert texture arrays to individual textures when beneficial

Debugging

Ryujinx provides tools for shader debugging:

Shader Dumping

Translation Logging

With TranslationFlags.DebugMode:
  • All IR operations are commented in output
  • Source line numbers are preserved
  • Optimization passes are logged

References

Source Files

  • src/Ryujinx.Graphics.Shader/Translation/Translator.cs
  • src/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs
  • src/Ryujinx.Graphics.Shader/Decoders/Decoder.cs
  • src/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs
  • src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs
  • src/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs