Skip to content

Shader containers and permutations

AnvilShadersApplies toRR

Riders Republic stores Shader Model 5 DXBC programs both in material templates and in ShaderDataDX11.bin beside the game executable. A template chooses its own code through stage-specific permutation tables; global passes also come from the standalone pack. Observed

The pack is 2,443 consecutive DXBC containers followed by 16 bytes containing the MD5 of everything before them. Every container’s stored checksum and the pack’s MD5 agree over the complete file; there are no intervening records. Resource-definition metadata is stripped from these programs. Proven · complete pack

All 432 template entries contain a stage-separated permutation table. Across base and patch copies, 177,578 records select 55,130 code frames: 124,398 vertex records and 53,180 pixel records. There are 13,790 distinct container byte sequences. Every UCodeHash resolves within its own template and stage; no code frame is unreferenced and no hash repeats within that stage. Proven · all template records

ShaderPermutation record41 bytes39% known
ProvenObservedSourcedInferredUnknownNot described
OffsetSizeTypeFieldConfidenceNotes
0x08u64stored identityUnknownzero in all 177,578 records
0x84u32 = 0x9467F2BBShaderPermutation classProven
0xC4u32ShaderKeyProven
0x104u32 = 0Parameters countProven
0x144u32UCodeHashProven
0x1816bytesstored digest-like dataUnknownnot identified as a tested common container hash
0x281u8stored byteUnknown0 in the table census

A code frame starts with ShaderCodePermutation class 0x7C7AC9C7, u32 byte length and that many DXBC bytes, followed by UCodeHash and a pass-like u32. Eight bytes after that are often zero but form the next element at stage boundaries, so they are not a universal reserved trailer. Proven · 55,130 frames

Vertex records precede pixel records. Each record block sorts by ShaderKey; each code block sorts by UCodeHash. One extra four-byte gap separates stages. Many keys share a code frame, and the key sets are sparse rather than the full product of their varying bits. Proven · all 432 templates

ShaderKey >> 22 Pixel output profile Confidence
0 No render target; depth/shadow family Proven · all corresponding containers
1 G-buffer: usually four targets; some families have three or five Proven · all corresponding containers
2 One target, often light-list reads; forward family Proven · all corresponding containers
3 One target; two distinct pixel programs across seven template names Proven · table census
4 Four targets, structured UAVs u6/u7, atomic allocation and fragment stores Proven · all 888 distinct containers

The code-frame pass value agrees with key>>22 except for 480 vertex records in 16 templates that reuse a pass-0 frame for pass 2. Proven

Static inspection of the engine’s key composer identifies bits 22–29 as pass, bits 17–21 as vertex layout, bits 14–16 as variants, bits 6–13 as features and the low bits as Material state. Layout bits enter the vertex key; Material bits 1–5 enter the pixel key. Observed · composer disassembly and Rocks table comparison

Bit Producer or effect Confidence
0x40 Both TwoSided and FlipNormalOnBackFace, gated by a template feature; adds front-face input Observed · composer and all one-bit shader comparisons
0x4 LayerMaterial in the G-buffer pass, gated by the template Observed · composer
0x20 LayerMaterial with nonzero blend mode, requiring 0x4 Observed · composer
0x80, 0x100 Reduced-material draw levels, gated by template support Observed · composer
0x200–0x1000 Base draw features with template and vertex-layout restrictions Observed · composer
0x2000 Vertex-pulling draw flag Observed · composer
0x4000 Draw-time variant; Rocks uses it for LOD dither discard, not texture alpha test Observed · variant code and Rocks shaders
0x8000 Instance-related variant; vertex layout 10 also requests it Observed · composer and shader comparisons
0x10000 Variant associated with vertex colour and structured inputs Observed · one-bit shader comparisons

The cache resolves all eight subsets of bits 14–16 into eight slots; it does not choose the first available subset. The later draw-time choice among them is unresolved. Rocks’ ordinary opaque Material has LayerMaterial clear, so its normal-map-alpha roughness path applies; the constant-roughness 0x20 permutation is not evidence that ordinary Rocks uses roughness 1. Observed · composer and permutation lookup

Which draw selects each cached variant?

The base-key and draw-flag producers, the final choice among eight cached subsets, the pass-4 consumer and the meaning of the 16-byte record data remain unresolved. Unknown