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>
This commit is contained in:
parent
b70b9832ff
commit
8a7a0837e1
121 changed files with 1243 additions and 19840 deletions
|
|
@ -28,7 +28,17 @@ namespace AcDream.App.Rendering.Wb
|
|||
/// </summary>
|
||||
public class ObjectRenderData
|
||||
{
|
||||
/// <summary>
|
||||
/// Campaign V slice V11 deleted the per-mesh raw-GL vertex array/buffer
|
||||
/// this used to carry — Vulkan bakes vertex input into the pipeline and
|
||||
/// the shared <see cref="GlobalMeshBuffer"/> arena has no VAO/VBO
|
||||
/// concept at all (see <see cref="GlobalMeshBuffer.VertexStore"/>). This
|
||||
/// is always 0 now; it survives only because
|
||||
/// <c>WbDrawDispatcher.cs</c>'s legacy (non-RHI) dispatcher still reads
|
||||
/// it into its own dead <c>anyVao</c> bookkeeping.
|
||||
/// </summary>
|
||||
public uint VAO { get; set; }
|
||||
/// <summary>See <see cref="VAO"/> — always 0 for the same reason.</summary>
|
||||
public uint VBO { get; set; }
|
||||
public int VertexCount { get; set; }
|
||||
public List<ObjectRenderBatch> Batches { get; set; } = new();
|
||||
|
|
@ -76,6 +86,11 @@ namespace AcDream.App.Rendering.Wb
|
|||
/// </summary>
|
||||
public class ObjectRenderBatch
|
||||
{
|
||||
/// <summary>See <see cref="ObjectRenderData.VAO"/> — Campaign V slice
|
||||
/// V11 deleted the legacy per-batch raw-GL index buffer this used to
|
||||
/// carry. Always 0 now; every batch's actual index range lives in the
|
||||
/// shared arena via <see cref="FirstIndex"/>/<see cref="BaseVertex"/>.
|
||||
/// </summary>
|
||||
public uint IBO { get; set; }
|
||||
public int IndexCount { get; set; }
|
||||
public TextureAtlasManager Atlas { get; set; } = null!;
|
||||
|
|
@ -124,26 +139,6 @@ namespace AcDream.App.Rendering.Wb
|
|||
/// </summary>
|
||||
private readonly IMeshPipelineDevice _graphicsDevice;
|
||||
|
||||
/// <summary>
|
||||
/// The GL context the LEGACY (pre-modern-path) upload bodies write
|
||||
/// through.
|
||||
///
|
||||
/// <para>Campaign V slice V6i-3 narrowed what still needs it. The modern
|
||||
/// path's arena upload is <see cref="GlobalMeshBuffer"/>'s, and that is
|
||||
/// now <see cref="AcDream.App.Rendering.Gpu.IGpuBuffer"/> work on both
|
||||
/// arms; what remains raw is the per-mesh VAO/VBO/IBO construction the
|
||||
/// N.5 ship amendment made unreachable — missing bindless or
|
||||
/// draw-parameters throws at startup, so <c>_useModernRendering</c> is
|
||||
/// true in every shipping configuration. The accessor therefore survives
|
||||
/// as the guard on genuinely dead code rather than as a blocker, and it
|
||||
/// is deleted with that code.</para>
|
||||
/// </summary>
|
||||
private GL RequireGl() =>
|
||||
_graphicsDevice.Gl
|
||||
?? throw new InvalidOperationException(
|
||||
"The mesh pipeline's legacy per-mesh vertex-array upload is raw GL and this "
|
||||
+ "device has no context. The modern path is mandatory (N.5 ship amendment), "
|
||||
+ "so reaching this is a composition error rather than a backend gap.");
|
||||
private readonly IPreparedAssetSource _preparedAssets;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
|
|
@ -158,20 +153,6 @@ namespace AcDream.App.Rendering.Wb
|
|||
/// </summary>
|
||||
private readonly AcDream.App.Rendering.Gpu.IGpuDevice _gpuDevice;
|
||||
|
||||
/// <summary>
|
||||
/// Campaign V slice V6i-2: the downcast moved here from the constructor.
|
||||
/// Only the raw-GL world renderers reach this — the Vulkan backend binds
|
||||
/// set 2 and never touches the handle table — so a Vulkan-composed mesh
|
||||
/// pipeline can now be CONSTRUCTED, and only a caller that genuinely
|
||||
/// needs a GL handle table fails, naming why.
|
||||
/// </summary>
|
||||
internal AcDream.App.Rendering.Gpu.Gl.GlGpuDevice WorldTextureTable =>
|
||||
_gpuDevice as AcDream.App.Rendering.Gpu.Gl.GlGpuDevice
|
||||
?? throw new InvalidOperationException(
|
||||
"The GL bindless handle table was requested from a mesh pipeline composed against "
|
||||
+ $"the {_gpuDevice.Backend} backend. It is GL-only emulation of the Vulkan texture "
|
||||
+ "table and is deleted with the raw-GL world path.");
|
||||
|
||||
/// <summary>
|
||||
/// Campaign V slice V6i-2: how a shared atlas's physical array is made.
|
||||
/// Composed once; see <see cref="IWorldTextureArrayFactory"/>.
|
||||
|
|
@ -339,7 +320,6 @@ namespace AcDream.App.Rendering.Wb
|
|||
}
|
||||
|
||||
public GlobalMeshBuffer? GlobalBuffer { get; }
|
||||
private readonly bool _useModernRendering;
|
||||
internal (int RenderData, int AtlasArrays, int UnusedLru, long EstimatedBytes) Diagnostics
|
||||
{
|
||||
get
|
||||
|
|
@ -527,11 +507,16 @@ namespace AcDream.App.Rendering.Wb
|
|||
_stagedMeshData = new MeshUploadStagingQueue(
|
||||
budgets.MeshStagingEntries,
|
||||
budgets.MeshStagingBytes);
|
||||
_useModernRendering = _graphicsDevice.HasOpenGL43 && _graphicsDevice.HasBindless;
|
||||
if (_useModernRendering)
|
||||
// The modern path is mandatory (N.5 ship amendment) and Campaign V
|
||||
// slice V11 deleted the only other backend, so a production
|
||||
// IMeshPipelineDevice always reports both flags true. The gate
|
||||
// survives because AcDream.App.Tests.Rendering.Wb.
|
||||
// MeshPipelineDeviceSeamTests exercises a device that reports
|
||||
// neither, to prove the arena is genuinely optional rather than
|
||||
// dereferenced unconditionally.
|
||||
if (_graphicsDevice.HasOpenGL43 && _graphicsDevice.HasBindless)
|
||||
{
|
||||
GlobalBuffer = new GlobalMeshBuffer(
|
||||
_graphicsDevice.Gl,
|
||||
gpuDevice,
|
||||
_graphicsDevice.ResourceRetirement);
|
||||
}
|
||||
|
|
@ -680,7 +665,7 @@ namespace AcDream.App.Rendering.Wb
|
|||
|
||||
/// <summary>
|
||||
/// #105 diagnostic: counts staged-but-unflushed texture layer updates across all
|
||||
/// shared atlases (see <see cref="ManagedGLTextureArray.PendingUpdateCount"/>).
|
||||
/// shared atlases (see <see cref="IWorldTextureArray.PendingUpdateCount"/>).
|
||||
/// Render thread only — <c>_globalAtlases</c> is render-thread-owned.
|
||||
/// </summary>
|
||||
public (int PendingUpdates, int ArraysWithPending, int TotalArrays) GetPendingTextureUpdateStats()
|
||||
|
|
@ -901,7 +886,7 @@ namespace AcDream.App.Rendering.Wb
|
|||
|
||||
private long GetReclaimableBytes(ObjectRenderData data)
|
||||
{
|
||||
if (_useModernRendering && data.GlobalAllocation is { } allocation)
|
||||
if (data.GlobalAllocation is { } allocation)
|
||||
{
|
||||
return checked(
|
||||
(long)allocation.Vertices.Length * VertexPositionNormalTexture.Size
|
||||
|
|
@ -1989,16 +1974,10 @@ namespace AcDream.App.Rendering.Wb
|
|||
|
||||
#region Private: GPU Upload
|
||||
|
||||
private unsafe ObjectRenderData? UploadGfxObjMeshData(ObjectMeshData meshData)
|
||||
private ObjectRenderData? UploadGfxObjMeshData(ObjectMeshData meshData)
|
||||
{
|
||||
if (meshData.Vertices.Length == 0) return null;
|
||||
|
||||
// Resolved lazily since Campaign V slice V6i-3: every reader below
|
||||
// is inside a !_useModernRendering branch, and the modern path is
|
||||
// mandatory, so a backend with no GL context uploads meshes here
|
||||
// without ever asking for one.
|
||||
GL? gl = _graphicsDevice.Gl;
|
||||
uint vao = 0, vbo = 0;
|
||||
var modernIndexBatches = meshData.TextureBatches.Values
|
||||
.SelectMany(batches => batches)
|
||||
.Where(batch => batch.Indices.Count != 0)
|
||||
|
|
@ -2007,62 +1986,23 @@ namespace AcDream.App.Rendering.Wb
|
|||
GlobalMeshAllocation? globalAllocation = null;
|
||||
var renderBatches = new List<ObjectRenderBatch>();
|
||||
var acquiredTextures = new List<(TextureAtlasManager Atlas, TextureKey Key)>();
|
||||
var legacyIndexBuffers = new List<(uint Name, int Bytes)>();
|
||||
|
||||
try
|
||||
{
|
||||
if (_useModernRendering)
|
||||
{
|
||||
// One mesh owns one vertex range and one contiguous index
|
||||
// range. The former append path duplicated the full vertex
|
||||
// array per material and never reclaimed evicted ranges.
|
||||
vao = GlobalBuffer!.VAO;
|
||||
vbo = GlobalBuffer!.VBO;
|
||||
}
|
||||
else
|
||||
{
|
||||
GL legacyGl = RequireGl();
|
||||
legacyGl.GenVertexArrays(1, out vao);
|
||||
legacyGl.BindVertexArray(vao);
|
||||
|
||||
legacyGl.GenBuffers(1, out vbo);
|
||||
legacyGl.BindBuffer(GLEnum.ArrayBuffer, vbo);
|
||||
fixed (VertexPositionNormalTexture* ptr = meshData.Vertices)
|
||||
{
|
||||
legacyGl.BufferData(GLEnum.ArrayBuffer, (nuint)(meshData.Vertices.Length * VertexPositionNormalTexture.Size), ptr, GLEnum.StaticDraw);
|
||||
}
|
||||
GpuMemoryTracker.TrackAllocation(meshData.Vertices.Length * VertexPositionNormalTexture.Size, GpuResourceType.Buffer);
|
||||
|
||||
int stride = VertexPositionNormalTexture.Size;
|
||||
// Position (location 0)
|
||||
legacyGl.EnableVertexAttribArray(0);
|
||||
legacyGl.VertexAttribPointer(0, 3, GLEnum.Float, false, (uint)stride, (void*)0);
|
||||
// Normal (location 1)
|
||||
legacyGl.EnableVertexAttribArray(1);
|
||||
legacyGl.VertexAttribPointer(1, 3, GLEnum.Float, false, (uint)stride, (void*)(3 * sizeof(float)));
|
||||
// TexCoord (location 2)
|
||||
legacyGl.EnableVertexAttribArray(2);
|
||||
legacyGl.VertexAttribPointer(2, 2, GLEnum.Float, false, (uint)stride, (void*)(6 * sizeof(float)));
|
||||
|
||||
// Instance data (shared VBO)
|
||||
legacyGl.BindBuffer(GLEnum.ArrayBuffer, _graphicsDevice.InstanceVBO);
|
||||
for (uint i = 0; i < 4; i++)
|
||||
{
|
||||
var loc = 3 + i;
|
||||
legacyGl.EnableVertexAttribArray(loc);
|
||||
legacyGl.VertexAttribPointer(loc, 4, GLEnum.Float, false, (uint)sizeof(InstanceData), (void*)(i * 16));
|
||||
legacyGl.VertexAttribDivisor(loc, 1);
|
||||
}
|
||||
legacyGl.EnableVertexAttribArray(8);
|
||||
legacyGl.VertexAttribIPointer(8, 1, GLEnum.UnsignedInt, (uint)sizeof(InstanceData), (void*)64);
|
||||
legacyGl.VertexAttribDivisor(8, 1);
|
||||
}
|
||||
|
||||
// Allocate the shared vertex/index range before acquiring texture
|
||||
// references. A buffer-growth failure therefore leaves every atlas
|
||||
// untouched; later failures still roll this allocation back below.
|
||||
if (_useModernRendering && modernIndexBatches.Length != 0)
|
||||
globalAllocation = GlobalBuffer!.UploadMesh(meshData.Vertices, modernIndexBatches);
|
||||
//
|
||||
// GlobalBuffer is null only for a test double that reports no
|
||||
// modern-path capability (MeshPipelineDeviceSeamTests); every
|
||||
// production IMeshPipelineDevice is Vulkan-backed and reports both
|
||||
// flags true (N.5 ship amendment; Campaign V slice V11 deleted the
|
||||
// only other backend). There is no longer a per-mesh vertex array
|
||||
// or vertex/index buffer to build here — Vulkan bakes vertex input
|
||||
// into the pipeline, and the shared arena's stores are bound once
|
||||
// per pass (see WbDrawDispatcher.Rhi.cs's BindPipelineWithMesh).
|
||||
if (GlobalBuffer is not null && modernIndexBatches.Length != 0)
|
||||
globalAllocation = GlobalBuffer.UploadMesh(meshData.Vertices, modernIndexBatches);
|
||||
|
||||
foreach (var (format, batches) in meshData.TextureBatches)
|
||||
{
|
||||
|
|
@ -2070,7 +2010,6 @@ namespace AcDream.App.Rendering.Wb
|
|||
{
|
||||
if (batch.Indices.Count == 0) continue;
|
||||
|
||||
uint ibo = 0;
|
||||
TextureAtlasManager? atlasManager = null;
|
||||
int textureIndex = 0;
|
||||
uint firstIndex = 0;
|
||||
|
|
@ -2128,24 +2067,6 @@ namespace AcDream.App.Rendering.Wb
|
|||
if (uploadsNewLayer)
|
||||
_dirtyAtlases.Add(atlasManager);
|
||||
|
||||
if (_useModernRendering)
|
||||
{
|
||||
ibo = GlobalBuffer!.IBO;
|
||||
}
|
||||
else
|
||||
{
|
||||
GL legacyGl = RequireGl();
|
||||
legacyGl.GenBuffers(1, out ibo);
|
||||
legacyGl.BindBuffer(GLEnum.ElementArrayBuffer, ibo);
|
||||
var indexArray = batch.Indices.ToArray();
|
||||
fixed (ushort* iptr = indexArray)
|
||||
{
|
||||
legacyGl.BufferData(GLEnum.ElementArrayBuffer, (nuint)(indexArray.Length * sizeof(ushort)), iptr, GLEnum.StaticDraw);
|
||||
}
|
||||
GpuMemoryTracker.TrackAllocation(indexArray.Length * sizeof(ushort), GpuResourceType.Buffer);
|
||||
legacyIndexBuffers.Add((ibo, indexArray.Length * sizeof(ushort)));
|
||||
}
|
||||
|
||||
// Campaign V slice V4t interned the atlas's resident
|
||||
// handle into the device's one texture table here and
|
||||
// carried the slot. Slice V6i-2 asks the array for the
|
||||
|
|
@ -2159,7 +2080,6 @@ namespace AcDream.App.Rendering.Wb
|
|||
|
||||
renderBatches.Add(new ObjectRenderBatch
|
||||
{
|
||||
IBO = ibo,
|
||||
IndexCount = batch.Indices.Count,
|
||||
Atlas = atlasManager!,
|
||||
TextureIndex = textureIndex,
|
||||
|
|
@ -2178,7 +2098,7 @@ namespace AcDream.App.Rendering.Wb
|
|||
}
|
||||
}
|
||||
|
||||
if (_useModernRendering && globalAllocation is not null)
|
||||
if (globalAllocation is not null)
|
||||
{
|
||||
if (renderBatches.Count != globalAllocation.BatchFirstIndices.Count)
|
||||
{
|
||||
|
|
@ -2197,8 +2117,6 @@ namespace AcDream.App.Rendering.Wb
|
|||
+ renderBatches.Sum(b => (long)b.IndexCount * sizeof(ushort)));
|
||||
var renderData = new ObjectRenderData
|
||||
{
|
||||
VAO = vao,
|
||||
VBO = vbo,
|
||||
VertexCount = meshData.Vertices.Length,
|
||||
Batches = renderBatches,
|
||||
GlobalAllocation = globalAllocation,
|
||||
|
|
@ -2209,26 +2127,17 @@ namespace AcDream.App.Rendering.Wb
|
|||
CPUEdgeLines = meshData.EdgeLines,
|
||||
MemorySize = geometryBytes,
|
||||
NonArenaGpuBytes = CalculateNonArenaGeometryBytes(
|
||||
_useModernRendering,
|
||||
GlobalBuffer is not null,
|
||||
geometryBytes),
|
||||
};
|
||||
|
||||
if (!_useModernRendering)
|
||||
{
|
||||
RequireGl().BindVertexArray(0);
|
||||
}
|
||||
return renderData;
|
||||
}
|
||||
catch (Exception uploadFailure)
|
||||
{
|
||||
RetryableResourceReleaseLedger rollback = CreateUploadRollback(
|
||||
meshData,
|
||||
gl,
|
||||
vao,
|
||||
vbo,
|
||||
globalAllocation,
|
||||
acquiredTextures,
|
||||
legacyIndexBuffers);
|
||||
acquiredTextures);
|
||||
ResourceReleaseAttempt attempt = rollback.Advance();
|
||||
if (!rollback.IsComplete)
|
||||
{
|
||||
|
|
@ -2248,13 +2157,8 @@ namespace AcDream.App.Rendering.Wb
|
|||
}
|
||||
|
||||
private RetryableResourceReleaseLedger CreateUploadRollback(
|
||||
ObjectMeshData meshData,
|
||||
GL? gl,
|
||||
uint vao,
|
||||
uint vbo,
|
||||
GlobalMeshAllocation? globalAllocation,
|
||||
IReadOnlyList<(TextureAtlasManager Atlas, TextureKey Key)> acquiredTextures,
|
||||
IReadOnlyList<(uint Name, int Bytes)> legacyIndexBuffers)
|
||||
IReadOnlyList<(TextureAtlasManager Atlas, TextureKey Key)> acquiredTextures)
|
||||
{
|
||||
var releases = new List<(string Name, Action Release)>();
|
||||
|
||||
|
|
@ -2282,35 +2186,6 @@ namespace AcDream.App.Rendering.Wb
|
|||
acquiredTextures[releaseIndex].Key)));
|
||||
}
|
||||
|
||||
if (!_useModernRendering)
|
||||
{
|
||||
GL legacyGl = gl ?? RequireGl();
|
||||
for (int i = 0; i < legacyIndexBuffers.Count; i++)
|
||||
{
|
||||
int bufferIndex = i;
|
||||
releases.Add((
|
||||
$"legacy-index-buffer-{bufferIndex}-delete",
|
||||
() => legacyGl.DeleteBuffer(legacyIndexBuffers[bufferIndex].Name)));
|
||||
releases.Add((
|
||||
$"legacy-index-buffer-{bufferIndex}-accounting",
|
||||
() => GpuMemoryTracker.TrackDeallocation(
|
||||
legacyIndexBuffers[bufferIndex].Bytes,
|
||||
GpuResourceType.Buffer)));
|
||||
}
|
||||
|
||||
if (vbo != 0)
|
||||
{
|
||||
releases.Add(("legacy-vertex-buffer-delete", () => legacyGl.DeleteBuffer(vbo)));
|
||||
releases.Add((
|
||||
"legacy-vertex-buffer-accounting",
|
||||
() => GpuMemoryTracker.TrackDeallocation(
|
||||
meshData.Vertices.Length * VertexPositionNormalTexture.Size,
|
||||
GpuResourceType.Buffer)));
|
||||
}
|
||||
if (vao != 0)
|
||||
releases.Add(("legacy-vertex-array-delete", () => legacyGl.DeleteVertexArray(vao)));
|
||||
}
|
||||
|
||||
return new RetryableResourceReleaseLedger(releases);
|
||||
}
|
||||
|
||||
|
|
@ -2447,48 +2322,14 @@ namespace AcDream.App.Rendering.Wb
|
|||
return null;
|
||||
|
||||
var releases = new List<(string Name, Action Release)>();
|
||||
if (_useModernRendering)
|
||||
if (data.GlobalAllocation is { } allocation)
|
||||
{
|
||||
if (data.GlobalAllocation is { } allocation)
|
||||
{
|
||||
releases.Add((
|
||||
"global-index-range",
|
||||
() => GlobalBuffer!.ReleaseIndexRange(allocation)));
|
||||
releases.Add((
|
||||
"global-vertex-range",
|
||||
() => GlobalBuffer!.ReleaseVertexRange(allocation)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GL gl = RequireGl();
|
||||
if (data.VAO != 0)
|
||||
releases.Add(("legacy-vertex-array-delete", () => gl.DeleteVertexArray(data.VAO)));
|
||||
if (data.VBO != 0)
|
||||
{
|
||||
releases.Add(("legacy-vertex-buffer-delete", () => gl.DeleteBuffer(data.VBO)));
|
||||
releases.Add((
|
||||
"legacy-vertex-buffer-accounting",
|
||||
() => GpuMemoryTracker.TrackDeallocation(
|
||||
data.VertexCount * VertexPositionNormalTexture.Size,
|
||||
GpuResourceType.Buffer)));
|
||||
}
|
||||
|
||||
for (int i = 0; i < data.Batches.Count; i++)
|
||||
{
|
||||
int batchIndex = i;
|
||||
ObjectRenderBatch batch = data.Batches[batchIndex];
|
||||
if (batch.IBO == 0)
|
||||
continue;
|
||||
releases.Add((
|
||||
$"legacy-index-buffer-{batchIndex}-delete",
|
||||
() => gl.DeleteBuffer(data.Batches[batchIndex].IBO)));
|
||||
releases.Add((
|
||||
$"legacy-index-buffer-{batchIndex}-accounting",
|
||||
() => GpuMemoryTracker.TrackDeallocation(
|
||||
data.Batches[batchIndex].IndexCount * sizeof(ushort),
|
||||
GpuResourceType.Buffer)));
|
||||
}
|
||||
releases.Add((
|
||||
"global-index-range",
|
||||
() => GlobalBuffer!.ReleaseIndexRange(allocation)));
|
||||
releases.Add((
|
||||
"global-vertex-range",
|
||||
() => GlobalBuffer!.ReleaseVertexRange(allocation)));
|
||||
}
|
||||
|
||||
for (int i = 0; i < data.Batches.Count; i++)
|
||||
|
|
@ -2841,7 +2682,7 @@ namespace AcDream.App.Rendering.Wb
|
|||
"One or more texture atlases could not be disposed.",
|
||||
failures!);
|
||||
|
||||
if (_useModernRendering && GlobalBuffer is not null)
|
||||
if (GlobalBuffer is not null)
|
||||
Capture(ref failures, GlobalBuffer.Dispose);
|
||||
|
||||
if (failures is not null)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue