refactor(render): extract typed retail pview passes
This commit is contained in:
parent
6d6e5b5fa5
commit
85239fb373
13 changed files with 1888 additions and 841 deletions
148
src/AcDream.App/Rendering/TerrainDrawDiagnosticsController.cs
Normal file
148
src/AcDream.App/Rendering/TerrainDrawDiagnosticsController.cs
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
using System.Diagnostics;
|
||||
using AcDream.App.Streaming;
|
||||
using AcDream.App.World;
|
||||
using AcDream.App.Rendering.Wb;
|
||||
|
||||
namespace AcDream.App.Rendering;
|
||||
|
||||
internal readonly record struct FramePipelineDiagnosticFacts(
|
||||
LandblockPresentationDiagnostics Presentation,
|
||||
RollingTimingPercentiles UploadTiming,
|
||||
int EntitiesWalked,
|
||||
int DeferredApplyBacklog,
|
||||
int FullWindowRetirementCount,
|
||||
int LastFullWindowRetirementLandblockCount,
|
||||
int MaterializedEntityCount,
|
||||
int SpawnSnapshotCount,
|
||||
int ResidentEntityCount);
|
||||
|
||||
internal interface IFramePipelineDiagnosticFactsSource
|
||||
{
|
||||
TerrainRenderDiagnosticFacts CaptureTerrain();
|
||||
|
||||
FramePipelineDiagnosticFacts CaptureFrame();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Samples the existing canonical runtime owners only when the five-second
|
||||
/// frame diagnostic cadence publishes. It owns no world or render resource.
|
||||
/// </summary>
|
||||
internal sealed class RuntimeFramePipelineDiagnosticFactsSource :
|
||||
IFramePipelineDiagnosticFactsSource
|
||||
{
|
||||
private readonly TerrainModernRenderer? _terrain;
|
||||
private readonly LandblockPresentationPipeline? _presentation;
|
||||
private readonly RuntimeRenderFrameLivePreparation? _livePreparation;
|
||||
private readonly WbDrawDispatcher? _dispatcher;
|
||||
private readonly StreamingController? _streaming;
|
||||
private readonly LiveEntityRuntime _liveEntities;
|
||||
private readonly GpuWorldState _world;
|
||||
|
||||
public RuntimeFramePipelineDiagnosticFactsSource(
|
||||
TerrainModernRenderer? terrain,
|
||||
LandblockPresentationPipeline? presentation,
|
||||
RuntimeRenderFrameLivePreparation? livePreparation,
|
||||
WbDrawDispatcher? dispatcher,
|
||||
StreamingController? streaming,
|
||||
LiveEntityRuntime liveEntities,
|
||||
GpuWorldState world)
|
||||
{
|
||||
_terrain = terrain;
|
||||
_presentation = presentation;
|
||||
_livePreparation = livePreparation;
|
||||
_dispatcher = dispatcher;
|
||||
_streaming = streaming;
|
||||
_liveEntities = liveEntities ?? throw new ArgumentNullException(nameof(liveEntities));
|
||||
_world = world ?? throw new ArgumentNullException(nameof(world));
|
||||
}
|
||||
|
||||
public TerrainRenderDiagnosticFacts CaptureTerrain() => new(
|
||||
_terrain?.VisibleSlots ?? 0,
|
||||
_terrain?.LoadedSlots ?? 0,
|
||||
_terrain?.CapacitySlots ?? 0);
|
||||
|
||||
public FramePipelineDiagnosticFacts CaptureFrame() => new(
|
||||
_presentation?.Diagnostics ?? default,
|
||||
_livePreparation?.UploadTiming ?? default,
|
||||
_dispatcher?.LastDrawStats.EntitiesWalked ?? 0,
|
||||
_streaming?.DeferredApplyBacklog ?? 0,
|
||||
_streaming?.FullWindowRetirementCount ?? 0,
|
||||
_streaming?.LastFullWindowRetirementLandblockCount ?? 0,
|
||||
_liveEntities.MaterializedWorldEntities.Count,
|
||||
_liveEntities.Snapshots.Count,
|
||||
_world.Entities.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Keeps the terrain timing sample and the frame-pipeline rollup on one
|
||||
/// failure-atomic publication cadence. The owner is shared by fallback and
|
||||
/// PView terrain passes, so extraction cannot silently split their telemetry.
|
||||
/// </summary>
|
||||
internal sealed class TerrainDrawDiagnosticsController
|
||||
{
|
||||
internal const long PublicationIntervalMilliseconds = 5_000;
|
||||
|
||||
private readonly bool _enabled;
|
||||
private readonly WorldRenderDiagnostics _world;
|
||||
private readonly IFramePipelineDiagnosticFactsSource _facts;
|
||||
private readonly IRenderFrameDiagnosticLog _log;
|
||||
private long _lastPublicationMilliseconds;
|
||||
|
||||
public TerrainDrawDiagnosticsController(
|
||||
bool enabled,
|
||||
WorldRenderDiagnostics world,
|
||||
IFramePipelineDiagnosticFactsSource facts,
|
||||
IRenderFrameDiagnosticLog log)
|
||||
{
|
||||
_enabled = enabled;
|
||||
_world = world ?? throw new ArgumentNullException(nameof(world));
|
||||
_facts = facts ?? throw new ArgumentNullException(nameof(facts));
|
||||
_log = log ?? throw new ArgumentNullException(nameof(log));
|
||||
}
|
||||
|
||||
public void Begin() => _world.BeginTerrainDraw();
|
||||
|
||||
public void Complete() => Complete(_enabled ? Environment.TickCount64 : 0L);
|
||||
|
||||
internal void Complete(long nowMilliseconds)
|
||||
{
|
||||
_world.EndTerrainDraw();
|
||||
if (!_enabled
|
||||
|| nowMilliseconds - _lastPublicationMilliseconds <= PublicationIntervalMilliseconds)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Both writes are one diagnostic transaction. Any failure leaves the
|
||||
// cadence uncommitted so a later terrain draw retries both publications.
|
||||
_world.PublishTerrainDiagnostics(_facts.CaptureTerrain());
|
||||
_log.WriteLine(FormatFrame(_facts.CaptureFrame()));
|
||||
_lastPublicationMilliseconds = nowMilliseconds;
|
||||
}
|
||||
|
||||
internal static string FormatFrame(FramePipelineDiagnosticFacts facts)
|
||||
{
|
||||
LandblockRenderPublisherDiagnostics render = facts.Presentation.Render;
|
||||
LandblockPhysicsPublisherDiagnostics physics = facts.Presentation.Physics;
|
||||
LandblockStaticPresentationDiagnostics statics = facts.Presentation.Statics;
|
||||
double ticksToMicros = 1_000_000.0 / Stopwatch.Frequency;
|
||||
double uploadMedian = facts.UploadTiming.MedianHundredthsMicroseconds / 100.0;
|
||||
double uploadP95 = facts.UploadTiming.Percentile95HundredthsMicroseconds / 100.0;
|
||||
return
|
||||
$"[FRAME-DIAG] publish={render.BeginCount}/{render.CompleteCount} "
|
||||
+ $"render_total_us=[terrain={render.TerrainPublishTicks * ticksToMicros:F1} "
|
||||
+ $"begin={render.BeginPublishTicks * ticksToMicros:F1} "
|
||||
+ $"complete={render.CompletePublishTicks * ticksToMicros:F1}] "
|
||||
+ $"physics_total_us=[base={physics.BasePublishTicks * ticksToMicros:F1} "
|
||||
+ $"gfx={physics.GfxCacheTicks * ticksToMicros:F1} "
|
||||
+ $"complete={physics.CompletePublishTicks * ticksToMicros:F1}] "
|
||||
+ $"static={statics.BeginCount}/{statics.CompleteCount}"
|
||||
+ $"(active={statics.ActiveEntityCount}) "
|
||||
+ $"entUpl_us={uploadMedian:F1}m/{uploadP95:F1}p95 "
|
||||
+ $"deferred={facts.DeferredApplyBacklog} "
|
||||
+ $"fullRetire={facts.FullWindowRetirementCount}"
|
||||
+ $"(landblocks={facts.LastFullWindowRetirementLandblockCount}) "
|
||||
+ $"esg={facts.MaterializedEntityCount} spawn={facts.SpawnSnapshotCount} "
|
||||
+ $"resident={facts.ResidentEntityCount} walked={facts.EntitiesWalked}";
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue