Repository navigation
OpenGL Native Depth Variant
Lifecycle: Performance - Unproven · Type: Numerical and early-depth experiment
Reviewed source:322986f4c5502b3fa887a9605ac8cd88e9b2c579
State: Source-backed. No OpenGL GPU benchmark or compatibility campaign has established a useful admitted subset.
OpenGL candidate directory · OpenGL Renderer · Shared shader architecture
The shared fragment generator writes gl_FragDepth for every generated normal fragment shader. Integer depth formats explicitly floor guest depth values and compensate for host depth-conversion differences. This is deliberate emulation logic, not an accidental assignment.
The proposed experiment creates a genuinely different shader/pipeline variant that relies on rasterizer-produced host depth for a narrow state subset. The main possible benefit is not the removal of a few arithmetic instructions. Avoiding a fragment-depth write may allow the driver to reject occluded fragments before executing the full texture and combiner program.
-
hw/xbox/nv2a/pgraph/glsl/psh.cpgraph_glsl_set_psh_state()pgraph_glsl_gen_psh()- depth-format-specific
gl_FragDepthemission
- Shared vertex/geometry shader generation and the OpenGL program key must include the selected depth policy.
- OpenGL depth/raster state is applied from
gl/draw.c.
Current source emits logic equivalent to:
// D16
float zvalue = ...;
gl_FragDepth = floor(zvalue) / 65535.0;
// D24
uint bits = floatBitsToUint(floor(zvalue) / 16777216.0) + 1u;
gl_FragDepth = uintBitsToFloat(bits);The D24 expression intentionally compensates for how different host GPUs quantize floating-point fragment depth into integer depth attachments.
flowchart TD
A[Vertex/geometry shader produces position] --> B[Rasterizer interpolates host depth]
B --> C[Fragment shader executes texture and combiner work]
C --> D[Compute guest-oriented zvalue]
D --> E[Floor/encode depth for D16 or D24]
E --> F[Write gl_FragDepth]
F --> G[Host depth/stencil result]
A fragment-depth write can limit early depth testing or force a conservative execution mode. The exact behavior remains driver- and shader-dependent; it must be measured rather than assumed.
flowchart TD
A[Shader-state builder] --> B{Native-depth subset admitted?}
B -->|No| C[Generate current custom-depth shader]
B -->|Yes| D[Generate matching native-depth vertex/raster mapping]
D --> E[Generate fragment shader with no gl_FragDepth write]
E --> F[Host may perform early depth rejection]
C --> G[Reference guest-depth route]
F --> H[Compare output and GPU work]
G --> H
Illustrative policy:
bool native_depth_eligible(const ShaderState *s)
{
return s->psh.depth_format == DEPTH_FORMAT_D16 &&
!s->psh.z_perspective &&
!s->geom.polygon_offset_enabled &&
!s->w_buffer_enabled &&
!s->depth_readback_sensitive &&
!s->occlusion_report_sensitive;
}
if (native_depth_eligible(state) &&
policy == DEPTH_POLICY_NATIVE_EXPERIMENT) {
options.depth_route = DEPTH_ROUTE_NATIVE;
} else {
options.depth_route = DEPTH_ROUTE_REFERENCE;
}The real implementation must derive the exact eligibility conditions from the current guest-depth mapping. The sketch is not a complete accepted guard.
- Per-fragment floor and encoding operations.
- The explicit fragment-depth write.
- Fragment shader invocations for pixels that the host can reject early.
- Texture reads and register-combiner work for those rejected pixels.
- Correct depth compare direction and range.
- Correct near/far clipping and depth clamp behavior.
- Stencil side effects and alpha/discard ordering.
- Polygon-offset semantics.
- W-buffer and perspective-depth handling.
- Guest-visible depth readback.
- Occlusion/report semantics.
- Exact reference route for unsupported or numerically sensitive states.
A native route is approximate until proven otherwise. It can graduate to an exact shortcut only for states where the host rasterizer and attachment conversion reproduce guest-visible results over all tested values.
The first experiment should be intentionally narrow:
ordinary Z buffering
opaque geometry
no alpha test/discard
no W buffering
no polygon-offset emulation
no guest depth readback during the measured interval
no occlusion report dependency
one depth format and one host GPU family initially
Expanding several dimensions at once would make numerical differences impossible to attribute.
This is the wrong shape:
if (native_depth_enabled) {
// skip assignment
} else {
gl_FragDepth = reference_depth;
}The shader still statically writes fragment depth, so the driver may not recover the intended early-depth behavior. The experiment needs a distinct module/program key and a variant in which no execution path writes gl_FragDepth.
Similarly, a conservative-depth declaration must not be used unless its promise is true for every fragment. A false depth_unchanged, depth_less, or depth_greater declaration can produce undefined depth-test behavior rather than a harmless approximation.
- Can remove whole fragment invocations, not only arithmetic.
- Benefits scale with overdraw and fragment-shader cost.
- Uses the existing shared shader-generation boundary.
- Can remain capability/policy selected with a maintained reference route.
- Also informs a possible Vulkan experiment because the generator is shared.
- One additional shader/program-key dimension increases cache pressure.
- Numerical mismatches can cause z-fighting, decal failure, or incorrect occlusion.
- Alpha/discard and stencil interactions can change ordering.
- A driver may already optimize some shaders, producing little benefit.
- Higher surface scaling can magnify both the opportunity and visible error.
- A successful synthetic overdraw test may not represent normal games.
native_depth_eligible_draws
native_depth_selected_draws
reference_depth_draws
blocked_w_buffer
blocked_polygon_offset
blocked_alpha_or_discard
blocked_report_or_readback
program_variants_created
fragment_invocations, when the host exposes them
GPU elapsed time for admitted draws
The accounting rule is:
eligible draws = native route + policy-forced reference route
If eligibility is near zero, the experiment has not tested the intended shortcut.
| Test | Required result |
|---|---|
| High-overdraw opaque layers | Lower GPU time or fragment invocation count |
| One guest-depth-unit separation | No unexpected compare reversal |
| Coplanar/decal geometry | Differences identified and scoped |
| Alpha-tested geometry | Reference route or proven ordering |
| Stencil operations | Same final stencil/depth state |
| Near/far clipping and depth clamp | Same accepted/rejected geometry |
| Occlusion reports | Same report values or route blocked |
| CPU depth readback | Same bytes or route blocked before readback |
| Native and upscaled resolutions | No scale-dependent unbounded error |
| Multiple host vendors | Capability/result recorded per driver |
Promote to Researched when a Release build proves frequent route use, lower GPU work or tail time, and a clearly bounded numerical compatibility envelope. Promotion to Implemented requires a guarded fallback and title/retail coverage appropriate to the admitted state.
Stop or narrow the route when it only changes depth output without reducing fragment work, when the allowed subset is rarely reached, or when compatibility depends on undeclared title-specific behavior.
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