test(overhaul): integrate reviewed consumed-light checkpoint observation
This commit is contained in:
parent
ad866b7f65
commit
59b0b6e72f
9 changed files with 703 additions and 1 deletions
|
|
@ -596,6 +596,8 @@ internal sealed class FrameRootCompositionPhase
|
|||
foundation.MeshAdapter,
|
||||
foundation.TextureCache,
|
||||
live.DrawDispatcher,
|
||||
live.EnvCellRenderer,
|
||||
d.Lighting,
|
||||
d.FrameProfiler,
|
||||
content.Dats,
|
||||
foundation.Residency,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ using System.Text.Json;
|
|||
using AcDream.App.Rendering;
|
||||
using AcDream.App.Rendering.Residency;
|
||||
using AcDream.App.Rendering.Scene;
|
||||
using AcDream.App.Rendering.Wb;
|
||||
using AcDream.App.Streaming;
|
||||
using AcDream.App.UI.Testing;
|
||||
using AcDream.Core.Physics;
|
||||
|
|
@ -96,7 +97,8 @@ internal sealed record WorldLifecycleResourceSnapshot(
|
|||
ResidencySnapshot Residency,
|
||||
double Fps,
|
||||
double FrameMilliseconds,
|
||||
string? LastFrameProfile);
|
||||
string? LastFrameProfile,
|
||||
EnvCellLightingConsumptionSnapshot? EnvCellLighting = null);
|
||||
|
||||
internal sealed record WorldLifecycleCheckpoint(
|
||||
int Sequence,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using AcDream.App.Streaming;
|
|||
using AcDream.App.World;
|
||||
using AcDream.Content;
|
||||
using AcDream.Core.Physics;
|
||||
using AcDream.Core.Lighting;
|
||||
using AcDream.Core.Vfx;
|
||||
using DatReaderWriter.Lib.IO;
|
||||
|
||||
|
|
@ -39,6 +40,8 @@ internal sealed class WorldLifecycleResourceSnapshotSource
|
|||
private readonly WbMeshAdapter? _meshes;
|
||||
private readonly TextureCache _textures;
|
||||
private readonly WbDrawDispatcher? _dispatcher;
|
||||
private readonly EnvCellRenderer? _envCellRenderer;
|
||||
private readonly LightManager _lighting;
|
||||
private readonly FrameProfiler _frameProfiler;
|
||||
private readonly IDatReaderWriter _dats;
|
||||
private readonly ResidencyManager _residency;
|
||||
|
|
@ -62,6 +65,8 @@ internal sealed class WorldLifecycleResourceSnapshotSource
|
|||
WbMeshAdapter? meshes,
|
||||
TextureCache textures,
|
||||
WbDrawDispatcher? dispatcher,
|
||||
EnvCellRenderer? envCellRenderer,
|
||||
LightManager lighting,
|
||||
FrameProfiler frameProfiler,
|
||||
IDatReaderWriter dats,
|
||||
ResidencyManager residency,
|
||||
|
|
@ -88,6 +93,8 @@ internal sealed class WorldLifecycleResourceSnapshotSource
|
|||
_meshes = meshes;
|
||||
_textures = textures ?? throw new ArgumentNullException(nameof(textures));
|
||||
_dispatcher = dispatcher;
|
||||
_envCellRenderer = envCellRenderer;
|
||||
_lighting = lighting ?? throw new ArgumentNullException(nameof(lighting));
|
||||
_frameProfiler = frameProfiler
|
||||
?? throw new ArgumentNullException(nameof(frameProfiler));
|
||||
_dats = dats ?? throw new ArgumentNullException(nameof(dats));
|
||||
|
|
@ -156,6 +163,10 @@ internal sealed class WorldLifecycleResourceSnapshotSource
|
|||
ParticleOwners: _particleSink.TrackedOwnerCount,
|
||||
EffectOwners: _effects.ReadyOwnerCount,
|
||||
LightOwners: _lights.TrackedOwnerCount,
|
||||
EnvCellLighting: CaptureEnvCellLighting(
|
||||
outcome,
|
||||
_envCellRenderer,
|
||||
_lighting),
|
||||
ScriptOwners: _scripts.ActiveOwnerCount,
|
||||
ActiveScripts: _scripts.ActiveScriptCount,
|
||||
MeshRenderData: mesh.RenderData,
|
||||
|
|
@ -203,4 +214,17 @@ internal sealed class WorldLifecycleResourceSnapshotSource
|
|||
FrameMilliseconds: render.FrameMilliseconds,
|
||||
LastFrameProfile: _frameProfiler.LastReport);
|
||||
}
|
||||
|
||||
internal static EnvCellLightingConsumptionSnapshot? CaptureEnvCellLighting(
|
||||
RenderFrameOutcome outcome,
|
||||
EnvCellRenderer? renderer,
|
||||
LightManager lighting)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(lighting);
|
||||
return renderer?.CaptureLightingConsumption(
|
||||
lighting,
|
||||
currentWorldFrame:
|
||||
!outcome.SkippedZeroArea
|
||||
&& outcome.World.NormalWorldDrawn);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,176 @@
|
|||
using AcDream.Core.Lighting;
|
||||
|
||||
namespace AcDream.App.Rendering.Wb;
|
||||
|
||||
internal sealed record EnvCellLightingVectorBits(
|
||||
uint X,
|
||||
uint Y,
|
||||
uint Z);
|
||||
|
||||
internal sealed record EnvCellLightingAmbientSnapshot(
|
||||
EnvCellLightingVectorBits AmbientColor,
|
||||
EnvCellLightingVectorBits SunColor,
|
||||
EnvCellLightingVectorBits SunDirection);
|
||||
|
||||
internal sealed record EnvCellLightingSourceSnapshot(
|
||||
int Index,
|
||||
uint OwnerId,
|
||||
uint CellId,
|
||||
int Kind,
|
||||
bool IsDynamic,
|
||||
bool IsLit,
|
||||
bool TracksOwnerPose,
|
||||
EnvCellLightingVectorBits Position,
|
||||
EnvCellLightingVectorBits Forward,
|
||||
EnvCellLightingVectorBits Color,
|
||||
uint Intensity,
|
||||
uint Range,
|
||||
uint ConeAngle,
|
||||
uint DistSq,
|
||||
uint[] LocalPose);
|
||||
|
||||
internal sealed record EnvCellLightingCellSetSnapshot(
|
||||
uint CellId,
|
||||
int[] Indices);
|
||||
|
||||
/// <summary>
|
||||
/// Checkpoint-only copy of the point-light inputs the EnvCell RHI submission
|
||||
/// already consumed. PackedGlobalLightBits is the authoritative binding-4
|
||||
/// payload; Sources records its identity/provenance and CellSets records the
|
||||
/// exact cached eight-index values copied to binding 5.
|
||||
/// </summary>
|
||||
internal sealed record EnvCellLightingConsumptionSnapshot(
|
||||
bool HasCurrentEnvCellInput,
|
||||
int FrameGeneration,
|
||||
int FrameSlot,
|
||||
int RegisteredLightCount,
|
||||
int LogicalGlobalLightCount,
|
||||
int UploadedGlobalLightCount,
|
||||
uint[] PackedGlobalLightBits,
|
||||
EnvCellLightingSourceSnapshot[] Sources,
|
||||
EnvCellLightingCellSetSnapshot[] CellSets,
|
||||
EnvCellLightingAmbientSnapshot Ambient);
|
||||
|
||||
public sealed partial class EnvCellRenderer
|
||||
{
|
||||
/// <summary>
|
||||
/// Copies the retained inputs from this frame's completed EnvCell submission
|
||||
/// for an explicitly requested lifecycle checkpoint. This method never
|
||||
/// rebuilds a light snapshot or invokes either cell selector.
|
||||
/// </summary>
|
||||
internal EnvCellLightingConsumptionSnapshot CaptureLightingConsumption(
|
||||
LightManager lighting,
|
||||
bool currentWorldFrame)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(lighting);
|
||||
|
||||
EnvCellLightingAmbientSnapshot ambient = CaptureAmbient(
|
||||
lighting.CurrentAmbient);
|
||||
if (!currentWorldFrame)
|
||||
return EmptyLightingConsumption(lighting.RegisteredCount, ambient);
|
||||
|
||||
List<KeyValuePair<uint, CachedCellLightSet>> currentCells = [];
|
||||
foreach (KeyValuePair<uint, CachedCellLightSet> entry in _cellLightSetCache)
|
||||
{
|
||||
if (entry.Value.FrameGeneration == _lightFrameGeneration)
|
||||
currentCells.Add(entry);
|
||||
}
|
||||
|
||||
currentCells.Sort(static (left, right) => left.Key.CompareTo(right.Key));
|
||||
if (currentCells.Count == 0)
|
||||
return EmptyLightingConsumption(lighting.RegisteredCount, ambient);
|
||||
|
||||
IReadOnlyList<LightSource>? pointSnapshot = _pointSnapshot;
|
||||
int logicalCount = pointSnapshot?.Count ?? 0;
|
||||
int uploadedCount = Math.Max(logicalCount, 1);
|
||||
int packedFloatCount = checked(
|
||||
uploadedCount * GlobalLightPacker.FloatsPerLight);
|
||||
var packedBits = new uint[packedFloatCount];
|
||||
for (int index = 0; index < packedFloatCount; index++)
|
||||
packedBits[index] = Bits(_globalLightData[index]);
|
||||
|
||||
var sources = new EnvCellLightingSourceSnapshot[logicalCount];
|
||||
for (int index = 0; index < logicalCount; index++)
|
||||
sources[index] = CaptureSource(index, pointSnapshot![index]);
|
||||
|
||||
var cellSets = new EnvCellLightingCellSetSnapshot[currentCells.Count];
|
||||
for (int index = 0; index < currentCells.Count; index++)
|
||||
{
|
||||
KeyValuePair<uint, CachedCellLightSet> entry = currentCells[index];
|
||||
cellSets[index] = new EnvCellLightingCellSetSnapshot(
|
||||
entry.Key,
|
||||
(int[])entry.Value.Indices.Clone());
|
||||
}
|
||||
|
||||
return new EnvCellLightingConsumptionSnapshot(
|
||||
HasCurrentEnvCellInput: true,
|
||||
FrameGeneration: _lightFrameGeneration,
|
||||
FrameSlot: _dynamicFrameSlot,
|
||||
RegisteredLightCount: lighting.RegisteredCount,
|
||||
LogicalGlobalLightCount: logicalCount,
|
||||
UploadedGlobalLightCount: uploadedCount,
|
||||
PackedGlobalLightBits: packedBits,
|
||||
Sources: sources,
|
||||
CellSets: cellSets,
|
||||
Ambient: ambient);
|
||||
}
|
||||
|
||||
private EnvCellLightingConsumptionSnapshot EmptyLightingConsumption(
|
||||
int registeredLightCount,
|
||||
EnvCellLightingAmbientSnapshot ambient) =>
|
||||
new(
|
||||
HasCurrentEnvCellInput: false,
|
||||
FrameGeneration: _lightFrameGeneration,
|
||||
FrameSlot: _dynamicFrameSlot,
|
||||
RegisteredLightCount: registeredLightCount,
|
||||
LogicalGlobalLightCount: 0,
|
||||
UploadedGlobalLightCount: 0,
|
||||
PackedGlobalLightBits: [],
|
||||
Sources: [],
|
||||
CellSets: [],
|
||||
Ambient: ambient);
|
||||
|
||||
private static EnvCellLightingSourceSnapshot CaptureSource(
|
||||
int index,
|
||||
LightSource source) =>
|
||||
new(
|
||||
Index: index,
|
||||
OwnerId: source.OwnerId,
|
||||
CellId: source.CellId,
|
||||
Kind: (int)source.Kind,
|
||||
IsDynamic: source.IsDynamic,
|
||||
IsLit: source.IsLit,
|
||||
TracksOwnerPose: source.TracksOwnerPose,
|
||||
Position: CaptureVector(source.WorldPosition),
|
||||
Forward: CaptureVector(source.WorldForward),
|
||||
Color: CaptureVector(source.ColorLinear),
|
||||
Intensity: Bits(source.Intensity),
|
||||
Range: Bits(source.Range),
|
||||
ConeAngle: Bits(source.ConeAngle),
|
||||
DistSq: Bits(source.DistSq),
|
||||
LocalPose:
|
||||
[
|
||||
Bits(source.LocalPose.M11), Bits(source.LocalPose.M12),
|
||||
Bits(source.LocalPose.M13), Bits(source.LocalPose.M14),
|
||||
Bits(source.LocalPose.M21), Bits(source.LocalPose.M22),
|
||||
Bits(source.LocalPose.M23), Bits(source.LocalPose.M24),
|
||||
Bits(source.LocalPose.M31), Bits(source.LocalPose.M32),
|
||||
Bits(source.LocalPose.M33), Bits(source.LocalPose.M34),
|
||||
Bits(source.LocalPose.M41), Bits(source.LocalPose.M42),
|
||||
Bits(source.LocalPose.M43), Bits(source.LocalPose.M44),
|
||||
]);
|
||||
|
||||
private static EnvCellLightingAmbientSnapshot CaptureAmbient(
|
||||
CellAmbientState ambient) =>
|
||||
new(
|
||||
CaptureVector(ambient.AmbientColor),
|
||||
CaptureVector(ambient.SunColor),
|
||||
CaptureVector(ambient.SunDirection));
|
||||
|
||||
private static EnvCellLightingVectorBits CaptureVector(
|
||||
System.Numerics.Vector3 value) =>
|
||||
new(Bits(value.X), Bits(value.Y), Bits(value.Z));
|
||||
|
||||
private static uint Bits(float value) =>
|
||||
BitConverter.SingleToUInt32Bits(value);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue