1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
# OpenGL
> **Scope.** How a stock guest OpenGL application's commands travel through the
> unmodified NVIDIA stack on the emulated vGPU, and the honest state of running
> OpenGL on it. The host-side execution machinery shared by all graphics APIs
> is on [`Graphics-Execution.md`](Graphics-Execution.md); CUDA compute is on
> [`Execution-Frontier.md`](Execution-Frontier.md). Canonical sources:
> [`../docs/04-implementation/05-graphics-execution-plan.md`](../docs/04-implementation/05-graphics-execution-plan.md)
> (the plan and milestones),
> [`../docs/04-implementation/04-real-render-walls.md`](../docs/04-implementation/04-real-render-walls.md)
> (the measured walls) and
> [`../docs/03-architecture/02-guest-stack-and-cudasw.md`](../docs/03-architecture/02-guest-stack-and-cudasw.md)
> (the guest stack). The docs tree wins on disagreement.
Status: 2026-11-13, tree `master @ 436cbf9d`. Tags: `[live]` observed with the
stock guest driver; `[wip]` partial; `[wall]` current blocker; `[target]`
defined success state.
## 1. The guest OpenGL stack
On Linux, an OpenGL application does not talk to the kernel driver directly:
it talks to the GL implementation, and — when a display is involved — through
the X server's GLX extension:
```text
application (toolkit / SDL / GLFW / raw GLX)
-> libGL (dispatch) -> libGLX_nvidia (NVIDIA GLX client)
-> libnvidia-glcore (the vendor GL engine: state, programs, shaders, draws)
-> ioctls + mappings to nvidia.ko -> channels, buffers, synchronization
X server (Xorg)
-> GLX extension module (glxserver_nvidia) and the NVIDIA DDX (X driver)
-> owns the screen, drawables and the present path
```
Two forms of operation exist, and both are visible in the guest:
* **Direct rendering** — the normal desktop case. The GL client builds GPU
commands in its own process and the X server coordinates buffers and
presents. The client's channel is the source of truth for per-draw state.
* **Indirect GLX** — the client's GL protocol is serialised to the X server,
which executes it against its own GL context. Here the X server's channel
carries the graphics stream.
On the emulated vGPU the readable command sources today are the **direct GL
client's own channels** — the GR channel `0xbeef0100` and its CE siblings
`0xbeef0101`/`0xbeef0102` — and the **X server's channels**, whose
graphics-class (`0xC597`, `TURING_A`) sections the emulation captures and
whose DDX kick channel (`0xbfef0002`) is decoded from its ring head
([`Graphics-Execution.md`](Graphics-Execution.md) §3).
## 2. What an NVIDIA GL frame involves (observed shapes)
* **Context and state setup** — shader programs (SASS) uploaded to device
memory, constant/descriptor banks, render targets and depth surfaces
allocated and mapped.
* **Per-draw work** — a graphics-class method stream: state binds (viewport,
render target, ZS, blend/ROP), program and constant binds, vertex/index
data, and draw-issuing methods that drive the fixed-function pipeline
(vertex fetch, primitive assembly, rasterisation, fragment work, ROP).
* **Program/descriptor delivery** — the driver uploads shader code and
descriptors through its copy/utility-channel inline-data path. The GL draw
path decodes these uploads and the engine executes the draw; Vulkan's
inline-to-memory arm is the remaining mirror-image gap
([`Vulkan.md`](Vulkan.md)).
* **Present** — the X server's present/readback path runs as light 2D-class
and copy-engine operations; the emulator decodes and executes those shapes.
## 3. Status on the emulated vGPU
Rated honestly, against the milestone ladder in the plan:
| Item | State |
|---|---|
| X server initialises on the emulated vGPU (driver push-DMA sanity test, ScreenInit) | `[live]` |
| nvidia-modeset/NvKms registers (`/dev/dri/card0`, `renderD128`, `fb0`); `nvidia-smi -L` enumerates | `[live]` (campaign configuration) |
| `glxinfo -B` reports the NVIDIA renderer (OpenGL 4.6.0, driver 570.144, direct rendering) | `[live]` |
| The stock GLX path is fully green: `glxinfo -B` returns 0, `glxgears` renders ~520 FPS, Xorg WAIT count 0 | `[live]` |
| The X driver's RC-watchdog channel registers and its notifier is authored | `[live]` |
| X green on attempt 1 in three consecutive cycles (`ebf3130f`) | `[live]` |
| GSP event-IRQ fix wakes the guest poll; glxgears completes swaps | `[live]` |
| 2D path end-to-end: accelerated X fills read back via `xwd` | `[live]` |
| Guest's real GL draws forward and execute on the physical GPU (`work_gr backend_ok=5-7`) | `[live]` |
| GR backend timeouts fixed (`backend_timeout=0`; draws retire in 3-2400 ms) | `[live]` |
| DDX 3D replay executes (`section captured` + `GR LAUNCH` on `0x1000014`, 12 launches/cycle) | `[live]` |
| First real GPU readback: pbuffer `glClear(red)+glReadPixels` -> `pixel=ff0000ff` | `[live]` |
| First non-black GPU-rendered frames: 500/500 off-screen 640x480 frames per run; 45.4 s video (`r1769`) and a 50 s capture (2026-11-12) | `[live]` |
| Direct-GL GR ring `0xbeef0100` resolves; releases advance; ring/VAS anchor hardened (verified page-directory discovery, eager push pins, per-rank scans) | `[live]` |
| Client-allocated USERD resolved from the channel's memory objects (`hUserdMemory`/`userdOffset`); foreign-USERD adoption skipped; aperture-aware wire fallback | `[live]` |
| X DDX idle-DMA/ScreenInit, USERD-latch lifetime, re-probe thrash, Xorg kernel-mode spin (GET-past-PUT) and flip-event walls closed; X green >10 minutes (`13a0c5d6`, `acb51d53`, `6ebc7cd4`, `770d6b4a`, `b9213c57`, `29690635`) | `[live]` |
| Captured GL sections execute on the engine (`GR LAUNCH submitted` / `GUEST GR LAUNCH OK`); data window populated (`n_data` 0 -> 1024) | `[live]` |
| Client push bodies decode as real GR method streams above 10 GiB via the VAS walk (live-PA bound raised to the registered guest-RAM top, `436cbf9d`) | `[live]` |
| GZDoom passes `V_Init: allocate screen` with GL 4.6.0 when shared nvClip `modeNum` is even | `[live]` |
| RM write-lock holder identified (Xorg in the DDX vidheap scrub wait) and fixed (`df6e71bb`) | `[live]` |
| Engine executes a launch built from the captured section (real `sm_75` SASS retired) | `[live]` |
| Verbatim 3D method-stream replay retired by the engine, no MMU fault | `[live]` |
| Emulated FB/GART sizing traps fixed (FB info replies in KB; GART default 256 MiB), removing the 4 GiB guest-allocation class | `[live]` |
| Direct-GL command-stream delivery (gl setup push at VA `0x4001004` and draws at `0x4250000`/`0x4250110`; the CE ring `0xbeef0101`) | `[wall]` — the payloads' user/UVM VAS is never registered; they resolve to zero/implausible PAs and no section opens for `0xbeef0100` |
| Window/screen present produces non-black screen pixels | `[wall]` |
| X screen-init first-generation lottery (`modeNum` parity; only an immediately-post-boot X passes DDX DMA init) | `[wip]` |
| 60 fps sustained, no forcing (M-GL4) | `[target]` |
## 4. How OpenGL runs are verified
Instruments that matter, in order of usefulness: the X server log and
`xdpyinfo` (did the server initialise?), `glxinfo -B` (which renderer is
real), the application's own progress output, and frame capture at the GL
source (a swap-hook capture is the ground truth for pixels — the X screen
itself is not, on some stacks). Captures are decoded offline and scored:
fraction of pixels above a luminance threshold, colour count, and
frame-to-frame motion. A run counts only when the capture shows motion with
the NVIDIA renderer in use.
## 5. Milestones on this path
The graphics plan defines M-GL1 (client context-init decodes and executes; the
client leaves its retry loop), M-GL2 (`glxgears` non-black), M-GL3 (GZDoom GL
non-black through the mdev), M-GL4 (60 fps, no forcing), M-GL5 (two VMs, two
mdevs), M-GL6 (split-screen video). The project sits **between M-GL1 and
M-GL2, with M-GL2's off-screen half proven**: the display/KMS stack registers,
X and the stock GLX path are fully green (`glxinfo -B` rc 0, ~520 FPS
`glxgears`, Xorg WAIT 0), the DDX/X-stability walls were closed (X green for
more than 10 minutes), the direct-GL ring/USERD machinery is hardened, and the
GPU-rendered pbuffer path produced non-black animated frames and captured
videos (45.4 s and 50 s). Captured GL sections now execute on the engine and
the client's push bodies decode as real GR method streams above 10 GiB. The
remaining gates are **delivery of the direct-GL client's own command stream**
(the setup push at `0x4001004` and the draws at `0x4250000`/`0x4250110` still
resolve to zero/implausible PAs because their user/UVM VAS is never
registered), the window/screen present path (glxgears' window is black and a
window draw can wedge X), and the X first-generation screen-init lottery —
then the first rendered screen frame.
## 6. What is not claimed
* No **window/screen** frame has rendered real pixels through the emulated
vGPU yet; every screen capture so far is black. The non-black frames and the
videos (45.4 s and 50 s) come from the off-screen pbuffer path (pbuffer ->
sysmem -> kvmfr ivshmem -> host reader), not from a windowed X screen
capture. The direct-GL payload VAS is not registered, its draws do not reach
the engine, a synchronous window draw wedges X, and X screen-init retains a
per-boot first-generation lottery. Those are the current walls.
* GZDoom reaching `V_Init: allocate screen` is not a rendered-frame claim; it
proves the client's GL init and the direct-GL GR lane, not the game loop or
a presented frame.
* No frame-rate or latency numbers.
## 7. Related pages
* [`Graphics-Execution.md`](Graphics-Execution.md) — the shared execution
machinery and the ranked walls.
* [`Vulkan.md`](Vulkan.md) — the sibling API path, further along in the
pipeline lifecycle.
* [`DirectX.md`](DirectX.md) — the Windows/DirectX target.
* [`CUDA-Userspace-Driver.md`](CUDA-Userspace-Driver.md) — how the NVIDIA
userspace stack is analysed.
* [`Install-and-First-Run.md`](Install-and-First-Run.md) — bringing the stack
up.
* [`../docs/04-implementation/05-graphics-execution-plan.md`](../docs/04-implementation/05-graphics-execution-plan.md) —
the canonical plan, gap list and gates.
|