From 7202d30ef1c59b214fe6bdc80e9d6fefebfa2efd Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Wed, 27 May 2026 13:32:38 +0100 Subject: [PATCH] Propagate Fensalir texture leases to video drivers --- docs/implementation-plan.md | 3 ++ notes/current-system-map.md | 3 ++ notes/fresh-workspace-handoff.md | 2 + src/Mimir.BufferSmoke/Program.cs | 40 ++++++++++++++++++- src/Mimir.Runtime/MimirRuntime.cs | 1 + .../IMimirFensalirTextureLeaseReceiver.cs | 6 +++ .../MimirSynchronizationHub.cs | 18 +++++++++ .../MimirVideoCaptureDriverSource.cs | 10 ++++- state/evidence.jsonl | 1 + state/map.yaml | 4 +- 10 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 src/Mimir.Runtime/Synchronization/IMimirFensalirTextureLeaseReceiver.cs diff --git a/docs/implementation-plan.md b/docs/implementation-plan.md index 2b40351..65aec58 100644 --- a/docs/implementation-plan.md +++ b/docs/implementation-plan.md @@ -187,6 +187,9 @@ a named invariant that the native runtime cannot protect yet. Fensalir for a keyed D3D12 texture/fence lease before decoded camera frames are written. `MimirRuntime` accepts `AquariumRuntimeServices` and commits producer fence values for leased video payloads before Fensalir samples them. + `MimirVideoCaptureDriverSource` forwards the lease client to drivers that + implement `IMimirFensalirTextureLeaseReceiver`, so native/direct camera + drivers can allocate their Fensalir destination texture before capture/decode. Metadata-only cadence frames remain observations with empty payload handles; they do not become fake render requests. The old direct `AquariumGpuSensorFrame` builder has been removed from Mimir's proof path. diff --git a/notes/current-system-map.md b/notes/current-system-map.md index 6e3fa9e..c263416 100644 --- a/notes/current-system-map.md +++ b/notes/current-system-map.md @@ -333,6 +333,9 @@ camera/decode producer writes that shared texture and signals the producer fence, then Mimir carries the same resource key through FieldEvidence. Fensalir waits on committed producer fence values before resolving shader reads. Shared foreign texture handles remain an import edge, not the primary camera authority. +`MimirVideoCaptureDriverSource` propagates the lease client to drivers that +implement `IMimirFensalirTextureLeaseReceiver`, so direct camera drivers can +request the destination texture before emitting a frame descriptor. Metadata-only cadence frames do not create camera surface intents or fake payload requests. The old direct `AquariumGpuSensorFrame` bridge proof has been removed from Mimir's active proof path. Camera image claims currently defer diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index a62fc76..d518f0c 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -47,6 +47,8 @@ Get-Content .\state\evidence.jsonl -Tail 8 are rendering inputs: Mimir asks the engine broker for a keyed D3D12 Texture2D/fence lease, writes decoded frames into that texture, commits the producer fence value, and lowers the same resource key through FieldEvidence. + `MimirVideoCaptureDriverSource` forwards that lease client to direct drivers + that implement `IMimirFensalirTextureLeaseReceiver`. Foreign shared texture handles are import edges, not the primary hot path. - The current Mimir/Fensalir rendering teardown map is [[docs/fensalir-rendering-rebuild-migration|Fensalir Rendering Rebuild diff --git a/src/Mimir.BufferSmoke/Program.cs b/src/Mimir.BufferSmoke/Program.cs index 659ac92..cd02588 100644 --- a/src/Mimir.BufferSmoke/Program.cs +++ b/src/Mimir.BufferSmoke/Program.cs @@ -756,6 +756,20 @@ static int RunFensalirTextureLeaseSmoke() _ = runtime.Frame; } + var receiverDriver = new FakeTextureLeaseVideoDriver(); + using (var runtime = new MimirRuntime( + new AquariumRuntimeOptions(Headless: true, CultCachePath: null), + new MimirSynchronizationSettings(), + [ + new MimirVideoCaptureDriverSource( + new MimirStreamDescriptor("driver-camera", MimirStreamKind.Video, MimirStreamOrigin.LocalDevice), + receiverDriver, + static () => 0) + ])) + { + runtime.AttachServices(new AquariumRuntimeServices(broker)); + } + var buffer = new MimirRollingStreamBuffer( new MimirStreamDescriptor("kiyo-pro-rgb", MimirStreamKind.Video, MimirStreamOrigin.LocalDevice), TimeSpan.FromSeconds(5)); @@ -776,9 +790,10 @@ static int RunFensalirTextureLeaseSmoke() var expectedResourceKey = MimirFensalirTextureLeaseClient.ResourceKeyForSource("kiyo-pro-rgb"); Console.WriteLine( - $"fensalir-texture-lease-smoke leased={lease.IsValid} committed={broker.CommittedFenceValue > 0} resources={frame.Resources.Count} claims={frame.Claims.Count} errors={validation.HasErrors}"); + $"fensalir-texture-lease-smoke leased={lease.IsValid} committed={broker.CommittedFenceValue > 0} driverClient={receiverDriver.HasClient} resources={frame.Resources.Count} claims={frame.Claims.Count} errors={validation.HasErrors}"); return lease.IsValid && + receiverDriver.HasClient && broker.CommittedResourceKey == expectedResourceKey && broker.CommittedVersion == 0 && broker.CommittedFenceValue == 41 && @@ -6068,3 +6083,26 @@ sealed class FakeFieldResourceBroker : IAquariumFieldResourceBroker return true; } } + +sealed class FakeTextureLeaseVideoDriver : IMimirVideoCaptureDriver, IMimirFensalirTextureLeaseReceiver +{ + public string DriverName => "fake-texture-lease-driver"; + + public bool HasClient { get; private set; } + + public void AttachTextureLeaseClient(MimirFensalirTextureLeaseClient? client) + { + HasClient = client != null; + } + + public bool TryCapture(out MimirVideoFrameDescriptor frame, out ReadOnlyMemory data) + { + frame = default!; + data = default; + return false; + } + + public void Dispose() + { + } +} diff --git a/src/Mimir.Runtime/MimirRuntime.cs b/src/Mimir.Runtime/MimirRuntime.cs index 7b8c9fb..243514e 100644 --- a/src/Mimir.Runtime/MimirRuntime.cs +++ b/src/Mimir.Runtime/MimirRuntime.cs @@ -149,6 +149,7 @@ public sealed class MimirRuntime : IAquariumRuntime, IAquariumRuntimeServicesRec public void AttachServices(AquariumRuntimeServices services) { runtimeServices = services; + synchronization.AttachTextureLeaseClient(new MimirFensalirTextureLeaseClient(services.FieldResources)); } private AquariumFrame CreateFrame() diff --git a/src/Mimir.Runtime/Synchronization/IMimirFensalirTextureLeaseReceiver.cs b/src/Mimir.Runtime/Synchronization/IMimirFensalirTextureLeaseReceiver.cs new file mode 100644 index 0000000..8afce15 --- /dev/null +++ b/src/Mimir.Runtime/Synchronization/IMimirFensalirTextureLeaseReceiver.cs @@ -0,0 +1,6 @@ +namespace Mimir.Runtime.Synchronization; + +public interface IMimirFensalirTextureLeaseReceiver +{ + void AttachTextureLeaseClient(MimirFensalirTextureLeaseClient? client); +} diff --git a/src/Mimir.Runtime/Synchronization/MimirSynchronizationHub.cs b/src/Mimir.Runtime/Synchronization/MimirSynchronizationHub.cs index 4a16aed..876caf0 100644 --- a/src/Mimir.Runtime/Synchronization/MimirSynchronizationHub.cs +++ b/src/Mimir.Runtime/Synchronization/MimirSynchronizationHub.cs @@ -9,6 +9,7 @@ public sealed class MimirSynchronizationHub : IDisposable private readonly Dictionary audioSynchronizationReports = new(StringComparer.Ordinal); private readonly Dictionary complexContourReports = new(StringComparer.Ordinal); private readonly MimirChirpBinCalibrationModel? chirpBinCalibrationModel; + private MimirFensalirTextureLeaseClient? textureLeaseClient; private ulong ingestedSamples; private int nextAudioSynchronizationCandidate; @@ -64,6 +65,23 @@ public sealed class MimirSynchronizationHub : IDisposable { Buffers.EnsureBuffer(source.Descriptor); } + + if (source is IMimirFensalirTextureLeaseReceiver receiver) + { + receiver.AttachTextureLeaseClient(textureLeaseClient); + } + } + + public void AttachTextureLeaseClient(MimirFensalirTextureLeaseClient? client) + { + textureLeaseClient = client; + foreach (var source in sources) + { + if (source is IMimirFensalirTextureLeaseReceiver receiver) + { + receiver.AttachTextureLeaseClient(client); + } + } } public int PollSources(int maxSamplesPerSource = 8192) diff --git a/src/Mimir.Runtime/Synchronization/MimirVideoCaptureDriverSource.cs b/src/Mimir.Runtime/Synchronization/MimirVideoCaptureDriverSource.cs index a94ed6e..19ebe19 100644 --- a/src/Mimir.Runtime/Synchronization/MimirVideoCaptureDriverSource.cs +++ b/src/Mimir.Runtime/Synchronization/MimirVideoCaptureDriverSource.cs @@ -1,6 +1,6 @@ namespace Mimir.Runtime.Synchronization; -public sealed class MimirVideoCaptureDriverSource : IMimirStreamSource +public sealed class MimirVideoCaptureDriverSource : IMimirStreamSource, IMimirFensalirTextureLeaseReceiver { private readonly IMimirVideoCaptureDriver driver; private readonly MimirNativeIngestStreamSource nativeSource; @@ -25,6 +25,14 @@ public sealed class MimirVideoCaptureDriverSource : IMimirStreamSource public Func ReadArrivalNs { get; } + public void AttachTextureLeaseClient(MimirFensalirTextureLeaseClient? client) + { + if (driver is IMimirFensalirTextureLeaseReceiver receiver) + { + receiver.AttachTextureLeaseClient(client); + } + } + public bool TryRead(out MimirStreamSample sample) { if (nativeSource.TryRead(out sample)) diff --git a/state/evidence.jsonl b/state/evidence.jsonl index 97467f0..01d0b53 100644 --- a/state/evidence.jsonl +++ b/state/evidence.jsonl @@ -174,3 +174,4 @@ {"ts": "2026-05-27T12:49:27+01:00", "type": "implementation", "status": "ok", "note": "Fensalir now resolves shared Texture2D field resources by native D3D12 handle and accepts Mimir video format names (Bgra8, Gray8/R8, Rg8, Nv12, LeapStereoIr). The camera observation bridge therefore produces resource declarations that can become real engine GPU resources before a selected camera/feature lowering exists."} {"ts": "2026-05-27T12:54:07+01:00", "type": "implementation", "status": "ok", "note": "Mimir's proof path no longer uses the direct AquariumAcousticFieldFrame builder. Sync states lower into FieldEvidence calibration constraints through MapCalibrationConstraints, and the profile/benchmark smokes now measure the claim/defer path until Fensalir owns a selected acoustic visualization/fusion lowering."} {"ts": "2026-05-27T13:26:42+01:00", "type": "decision", "status": "ok", "note": "Fensalir-owned Texture2D leases are the preferred live camera payload authority: Mimir receives AquariumRuntimeServices, requests keyed D3D12 texture/fence leases, writes decoded frames into the engine-owned shared texture, commits producer fence values, and lowers the resource key through FieldEvidence. Imported shared texture handles remain fallback/import edges."} +{"ts": "2026-05-27T13:32:24+01:00", "type": "decision", "status": "ok", "note": "Texture lease services now propagate from MimirRuntime into direct video capture sources. MimirVideoCaptureDriverSource forwards a MimirFensalirTextureLeaseClient to drivers that implement IMimirFensalirTextureLeaseReceiver, so a direct camera driver can request its Fensalir-owned destination texture before it emits the frame descriptor and producer fence value."} diff --git a/state/map.yaml b/state/map.yaml index 55ce88a..fae78f5 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -312,7 +312,9 @@ accepted_design: asks the engine field resource broker for a keyed Texture2D lease, writes decoded frames into the returned shared D3D12 texture, signals the returned producer fence, and commits that fence value before the resource key reaches - shader sampling. `Mimir.BufferSmoke --fensalir-camera-observation-smoke` + shader sampling. `MimirVideoCaptureDriverSource` forwards that lease client + to direct camera drivers that implement `IMimirFensalirTextureLeaseReceiver`. + `Mimir.BufferSmoke --fensalir-camera-observation-smoke` verifies the split, and `--fensalir-texture-lease-smoke` verifies the engine-owned lease path. Camera image claims currently defer until Fensalir has a selected visual fusion/feature extraction lowering for camera textures. Fensalir now owns the first in-process