fix #225: stabilize render pacing and frame CPU

Replace scheduler-quantized software sleeps with a reusable Windows high-resolution deadline timer, expose pacing in the frame profiler, and make shutdown wake every persistent mesh worker without losing the shared signal.

Preserve retail alpha order while using a stable radix, skip duplicate deferred-alpha SSBO packing, pack light sets, cache static selection descriptors, and retire historical material groups at the whole-frame boundary. The fixed dense-Caul sample improved from roughly 9-12 ms CPU to 5.3-6.2 ms without reducing visual quality.

Release build succeeds with zero warnings and all 6,300 tests pass with five intentional skips. Three independent retail, architecture, and adversarial reviews are clean; the post-review connected route remains pending because local ACE is offline.

Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-19 06:29:30 +02:00
parent 47d7086a74
commit 3718e341be
17 changed files with 1103 additions and 225 deletions

View file

@ -10,6 +10,9 @@ namespace AcDream.App.Rendering.Wb;
/// <c>subPart.PartTransform * meshRef.PartTransform</c> product.
/// <see cref="LocalSortCenter"/> preserves the authored GfxObj key used by
/// retail's delayed-alpha viewer-distance ordering on cache hits.
/// <see cref="Group"/> is a registration-checked fast handle into the
/// dispatcher's bounded group table; a retired or synthetic entry falls back
/// to key lookup and refreshes this array entry.
///
/// Accessibility: <c>internal</c> because <see cref="GroupKey"/> is
/// <c>internal</c> and shows up in this struct's constructor / <c>Deconstruct</c>
@ -21,7 +24,19 @@ internal readonly record struct CachedBatch(
GroupKey Key,
ulong BindlessTextureHandle,
Matrix4x4 RestPose,
Vector3 LocalSortCenter = default);
Vector3 LocalSortCenter = default,
WbDrawDispatcher.InstanceGroup? Group = null,
long GroupRegistration = 0);
/// <summary>
/// Immutable retail-picking descriptor for one static entity part. The cache
/// stores only authored identity and rest pose; the current entity transform
/// and the selection system's live frustum/geometry verdict remain per-frame.
/// </summary>
internal readonly record struct CachedSelectionPart(
int PartIndex,
uint GfxObjId,
Matrix4x4 RestPose);
/// <summary>
/// One entity's cached classification. <see cref="Batches"/> is flat across
@ -39,4 +54,5 @@ internal sealed class EntityCacheEntry
public required uint EntityId { get; init; }
public required uint LandblockHint { get; init; }
public required CachedBatch[] Batches { get; init; }
public CachedSelectionPart[] SelectionParts { get; init; } = [];
}