feat(rendering): compare the incremental shadow scene
Construct Slice F's non-drawing scene only for lifecycle automation, drain accepted static and live deltas at the final update boundary, and compare exact current-path fingerprints at cadence and checkpoints. Publish bounded mismatch, journal, index, digest, and memory evidence without changing normal launches or draw submission. Release: 8,211 passed, 5 skipped.
This commit is contained in:
parent
ff5d86175f
commit
0eb6648589
21 changed files with 937 additions and 20 deletions
|
|
@ -374,6 +374,20 @@ internal sealed class FrameRootCompositionPhase
|
|||
&& d.Options.AutomationArtifactDirectory is not null
|
||||
? new CurrentRenderSceneOracle()
|
||||
: null;
|
||||
if ((currentRenderSceneOracle is null)
|
||||
!= (live.RenderSceneShadow is null))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Lifecycle automation must compose the current-path referee and shadow render scene together.");
|
||||
}
|
||||
RenderSceneShadowComparisonController? renderSceneShadowComparison =
|
||||
currentRenderSceneOracle is not null
|
||||
&& live.RenderSceneShadow is not null
|
||||
? new RenderSceneShadowComparisonController(
|
||||
live.RenderSceneShadow,
|
||||
currentRenderSceneOracle,
|
||||
message => d.Log("[UI-PROBE] " + message))
|
||||
: null;
|
||||
live.DrawDispatcher.SetCurrentRenderSceneObserver(
|
||||
currentRenderSceneOracle);
|
||||
live.SelectionScene.SetCurrentRenderSceneObserver(
|
||||
|
|
@ -421,7 +435,8 @@ internal sealed class FrameRootCompositionPhase
|
|||
d.FrameProfiler,
|
||||
content.Dats,
|
||||
foundation.Residency,
|
||||
currentRenderSceneOracle);
|
||||
currentRenderSceneOracle,
|
||||
renderSceneShadowComparison);
|
||||
lifecycleAutomation =
|
||||
new WorldLifecycleAutomationController(
|
||||
() => session.WorldReveal.Snapshot,
|
||||
|
|
@ -463,6 +478,14 @@ internal sealed class FrameRootCompositionPhase
|
|||
renderFrameResources,
|
||||
settings.DevTools?.Presenter,
|
||||
renderWeatherFrame);
|
||||
IRenderFramePostDiagnosticsPhase postDiagnostics =
|
||||
renderSceneShadowComparison is not null
|
||||
&& lifecycleAutomation is not null
|
||||
? new SerialRenderFramePostDiagnosticsPhase(
|
||||
renderSceneShadowComparison,
|
||||
lifecycleAutomation)
|
||||
: (IRenderFramePostDiagnosticsPhase?)lifecycleAutomation
|
||||
?? NullRenderFramePostDiagnosticsPhase.Instance;
|
||||
var renderFrame = new RenderFrameOrchestrator(
|
||||
host.GpuFrameFlights,
|
||||
new FrameProfilerGpuMeasurement(d.FrameProfiler, d.Gl),
|
||||
|
|
@ -470,8 +493,7 @@ internal sealed class FrameRootCompositionPhase
|
|||
worldSceneRenderer,
|
||||
privatePresentation,
|
||||
live.FrameDiagnostics,
|
||||
(IRenderFramePostDiagnosticsPhase?)lifecycleAutomation
|
||||
?? NullRenderFramePostDiagnosticsPhase.Instance,
|
||||
postDiagnostics,
|
||||
(IRenderFrameFailureRecovery?)settings.DevTools?.Presenter
|
||||
?? NullRenderFrameFailureRecovery.Instance);
|
||||
Fault(FrameRootCompositionPoint.RenderRootCreated);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using AcDream.App.Interaction;
|
|||
using AcDream.App.Physics;
|
||||
using AcDream.App.Rendering;
|
||||
using AcDream.App.Rendering.Residency;
|
||||
using AcDream.App.Rendering.Scene;
|
||||
using AcDream.App.Rendering.Selection;
|
||||
using AcDream.App.Rendering.Sky;
|
||||
using AcDream.App.Rendering.Vfx;
|
||||
|
|
@ -80,6 +81,7 @@ internal sealed record LivePresentationResult(
|
|||
RetailStaticAnimatingObjectScheduler StaticAnimationScheduler,
|
||||
WorldGenerationAvailabilityState WorldAvailability,
|
||||
GpuWorldState WorldState,
|
||||
RenderSceneShadowRuntime? RenderSceneShadow,
|
||||
LiveEntityRuntime LiveEntities,
|
||||
ProjectileController ProjectileController,
|
||||
LiveEntityProjectionWithdrawalController ProjectionWithdrawal,
|
||||
|
|
@ -196,6 +198,20 @@ internal sealed class LivePresentationCompositionPhase
|
|||
|
||||
try
|
||||
{
|
||||
CompositionAcquisitionScope.CompositionAcquisitionLease<
|
||||
RenderSceneShadowRuntime>? renderSceneShadowLease = null;
|
||||
if (interaction.RetainedUi?.Screenshots is not null
|
||||
&& d.Options.AutomationArtifactDirectory is not null)
|
||||
{
|
||||
renderSceneShadowLease = scope.Acquire(
|
||||
"shadow render scene",
|
||||
() => new RenderSceneShadowRuntime(
|
||||
RenderSceneGeneration.FromRaw(1)),
|
||||
static value => value.Dispose());
|
||||
}
|
||||
RenderSceneShadowRuntime? renderSceneShadow =
|
||||
renderSceneShadowLease?.Resource;
|
||||
|
||||
var componentLifecycle =
|
||||
new DeferredLiveEntityRuntimeComponentLifecycle();
|
||||
var wbSpawnAdapter = new LandblockSpawnAdapter(foundation.MeshAdapter);
|
||||
|
|
@ -333,20 +349,33 @@ internal sealed class LivePresentationCompositionPhase
|
|||
"developer world-entity source",
|
||||
devWorldEntities.BindOwned(worldState));
|
||||
}
|
||||
liveEntities = new LiveEntityRuntime(
|
||||
worldState,
|
||||
new CompositeLiveEntityResourceLifecycle(
|
||||
var resourceOwners =
|
||||
new List<CompositeLiveEntityResourceLifecycle.Owner>
|
||||
{
|
||||
new(
|
||||
entity => _ = entitySpawnAdapter.OnCreate(entity),
|
||||
entity => _ = entitySpawnAdapter.OnRemove(entity)),
|
||||
new(
|
||||
entityScriptActivator.OnCreate,
|
||||
entityScriptActivator.OnRemove)),
|
||||
entityScriptActivator.OnRemove),
|
||||
};
|
||||
if (renderSceneShadow is not null)
|
||||
{
|
||||
resourceOwners.Add(new(
|
||||
renderSceneShadow.OnLiveResourceRegistered,
|
||||
renderSceneShadow.OnLiveResourceUnregistered));
|
||||
}
|
||||
liveEntities = new LiveEntityRuntime(
|
||||
worldState,
|
||||
new CompositeLiveEntityResourceLifecycle(
|
||||
[.. resourceOwners]),
|
||||
componentLifecycle);
|
||||
var liveRuntimeLease = scope.Own(
|
||||
"canonical live-entity runtime",
|
||||
liveEntities,
|
||||
static runtime => runtime.Clear());
|
||||
LiveRenderProjectionJournal? liveRenderProjections =
|
||||
renderSceneShadow?.BindLiveRuntime(liveEntities);
|
||||
Fault(LivePresentationCompositionPoint.CanonicalRuntimeCreated);
|
||||
|
||||
bindings.Adopt(
|
||||
|
|
@ -376,6 +405,13 @@ internal sealed class LivePresentationCompositionPhase
|
|||
liveEntities,
|
||||
wbVisibility,
|
||||
"WB projection visibility");
|
||||
if (liveRenderProjections is not null)
|
||||
{
|
||||
bindings.BindProjectionVisibility(
|
||||
liveEntities,
|
||||
liveRenderProjections.OnProjectionVisibilityChanged,
|
||||
"shadow render projection visibility");
|
||||
}
|
||||
Action<LiveEntityRecord, bool> particleVisibility = (record, visible) =>
|
||||
{
|
||||
if (record.WorldEntity is { } entity)
|
||||
|
|
@ -511,6 +547,15 @@ internal sealed class LivePresentationCompositionPhase
|
|||
bindings.BindProjectionPoseReady(
|
||||
equippedLease.Resource,
|
||||
lightsLease.Resource.OnAttachedPoseReady);
|
||||
if (liveRenderProjections is not null)
|
||||
{
|
||||
bindings.BindProjectionPoseReady(
|
||||
equippedLease.Resource,
|
||||
liveRenderProjections.OnProjectionPoseReady);
|
||||
bindings.BindProjectionRemoved(
|
||||
equippedLease.Resource,
|
||||
liveRenderProjections.OnProjectionRemoved);
|
||||
}
|
||||
bindings.Adopt(
|
||||
"entity-effect animation hooks",
|
||||
content.HookRegistrations.RegisterOwned(entityEffects));
|
||||
|
|
@ -529,6 +574,8 @@ internal sealed class LivePresentationCompositionPhase
|
|||
staticAnimationScheduler,
|
||||
worldAvailability,
|
||||
worldState,
|
||||
renderSceneShadow,
|
||||
renderSceneShadowLease,
|
||||
liveEntities,
|
||||
projectileController,
|
||||
projectionWithdrawal,
|
||||
|
|
@ -574,6 +621,9 @@ internal sealed class LivePresentationCompositionPhase
|
|||
RetailStaticAnimatingObjectScheduler staticAnimationScheduler,
|
||||
WorldGenerationAvailabilityState worldAvailability,
|
||||
GpuWorldState worldState,
|
||||
RenderSceneShadowRuntime? renderSceneShadow,
|
||||
CompositionAcquisitionScope.CompositionAcquisitionLease<
|
||||
RenderSceneShadowRuntime>? renderSceneShadowLease,
|
||||
LiveEntityRuntime liveEntities,
|
||||
ProjectileController projectileController,
|
||||
LiveEntityProjectionWithdrawalController projectionWithdrawal,
|
||||
|
|
@ -818,7 +868,8 @@ internal sealed class LivePresentationCompositionPhase
|
|||
worldState,
|
||||
landblockRetirementOwner,
|
||||
landblockLoaded.OnLandblockLoaded,
|
||||
landblockRenderPublisher.PrepareAfterRenderPins);
|
||||
landblockRenderPublisher.PrepareAfterRenderPins,
|
||||
renderSceneShadow?.StaticProjections);
|
||||
Fault(LivePresentationCompositionPoint.LandblockPipelineCreated);
|
||||
|
||||
var clipFrameLease = scope.Acquire(
|
||||
|
|
@ -965,6 +1016,7 @@ internal sealed class LivePresentationCompositionPhase
|
|||
staticAnimationScheduler,
|
||||
worldAvailability,
|
||||
worldState,
|
||||
renderSceneShadow,
|
||||
liveEntities,
|
||||
projectileController,
|
||||
projectionWithdrawal,
|
||||
|
|
@ -1010,6 +1062,7 @@ internal sealed class LivePresentationCompositionPhase
|
|||
_publication.PublishLivePresentation(result);
|
||||
|
||||
liveRuntimeLease.Transfer();
|
||||
renderSceneShadowLease?.Transfer();
|
||||
lightsLease.Transfer();
|
||||
equippedLease.Transfer();
|
||||
presentationLease.Transfer();
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using AcDream.App.Diagnostics;
|
|||
using AcDream.App.Net;
|
||||
using AcDream.App.Physics;
|
||||
using AcDream.App.Rendering;
|
||||
using AcDream.App.Rendering.Scene;
|
||||
using AcDream.App.Rendering.Vfx;
|
||||
using AcDream.App.Rendering.Wb;
|
||||
using AcDream.App.Settings;
|
||||
|
|
@ -454,7 +455,8 @@ internal sealed class SessionPlayerCompositionPhase
|
|||
new LiveEntityReadyPublisher(
|
||||
live.LiveEntities,
|
||||
live.EntityEffects,
|
||||
live.Presentation),
|
||||
live.Presentation,
|
||||
live.RenderSceneShadow?.LiveProjections),
|
||||
originCoordinator,
|
||||
networkUpdateBridge,
|
||||
localPhysicsTimestamps,
|
||||
|
|
@ -603,7 +605,9 @@ internal sealed class SessionPlayerCompositionPhase
|
|||
live.EntityEffects,
|
||||
live.EquippedChildren,
|
||||
content.ParticleSink,
|
||||
live.Lights);
|
||||
live.Lights,
|
||||
live.RenderSceneShadow?.LiveProjections,
|
||||
live.RenderSceneShadow);
|
||||
var localPlayerAnimation = new LocalPlayerAnimationController(
|
||||
live.LiveEntities,
|
||||
d.PlayerIdentity,
|
||||
|
|
@ -650,7 +654,9 @@ internal sealed class SessionPlayerCompositionPhase
|
|||
live.AnimationPresenter,
|
||||
d.AnimatedEntities,
|
||||
live.EquippedChildren,
|
||||
liveEffectFrame);
|
||||
liveEffectFrame,
|
||||
live.RenderSceneShadow?.LiveProjections,
|
||||
live.RenderSceneShadow?.StaticProjections);
|
||||
Fault(SessionPlayerCompositionPoint.UpdateLeavesCreated);
|
||||
|
||||
var playerMode = new PlayerModeController(
|
||||
|
|
@ -812,7 +818,8 @@ internal sealed class SessionPlayerCompositionPhase
|
|||
live.EntityEffects,
|
||||
content.AnimationHookFrames,
|
||||
live.Presentation,
|
||||
d.RemoteMovementObservations),
|
||||
d.RemoteMovementObservations,
|
||||
live.RenderSceneShadow),
|
||||
d.Log);
|
||||
LiveSessionHost sessionHost = sessionRuntimeFactory.Create(liveSession);
|
||||
Fault(SessionPlayerCompositionPoint.SessionHostCreated);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue