Revert "perf(rendering): draw retained frame product"

This reverts commit ef1d263337.
This commit is contained in:
Erik 2026-07-25 06:28:31 +02:00
parent 624e1119ca
commit 2c848d4167
13 changed files with 268 additions and 1334 deletions

View file

@ -1483,10 +1483,41 @@ public sealed unsafe partial class WbDrawDispatcher : IDisposable
HashSet<uint>? animatedEntityIds = null,
EntitySet set = EntitySet.All)
{
bool diag = BeginEntityDispatch(
camera,
out Matrix4x4 vp,
out Vector3 camPos);
_shader.Use();
_selectionLighting?.TickLighting();
_indoorProbeFrameCounter++;
var vp = camera.View * camera.Projection;
_shader.SetMatrix4("uViewProjection", vp);
// A7 Fix D D-3/D-4: object path — plain Lambert points + sun. MUST set
// explicitly (shared GL uniform; EnvCellRenderer sets it to 1).
_shader.SetInt("uLightingMode", 0);
// #176 stripe-hunt isolation (ACDREAM_LIGHT_DEBUG) — throwaway diagnostic.
_shader.SetInt("uLightDebug", AcDream.Core.Rendering.RenderingDiagnostics.LightDebugMode);
// #128 self-heal: fresh re-request dedup per Draw pass.
_missRequested.Clear();
bool diag = string.Equals(Environment.GetEnvironmentVariable("ACDREAM_WB_DIAG"), "1", StringComparison.Ordinal);
if (diag && !_gpuQueriesInitialized)
{
for (int i = 0; i < GpuQueryRingDepth; i++)
{
_gpuQueryOpaque[i] = _gl.GenQuery();
_gpuQueryTransparent[i] = _gl.GenQuery();
}
_gpuQueriesInitialized = true;
}
// Always run the CPU stopwatch — cheap; only logged under diag.
_cpuStopwatch.Restart();
// Camera world-space position for front-to-back sort (perf #2). The view
// matrix is the inverse of the camera's world transform, so the world
// translation lives in the inverse's translation row.
Vector3 camPos = Vector3.Zero;
if (Matrix4x4.Invert(camera.View, out var invView))
camPos = invView.Translation;
// ── Phase 1: clear groups, walk entities, build groups ──────────────
// Draw is invoked several times per frame (landscape slices, late
@ -2027,71 +2058,11 @@ public sealed unsafe partial class WbDrawDispatcher : IDisposable
if (RenderingDiagnostics.ProbeClipRouteEnabled && _clipRoutingActive)
EmitClipRouteDispatchProbe(probeCulledEntities);
ExecuteClassifiedGroups(
vp,
camPos,
anyVao,
_groups.Values,
set,
walkResult.EntitiesWalked,
_walkScratch.Count,
diag,
observeCurrentPath: true);
}
private bool BeginEntityDispatch(
ICamera camera,
out Matrix4x4 viewProjection,
out Vector3 cameraWorldPosition)
{
_shader.Use();
_selectionLighting?.TickLighting();
_indoorProbeFrameCounter++;
viewProjection = camera.View * camera.Projection;
_shader.SetMatrix4("uViewProjection", viewProjection);
_shader.SetInt("uLightingMode", 0);
_shader.SetInt(
"uLightDebug",
RenderingDiagnostics.LightDebugMode);
_missRequested.Clear();
bool diagnosticsEnabled = string.Equals(
Environment.GetEnvironmentVariable("ACDREAM_WB_DIAG"),
"1",
StringComparison.Ordinal);
if (diagnosticsEnabled && !_gpuQueriesInitialized)
{
for (int index = 0; index < GpuQueryRingDepth; index++)
{
_gpuQueryOpaque[index] = _gl.GenQuery();
_gpuQueryTransparent[index] = _gl.GenQuery();
}
_gpuQueriesInitialized = true;
}
_cpuStopwatch.Restart();
cameraWorldPosition = Vector3.Zero;
if (Matrix4x4.Invert(camera.View, out Matrix4x4 inverseView))
cameraWorldPosition = inverseView.Translation;
return diagnosticsEnabled;
}
private void ExecuteClassifiedGroups(
Matrix4x4 vp,
Vector3 camPos,
uint anyVao,
IEnumerable<InstanceGroup> groups,
EntitySet set,
int entitiesWalked,
int tupleCount,
bool diag,
bool observeCurrentPath)
{
// Nothing visible — skip the GL pass entirely.
if (anyVao == 0)
{
LastDrawStats = new DrawStats(set, entitiesWalked, tupleCount, 0, 0, 0, 0, 0, 0);
ObserveClassifiedDispatcherSubmission(observeCurrentPath,
LastDrawStats = new DrawStats(set, walkResult.EntitiesWalked, _walkScratch.Count, 0, 0, 0, 0, 0, 0);
ObserveCurrentDispatcherSubmission(
visibleInstanceCount: 0,
immediateInstanceCount: 0,
deferTransparent: false,
@ -2104,7 +2075,7 @@ public sealed unsafe partial class WbDrawDispatcher : IDisposable
// ── Phase 3: assign FirstInstance per group, lay matrices contiguously, sort opaque ──
bool deferTransparent = _alphaQueue?.IsCollecting == true;
var instanceCounts = PartitionInstanceGroups(
groups,
_groups.Values,
deferTransparent,
camPos,
_opaqueDraws,
@ -2113,8 +2084,8 @@ public sealed unsafe partial class WbDrawDispatcher : IDisposable
int immediateInstances = instanceCounts.ImmediateInstances;
if (totalInstances == 0)
{
LastDrawStats = new DrawStats(set, entitiesWalked, tupleCount, 0, 0, 0, 0, 0, 0);
ObserveClassifiedDispatcherSubmission(observeCurrentPath,
LastDrawStats = new DrawStats(set, walkResult.EntitiesWalked, _walkScratch.Count, 0, 0, 0, 0, 0, 0);
ObserveCurrentDispatcherSubmission(
visibleInstanceCount: 0,
immediateInstanceCount: 0,
deferTransparent,
@ -2231,15 +2202,15 @@ public sealed unsafe partial class WbDrawDispatcher : IDisposable
_transparentByteOffset = layout.TransparentByteOffset;
LastDrawStats = new DrawStats(
set,
entitiesWalked,
tupleCount,
walkResult.EntitiesWalked,
_walkScratch.Count,
totalInstances,
totalDraws,
cullRuns,
_opaqueDrawCount,
_transparentDrawCount,
totalTriangles);
ObserveClassifiedDispatcherSubmission(observeCurrentPath,
ObserveCurrentDispatcherSubmission(
totalInstances,
immediateInstances,
deferTransparent,
@ -2450,7 +2421,6 @@ public sealed unsafe partial class WbDrawDispatcher : IDisposable
}
}
/// <summary>
/// Phase A8 RR5 (2026-05-26): per-building draw overload. Walks only
/// entities whose ParentCellId is in <paramref name="cellIds"/>, plus
@ -2606,23 +2576,6 @@ public sealed unsafe partial class WbDrawDispatcher : IDisposable
observer.ObserveDispatcherSubmission(in submission);
}
private void ObserveClassifiedDispatcherSubmission(
bool observeCurrentPath,
int visibleInstanceCount,
int immediateInstanceCount,
bool deferTransparent,
Vector3 cameraWorldPosition)
{
if (observeCurrentPath)
{
ObserveCurrentDispatcherSubmission(
visibleInstanceCount,
immediateInstanceCount,
deferTransparent,
cameraWorldPosition);
}
}
internal static CurrentRenderDispatcherSubmission
CreateDispatcherSubmission(
int visibleInstanceCount,