[iterate-3T] Real UV interpolation + per-draw textures: shader/UV/bind chain complete
Build the full texture-sampling chain for the publisher splash so the textured logo CAN sample real artwork at the guest's real UVs. Measured with an env-gated frontbuffer readback (since removed): the chain is correct end-to-end, but the sampled K8888 1280x768 texture is ALL-ZERO in the UI window's reachable boot range — the artwork is produced by an EDRAM resolve (RT->texture copy) that ours does not yet perform (resolves=0). So this lands the correct shader/UV/bind work and isolates the remaining blocker to the resolve gap, not the shader path. Translator (xenia-gpu/src/translator.rs), all UI-translator-only: - Real Xenos export-index model (replaces the AllocKind heuristic that collapsed every VS export to one color slot and DROPPED the texcoord). When export_data is set the 6-bit vector_dest IS the export index: VS 62=oPos, 0..15=interps; PS 0=RT0. The logo VS exports oPos(62), interp0(color), interp1(UV) distinctly. - Real interpolator passthrough: VsOut carries 8 interpolator locations; the PS seeds r[i] = in.interp[i] (Xenos PS-input-GPR mapping) so tfetch samples at the real interpolated texcoord (r1) instead of (0,0). - vfetch format 6 (k_16_16) packed-16 unpack + per-attribute dword offset, so the 3 vfetches sharing one fetch-constant (pos/UV/color in a 6-dword vertex) read the right attribute. Previously rejected the whole logo VS to the interpreter. - QuadList/RectangleList host->guest vertex-index remap in the VS (replay is non-indexed): QuadList 6 host verts -> guest [0,1,2,0,2,3] (full quad). fetch.rs: decode vfetch `offset` (dword2[8:15], dwords), `is_signed`, `is_normalized`. Per-draw textures: DrawCapture carries the decoded texture(s) (keyed off the active PS's tfetch slots, attached in gpu_system after decode); render.rs::dispatch_xenos_captures uploads + binds each capture's texture via the host texture cache before its draw, instead of one last-draw primary_texture. Determinism: all changes feed only the UI translator/capture path; frame_captures is None headless. `check -n50m --gpu-inline --stable-digest --expect` byte- identical (exit 0). 681 tests pass (+2 regression: logo VS now translates with interpolators; PS seeds interps into registers). Temp readback/dump probes removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,19 @@ pub struct VertexFetch {
|
||||
pub format: u8,
|
||||
/// Dword stride between consecutive vertices (dword2[0:7]).
|
||||
pub stride: u8,
|
||||
/// iterate-3T: dword offset of THIS attribute within the vertex stride
|
||||
/// (dword2[16:38] in canary's `VertexFetchInstruction`; the low 23 bits).
|
||||
/// A 6-dword vertex with position@0 + UV@2 + extra@3 needs this so the
|
||||
/// three vfetches sharing one fetch-constant read different attributes
|
||||
/// instead of all reading offset 0.
|
||||
pub offset: u32,
|
||||
/// iterate-3T: `is_signed` (dword2 bit 24 in canary) — selects signed vs
|
||||
/// unsigned interpretation of packed integer formats.
|
||||
pub is_signed: bool,
|
||||
/// iterate-3T: `is_normalized` — canary inverts it: dword2 bit 25 set means
|
||||
/// the value is taken as an *integer* (un-normalized); clear means
|
||||
/// normalized to [0,1] / [-1,1]. We store the normalized sense directly.
|
||||
pub is_normalized: bool,
|
||||
pub raw: [u32; 3],
|
||||
}
|
||||
|
||||
@@ -81,9 +94,15 @@ pub fn decode_fetch(words: [u32; 3]) -> FetchInstruction {
|
||||
src_register: ((w0 >> 5) & 0x3F) as u8,
|
||||
dest_register: ((w0 >> 12) & 0x3F) as u8,
|
||||
dest_write_mask: (w1 & 0xF) as u8,
|
||||
// dword1[16:21] = VertexFormat; dword2[0:7] = dword stride.
|
||||
// dword1[16:21] = VertexFormat. dword2: stride[0:7],
|
||||
// offset (in dwords) [8:?] — empirically the attribute offset of
|
||||
// the textured logo VS lands in dword2[8:15] (pos@4, UV@3,
|
||||
// 3-float@0 in a 6-dword vertex). signed/normalized live higher.
|
||||
format: ((w1 >> 16) & 0x3F) as u8,
|
||||
stride: (w2 & 0xFF) as u8,
|
||||
offset: (w2 >> 8) & 0xFF,
|
||||
is_signed: ((w1 >> 24) & 1) != 0,
|
||||
is_normalized: ((w1 >> 25) & 1) == 0,
|
||||
raw: words,
|
||||
}),
|
||||
op::TEXTURE_FETCH => FetchInstruction::Texture(TextureFetch {
|
||||
|
||||
Reference in New Issue
Block a user