Skip to content

OpenGL Direct Surface Binding

github-actions[bot] edited this page Sep 15, 2026 · 1 revision

OpenGL Direct Surface Binding

Lifecycle: Performance - Unproven · Type: Copy-bypass and aliasing shortcut
Reviewed source: 322986f4c5502b3fa887a9605ac8cd88e9b2c579
State: The current backend materializes a separate texture version. Direct aliasing is not implemented and has substantial ordering hazards.

OpenGL candidate directory · Copy-image surface transfer · OpenGL Renderer

Purpose

When a render surface is later sampled as a texture, xemu currently copies or renders the surface into a separate texture object. That independent destination freezes a version: later rendering to the original surface does not change the already-materialized texture.

Direct surface binding removes the copy entirely for states where the surface image itself can be sampled with the required interpretation. The challenge is not creating a view—it is preserving guest ordering, texture-version identity, and feedback behavior.

This is intentionally a separate experiment from glCopyImageSubData():

  • Copy-image transfer retains an independent texture version.
  • Direct binding aliases the producer resource and must prove that later writes cannot change earlier consumers.

Source seams

  • hw/xbox/nv2a/pgraph/gl/texture.c
    • surface lookup during texture binding
    • pgraph_gl_render_surface_to_texture() call
    • texture binding draw_time and scale tracking
  • hw/xbox/nv2a/pgraph/gl/surface.c
    • surface/texture compatibility checks
    • render-copy and CPU fallback routes
  • Surface cache lifetime, draw version, upload/download, and framebuffer attachment handling.

Current execution flow

flowchart TD
    A[Texture stage points into active render-surface range] --> B{Surface/texture compatible?}
    B -->|No| C[Download/convert/upload texture]
    B -->|Yes| D{Texture binding older than surface draw_time?}
    D -->|No| E[Reuse independent texture]
    D -->|Yes| F[Materialize new independent texture version]
    F --> G[Bind copied texture for guest draw]
    E --> G
    C --> G
Loading

The independent texture object is a version barrier.

Candidate execution flow

flowchart TD
    A[Texture stage references render surface] --> B{Direct-view eligibility proven?}
    B -->|No| C[Reference copy/materialization route]
    B -->|Yes| D[Create/reuse sample-compatible view state]
    D --> E{Feedback or later-write hazard?}
    E -->|Yes| C
    E -->|No| F[Retain surface version reference]
    F --> G[Bind surface image directly]
    G --> H[Draw samples exact retained version]
    H --> I[Release version after GPU completion]
Loading

Possible binding record:

typedef struct GLDirectSurfaceTexture {
    SurfaceBinding *surface;
    uint64_t surface_lifetime_id;
    uint64_t content_version;
    GLenum target;
    GLenum sampling_format;
    unsigned base_level;
    unsigned width;
    unsigned height;
    uint32_t scale;
} GLDirectSurfaceTexture;

A raw pointer to SurfaceBinding is insufficient if the cache can destroy and reuse the allocation.

Eligibility dimensions

Representation

  • Color surface; depth/stencil requires separate research.
  • Sampleable OpenGL texture target exists for the surface storage.
  • Guest texture format can be represented without copy-time conversion.
  • Dimensions, scale, mip level, and border semantics match.
  • Channel/alpha interpretation matches shader expectations.

Ordering

  • The surface producer is complete before the sampling draw.
  • The surface is not simultaneously attached for a prohibited feedback loop.
  • Later writes cannot mutate the version needed by already-recorded/issued draws.
  • Surface recreation at the same guest address produces a new lifetime ID.

State

  • Sampler state can be applied without mutating the surface in a way that breaks its rendering role; sampler objects are preferable.
  • Texture cache/refcount/lifetime rules retain the surface until the last sampling draw completes.
  • CPU upload/download authority changes invalidate the direct view.

Versioning problem

Consider:

1. Render red into surface A.
2. Draw B while sampling A.
3. Render blue into A.
4. Draw C while sampling A.

Correct output:

B observes red.
C observes blue.

If the host executes work asynchronously and both draws sample the same mutable texture storage, B can incorrectly observe blue unless command ordering and resource hazards guarantee the earlier sample completes before the later write.

OpenGL command ordering in one context may protect some sequences, but cross-context work, FBO reattachment, driver reordering, and shared-resource ownership still require an explicit model. A shortcut must document which ordering guarantee it relies on.

Feedback loops

Sampling from a texture that is simultaneously attached to the active framebuffer can be undefined or require a specific texture-barrier strategy. The initial route should reject:

  • same surface as active color target;
  • same surface as active depth/stencil target;
  • overlapping regions with unresolved write/read order;
  • guest patterns requiring feedback semantics not proven by the backend.

A texture barrier is not a universal permission to ignore feedback restrictions.

What may disappear

  • Destination texture allocation/redefinition.
  • Copy-image or full-screen render-copy work.
  • Additional texture memory for the copied representation.
  • Version-copy latency on repeated render-to-texture use.
  • Some cache lookup and upload work.

What remains mandatory

  • Exact guest sampling representation.
  • Independent version behavior when later writes would otherwise change earlier observations.
  • Correct surface-to-texture ordering.
  • Feedback-loop rejection or proven handling.
  • Correct scale, border, mip, format, and alpha behavior.
  • CPU visibility/readback when requested.
  • Copy fallback for unsupported or unsafe states.

Sampler-state dependency

The current backend applies filter/wrap/border parameters to texture objects. Applying guest sampling state directly to a render-surface texture can alter state used by other consumers. A robust direct-binding route should depend on OpenGL Sampler Objects or maintain separate safe texture state.

This dependency does not mean sampler objects must be implemented first for all textures, but the direct route must not mutate shared surface storage unpredictably.

Advantages

  • Removes the entire copy/materialization step on a hit.
  • Reduces host image memory and bandwidth.
  • High potential in render-to-texture-heavy games.
  • Can use existing surface lifetime and draw-version concepts as a foundation.
  • Maintains a complete copy fallback.

Costs and risks

  • Most dangerous OpenGL surface optimization in this set.
  • Missing version ownership causes nondeterministic stale/future data.
  • Feedback behavior can become undefined.
  • Surface and texture lifetimes become coupled.
  • Scale/format compatibility may leave a narrow hit rate.
  • Driver/context differences can expose hidden synchronization assumptions.
  • Direct aliasing may worsen cache behavior despite removing copies.

Required counters

surface_texture_requests
direct_binding_eligible
direct_binding_hits
direct_binding_fallbacks{reason}
copy_materializations_avoided
bytes_avoided
surface_versions_retained
surface_version_reuse_waits
feedback_blocks
lifetime_mismatch_blocks
format_or_scale_blocks
GPU time for materialization versus direct route

Qualification matrix

Scenario Required result
Render red → sample → render blue → sample First consumer red, second blue
Several draws sample one stable surface Direct reuse without copies
Source reused at same guest address New lifetime prevents old alias
Surface attached while sampled Rejected or proven safe route
Multiple texture stages sample source Correct sampler/state separation
Scale/format/border mismatch Copy fallback
CPU upload overwrites guest range Direct view invalidated
CPU readback after direct use Correct guest bytes
Context reset/snapshot/eviction No dangling surface reference
Artificial GPU delay No early destruction or mutation

Acceptance rule

Promote to Researched only after versioned red/blue ordering fixtures, feedback rejection, lifetime stress, and output comparisons pass, and real workloads show enough avoided materialization to improve Release performance.

Rejection rule

Reject or restrict the route if safe version retention effectively requires making a copy anyway, if feedback/format constraints make coverage negligible, or if cross-context ownership cannot be proven.

Related

Clone this wiki locally