Add reservoir baseline comparison mode
This commit is contained in:
parent
0e92ce2a8f
commit
5e4b9eea00
18 changed files with 144 additions and 20 deletions
Binary file not shown.
|
|
@ -370,6 +370,13 @@ and conservative object support. Exact client SDF distance re-evaluation
|
|||
remains producer-owned work rather than a generic postprocess authority.
|
||||
Debug modes expose selected coordinates, support footprint/domain kind, and
|
||||
shift/rejection state from the same row-3 layer consumed by presentation.
|
||||
The renderer also exposes a field-reservoir mode switch for comparison: native
|
||||
mode enables domain validity, support overlap, and producer replay during
|
||||
temporal reuse, while texel-baseline mode keeps the same rows but disables those
|
||||
native-domain gates. The first paired capture set
|
||||
\texttt{reservoir-compare-20260529-231904-*} changed 10.8208\% of final-frame
|
||||
pixels between modes. This proves the comparison switch is live; it is not yet
|
||||
a temporal leakage or ghosting metric.
|
||||
|
||||
\section{Required Evaluation}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -654,7 +654,13 @@ producer-keyed manifest/source table to re-evaluate selected logical
|
|||
column/curve coordinates in the current frame, and SDF object-hit replay carries
|
||||
the previous selected hit through object motion before validating current
|
||||
ray/travel/support. The next proof cuts are exact producer SDF replay, measured
|
||||
rejection precision, and baseline/native-domain captures.
|
||||
temporal leakage/ghosting, and measured rejection precision.
|
||||
Those captures now have an explicit comparison switch: native mode enables the
|
||||
domain validity, support-overlap, and producer-replay gates, while texel-baseline
|
||||
mode uses the same row ABI but disables those native-domain gates during
|
||||
temporal reuse. The first paired Fensalir capture set
|
||||
\texttt{reservoir-compare-20260529-231904-*} produced a 10.8208\% final-frame
|
||||
pixel delta. That is a live-switch check, not a quality claim.
|
||||
The system has cut the false ``nearest-travel-minus-coverage'' priority owner
|
||||
and the side-cache temptation.
|
||||
|
||||
|
|
|
|||
|
|
@ -493,8 +493,12 @@ Work packet:
|
|||
reconstructed from stored selected UV/travel, carried through object center
|
||||
motion, and checked against the current camera ray/travel/support before
|
||||
reuse can merge them.
|
||||
8. Next: capture the occluded-spectrum-tubes scene in baseline and native-domain
|
||||
modes.
|
||||
8. Done: add an explicit field-reservoir mode switch and capture paired
|
||||
native-domain versus texel-baseline outputs. The first comparison set lives
|
||||
under `artifacts/fensalir-captures/reservoir-compare-20260529-231904-*`.
|
||||
Native versus baseline changed 10.8208% of final-frame pixels, 0.0165% of
|
||||
rejection-debug pixels, and 0.2976% of shift-debug pixels. That proves the
|
||||
switch is live; it is not yet a quality metric.
|
||||
|
||||
Required verification:
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ param(
|
|||
[int]$Height = 720,
|
||||
[int]$ReadyFrames = 8,
|
||||
[int]$RenderDebugMode = -1,
|
||||
[ValidateSet("native", "baseline")]
|
||||
[string]$FieldReservoirMode = "native",
|
||||
[int]$RetainSlots = 4,
|
||||
[int]$TimeoutSeconds = 120
|
||||
)
|
||||
|
|
@ -55,6 +57,9 @@ $arguments = @(
|
|||
if ($RenderDebugMode -ge 0) {
|
||||
$arguments += @("--render-debug", $RenderDebugMode)
|
||||
}
|
||||
if ($FieldReservoirMode -eq "baseline") {
|
||||
$arguments += @("--field-reservoir-mode", "baseline")
|
||||
}
|
||||
|
||||
$env:AQUARIUM_HEADLESS_READY_FRAMES = [string][Math]::Max(1, $ReadyFrames)
|
||||
$process = Start-Process -FilePath $exePath -ArgumentList $arguments -NoNewWindow -PassThru -RedirectStandardOutput $stdoutLog -RedirectStandardError $stderrLog
|
||||
|
|
|
|||
|
|
@ -39,5 +39,9 @@ public interface IAquariumRuntimeFactory
|
|||
IAquariumRuntime Create(AquariumRuntimeOptions options);
|
||||
}
|
||||
|
||||
public readonly record struct AquariumRuntimeOptions(bool Headless, string? CultCachePath, int? RenderDebugModeOverride = null);
|
||||
public readonly record struct AquariumRuntimeOptions(
|
||||
bool Headless,
|
||||
string? CultCachePath,
|
||||
int? RenderDebugModeOverride = null,
|
||||
int? FieldReservoirModeOverride = null);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,13 @@ public readonly record struct GraphicsSettings(
|
|||
int RenderDebugMode,
|
||||
float SceneExposure,
|
||||
float BloomIntensity,
|
||||
float BloomVeilIntensity)
|
||||
float BloomVeilIntensity,
|
||||
int FieldReservoirMode)
|
||||
{
|
||||
public const int MinRenderDebugMode = 0;
|
||||
public const int MaxRenderDebugMode = 18;
|
||||
public const int FieldReservoirModeNativeDomain = 0;
|
||||
public const int FieldReservoirModeTexelBaseline = 1;
|
||||
public const float MinSceneExposure = 0.02f;
|
||||
public const float MaxSceneExposure = 1.2f;
|
||||
public const float MinBloomIntensity = 0.0f;
|
||||
|
|
@ -19,7 +22,8 @@ public readonly record struct GraphicsSettings(
|
|||
RenderDebugMode: 0,
|
||||
SceneExposure: 0.16f,
|
||||
BloomIntensity: 0.072f,
|
||||
BloomVeilIntensity: 0.014f);
|
||||
BloomVeilIntensity: 0.014f,
|
||||
FieldReservoirMode: FieldReservoirModeNativeDomain);
|
||||
|
||||
public GraphicsSettings Normalized()
|
||||
{
|
||||
|
|
@ -27,6 +31,7 @@ public readonly record struct GraphicsSettings(
|
|||
Math.Clamp(RenderDebugMode, MinRenderDebugMode, MaxRenderDebugMode),
|
||||
Math.Clamp(SceneExposure, MinSceneExposure, MaxSceneExposure),
|
||||
Math.Clamp(BloomIntensity, MinBloomIntensity, MaxBloomIntensity),
|
||||
Math.Clamp(BloomVeilIntensity, MinBloomVeilIntensity, MaxBloomVeilIntensity));
|
||||
Math.Clamp(BloomVeilIntensity, MinBloomVeilIntensity, MaxBloomVeilIntensity),
|
||||
Math.Clamp(FieldReservoirMode, FieldReservoirModeNativeDomain, FieldReservoirModeTexelBaseline));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,11 @@ public static class AquariumHost
|
|||
{
|
||||
public static int Run(string[] args)
|
||||
{
|
||||
var runtimeOptions = new AquariumRuntimeOptions(ParseHeadless(args), ParseCachePath(args), ParseRenderDebugMode(args));
|
||||
var runtimeOptions = new AquariumRuntimeOptions(
|
||||
ParseHeadless(args),
|
||||
ParseCachePath(args),
|
||||
ParseRenderDebugMode(args),
|
||||
ParseFieldReservoirMode(args));
|
||||
using var runtimeLoader = new ClientRuntimeLoader(runtimeOptions, ParseClientAssemblyPath(args), ParseClientReloadPointerPath(args));
|
||||
var runtime = runtimeLoader.Load();
|
||||
if (runtimeOptions.RenderDebugModeOverride is { } renderDebugModeOverride)
|
||||
|
|
@ -21,6 +25,13 @@ public static class AquariumHost
|
|||
RenderDebugMode = renderDebugModeOverride,
|
||||
}).Normalized();
|
||||
}
|
||||
if (runtimeOptions.FieldReservoirModeOverride is { } fieldReservoirModeOverride)
|
||||
{
|
||||
runtime.GraphicsSettings = (runtime.GraphicsSettings with
|
||||
{
|
||||
FieldReservoirMode = fieldReservoirModeOverride,
|
||||
}).Normalized();
|
||||
}
|
||||
var input = new InputState();
|
||||
var headlessSize = ParseHeadlessSize(args);
|
||||
var width = runtime.Options.Headless ? headlessSize.Width : 1280;
|
||||
|
|
@ -264,6 +275,30 @@ public static class AquariumHost
|
|||
: null;
|
||||
}
|
||||
|
||||
private static int? ParseFieldReservoirMode(IReadOnlyCollection<string> args)
|
||||
{
|
||||
var values = args.ToArray();
|
||||
for (var index = 0; index < values.Length - 1; index++)
|
||||
{
|
||||
if (string.Equals(values[index], "--field-reservoir-mode", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return ParseFieldReservoirModeValue(values[index + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
return ParseFieldReservoirModeValue(Environment.GetEnvironmentVariable("AQUARIUM_FIELD_RESERVOIR_MODE"));
|
||||
}
|
||||
|
||||
private static int? ParseFieldReservoirModeValue(string? value)
|
||||
{
|
||||
return value?.Trim().ToLowerInvariant() switch
|
||||
{
|
||||
"native" or "native-domain" or "0" => GraphicsSettings.FieldReservoirModeNativeDomain,
|
||||
"baseline" or "texel" or "texel-baseline" or "1" => GraphicsSettings.FieldReservoirModeTexelBaseline,
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
private static int ParsePositiveIntArgument(IReadOnlyCollection<string> args, string name, string environmentName, int fallback)
|
||||
{
|
||||
var values = args.ToArray();
|
||||
|
|
|
|||
|
|
@ -139,6 +139,11 @@ public sealed class D3D12Renderer : IAquariumRenderer
|
|||
new(17, "Reservoir Support"),
|
||||
new(18, "Reservoir Shift"),
|
||||
];
|
||||
private static readonly DebugUi.DebugUiOption[] FieldReservoirModeOptions =
|
||||
[
|
||||
new(GraphicsSettings.FieldReservoirModeNativeDomain, "Native Domain"),
|
||||
new(GraphicsSettings.FieldReservoirModeTexelBaseline, "Texel Baseline"),
|
||||
];
|
||||
private static readonly DebugUi.DebugUiOption[] SynthPresetOptions = AquaSynth.Dsl.BuiltInScripts.ReferenceScripts()
|
||||
.Select((preset, index) => new DebugUi.DebugUiOption(index, $"{preset.Family}/{preset.Name}"))
|
||||
.ToArray();
|
||||
|
|
@ -572,6 +577,7 @@ public sealed class D3D12Renderer : IAquariumRenderer
|
|||
.Section("View", () => activeDebugTab == 0)
|
||||
.Options("Render Debug", () => RenderDebugMode, value => RenderDebugMode = Math.Clamp(value, GraphicsSettings.MinRenderDebugMode, GraphicsSettings.MaxRenderDebugMode), RenderDebugOptions, "Selects the active renderer debug view.", () => activeDebugTab == 0)
|
||||
.Button("Reset View", () => RenderDebugMode = 0, "Returns to the final presented frame.", () => activeDebugTab == 0)
|
||||
.Options("Reservoir Mode", () => settings.FieldReservoirMode, value => settings = (settings with { FieldReservoirMode = Math.Clamp(value, GraphicsSettings.FieldReservoirModeNativeDomain, GraphicsSettings.FieldReservoirModeTexelBaseline) }).Normalized(), FieldReservoirModeOptions, "Selects native-domain validation or texel-owned baseline reuse.", () => activeDebugTab == 0)
|
||||
.Section("HDR", () => activeDebugTab == 0)
|
||||
.Slider("Exposure", () => settings.SceneExposure, value => settings = (settings with { SceneExposure = Math.Clamp(value, GraphicsSettings.MinSceneExposure, GraphicsSettings.MaxSceneExposure) }).Normalized(), GraphicsSettings.MinSceneExposure, GraphicsSettings.MaxSceneExposure, "0.###", "Manual scene exposure before display transform.", () => activeDebugTab == 0)
|
||||
.Slider("Bloom Intensity", () => settings.BloomIntensity, value => settings = (settings with { BloomIntensity = Math.Clamp(value, GraphicsSettings.MinBloomIntensity, GraphicsSettings.MaxBloomIntensity) }).Normalized(), GraphicsSettings.MinBloomIntensity, GraphicsSettings.MaxBloomIntensity, "0.###", "Strength of pre-tonemap bloom energy.", () => activeDebugTab == 0)
|
||||
|
|
@ -907,7 +913,7 @@ public sealed class D3D12Renderer : IAquariumRenderer
|
|||
cameraFrustum.Right / cameraFrustum.Near,
|
||||
cameraFrustum.Bottom / cameraFrustum.Near,
|
||||
cameraFrustum.Top / cameraFrustum.Near),
|
||||
new Vector4(cameraFrustum.Near, cameraFrustum.Far, 0.0f, 0.0f),
|
||||
new Vector4(cameraFrustum.Near, cameraFrustum.Far, settings.FieldReservoirMode, 0.0f),
|
||||
new Vector4(
|
||||
acousticConstraintCount,
|
||||
gpuFusionPointCount,
|
||||
|
|
|
|||
|
|
@ -116,6 +116,12 @@ static const float FIELD_ID_TUBE_FIELD_BASE = 5100.0;
|
|||
static const float FIELD_ID_TUBE_FIELD_MAX = 10000.0;
|
||||
static const int AQUARIUM_SDF_OBJECT_CAPACITY = 64;
|
||||
static const float MAX_HISTORY_AGE = 32.0;
|
||||
|
||||
bool nativeDomainReservoirEnabled()
|
||||
{
|
||||
return cameraFrustumZ.z < 0.5;
|
||||
}
|
||||
|
||||
VertexOut FullscreenTriangleVS(uint vertexId : SV_VertexID)
|
||||
{
|
||||
float2 uv = float2((vertexId << 1) & 2, vertexId & 2);
|
||||
|
|
@ -716,14 +722,21 @@ float reservoirTemporalValidationWeight(
|
|||
: 1.0 - smoothstep(0.10, 0.50, abs(saturate(previousSample.control.x) - saturate(currentSample.control.x)));
|
||||
float detailWeight = 1.0 - smoothstep(0.08, 0.45, abs(saturate(previousSample.control.z) - saturate(currentSample.control.z)));
|
||||
float confidenceWeight = lerp(0.45, 1.0, min(reservoirSampleConfidence(currentSample), reservoirSampleConfidence(previousSample)));
|
||||
float domainWeight = reservoirSampleDomainValidity(currentSample) * reservoirSampleDomainValidity(previousSample);
|
||||
float supportOverlap = fieldReservoirDomainSupportOverlap(currentSample, previousSample, dimensions);
|
||||
bool useNativeDomain = nativeDomainReservoirEnabled();
|
||||
float domainWeight = useNativeDomain
|
||||
? reservoirSampleDomainValidity(currentSample) * reservoirSampleDomainValidity(previousSample)
|
||||
: 1.0;
|
||||
float supportOverlap = useNativeDomain
|
||||
? fieldReservoirDomainSupportOverlap(currentSample, previousSample, dimensions)
|
||||
: 1.0;
|
||||
uint2 currentPixel = (uint2)pixelFromUv(currentSample.domainSample.xy);
|
||||
float replayWeight = fieldReservoirSampleRequiresExplicitMotion(currentSample)
|
||||
float replayWeight = !useNativeDomain
|
||||
? 1.0
|
||||
: (fieldReservoirSampleRequiresExplicitMotion(currentSample)
|
||||
? tubeFieldReplayValidationWeight(currentSample, previousSample, currentPixel)
|
||||
: (fieldReservoirSampleIsSdfObject(currentSample)
|
||||
? sdfObjectReplayValidationWeight(currentSample, previousSample, currentPixel)
|
||||
: 1.0);
|
||||
: 1.0));
|
||||
return travelWeight * fieldWeight * normalWeight * colorWeight * coverageWeight * coverageContinuityWeight * detailWeight * confidenceWeight * domainWeight * supportOverlap * replayWeight;
|
||||
}
|
||||
|
||||
|
|
@ -754,6 +767,11 @@ float reservoirTemporalRejectionCode(
|
|||
return 6.0;
|
||||
}
|
||||
|
||||
if (!nativeDomainReservoirEnabled())
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
if (!fieldReservoirDomainStateValid(previousSample) || !fieldReservoirDomainStateValid(currentSample))
|
||||
{
|
||||
return 7.0;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,12 @@ public sealed class FensalirRuntime : IAquariumRuntime
|
|||
|
||||
public AquariumRuntimeOptions Options { get; private set; }
|
||||
|
||||
public GraphicsSettings GraphicsSettings { get; set; } = new(0, 1.04f, 0.52f, 0.08f);
|
||||
public GraphicsSettings GraphicsSettings { get; set; } = new(
|
||||
0,
|
||||
1.04f,
|
||||
0.52f,
|
||||
0.08f,
|
||||
GraphicsSettings.FieldReservoirModeNativeDomain);
|
||||
|
||||
public AquariumRenderPlan RenderPlan { get; } = FensalirRenderPlan.Create();
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,12 @@ public sealed class ZyphosRuntime : IAquariumRuntime
|
|||
|
||||
public AquariumRuntimeOptions Options { get; private set; }
|
||||
|
||||
public GraphicsSettings GraphicsSettings { get; set; } = new(0, 1.08f, 0.32f, 0.05f);
|
||||
public GraphicsSettings GraphicsSettings { get; set; } = new(
|
||||
0,
|
||||
1.08f,
|
||||
0.32f,
|
||||
0.05f,
|
||||
GraphicsSettings.FieldReservoirModeNativeDomain);
|
||||
|
||||
public AquariumRenderPlan RenderPlan { get; } = ZyphosRenderPlan.Create();
|
||||
|
||||
|
|
|
|||
|
|
@ -296,3 +296,4 @@
|
|||
{"timestamp":"2026-05-29T22:42:00+01:00","topic":"tubefield-single-batch-replay","lesson":"TubeField native-domain replay now uses logical source column plus curve coordinate as the selected producer coordinate while field id retains physical rolling-column identity. The reservoir history compute pass receives a TubeField replay source/constants binding only when exactly one TubeField batch exists, then re-evaluates the shifted selected sample against the live producer buffer before temporal merge. Multi-batch TubeField replay is intentionally invalid until a producer-keyed replay manifest maps selected samples to source buffers and constants; do not fill that gap with a side cache.","files":["src/Aquarium.Engine/Render/Shaders/D3D12TubeField.hlsl","src/Aquarium.Engine/Render/Shaders/D3D12Post.hlsl","src/Aquarium.Engine/Render/D3D12Renderer.cs","docs/perfect-fensalir-machine-roadmap.md","docs/papers/fensalir-native-domain-reservoirs.tex","docs/papers/fensalir-pipeline.tex","state/map.yaml","state/scratch.md"],"sources":["docs/perfect-fensalir-machine-roadmap.md"]}
|
||||
{"timestamp":"2026-05-29T23:10:00+01:00","topic":"native-domain-sdf-object-replay","lesson":"SDF temporal reuse should validate the visible hit, not merely the texel history. The native reservoir now reconstructs the previous selected SDF world hit from stored UV/travel, carries it through object center motion, and rejects history unless the replayed hit still matches the current ray/travel/support envelope; exact client SDF distance re-evaluation remains producer-owned work until replay manifests or shared includes exist.","files":["src/Aquarium.Engine/Render/Shaders/D3D12Post.hlsl","tests/Aquarium.Engine.Tests/FieldReservoirAbiTests.cs","docs/perfect-fensalir-machine-roadmap.md","state/map.yaml","state/memory.json"],"source":"docs/perfect-fensalir-machine-roadmap.md"}
|
||||
{"timestamp":"2026-05-29T23:16:00+01:00","topic":"tubefield-replay-manifest","lesson":"TubeField replay authority no longer comes from a CPU-side single-batch special case. The history shader reads a bounded producer-keyed replay manifest and raw source descriptor table, scans for the selected sample's field-id family, and re-evaluates the shifted logical column/curve coordinate from the matching source. Overflow is invalid instead of guessed; exact scaling beyond the descriptor cap should become a replay atlas only when captures prove the cap is real pressure.","files":["src/Aquarium.Engine/Render/D3D12Renderer.cs","src/Aquarium.Engine/Render/D3D12StructuredBuffer.cs","src/Aquarium.Engine/Render/Shaders/D3D12Post.hlsl","tests/Aquarium.Engine.Tests/FieldReservoirAbiTests.cs","docs/perfect-fensalir-machine-roadmap.md","state/map.yaml","state/memory.json"],"source":"docs/perfect-fensalir-machine-roadmap.md"}
|
||||
{"timestamp":"2026-05-29T23:30:00+01:00","topic":"reservoir-baseline-comparison-mode","lesson":"Native-domain versus texel-owned baseline comparison now has an explicit field-reservoir mode switch. Both modes use the same reservoir rows; native mode enables domain validity, support overlap, and producer replay at temporal reuse, while baseline mode keeps texel-owned field/travel/normal/color/confidence validation. First paired captures at artifacts/fensalir-captures/reservoir-compare-20260529-231904-* changed 10.8208% of final-frame pixels, 0.0165% of rejection-debug pixels, and 0.2976% of shift-debug pixels. This proves the switch is live but does not yet measure temporal leakage or ghosting quality.","files":["src/Aquarium.Engine.Contracts/GraphicsSettings.cs","src/Aquarium.Engine.Contracts/AquariumRuntimeContracts.cs","src/Aquarium.Engine/AquariumHost.cs","src/Aquarium.Engine/Render/D3D12Renderer.cs","src/Aquarium.Engine/Render/Shaders/D3D12Post.hlsl","scripts/capture-fensalir-frame.ps1","tests/Aquarium.Engine.Tests/FieldReservoirAbiTests.cs","docs/perfect-fensalir-machine-roadmap.md"],"source":"artifacts/fensalir-captures/reservoir-compare-20260529-231904-*"}
|
||||
|
|
|
|||
|
|
@ -135,8 +135,11 @@ next_actions:
|
|||
producer-keyed manifest before re-evaluating the shifted logical
|
||||
column/curve coordinate against the live producer buffer, and SDF history
|
||||
carries the previous selected hit through object motion before validating
|
||||
current ray/travel/support. The next cut is baseline/native-domain capture
|
||||
plus future exact producer SDF replay.
|
||||
current ray/travel/support. A field-reservoir mode switch now captures
|
||||
native-domain validation against a texel-owned baseline; the first paired
|
||||
set is `reservoir-compare-20260529-231904-*`, where native versus baseline
|
||||
changed 10.8208% of final-frame pixels. The next cut is a temporal
|
||||
leakage/ghosting metric harness plus future exact producer SDF replay.
|
||||
- Build the planetary flow organ in staged cuts: provenance manifest, static
|
||||
relief and reanalysis cube-sphere bake pipeline, stochastic advection
|
||||
contracts, synthetic runtime slice, ERA5/OSCAR baseline learning, then
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@
|
|||
"The consolidated fractal brush architecture lives in research/rendering/fractal-brush-architecture-plan.md. Pipeline: client intent -> domain roots -> semantic IFS brush grammar -> ownership tree -> node summaries -> contribution cache/residency scheduler -> backend packets -> renderer passes -> debug/evidence.",
|
||||
"The fractal domain reservoir doctrine lives in docs/fractal-domain-reservoir.md. Area ReSTIR makes selected sample coordinates and support part of reservoir identity; TSR-style reconstruction then consumes that validated domain evidence. Pixel rows are execution projections, not the native sampling domain.",
|
||||
"Native-domain reservoir temporal reuse validates producer replay at the visible field layer: TubeField history chooses a bounded producer-keyed replay manifest/source table before re-evaluating selected logical column/curve coordinates against the live buffer, and SDF history carries the previous selected hit through object motion before accepting current ray/travel/support.",
|
||||
"Field reservoir comparison is an explicit renderer mode, not a separate producer path: native-domain validation and texel-baseline reuse share rows and differ at the temporal reuse gate. The 2026-05-29 comparison capture proved the switch is live but is not yet a temporal quality metric.",
|
||||
"The actionable implementation checklist lives in research/rendering/fractal-brush-implementation-roadmap.md.",
|
||||
"The .aquageo DSL carries semantic domains and Form claims before backend lowering. Height, SignedDistance, Density, and Extinction must not be collapsed into one payload lane.",
|
||||
"Fractal summaries carry FormEncodingMask so selected-cut structural probes do not silently default transparent form nodes back into SDF.",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@
|
|||
## Current Slice
|
||||
|
||||
Extend native-domain reservoir replay from single-batch TubeField/SDF proof
|
||||
paths into measured baseline/native-domain capture.
|
||||
paths into measured baseline/native-domain capture. The first comparison set is
|
||||
`artifacts/fensalir-captures/reservoir-compare-20260529-231904-*`: native versus
|
||||
texel-baseline changed 10.8208% of final-frame pixels, 0.0165% of
|
||||
rejection-debug pixels, and 0.2976% of shift-debug pixels.
|
||||
|
||||
## Hot Lesson
|
||||
|
||||
|
|
@ -32,8 +35,8 @@ cap remain intentionally non-authoritative.
|
|||
|
||||
Follow `docs/perfect-fensalir-machine-roadmap.md` Phase 1:
|
||||
|
||||
1. Capture the occluded-spectrum-tubes scene in baseline/native-domain modes
|
||||
after replay is real, not merely support-overlap filtered.
|
||||
1. Add a real metric harness for temporal leakage/ghosting instead of relying
|
||||
on single-frame image deltas.
|
||||
2. Add exact SDF producer replay only when client SDF distance functions have a
|
||||
shared replay include or manifest instead of duplicating shader policy in
|
||||
post.
|
||||
|
|
|
|||
|
|
@ -67,6 +67,22 @@ public sealed class FieldReservoirAbiTests
|
|||
Assert.Contains("CreateRawShaderResourceView", renderer);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReservoirBaselineModeIsAnExplicitValidationSwitch()
|
||||
{
|
||||
var repoRoot = FindRepoRoot();
|
||||
var settings = File.ReadAllText(Path.Combine(repoRoot, "src", "Aquarium.Engine.Contracts", "GraphicsSettings.cs"));
|
||||
var host = File.ReadAllText(Path.Combine(repoRoot, "src", "Aquarium.Engine", "AquariumHost.cs"));
|
||||
var post = File.ReadAllText(Path.Combine(repoRoot, "src", "Aquarium.Engine", "Render", "Shaders", "D3D12Post.hlsl"));
|
||||
var capture = File.ReadAllText(Path.Combine(repoRoot, "scripts", "capture-fensalir-frame.ps1"));
|
||||
|
||||
Assert.Contains("FieldReservoirModeNativeDomain", settings);
|
||||
Assert.Contains("FieldReservoirModeTexelBaseline", settings);
|
||||
Assert.Contains("--field-reservoir-mode", host);
|
||||
Assert.Contains("nativeDomainReservoirEnabled", post);
|
||||
Assert.Contains("FieldReservoirMode", capture);
|
||||
}
|
||||
|
||||
private static string FindRepoRoot()
|
||||
{
|
||||
var directory = new DirectoryInfo(AppContext.BaseDirectory);
|
||||
|
|
|
|||
Loading…
Reference in a new issue