test: replace render source freezes
This commit is contained in:
parent
c31a9ac411
commit
5a33369074
7 changed files with 425 additions and 345 deletions
|
|
@ -1,7 +1,9 @@
|
|||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using AcDream.App.Composition;
|
||||
using AcDream.App.Rendering;
|
||||
using AcDream.App.Rendering.Scene;
|
||||
using AcDream.App.Tests.Architecture;
|
||||
using AcDream.Core.World;
|
||||
|
||||
namespace AcDream.App.Tests.Rendering;
|
||||
|
|
@ -219,7 +221,7 @@ public sealed class RetailPViewPassExecutorTests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void DrawInside_production_product_does_not_require_compare_only_referee()
|
||||
public void DrawInside_production_product_uses_retained_routes_without_legacy_partition_when_diagnostics_are_disabled()
|
||||
{
|
||||
LoadedCell interior = InteriorWithExit(0xA9B40100u);
|
||||
WorldEntity dynamic = Entity(
|
||||
|
|
@ -274,70 +276,6 @@ public sealed class RetailPViewPassExecutorTests
|
|||
Assert.Contains("look-in-punch", executor.Operations);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Renderer_source_preserves_retail_stage_order_through_typed_operations()
|
||||
{
|
||||
string source = RendererSource();
|
||||
string drawInside = MethodBody(source, "public RetailPViewFrameResult DrawInside(");
|
||||
AssertAppearsInOrder(
|
||||
drawInside,
|
||||
"passes.BeginFrame();",
|
||||
"passes.EmitDiagnostics(ctx, result);",
|
||||
"DrawLandscapeThroughOutsideView(",
|
||||
"DrawExitPortalMasks(ctx, passes",
|
||||
"DrawEnvCellShells(passes, pvFrame);",
|
||||
"DrawCellObjectLists(",
|
||||
"DrawDynamicsLast(");
|
||||
|
||||
string landscape = MethodBody(
|
||||
source,
|
||||
"private void DrawLandscapeThroughOutsideView(");
|
||||
AssertAppearsInOrder(
|
||||
landscape,
|
||||
"passes.SetTerrainClip(slice.Planes);",
|
||||
"passes.DrawLandscapeSlice(",
|
||||
"DrawBuildingLookIns(",
|
||||
"passes.DrawLandscapeSliceLate(",
|
||||
"passes.DrawUnattachedSceneParticles(ctx);",
|
||||
"passes.FlushLandscapeAlpha();",
|
||||
"passes.ClearInteriorDepth();");
|
||||
|
||||
string lookIns = MethodBody(source, "private void DrawBuildingLookIns(");
|
||||
AssertAppearsInOrder(
|
||||
lookIns,
|
||||
"passes.DrawLookInPortalPunch(ctx",
|
||||
"passes.DrawOpaqueCellShells(_shellBatch);",
|
||||
"passes.DrawCellParticles(ctx");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Production_uses_retained_routes_without_rebuilding_legacy_partition()
|
||||
{
|
||||
string source = RendererSource();
|
||||
string drawInside = MethodBody(
|
||||
source,
|
||||
"public RetailPViewFrameResult DrawInside(");
|
||||
|
||||
Assert.Contains(
|
||||
"if (_sceneFrameProduct is null || LegacyPartitionDiagnosticsEnabled)",
|
||||
drawInside,
|
||||
StringComparison.Ordinal);
|
||||
AssertAppearsInOrder(
|
||||
drawInside,
|
||||
"_sceneFrameProduct.BuildAndBorrow(",
|
||||
"if (_sceneFrameProduct is null || LegacyPartitionDiagnosticsEnabled)",
|
||||
"InteriorEntityPartition.Partition(");
|
||||
|
||||
Assert.Contains(
|
||||
"RenderFrameRouteOwnerSelector.Replace(",
|
||||
source,
|
||||
StringComparison.Ordinal);
|
||||
Assert.Contains(
|
||||
"RenderFrameRouteOwnerSelector.ExceptRoute(",
|
||||
source,
|
||||
StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Extracted_contracts_retain_no_window_callbacks_or_visibility_owner()
|
||||
{
|
||||
|
|
@ -360,61 +298,61 @@ public sealed class RetailPViewPassExecutorTests
|
|||
[Fact]
|
||||
public void Concrete_executor_forwards_frame_reset_and_brackets_terrain_diagnostics()
|
||||
{
|
||||
string source = ExecutorClassSource();
|
||||
string begin = MethodBody(source, "public void BeginFrame()");
|
||||
Assert.Contains("_particleClassifications.BeginFrame();", begin);
|
||||
MethodInfo begin = typeof(RetailPViewPassExecutor).GetMethod(
|
||||
nameof(RetailPViewPassExecutor.BeginFrame))!;
|
||||
IReadOnlyList<CompiledCall> beginCalls = CompiledCallGraph.Read(begin);
|
||||
Assert.True(
|
||||
CompiledCallGraph.IndexOf(
|
||||
beginCalls,
|
||||
typeof(RetailPViewParticleClassifications),
|
||||
nameof(RetailPViewParticleClassifications.BeginFrame)) >= 0);
|
||||
|
||||
string landscape = MethodBody(source, "public void DrawLandscapeSlice(");
|
||||
AssertAppearsInOrder(
|
||||
landscape,
|
||||
"_terrainDiagnostics.Begin();",
|
||||
"_terrain?.Draw(",
|
||||
"_terrainDiagnostics.Complete();");
|
||||
MethodInfo landscape = typeof(RetailPViewPassExecutor).GetMethod(
|
||||
nameof(RetailPViewPassExecutor.DrawLandscapeSlice))!;
|
||||
IReadOnlyList<CompiledCall> landscapeCalls = CompiledCallGraph.Read(landscape);
|
||||
int diagnosticsBegin = RequiredCallIndex(
|
||||
landscapeCalls,
|
||||
typeof(TerrainDrawDiagnosticsController),
|
||||
nameof(TerrainDrawDiagnosticsController.Begin));
|
||||
int terrainDraw = RequiredCallIndex(
|
||||
landscapeCalls,
|
||||
typeof(TerrainModernRenderer),
|
||||
nameof(TerrainModernRenderer.Draw));
|
||||
int diagnosticsComplete = RequiredCallIndex(
|
||||
landscapeCalls,
|
||||
typeof(TerrainDrawDiagnosticsController),
|
||||
nameof(TerrainDrawDiagnosticsController.Complete));
|
||||
|
||||
Assert.DoesNotContain("Console.WriteLine", source);
|
||||
Assert.DoesNotContain("Console.WriteLine", RendererSource());
|
||||
Assert.True(diagnosticsBegin < terrainDraw);
|
||||
Assert.True(terrainDraw < diagnosticsComplete);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GameWindow_composes_one_executor_instead_of_a_draw_callback_bag()
|
||||
{
|
||||
string source = File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
"src",
|
||||
"AcDream.App",
|
||||
"Composition",
|
||||
"FrameRootComposition.cs"));
|
||||
MethodInfo compose = typeof(FrameRootCompositionPhase).GetMethod(
|
||||
"ComposeCore",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic)!;
|
||||
IReadOnlyList<CompiledCall> calls = CompiledCallGraph.Read(compose);
|
||||
|
||||
Assert.Contains("new RetailPViewPassExecutor(", source);
|
||||
Assert.Contains("new WorldScenePViewRenderer(", source);
|
||||
Assert.DoesNotContain("new AcDream.App.Rendering.RetailPViewFrameInput", source);
|
||||
Assert.DoesNotContain("RetailPViewDrawContext", source);
|
||||
Assert.DoesNotContain("DrawLandscapeSlice =", source);
|
||||
Assert.DoesNotContain("DrawExitPortalMasks =", source);
|
||||
}
|
||||
int executor = RequiredCallIndex(
|
||||
calls,
|
||||
typeof(RetailPViewPassExecutor),
|
||||
".ctor");
|
||||
int renderer = RequiredCallIndex(
|
||||
calls,
|
||||
typeof(WorldScenePViewRenderer),
|
||||
".ctor");
|
||||
|
||||
private static string RendererSource() => File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
"src",
|
||||
"AcDream.App",
|
||||
"Rendering",
|
||||
"RetailPViewRenderer.cs"));
|
||||
|
||||
private static string ExecutorSource() => File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
"src",
|
||||
"AcDream.App",
|
||||
"Rendering",
|
||||
"RetailPViewPassExecutor.cs"));
|
||||
|
||||
private static string ExecutorClassSource()
|
||||
{
|
||||
string source = ExecutorSource();
|
||||
int start = source.IndexOf(
|
||||
"internal sealed class RetailPViewPassExecutor",
|
||||
StringComparison.Ordinal);
|
||||
Assert.True(start >= 0, "Missing concrete RetailPViewPassExecutor.");
|
||||
return source[start..];
|
||||
Assert.True(executor < renderer);
|
||||
Assert.Single(
|
||||
calls,
|
||||
call => call.Target.DeclaringType == typeof(RetailPViewPassExecutor)
|
||||
&& call.Target.Name == ".ctor");
|
||||
Assert.Single(
|
||||
calls,
|
||||
call => call.Target.DeclaringType == typeof(WorldScenePViewRenderer)
|
||||
&& call.Target.Name == ".ctor");
|
||||
}
|
||||
|
||||
private static RetailPViewFrameInput Frame(
|
||||
|
|
@ -565,23 +503,6 @@ public sealed class RetailPViewPassExecutorTests
|
|||
ParentCellId = parentCellId,
|
||||
};
|
||||
|
||||
private static string MethodBody(string source, string signature)
|
||||
{
|
||||
int start = source.IndexOf(signature, StringComparison.Ordinal);
|
||||
Assert.True(start >= 0, $"Missing method: {signature}");
|
||||
int open = source.IndexOf('{', start);
|
||||
int depth = 0;
|
||||
for (int index = open; index < source.Length; index++)
|
||||
{
|
||||
if (source[index] == '{')
|
||||
depth++;
|
||||
else if (source[index] == '}' && --depth == 0)
|
||||
return source[start..(index + 1)];
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Unterminated method: {signature}");
|
||||
}
|
||||
|
||||
private static void AssertAppearsInOrder(string source, params string[] needles)
|
||||
{
|
||||
int cursor = -1;
|
||||
|
|
@ -593,17 +514,14 @@ public sealed class RetailPViewPassExecutorTests
|
|||
}
|
||||
}
|
||||
|
||||
private static string FindRepoRoot()
|
||||
private static int RequiredCallIndex(
|
||||
IReadOnlyList<CompiledCall> calls,
|
||||
Type declaringType,
|
||||
string methodName)
|
||||
{
|
||||
DirectoryInfo? directory = new(AppContext.BaseDirectory);
|
||||
while (directory is not null)
|
||||
{
|
||||
if (File.Exists(Path.Combine(directory.FullName, "AcDream.slnx")))
|
||||
return directory.FullName;
|
||||
directory = directory.Parent;
|
||||
}
|
||||
|
||||
throw new DirectoryNotFoundException("Could not find AcDream.slnx.");
|
||||
int index = CompiledCallGraph.IndexOf(calls, declaringType, methodName);
|
||||
Assert.True(index >= 0, $"Missing compiled call: {declaringType.Name}.{methodName}");
|
||||
return index;
|
||||
}
|
||||
|
||||
private sealed class DictionaryCellSource(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue