Repository navigation
Hot Path Vulkan Shader Selection Epoch Trust
Lifecycle: Performance - Unproven · Type: Assumption shortcut
State: Source-backed; runtime value is not established.
Status: Applicable extension of an existing shortcut; not implemented as a generation-only route and not benchmarked.
Mechanism class: Guarded shortcut / dependency-generation trust.
Reviewed source:
322986f4c5502b3fa887a9605ac8cd88e9b2c579Backend: Vulkan.
Current xemu already has Skip Unchanged Shader Work. That shortcut retains the current executable only after checking several current-state conditions: no register writes since the draw, no dirty program data, a complete current binding and pipeline, unchanged hybrid selection epoch, unchanged non-register shader state, and no dirty pipeline state.
This proposal is a stronger variant. It asks whether all shader-selection dependencies can be represented by one renderer-owned generation so a common hit performs one generation comparison instead of repeating the dirty-register scans and state comparisons.
It is not a separate implemented shortcut today. It belongs as a research extension because the current conservative route is already the maintained baseline.
On a trusted generation hit, the draw would bypass:
- the fixed dirty-register list scan;
- per-combiner-stage dirty-register checks;
- texture-register dirty checks;
- repeated non-register state comparison;
- construction and zeroing of a complete
ShaderState; - route/key work already proven unchanged by the generation.
Dynamic uniforms, descriptors, textures, draw resources, and ubershader controls remain live. This shortcut concerns selection of the executable, not all draw preparation.
pgraph_glsl_check_shader_state_dirty() checks program_data_dirty, a fixed register list, active combiner-stage registers, non-register inputs, and texture registers. pgraph_glsl_get_shader_state() then clears program_data_dirty, zeroes a complete ShaderState, and repopulates vertex, geometry, and fragment state.
The existing Vulkan shortcut avoids much of that work only after several direct guards remain favorable.
flowchart TD
A[Draw needs shader binding] --> B{Current fast-path control enabled?}
B -->|No| R[Run full state and route preparation]
B -->|Yes| C{No register/program change?}
C -->|No| R
C -->|Yes| D{Binding and complete pipeline valid?}
D -->|No| R
D -->|Yes| E{Selection epoch, non-register state and pipeline unchanged?}
E -->|No| R
E -->|Yes| F[Retain current executable]
F --> G[Refresh dynamic uniforms, controls and resources]
R --> G
flowchart TD
A[Shader-affecting state writer] --> B[Increment shader-selection generation]
C[Hybrid result publication or cache replacement] --> B
D[Reset, restore or renderer recreation] --> E[Invalidate retained selection]
B --> E
F[Draw needs shader binding] --> G{Retained selection valid and generation equal?}
G -->|Yes| H[Retain complete executable without rescanning dependencies]
G -->|No| I[Run maintained reference selection]
I --> J[Publish retained selection and current generation]
H --> K[Update dynamic uniforms, controls, textures and draw resources]
J --> K
The generation must change for every dependency that can change the effective shader or graphics pipeline route, including at least:
- vertex-program data and execution mode;
- combiner controls and active-stage inputs/outputs;
- relevant texture format/filter/control state;
- primitive mode and polygon/geometry behavior;
- active/uniform/compressed/swizzled attribute classification;
- texture-matrix enable state;
- surface scale and relevant color/zeta format state;
- ubershader versus specialized route selection;
- publication of a newly complete specialized pipeline;
- cache eviction or replacement of the retained executable;
- renderer reset, snapshot restoration, and recreation.
A write-path-only implementation is unsafe if any dependency can change through direct state mutation, restoration, or worker publication without using that writer.
The Xbox guest observes the shader behavior and draw ordering. It does not observe whether xemu rescanned dirty arrays or compared one generation.
The exact acceptance contract is:
Equal generation means the same complete executable would be selected by the maintained reference route for this draw.
That contract is stronger than “no commonly observed register changed.” It requires complete dependency coverage.
| Area | Role |
|---|---|
hw/xbox/nv2a/pgraph/glsl/shaders.c |
Current state reconstruction and dirty inspection |
hw/xbox/nv2a/pgraph/vk/draw.c |
Existing conservative shortcut and route activation |
| PGRAPH register/state writers | Candidate generation increments |
| Hybrid compiler/pipeline publication | Generation change when a better complete route becomes ready |
| Renderer reset/load/recreation | Retained-selection invalidation |
| Renderer thread | Sole owner of retained executable selection |
The opportunity depends on:
shader-binding requests
× percentage with unchanged selection
× cost of current repeated checks/reconstruction
− cost moved into state writers
This is worthwhile only if selection requests greatly outnumber shader-affecting state changes and the current checks appear in Release profiles or bounded timers.
The need is source-backed, and current main already contains a conservative unchanged-shader shortcut. That demonstrates a real common-case target, but it does not prove that replacing all its guards with one generation is faster or complete.
No current evidence establishes the cost of the remaining checks relative to uniforms, textures, descriptor work, or pipeline handling.
Generation counters and versioned prepared state are common renderer patterns. They are useful when one owner can enumerate all mutations. That general precedent does not prove xemu’s dependency set; guest register state, direct state changes, snapshots, and asynchronous hybrid publication make the invalidation proof emulator-specific.
shader_selection_requests
existing_conservative_hits
reference_selection_calls
generation_hits
generation_misses
generation_invalidations_by_reason
reference_comparisons_in_correctness_mode
selection_mismatches
writer_increment_cpu_ns
selection_cpu_ns
A diagnostic correctness build should occasionally run an independently seeded reference selection and compare the selected route/key without mutating the candidate’s live dirty state.
- Omit one register-writer increment and prove a single-dependency test detects stale selection.
- Publish a hybrid pipeline without incrementing the generation and prove route promotion is missed.
- Restore a snapshot with the same numeric generation but different shader state; the retained selection must be invalidated independently.
- Recreate or evict the active pipeline while preserving guest state; the retained handle must not remain trusted.
- Change one non-register dependency at a time, including attribute classification and surface scale.
- Missing an obscure dependency writer.
- Treating a guest register epoch as sufficient when host resource readiness also changes selection.
- Generation wrap without invalidation strategy.
- Reset/load restoring a stale retained generation.
- Extra writer bookkeeping costing more than the checks it replaces.
- Hiding a current invalidation bug by moving it behind one trusted number.
- Add complete mutation inventory and unit tests for every dependency family.
- Add deliberate broken-writer negative controls.
- Compare generation selection against an independently owned reference state.
- Run Vulkan XISO with output/hash and validation checks.
- Exercise PGR2 and Morrowind with route counters and Release profiling.
- Verify snapshot restore, renderer recreation, worker completion, cache eviction, and teardown.
- Report local selection work and whole-frame p95/p99; a faster local check without frame benefit remains diagnostic only.
Applicable, but not a new current shortcut. The current conservative shortcut should remain the reference until a complete generation contract and a measured benefit are proven.
- Skip Unchanged Shader Work
- Vulkan Hybrid Ubershader
- Assumption-Based Shortcut Validation
- Using Hot-Path Shortcuts
Primary reference: This subject page is the design and research reference for Shader Selection Epoch Trust. Pull requests are implementation/test history only.
Lifecycle: Performance - Unproven · Mechanism: Generation-based shader-selection shortcut
Reviewed source:322986f4c5502b3fa887a9605ac8cd88e9b2c579· Acceptance class: intended exact or behavior-preserving for its admitted scope
Replace repeated multi-category shader dependency inspection with one complete generation comparison, while leaving current uniforms and resources live.
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/glsl/shaders.c |
pgraph_glsl_check_shader_state_dirty() and pgraph_glsl_get_shader_state() |
hw/xbox/nv2a/pgraph/vk/shaders.c |
current binding/pipeline and hybrid publication interactions |
flowchart TD
N0["Shader preparation requested"]
N1["Inspect dirty register lists"]
N0 --> N1
N2["Inspect combiner/non-register/texture state"]
N1 --> N2
N3["Possibly rebuild ShaderState key"]
N2 --> N3
N4["Select modules/pipeline"]
N3 --> N4
N5["Update dynamic draw resources"]
N4 --> N5
flowchart TD
N0["Shader-affecting writers increment generation"]
N1["Preparation compares current generation"]
N0 --> N1
N2["Equal: retain complete selection"]
N1 --> N2
N3["Different: run reference selection and publish new generation"]
N2 --> N3
N4["Update dynamic resources normally"]
N3 --> N4
The fork already has an unchanged-shader fast path, but it still validates several dependency categories. A single complete epoch can be cheaper only if every relevant writer and lifecycle event updates it. This moves work from frequent reads to less frequent state-change points.
- Repeated dirty-list and non-register inspection
- Repeated ShaderState reconstruction on ordinary unchanged requests
- Uniform updates
- Texture/resource binding
- Pipeline validity
- Reference selection on generation mismatch
- Hybrid ready-result adoption
if (selected.valid && selected.epoch == pg->shader_selection_epoch &&
selected.pipeline_complete) {
stats.selection_epoch_hits++;
retain_current_shader_and_pipeline(pg);
} else {
run_reference_shader_selection(pg);
selected.epoch = pg->shader_selection_epoch;
selected.valid = true;
stats.selection_rebuilds++;
}
update_current_uniforms_and_draw_resources(pg);The sketch defines the intended boundary; it is not a complete patch and does not replace source review, ownership design, or focused tests.
- Every input that can change executable selection must touch the epoch.
- Resource replacement/eviction and hybrid pipeline publication must invalidate or advance selection state.
- Uniform-only and draw-resource changes must not unnecessarily advance the selection epoch.
- Generation wrap must remain safe.
The epoch is owned by the renderer/state-write domain and published coherently with selected pipeline state. Reset, snapshot restore, renderer recreation, cache eviction, and asynchronous ready-result adoption invalidate selection.
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.
- Very cheap common-path comparison
- Centralizes dependency ownership
- Can remove repeated key reconstruction
- Negative controls can prove test coverage
- One missed writer causes stale shaders
- Writer-side bookkeeping may spread widely
- Epoch churn can eliminate hits
- Asynchronous publication and cache replacement are easy to miss
Counters must be cheap, subsystem-owned, and snapshotted outside the hot loop. Record at least:
- selection_requests
- selection_epoch_hits
- selection_rebuilds
- epoch_increments_by_source
- reference_mismatches
- shader_prepare_cpu_us
- draw/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.
- Change each shader dependency independently
- Alternate/direct register writes
- Texture format/matrix changes
- Primitive/attribute classification
- Cache eviction/resource replacement
- Hybrid specialization publication
- Reset/snapshot/recreation
- Deliberately omit one increment and prove the oracle catches it
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 when writer coverage is demonstrably complete, hit rate is high, reference comparison finds no mismatches, and total preparation cost falls.
Reject or keep diagnostic-only if a complete writer inventory cannot be maintained, asynchronous events race publication, or bookkeeping cost merely moves the bottleneck.
Vulkan-Shader-Binding-and-Compilation · Performance-Unproven · Hot-Path-Vulkan-Unchanged-Shader-Work · Hot-Path-Vulkan-Hybrid-Ubershader
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