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.
36 lines
2.2 KiB
Plaintext
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.
|