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>
This commit is contained in:
parent
8a7a0837e1
commit
7a0227c12e
44 changed files with 300 additions and 977 deletions
|
|
@ -13,7 +13,6 @@ using AcDream.Core.Terrain;
|
|||
using AcDream.UI.Abstractions.Settings;
|
||||
using DatReaderWriter.DBObjs;
|
||||
using Silk.NET.Input;
|
||||
using Silk.NET.OpenGL;
|
||||
|
||||
namespace AcDream.App.Tests.Composition;
|
||||
|
||||
|
|
@ -293,7 +292,6 @@ public sealed class WorldRenderCompositionTests
|
|||
new ConcurrentDictionary<uint, SurfaceInfo>());
|
||||
|
||||
public WbMeshAdapter CreateMeshAdapter(
|
||||
GL? gl,
|
||||
IGpuDevice device,
|
||||
IDatReaderWriter dats,
|
||||
IPreparedAssetSource preparedAssets,
|
||||
|
|
|
|||
|
|
@ -36,8 +36,10 @@ public sealed class GpuContractTests
|
|||
[Fact]
|
||||
public void StorageBindingsMatchTheShaderSources()
|
||||
{
|
||||
// mesh_modern.vert declares std430 bindings 0..8 in exactly this order;
|
||||
// binding 9 is the GL-only texture handle table added by slice V2.
|
||||
// mesh_modern.vert declares std430 bindings 0..8 in exactly this order.
|
||||
// Binding 9 was the GL-only texture handle table added by slice V2;
|
||||
// Campaign V slice V11 deleted it (StorageTextureTable) along with the
|
||||
// rest of the raw-GL arm, so 9 is now one past the highest binding.
|
||||
Assert.Equal(0u, GpuBindingModel.StorageInstances);
|
||||
Assert.Equal(1u, GpuBindingModel.StorageBatches);
|
||||
Assert.Equal(2u, GpuBindingModel.StorageClipRegions);
|
||||
|
|
@ -47,8 +49,7 @@ public sealed class GpuContractTests
|
|||
Assert.Equal(6u, GpuBindingModel.StorageInstanceIndoor);
|
||||
Assert.Equal(7u, GpuBindingModel.StorageInstanceAlpha);
|
||||
Assert.Equal(8u, GpuBindingModel.StorageInstanceSelectionLighting);
|
||||
Assert.Equal(9u, GpuBindingModel.StorageTextureTable);
|
||||
Assert.Equal(10u, GpuBindingModel.StorageBindingCount);
|
||||
Assert.Equal(9u, GpuBindingModel.StorageBindingCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -219,11 +219,10 @@ public sealed class VulkanCapabilityGateTests
|
|||
Assert.False(VulkanPipelineLayouts.IsDynamicStorageBinding(GpuBindingModel.StorageGlobalLights));
|
||||
Assert.False(VulkanPipelineLayouts.IsDynamicStorageBinding(GpuBindingModel.StorageClipRegions));
|
||||
|
||||
// Binding 9 is the GL-only uvec2 handle-table emulation. The Vulkan
|
||||
// backend binds set 2 instead and never touches it, so spending a scarce
|
||||
// dynamic descriptor on it would be spending one on a binding that is
|
||||
// provably never bound.
|
||||
Assert.False(VulkanPipelineLayouts.IsDynamicStorageBinding(GpuBindingModel.StorageTextureTable));
|
||||
// Binding 9 (the GL-only uvec2 handle-table emulation, StorageTextureTable)
|
||||
// is deleted as of Campaign V slice V11 — the Vulkan backend always bound
|
||||
// set 2 instead and never touched it, so there is no longer a ninth
|
||||
// binding to assert never spends a scarce dynamic descriptor.
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -20,8 +20,11 @@ namespace AcDream.App.Tests.Rendering.Gpu.Vk;
|
|||
/// backend silently keeps rendering the old one. This test is what turns that
|
||||
/// into a red build.</para>
|
||||
///
|
||||
/// <para>It also pins which production shaders are Vulkan-expressible TODAY. Nine
|
||||
/// of the ten pairs are not, and each failure is a specific source-level fact
|
||||
/// <para>It also pins which production shaders are Vulkan-expressible TODAY. As
|
||||
/// of Campaign V slice V11 (which deleted the one pair that never was —
|
||||
/// <c>mesh.vert</c>/<c>mesh.frag</c>, the pre-modern-pipeline shader the N.5 ship
|
||||
/// amendment's mandatory modern path made unreachable) every remaining pair
|
||||
/// compiles. A future non-ready pair's failure is a specific source-level fact
|
||||
/// belonging to a renderer-port slice that has not landed — not a toolchain gap.
|
||||
/// Recording them here means the next slice inherits an inventory rather than a
|
||||
/// rediscovery.</para>
|
||||
|
|
|
|||
|
|
@ -50,15 +50,17 @@ public sealed class ParticleBindlessInstanceTests
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Campaign V slice V6e: "this particle has no texture" is now a reserved
|
||||
/// index rather than a null handle, and that value is written in three
|
||||
/// places — the CPU that produces it, the GL preamble that tests it, and the
|
||||
/// Vulkan preamble that will. Three copies of a magic number is a drift
|
||||
/// waiting to happen, and its failure mode is silent: a particle would
|
||||
/// sample slot 0xFFFFFFFF instead of drawing the procedural blob.
|
||||
/// Campaign V slice V6e: "this particle has no texture" is a reserved index
|
||||
/// rather than a null handle, and that value is written in two places — the
|
||||
/// CPU that produces it and the Vulkan preamble that tests it in the shader.
|
||||
/// Before Campaign V slice V11 deleted the GL arm there was a third copy in
|
||||
/// common.glsl, which this test also cross-checked; two copies of a magic
|
||||
/// number is still a drift waiting to happen, and its failure mode is
|
||||
/// silent: a particle would sample slot 0xFFFFFFFF instead of drawing the
|
||||
/// procedural blob.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void TheReservedNoTextureSlotAgreesAcrossCpuAndBothDialects()
|
||||
public void TheReservedNoTextureSlotAgreesBetweenCpuAndTheVulkanPreamble()
|
||||
{
|
||||
const string literal = "0xFFFFFFFF";
|
||||
|
||||
|
|
@ -67,13 +69,9 @@ public sealed class ParticleBindlessInstanceTests
|
|||
?.GetRawConstantValue();
|
||||
Assert.Equal(0xFFFFFFFFu, Assert.IsType<uint>(cpuValue));
|
||||
|
||||
string common = File.ReadAllText(Path.Combine(
|
||||
AppContext.BaseDirectory, "Rendering", "Shaders", "common.glsl"));
|
||||
Assert.Contains($"#define ACDREAM_TEXTURE_NONE {literal}u", common);
|
||||
|
||||
// The Vulkan half is injected by the offline compiler, not by
|
||||
// common.glsl, so it is a separate declaration that has to say the same
|
||||
// thing.
|
||||
// The Vulkan half is injected by the offline compiler at compile time,
|
||||
// not carried in a shared GLSL source, so it is a separate declaration
|
||||
// that has to say the same thing.
|
||||
string preamble = File.ReadAllText(Path.Combine(
|
||||
RepositoryRoot(), "tools", "ShaderCompiler", "VulkanGlslPreamble.cs"));
|
||||
Assert.Contains($"#define ACDREAM_TEXTURE_NONE {literal}u", preamble);
|
||||
|
|
|
|||
|
|
@ -79,21 +79,15 @@ public sealed class RenderFrameResourceControllerTests
|
|||
"_particles?.BeginFrame(gpuSlot);");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Production_clear_phase_preserves_atmosphere_and_gl_state_order()
|
||||
{
|
||||
string source = ResourceSource();
|
||||
|
||||
AssertAppearsInOrder(
|
||||
source,
|
||||
"bool portalViewportVisible = _portal.IsPortalViewportVisible;",
|
||||
"_particleVisibility.Reset();",
|
||||
"SkyKeyframe sky = _worldTime.CurrentSky;",
|
||||
"AtmosphereSnapshot atmosphere = _weather.Snapshot(in sky);",
|
||||
"_frameGlState.RestoreFrameDefaults();",
|
||||
"_gl.Clear(",
|
||||
"_diagnostics.EmitGlStateTripwireIfChanged(");
|
||||
}
|
||||
// Campaign V slice V11 deleted RuntimeRenderFrameClearPhase (the raw-GL
|
||||
// IRenderFrameClearPhase implementation this test pinned): its whole
|
||||
// subject — the frame-global GL state restore, glClear, and GL-state
|
||||
// tripwire, in that order — no longer exists anywhere. The ordering it
|
||||
// shared with the surviving Vulkan implementation (portal check →
|
||||
// particle reset → sky → atmosphere) has no GL-specific steps left to
|
||||
// pin, since VulkanRenderFrameClearPhase (VulkanCompositionFramePhases.cs)
|
||||
// hands the clear colour to a pass load-op instead of restoring ambient
|
||||
// state and issuing glClear.
|
||||
|
||||
[Fact]
|
||||
public void Weather_frame_clock_advances_only_after_the_weather_tick()
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ using System.Threading;
|
|||
using AcDream.Content;
|
||||
using Chorizite.Core.Render.Enums;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Silk.NET.OpenGL;
|
||||
|
||||
namespace AcDream.App.Tests.Rendering.Wb;
|
||||
|
||||
|
|
@ -16,17 +15,18 @@ namespace AcDream.App.Tests.Rendering.Wb;
|
|||
///
|
||||
/// <para>Plan §5.5.10 recorded the blocker as a fact about types — "WbMeshAdapter
|
||||
/// owns an OpenGLGraphicsDevice, so it is not constructible on Vulkan" — which is
|
||||
/// why <c>NullWbMeshAdapter</c> exists. §5.5.12 item 6 measured how wide the
|
||||
/// dependency really is: a GL context, the retirement queue, the instance VBO,
|
||||
/// why <c>NullWbMeshAdapter</c> existed. §5.5.12 item 6 measured how wide the
|
||||
/// dependency really was: a GL context, the retirement queue, the instance VBO,
|
||||
/// and two capability flags. This suite proves the interface at that surface is
|
||||
/// load-bearing rather than cosmetic, by building the object graph against a
|
||||
/// device that has NO GL context at all.</para>
|
||||
///
|
||||
/// <para>It deliberately proves construction and nothing more. The upload bodies
|
||||
/// are still raw GL and the world renderers still bind a GL handle table; both
|
||||
/// belong to the slice that draws Dereth on Vulkan. What matters here is that
|
||||
/// each of those now fails at the site that needs GL, naming why, instead of
|
||||
/// throwing a cast before the constructor has run a statement.</para>
|
||||
/// <para>It originally proved construction and nothing more, back when the
|
||||
/// upload bodies were still raw GL and the world renderers still bound a GL
|
||||
/// handle table. Campaign V slice V11 deleted both along with the rest of the
|
||||
/// raw-GL arm (and the interface's own <c>Gl</c> member, which nothing read any
|
||||
/// more once they were gone) — the arena-build and upload tests below now cover
|
||||
/// what those slices only asserted would eventually fail loudly.</para>
|
||||
/// </summary>
|
||||
public sealed class MeshPipelineDeviceSeamTests
|
||||
{
|
||||
|
|
@ -36,8 +36,6 @@ public sealed class MeshPipelineDeviceSeamTests
|
|||
bool modernPath = false)
|
||||
: IMeshPipelineDevice
|
||||
{
|
||||
public GL? Gl => null;
|
||||
|
||||
public IGpuResourceRetirementQueue ResourceRetirement { get; } = retirement;
|
||||
|
||||
public uint InstanceVBO => 0;
|
||||
|
|
@ -120,8 +118,9 @@ public sealed class MeshPipelineDeviceSeamTests
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// The seam's whole value is that it is NARROW — seven members measured out
|
||||
/// of a 760-line class. A later slice that quietly widens it back out would
|
||||
/// The seam's whole value is that it is NARROW — six members measured out
|
||||
/// of a 760-line class (seven until Campaign V slice V11 deleted the unread
|
||||
/// <c>Gl</c> member). A later slice that quietly widens it back out would
|
||||
/// re-couple the mesh pipeline to a backend without any other gate noticing,
|
||||
/// so the member set is pinned rather than described.
|
||||
/// </summary>
|
||||
|
|
@ -143,7 +142,6 @@ public sealed class MeshPipelineDeviceSeamTests
|
|||
|
||||
Assert.Equal(
|
||||
[
|
||||
"Gl",
|
||||
"HasBindless",
|
||||
"HasOpenGL43",
|
||||
"HasPendingWork",
|
||||
|
|
@ -244,7 +242,6 @@ public sealed class MeshPipelineDeviceSeamTests
|
|||
using var vulkanDevice =
|
||||
new AcDream.App.Rendering.Gpu.Vk.VulkanMeshPipelineDevice(device.Retirement);
|
||||
|
||||
Assert.Null(vulkanDevice.Gl);
|
||||
Assert.True(vulkanDevice.HasBindless);
|
||||
Assert.True(vulkanDevice.HasOpenGL43);
|
||||
Assert.False(vulkanDevice.HasPendingWork);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using AcDream.App.Rendering.Wb;
|
||||
using AcDream.Content;
|
||||
using Chorizite.Core.Render.Enums;
|
||||
using Silk.NET.OpenGL;
|
||||
|
||||
namespace AcDream.App.Tests.Rendering.Wb;
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ public sealed class TextureAtlasCapacityTests
|
|||
public void DirectUploadAcceptsExactRgbaPayload()
|
||||
{
|
||||
RhiWorldTextureArray.ValidateUploadPayload(
|
||||
TextureFormat.RGBA8, 2, 2, 16, PixelFormat.Rgba, PixelType.UnsignedByte);
|
||||
TextureFormat.RGBA8, 2, 2, 16, UploadPixelFormat.Rgba, UploadPixelType.UnsignedByte);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -43,7 +43,7 @@ public sealed class TextureAtlasCapacityTests
|
|||
{
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
RhiWorldTextureArray.ValidateUploadPayload(
|
||||
TextureFormat.RGBA8, 2, 2, bytes, PixelFormat.Rgba, PixelType.UnsignedByte));
|
||||
TextureFormat.RGBA8, 2, 2, bytes, UploadPixelFormat.Rgba, UploadPixelType.UnsignedByte));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -51,10 +51,10 @@ public sealed class TextureAtlasCapacityTests
|
|||
{
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
RhiWorldTextureArray.ValidateUploadPayload(
|
||||
TextureFormat.RGBA8, 2, 2, 16, PixelFormat.Rgb, PixelType.UnsignedByte));
|
||||
TextureFormat.RGBA8, 2, 2, 16, UploadPixelFormat.Rgb, UploadPixelType.UnsignedByte));
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
RhiWorldTextureArray.ValidateUploadPayload(
|
||||
TextureFormat.RGBA8, 2, 2, 16, PixelFormat.Rgba, PixelType.Float));
|
||||
TextureFormat.RGBA8, 2, 2, 16, UploadPixelFormat.Rgba, UploadPixelType.Float));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -63,7 +63,7 @@ public sealed class TextureAtlasCapacityTests
|
|||
int bytes = RhiWorldTextureArray.CalculateExpectedDataSize(TextureFormat.DXT1, 4, 4);
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
RhiWorldTextureArray.ValidateUploadPayload(
|
||||
TextureFormat.DXT1, 4, 4, bytes, PixelFormat.Rgba, PixelType.UnsignedByte));
|
||||
TextureFormat.DXT1, 4, 4, bytes, UploadPixelFormat.Rgba, UploadPixelType.UnsignedByte));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -71,6 +71,6 @@ public sealed class TextureAtlasCapacityTests
|
|||
{
|
||||
Assert.Equal(18, RhiWorldTextureArray.CalculateExpectedDataSize(TextureFormat.RGB8, 3, 2));
|
||||
RhiWorldTextureArray.ValidateUploadPayload(
|
||||
TextureFormat.RGB8, 3, 2, 18, PixelFormat.Rgb, PixelType.UnsignedByte);
|
||||
TextureFormat.RGB8, 3, 2, 18, UploadPixelFormat.Rgb, UploadPixelType.UnsignedByte);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,29 +99,12 @@ public sealed class WorldRenderDiagnosticsTests
|
|||
field => typeof(Delegate).IsAssignableFrom(field.FieldType));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SilkGlReader_ConsumesEnteringErrorBeforeStateQueries()
|
||||
{
|
||||
string source = File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
"src",
|
||||
"AcDream.App",
|
||||
"Rendering",
|
||||
"WorldRenderDiagnostics.cs"));
|
||||
|
||||
int captureStart = source.IndexOf(
|
||||
"public RenderGlStateSnapshot CaptureState()",
|
||||
StringComparison.Ordinal);
|
||||
int error = source.IndexOf("_gl.GetError()", captureStart, StringComparison.Ordinal);
|
||||
int depth = source.IndexOf(
|
||||
"_gl.IsEnabled(EnableCap.DepthTest)",
|
||||
captureStart,
|
||||
StringComparison.Ordinal);
|
||||
|
||||
Assert.True(captureStart >= 0);
|
||||
Assert.True(error > captureStart);
|
||||
Assert.True(depth > error);
|
||||
}
|
||||
// Campaign V slice V11 deleted SilkRenderGlStateReader, the raw-GL
|
||||
// IRenderGlStateReader implementation this test pinned (it was never
|
||||
// constructed in production — NullRenderGlStateReader.Instance is the
|
||||
// sole surviving implementer), so the "consume the entering GL error
|
||||
// before other state reads" source-order tripwire it protected has
|
||||
// nothing left to pin.
|
||||
|
||||
[Fact]
|
||||
public void TerrainDiagnostics_RetryFailedPublicationWithoutLosingSamples()
|
||||
|
|
@ -276,17 +259,4 @@ public sealed class WorldRenderDiagnosticsTests
|
|||
exteriorPartition: null,
|
||||
cameraPosition: Vector3.Zero,
|
||||
playerPosition: Vector3.Zero);
|
||||
|
||||
private static string FindRepoRoot()
|
||||
{
|
||||
DirectoryInfo? directory = new(AppContext.BaseDirectory);
|
||||
while (directory is not null)
|
||||
{
|
||||
if (File.Exists(Path.Combine(directory.FullName, "AcDream.slnx")))
|
||||
return directory.FullName;
|
||||
directory = directory.Parent;
|
||||
}
|
||||
|
||||
throw new DirectoryNotFoundException("Could not find AcDream.slnx.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,8 +134,9 @@ public sealed class WbDrawDispatcherIndirectBuilderTests
|
|||
//
|
||||
// Campaign V slice V2 (2026-07-27): TextureHandle (ulong, an
|
||||
// ARB_bindless_texture handle) became TextureIndex (uint) plus an
|
||||
// explicit Reserved pad word — a slot into the binding=9 handle table
|
||||
// (GpuBindingModel.StorageTextureTable) instead of the raw handle.
|
||||
// explicit Reserved pad word — a slot into the GL-only binding=9 handle
|
||||
// table instead of the raw handle (that binding, GpuBindingModel's
|
||||
// former StorageTextureTable, was deleted at Campaign V slice V11).
|
||||
// The struct stays 16 bytes and TextureLayer/Flags keep their offsets
|
||||
// (8/12), matching GpuBindingModel.GpuBatchDataStrideBytes and every
|
||||
// existing CPU writer, so both structs only need 4-byte packing now.
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
using System;
|
||||
using AcDream.App.Rendering.Wb;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Silk.NET.OpenGL;
|
||||
|
||||
namespace AcDream.Core.Tests.Rendering.Wb;
|
||||
|
||||
public sealed class WbMeshAdapterTests
|
||||
{
|
||||
[Fact]
|
||||
public void Construct_WithNullGl_ThrowsArgumentNull()
|
||||
public void Construct_WithNullGpuDevice_ThrowsArgumentNull()
|
||||
{
|
||||
// GL is the first guarded parameter; verifies the constructor validates inputs.
|
||||
// We can't pass a real GL (no context in tests), so we verify only the
|
||||
// null-GL guard. The real pipeline is tested via integration.
|
||||
// gpuDevice is the first guarded parameter (Campaign V slice V11 deleted
|
||||
// the GL? gl parameter this test used to pass null through — the
|
||||
// constructor never null-checked it; this assertion was always really
|
||||
// exercising gpuDevice's guard). The real pipeline is tested via
|
||||
// integration.
|
||||
Assert.Throws<ArgumentNullException>(() =>
|
||||
new WbMeshAdapter(
|
||||
gl: null!,
|
||||
gpuDevice: null!,
|
||||
dats: null!,
|
||||
logger: NullLogger<WbMeshAdapter>.Instance));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue