From cf96e58bd9adcfef429948f112213a6d461234c0 Mon Sep 17 00:00:00 2001 From: woutermans Date: Wed, 14 Oct 2026 21:11:42 +0200 Subject: [PATCH] engine/rr: bind the game colour and the exposure values for preset F's downp stage downp reads the game colour at argument 80 (the render rectangle, where it composites the particle layer) and scales its output by 1 / the exposure at buffer 72; left null/zeroed every output pixel was NaN - Cyberpunk 2077, which passes ColorBeforeParticles, showed black. --- engine/runtime_rr2.inc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/engine/runtime_rr2.inc b/engine/runtime_rr2.inc index b3009b2..016fabf 100644 --- a/engine/runtime_rr2.inc +++ b/engine/runtime_rr2.inc @@ -238,6 +238,10 @@ struct R2Engine { if (surface && offset == 40) return Resource{output, false, false}; } else if (stage == R2DownP) { if (surface && offset == 40) return Resource{output, false, false}; + // the game's colour, which this variant reads at the render rectangle (arguments 88 - 100) where it + // composites the particle layer. NGX binds it (a CUDA-path replay of a harness frame with + // ColorBeforeParticles, 2026-10-14); left null, the kernel's output is NaN (Cyberpunk 2077 showed black) + if (!surface && offset == 80) return G(in.color); if (surface && offset == 264) return T(pb[par]); if (!surface && offset == 208) return in.colorBeforeParticles ? G(in.colorBeforeParticles) : Resource{}; if (!surface && offset == 256) return T(pb[par ^ 1], true); @@ -477,9 +481,11 @@ struct R2Engine { bindImage(d.handle, set, binding++, res.view ? res.view : spare.at(format).view); } for (uint32_t offset : st.buffers) { - // the exposure values (enc0 256, post 16, down 72), enc0's second table (104); the progress counters - // are never accessed (their pointers are null) - const bool vals = (stage == R2Enc0 && offset == 256) || (stage == R2Post && offset == 16) || (stage == R2Down && offset == 72); + // the exposure values (enc0 256, post 16, down and downp 72), enc0's second table (104); the progress counters + // are never accessed (their pointers are null). downp scales its output by 1 / the exposure: with the + // zeroed dummy there every pixel was NaN (Cyberpunk 2077, which passes ColorBeforeParticles, showed black) + const bool vals = (stage == R2Enc0 && offset == 256) || (stage == R2Post && offset == 16) || + ((stage == R2Down || stage == R2DownP) && offset == 72); bindBuffer(d.handle, set, binding++, vals ? values : (stage == R2Enc0 && offset == 104) ? model.aux : dummy); } return set;