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>
157 lines
7.7 KiB
C#
157 lines
7.7 KiB
C#
namespace AcDream.App.Rendering.Gpu;
|
||
|
||
/// <summary>
|
||
/// Campaign V (V0): the PINNED binding model shared by the CPU renderers, the
|
||
/// GLSL sources, and both RHI backends. Every number here appears in a shader
|
||
/// file; changing one is a contract change that must land in the same commit as
|
||
/// the matching shader edit.
|
||
///
|
||
/// The model is deliberately Vulkan-shaped and dual-legal:
|
||
///
|
||
/// set 0 — storage buffers, bindings 0..9. GLSL omits the set qualifier, and
|
||
/// GL_KHR_vulkan_glsl defines an omitted set as set 0, so one source
|
||
/// file compiles for both backends.
|
||
/// set 1 — uniform buffers. Vulkan has ONE binding namespace per set, while
|
||
/// GL keeps GL_SHADER_STORAGE_BUFFER and GL_UNIFORM_BUFFER tables
|
||
/// separate. Today mesh_modern.vert exploits that: the BatchBuffer
|
||
/// SSBO and the SceneLighting UBO both sit at binding=1. Moving UBOs
|
||
/// to their own set preserves both numbers and removes the collision.
|
||
/// set 2 — the global sampled-texture table that replaces ARB_bindless_texture.
|
||
/// Vulkan binds it as one variable-count, partially-bound,
|
||
/// update-after-bind descriptor array. GL used to emulate it with a
|
||
/// storage buffer of uvec2 handles at set 0 binding 9
|
||
/// (<c>StorageTextureTable</c>); Campaign V slice V11 deleted that
|
||
/// binding along with the rest of the raw-GL arm, so set 2 is the
|
||
/// only texture table left.
|
||
///
|
||
/// A batch no longer carries a 64-bit bindless handle; it carries a
|
||
/// <see cref="GpuTextureSlot"/> index into the table. That single change is what
|
||
/// makes the CPU-side data model backend-neutral (Campaign V slice V2), and it
|
||
/// lands on GL — pixel-gated — long before any Vulkan code exists.
|
||
/// </summary>
|
||
internal static class GpuBindingModel
|
||
{
|
||
// ---- set 0: storage buffers (identical numbering to today's SSBO bindings) ----
|
||
|
||
/// <summary>Per-instance transforms. std430 <c>InstanceData { mat4 transform; }</c>.</summary>
|
||
public const uint StorageInstances = 0;
|
||
|
||
/// <summary>Per-draw batch metadata. std430 <c>BatchData</c> (see <see cref="GpuBatchDataStrideBytes"/>).</summary>
|
||
public const uint StorageBatches = 1;
|
||
|
||
/// <summary>Phase U.3 shared per-frame clip regions (<c>CellClip</c>, 144 B/slot). Slot 0 = no-clip.</summary>
|
||
public const uint StorageClipRegions = 2;
|
||
|
||
/// <summary>Phase U.3 per-instance clip-slot index, parallel to <see cref="StorageInstances"/>.</summary>
|
||
public const uint StorageClipSlots = 3;
|
||
|
||
/// <summary>A7 Fix B global point/spot light array.</summary>
|
||
public const uint StorageGlobalLights = 4;
|
||
|
||
/// <summary>A7 Fix B per-instance light set: 8 indices into the global light array, -1 = unused.</summary>
|
||
public const uint StorageInstanceLightSets = 5;
|
||
|
||
/// <summary>#142 per-instance indoor flag (1 = parented to an EnvCell, skip the sun).</summary>
|
||
public const uint StorageInstanceIndoor = 6;
|
||
|
||
/// <summary>#188 per-instance opacity multiplier for TransparentPartHook fades.</summary>
|
||
public const uint StorageInstanceAlpha = 7;
|
||
|
||
/// <summary>Retail SmartBox selection lighting: one vec2 (luminosity, diffuse) per instance.</summary>
|
||
public const uint StorageInstanceSelectionLighting = 8;
|
||
|
||
// Campaign V slice V11 deleted StorageTextureTable (binding 9): the GL-only
|
||
// emulation of the Vulkan texture table via a storage buffer of uvec2
|
||
// bindless handles indexed by GpuTextureSlot.Index. The Vulkan backend
|
||
// always bound TextureTableSet instead and never used this binding — every
|
||
// Vulkan descriptor set layout declared it anyway (seeded with a dummy
|
||
// buffer, like every other unused-by-a-given-shader binding), purely
|
||
// because it counted toward StorageBindingCount.
|
||
|
||
/// <summary>One past the highest storage binding — the count the backend must support.</summary>
|
||
public const uint StorageBindingCount = 9;
|
||
|
||
// ---- set 1: uniform buffers ----
|
||
|
||
/// <summary>
|
||
/// SceneLighting std140 block. Keeps binding=1 so the existing shader source
|
||
/// and <c>SceneLightingUboBinding</c> layout are untouched; the set index is
|
||
/// what disambiguates it from <see cref="StorageBatches"/> under Vulkan.
|
||
/// </summary>
|
||
public const uint UniformSceneLighting = 1;
|
||
|
||
/// <summary>
|
||
/// Terrain per-layer texture tiling factors — 36 floats.
|
||
///
|
||
/// Added at slice V4d. These live in a <c>uniform float[36]</c> today, which
|
||
/// is 144 bytes: too large for the 96-byte push-constant block (and for
|
||
/// Vulkan's guaranteed 128-byte ceiling), and there is no RHI verb for setting
|
||
/// a uniform array. A small uniform buffer is the Vulkan-legal home. Binding 2
|
||
/// is taken by the terrain clip block, so this is 3.
|
||
/// </summary>
|
||
public const uint UniformTerrainTiling = 3;
|
||
|
||
/// <summary>
|
||
/// Sky per-draw parameters — the sky/model transforms, the keyframe's
|
||
/// ambient/sun colours and sun direction, the UV scroll, and the
|
||
/// per-surface emissive/diffuse/opacity/fog scalars.
|
||
///
|
||
/// Added at slice V6e for the same reason as
|
||
/// <see cref="UniformTerrainTiling"/>: Vulkan GLSL has no default uniform
|
||
/// block, so a loose <c>uniform mat4 uSkyView;</c> is unspellable, and this
|
||
/// set is 256 bytes in std140 — three matrices alone are twice the entire
|
||
/// 96-byte push-constant block. A uniform buffer is the only legal home.
|
||
/// Bindings 1, 2 and 3 are taken by SceneLighting, the terrain clip block
|
||
/// and terrain tiling, so this is 4.
|
||
/// </summary>
|
||
public const uint UniformSkyParams = 4;
|
||
|
||
/// <summary>Set index carrying every uniform buffer.</summary>
|
||
public const uint UniformSet = 1;
|
||
|
||
// ---- set 2: the global texture table ----
|
||
|
||
/// <summary>Set index of the sampled-texture descriptor array (Vulkan) / logical table (GL).</summary>
|
||
public const uint TextureTableSet = 2;
|
||
|
||
/// <summary>Binding of the descriptor array within <see cref="TextureTableSet"/>.</summary>
|
||
public const uint TextureTableBinding = 0;
|
||
|
||
/// <summary>
|
||
/// Upper bound on simultaneously registered textures. Vulkan requires
|
||
/// <c>maxDescriptorSetUpdateAfterBindSampledImages</c> to reach this; the
|
||
/// capability probe asserts it rather than discovering it at draw time.
|
||
/// </summary>
|
||
public const uint TextureTableCapacity = 16384;
|
||
|
||
// ---- push constants ----
|
||
|
||
/// <summary>
|
||
/// Bytes actually written by <see cref="GpuPushConstants"/>. Vulkan guarantees
|
||
/// at least <see cref="MaxPushConstantBytes"/>, so 32 bytes of headroom remain
|
||
/// for later slices; any growth updates this constant and the shader block in
|
||
/// the same commit.
|
||
/// </summary>
|
||
public const int PushConstantBytes = 96;
|
||
|
||
/// <summary>The Vulkan-guaranteed minimum push-constant budget. A hard ceiling for us.</summary>
|
||
public const int MaxPushConstantBytes = 128;
|
||
|
||
// ---- shared layout facts the CPU writers and the shaders must agree on ----
|
||
|
||
/// <summary>
|
||
/// std430 stride of <c>BatchData</c>. The bindless <c>uvec2 textureHandle</c>
|
||
/// becomes <c>uint textureIndex</c> plus one pad word at slice V2, so the
|
||
/// stride is unchanged and every existing CPU writer keeps its offsets.
|
||
/// </summary>
|
||
public const int GpuBatchDataStrideBytes = 16;
|
||
|
||
/// <summary>Clip planes per <c>CellClip</c> slot; also the required <c>gl_ClipDistance</c> size.</summary>
|
||
public const int ClipPlanesPerSlot = 8;
|
||
|
||
/// <summary>std430 stride of one <c>CellClip</c> slot: 16 B header + 8 × vec4.</summary>
|
||
public const int ClipRegionStrideBytes = 16 + (ClipPlanesPerSlot * 16);
|
||
|
||
/// <summary>Lights selected per object by retail's <c>minimize_object_lighting</c>.</summary>
|
||
public const int MaxLightsPerObject = 8;
|
||
}
|