Give terrain, sky, retained UI, portal preparation, and the update/render frame pair explicit single owners. Make shader, texture, text, bindless, and GL construction prefixes checked and retryable so partial failure cannot lose or replay resource ownership. Co-authored-by: Codex <codex@openai.com>
67 lines
1.8 KiB
C#
67 lines
1.8 KiB
C#
using AcDream.App.Update;
|
|
|
|
namespace AcDream.App.Rendering;
|
|
|
|
internal interface IGameUpdateFrameRoot
|
|
{
|
|
void Tick(UpdateFrameInput input);
|
|
}
|
|
|
|
internal interface IGameRenderFrameRoot
|
|
{
|
|
RenderFrameOutcome Render(RenderFrameInput input);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sole atomic publication point for the current update/render frame pair.
|
|
/// Native callbacks are deliberately inert before publication and after
|
|
/// withdrawal so a partial load or converging shutdown cannot enter half a
|
|
/// frame graph.
|
|
/// </summary>
|
|
internal sealed class GameFrameGraphSlot
|
|
{
|
|
private sealed record FrameGraphPair(
|
|
IGameUpdateFrameRoot Update,
|
|
IGameRenderFrameRoot Render);
|
|
|
|
private FrameGraphPair? _pair;
|
|
|
|
public bool IsPublished => Volatile.Read(ref _pair) is not null;
|
|
|
|
public void Publish(IGameUpdateFrameRoot update, IGameRenderFrameRoot render)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(update);
|
|
ArgumentNullException.ThrowIfNull(render);
|
|
var pair = new FrameGraphPair(update, render);
|
|
if (Interlocked.CompareExchange(ref _pair, pair, null) is not null)
|
|
throw new InvalidOperationException("A game frame graph is already published.");
|
|
}
|
|
|
|
public bool Tick(UpdateFrameInput input)
|
|
{
|
|
FrameGraphPair? pair = Volatile.Read(ref _pair);
|
|
if (pair is null)
|
|
return false;
|
|
|
|
pair.Update.Tick(input);
|
|
return true;
|
|
}
|
|
|
|
public bool Render(RenderFrameInput input, out RenderFrameOutcome outcome)
|
|
{
|
|
FrameGraphPair? pair = Volatile.Read(ref _pair);
|
|
if (pair is null)
|
|
{
|
|
outcome = default;
|
|
return false;
|
|
}
|
|
|
|
outcome = pair.Render.Render(input);
|
|
return true;
|
|
}
|
|
|
|
public void Withdraw()
|
|
{
|
|
Interlocked.Exchange(ref _pair, null);
|
|
}
|
|
}
|