perf(streaming): cursor publication across frame budgets
This commit is contained in:
parent
bb16f74fd4
commit
98f1ac8934
32 changed files with 2215 additions and 823 deletions
|
|
@ -29,8 +29,11 @@ using Silk.NET.OpenGL;
|
|||
|
||||
namespace AcDream.App.Rendering.Wb;
|
||||
|
||||
public sealed unsafe class EnvCellRenderer : IDisposable
|
||||
public sealed unsafe class EnvCellRenderer :
|
||||
IDisposable,
|
||||
IEnvCellLandblockPublisher
|
||||
{
|
||||
private readonly object _publicationOwner = new();
|
||||
private readonly GL _gl;
|
||||
private readonly ObjectMeshManager _meshManager;
|
||||
private readonly WbFrustum _frustum;
|
||||
|
|
@ -381,8 +384,80 @@ public sealed unsafe class EnvCellRenderer : IDisposable
|
|||
/// </summary>
|
||||
public void CommitLandblock(EnvCellLandblockBuild build)
|
||||
{
|
||||
_landblocks[build.LandblockId] = CreateCommittedSnapshot(build);
|
||||
EnvCellLandblockPublication publication = PreparePublication(build);
|
||||
while (!AdvancePreparationOne(publication))
|
||||
{
|
||||
}
|
||||
CommitPublication(publication);
|
||||
}
|
||||
|
||||
EnvCellLandblockPublication IEnvCellLandblockPublisher.PreparePublication(
|
||||
EnvCellLandblockBuild build) =>
|
||||
PreparePublication(build);
|
||||
|
||||
bool IEnvCellLandblockPublisher.AdvancePreparationOne(
|
||||
EnvCellLandblockPublication publication) =>
|
||||
AdvancePreparationOne(publication);
|
||||
|
||||
void IEnvCellLandblockPublisher.CommitPublication(
|
||||
EnvCellLandblockPublication publication) =>
|
||||
CommitPublication(publication);
|
||||
|
||||
internal EnvCellLandblockPublication PreparePublication(
|
||||
EnvCellLandblockBuild build)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(build);
|
||||
return new EnvCellLandblockPublication(_publicationOwner, build);
|
||||
}
|
||||
|
||||
internal bool AdvancePreparationOne(
|
||||
EnvCellLandblockPublication publication)
|
||||
{
|
||||
ValidatePublication(publication);
|
||||
if (publication.PreparationCommitted)
|
||||
return true;
|
||||
|
||||
if (publication.ShellCursor < publication.Build.Shells.Length)
|
||||
{
|
||||
AddShell(
|
||||
publication.Replacement,
|
||||
publication.Build.Shells[publication.ShellCursor]);
|
||||
WbBoundingBox bounds =
|
||||
publication.Build.Shells[publication.ShellCursor].WorldBounds;
|
||||
publication.TotalBounds =
|
||||
publication.ShellCursor == 0
|
||||
? bounds
|
||||
: WbBoundingBox.Union(
|
||||
publication.TotalBounds,
|
||||
bounds);
|
||||
publication.ShellCursor++;
|
||||
return false;
|
||||
}
|
||||
|
||||
publication.Replacement.TotalEnvCellBounds =
|
||||
publication.Replacement.EnvCellBounds.Count == 0
|
||||
? new WbBoundingBox(Vector3.Zero, Vector3.Zero)
|
||||
: publication.TotalBounds;
|
||||
publication.Replacement.InstancesReady = true;
|
||||
publication.Replacement.MeshDataReady = true;
|
||||
publication.Replacement.GpuReady = true;
|
||||
publication.PreparationCommitted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
internal void CommitPublication(
|
||||
EnvCellLandblockPublication publication)
|
||||
{
|
||||
ValidatePublication(publication);
|
||||
if (!publication.PreparationCommitted)
|
||||
throw new InvalidOperationException(
|
||||
"EnvCell landblock publication cannot commit before preparation.");
|
||||
if (publication.PublicationCommitted)
|
||||
return;
|
||||
|
||||
_landblocks[publication.Build.LandblockId] = publication.Replacement;
|
||||
NeedsPrepare = true;
|
||||
publication.PublicationCommitted = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -398,35 +473,7 @@ public sealed unsafe class EnvCellRenderer : IDisposable
|
|||
};
|
||||
|
||||
foreach (var shell in build.Shells)
|
||||
{
|
||||
replacement.Instances.Add(new EnvCellSceneryInstance
|
||||
{
|
||||
ObjectId = shell.GeometryId,
|
||||
InstanceId = shell.CellId,
|
||||
IsBuilding = true,
|
||||
IsEntryCell = false,
|
||||
WorldPosition = shell.WorldPosition,
|
||||
LocalPosition = Vector3.Zero,
|
||||
Rotation = shell.Rotation,
|
||||
Scale = Vector3.One,
|
||||
Transform = shell.Transform,
|
||||
LocalBoundingBox = shell.LocalBounds,
|
||||
BoundingBox = shell.WorldBounds,
|
||||
});
|
||||
replacement.EnvCellBounds[shell.CellId] = shell.WorldBounds;
|
||||
|
||||
if (!replacement.BuildingPartGroups.TryGetValue(shell.GeometryId, out var instances))
|
||||
{
|
||||
instances = new List<InstanceData>();
|
||||
replacement.BuildingPartGroups[shell.GeometryId] = instances;
|
||||
}
|
||||
instances.Add(new InstanceData
|
||||
{
|
||||
Transform = shell.Transform,
|
||||
CellId = shell.CellId,
|
||||
Flags = 0,
|
||||
});
|
||||
}
|
||||
AddShell(replacement, shell);
|
||||
|
||||
var total = new WbBoundingBox(new Vector3(float.MaxValue), new Vector3(float.MinValue));
|
||||
foreach (var bounds in replacement.EnvCellBounds.Values)
|
||||
|
|
@ -441,6 +488,53 @@ public sealed unsafe class EnvCellRenderer : IDisposable
|
|||
return replacement;
|
||||
}
|
||||
|
||||
private static void AddShell(
|
||||
EnvCellLandblock replacement,
|
||||
EnvCellShellPlacement shell)
|
||||
{
|
||||
replacement.Instances.Add(new EnvCellSceneryInstance
|
||||
{
|
||||
ObjectId = shell.GeometryId,
|
||||
InstanceId = shell.CellId,
|
||||
IsBuilding = true,
|
||||
IsEntryCell = false,
|
||||
WorldPosition = shell.WorldPosition,
|
||||
LocalPosition = Vector3.Zero,
|
||||
Rotation = shell.Rotation,
|
||||
Scale = Vector3.One,
|
||||
Transform = shell.Transform,
|
||||
LocalBoundingBox = shell.LocalBounds,
|
||||
BoundingBox = shell.WorldBounds,
|
||||
});
|
||||
replacement.EnvCellBounds[shell.CellId] = shell.WorldBounds;
|
||||
|
||||
if (!replacement.BuildingPartGroups.TryGetValue(
|
||||
shell.GeometryId,
|
||||
out var instances))
|
||||
{
|
||||
instances = new List<InstanceData>();
|
||||
replacement.BuildingPartGroups[shell.GeometryId] = instances;
|
||||
}
|
||||
instances.Add(new InstanceData
|
||||
{
|
||||
Transform = shell.Transform,
|
||||
CellId = shell.CellId,
|
||||
Flags = 0,
|
||||
});
|
||||
}
|
||||
|
||||
private void ValidatePublication(
|
||||
EnvCellLandblockPublication publication)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(publication);
|
||||
if (!ReferenceEquals(publication.Owner, _publicationOwner))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"The EnvCell publication receipt belongs to another renderer.",
|
||||
nameof(publication));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a landblock from the renderer. Future PrepareRenderBatches will exclude it.
|
||||
/// </summary>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue