Skip to content

Vulkan Native Presentation

github-actions[bot] edited this page Sep 14, 2026 · 3 revisions

Native Vulkan Presentation

Lifecycle: Performance - Unproven · Type: Presentation architecture
Reviewed source: 322986f4c5502b3fa887a9605ac8cd88e9b2c579
State: The Vulkan-to-OpenGL handoff is source-confirmed. Its cost has not been isolated in xemu.

Vulkan throughput pages: Overview · Submission & retirement · Native presentation · Dynamic uniforms · PVIDEO lifetime · GPU-resident consumers · Buffer placement

Status

The Vulkan renderer exposes its result to an OpenGL-based frontend. Shared external memory avoids a CPU pixel copy when supported, but display composition still uses a synchronous one-time submission. The fallback path reads pixels to host memory and uploads them into an OpenGL texture.

Source seams:

Why it matters

A modern GPU can finish guest rendering quickly and still be stalled by the route used to make the result presentable to the host window.

The fallback path adds a representation round trip. The shared path avoids that copy but still requires Vulkan work to be synchronously ready for OpenGL consumption.

Current path

flowchart TD
    A[NV2A rendering in Vulkan] --> B[Vulkan display and PVIDEO composition]
    B --> C[One-time Vulkan submission]
    C --> D[vkQueueWaitIdle]
    D --> E{External-memory sharing available?}
    E -->|Yes| F[Expose shared image as OpenGL texture]
    E -->|No| G[Copy display image to host buffer]
    G --> H[glTexImage2D or glTexSubImage2D]
    F --> I[OpenGL frontend and UI]
    H --> I
    I --> J[Host window]
Loading

Candidate path

Use Vulkan for scene output, display/PVIDEO composition, UI composition, and final swapchain presentation.

flowchart LR
    A[Vulkan scene] --> B[Vulkan scanout and overlay]
    B --> C[Vulkan UI composition]
    C --> D[Vulkan swapchain]
    D --> E[Present]
Loading

This is a frontend/backend integration change. It is not equivalent to adding a swapchain inside the renderer while the rest of the UI still owns an OpenGL texture.

What changes

  • The framebuffer interface no longer requires an OpenGL texture.
  • Display image readiness can be expressed through Vulkan submission dependencies instead of a queue-wide idle.
  • The host-copy route can disappear on a native Vulkan frontend.
  • Resize, fullscreen, minimized-window, UI, and swapchain recreation become part of Vulkan ownership.

Diagnostic before the rewrite

Add a laboratory mode that suppresses host display production while preserving guest flip, timing, and synchronization behavior.

This measures the cost of producing/presenting the host image. It is not a playable benchmark and must not remove guest pacing.

Required guard

The candidate must preserve:

  • guest flip and stall semantics;
  • interlace and scanout offsets;
  • PVIDEO composition and color keying;
  • surface version ordering;
  • frontend UI and overlays;
  • resize/fullscreen/minimize behavior;
  • swapchain loss and recreation;
  • renderer reset and teardown ordering.

Risks

  • Measuring a no-display mode that also removes guest-visible pacing.
  • Replacing one queue wait with a swapchain-acquire/present wait of equal cost.
  • Splitting UI ownership between OpenGL and Vulkan without a complete synchronization contract.
  • Holding framebuffer resources across resize or renderer recreation.
  • Platform-specific window-system behavior producing different results.

Evidence

display_render_submits
display_queue_idle_us
host_copy_bytes
OpenGL texture upload bytes and CPU time
shared-presentation frames
host-copy frames
present/acquire wait time
renderer CPU time
fixed guest progress and frame p95/p99

Compare shared-GL, host-copy, no-host-display diagnostic, and minimal native-Vulkan prototype separately.

How to test

  1. Measure display composition and presentation cost with the existing two transports.
  2. Run a fixed captured workload with host display production suppressed but guest timing intact.
  3. Build a minimal native Vulkan presenter before porting every UI feature.
  4. Test resize, fullscreen, interlaced output, scanout offsets, PVIDEO, UI composition, minimized windows, and resource recreation.
  5. Use Release builds for timing and Vulkan validation builds for ownership/synchronization checks.

Related

Full technical reference

Primary reference: This subject page is the design and research reference for Native Vulkan Presentation. Pull requests are implementation/test history only.
Lifecycle: Performance - Unproven · Mechanism: Frontend/presentation architecture
Reviewed source: 322986f4c5502b3fa887a9605ac8cd88e9b2c579 · Acceptance class: intended exact or behavior-preserving for its admitted scope

1. Scope

Present the Vulkan-composed image through a Vulkan swapchain and Vulkan UI path, removing the requirement to synchronously expose each new output as an OpenGL texture.

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.

2. Source seams

File / function Role
hw/xbox/nv2a/pgraph/vk/display.c display/PVIDEO composition and one-time command submission
hw/xbox/nv2a/pgraph/vk/renderer.c shared external-memory vs host-copy OpenGL texture handoff
ui/* OpenGL-based frontend/UI ownership

3. Current execution path

flowchart TD
    N0["Vulkan scene"]
    N1["Vulkan display composition"]
    N0 --> N1
    N2["Synchronous completion"]
    N1 --> N2
    N3["External-memory GL texture or host readback"]
    N2 --> N3
    N4["OpenGL texture upload"]
    N3 --> N4
    N5["OpenGL UI/frontend"]
    N4 --> N5
    N6["Host window"]
    N5 --> N6
Loading

4. Candidate execution path

flowchart TD
    N0["Vulkan scene"]
    N1["Vulkan scanout/PVIDEO composition"]
    N0 --> N1
    N2["Vulkan UI composition"]
    N1 --> N2
    N3["Swapchain acquire/submit"]
    N2 --> N3
    N4["Vulkan present"]
    N3 --> N4
Loading

5. Why it may help

The fallback path copies image data to host memory and uploads it to OpenGL. Shared external memory avoids the CPU copy but not the architectural handoff and synchronous display submission. A native path can remove a whole API boundary, but it is a frontend integration project rather than a renderer-only tweak.

6. Work removed

  • Vulkan-to-OpenGL synchronization
  • Fallback host readback and GL upload
  • Cross-API texture ownership
  • Some queue-idle display completion

7. Work that remains mandatory

  • Guest flip/stall semantics
  • Display/PVIDEO composition
  • Window-system present synchronization
  • UI/overlay rendering
  • Resize/minimize/swapchain lifecycle

8. Implementation sketch

acquire_swapchain_image(&frame);
record_nv2a_display_composition(frame.cmd, frame.image);
record_ui_composition(frame.cmd, frame.image);
submit_frame(frame.cmd, frame.acquire_semaphore,
             frame.present_semaphore, frame.fence);
present_frame(frame.image_index, frame.present_semaphore);

The sketch defines the intended boundary; it is not a complete patch and does not replace source review, ownership design, or focused tests.

9. Correctness contract

  • Guest pacing and flip events remain independent from host present count.
  • PVIDEO, interlace, scanout offsets, color key and scaling match the reference.
  • Swapchain recreation and minimized windows cannot deadlock renderer/UI ownership.
  • A no-display diagnostic must not remove guest synchronization and claim a false speedup.

10. State, ownership, invalidation, and fallback

Swapchain images and per-frame contexts are frontend-owned; renderer output is consumed through an explicit interface. Resize/fullscreen/device loss recreate dependent objects only after safe retirement. UI and renderer must share one Vulkan device/queue contract or define explicit transfer.

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.

11. Advantages

  • Removes cross-API handoff
  • Eliminates fallback pixel round trip
  • May reduce synchronous display waits
  • Simplifies future Vulkan-native UI integration

12. Costs and failure modes

  • Large platform/frontend rewrite
  • Swapchain behavior varies by OS/driver
  • Could replace one wait with acquire/present latency
  • UI and tooling currently assume OpenGL
  • Hard lifecycle edge cases

13. Evidence counters

Counters must be cheap, subsystem-owned, and snapshotted outside the hot loop. Record at least:

  • display_submit_us
  • display_queue_idle_us
  • host_copy_bytes
  • GL_upload_us
  • shared_vs_host_copy_frames
  • swapchain_acquire_wait_us
  • present_wait/result
  • guest flips
  • host presents
  • 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.

14. Qualification matrix

  • No-host-display cost-isolation mode with guest timing intact
  • Minimal swapchain prototype
  • Resize/fullscreen/minimize
  • PVIDEO and interlace
  • UI/overlay composition
  • Different GPUs/adapters
  • Renderer reset and device loss
  • Presentation modes and pacing

Correctness runs may use validation layers, detailed comparisons, and fault injection. Performance acceptance must use optimized Release builds with matching symbols and minimal instrumentation.

15. Acceptance rule

Promote only after measured presentation cost justifies the rewrite and a minimal native path passes platform/lifecycle tests with correct guest pacing.

16. Rejection rule

Reject claims based solely on no-display FPS, or if native presentation simply relocates the same serialization without reducing total frame cost.

17. Related architecture and history

Vulkan-Renderer · Performance-Unproven · Hot-Path-Vulkan-Unchanged-Scanout · Vulkan-PVIDEO-Resource-Lifetime

PR pages may be linked as supporting evidence, but they are not substitutes for this reference.

Clone this wiki locally