Repository navigation
Vulkan GPU Resident Surface Consumers
Lifecycle: Performance - Unproven · Type: Representation and coherency architecture
Reviewed source:322986f4c5502b3fa887a9605ac8cd88e9b2c579
State: The readback-then-upload route is source-confirmed. A safe GPU-only route is not implemented.
Vulkan throughput pages: Overview · Submission & retirement · Native presentation · Dynamic uniforms · PVIDEO lifetime · GPU-resident consumers · Buffer placement
Before updating the Vulkan vertex-RAM mirror, pgraph_vk_update_vertex_ram_buffer() downloads dirty surfaces overlapping the requested range into guest-visible RAM. It then copies those RAM bytes into the vertex buffer.
For GPU-produced data consumed next by the GPU, this can create a round trip.
Source seams:
The guest memory contract requires correct bytes when the CPU observes them. It does not require every GPU-to-GPU dependency to pass through host RAM first.
flowchart TD
A[GPU renders surface] --> B[Surface is newest representation]
B --> C[Download/convert surface to guest RAM]
C --> D[Read guest RAM bytes]
D --> E[Copy through vertex staging or mapped mirror]
E --> F[GPU fetches vertex data]
Surface download may also include scaling, swizzle handling, or depth/stencil conversion.
Track which representation contains the newest bytes and materialize only for the next real consumer.
flowchart TD
A[GPU produces range] --> B[Mark GPU representation newest]
B --> C{Next consumer}
C -->|GPU texture| D[Use direct compatible image/view route]
C -->|GPU vertex fetch| E[GPU transfer or compute conversion to vertex storage]
C -->|Guest CPU read| F[Materialize guest RAM and wait]
C -->|Unsupported interpretation| G[Use current readback route]
- Guest RAM stops being the mandatory intermediate for GPU-only dependencies.
- Surface, RAM, texture, and vertex representations need explicit version/ownership state.
- CPU-visible reads remain synchronization boundaries.
- Unsupported formats or CPU-side preparation retain the reference path.
This is broader than Direct Surface Sampling, which only targets a compatible surface used as a texture.
- The exact byte representation required by the consumer is known.
- Producer and consumer ranges, versions, formats, scale, swizzle, and component interpretation match.
- GPU ordering guarantees the producer is complete before the consumer reads.
- CPU-visible RAM is materialized before any guest CPU or device path reads it.
- Partial overlap and same-address resource reuse update the correct version state.
- Returning the right pixels but the wrong guest byte layout.
- Missing a CPU observation boundary.
- Reusing a GPU resource after the same guest address was rebound.
- CPU-side vertex preparation reading stale RAM.
- Incorrect partial-range version tracking.
- Moving work to compute/transfer without reducing total cost.
surface_readback_bytes{reason}
surface_readbacks_for_GPU_consumer
vertex_upload_bytes_after_surface_readback
GPU_to_GPU_materializations
CPU_materializations
reference_fallbacks{reason}
wait_us_for_CPU_visibility
fixed-work CPU/GPU/frame time
The important count is readback bytes whose next consumer is another GPU operation.
- Render known bytes into a surface and consume the range as vertex data.
- Modify part of the range, consume it again, then read the final bytes from the guest CPU.
- Exercise overlaps, page boundaries, scaling, swizzle, depth/stencil formats, and same-address resource reuse.
- Include cases requiring CPU-side provoking values or conversions; they must fall back safely.
- Run Vulkan validation and compare output/RAM hashes with the current route.
- Measure an uninstrumented Release build only after the ownership model passes fault and lifecycle tests.
- Vulkan Throughput Candidates
- Direct Surface Sampling
- Color-Download Folding
- Memory & DMA
- Vertex Uploads and Render-Pass Lifetime
Primary reference: This subject page is the design and research reference for GPU-Resident Surface Consumers. Pull requests are implementation/test history only.
Lifecycle: Performance - Unproven · Mechanism: Representation/coherency architecture
Reviewed source:322986f4c5502b3fa887a9605ac8cd88e9b2c579· Acceptance class: intended exact or behavior-preserving for its admitted scope
Keep GPU-produced data on the GPU when the next consumer is also GPU-side, materializing guest RAM only at real CPU/device observation boundaries.
This entry remains Unproven: the source path and opportunity are concrete, but no accepted xemu runtime result has established that the candidate improves representative workloads. The page defines what must be bypassed, what remains mandatory, and how the hypothesis can be rejected.
| File / function | Role |
|---|---|
hw/xbox/nv2a/pgraph/vk/surface.c |
dirty surface download and format conversion |
hw/xbox/nv2a/pgraph/vk/vertex.c |
download-overlap before vertex mirror update |
hw/xbox/nv2a/pgraph/vk/texture.c |
surface-backed texture materialization |
flowchart TD
N0["GPU surface is newest"]
N1["Download/convert to guest RAM"]
N0 --> N1
N2["CPU-visible bytes become authoritative"]
N1 --> N2
N3["Copy/upload to vertex or texture representation"]
N2 --> N3
N4["GPU consumes again"]
N3 --> N4
flowchart TD
N0["Track newest representation/version"]
N1["GPU texture consumer: direct compatible view"]
N0 --> N1
N2["GPU vertex consumer: transfer/compute materialization"]
N1 --> N2
N3["CPU read: download/wait"]
N2 --> N3
N4["Unsupported case: reference route"]
N3 --> N4
The guest contract requires correct bytes at CPU observation points, but GPU-to-GPU consumers need not always traverse host RAM. Avoiding that round trip can remove transfer, conversion, CPU copying, and synchronization. The main challenge is byte representation and discovering every observer.
- Surface readback whose next consumer is GPU
- Host copy followed by GPU upload
- CPU wait used only to establish an unnecessary intermediate
- Correct guest bytes on CPU read
- Producer-consumer GPU ordering
- Format/swizzle/scale conversion
- Partial-range coherency
- Reference fallback
switch (next_consumer(range)) {
case GPU_TEXTURE:
return materialize_texture_view_on_gpu(range, version);
case GPU_VERTEX:
return materialize_vertex_bytes_on_gpu(range, version);
case GUEST_CPU:
return download_guest_ram_and_wait(range, version);
default:
return reference_materialization(range);
}The sketch defines the intended boundary; it is not a complete patch and does not replace source review, ownership design, or focused tests.
- Version state covers partial ranges and same-address resource reuse.
- Consumer representation is byte/format correct, not merely visually similar.
- Every CPU/device read path materializes RAM first.
- In-flight versions cannot be overwritten prematurely.
Maintain per-range or resource-version ownership among surface, guest RAM, texture and vertex representations. Writes advance the owning version; materialization records which representation matches it. Reset/snapshot can conservatively force RAM authority/full invalidation.
The maintained reference path remains the fallback whenever admission, capability, lifetime, or validation is uncertain. A fast result with an unproven dependency is not acceptable as an exact optimization.
- Removes whole representation round trips
- Potentially reduces CPU/GPU synchronization
- Unifies several coherency optimizations
- Preserves CPU correctness through explicit observation boundaries
- High complexity and broad observer inventory
- Partial-range tracking
- Format conversion may still require GPU compute
- CPU-side vertex preparation can force fallback
- Silent stale RAM is severe
Counters must be cheap, subsystem-owned, and snapshotted outside the hot loop. Record at least:
- surface_readback_bytes_by_reason
- readbacks_for_GPU_consumer
- GPU_to_GPU_materializations
- CPU_materializations
- vertex_upload_after_readback_bytes
- fallbacks_by_reason
- wait_us
- frame p95/p99
A local reduction is not enough. Evidence must connect route reachability and removed work to fixed guest progress, CPU/GPU time where applicable, and p95/p99 behavior.
- Render known bytes, consume as texture/vertex, overwrite subset, consume again, then CPU-read
- Overlaps/page boundaries
- Scale/swizzle/depth formats
- Same-address lifetime reuse
- CPU-side provoking/conversion cases
- Device/DMA observers
- Snapshot/reset
- Validation and output/RAM hashes
Correctness runs may use validation layers, detailed comparisons, and fault injection. Performance acceptance must use optimized Release builds with matching symbols and minimal instrumentation.
Promote only in narrow consumer classes with explicit version/observer proofs and measured elimination of readback/reupload cost.
Reject broad 'RAM can be stale' modes, incomplete observer inventories, or designs that move equal work into compute without total improvement.
Memory-and-DMA · Performance-Unproven · Hot-Path-Vulkan-Direct-Surface-Sampling · Vulkan-Vertex-Uploads-and-Render-Pass-Lifetime
PR pages may be linked as supporting evidence, but they are not substitutes for this reference.
DSP tooling guide and navigation updated November 2, 2026 for experimental PR #384, source 8f51d237. Capture/replay usage and limits.
The earlier wiki-wide review was published November 1, 2026. Emulator source: b7140848. Reviewed wiki content: 1d2b671. Current status · Release availability · Publication process.
- Home
- Current status
- Stable versus main
- Implemented mechanisms
- Controls and defaults
- Measured results and limits
- Complete change register
- System
- CPU and vCPU
- Memory and DMA
- Graphics / NV2A
- APU and audio
- Timing and timers
- Platform and I/O
- Hardware observations
- Fidelity boundaries
- Methodology
- PGR2 routes
- Debugging lag / hot paths
- Tools and commands
- DSP capture, replay and fuzzing
- HLE readiness and public XISO proof
- Concurrent DSP shadow and OpenAL proof
- DSP HLE operation inventory
- DSP HLE fix examples and testing
- Development
- Upstream shortlist
- Wiki maintenance
- Research / retired work
- Optimization catalog
- Hot-path shortcuts
- Researched experiments
- Unproven proposal directory
- PR lessons
- September26 snapshot
Repository · PRs · Issues