From d312bd2ff111dfa5bfda09b49222c0f3943730d8 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 29 Jul 2026 03:24:34 +0200 Subject: [PATCH] =?UTF-8?q?docs(render):=20Campaign=20V=20V11=20status=20?= =?UTF-8?q?=E2=80=94=20deleted=20and=20statically=20green,=20runtime=20gat?= =?UTF-8?q?es=20blocked?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Records what V11 actually achieved and, more importantly, what it did not. The deletion landed: 204 files, +1,870 / -27,607 lines across five commits. Section 5.5.24 keeps the three findings that outlive the diff. * Chorizite could NOT be dropped, and not for the reason section 6 predicted. The risk register assumed the package survived only because the ManagedGL types implemented IUniformBuffer from it. The audit found TextureFormat in the IWorldTextureArray signature the VULKAN path implements, and BoundingBox serialized into the pak format. Dropping it is a slice that touches the on-disk format, not a V11 cleanup. * Two traps the V11 row did not know about. Studio/SampleData.cs is production code behind the character sheet's fallback, so it moved rather than died; ACDREAM_DEVTOOLS also gates Vulkan debug-utils, so the flag survives and now says out loud that its UI is gone. * Deleting GL surfaced a real bug: WbMeshAdapter.Dispose() was still pattern-matching the GpuFrameFlightController that V6a replaced, so its wait for submitted GPU work had been silently dead on every Vulkan run since. Removing the type turned a no-op into a compile error. The runtime gates did not run, and the honest reason is written down rather than smoothed over. The client dies at vkGetPhysicalDeviceSurfaceCapabilitiesKHR in files V11 never touched. Bisecting put the failure at the PRE-V11 commit whose Vulkan soak had passed 91 checkpoints three hours earlier, and `vulkaninfo --summary` -- a Khronos tool with none of our code -- fails at the same call. Win32 surface creation is broken machine-wide; Vulkan itself is fine. That is issue #259, with the one-line diagnosis at the top so the next person checks the machine before bisecting the tree. So the row reads DELETED AND STATICALLY GREEN, RUNTIME GATES BLOCKED. Release build is 0/0 and the complete Release suite is 8,999 / 5 skipped (-218 against V10, every one a test that lost its subject). Nothing was relaxed to manufacture a pass: section 7.1 rule 2 cuts both ways, and a gate that could not run is not a gate that passed. The rerun list is in 5.5.24, and the pre-deletion pixel baseline was captured BEFORE the deletion, so the self-differential is still available whenever a window can be made again. Co-Authored-By: Claude Fable 5 --- docs/ISSUES.md | 51 +++++++++++++ docs/plans/2026-07-27-vulkan-campaign.md | 92 +++++++++++++++++++++++- 2 files changed, 142 insertions(+), 1 deletion(-) diff --git a/docs/ISSUES.md b/docs/ISSUES.md index 7c8565fa..5d880d59 100644 --- a/docs/ISSUES.md +++ b/docs/ISSUES.md @@ -97,6 +97,57 @@ Copy this block when adding a new issue: --- +## #259 — Win32 Vulkan surface creation fails machine-wide (`ERROR_UNKNOWN`) + +**Status:** OPEN — environment fault, not a product defect; recorded so the next +reader does not bisect the tree for it +**Severity:** HIGH while it lasts (the client cannot start at all) +**Filed:** 2026-07-29 +**Component:** host machine / AMD driver / Win32 WSI + +**Symptom:** every `AcDream.App` launch dies during startup with + +``` +VulkanCallException: vkGetPhysicalDeviceSurfaceCapabilitiesKHR returned ErrorUnknown + at VulkanSwapchain.QuerySurface() + at VulkanGraphicsContext.SelectDeviceAndGate() +``` + +**It is not our code.** Observed first during the V11 gate battery and bisected: +the failure reproduces identically at V11 HEAD, at both V11 implementation +commits, and at `db4426d5` — the **pre-V11** commit whose Vulkan soak had +completed 91 checkpoints three hours earlier on the same machine. +`VulkanSwapchain.cs` and `VulkanGraphicsContext.cs` were not modified by V11. + +**The one-line diagnosis.** Run the Khronos tool, which shares no code with us: + +``` +> vulkaninfo --summary +ERROR while creating surface for extension VK_KHR_win32_surface : failed with ERROR_UNKNOWN +``` + +If `vulkaninfo` fails there too, the fault is the machine's, not acdream's, and +no amount of bisecting the tree will find it. **Check this first** whenever the +client will not open a window. + +**State when observed:** session not locked (`LogonUI` absent), desktop present +at 2560x1440, both adapters (RX 9070 XT driver 32.0.31021.5001, and the +integrated Radeon) reporting `Status = OK` and enumerating with Vulkan 1.4. +Vulkan instance and device creation succeed; only Win32 *surface* creation +fails. It followed several hours of continuous GPU-heavy soak runs. + +**Expected remedy:** restart the display driver or reboot. Not reproduced from a +cold boot. If it recurs *after* a reboot, it stops being an environment note and +becomes a real investigation — capture `vulkaninfo --summary` and the driver +version at that point. + +**Blocked by this:** V11's runtime gate battery (offline pixel gate, both +connected routes, validation run, working-set re-measure). The pre-deletion +pixel baseline is already captured at `artifacts/v11-pre`, so the +self-differential is still available once a window can be created. + +--- + ## #258 — Developer panels have no host after V11 deleted ImGui **Status:** OPEN diff --git a/docs/plans/2026-07-27-vulkan-campaign.md b/docs/plans/2026-07-27-vulkan-campaign.md index 240a36db..1cf5d504 100644 --- a/docs/plans/2026-07-27-vulkan-campaign.md +++ b/docs/plans/2026-07-27-vulkan-campaign.md @@ -624,7 +624,7 @@ tenth pair with no consumer at all; see the V6e report. | **V8** ⏸ **measured; two floors missed; the cutover call is the user's — §5.5.21** | Perf gate on the RX 9070 XT, uncapped, both backends, same scene, same day. **What landed:** `VulkanFrameGpuMeasurement` (`00e1b321`), without which the Vulkan arm emitted no `[frame-prof]` line at all — `NullRenderFrameGpuMeasurement` was the only caller of `FrameProfiler.FrameBoundary`, so no performance vehicle could be pointed at it; the finding that **the R6 soak is NOT the vehicle §2's founding numbers came from and is biased against Vulkan** by the per-frame swapchain copy its own artifact directory arms; a same-day GL-versus-Vulkan profile on the G5 ordinary-production vehicle; a phase-level CPU attribution on both arms; and **the R6 soak run natively on Vulkan** (PASS, 0 failures, graceful exit), which V7 left outstanding. **Result, in three configurations:** on a stationary LIGHT scene at 780-870 FPS Vulkan is 75.4% cheaper on GPU p50 and 85.3% lighter on allocation but **14.8% more expensive on CPU p50 and 8.8% on p99** — two floors missed; on a stationary DENSE scene (21,024 entities, identical on both arms) **Vulkan wins every row**, including CPU p50/p99 and 18.5% less total process CPU by Windows' accounting; and on the nine-stop route against an identical world **Vulkan wins every row** and renders **27.3% more frames**. The Vulkan-specific cost is **fixed per frame** — 0.148 ms of required WSI/sync calls (present 0.070, submit 0.027, timeline wait 0.026, acquire 0.025) against GL's ~0.014 ms of present — so it dominates an almost-empty frame and disappears into a full one. **The campaign's named cost centre is closed as measured-and-not-worth-it:** bindings 4/6/7/8 cost **0.031 ms for all ~216 draws of the frame**, 2.4% of it. No Vulkan code was changed to chase the miss. **Not taken:** the RenderDoc capture — RenderDoc is not installed on this machine; it carries to V10. | §2 acceptance table; parity is the floor | | **V9** ✅ **CI green — §5.5.20, §5.5.22** | Linux + CI: a `linux-vulkan` job on lavapipe (probe accepts on a real 1.3+ software device, a short real render under xvfb, forced-unsupported → exit 4, `.spv` freshness). **What landed:** the eleven-step job; `ACDREAM_VULKAN_PROBE_FRAMES`, without which the harness cannot terminate unattended; `tools/compile-shaders.ps1` made path-portable; and the report's jq contract pinned by App tests so a rename fails locally rather than in CI. lavapipe clears every gate requirement by source inspection, including the `samplerAnisotropy` V7 made load-bearing. **Deferred:** the physical Linux GPU row, post-cutover, as for Slice L; and Wayland, which no runner offers. **Not attempted, with cause:** a GL-versus-Vulkan pixel comparison — the GL job asserts exit 4 and so has no frame, and the probe renders synthetic scenes rather than the DAT world CI cannot have. | CI green including the new job — **met**: run 30393357552, all four jobs green, lavapipe `llvmpipe (Cpu)` at Vulkan 1.4.318 / Mesa 25.2.8, a 1280x720 / 35,594-byte captured frame, and "all committed .spv match a fresh compile" on Linux | | **V10** ◐ **flipped and measured; PENDING THE USER'S SIGNATURE — §5.5.23** | Cutover: Vulkan default, GL reachable by env var for one slice, gate scripts default to VK. **What landed:** `ParseRenderBackend` inverted (unset/typo → Vulkan; only `gl`/`opengl` → OpenGL, the polarity of the typo case flipping with the default because GL is now the backend V11 deletes); `run-offline-pixel-gate.ps1` gained `-Backend` (default `vulkan`) and forces all four determinism levers plus MSAA off instead of inheriting them; the two connected gates **clear** `ACDREAM_RENDER_BACKEND` so they exercise the process default and an ambient override cannot disguise a GL run as one. **Battery:** complete Release suite **9,222 / 5 skipped / 0 failed** (`#250` family also 4/4 singly); repeat connected gate **3/3 on both columns**; connected world-lifecycle route **PASS**, 0 failures, both sessions graceful at exit 0; validation layer proven inserted at instance and device level with **zero errors and zero warnings**; GL escape hatch verified by two offline launches. **Every connected launch reached Vulkan with no environment variable set.** **The pixel gate is NOT met and was not relaxed:** VK against the GL-era capture is **1.099e-03 masked / 3.764e-02 whole-frame**, 97.9% of it in the treeline band, the masked residual entirely on distant alpha-blended scenery silhouettes — `AD-46`, whose register row this slice moves from dormant to live. Below the band the arms are photometrically identical (mean luminance Δ 0.01 of 255). Nothing GL, ImGui or Studio is deleted; that stays V11's. **Rollback: `git revert` of this slice's commit.** | complete Release suite + retail expected PNGs **on VK** (baselines not regenerated) + both connected routes + **user visual sign-off** | -| **V11** | GL deletion and closeout: delete `Gpu/Gl`, `OpenGLGraphicsDevice`, `ManagedGL*`, `GLSLShader`, `GLHelpers`, `GLStateScope`, `RenderStateCache`, `BindlessSupport`, `GraphicalGlFunctionProbe`, the GL branch in `GameWindow`, the ImGui project and Studio; drop the GL and (if the audit is clean) Chorizite packages; file the retained-UI dev-panels follow-up; swap CI assertions to VK; update the divergence register, architecture doc, code-structure doc, and rendering memory crib; re-measure memory. | complete Release suite + both connected routes + working-set re-measure | +| **V11** ◐ **DELETED AND STATICALLY GREEN; RUNTIME GATES BLOCKED BY A MACHINE-LEVEL WSI FAULT — §5.5.24** | GL deletion and closeout. **What landed (5 commits, `844cf092`→`c265b52d`): 204 files, +1,870 / −27,607 lines.** The GL backend, `ManagedGL*`, `GLHelpers`, `GLStateScope`, both render-state caches, `BindlessSupport`, `GraphicalGlFunctionProbe`, the ImGui project, the Studio tree and the `ui-studio` verb are gone; `RenderBackendKind` and the `ACDREAM_RENDER_BACKEND` escape hatch are gone with them. `Silk.NET.OpenGL` and `.Extensions.ARB` dropped — **final reference count zero**. `common.glsl`'s GL-only binding-9 texture table and every `GL_ARB_bindless_texture` pragma removed; 9/9 shader pairs recompile. **Two traps the plan did not anticipate:** `Studio/SampleData.cs` was a live production dependency of the retained-UI composition (moved, not deleted) and `ACDREAM_DEVTOOLS` also gates Vulkan debug-utils (kept, now logs that the UI is gone). **Chorizite stays** — the audit is NOT clean: `TextureFormat` is in surviving texture-array signatures and `BoundingBox` is a serialized pak type. **Static gates PASS:** Release build 0 warnings / 0 errors; complete Release suite **8,999 passed / 5 skipped / 9,004** (−218 against V10's 9,222, every one a GL/Studio/DevTools test that lost its subject). **Runtime gates NOT RUN:** the offline pixel gate, both connected routes, the validation run and the working-set re-measure all need a window, and this machine cannot currently create one — see §5.5.24. **Rollback:** revert `c265b52d`, `5852bdb8`, `7a0227c1`, `8a7a0837`, `844cf092`, newest first. | complete Release suite ✅ + both connected routes ⚠ outstanding + working-set re-measure ⚠ outstanding | ### 5.2 Why V2's handle table is not the device's table @@ -3473,6 +3473,96 @@ notes that the reason it was demoted no longer obviously applies. outstanding: V8 established the cause — RenderDoc is not installed on this machine — and nothing about the cutover changes that. It carries to V11. +#### 5.5.24 V11 (2026-07-29): the deletion lands, and the machine stops making windows + +**The deletion is done and the static gates pass.** Five commits removed 27,607 +lines against 1,870 added. What went is listed in the V11 row; what stayed, and +why, is the part worth keeping. + +**Chorizite could not be dropped, and the reason is not the one the risk +register predicted.** §6 assumed the package survived only because +`ManagedGLUniformBuffer` and `OpenGLGraphicsDevice` implemented `IUniformBuffer` +from it — so deleting them would free it. The audit found otherwise: +`Chorizite.Core.Render.Enums.TextureFormat` sits in the +`IWorldTextureArray.CreateClampedArray` signature that the **Vulkan** path +implements, `AcDream.Core/Rendering/Wb/TextureHelpers.cs` needs it, and +`Chorizite.Core.Lib.BoundingBox` is a **serialized type in the pak format** via +`AcDream.Content`. Dropping it is a separate slice that touches the on-disk +format, not a V11 cleanup. The stale justification comment in the csproj is +corrected in place so the next reader is not misled the same way. + +**Two traps the plan's V11 row did not know about**, both of which would have +broken the build or the client if taken literally: + +1. `Studio/SampleData.cs` is **production code**. + `InteractionRetainedUiComposition` passes `SampleData.SampleCharacter` as the + character sheet's fallback, and three surviving UI-layout test files use it + about ninety times. It was moved to `UI/Layout/`, not deleted. +2. `ACDREAM_DEVTOOLS` is **not only** a devtools switch — it also selects + Vulkan's debug-utils instance extensions in `VulkanGraphicsContext`. The flag + survives; only the ImGui frontend went, and setting it now logs one line + saying so rather than silently doing nothing. + +**One real bug fell out of the deletion.** `WbMeshAdapter.Dispose()` was still +pattern-matching the deleted `GpuFrameFlightController` to decide whether to +wait for submitted GPU work. `VulkanFrameFlightController` replaced that type at +V6a and this site was never updated, so **the wait had been silently dead on +every Vulkan run since V6a**. Deleting the GL type is what made it a compile +error instead of a no-op. + +--- + +**The runtime gates did not run, and the reason is not V11.** + +The offline pixel gate failed with the client dying at startup: + +``` +VulkanCallException: vkGetPhysicalDeviceSurfaceCapabilitiesKHR returned ErrorUnknown + at VulkanSwapchain.QuerySurface() + at VulkanGraphicsContext.SelectDeviceAndGate() +``` + +`VulkanSwapchain.cs` and `VulkanGraphicsContext.cs` are **untouched by V11**, so +the first move was to bisect rather than to theorise. The client fails +identically at V11 commit 2, at V11 commit 1, and at **`db4426d5`, the pre-V11 +commit whose Vulkan churn arm had completed 91 checkpoints three hours earlier +and whose offline capture had succeeded.** + +That put the fault outside the tree, and one command settled it: + +``` +> vulkaninfo --summary +ERROR while creating surface for extension VK_KHR_win32_surface : failed with ERROR_UNKNOWN +GPU0: AMD Radeon RX 9070 XT apiVersion 1.4.349 +GPU1: AMD Radeon(TM) Graphics apiVersion 1.4.315 +``` + +**A Khronos tool containing no acdream code fails at the same call.** Vulkan +itself is healthy — both adapters enumerate and report 1.4 — but *Win32 surface +creation is broken process-wide on this machine*. The session is not locked, +`LogonUI` is not running, the desktop is present at 2560x1440 and both adapters +report `Status = OK`. This is transient driver/compositor state, of the class a +reboot or a display-driver restart clears. + +**So V11 is committed and statically green, and its runtime evidence is +outstanding.** Nothing was relaxed to manufacture a pass and nothing was +declared green on a prediction — §7.1 rule 2 cuts both ways, and a gate that +could not run is not a gate that passed. When the machine can make a window +again, the outstanding list is exactly: + +| Gate | Command | +|---|---| +| Offline pixel gate (VK self-differential) | `tools/run-offline-pixel-gate.ps1 -Out artifacts/v11-post -Baseline artifacts/v11-pre -SkipBuild` — **the pre-deletion baseline was captured before the deletion and is already on disk at `artifacts/v11-pre`** | +| Repeat connected gate | `tools/run-repeat-connected-gate.ps1 -Runs 3` | +| Connected world-lifecycle route | `tools/run-connected-world-lifecycle-gate.ps1` | +| Validation proven-loaded, zero errors | any connected launch with `ACDREAM_DEVTOOLS=1` | +| Working-set re-measure | the offline scene, once it renders | + +The baseline capture being taken *before* the deletion is the one piece of +timing that survived the fault: the left-hand side of the self-differential +exists, so the comparison is still available whenever the right-hand side can be +produced. + ### 5.4 The null-target `BeginPass` divergence (V4c) — ✅ DISCHARGED at V6k > **Closed 2026-07-28 by V6k commit 2 (`eb7e6b4e`); see §5.5.16.** The answer is