Fensalir/state/evidence.jsonl
2026-05-09 13:55:19 +01:00

76 lines
56 KiB
JSON

{"ts":"2026-05-08","topic":"mainline_engine_birth","summary":"Merged the native C# Aquarium Engine line to main and made it the live development branch. Removed branch-lineage memorial docs so the repo describes the current engine instead of carrying prototype-era debris.","files":["README.md","docs/branch-lineage.md"],"verification":["git merge --ff-only codex/port-bevy-features"]}
{"ts":"2026-05-08","topic":"persistent_state_surface","summary":"Added Aquarium-owned persistent state machinery: AGENTS.md for local operating doctrine, state/map.yaml for canonical project map, state/memory.json for durable renderer/state/UI lessons, state/evidence.jsonl for compact lesson entries, and state/scratch.md for disposable working context.","files":["AGENTS.md","state/map.yaml","state/memory.json","state/evidence.jsonl","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"]}
{"ts":"2026-05-08","topic":"engine_doctrine_distillation","summary":"Distilled only engine-relevant doctrine from the older Aquarium state: camera/Grid invariants, world-space anchors/domains, shader-owned visible world, conservative raymarch broad phase, diegetic lighting, DirectWrite overlay text, CultCache reload state, and hot reload failure behavior.","files":["docs/aquarium-engine-doctrine.md","state/memory.json","state/map.yaml"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"]}
{"topic":"grid_derivative_linework","summary":"Ported the Aetheria UI isoline idea into the Aquarium Grid shader: height contours and gradient-angle field lines now derive from the deferred Grid height field, and Cartesian Gridlines use fwidth-based masks so line width stays stable in pixels across zoom.","files":["src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","docs/hlsl-renderer.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"topic":"dev_reload_visible_headless_split","summary":"Fixed dev-reload so headless smoke runs use separate PID state and logs from the visible dev window, preventing headless verification from stopping the active window. Added -Reopen to relaunch the last visible slot without rebuilding.","files":["scripts/dev-reload.ps1","README.md","state/evidence.jsonl"],"verification":[".\\scripts\\dev-reload.ps1 -Reopen",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4","visible Aquarium PID remained running after headless smoke"],"ts":"2026-05-08"}
{"topic":"grid_far_distance","summary":"Replaced the shader fixed raymarch far distance with a per-frame value equal to camera distance from the Grid origin plus Grid radius, matching the circular Grid fade boundary.","files":["src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","docs/hlsl-renderer.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"topic":"watcher_renderer_contract_reload","summary":"dev-watch now fingerprints the AquariumFrame cbuffer in Aquarium.hlsl as host contract input. Ordinary shader edits can still hot reload, but cbuffer layout changes trigger a host reload so C# frame constants and shader reads stay in sync.","files":["scripts/dev-watch.ps1","docs/hlsl-renderer.md","state/evidence.jsonl"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -RetainSlots 4",".\\scripts\\dev-watch.ps1 -NoInitialLaunch -Once"],"ts":"2026-05-08"}
{"topic":"volumetrics_research_sweep","summary":"Preserved a realtime volumetrics research map covering Bruneton atmospheric scattering, Wronski AC4 volumetric fog, Hillaire/Frostbite froxel volumetrics and sky/clouds, Dreams Learning from Failure, GigaVoxels, Horizon clouds, Gobo stable volume sampling, NVIDIA GDC volumetric scattering, and Unreal volumetric fog docs. Distilled the Aquarium path: explicit renderer-owned low-resolution volume pass first, Bruneton LUT atmosphere later, sparse brick streaming only if scale demands it.","files":["research/volumetrics/README.md","research/volumetrics/source-manifest.md","research/volumetrics/synthesis.md","state/map.yaml","state/memory.json",".gitignore"],"verification":["downloaded local source cache under research/volumetrics/sources","extracted working text under research/volumetrics/extracted-text","source cache and extracts gitignored due binary size and copyright"],"ts":"2026-05-08"}
{"area":"research/volumetrics","lesson":"Follow-up scan through newer Advances/citation trails keeps Wronski/Hillaire froxel fog as Aquarium pass one. Nubis 2022/2023 is later cloud-asset work; AMD/Brixelizer-style GPU SDF points to cascaded sparse bricks with static/dynamic and toroidal partial updates; Neural Light Grid says learned fields are preprocessing/storage tools until runtime decode is cheap and inspectable.","source":"research/volumetrics/recent-volumetrics-and-gpu-sdf.md","ts":"2026-05-08"}
{"area":"research/volumetrics","lesson":"Do not treat slide decks or presenter notes as transcripts. yt-dlp subtitle pulls for Dreams and GPUOpen sparse SDF materially changed the distilled lesson: Dreams preserved the evaluator/field into a painterly splat renderer after SDF, brick, hybrid transparency, and froxel-lighting attempts failed; Brixelizer is primarily an update/integration system with caps and debug tracing, not just an SDF sampler.","source":"research/volumetrics/transcript-addendum.md","ts":"2026-05-08"}
{"area":"research/volumetrics","lesson":"Sea of Thieves clouds provide a stylized counterexample to dense cloud raymarching: Rare used authored opaque polygonal cloud geometry, low-res blurred color/depth compositing, approximate world-position reconstruction, noise/distortion, synchronized wrapped wind offsets, and pressure zones so clouds could be readable world/event objects like skulls, ships, and storms. For Aquarium, symbolic weather/field omens may want geometry/field silhouettes plus cloudy compositing before volumetric traversal.","source":"research/volumetrics/transcript-addendum.md","ts":"2026-05-08"}
{"area":"renderer/sdf-fields","lesson":"Documented the SDF field renderer plan and started a local SDF cloud prototype. Aquarium/Aetheria clouds are local world media that may be above, below, around, or enclosing the camera, so the core cloud architecture must not rely on skybox, hemisphere, paraboloid, or far-only assumptions. First implementation integrates four bounded analytic SDF cloud media along the camera ray before surface composition.","files":["docs/sdf-field-renderer-plan.md","docs/hlsl-renderer.md","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/map.yaml","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/sdf-fields","lesson":"The first SDF cloud transfer function made nearer ellipsoid edges occlude farther clouds because the SDF boundary produced a positive-distance absorbing veil and too much extinction. Cloud SDFs should provide sculptural containment and empty-space skipping, while density should be eroded interior occupancy with feathered boundaries and low extinction until a real volume pass owns the transfer function.","files":["src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","docs/hlsl-renderer.md","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/sdf-fields","lesson":"Fainter extinction did not fix near-cloud silhouettes because the prototype was still structurally wrong: a global SDF shell march could spend the frame's cloud sample budget inside a nearer ellipsoid and fail to reach farther cloud intervals. The analytic prototype now intersects ray/ellipsoid intervals, jumps empty space to true entries, and samples density only inside container volumes.","files":["src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","docs/hlsl-renderer.md","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/sdf-fields","lesson":"The SDF field/cloud renderer should use a waterfall implementation shape, not a chain of shy compromised prototypes. Define the target machine first: field ABI, broad phase, explicit local volume pass, composition contract, and acceleration gates. The current fullscreen analytic cloud code is temporary scaffolding for inspection only, not a place to accumulate features.","files":["docs/sdf-field-renderer-plan.md","docs/hlsl-renderer.md","state/memory.json","state/scratch.md"],"ts":"2026-05-08"}
{"area":"renderer/composition","lesson":"Removed the analytic SDF cloud scaffold from visible scene composition and made the Grid a transparent schematic overlay. Bodies now trace as solid scene content; the Grid traces separately and blends lines/isolines/field lines/weather tint over the result. This preserves legibility while reserving real scene mass for the future explicit volumetric field renderer.","files":["src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","docs/hlsl-renderer.md","docs/sdf-field-renderer-plan.md","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/composition","lesson":"Diegetic Grid transparency over raymarched content should use Aetheria-style stochastic coverage, not alpha blending. Aquarium now ports the dither-clip path from Aetheria's Dither Functions and Dithered Particles shaders using the copied LDR_LLL1_0 blue-noise texture, and it only draws the Grid when the Grid hit is closer than the nearest solid body so planets are not overlaid.","files":["src/Aquarium.Engine/Assets/Textures/Aetheria-LDR_LLL1_0.png","src/Aquarium.Engine/Assets/Textures/Aetheria-LDR_LLL1_0.r8","src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","src/Aquarium.Engine/Aquarium.Engine.csproj","docs/hlsl-renderer.md","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"dev-loop/reload","lesson":"dev-watch must treat runtime content as restart-owned input. Shader hot reload can swap HLSL, and live reload can swap Aquarium.Engine.Live, but new files under src/Aquarium.Engine/Assets require rebuilding the apphost slot and restarting the process so the renderer loads them.","files":["scripts/dev-watch.ps1","README.md","state/memory.json","state/scratch.md"],"verification":[".\\scripts\\dev-watch.ps1 -NoInitialLaunch -Once -IntervalMilliseconds 10 -DebounceMilliseconds 10","asset fingerprint check includes Aetheria-LDR_LLL1_0.png and .r8","dotnet build Aquarium.Engine.slnx"],"ts":"2026-05-08"}
{"area":"renderer/taa","lesson":"Added a clean-room TSR-inspired Gate 1 temporal resolver instead of Playdead-style TAA. Aquarium now renders linear HDR scene color plus ray travel, applies Halton jitter, reprojects current world hits into the previous camera basis, clamps history to the current 3x3 neighborhood, rejects by travel delta, writes ping-pong history, and tonemaps after resolve.","files":["docs/tsr-inspired-taa-spec.md","docs/hlsl-renderer.md","src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/map.yaml","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/taa","lesson":"TAA Gate 2A adds renderer metadata to history validation. Scene and history now carry material id plus surface normal; resolve rejects material mismatches and normal discontinuities. Grid stochastic surfaces write Grid travel/normal even on dither-miss pixels, preventing temporal accumulation from reprojecting against the body or background behind the diegetic Grid surface.","files":["docs/tsr-inspired-taa-spec.md","docs/hlsl-renderer.md","src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/taa","lesson":"TAA Gate 2B replaces coarse material identity with stable field ids and adds analytic object-motion reprojection for orbiting SDF bodies. Planet hits now move from current planet center to previous planet center before history projection, so history follows rigid body motion instead of relying only on camera reprojection.","files":["docs/tsr-inspired-taa-spec.md","docs/hlsl-renderer.md","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/taa","lesson":"TAA Gate 3A adds a current-frame temporal-control target separate from field/normal metadata. It carries reactive strength, stochastic/composition coverage, a reserved medium-opacity slot, and a spare channel; the resolve now reduces history for low-coverage reactive Grid samples while keeping the volumetric contract explicit for later medium history.","files":["docs/tsr-inspired-taa-spec.md","docs/hlsl-renderer.md","src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/map.yaml","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/taa","lesson":"TAA Gate 3B gives temporal-control data its own history ping-pong. Resolve now samples previous control at the reprojected UV and reduces history across stochastic coverage or reserved medium-opacity discontinuities, giving future volumetrics a real continuity signal instead of a one-frame mask.","files":["docs/tsr-inspired-taa-spec.md","docs/hlsl-renderer.md","src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/taa","lesson":"TAA Gate 3C stores accepted history age in temporal-control history w. The resolver grows age only when validation passes, resets it on failure, and ramps history authority with age so a newly reprojected sample can contribute without immediately carrying full stable-history weight.","files":["docs/tsr-inspired-taa-spec.md","docs/hlsl-renderer.md","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/taa","lesson":"TAA Gate 3D fixes travel validation under camera motion. Previous history travel must be compared to the reprojected previous-world position's distance from the previous camera, not to current-frame travel; otherwise stable history is falsely rejected whenever camera motion changes ray distance.","files":["docs/tsr-inspired-taa-spec.md","docs/hlsl-renderer.md","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/taa","lesson":"TAA Gate 3E fixes stochastic Grid accumulation. Opaque-surface neighborhood clamping and current-frame color-delta rejection collapse Grid history on dither-miss frames because the current sample looks like background; Grid history now bypasses those color checks and validates through field, travel, normal, coverage, reactive, and age terms.","files":["docs/tsr-inspired-taa-spec.md","docs/hlsl-renderer.md","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/debug","lesson":"Temporal debugging must be visible in the running window, not hidden behind relaunch-only command flags. F1 cycles render debug modes and 0-4 select final, raw current scene, reprojected history, history age, and history weight, making it possible to prove whether the presented frame is resolved and whether history is alive.","files":["docs/tsr-inspired-taa-spec.md","docs/hlsl-renderer.md","src/Aquarium.Engine/AquariumHost.cs","src/Aquarium.Engine.Contracts/Input/InputState.cs","src/Aquarium.Engine/Platform/Win32Window.cs","src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/DirectWriteOverlay.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"dev-loop/reload","lesson":"dev-watch must not only classify source changes; it must also verify the recorded script-owned process is alive. If the visible/headless PID recorded by dev-reload is gone or no longer belongs to the recorded slot, the watcher relaunches from a fresh slot. The watch fingerprint also includes scripts/*.ps1 so script changes match the documented restart-owned contract.","files":["scripts/dev-watch.ps1","README.md","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-watch.ps1 -Headless -Once -IntervalMilliseconds 10 -DebounceMilliseconds 10 -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/taa","lesson":"TAA Gate 3F gives stochastic Grid coverage a high-retention temporal blend. Coverage and reactive strength must not reduce Grid history authority because low coverage is exactly where temporal accumulation is required; Grid now validates with travel, field, normal, coverage continuity, medium continuity, and age while using a higher max history weight than opaque surfaces.","files":["docs/tsr-inspired-taa-spec.md","docs/hlsl-renderer.md","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/taa","lesson":"TAA Gate 3G fixes foreground glow leaking into background Grid history. Identity/control buffers are now point-loaded and field ids use exact equality, while Grid history color uses nearest identity-aligned sampling instead of bilinear color sampling. Grid max history weight was also reduced from 0.975 to 0.94 to keep linework less over-smoothed.","files":["docs/tsr-inspired-taa-spec.md","docs/hlsl-renderer.md","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/taa","lesson":"TAA Gate 3H fixes Grid history smoke by separating temporal support from broad overlay alpha. Grid control coverage now stores line/contour/field-line support, not field tint alpha; current support gates Grid history, broad tint no longer keeps age alive across the surface, and Grid retention is reduced to 0.90 for crisper response.","files":["docs/tsr-inspired-taa-spec.md","docs/hlsl-renderer.md","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/taa","lesson":"TAA Gate 3I stops using raw stochastic Grid hit/miss color as the current radiance truth. For Grid pixels the resolve reconstructs the analytic overlay at the current world hit and uses premultiplied overlay color as the current estimate; history then stabilizes the estimate instead of trying to recover alpha from binary noise alone.","files":["docs/tsr-inspired-taa-spec.md","docs/hlsl-renderer.md","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/taa","lesson":"TAA Gate 3J restores debug mode 1 to true raw scene color and stops final Grid pixels from blending previous color history. The current Grid renderer now uses analytic current Grid color for final output and writes that estimate into history; history age/weight/color remain diagnostics until a real transparent/volumetric composition contract needs color history again.","files":["docs/tsr-inspired-taa-spec.md","docs/hlsl-renderer.md","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/taa","lesson":"TAA Gate 3L disables projection jitter in the live frame by scaling Halton jitter to zero. Visible judder on Self/planet surfaces means the resolver is not yet hiding sample offsets; jitter should stay disabled until opaque and Grid paths both prove stable.","files":["docs/tsr-inspired-taa-spec.md","docs/hlsl-renderer.md","src/Aquarium.Engine/Render/D3D11Renderer.cs","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"renderer/taa","lesson":"Removed the abandoned unjittered Grid retrace after projection jitter was disabled. The retrace was a temporary splint that solved the Grid surface twice; with live jitter at zero, Grid analytic final color can reconstruct from the existing current hit without adding renderer Jenga.","files":["docs/tsr-inspired-taa-spec.md","docs/hlsl-renderer.md","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"dev-loop/reload","lesson":"Live runtime reload must be end-to-end acknowledged. dev-watch now treats live-current.txt as a request, not success: after building a live slot and updating the pointer, it waits for the running host stdout to report the exact live DLL path or marks the reload failed. Visible dev windows can use dev-watch -ReopenWhenClosed to reopen the last good slot without rebuilding after the window is closed.","files":["scripts/dev-watch.ps1","README.md","state/map.yaml","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-watch.ps1 -NoInitialLaunch -Once -IntervalMilliseconds 10 -DebounceMilliseconds 10 -RetainSlots 4",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-08"}
{"area":"dev-loop/reload","lesson":"dev-watch was not reaching its poll loop because Start-Process -Wait around dev-reload could remain attached to the long-lived launched Aquarium process after initial launch. The watcher now invokes dev-reload synchronously, leaving app process ownership inside dev-reload, and a live-only Aquarium.Engine.Live cosmetic change produced a live slot plus host acknowledgement without rebuilding the host.","files":["scripts/dev-watch.ps1","src/Aquarium.Engine.Live/AquariumRuntime.cs","state/memory.json","state/scratch.md"],"verification":["watch.log: Live reload requested, pointer updated, and acknowledged for artifacts/dev-reload/live-slots/20260509-000855-c3f6310c/Aquarium.Engine.Live.dll","latest.out.log: Live reload probe armed and Live runtime reload applied"],"ts":"2026-05-09"}
{"area":"renderer/debug","lesson":"Temporal debug modes now expose the resolver's control data directly. Modes 5 and 6 show current temporal control channels and current field identity, so Grid support, reactive strength, medium opacity, and field ownership can be inspected without inferring them from final color or history artifacts.","files":["src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/DirectWriteOverlay.cs","src/Aquarium.Engine/AquariumHost.cs","src/Aquarium.Engine/Platform/Win32Window.cs","src/Aquarium.Engine.Contracts/Input/InputState.cs","docs/tsr-inspired-taa-spec.md","docs/hlsl-renderer.md","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx","Shader hot reload applied after Grid reactive channel fix","Mode 5 screenshot showed stale full-Grid reactive red; Grid reactive now zero and support remains coverage"],"ts":"2026-05-09"}
{"area":"renderer/debug","lesson":"Temporal control coverage now distinguishes empty background from stable surfaces. Background pixels default coverage to zero, opaque body hits write coverage 1, and Grid hits write line/support coverage; mode 5 should therefore show black empty background rather than green covered history everywhere.","files":["src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/memory.json","state/scratch.md"],"verification":["Shader hot reload applied with no stderr after control coverage fix"],"ts":"2026-05-09"}
{"area":"renderer/taa","lesson":"Gate 3M cuts temporal color history out of final presentation while projection jitter is disabled. The resolver still writes history, metadata, control, age, and weight for debug/future volumetrics, but mode 0 now presents current-frame color after analytic Grid reconstruction instead of letting stale opaque-surface history ghost the frame.","files":["src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","docs/hlsl-renderer.md","docs/tsr-inspired-taa-spec.md","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx","Shader hot reload applied with no stderr after Gate 3M cut"],"ts":"2026-05-09"}
{"area":"renderer/hdr","lesson":"Modern HDR/PBR presentation should be built as scene-linear lighting, explicit exposure, pre-tonemap bloom/veil, and an explicit display transform. Aquarium should avoid thresholded 2000s bloom; broad low-intensity bloom should spread existing HDR energy and be inspected with luminance/bloom debug views before SDF volumetrics land.","files":["research/rendering/hdr-pbr-presentation.md","state/map.yaml","state/memory.json","state/scratch.md"],"verification":["research pass over ACES, Unreal exposure/bloom docs, Jimenez COD AW post-processing, Hable filmic tonemapping, and Frostbite PBR notes"],"ts":"2026-05-09"}
{"area":"renderer/hdr","lesson":"Aquarium now has the first HDR presentation pipe before volumetrics: fixed manual exposure, half/quarter/eighth pre-tonemap bloom targets, firefly-safe downsampling, separable horizontal/vertical blur per level, low-gain bloom/veil composite before the ACES fit, and debug modes for bloom contribution and exposed luminance. This replaces the tempting full-res gather prototype with a proper hierarchical shape.","files":["src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","src/Aquarium.Engine.Contracts/Input/InputState.cs","src/Aquarium.Engine/AquariumHost.cs","src/Aquarium.Engine/Platform/Win32Window.cs","src/Aquarium.Engine/Render/DirectWriteOverlay.cs","docs/hlsl-renderer.md","docs/tsr-inspired-taa-spec.md","research/rendering/hdr-pbr-presentation.md","state/map.yaml","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-09"}
{"area":"renderer/debug-ui","lesson":"Aquarium debug UI now uses a native Direct2D/DirectWrite retained panel inspired by CultLib code-first composition: controls are bound by explicit read/write delegates and styled as flat compact rows rather than importing Unity prefabs or ImGui chrome. The first panel toggles with F2 and drives render debug mode plus HDR exposure, bloom intensity, and bloom veil through shader constants.","files":["src/Aquarium.Engine/Render/Ui/DebugUi.cs","src/Aquarium.Engine/Render/DirectWriteOverlay.cs","src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","src/Aquarium.Engine.Contracts/Input/InputState.cs","src/Aquarium.Engine/Platform/Win32Window.cs","docs/hlsl-renderer.md","state/map.yaml","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-09"}
{"area":"runtime/cultcache","lesson":"A startup EndOfStreamException from CultCache means the backing MessagePack snapshot itself is truncated, not that schema guardrails failed. Aquarium now quarantines unreadable snapshots beside the live cache and boots fresh typed state; CultLib single-file stores now write via same-directory temp file plus atomic replace so process death cannot leave a zero-byte live cache.","files":["src/Aquarium.Engine.Live/State/AquariumCultStateStore.cs","docs/cult-runtime-surface.md","state/memory.json","state/scratch.md","E:\\Projects\\CultLib\\src\\GameCult.Caching\\CultCache.cs"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4","zero-byte artifacts/dev-reload/cultcache/aquarium-client.msgpack quarantined and fresh 1773-byte cache created"],"ts":"2026-05-09"}
{"area":"renderer/debug-ui","lesson":"Direct2D/Vortice Rect construction takes x, y, width, height. Aquarium UI code should use explicit RectFromEdges helpers whenever layout is expressed as left/top/right/bottom, otherwise sliders and fills can explode into full-frame slabs.","files":["src/Aquarium.Engine/Render/Ui/DebugUi.cs","src/Aquarium.Engine/Render/DirectWriteOverlay.cs","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-09"}
{"area":"renderer/debug-ui","lesson":"Debug UI interaction feedback should be element-specific and stable-geometry: base/hover/active states, slider track/fill and handle brighten independently, active brightens further, and saturated accent colors should lerp toward white rather than resizing controls or darkening surfaces.","files":["src/Aquarium.Engine/Render/Ui/DebugUi.cs","src/Aquarium.Engine/Render/DirectWriteOverlay.cs","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-09"}
{"area":"renderer/debug-ui","lesson":"Tooltips now belong to code-first control declarations as optional intent strings and render as viewport-clamped Direct2D overlay slabs. Keep that path for future renderer controls instead of adding separate anonymous tooltip plumbing.","files":["src/Aquarium.Engine/Render/Ui/DebugUi.cs","src/Aquarium.Engine/Render/D3D11Renderer.cs","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-09"}
{"area":"renderer/state","lesson":"Global renderer presentation knobs should be a typed CultCache document, not process-local debug UI state. Aquarium now uses a contracts-level GraphicsSettings DTO, a live epiphany.aquarium.graphics_settings document, host sync from renderer to runtime, and runtime flush before live assembly reload so render debug mode plus HDR exposure/bloom controls persist across restart and reload without forcing disk writes on every slider twitch.","files":["src/Aquarium.Engine.Contracts/GraphicsSettings.cs","src/Aquarium.Engine.Contracts/AquariumRuntimeContracts.cs","src/Aquarium.Engine.Live/State/AquariumGraphicsSettingsState.cs","src/Aquarium.Engine.Live/State/AquariumCultStateStore.cs","src/Aquarium.Engine.Live/AquariumRuntime.cs","src/Aquarium.Engine/AquariumHost.cs","src/Aquarium.Engine/Live/LiveRuntimeLoader.cs","src/Aquarium.Engine/Render/D3D11Renderer.cs","docs/cult-runtime-surface.md","docs/hlsl-renderer.md","state/map.yaml","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4","direct headless two-run probe: --render-debug 7 persisted as debug 7 on the next run using artifacts/verification/graphics-settings-persist.msgpack"],"ts":"2026-05-09"}
{"area":"renderer/volumetrics","lesson":"The first fog-land implementation should establish the field contract and diagnostics before compositing fog. Aquarium now sends a fixed field instance structured buffer for Self, planets, and local medium ellipsoids to HLSL; modes 9 and 10 expose registered medium density and transmittance. Final mode 0 remains unchanged until the explicit low-res volume pass and compositor are built.","files":["src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","src/Aquarium.Engine.Contracts/GraphicsSettings.cs","src/Aquarium.Engine.Contracts/Input/InputState.cs","src/Aquarium.Engine/AquariumHost.cs","src/Aquarium.Engine/Platform/Win32Window.cs","src/Aquarium.Engine/Render/DirectWriteOverlay.cs","docs/sdf-field-renderer-plan.md","docs/hlsl-renderer.md","state/map.yaml","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4","direct headless startup with --render-debug 10 compiled shaders and loaded persisted debug mode 10"],"ts":"2026-05-09"}
{"area":"renderer/volumetrics","lesson":"Registered medium diagnostics now come from a separate half-resolution medium pass instead of being integrated inside the scene shader. The pass samples the field instance buffer, writes density/transmittance/source into a medium texture, and scene/resolve stages sample that texture for debug/control. Final composition remains unchanged until the compositor is explicit.","files":["src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","src/Aquarium.Engine.Contracts/GraphicsSettings.cs","docs/sdf-field-renderer-plan.md","docs/hlsl-renderer.md","state/map.yaml","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4","direct headless startup with --render-debug 11 compiled shaders and loaded persisted debug mode 11"],"ts":"2026-05-09"}
{"area":"renderer/volumetrics","lesson":"Medium composition is now explicit and gated: the half-resolution medium pass writes diagnostic and transport textures, and resolve can composite surface * transmittance + in-scattering through a persisted Medium Composite setting. The default remains zero so final presentation does not change until the medium is intentionally enabled and tuned.","files":["src/Aquarium.Engine.Contracts/GraphicsSettings.cs","src/Aquarium.Engine.Live/State/AquariumGraphicsSettingsState.cs","src/Aquarium.Engine.Live/State/AquariumCultStateStore.cs","src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","docs/cult-runtime-surface.md","docs/hlsl-renderer.md","docs/sdf-field-renderer-plan.md","state/map.yaml","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4","direct headless startup in final mode with default Medium Composite 0"],"ts":"2026-05-09"}
{"area":"renderer/volumetrics","lesson":"The first medium density view was too screen-ray dependent: it stored a completed half-res ray integral, so debug texture detail read as view-space soup. The pass now stores a 4x4 frustum slice atlas where each texel reconstructs a world point and evaluates field-local density; resolve integrates those stored cells front-to-back. Erosion noise is stationary in field-local space.","files":["src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","docs/hlsl-renderer.md","docs/sdf-field-renderer-plan.md","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-09"}
{"area":"renderer/volumetrics","lesson":"Do not label a view-dependent transport projection as Medium Density. Mode 9 now evaluates the registered medium field on a world-anchored Grid-altitude slice, while modes 10 and 11 remain frustum transport diagnostics. Density debugging and transport debugging are different tools.","files":["src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","docs/hlsl-renderer.md","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx"],"ts":"2026-05-09"}
{"area":"renderer/volumetrics","lesson":"A single Grid-altitude density slice can be legitimately blank when local media live above or below the Grid. Mode 9 is now a world-anchored density column over the Grid plane, sampling a fixed z range and visualizing max/mean density. Source debug is boosted independently from physical transport so near-black source patches do not masquerade as useful diagnostics.","files":["src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","docs/hlsl-renderer.md","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4"],"ts":"2026-05-09"}
{"area":"dev-reload/headless","lesson":"Headless verification must wait for the Aquarium process to exit after its requested frames, not return when the process merely starts. Hidden headless windows prevent stuck smoke tests from leaving visible non-responsive windows, stdout startup checkpoints reveal where startup wedged, and shader debug loops that call the registered medium stack should stay rolled instead of forcing D3DCompiler to unroll a huge expansion.","files":["scripts/dev-reload.ps1","src/Aquarium.Engine/AquariumHost.cs","src/Aquarium.Engine/Platform/Win32Window.cs","src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4 -HeadlessTimeoutSeconds 60","Get-Process Aquarium.Engine returned no remaining processes"],"ts":"2026-05-09"}
{"area":"renderer/volumetrics","lesson":"Do not expose a Medium Source debug mode until the renderer has a real light-injection/scattering stage. Source means in-scattered radiance, not a tinted-density placeholder. Medium debugging should first show direct camera-ray density, direct camera-ray transmittance, and atlas/pass density so missing media can be diagnosed without semantic fog.","files":["src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4 -HeadlessTimeoutSeconds 60"],"ts":"2026-05-09"}
{"area":"debug-ui/volumetrics","lesson":"Ray-based debug views need a visible step selector instead of more opaque modes. DebugUi controls now support conditional visibility; the persisted MediumDebugStep slider appears only for medium ray preview modes and drives shader inspection of the selected raymarch sample or cumulative transmittance to that sample.","files":["src/Aquarium.Engine.Contracts/GraphicsSettings.cs","src/Aquarium.Engine.Live/State/AquariumGraphicsSettingsState.cs","src/Aquarium.Engine.Live/State/AquariumCultStateStore.cs","src/Aquarium.Engine/Render/Ui/DebugUi.cs","src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4 -HeadlessTimeoutSeconds 60"],"ts":"2026-05-09"}
{"area":"renderer/volumetrics","lesson":"If the medium atlas density view shows fields but ray density/transmittance are empty at every step, check pass bindings before tuning density. The resolve shader also calls registeredMediumDensity for ray preview modes, so it must bind fieldInstances at t12 just like the medium and scene passes.","files":["src/Aquarium.Engine/Render/D3D11Renderer.cs","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4 -HeadlessTimeoutSeconds 60"],"ts":"2026-05-09"}
{"area":"renderer/volumetrics","lesson":"Do not compose the final frame from the diagnostic 4x4 medium atlas. If atlas density shows frustum-slice blobs while direct ray density is continuous, final composition should use direct registered-medium ray integration until a real froxel volume replaces the diagnostic atlas. Keep atlas density as an artifact-revealing debug view only.","files":["src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4 -HeadlessTimeoutSeconds 60"],"ts":"2026-05-09"}
{"area":"renderer/volumetrics","lesson":"The medium atlas trial has been replaced by a first real packed froxel volume: independent froxel dimensions, 32 depth slices, 8x4 D3D11 atlas packing, per-froxel density/transmittance/in-scattering, and resolve-side front-to-back composition. Direct ray density/transmittance debug remains the correctness reference; froxel density is the volume inspection view.","files":["src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","docs/hlsl-renderer.md","docs/sdf-field-renderer-plan.md","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4 -HeadlessTimeoutSeconds 60"],"ts":"2026-05-09"}
{"area":"renderer/volumetrics","lesson":"The Grid is a transparent schematic overlay, not a participating-medium occluder. Keep Grid travel/field id for temporal stability, but do not clamp fog integration to Grid travel; only solid fields such as Self and planets terminate the froxel composite ray.","files":["src/Aquarium.Engine/Render/Shaders/Aquarium.hlsl","state/scratch.md"],"verification":["Aquarium.Engine project build succeeded","Full solution/headless verification blocked by dirty external CultLib changes on E:\\Projects\\CultLib codex/cultcache-attribute-first: CultCache.cs currently fails GameCult.Caching build with System.Text.Json/IsExternalInit errors"],"ts":"2026-05-09"}
{"area":"renderer/d3d12","lesson":"Before building the transparent stochastic surface pipe, keep D3D11 as the reference backend and add D3D12 beside it behind IAquariumRenderer. The first D3D12 pass should prove device, command queue, swapchain, RTV heap, command list, fence, clear, and present lifecycle with headless execution before porting scene passes.","files":["src/Aquarium.Engine/AquariumHost.cs","src/Aquarium.Engine/Render/IAquariumRenderer.cs","src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/D3D12Renderer.cs","docs/d3d12-migration.md","state/scratch.md"],"verification":["dotnet build src\\Aquarium.Engine\\Aquarium.Engine.csproj","Aquarium.Engine.exe --headless --renderer d3d12 with latest known-good live assembly exited 0","Aquarium.Engine.exe --headless --renderer d3d11 with latest known-good live assembly exited 0"],"ts":"2026-05-09"}
{"area":"renderer/backend-selection","lesson":"Backend-neutral startup logging matters once D3D12 exists beside D3D11. Live runtime messages should describe Aquarium host invariants, not claim a specific graphics API that may be false for the selected renderer.","files":["src/Aquarium.Engine.Live/AquariumRuntime.cs"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4 -HeadlessTimeoutSeconds 60","Latest slot Aquarium.Engine.exe --headless --renderer d3d12 exited 0 and logged D3D12 device/swapchain creation"],"ts":"2026-05-09"}
{"area":"renderer/d3d12","lesson":"A useful D3D12 foothold must exercise shader and PSO machinery, not just ClearRenderTargetView. The D3D12 backend now uses per-swapchain-buffer command allocators, a pass context, fullscreen root signature, compiled smoke shader, PSO, viewport/scissor/RTV binding, and DrawInstanced fullscreen triangle submission.","files":["src/Aquarium.Engine/Render/D3D12Renderer.cs","src/Aquarium.Engine/Render/Shaders/D3D12Smoke.hlsl","docs/d3d12-migration.md","state/scratch.md"],"verification":["dotnet build src\\Aquarium.Engine\\Aquarium.Engine.csproj","Aquarium.Engine.exe --headless --renderer d3d12 exited 0 and logged fullscreen smoke pipeline creation"],"ts":"2026-05-09"}
{"area":"renderer/d3d12","lesson":"D3D12 descriptor/upload ownership is now represented in the backend instead of hiding inside a draw call. The smoke pass uses a shader-visible CBV/SRV/UAV descriptor arena, one upload constant buffer per swapchain frame, a CBV descriptor table at b0, and per-frame writes before command recording. Generalize this foothold into renderer-wide descriptor and upload ring helpers before porting Aquarium scene resources.","files":["src/Aquarium.Engine/Render/D3D12Renderer.cs","src/Aquarium.Engine/Render/Shaders/D3D12Smoke.hlsl","docs/d3d12-migration.md","state/scratch.md"],"verification":["dotnet build src\\Aquarium.Engine\\Aquarium.Engine.csproj","Aquarium.Engine.exe --headless --renderer d3d12 exited 0 with CBV descriptor table smoke pass"],"ts":"2026-05-09"}
{"area":"renderer/d3d12","lesson":"D3D12 now has reusable renderer-side primitives instead of smoke-pass-local plumbing: a descriptor arena, persistent mapped upload buffer, and default-heap render target with explicit state tracking. The smoke pass renders into the offscreen target and copies to the swapchain, proving render target lifetime and copy barriers before porting Aquarium scene/history/froxel textures.","files":["src/Aquarium.Engine/Aquarium.Engine.csproj","src/Aquarium.Engine/Render/D3D12DescriptorArena.cs","src/Aquarium.Engine/Render/D3D12UploadBuffer.cs","src/Aquarium.Engine/Render/D3D12RenderTarget.cs","src/Aquarium.Engine/Render/D3D12Renderer.cs","docs/d3d12-migration.md","state/scratch.md"],"verification":["dotnet build src\\Aquarium.Engine\\Aquarium.Engine.csproj","Aquarium.Engine.exe --headless --renderer d3d12 exited 0 with offscreen render target copy path"],"ts":"2026-05-09"}
{"area":"renderer/d3d12","lesson":"D3D12 best-practice pass distilled Microsoft, NVIDIA, and AMD guidance. Current Aquarium D3D12 backend is acceptable bring-up scaffolding, but real pass migration should wait for a named resource registry, static/transient descriptor allocation, fence-reclaimed upload ring, debug names, PIX markers, and backbuffer state tracking. Committed resources and fixed arenas must not become production policy by inertia.","files":["research/d3d12/source-manifest.md","research/d3d12/synthesis.md","docs/d3d12-best-practices-audit.md","docs/d3d12-migration.md","state/scratch.md"],"verification":["Research sources reviewed via Microsoft Learn, DirectX Developer Blog, NVIDIA Technical Blog, and AMD GPUOpen","Current D3D12 helper code audited against descriptor, upload, barrier, memory, and fence guidance"],"ts":"2026-05-09"}
{"area":"renderer/d3d12","lesson":"Full-ass D3D12 foundation pass added debug names, command-list events, tracked swapchain backbuffer states, and per-frame persistent-mapped upload rings. This moves current code closer to the researched doctrine: visible ownership, inspectable GPU captures, and fence-safe transient CPU-to-GPU data. Next remaining pre-pass work is static/transient descriptor separation, resource registry, resize-safe recreation, and capacity diagnostics.","files":["src/Aquarium.Engine/Render/D3D12TrackedResource.cs","src/Aquarium.Engine/Render/D3D12DescriptorArena.cs","src/Aquarium.Engine/Render/D3D12UploadRing.cs","src/Aquarium.Engine/Render/D3D12RenderTarget.cs","src/Aquarium.Engine/Render/D3D12Renderer.cs","docs/d3d12-best-practices-audit.md","docs/d3d12-migration.md","state/scratch.md"],"verification":["dotnet build src\\Aquarium.Engine\\Aquarium.Engine.csproj","Aquarium.Engine.exe --headless --renderer d3d12 exited 0 with tracked resources, events, and upload ring"],"ts":"2026-05-09"}
{"area":"renderer/d3d12","lesson":"D3D12 now separates static shader descriptors from per-frame transient descriptor arenas, resets transient descriptors only after frame fence wait, registers named resources, and reports capacity for upload ring, transient/static shader descriptors, and RTV descriptors. Keep arenas simple until real churn demands free lists; avoid exact-fit capacities that leave no room for immediate next resources.","files":["src/Aquarium.Engine/Render/D3D12DescriptorArena.cs","src/Aquarium.Engine/Render/D3D12ResourceRegistry.cs","src/Aquarium.Engine/Render/D3D12UploadRing.cs","src/Aquarium.Engine/Render/D3D12Renderer.cs","docs/d3d12-best-practices-audit.md","docs/d3d12-migration.md","state/scratch.md"],"verification":["dotnet build src\\Aquarium.Engine\\Aquarium.Engine.csproj","Aquarium.Engine.exe --headless --renderer d3d12 exited 0 and printed resource registry plus capacity diagnostics"],"ts":"2026-05-09"}
{"area":"renderer/d3d12","lesson":"D3D12 render targets now support SRV descriptors, and the smoke target is sampled by a second fullscreen pass instead of copied as an opaque resource. The renderer interface now receives current window dimensions, allowing D3D12 to recreate swapchain buffers and dependent smoke resources on resize. Resize still consumes fixed bring-up descriptors and fails loudly before exhaustion; production descriptor reclamation/rebuild policy is still needed before serious pass migration.","files":["src/Aquarium.Engine/Render/IAquariumRenderer.cs","src/Aquarium.Engine/AquariumHost.cs","src/Aquarium.Engine/Render/D3D11Renderer.cs","src/Aquarium.Engine/Render/D3D12RenderTarget.cs","src/Aquarium.Engine/Render/D3D12Renderer.cs","src/Aquarium.Engine/Render/Shaders/D3D12Smoke.hlsl","docs/d3d12-best-practices-audit.md","docs/d3d12-migration.md","state/scratch.md"],"verification":["dotnet build src\\Aquarium.Engine\\Aquarium.Engine.csproj","Aquarium.Engine.exe --headless --renderer d3d12 exited 0 with SRV copy/display pass and capacity diagnostics"],"ts":"2026-05-09"}
{"area":"renderer/d3d12","lesson":"D3D12 render targets now support UAV descriptors, and the smoke pass proves a transient per-frame UAV table by writing a diagnostic texture from the pixel shader. Pixel shader UAV registers share the render-target output namespace, so the first manual UAV must bind at u1 when SV_Target0 is present. Resize now waits for the GPU, releases swapchain-dependent resources, rebuilds static shader/RTV descriptor arenas, and recreates descriptors from a clean state instead of burning fixed slots. The D3D12 backend also ignores the D3D11 shader-source override and compiles its copied D3D12Smoke.hlsl.","files":["src/Aquarium.Engine/Render/D3D12RenderTarget.cs","src/Aquarium.Engine/Render/D3D12Renderer.cs","src/Aquarium.Engine/Render/Shaders/D3D12Smoke.hlsl","docs/d3d12-best-practices-audit.md","docs/d3d12-migration.md","state/memory.json","state/map.yaml","state/scratch.md"],"verification":["dotnet build src\\Aquarium.Engine\\Aquarium.Engine.csproj",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4 -HeadlessTimeoutSeconds 20 with AQUARIUM_RENDERER=d3d12 exited 0 and printed UAV/static/transient capacity diagnostics"],"ts":"2026-05-09"}
{"area":"renderer/d3d12","lesson":"D3D12 resource capability must remain separate from descriptor ownership. A texture can be created with AllowUnorderedAccess for transient UAV views without allocating a persistent static UAV descriptor. The diagnostic UAV target now uses a transient per-frame UAV descriptor only, reducing static heap use and keeping descriptor ownership honest before real pass migration.","files":["src/Aquarium.Engine/Render/D3D12RenderTarget.cs","src/Aquarium.Engine/Render/D3D12Renderer.cs","research/d3d12/synthesis.md","docs/d3d12-best-practices-audit.md","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx", ".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4 -HeadlessTimeoutSeconds 20 with AQUARIUM_RENDERER=d3d12 exited 0 and static shader descriptors dropped to 1/64"],"ts":"2026-05-09"}
{"area":"renderer/d3d12","lesson":"The first real D3D12 pass migration exposed the Grid height target and frame-constant path, but its original fullscreen per-texel body loop was intentionally superseded by a brush-rendered pass. Keep temporal previous camera/Grid/time as renderer-level state; swapchain frame resources are allocator reuse buckets, not frame-history state.","files":["src/Aquarium.Engine/Render/D3D12Renderer.cs","src/Aquarium.Engine/Render/Shaders/D3D12Smoke.hlsl","docs/d3d12-migration.md","docs/d3d12-best-practices-audit.md","docs/hlsl-renderer.md","state/map.yaml","state/memory.json","state/scratch.md"],"verification":["dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4 -HeadlessTimeoutSeconds 20 with AQUARIUM_RENDERER=d3d12 and AQUARIUM_RENDER_DEBUG_MODE=11 exited 0",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4 -HeadlessTimeoutSeconds 20 with AQUARIUM_RENDERER=d3d12 and AQUARIUM_RENDER_DEBUG_MODE=0 exited 0"],"ts":"2026-05-09"}
{"area":"renderer/d3d12","lesson":"The D3D12 Grid height pass must be a real gravity brush pass, not a fullscreen shader loop over every body per texel. It renders a base field, uploads a small body brush constant table, and draws one additive up-facing quad per body into a 128x128 scalar R16_Float target. R32G32B32A32_Float is the wrong target format for additive blending here, and extra channels are waste unless the pass contract actually stores extra data. The root signature must expose frame constants to the vertex shader because the brush vertex shader performs the top-down Grid-space orthographic transform.","files":["src/Aquarium.Engine/Render/D3D12Renderer.cs","src/Aquarium.Engine/Render/Shaders/D3D12Grid.hlsl","docs/d3d12-migration.md","docs/d3d12-best-practices-audit.md","docs/hlsl-renderer.md","state/memory.json","state/scratch.md"],"verification":["dotnet build src\\Aquarium.Engine\\Aquarium.Engine.csproj",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4 -HeadlessTimeoutSeconds 20 with AQUARIUM_RENDERER=d3d12 and AQUARIUM_RENDER_DEBUG_MODE=11 exited 0","dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4 -HeadlessTimeoutSeconds 20 with AQUARIUM_RENDERER=d3d12 and AQUARIUM_RENDER_DEBUG_MODE=0 exited 0"],"ts":"2026-05-09"}
{"area":"renderer/d3d12","lesson":"A Grid height target is scalar. The D3D12 brush-rendered Grid height pass should use R16_Float and scalar pixel-shader outputs; four float channels were defensive waste after the R32G32B32A32_Float blend failure, not a real contract. Add channels only when the pass explicitly stores more than height.","files":["src/Aquarium.Engine/Render/D3D12Renderer.cs","src/Aquarium.Engine/Render/Shaders/D3D12Grid.hlsl","docs/d3d12-migration.md","docs/d3d12-best-practices-audit.md","docs/hlsl-renderer.md","state/memory.json","state/scratch.md"],"verification":["dotnet build src\\Aquarium.Engine\\Aquarium.Engine.csproj",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4 -HeadlessTimeoutSeconds 20 with AQUARIUM_RENDERER=d3d12 and AQUARIUM_RENDER_DEBUG_MODE=11 exited 0","dotnet build Aquarium.Engine.slnx",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4 -HeadlessTimeoutSeconds 20 with AQUARIUM_RENDERER=d3d12 and AQUARIUM_RENDER_DEBUG_MODE=0 exited 0"],"ts":"2026-05-09"}
{"area":"renderer/d3d12","lesson":"D3D12 now has the first real Aquarium field data upload path: froxel primitive ids and field instances are built on CPU, uploaded through the per-frame upload ring, copied into default-heap structured buffers, and bound through transient SRV descriptors for a shader that actually reads them. Static and transient CBV/SRV/UAV heaps cannot be co-bound; pass-visible descriptor tables need to live in the active transient heap or be copied there. The table builders are temporarily duplicated from D3D11 and should be extracted into one shared field ABI owner before more consumers depend on them.","files":["src/Aquarium.Engine/Render/D3D12UploadRing.cs","src/Aquarium.Engine/Render/D3D12StructuredBuffer.cs","src/Aquarium.Engine/Render/D3D12ResourceRegistry.cs","src/Aquarium.Engine/Render/D3D12Renderer.cs","src/Aquarium.Engine/Render/Shaders/D3D12Smoke.hlsl","docs/d3d12-migration.md","docs/d3d12-best-practices-audit.md","docs/hlsl-renderer.md","state/memory.json","state/scratch.md"],"verification":["dotnet build src\\Aquarium.Engine\\Aquarium.Engine.csproj",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4 -HeadlessTimeoutSeconds 20 with AQUARIUM_RENDERER=d3d12 and AQUARIUM_RENDER_DEBUG_MODE=0 exited 0",".\\scripts\\dev-reload.ps1 -Headless -RetainSlots 4 -HeadlessTimeoutSeconds 20 with AQUARIUM_RENDERER=d3d12 and AQUARIUM_RENDER_DEBUG_MODE=11 exited 0","dotnet build Aquarium.Engine.slnx"],"ts":"2026-05-09"}