acdream/src/AcDream.App/Rendering/SceneLightingUboBinding.cs
Erik 8a7a0837e1 feat(render): Vulkan campaign V11 step 2 — delete the OpenGL backend
Vulkan is the sole, user-signed-off backend (V10 landed) and step 1
already removed ImGui/Studio/DevTools. This step deletes the GL
rendering backend itself: every Gpu/Gl/** implementation, the Wb
ManagedGL*/GLHelpers/GLSLShader/GLStateScope/RenderStateCache/
BindlessSupport family, Shader/ShaderProgramConstruction/SamplerCache,
RenderBootstrap, and RenderFrameGlStateController.

GameWindow.cs's Run()/CreateGraphics()/CreateBackbufferReader()/
OnLoad() collapse to their Vulkan-only arm; GameWindowGraphics loses
its OpenGlGameWindowGraphics subclass. RuntimeOptions.RenderBackend and
RenderBackendKind (incl. the Gl member of GpuBackendKind) are gone —
there is nothing left to select between. The five world-draw dual-arm
renderers (WbDrawDispatcher, EnvCellRenderer, TerrainModernRenderer,
ParticleRenderer, SkyRenderer) and the composition roots
(WorldRenderComposition, HostInputCameraComposition,
LivePresentationComposition, FrameRootComposition) collapse to their
RHI-only arm. GL-only diagnostic properties with a live external reader
(DynamicBufferCount and friends) simplify to a documented `=> 0`/no-op
rather than disappearing, since the reader is out of this commit's
scope.

A few GL-flavored mechanisms turned out to be backend-neutral once
isolated: GlConstructionCleanupLedger is renamed
ResourceConstructionCleanupLedger (exception-chain walking has nothing
to do with GL), and GlfwNativePlatformProbe moved out of the otherwise
GL-only GraphicalCapabilityRecord.cs into
GraphicalWindowBackendSelection.cs before the rest of that file was
deleted.

Test files with no surviving subject are deleted outright
(GraphicalCapabilityRequirementsTests, ShaderProgramConstructionTests,
PortalDepthShaderParityTests, TextureCacheBindlessTests,
TextRendererFailureSafetyTests, ClipFrameUploadTests, every
Gpu/Gl/*Tests, GlTextureOwnershipTests, RenderFrameGlStateControllerTests);
others get their dead GL-only members trimmed while their live
assertions stay (ClipFrameLayoutTests' MeshClipSsboBinding check now
reads GpuBindingModel.StorageClipRegions, the same binding index under
its new backend-neutral name; GpuResourceRetirementTransactionTests
drops its OpenGLGraphicsDevice-subclassing test double and the two GL
queue tests it existed for). EnvCellRendererTests' construction helper
now builds a real ObjectMeshManager via VulkanMeshPipelineDevice
instead of passing null through a null-forgiving operator, since the
RHI constructor never tolerated a null mesh manager and the old GL
constructor (which did) is gone.

Deferred to the next two steps, deliberately not touched here: the
Silk.NET.OpenGL/.Extensions.ARB package references, IMeshPipelineDevice.Gl
(WbMeshAdapter's GL? threading stays in place), Chorizite.Core's stale
csproj comment (the package itself is still load-bearing —
TextureFormat and friends are used well beyond the deleted
ManagedGLUniformBuffer), and the CI/gate scripts.

Build: `dotnet build AcDream.slnx -c Release` — 0 warnings, 0 errors.
Tests: full-solution `dotnet test` green across every project
(App.Tests 3937/3940 + 3 skips, Core.Tests 3296/3298 + 2 skips, all
others 100%); the 2 App.Tests names that flake under full-suite
parallel execution (#250-family, documented pre-existing) pass in
isolation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 02:19:53 +02:00

88 lines
3.6 KiB
C#

using System;
using AcDream.App.Rendering.Gpu;
using AcDream.Core.Lighting;
namespace AcDream.App.Rendering;
/// <summary>
/// Publishes the SceneLighting UBO each frame so every shader sampling
/// <c>uLights[]</c> / <c>uFogColor</c> / etc reads consistent data without
/// per-shader re-upload.
///
/// <para>The raw-GL arm this used to have alongside it — a global uniform
/// binding point kept live by a per-flight-slot buffer pool — was deleted at
/// Campaign V slice V11. Vulkan has no such global binding point: a
/// descriptor set is bound per draw, so the upload is a frame ring slice
/// PUBLISHED on <see cref="WorldFrameSections.SceneLighting"/>, and each world
/// renderer binds it inside the pass after its own binds (plan §5.5.14 item
/// 2). Every allocation within a frame is already distinct memory that lives
/// until the frame retires, which is the property the deleted buffer pool
/// existed to provide when the world, portal-space and paperdoll draws each
/// upload different lighting.</para>
/// </summary>
public sealed unsafe class SceneLightingUboBinding : IDisposable
{
private readonly ICurrentGpuFrameSource _frames;
private readonly WorldFrameSections _sections;
private bool _frameStarted;
/// <summary>
/// The GL arm's per-flight-slot buffer pool this used to report on was
/// deleted at Campaign V slice V11: every allocation now comes from a ring
/// that lives until its frame retires, so there is no persistent
/// dynamic-buffer pool left to size.
/// </summary>
internal int DynamicBufferCount => 0;
internal SceneLightingUboBinding(
ICurrentGpuFrameSource frames,
WorldFrameSections sections)
{
_frames = frames ?? throw new ArgumentNullException(nameof(frames));
_sections = sections ?? throw new ArgumentNullException(nameof(sections));
}
/// <summary>
/// Resets the lighting-submission cursor for a GPU-fenced frame slot.
/// World, portal-space, and paperdoll draws can each upload different
/// lighting in one frame, so every upload receives distinct storage.
/// </summary>
public void BeginFrame(int frameSlot)
{
ArgumentOutOfRangeException.ThrowIfNegative(frameSlot);
_frameStarted = true;
}
/// <summary>
/// Push the current frame's UBO contents to the GPU. Cheap (576 bytes)
/// so fine to call unconditionally every frame.
/// </summary>
public void Upload(SceneLightingUbo data)
{
if (!_frameStarted)
throw new InvalidOperationException("BeginFrame must be called before uploading scene lighting.");
IGpuFrame frame = _frames.CurrentFrame
?? throw new InvalidOperationException(
"Scene lighting requires an open IGpuFrame (see GpuDeviceFrameLifetime).");
GpuRingAllocation allocation = frame.AllocateRing(
SceneLightingUbo.SizeInBytes,
GpuRingUsage.Uniform);
new ReadOnlySpan<byte>(&data, SceneLightingUbo.SizeInBytes)
.CopyTo(allocation.Data);
_sections.SceneLighting = new GpuBufferSection(
allocation.Buffer,
allocation.OffsetBytes,
(uint)SceneLightingUbo.SizeInBytes);
}
/// <summary>
/// No-op: this binding owns no GPU resource of its own on the RHI arm — the
/// deleted GL arm's per-flight buffer pool was the only thing to release.
/// Kept as a method so callers that hold this behind an <see cref="IDisposable"/>
/// reference (composition's acquisition scope) don't need a special case.
/// </summary>
public void Dispose()
{
}
}