Commit graph

4 commits

Author SHA1 Message Date
Erik
7a0227c12e feat(render): Vulkan campaign V11 step 3 — drop the GL packages and shaders
Commit 2 deleted the GL rendering backend's implementations; this step
removes the package references and shader vocabulary they leave behind,
so nothing in the App project still spells Silk.NET.OpenGL.

Silk.NET.OpenGL and Silk.NET.OpenGL.Extensions.ARB are dropped from
AcDream.App.csproj. Chorizite.Core stays — the audit is NOT clean: its
Render.Enums (TextureFormat, BufferUsage) and Lib.BoundingBox types are
used directly and extensively across the Wb texture/mesh pipeline,
independent of the deleted GL IUniformBuffer implementers the package
comment used to cite. The stale comment is corrected in place.

IMeshPipelineDevice.Gl is removed along with the GL? gl parameter
threaded through WbMeshAdapter's four constructors, WorldRenderComposition's
CreateMeshAdapter, and VulkanMeshPipelineDevice's Gl => null
implementation — nothing read any of them once the legacy per-mesh
upload bodies were gone (confirmed by grep: the sole non-doc-comment hit
was a test assertion). While in WbMeshAdapter.Dispose(), found and fixed
a real bug along the way: its teardown still pattern-matched the deleted
GL GpuFrameFlightController to decide whether to wait for submitted work,
which VulkanFrameFlightController replaced at slice V6a without this site
being updated — so the wait had been silently dead on every Vulkan run
since then. Retargeted to VulkanFrameFlightController, which carries the
same WaitForSubmittedWork().

The GL pixel-format vocabulary (Silk.NET.OpenGL.PixelFormat/PixelType) that
WorldTextureArray/TextureFormatExtensions/TextureAtlasManager used for
upload validation is replaced by AcDream.Content's existing Silk.NET-free
UploadPixelFormat/UploadPixelType enums (added at MP1a to keep the bake
tool GL-free); two new members (Rgb, Red, Float) extend that enum with
their GL ABI constants to cover the full vocabulary WorldTextureArray
needs, since MP1a's original set only covered what the extractor itself
emits. ObjectMeshManager's App-boundary cast
`(Silk.NET.OpenGL.PixelFormat?)batch.UploadPixelFormat` becomes a direct
pass-through now that both sides share the type.

GpuBindingModel.StorageTextureTable (the GL-only binding=9 emulation of
the Vulkan texture table) is deleted and StorageBindingCount drops from
10 to 9; the descriptor-set-layout code that builds from that count
(VulkanPipelineLayouts, VulkanFrameBindings) is untouched and just
allocates one fewer always-dummy-seeded, always-unused binding.

Several fully dead GL-only classes came along for the ride, confirmed by
zero construction sites: SilkFramebufferViewportTarget
(NullFramebufferViewportTarget is the sole production
IFramebufferViewportTarget), SilkRenderGlStateReader
(NullRenderGlStateReader.Instance is the sole IRenderGlStateReader),
RuntimeRenderFrameClearPhase (VulkanRenderFrameClearPhase is the sole
IRenderFrameClearPhase, expressing the same atmosphere-clear logic as a
pass load-op instead), and GpuFrameTimer plus FrameProfiler's
GL-owning FrameBoundary(GL) overload and BeginGpuFrame/EndGpuFrame
bracket (RecordGpuSample is the only GPU-timing path any backend uses
now — the ACDREAM_WB_DIAG nested-query exclusion these existed for no
longer applies, since WbDrawDispatcher's own diagnostic GPU sampling
already moved to the device's Vulkan timer pool). GpuFrameFlightController
itself stays (never constructed with a real fence API in production, but
its retirement-ledger/serial-ring logic is backend-neutral and still
covered by its own unit tests) — only its GL-specific parts (the public
GL constructor overload, SilkGpuFenceApi) are deleted, since removing the
whole class would mean restructuring the frozen Slice-8 composition
shape's GpuFrameFlightController? threading, which is out of this
commit's scope. TextureParameters.cs and BufferUsageExtensions.cs
(zero callers each) are deleted outright.

common.glsl is deleted: nothing in the actual Vulkan .spv build reads
it. tools/ShaderCompiler/Program.cs compiles each .vert/.frag pair
directly and tools/ShaderCompiler/VulkanGlslPreamble.cs injects its own
complete self-contained preamble per file; common.glsl's textual
concatenation was exclusively Shader.cs's GL-only mechanism, deleted at
Commit 2. The five shader files that named it in comments
(mesh_modern.vert, particle.vert, particle.frag, sky.frag,
terrain_modern.frag) are corrected to point at VulkanGlslPreamble.cs
instead. mesh.vert/mesh.frag — the pre-N.5 legacy shader pair the
mandatory modern path already made unreachable, with zero C# consumers
and no compiled .spv — are deleted too. Regenerated via
tools/compile-shaders.ps1: 9/9 remaining shader pairs compile
(previously 9/10, with mesh the sole failure — the VulkanShaderManifestTests
doc comment's "nine of ten are not Vulkan-expressible" was already
stale before this commit).

Test fallout: dead-subject test methods/files are deleted rather than
patched (TextRendererFailureSafetyTests.cs, ClipFrameUploadTests.cs,
GpuResourceRetirementTransactionTests.cs's GL queue tests, one
WorldRenderDiagnosticsTests source-order test, one
RenderFrameResourceControllerTests clear-phase-order test); tests whose
subject moved or was renamed are updated in place rather than deleted
(GpuContractTests, VulkanCapabilityGateTests, MeshPipelineDeviceSeamTests'
pinned seven-member surface now reads six, ParticleBindlessInstanceTests'
cross-dialect check now covers the one surviving dialect,
WbMeshAdapterTests' misleadingly-named null-gl test — gpuDevice was
always the parameter that actually threw).

Build: `dotnet build AcDream.slnx -c Release` — 0 warnings, 0 errors,
with the Silk.NET.OpenGL/.Extensions.ARB package references physically
removed from the csproj (not just unreferenced in code).
Tests: full-solution `dotnet test` green across every project.
Zero remaining `using Silk.NET.OpenGL` anywhere in src/ or tests/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 02:58:15 +02:00
Erik
fed636b9c0 test(render): add blank-world attribution apparatus and a post-world GL sample
Investigating the V4c connected blank-world failure needed two things the tree
did not have: a way to tell whether a blank run is caused by the binary under
test, and a way to see GL state at the end of the world phase rather than only
at the frame clear. Both are apparatus only - no production behaviour changes,
and the new probe emits nothing unless ACDREAM_PROBE_GLSTATE=1.

run-blank-world-ab-probe.ps1 interleaves two client builds over the repeat
gate's exact connected route and reports the blank rate per arm. This exists
because the blank rate is not stable across blocks: the same V4c binary
measured 3/10 in one block and 7/10 in another an hour later, so a block of A
followed by a block of B confounds the change with whatever else moved on the
machine in between. Strict alternation shares that drift between both arms.
Run against V4c and its parent it reported 4/5 versus 0/5 (Fisher exact
p~0.024), which is what established the defect follows the binary.

run-blank-world-surface-probe.ps1 grabs the composited window off the desktop
with CopyFromScreen at the same moment the client writes its own screenshot.
No instrument inside the GL context can separate "the renderer drew nothing"
from "the read did not return what the renderer drew", because both live on
the same side of the readback; an independent witness can. It is what showed
the two disagree - see below.

EmitPostWorldGlStateIfChanged is a second sample of the existing [gl-state]
snapshot, taken at the end of the normal-world phase. The existing tripwire
samples just after the clear phase's RestoreFrameDefaults, so it can only
observe state that survives from one frame into the next, and the draw
framebuffer is restored by no frame-global path. A binding established during
the world phase and put back before the next clear was therefore invisible to
it. Sampling at both ends brackets the phase.

What the apparatus established, recorded here rather than in the campaign doc
because no fix landed and the doc's re-land conditions are unchanged:

  * The world draw path is not what is missing from the frame. On a blank run
    the desktop grab shows the atmosphere clear over the whole viewport and the
    complete retained UI - chat, radar, toolbar, vitals - in their normal
    places, with every 3-D surface absent. Terrain and sky are still raw GL and
    V4c does not touch them, so whatever V4c disturbs is shared, not per-
    renderer.
  * The CPU issues the same work either way. With ACDREAM_PROBE_FLAP=1 the
    render signature is identical between blank and rendered runs: same
    RetailPViewInside branch, same resolved root, terrain drawn, 3,331 outdoor
    statics and 6 live dynamics dispatched.
  * Both GL-state samples read fbo=0, full 1280x720 viewport, scissor off and
    err=0x0, byte-identical between blank and rendered runs.
  * The client's own capture disagrees with the screen. glReadPixels returns
    uniformly RGBA(0,0,0,0) on a frame the desktop grab shows as fog plus UI.
    The default framebuffer is 4x multisampled (SampleBuffers=1, Samples=4 in
    the capability report) and glReadPixels against a multisampled read
    framebuffer is undefined per the GL spec, so the gate's blank-versus-
    rendered verdict rests on undefined behaviour in both directions.

Baseline App tests 3,864 passed / 3 skipped, unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-28 00:08:10 +02:00
Erik
85239fb373 refactor(render): extract typed retail pview passes 2026-07-22 06:40:09 +02:00
Erik
733126a272 refactor(render): extract frame presentation diagnostics 2026-07-22 05:02:31 +02:00