Separate logical ownership, render publication, and GPU retirement across live entities, landblocks, particles, textures, mesh arenas, portal/UI teardown, and per-frame scratch storage. Add bounded DAT/texture caches, upload budgets, three-frame fence retirement, exact-incarnation appearance reconciliation, frame pacing, and extensive lifetime conformance coverage.\n\nThe seven-destination connected route now cuts peak working/private memory roughly in half, returns Caul to 125-153 FPS locally, and produces no WER or AMD reset.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>
30 lines
1.2 KiB
C#
30 lines
1.2 KiB
C#
namespace AcDream.App.Rendering;
|
|
|
|
/// <summary>
|
|
/// Capacity policy for render-thread-owned streaming GPU buffers. Dynamic
|
|
/// buffers keep one backing allocation and update its active prefix; they do
|
|
/// not orphan a new driver allocation on every draw call.
|
|
/// </summary>
|
|
internal static class DynamicBufferCapacity
|
|
{
|
|
internal const int DefaultAlignment = 4096;
|
|
|
|
public static int Grow(int currentBytes, int requiredBytes, int alignment = DefaultAlignment)
|
|
{
|
|
if (currentBytes < 0)
|
|
throw new ArgumentOutOfRangeException(nameof(currentBytes));
|
|
if (requiredBytes < 0)
|
|
throw new ArgumentOutOfRangeException(nameof(requiredBytes));
|
|
if (alignment <= 0)
|
|
throw new ArgumentOutOfRangeException(nameof(alignment));
|
|
if (requiredBytes <= currentBytes)
|
|
return currentBytes;
|
|
|
|
long doubled = currentBytes == 0 ? alignment : (long)currentBytes * 2L;
|
|
long target = Math.Max(requiredBytes, doubled);
|
|
long aligned = ((target + alignment - 1L) / alignment) * alignment;
|
|
if (aligned > int.MaxValue)
|
|
throw new OverflowException("Dynamic GPU buffer capacity exceeds Int32.MaxValue.");
|
|
return (int)aligned;
|
|
}
|
|
}
|