feat(render): implement Campaign AR and terrain fidelity
This commit is contained in:
parent
99cf26e00c
commit
7a5f96ede5
368 changed files with 50611 additions and 950 deletions
|
|
@ -35,6 +35,43 @@ public sealed class GameWindow :
|
|||
System.Diagnostics.Stopwatch.GetTimestamp()
|
||||
/ (double)System.Diagnostics.Stopwatch.Frequency;
|
||||
|
||||
internal static WindowOptions CreateStartupWindowOptions(
|
||||
bool exactAutomationFramebuffer,
|
||||
string persistedResolution,
|
||||
bool useVSync)
|
||||
{
|
||||
WindowOptions defaults = WindowOptions.DefaultVulkan;
|
||||
Vector2D<int> size = new(1280, 720);
|
||||
WindowBorder border = defaults.WindowBorder;
|
||||
if (exactAutomationFramebuffer)
|
||||
{
|
||||
if (!SilkRuntimeDisplayWindowTarget.TryParseResolution(
|
||||
persistedResolution,
|
||||
out int width,
|
||||
out int height))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Exact automation framebuffer requires a valid persisted resolution.");
|
||||
}
|
||||
size = new Vector2D<int>(width, height);
|
||||
border = WindowBorder.Hidden;
|
||||
}
|
||||
|
||||
return defaults with
|
||||
{
|
||||
Size = size,
|
||||
Title = "acdream — Vulkan",
|
||||
VSync = useVSync,
|
||||
WindowBorder = border,
|
||||
// A desktop-sized borderless automation window must stay hidden,
|
||||
// not iconified. Windows throttles/occludes an iconified GLFW
|
||||
// surface, which prevents the performance gate from collecting a
|
||||
// complete rolling sample window. Ordinary launches retain the
|
||||
// Silk default visibility.
|
||||
IsVisible = !exactAutomationFramebuffer,
|
||||
};
|
||||
}
|
||||
|
||||
private readonly AcDream.App.RuntimeOptions _options;
|
||||
// Campaign LA slice LA1: no-op instance when --session-config didn't
|
||||
// configure a statusFile (or the env-var launch path was used at all).
|
||||
|
|
@ -57,6 +94,13 @@ public sealed class GameWindow :
|
|||
// loop!" and would otherwise bury whatever exception actually wounded
|
||||
// the loop). See docs/ISSUES.md #343.
|
||||
private bool _renderLoopArmed;
|
||||
// Silk may invoke Closing synchronously from IWindow.Close during Update,
|
||||
// then still invoke Render once before its loop exits. Teardown cannot run
|
||||
// from that Closing callback: it would dispose the scene while the cached
|
||||
// render delegate is still eligible to execute. Latch the edge, skip that
|
||||
// terminal render, and close the ownership graph after Run returns.
|
||||
private bool _nativeCloseRequested;
|
||||
private bool _nativeRunReturned;
|
||||
private SilkWindowCallbackBinding? _windowCallbacks;
|
||||
private GameWindowGraphics? _graphics;
|
||||
// Campaign V slice V6h: borrowed, not owned — _graphics owns the context and
|
||||
|
|
@ -414,6 +458,8 @@ public sealed class GameWindow :
|
|||
private readonly AcDream.App.UI.RetailUiRuntimeLease _retailUiLease = new();
|
||||
private InteractionUiLateBindings? _interactionUiLateBindings;
|
||||
private readonly DeferredRenderFrameDiagnosticsSource _uiFrameDiagnostics = new();
|
||||
private readonly AcDream.App.Rendering.Packs.DeferredRenderPackDiagnosticsSource
|
||||
_renderPackDiagnostics = new();
|
||||
private readonly AcDream.App.Combat.CombatAttackOperationsSlot
|
||||
_combatAttackOperations = new();
|
||||
private readonly AcDream.App.Combat.RuntimeCombatTargetOperationsSlot
|
||||
|
|
@ -449,6 +495,7 @@ public sealed class GameWindow :
|
|||
private AcDream.App.Rendering.ChargenPreviewController? _summaryPreviewController;
|
||||
// Phase D.2b Task 9 — plugin UI registrations buffered before OnLoad; drained in OnLoad.
|
||||
private readonly AcDream.App.Plugins.BufferedUiRegistry? _uiRegistry;
|
||||
private readonly AcDream.App.Plugins.BufferedRenderPackRegistry? _renderPackRegistry;
|
||||
private AcDream.App.Plugins.GraphicalPluginSession? _pluginSession;
|
||||
// Campaign V slice V11 deleted the ImGui developer-tools frontend along
|
||||
// with the OpenGL backend it required, so no host ever composes a
|
||||
|
|
@ -636,7 +683,8 @@ public sealed class GameWindow :
|
|||
WorldEvents worldEvents,
|
||||
AcDream.App.Plugins.BufferedUiRegistry? uiRegistry,
|
||||
GraphicalHostPlatformServices platformServices,
|
||||
AcDream.App.Plugins.AppAutomationSurface? automation = null)
|
||||
AcDream.App.Plugins.AppAutomationSurface? automation = null,
|
||||
AcDream.App.Plugins.BufferedRenderPackRegistry? renderPackRegistry = null)
|
||||
{
|
||||
_options = options ?? throw new System.ArgumentNullException(nameof(options));
|
||||
_automation = automation;
|
||||
|
|
@ -724,6 +772,7 @@ public sealed class GameWindow :
|
|||
characterOptionValue: _runtime.CharacterOwner.Options.GetOptionBit);
|
||||
_animationDiagnostics = AnimationPresentationDiagnostics.FromEnvironment();
|
||||
_uiRegistry = uiRegistry;
|
||||
_renderPackRegistry = renderPackRegistry;
|
||||
_animatedEntities = new LiveEntityAnimationRuntimeView<LiveEntityAnimationState>(
|
||||
_liveEntityRuntimeSlot);
|
||||
// #184 Slice 2a: the extracted per-remote DR tick. Its stateful
|
||||
|
|
@ -799,12 +848,10 @@ public sealed class GameWindow :
|
|||
// attribute there — both are attachment properties the RHI device
|
||||
// configures instead. The raw-GL window options this used to fork to
|
||||
// were deleted at Campaign V slice V11.
|
||||
var options = WindowOptions.DefaultVulkan with
|
||||
{
|
||||
Size = new Vector2D<int>(1280, 720),
|
||||
Title = "acdream — Vulkan",
|
||||
VSync = startupPacing.UseVSync,
|
||||
};
|
||||
WindowOptions options = CreateStartupWindowOptions(
|
||||
_options.ExactAutomationFramebuffer,
|
||||
startup.Display.Resolution,
|
||||
startupPacing.UseVSync);
|
||||
_startupPacing = startupPacing;
|
||||
_startupQuality = startup.Quality;
|
||||
|
||||
|
|
@ -833,6 +880,8 @@ public sealed class GameWindow :
|
|||
try
|
||||
{
|
||||
_window.Run();
|
||||
_nativeRunReturned = true;
|
||||
CompleteShutdown(releaseNativeWindow: false);
|
||||
}
|
||||
catch (Exception failure)
|
||||
{
|
||||
|
|
@ -1359,7 +1408,10 @@ public sealed class GameWindow :
|
|||
_localPlayerMode,
|
||||
_chaseCameraInput,
|
||||
_pointerPosition,
|
||||
_renderDiagnosticLog),
|
||||
_renderDiagnosticLog,
|
||||
_options.InitialOrbitDistanceMeters,
|
||||
_options.InitialOrbitYawDegrees,
|
||||
_options.InitialOrbitPitchDegrees),
|
||||
this).Compose(platformResult),
|
||||
(platformResult, hostInputCamera) =>
|
||||
new ContentEffectsAudioCompositionPhase(
|
||||
|
|
@ -1387,7 +1439,11 @@ public sealed class GameWindow :
|
|||
new SilkRuntimeDisplayWindowTarget(_window!),
|
||||
_displayFramePacing,
|
||||
hostInputCamera.CameraController,
|
||||
contentEffectsAudio.Audio?.Engine)))
|
||||
contentEffectsAudio.Audio?.Engine))
|
||||
{
|
||||
RenderPacks = _renderPackRegistry,
|
||||
GpuDevice = hostInputCamera.GpuDevice,
|
||||
})
|
||||
.Compose(platformResult, hostInputCamera, contentEffectsAudio),
|
||||
(platformResult, contentEffectsAudio, settingsDevTools) =>
|
||||
{
|
||||
|
|
@ -1461,7 +1517,9 @@ public sealed class GameWindow :
|
|||
Console.WriteLine,
|
||||
hostInputCamera.GpuDevice,
|
||||
hostInputCamera.GpuFrameLifetime,
|
||||
() => WorldTime.CurrentCalendar),
|
||||
() => WorldTime.CurrentCalendar,
|
||||
settingsDevTools.RenderPacks,
|
||||
_renderPackDiagnostics.CaptureDiagnostics),
|
||||
_retailUiLease,
|
||||
this).Compose(
|
||||
platformResult,
|
||||
|
|
@ -1519,7 +1577,8 @@ public sealed class GameWindow :
|
|||
DevFrameDiagnostics: null,
|
||||
_uiFrameDiagnostics,
|
||||
Console.WriteLine,
|
||||
compositionToast),
|
||||
compositionToast,
|
||||
_renderPackDiagnostics),
|
||||
this).Compose(
|
||||
platformResult,
|
||||
hostInputCamera,
|
||||
|
|
@ -1631,7 +1690,8 @@ public sealed class GameWindow :
|
|||
_animatedEntities,
|
||||
_updateFrameClock,
|
||||
_frameGraphs,
|
||||
Console.WriteLine),
|
||||
Console.WriteLine,
|
||||
_renderPackDiagnostics),
|
||||
this).Compose(
|
||||
platformResult,
|
||||
hostInputCamera,
|
||||
|
|
@ -1672,6 +1732,11 @@ public sealed class GameWindow :
|
|||
// #343: see OnUpdate above — armed on entry, cleared on every normal
|
||||
// exit path below, left stuck true if anything here throws.
|
||||
_renderLoopArmed = true;
|
||||
if (_nativeCloseRequested)
|
||||
{
|
||||
_renderLoopArmed = false;
|
||||
return;
|
||||
}
|
||||
Vector2D<int> size = _window!.Size;
|
||||
// Campaign V slice V6h: swapchain currency is the one piece of
|
||||
// presentation the RHI contract deliberately leaves to the host (plan
|
||||
|
|
@ -1735,12 +1800,23 @@ public sealed class GameWindow :
|
|||
|
||||
private void CompleteShutdown(bool releaseNativeWindow)
|
||||
{
|
||||
// IWindow.Close can raise Closing synchronously from Update and Silk
|
||||
// can still issue one cached Render callback before Run returns. Keep
|
||||
// Closing as the one narrow shutdown edge, but do not release frame
|
||||
// owners until the native loop has actually returned. OnRender sees
|
||||
// this latch and makes that terminal callback inert.
|
||||
if (!releaseNativeWindow && !_nativeRunReturned)
|
||||
{
|
||||
_nativeCloseRequested = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_lifetime.HasShutdownRoots)
|
||||
{
|
||||
// Campaign LA slice LA1: capture BEFORE the shutdown roots run —
|
||||
// by the time teardown completes, IsInWorld is always false
|
||||
// regardless of whether a real session was ever connected.
|
||||
// OnClosing() and Dispose() both funnel through this method;
|
||||
// post-Run shutdown and Dispose() both funnel through this method;
|
||||
// HasShutdownRoots's own guard means this fires exactly once,
|
||||
// from whichever of the two reaches it first.
|
||||
if (_runtime.Session.IsInWorld)
|
||||
|
|
@ -1754,7 +1830,7 @@ public sealed class GameWindow :
|
|||
if (report.Status == GameWindowLifetimeStatus.Complete)
|
||||
{
|
||||
// "exited" = terminal — only the true Dispose() call (not the
|
||||
// OnClosing() native-window-close-request pass) represents the
|
||||
// post-Run native-window-close-request pass) represents the
|
||||
// process actually being done.
|
||||
if (releaseNativeWindow)
|
||||
ReportExited(report);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue