Files
Sylpheed/docs/re/data/blend-space-rt-format.txt
sylph-decoder 5436ba2039 re: the game blends in the ENCODED space -- no gamma render target, anywhere
The Port asks whether the blend is evaluated on sRGB-encoded values or
linearised and re-encoded. It is answered by one register field I already
log, and the answer is the same on every draw of two full captures.

RB_COLOR_INFO.color_format is k_8_8_8_8 (0) on 2402/2402 splash draws and
33779/33791 draws of the boot-through-title capture; the other 12 are
k_32_FLOAT and k_16_16_FLOAT and are not colour passes. k_8_8_8_8_GAMMA (1)
appears ZERO times, and color_exp_bias is 0 everywhere so nothing stands in
for a gamma either.

The mechanism is Canary's own source, not our inference: k_8_8_8_8_GAMMA is
the ONLY colour format around which a piecewise-linear gamma<->linear
conversion is applied (spirv_shader_translator.h:510 PWLGammaToLinear /
LinearToPWLGamma, render_target_cache.h:720, dxbc_shader_translator_om.cc).
With k_8_8_8_8 there is none, so the blender operates on the stored values
as they are.

So a renderer that linearises before blending and re-encodes after is doing
a different operation -- and the difference is gamma-shaped and exactly zero
on unblended pixels, which is the divergence signature the port reports.

Also renamed my units-per-second pre-registration off the 'h4' prefix: the
Port's BLOCKED.md numbers this blend-space question H4 and two different H4s
in one corpus is how a citation goes wrong.
2026-09-01 17:01:11 +00:00

36 lines
2.2 KiB
Plaintext

# In what SPACE does the game blend? -- answered from RB_COLOR_INFO.color_format,
# over every draw of two full captures.
#
# The mechanism, from Canary's own source (a non-ours instrument):
# ColorRenderTargetFormat (xenos.h:297)
# k_8_8_8_8 = 0 plain UNORM. No conversion anywhere.
# k_8_8_8_8_GAMMA = 1 the ONLY colour format for which a piecewise-linear
# gamma<->linear conversion is applied around the
# render target (spirv_shader_translator.h:510,
# PWLGammaToLinear / LinearToPWLGamma;
# render_target_cache.h:720; dxbc_shader_translator_om.cc)
# So: fmt=1 would mean "decode to linear, blend, re-encode".
# fmt=0 means the blender operates on the stored values as they are.
#
# ── census ────────────────────────────────────────────────────────────────────
#
# Capture A -- both boot splashes (2402 draws, frames 1..600)
# 2402 rt0=[tile=0 fmt=0 exp=0]
#
# Capture B -- boot through the attract movie to the settled title with the
# PRESS (A) plate (33 791 draws over 6565 frame labels)
# 33779 rt0=[tile=0 fmt=0 exp=0]
# 10 rt0=[tile=0 fmt=14 exp=0] k_32_FLOAT -- 10 draws, not a colour pass
# 2 rt0=[tile=0 fmt=6 exp=0] k_16_16_FLOAT -- 2 draws
#
# k_8_8_8_8_GAMMA (fmt=1) appears ZERO times in either capture.
# color_exp_bias is 0 on every draw in both, so there is no exponent scaling
# standing in for a gamma either.
#
# ── conclusion ────────────────────────────────────────────────────────────────
# The game blends in the ENCODED space, on the stored 8-bit values, with no
# linearisation and no re-encode. A renderer that linearises before blending and
# re-encodes after is performing a different operation, and the difference is
# gamma-shaped and exactly zero on unblended pixels -- which is the signature the
# port reports.