NR runtimes 310.8 and 310.9.16: static analysis (full technical)
Back to the report · ControlMask how-to · Noisy-domain NR feasibility
Written by Claude Opus 5.5 (Claude Code, high effort) on behalf of GrimsVerk, who skimmed it. The research, the test-build code changes, the measurements and this text are Claude's work.
Files: nvngx_dlssnr.dll 310.8.0.0 (CL 38718415, 165,840,496 bytes, SHA-256 4b8d19bc3eff58a084f5eca7489c921501c203450169fb82ff4f649a4482ba05) and 310.9.16.0 (CL 39025366, 266,424,944 bytes, SHA-256 2bc19bc09a7b89dd44f73e2ac0108fcc586e2154bdd0830f242f4f040e28789f).
Method:
- PE inventory with pefile; strings (ASCII and UTF-16) diffed between versions.
- Resource and weight-container parsing.
- CUDA fatbins unpacked (zstd) to PTX and SASS ELF.
- Full Ghidra 12.1.4 auto-analysis and decompile of both DLLs, image base
0x180000000.
"Seen in game" means the runtime's own NGX log confirmed it in The Witcher 3. The log was switched on with the __NGX_LOG_LEVEL environment variable, set in-process by the research build.
About line numbers. "l.NNNN" refers to a full decompile export (every function, Ghidra 12.1.4 default analysis, in address order). They only help if you make the same export. Function names and addresses (FUN_18xxxxxxx) are the stable reference: they are identical in any Ghidra project of the same file with the same base.
1. Summary
- Exactly two models exist, and only 310.9.16 has both:
CC_Control_History_Blend_Quantize_With_Teacher_honest_tench_2026_07_04_22_30_weights("honest tench"), resourceWEIGHTS_HT, 147,695,410 bytes;hnet-crazy-cuckoo-small-fp8("crazy cuckoo small"), resourceWEIGHTS_CC_SMALL_FP8, 113,893,343 bytes.
WEIGHTS_HTis byte-identical in both DLLs. The ~100 MB growth of 310.9.16 is the new small model.- Presets:
- 310.8 registers one preset (1 = honest tench); every value falls back to it, so Preset has no effect in 310.8.
- 310.9.16 registers preset 1 (honest tench) and preset 2 (crazy cuckoo). 0/auto and every unknown value fall back to preset 2 (seen in game: "preset 0 is not available in this DLL build; falling back to shipping default preset 2 ('hnet-crazy-cuckoo-small-fp8')").
hnet-almond-eagle-11mis not a third model. It is the string the on-screen indicator draws in place ofhnet-crazy-cuckoo-small-fp8(strcmp+ swap inFUN_18001c120). Nothing else references it.- No hidden presets, styles, models, weight files or debug views exist in either file. The weight registry, the descriptor list and the style tables were all read directly.
- Style is 0/1/2 in both versions; values ≥ 3 clamp to 2. Style is a network input and a colour grade applied to the result (section 4).
- New in 310.9.16:
DLSSNR.MaskBlendMode(0-3). It only has an effect with a suppliedDLSSNR.ControlMaskand AutoMask on. - 310.9.16 dropped Ada (RTX 40): CreateFeature only accepts arch 0x1B0, and only sm_120 code ships. 310.8 accepts 0x190 and 0x1B0 and ships sm_89 SASS.
- Both versions run both models in FP8. 310.8 also ships FP16 kernels, but they are unused.
- Parameters with no effect in either version:
- Depth / DepthInverted: the network's depth slot is hard-wired to null.
- BidirectionalDistortionField: sets a telemetry bit only.
- ScalingRatio / PerfQualityValue: never used for anything.
- Intensity above 1: clamped.
- A runtime-side reduced-resolution path with guided upsample exists, but it is dead code: its scale is fixed at 1.0. Downscaling must stay app-side.
2. PE inventory
| 310.8 | 310.9.16 | |
|---|---|---|
| File size | 165,840,496 | 266,424,944 |
| FileVersion / OriginalFilename | 310.8.0.0 / CL 38718415 | 310.9.16.0 / CL 39025366 |
| Source branch (paths in strings) | snippets/rel_310_8 |
snippets/rel_310_9 |
| NGXAppId (version resource) | literal APP_ID_HASH |
241534723 |
| NGXGpuArchitecture / NGXApiVersion / NGXMinimumDriverVersion | Blackwell2 / 0x13 / 615.00 | same |
| TimeDateStamp | 1786480171 | 1790318716 |
| SizeOfImage | 0x9e42000 | 0xfe2f000 |
| Exports | 55, identical names: D3D11/D3D12/Vulkan/CUDA entry points, GetAPIVersion, GetApplicationId, GetDriverVersionEx, GetGPUArchitecture, GetSnippetVersion, SetOverrideStatusCallback, SetRuntimeParamsCallback, SetTelemetryEvaluateCallback | same 55 |
| Imports | KERNEL32 (120), ADVAPI32 (3), USER32 (1), VERSION (3). CUDA/D3D/Vulkan only through NGX core callbacks | same |
| .text (VA / raw size) | 0x1000 / 0xaae00 | 0x1000 / 0xd5400 |
| .rdata | 0xac000 / 0x33800 | 0xd7000 / 0x38800 |
| .data | 0xe0000 / 0x1062800 (16.5 MB, entropy 5.3) | 0x110000 / 0x380a00 (3.7 MB, entropy 8.0) |
| .rsrc | 0x1165000 / 0x8cdae00 | 0x4b4000 / 0xf978e00 |
Resources (type 10 = RCDATA):
| Resource | 310.8 RVA / file offset / size | 310.9.16 RVA / file offset / size |
|---|---|---|
WEIGHTS_HT |
0x1165560 / 0x114a160 / 147,695,410 | 0x4b45b8 / 0x498db8 / 147,695,410 (identical bytes) |
WEIGHTS_CC_SMALL_FP8 |
absent | 0x918ecf0 / 0x91734f0 / 113,893,343 |
| VS_VERSION_INFO | 0x11650c0 / 0x1149cc0 / 1184 | 0x4b4110 / 0x498910 / 1188 |
CUDA fatbins (magic 50 ED 55 BA). Payloads are zstd-compressed. 310.8: each fatbin has sm_89 SASS + sm_120 PTX + sm_120 SASS. 310.9.16: sm_120 PTX + sm_120 SASS only. File offsets:
- 310.8: 0xdf0e0 0x4a2220 0x6fe100 0x94cb60 0xbd0990 0xdd4bc0 0x10e2a40 0x1121b90 0x1123af0 0x1126590 0x11293b0 0x112bd00 0x112e3f0 0x112fd90 0x113d3c0
- 310.9.16: 0x10e6d0 0x1dbed0 0x263ec0 0x2df920 0x36ed70 0x3d8990 0x45d280 0x46f140 0x4710a0 0x473b40 0x476960 0x4792b0 0x47b9a0 0x47d340 0x48a970
- The fused pre/post-block kernels are in the fatbin at 0x10e6d0;
cg2r_post_process_kernelis in the one at 0x47d340.
- The fused pre/post-block kernels are in the fatbin at 0x10e6d0;
PTX entry points: 310.8 has 231 (FP16 + FP8 variants); 310.9.16 has 120 (FP8 only, plus cc_cb_clear, cg2r_copy_kernel, cg2r_post_process_kernel, and the cuda_capture_*/cuda_font_kernel NGX helpers). Every 310.9.16 kernel name also exists in 310.8. No ONNX, TensorRT plans, LZ4 or DXBC were found. There is one SPIR-V blob in each (NGX helper).
Weights container format (both resources): u64 total size, then per tensor u64 name length, name, u64 record length, [u64 record length, u64 data length, u32 flag, data, 20-byte trailer: u64 0, u64 1, u32 element count]. Tensors are named blockN.layerM.layer, plus one blockN.layer0.blend_scale (2 bytes). Element counts equal data length / 2.
3. The two models
| honest tench (preset 1) | crazy cuckoo small (preset 2, 310.9.16 default) | |
|---|---|---|
| In 310.8 / 310.9.16 | yes / yes | no / yes |
| Tensors | 153 (71 blocks) | 77 (31 blocks) |
| Weight bytes | 147.7 MB | 113.9 MB |
| GPU weight heap (seen in game) | 140.9 MB | 108.6 MB |
| GPU work pool at 3840x2160 (seen in game) | 727.7 MB in 310.8 · 528.5 MB in 310.9.16 | 526.6 MB |
| Descriptor templates (blocks per stage) | {4, 4, 6, 8, 8} | {2, 2, 2, 2, 2} |
| Bottleneck | 8 transformer blocks at 1024 channels (q/k/v + FFN 4096) | the same 8 blocks |
| Registry entry | 310.8 0x1800b0d80 (stride 0x288); 310.9.16 0x1800dbe30 (stride 0x290) |
310.9.16 0x1800dbe30 + 0x290 |
| Arch tag string | CC_SILVER_AARDWOLD |
CC_SMALL_FP8 |
- Architecture. U-Net-style encoder/decoder: conv + windowed-attention (Swin, 1/2/4/8 heads at 32-256 ch) stages, split 16-head Swin at 512 ch, a 1024-ch ViT bottleneck, and a mirrored decoder. "Small" keeps the bottleneck and cuts the repeated blocks per stage.
- Quantisation. The honest tench weights already look FP8-quantised (few distinct byte values in the large matrices). That fits "Quantize_With_Teacher": quantisation-aware training, no quantisation at load time.
- Precision. Both runtimes append
_fp8to every kernel name and set activation dtype 2 for both models (310.9.16FUN_1800572f0; 310.8FUN_180032e20). - Memory. The work pool is set by the runtime, not the model: 310.9.16 needs about 527 MB at 4K for either model, 310.8 needs 728 MB. By working scale, 310.8 / 310.9.16:
| Scale | 310.8 | 310.9.16 |
|---|---|---|
| 0.875 | 583 MB | not logged |
| 0.75 | 433 MB | 311 MB |
| 0.625 | 310 MB | 222 MB |
| 0.5 | 203 MB | 144 MB |
| 0.33 | 86 MB | 62 MB |
- The same weights give the same picture. Preset 1 in 310.9.16 and 310.8 are the same weights. The pre-block parameter block differs only by the new 8-byte MaskBlendMode field (264 → 272 bytes); post-process and blend kernels have identical parameter layouts. In game, the two pictures differ only by the noise floor in all five scenes.
Registry entry layout (310.9.16; 310.8 is the same minus 8 bytes):
| Offset | Content |
|---|---|
| +0 | config name |
| +8 | preset id |
| +16 | resource name |
| +24 | arch tag |
| +0x20 | 1 (tone/structure inputs, likely) |
| +0x21 | 1 (automask channel path, likely) |
| +0x24 | 15 (input channel layout, likely) |
| +0x28 | 1 (style conditioning, likely) |
| +0x2c | 3 (style count, certain) |
| from +0x38 | 8 style-grade slots of 14 floats each |
4. Every parameter the runtime reads
"Create" = read in CreateFeature (310.9.16 FUN_180017b20, 310.8 FUN_180017e20). "Eval" = read by the per-evaluation parser (310.9.16 FUN_18001a020, 310.8 FUN_180019f30). "v0.3.8" = what OptiScaler-NR v0.3.8 sends.
| Parameter | Type | Read | Default | Values / range | What it does | 310.8 | 310.9.16 | v0.3.8 |
|---|---|---|---|---|---|---|---|---|
| CreationNodeMask, VisibilityNodeMask | uint | Create | 1 | node masks | multi-GPU only | yes | yes | 1 / 1 |
| DLSSNR.Width / Height | uint | Create | output size | > 0 | allocation size; the network runs at the active rect size and grows past this with a warning | yes | yes | work size |
| DLSSNR.Hint.Render.Preset | uint (& 0x7fffffff) | Create | 0 | 310.8: 1; 310.9.16: 1, 2 | picks the model; unknown values fall back to the shipping default (310.8: 1, 310.9.16: 2). Lookup: 310.9.16 FUN_180023c20, 310.8 FUN_180023a40 |
no effect (one model) | 1 = honest tench, 2 = small | 0 (→ 2) |
| DLSSNR.Color | resource | Eval | required | display-referred RGB in [0,1] | the picture to edit. Encoded (c - 0.5)/8; no exposure, sRGB, PQ or HDR handling; output always clamped to [0,1], alpha written as 1 | yes | yes | HUD-less picture |
| DLSSNR.Output | resource | Eval | required | same size as Color | result | yes | yes | yes |
| DLSSNR.MVec + subrect | resource | Eval | none | pixel units × MVecScale / MVec size | temporal history: previous network output fetched (Catmull-Rom) at uv + mv·scale/size; without MVec, or with Reset, history = current colour | yes | yes | game's DLSS vectors |
| DLSSNR.MVecScaleX / Y | float | Eval | 1.0 | see MVec | yes | yes | game's values | |
| DLSSNR.Depth + subrect | resource | Eval | none | not used. The pre-block kernel's depth slot is passed a literal 0 (310.9.16 l.26416) | read, unused | read, unused | passed | |
| DLSSNR.DepthInverted | uint | Eval | 1 | 0/1 | no effect (only feeds dead depth code) | yes | yes | passed |
| DLSSNR.Intensity | float | Eval | 1.0 | effective 0..1 | final lerp: out = orig + sat(I [× mask.r]) · (NR − orig). Not a network input; > 1 does nothing | yes | yes | 1 |
| DLSSNR.LocalToneStrength | float | Eval | 1.0 | unclamped | network input (channel 11, × ControlMask.g); also scales the style grade by clamp(tone, 0, 1) | yes | yes | 1 |
| DLSSNR.LocalStructureStrength | float | Eval | 1.0 | unclamped | network input (channels 12-14) | yes | yes | 1 |
| DLSSNR.SkinStructureStrength | float | Eval | -1 | -1 = follow structure; else unclamped | skin structure (channel 13) | yes | yes | -1 |
| DLSSNR.UseAutoMask | uint | Eval | 0 | 0/1 | 1: separate skin/structure channels (13, 14). 0: those are -1 and structure goes into channel 12. A ControlMask forces it to 0 (310.8 always; 310.9.16 only with MaskBlendMode 0) | yes | yes | 1 |
| DLSSNR.MaskBlendMode | uint | Eval | 0 | 0..3 (> 3 → 0) | new. With a ControlMask and AutoMask on: m = mask.b × structure is combined with the automatic skin/structure values, 1 average, 2 min, 3 max. 0 = the mask replaces AutoMask | no | yes | not sent |
| DLSSNR.ControlMask + subrect | resource | Eval | none | RGBA | per-pixel controls: r = intensity, g = tone, b = structure, a unused (see controlmask.html) | yes | yes | null |
| DLSSNR.Style | uint | Eval | 0 | 0, 1, 2 (≥ 3 → 2) | network input (channel 10 = style/128) and a colour grade on the result, × clamp(tone, 0, 1): 0 = none; 1 = exposure −0.1 EV, contrast −0.25, saturation −10 %; 2 = saturation −15 %. A change resets history | yes | yes | 1 |
| DLSSNR.Reset | uint | Eval | 0 | 0/1 | drops temporal history for this frame | yes | yes | on first frame |
| DLSSNR.Enabled | uint | Eval | 1 | 0/1 | 0 copies Backbuffer or Color straight to Output | yes | yes | 1 |
| DLSSNR.UICorrection | uint | Eval | 0 | 0/1 | with UI/UIAlpha (+ Backbuffer): NR is faded under UI by (1 − alpha), result rebuilt on the Backbuffer. With a Backbuffer and no UI, the network runs on the Backbuffer | yes | yes | 1 (no UI given) |
| DLSSNR.UI / UIAlpha / Backbuffer + subrects | resource | Eval | none | see UICorrection; alpha = UIAlpha.r, else UI.a | yes | yes | null | |
| DLSSNR.BidirectionalDistortionField + subrect | resource | Eval | none | no effect (one telemetry bit, l.20074) | yes | yes | not sent | |
| DLSSNR.ScalingRatio | float | Eval (310.8) / never (310.9.16) | 1.0 | no effect. 310.8 reads it and overwrites it with 1.0; 310.9.16 never reads it. Only the ComputeScalingRatio callback writes it (310.9.16 FUN_180012740, 310.8 FUN_180012e80): PerfQualityValue 2/5 → 1.0, 4 → 0.85 (0x1800d9848), else error; 310.8 → 1.0 (0x1800ad684) for 0/1/2/4/5 |
no effect | no effect | not sent | |
| DLSS.Indicator.Invert.X / Y.Axis | uint | Eval | 0 | 0/1 | moves the on-screen indicator only | yes | yes | not sent |
Evaluate parser struct P (310.9.16, 0x160 bytes):
| Offset | Field |
|---|---|
| +0 | Color |
| +0x18 | MVec |
| +0x30 | Depth |
| +0x48 | Output |
| +0x60 | ControlMask |
| +0x78 | UI |
| +0x90 | UIAlpha |
| +0xa8 | Backbuffer |
| +0xc0 | BDF |
| +0xd8 / +0xdc | MVecScale X / Y |
| +0xe0 | Intensity |
| +0xe4 | Tone |
| +0xe8 | Structure |
| +0xec | Style |
| +0xf0 | AutoMask |
| +0xf4 | MaskBlendMode |
| +0xf8 | Skin |
| +0xfc / +0x100 | effective skin / structure (both −1.0 when AutoMask is off) |
| +0x104 | Reset |
| +0x108 | DepthInverted |
| +0x10c | Enabled |
| +0x110 | UICorrection |
| +0x114 / +0x118 | indicator invert X / Y |
| +0x120 | downscale flag (always 0) |
| +0x124 | scale (always 1.0, clamped to [0.5, 1.0] by the constants at 0x1800d9844 and 0x1800d877c) |
| +0x128..+0x15c | 14-float grade vector |
Network input, 16 channels per pixel (same layout in both versions)
Built by the pre-block parameter setup (310.9.16 FUN_1800834b0, called via FUN_1800620c0 → FUN_180083ee0; pre-block PTX in the fatbin at 0x10e6d0, ~l.130-610 of the PTX):
| Channel | Content |
|---|---|
| 0-2 | Gaussian noise (Box-Muller), seeded every frame from x, y and a frame counter: part of the "detail" is sampled |
| 3 | 1.0 |
| 4-6 | colour, encoded (c − 0.5) · 0.125 |
| 7-9 | warped history (previous network output, Catmull-Rom) |
| 10 | Style / 128 |
| 11 | Tone × ControlMask.g |
| 12 | AutoMask on: 1.0; off: structure × ControlMask.b |
| 13 | skin structure (AutoMask on), else −1 |
| 14 | structure (AutoMask on), else −1 |
| 15 | 0 |
Pre-block kernel parameters (272 bytes in 310.9.16, 264 in 310.8):
| Offset | Content |
|---|---|
| +0 | Color |
| +8 | previous output |
| +16 | MVec |
| +24 | Depth (always 0) |
| +32 | ControlMask |
| +40 | MaskBlendMode (310.9.16) |
| +164 / +168 | MVecScale ÷ MVec size |
| +172 | DepthInverted |
| +176 | Tone |
| +180 | Structure |
| +184 | Style/128 |
| +188 / +192 | effective skin / structure |
| +196 | 15 |
| +200 | registry +0x21 |
| +204 | 0.0625 |
| +208 | frame counter |
The network output is a residual: x = enc(Color) + k·net, decoded as clamp(x·8 + 0.5, 0, 1), then blended with the warped history by a learned sigmoid weight (post-block PTX, ~l.13895-14125).
The final blend has two paths:
- Fused into the last network kernel:
..._simple_blend(no mask),..._control_mask, plus..._full_rectvariants when the rect is the whole texture. Picked byFUN_18001d2e0, rect test inFUN_18001d660. Used when the grade is the identity and there is no UI correction. cg2r_post_process_kernel: dispatched byFUN_18001ca00with 376 bytes of parameters. It handles the grade, UI correction, and the (dead) guided upsample.
5. Hidden and debug switches (complete list)
| Switch | Where | Effect |
|---|---|---|
env __NGX_LOG_LEVEL; registry LogLevel, EnableConsoleLogging (HKLM\SOFTWARE\NVIDIA Corporation\Global\NGXCore) |
both (310.9.16 l.11377-11394) | log level = max(registry, env, Init level). With 0, nothing is logged. Logging writes two lines per evaluation |
env __NGX_ENABLE_OVERRIDE_LOG_PATH + __NGX_LOG_PATH_OVERRIDE; registry EnableLogPathOverride + LogPath |
both (l.5971-5991) | log folder; files nvngx_dlssnr_<version>.log |
registry ShowDlssIndicator = 0x400 |
310.9.16 FUN_18006ac20 (l.81091-81131), drawn by FUN_18001c120 |
overlay "DLSSNR v.. (default) on/off · W x H · active/alloc · weights: |
registry ShowDlssWeights (non-zero) |
310.9.16 | only the "weights: |
env __NGX_SHOW_INDICATOR, __NGX_CUBIN_DISABLE_RESOURCE_CACHE; registry NgxCubinDisableResourceCache |
both (l.81120-81125) | indicator; kernel cache |
export NVSDK_NGX_SetRuntimeParamsCallback |
both | 310.8: NGXCG2R::PollRuntimeParams (FUN_18001ac30), called from EvaluateFeature (FUN_180018620, l.19254 of the 310.8 export) after the parser, queries the callback with feature 0x12 and 8 entries of 24 bytes {1, 2, id, present, double value}. Ids: 0 Enabled → +0x108, 1 Tone → +0xe4, 2 Structure → +0xe8, 3 Intensity → +0xe0, 4 Style → +0xec, 5 AutoMask → +0xf0, 6 Skin/1000 → +0xf4, 7 scale/1000 → +0x120 (divisor 1000.0 at 0x1800afc30). The NGX core in the game never set it (logged: "callback is NULL (core did not set it)"). The scale override does nothing: the network size is hard-wired to the output size (local_5d8 = 1.0). 310.9.16: the pointer is stored at 0x1804a0a80 and never read. |
| weight files on disk, config files, forced presets, debug views, alternative kernels | none in either version | weights only come from the embedded resources |
6. Runtime-side reduced resolution and guided upsample (dead code)
310.9.16 contains a complete reduced-resolution path (local_816, l.19225-19268 and 19819-19923):
- the network runs at floor(W·s + 0.5) × floor(H·s + 0.5);
- the full-resolution Color/Backbuffer is kept as the high source (copied to
dlssnr_guided_high_source_scratch, RGBA16F, if it aliases the output); - in
cg2r_post_process_kernel, a 17×17×12-bytetransferTileper 16×16 tile carries low-resolution deltas in Oklab (log-L ratio clamped ±2 and faded below L = 0.1, plus Δa/Δb), upsampled bilinearly onto the high source. That is the same idea as OptiScaler-NR's guided residual enlargement (Transfer 5), in Oklab and not edge-aware.
It is unreachable. P+0x124 is only written at parser initialisation (1.0, l.20203, disassembly 0x18001a12e) and clamped, so P+0x120 is always 0. DLSSNR.ScalingRatio is only written by the callback (l.14441) and never read. 310.8 ships the same transferTile code but also hard-wires the network size.
7. GPU architecture and precision
| 310.8 | 310.9.16 | |
|---|---|---|
| Arch accepted by CreateFeature | 0x190 (Ada) and 0x1B0 (Blackwell) | 0x1B0 only (error "Unsupported GPU architecture 0x%x, minimum required 0x%x") |
| SASS / PTX shipped | sm_89 + sm_120 / sm_120 | sm_120 / sm_120 |
| Kernel precision | FP8 used (FP16 present, unused) | FP8 only |
| Kernel families | Swin "tinlayout" fused blocks, split Swin 16-head 512 ch, ViT (2-D and 1-D token) 1024 ch, decoder upsample, CG2R post-process and copy | same, plus cc_vit_1d_* / mma-token1d-* / splitk-f16-* for the small model |
8. Key functions (Ghidra names, image base 0x180000000)
| Role | 310.9.16 | 310.8 |
|---|---|---|
| NGXCG2R::CreateFeature (reads Width/Height/Preset, arch check) | FUN_180017b20 |
FUN_180017e20 |
| NGXCG2R::EvaluateFeature | FUN_180018250 |
FUN_180018620 |
| Evaluate parameter parser | FUN_18001a020 |
FUN_180019f30 |
| Reset temporal history on control change | FUN_1800176c0 |
|
| Create previous-output texture | FUN_1800173b0 |
|
| CG2RNetworkManager::CreateNetwork / ResolvePresetToDescriptor | FUN_180021000 |
|
| CG2RNetworkManager::Evaluate | FUN_180021df0 |
|
| CG2RFindWeightByPreset (fallback preset 2 / 1) | FUN_180023c20 |
FUN_180023a40 |
| Weight registry lookup by name | FUN_180023b80 |
FUN_1800239a0 |
| CG2RLoadWeightBlob (FindResourceA type 10) | FUN_180023ca0 |
FUN_180023ac0 |
| Descriptor list builder | FUN_1800602e0 |
FUN_18003d670 |
| Backbone/template builder | FUN_18005c5a0 |
FUN_180039780 |
| Convert to FP8 kernels | FUN_1800572f0 |
FUN_180032e20 |
| Style grade lookup / write | FUN_18001d8a0 / FUN_18001d6d0 |
|
| Fused blend mode select | FUN_18001d2e0 |
|
| Post-process dispatch | FUN_18001ca00 |
|
| Pre-block parameters | FUN_1800834b0 |
|
| Indicator text / registry read | FUN_18001c120 / FUN_18006ac20 |
|
| ComputeScalingRatio callback | FUN_180012740 |
FUN_180012e80 |
| PollRuntimeParams | (removed) | FUN_18001ac30 |
| Log sink / log init | FUN_18000df60 / the function around l.11290 |
|
| Weight registry table | 0x1800dbe30, 2 × 0x290 |
0x1800b0d80, 1 × 0x288 |
Useful constants (310.9.16):
| Address | Value |
|---|---|
| 0x1800d9844 | 0.5 |
| 0x1800d877c | 1.0 |
| 0x1800d9848 | 0.85 |
| 0x1800dad8c | 0.9999 |
| 0x1800dad98 | −1.0 |
Appendix A: 310.9.16 parameter trace (line numbers = full decompile export)
Line numbers refer to the full 310.9.16 decompile export unless noted. "PTX" = cg2r_post_process_kernel (fatbin at file offset 0x47d340); "pre/post PTX" = the fused pre/post-block kernels (fatbin at file offset 0x10e6d0); PTX line numbers count from the start of that PTX text. CERTAIN = seen in code/data; LIKELY = inferred.
Corrections
- FUN_1800176c0 is called (state, mgr, &P) (l.19403); the first arg is the per-feature state (featureNode+8). Offsets +0x170.. are relative to that state. It does not compare Intensity. CERTAIN.
- P is 0x160 bytes; P+0x128..+0x15c = 14-float colour-grade vector; P+0x11c never written. CERTAIN.
Q1 Style
- Read unclamped into P+0xec (l.20519-20525); EvaluateFeature clamps with an unsigned compare against the descriptor style count = 3 (registry entry +0x2c): Style >= 3 -> 2 (negative also -> 2) (l.19388-19394; FUN_18001f640 l.24188; again FUN_180021df0 l.26376-26385). CERTAIN.
- Network input: Style/128 -> pre-block kernel param +184 -> constant input channel 10 (l.26414 -> FUN_1800620c0 l.75030 -> FUN_180083ee0 -> FUN_1800834b0 l.99528; pre PTX l.80-82,168). Both registry entries enable it (+0x28 = 1). CERTAIN.
- Also selects a colour grade: FUN_18001d8a0 (l.22743) looks up the style in 8 slots per registry entry; FUN_18001d6d0 (l.22679) writes value x clamp(LocalToneStrength,0,1) into P+0x128..; applied in cg2r_post_process_kernel. Data (CERTAIN):
- Style 0: no grade
- Style 1: exposure -0.1 EV, contrast -0.25 (flatter), saturation -10 %
- Style 2: saturation -15 %
- slots 3-8 empty; nothing hidden selectable.
- Grade engine has 14 controls (params +316..+371, host l.22327-22334; order from PTX l.720-1372): black point, white point, temperature, tint, exposure 2^v, contrast (smoothstep S-curve), 5-band per-channel tone curve, gamma c^(2^-v), HSL saturation x(1+v), saturation curve s^(2^-v). The styles use only three. Not reachable through parameters.
- An active grade forces the post-process pass (output clamped [0,1], alpha 1, fused blend off). A Style change resets temporal history.
Q2 Strengths
Pre-block params (FUN_1800834b0, 272 B): 0 Color; 8 previous network output (history); 16 MVec; 24 Depth = always 0 (literal, l.26416); 32 ControlMask; 40 MaskBlendMode; 164/168 MVecScale / MVec size; 172 DepthInverted; 176 LocalTone (raw); 180 LocalStructure (raw); 184 Style/128; 188/192 effective skin / effective structure; 196 = 15 (registry +0x24); 200 registry +0x21; 204 0.0625; 208 frame counter (noise seed). CERTAIN.
Input channels per pixel (pre PTX l.130-610), CERTAIN: | ch | content | |---|---| | 0-2 | Gaussian noise (Box-Muller, seeded by x, y, frame) | | 3 | 1.0 | | 4-6 | colour, encoded (c-0.5)0.125 | | 7-9 | history: Catmull-Rom at uv + mvscale/size; copy of colour if no MVec / no valid history / Reset | | 10 | Style/128 | | 11 | Tone x mask.g | | 12 | AutoMask on: 1.0; off: structure x mask.b | | 13 | skin (or structure if skin < 0); -1 when AutoMask off | | 14 | structure; -1 when AutoMask off | | 15 | 0 |
- Tone/structure are conditioning inputs (not a frequency split), not clamped. CERTAIN.
- MaskBlendMode acts only with ControlMask + AutoMask on + mode != 0: m = mask.b x structure into ch 13/14: 1 average, 2 min, 3 max. CERTAIN.
- Output is a residual: x = enc(Color) + knet, decoded clamp(x8+0.5,0,1), blended with history by a learned sigmoid weight (post PTX l.13895-14125). Math CERTAIN, meaning LIKELY.
- Intensity is never a network input. Blend only when Intensity < 1, ControlMask, grade, or UICorrection with UI (l.19478). Intensity > 1 does nothing.
- Fused blend in the last network kernel (FUN_18001d2e0 l.22490): _simple_blend (no mask), _control_mask (mask), _full_rect variants when the rect is the whole texture (FUN_18001d660). Needs identity grade and no UICorrection+UI. out = sat(orig + sat(I [x mask.r])*(net-orig)). CERTAIN.
- cg2r_post_process_kernel (FUN_18001ca00 l.21961): out = sat(orig + sat(Imask.r(1-uiAlpha))*(graded-base)) (PTX l.1375-2095). CERTAIN.
- => Intensity is effectively [0,1], a plain lerp. ControlMask: r = intensity, g = tone, b = structure, a unused.
Q3 Working scale
- P+0x124 is only written at parser init (1.0) and clamped; P+0x120 always 0. No NGX parameter feeds it. DLSSNR.ScalingRatio is only written by the callback (l.14441), never read. CreateFeature uses W x H at scale 1.0. CERTAIN.
- The downscale + guided path (l.19225-19268, 19819-19923) is dead code. It would run the network at floor(Ws+0.5) x floor(Hs+0.5), use full-res Color/Backbuffer as high source, and in the post-process kernel build a 17x17 transferTile per 16x16 tile of low-res deltas in Oklab (log-L ratio clamped +-2, faded below L = 0.1, plus da/db), upsampled bilinearly onto the high source: like the fork's Transfer=5 in Oklab, not edge-aware.
- Implication: keep downscale + guided enlargement on the app side.
Q4 Inputs
- Required: Color and Output (else skipped, 0xbad00005, l.19116).
- Colour: display-referred [0,1] only; no exposure input, no sRGB/PQ/HDR handling; output clamped [0,1]; alpha always 1. CERTAIN.
- MVec: needed for temporal history with valid history and Reset=0 (l.26151); uv_prev = uv + mv*MVecScale/size.
- Depth: never bound (literal 0) -> DepthInverted no effect. CERTAIN.
- BidirectionalDistortionField: only sets a telemetry bit (l.20074). CERTAIN.
- UICorrection + UI/UIAlpha + Backbuffer: out = Backbuffer + w*(graded(net) - Color), w x (1 - alpha), alpha = UIAlpha.r else UI.a. With UICorrection + Backbuffer but no UI/UIAlpha the network runs on the Backbuffer (l.19471). Without Backbuffer NR is suppressed under UI.
- Enabled=0: copies Backbuffer or Color to Output (l.19423).
- Rects: Color and Output same size (except full-texture Output with a Color subrect inside, l.19141-19211). Network runs at active size. Limits: non-zero sizes, buffer pool < 4 GB; LIKELY no alignment need.
Q5 Hidden switches
- Registry HKLM\SOFTWARE\NVIDIA Corporation\Global\NGXCore: ShowDlssIndicator (only 0x400: full overlay), ShowDlssWeights (non-zero: "weights:
", crazy-cuckoo shown as almond-eagle-11m). FUN_18006ac20 l.81091-81131, drawn FUN_18001c120. CERTAIN. - Registry NgxCubinDisableResourceCache; env __NGX_SHOW_INDICATOR, __NGX_CUBIN_DISABLE_RESOURCE_CACHE (l.81120-81125).
- Registry LogLevel, EnableConsoleLogging; env __NGX_LOG_LEVEL (l.11377-11394). Registry EnableLogPathOverride, LogPath; env __NGX_ENABLE_OVERRIDE_LOG_PATH, __NGX_LOG_PATH_OVERRIDE (l.5971-5991).
- DLSS.Indicator.Invert.X/Y.Axis only move the overlay.
- SetRuntimeParamsCallback stores a pointer that nothing reads: dead (310.8 PollRuntimeParams gone). CERTAIN.
- No config/weights files, no forced presets, no alternative kernels. cuda_capture_* kernels have no NR caller. CERTAIN.
Q6 Preset 1 in FP8
- FUN_1800602e0 builds both descriptors (templates {4,4,6,8,8} honest_tench, {2,2,2,2,2} crazy-cuckoo, LIKELY per-stage block counts); FUN_1800572f0 appends _fp8 to every kernel name and sets activation dtype 2 for both. 310.8 did the same for honest_tench (FUN_180032e20, line 45667 of the 310.8 export): preset 1 already ran FP8 in 310.8. CERTAIN.
- No quantization at load (bytes copied). WEIGHTS_HT already looks FP8-quantized (few distinct byte values), consistent with "Quantize_With_Teacher" QAT. LIKELY.
- Factory accepts only backbone "CCNetwork" (l.75151). CERTAIN.
- Registry bytes +0x20..+0x2f (same in both): +0x20 = 1 tone/structure inputs (LIKELY), +0x21 = 1 automask path (LIKELY), +0x24 = 15 input layout (LIKELY), +0x28 = 1 style conditioning (LIKELY), +0x2c = 3 style count (CERTAIN).
- 0/auto/unknown preset -> preset 2 (FUN_180023c20 l.27403).
Appendix B: what OptiScaler-NR v0.3.8 does not send, and what the tests showed
| Parameter | Result |
|---|---|
| Preset 1 on 310.9.16 | the old model inside the new runtime: the same picture as 310.8, about 3 % faster than 310.8, about 70 % more GPU time than preset 2 |
| ControlMask + MaskBlendMode | works exactly as traced; see controlmask.html |
| Tone / Structure / Skin above 2 | unclamped network inputs; Structure 4 breaks the small model's picture (+60 brightness, heavy flicker) |
| Style 0 | removes the built-in grade: visibly more colour and contrast than Style 1 |
| Depth, DepthInverted, BidirectionalDistortionField, ScalingRatio, Intensity > 1 | no effect in either version |