[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:
@@ -748,6 +748,39 @@ impl RenderState {
|
||||
label: Some("xenos capture replay"),
|
||||
});
|
||||
for cap in captures {
|
||||
// iterate-3T: bind this draw's REAL decoded texture (keyed off the
|
||||
// active PS's tfetch slot, attached in `gpu_system`) so the textured
|
||||
// logo samples the artwork. `None` reverts to the magenta stub for
|
||||
// flat draws. Each `set_texture_view` rebuilds the tex bind group;
|
||||
// the subsequent `render_one*` reads it, so per-draw binding works
|
||||
// even though all draws share one encoder.
|
||||
{
|
||||
let Self {
|
||||
device,
|
||||
queue,
|
||||
xenos_pipeline,
|
||||
host_texture_cache,
|
||||
..
|
||||
} = self;
|
||||
match cap.textures.first() {
|
||||
Some((key, bytes)) => {
|
||||
// Stable version: identical (key,bytes) across draws
|
||||
// reuse the uploaded wgpu texture (the splash artwork is
|
||||
// static). A genuine content change arrives as a new key
|
||||
// (base_address/dims) from the decoder.
|
||||
let cached = xenia_gpu::texture_cache::CachedTexture {
|
||||
key: *key,
|
||||
version_when_uploaded: 1,
|
||||
bytes: bytes.clone(),
|
||||
};
|
||||
host_texture_cache.upload(device, queue, &cached);
|
||||
if let Some(view) = host_texture_cache.view_for(key) {
|
||||
xenos_pipeline.set_texture_view(device, Some(view));
|
||||
}
|
||||
}
|
||||
None => xenos_pipeline.set_texture_view(device, None),
|
||||
}
|
||||
}
|
||||
let raw_vs = shader_blobs.get(&cap.vs_key).cloned().unwrap_or_default();
|
||||
let raw_ps = shader_blobs.get(&cap.ps_key).cloned().unwrap_or_default();
|
||||
let parsed_vs = xenia_gpu::ucode::parse_shader(&raw_vs);
|
||||
|
||||
Reference in New Issue
Block a user