[iterate-4A] intro-video ROOT #3: render the YUV movie in correct color
The intro video (ADV.wmv) now plays end-to-end in correct color. Three stacked host-render-path bugs, each masked by the prior: #3a Multi-texture render path. The host bound a single texture slot, so the YUV pixel shader's three plane fetches (Y 1280x720 + U/V 640x360, all k_8) collapsed onto one texture. Expanded the Xenos pipeline to 8 tex+1 sampler slots (xenos_pipeline.rs, xenos_interp.wgsl, translator.rs headers); each tfetch selects its texture by fetch-constant slot; the DrawCapture textures tuple now carries the slot; render.rs uploads+binds every plane per-draw. Also added the scalar-constant ALU ops MULSC/ADDSC/ SUBSC (42-47) the YUV->RGB shader uses. #3b tfetch destination swizzle. decode_fetch read the tfetch dest as a 4-bit write mask (w1 & 0xF), but Xenos tfetch dword1[0:11] is a 12-bit destination swizzle (3 bits/component: 0-3=xyzw, 4/5=const 0/1, 6/7=keep). The result: all three plane fetches did a full-vec4 overwrite of the dest register, so only the last plane survived. Decode the real 12-bit swizzle (dest_swizzle) and emit per-lane writes so Y/U/V coexist in r1.x/.y/.z. #3c Pixel-shader constant bank. Xenos splits the 512-entry float-constant file: the vertex shader addresses c0..255 -> physical 0..255, but the pixel shader's c0..255 map to physical 256..511. The game uploads the YUV->RGB coefficients to physical 510/511. Our translator indexed the low half for PS constants, reading all-zero -> R=B=Y^2, G=0 (magenta). emit_alu now adds a const_base of 256 for pixel-stage constant reads. Plus a bounded (FIFO, 64-entry) host texture cache: the movie streams ~3 new-VA planes per frame, and the previously-unbounded cache exhausted GPU memory into a device-lost crash mid-playback. Verified visually: the SQUARE ENIX logo and ADV.wmv footage render in correct color (was magenta); the translated movie shader now reads alu[510]/alu[511]; frame green channel is nonzero and R != B. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -68,20 +68,23 @@ pub struct DrawCapture {
|
||||
pub ndc_offset: [f32; 2],
|
||||
/// iterate-3T: the decoded texture(s) this draw's active pixel shader
|
||||
/// samples, keyed off its real `tfetch` fetch-constant slots (the 3M
|
||||
/// decoder makes these decode). The UI uploads + binds the FIRST entry
|
||||
/// per-draw so the textured logo samples the real artwork instead of the
|
||||
/// magenta stub. Empty for flat (no-tfetch) draws. Populated by
|
||||
/// `gpu_system` after decode (left empty by `build`).
|
||||
/// decoder makes these decode). Root-#3: the UI uploads + binds EACH entry
|
||||
/// to its own texture slot per-draw, so a multi-plane shader (e.g. the
|
||||
/// intro video's YUV Y/U/V planes) samples the right texture per fetch.
|
||||
/// Empty for flat (no-tfetch) draws. Populated by `gpu_system` after
|
||||
/// decode (left empty by `build`).
|
||||
///
|
||||
/// Each entry is `(key, content_version, bytes)`. iterate-3AD: the
|
||||
/// `content_version` (from `span_max_version` over the texel span) lets the
|
||||
/// UI host texture cache RE-UPLOAD when the guest fills more of an evolving
|
||||
/// atlas. The publisher and the 2nd splash logo share one K8888 surface
|
||||
/// (base `0x4dbee000`); the 2nd logo's texels are CPU-written *after* the
|
||||
/// publisher's first upload. Without the real version the host cache (which
|
||||
/// previously pinned `version_when_uploaded = 1`) kept the first partial
|
||||
/// upload, so the 2nd logo sampled its still-zero atlas region as black.
|
||||
pub textures: Vec<(crate::texture_cache::TextureKey, u64, Vec<u8>)>,
|
||||
/// Each entry is `(slot, key, content_version, bytes)` where `slot` is the
|
||||
/// `tfetch` fetch-constant index (0..31) the shader samples this texture
|
||||
/// from. iterate-3AD: the `content_version` (from `span_max_version` over
|
||||
/// the texel span) lets the UI host texture cache RE-UPLOAD when the guest
|
||||
/// fills more of an evolving atlas. The publisher and the 2nd splash logo
|
||||
/// share one K8888 surface (base `0x4dbee000`); the 2nd logo's texels are
|
||||
/// CPU-written *after* the publisher's first upload. Without the real
|
||||
/// version the host cache (which previously pinned `version_when_uploaded
|
||||
/// = 1`) kept the first partial upload, so the 2nd logo sampled its
|
||||
/// still-zero atlas region as black.
|
||||
pub textures: Vec<(u8, crate::texture_cache::TextureKey, u64, Vec<u8>)>,
|
||||
/// iterate-3Y: per-draw color/blend render state captured from the
|
||||
/// register file so the host pipeline composites the way the guest
|
||||
/// intends (instead of one fixed alpha-blend state). Mirrors the fields
|
||||
|
||||
Reference in New Issue
Block a user