Bind spectrum ramp as field resource
This commit is contained in:
parent
167b87911f
commit
c8d4496cac
7 changed files with 37 additions and 11 deletions
|
|
@ -233,7 +233,8 @@ Fensalir-owned structured buffer resource, so the TubeField path consumes live
|
|||
GPU buffer contents rather than an empty declaration. The runtime-level receipt
|
||||
is `Mimir.BufferSmoke --mimir-spectrum-upload-smoke`: it boots Mimir's frame
|
||||
path, advances spectrum analysis, and verifies one Float32 upload, one planned
|
||||
TubeField packet, and no live legacy spline/buffer-field dashboard input.
|
||||
TubeField packet, a resource-bound local blackbody ramp Texture2D, and no live
|
||||
legacy spline/buffer-field dashboard input.
|
||||
|
||||
### 3. Calibration Constraint
|
||||
|
||||
|
|
|
|||
|
|
@ -145,7 +145,8 @@ a named invariant that the native runtime cannot protect yet.
|
|||
--mimir-spectrum-upload-smoke` boots `MimirRuntime`, advances the synthetic
|
||||
spectrum preview path, and verifies that the frame contains the Float32
|
||||
resource upload plus planned TubeField packet while legacy spline and buffer
|
||||
field inputs stay empty.
|
||||
field inputs stay empty. The same runtime path declares the local blackbody
|
||||
ramp PNG as a GPU-resident Texture2D resource and binds it by resource key.
|
||||
- `MimirFensalirFieldLowering` now emits `AquariumFieldResourceDeclaration`
|
||||
rows for live native/GPU payload views. Observation claims reference
|
||||
`mimir:resource:*` keys, and Fensalir validation/planning can reject or defer
|
||||
|
|
|
|||
|
|
@ -382,7 +382,9 @@ a handle: Mimir uploads the current spectral amplitudes as row-major Float32
|
|||
data into a Fensalir-owned GPU structured buffer before TubeField compute reads
|
||||
it. `Mimir.BufferSmoke --mimir-spectrum-upload-smoke` verifies this through the
|
||||
actual `MimirRuntime` frame path and confirms the legacy direct spline and
|
||||
buffer-field dashboard inputs are empty.
|
||||
buffer-field dashboard inputs are empty. The same path declares the local
|
||||
blackbody ramp as a Texture2D field resource and binds the TubeField material by
|
||||
resource key.
|
||||
|
||||
## Known Risks
|
||||
|
||||
|
|
|
|||
|
|
@ -653,6 +653,9 @@ static int RunMimirSpectrumUploadSmoke()
|
|||
var matchingResources = field.Resources
|
||||
.Where(resource => string.Equals(resource.ResourceKey, "mimir:resource:spectrum:field-upload", StringComparison.Ordinal))
|
||||
.ToArray();
|
||||
var matchingRamps = field.Resources
|
||||
.Where(resource => string.Equals(resource.ResourceKey, "aquarium:resource:ramp:blackbody", StringComparison.Ordinal))
|
||||
.ToArray();
|
||||
var matchingLowerings = field.TubeSplineLowerings
|
||||
.Where(lowering => string.Equals(lowering.ResourceKey, "mimir:resource:spectrum:field-upload", StringComparison.Ordinal))
|
||||
.ToArray();
|
||||
|
|
@ -660,6 +663,7 @@ static int RunMimirSpectrumUploadSmoke()
|
|||
.Where(claim => string.Equals(claim.ClaimKey, "intent:mimir:spectrum:field-upload", StringComparison.Ordinal))
|
||||
.ToArray();
|
||||
var resource = matchingResources.FirstOrDefault();
|
||||
var ramp = matchingRamps.FirstOrDefault();
|
||||
var lowering = matchingLowerings.FirstOrDefault();
|
||||
var claim = matchingClaims.FirstOrDefault();
|
||||
var validation = AquariumFieldEvidenceValidator.Validate(field);
|
||||
|
|
@ -674,6 +678,7 @@ static int RunMimirSpectrumUploadSmoke()
|
|||
!frame.Scene.BufferFieldFrame.HasInput &&
|
||||
upload is not null &&
|
||||
matchingResources.Length == 1 &&
|
||||
matchingRamps.Length == 1 &&
|
||||
matchingLowerings.Length == 1 &&
|
||||
matchingClaims.Length == 1 &&
|
||||
upload.Version == resource.Version &&
|
||||
|
|
@ -683,8 +688,14 @@ static int RunMimirSpectrumUploadSmoke()
|
|||
resource.Access == AquariumFieldShaderAccess.ShaderResource &&
|
||||
string.Equals(resource.Format, "Float32", StringComparison.OrdinalIgnoreCase) &&
|
||||
resource.StrideBytes == sizeof(float) &&
|
||||
ramp.Kind == AquariumFieldResourceKind.Texture2D &&
|
||||
ramp.Residency == AquariumFieldResourceResidency.GpuResident &&
|
||||
ramp.Access == AquariumFieldShaderAccess.ShaderResource &&
|
||||
string.Equals(ramp.Format, "Rgba8Unorm", StringComparison.OrdinalIgnoreCase) &&
|
||||
string.Equals(ramp.SourceUri, @"D:\WIP4\Projects\Aetheria\Assets\Resources\Ramps\blackbody.png", StringComparison.OrdinalIgnoreCase) &&
|
||||
lowering.Width * lowering.Height == upload.Float32Data.Count &&
|
||||
lowering.ClaimKey == claim.ClaimKey &&
|
||||
string.Equals(lowering.RampResourceKey, ramp.ResourceKey, StringComparison.Ordinal) &&
|
||||
claim.PayloadHandle == resource.ResourceKey &&
|
||||
plan.Packets.Any(packet =>
|
||||
packet.Backend == AquariumFieldBackendKind.TubeField &&
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ public sealed class MimirRuntime : IAquariumRuntime
|
|||
private const float SpectrumCameraFitPadding = 1.12f;
|
||||
private const float SpectrumFrustumMinimumNear = 0.01f;
|
||||
private const float SpectrumSplineTubePadding = 0.18f;
|
||||
private const string SpectrumFieldResourceKey = "mimir:resource:spectrum:field-upload";
|
||||
private const string SpectrumRampResourceKey = "aquarium:resource:ramp:blackbody";
|
||||
private const string SpectrumRampTexturePath = @"D:\WIP4\Projects\Aetheria\Assets\Resources\Ramps\blackbody.png";
|
||||
private readonly MimirSynchronizationHub synchronization;
|
||||
private readonly MimirFensalirFieldLowering fieldLowering;
|
||||
private readonly MimirAudioSpectrumAnalyzer spectrumAnalyzer;
|
||||
|
|
@ -244,7 +247,6 @@ public sealed class MimirRuntime : IAquariumRuntime
|
|||
WriteNormalizedSpectrum(spectra[row], samples.AsSpan(row * width, width));
|
||||
}
|
||||
|
||||
const string resourceKey = "mimir:resource:spectrum:field-upload";
|
||||
const string domainKey = "mimir:domain:spectrum:field-upload";
|
||||
const string claimKey = "intent:mimir:spectrum:field-upload";
|
||||
var version = unchecked((ulong)Math.Max(0, spectrumHistorySequence));
|
||||
|
|
@ -264,7 +266,7 @@ public sealed class MimirRuntime : IAquariumRuntime
|
|||
RepresentedCandidateCount: height,
|
||||
Seed: 0x5EC7_0001u);
|
||||
var resource = new AquariumFieldResourceDeclaration(
|
||||
ResourceKey: resourceKey,
|
||||
ResourceKey: SpectrumFieldResourceKey,
|
||||
Kind: AquariumFieldResourceKind.StructuredBuffer,
|
||||
Residency: AquariumFieldResourceResidency.GpuResident,
|
||||
Access: AquariumFieldShaderAccess.ShaderResource,
|
||||
|
|
@ -278,6 +280,10 @@ public sealed class MimirRuntime : IAquariumRuntime
|
|||
Version: version,
|
||||
NativeHandle: IntPtr.Zero,
|
||||
NativeHandleKind: "fensalir-owned-spectrum-upload");
|
||||
var ramp = AquariumFieldResourceDeclaration.LocalTexture2D(
|
||||
SpectrumRampResourceKey,
|
||||
SpectrumRampTexturePath,
|
||||
version: 1);
|
||||
var claim = new AquariumFieldClaim(
|
||||
ClaimKey: claimKey,
|
||||
DomainKey: domainKey,
|
||||
|
|
@ -286,7 +292,7 @@ public sealed class MimirRuntime : IAquariumRuntime
|
|||
Encoding: AquariumFieldEncoding.Tube,
|
||||
Support: support,
|
||||
Proposal: proposal,
|
||||
PayloadHandle: resourceKey,
|
||||
PayloadHandle: SpectrumFieldResourceKey,
|
||||
ObservedTimeNs: 0,
|
||||
Confidence: confidence);
|
||||
var axisStepX = width > 1 ? 10.0f / (width - 1) : 10.0f;
|
||||
|
|
@ -320,13 +326,13 @@ public sealed class MimirRuntime : IAquariumRuntime
|
|||
AquariumFieldGuide.Valid(confidence, spectrumUpdateIntervalSeconds)),
|
||||
],
|
||||
BackendPackets = frame.BackendPackets,
|
||||
Resources = [.. frame.Resources, resource],
|
||||
Resources = [.. frame.Resources, resource, ramp],
|
||||
ResourceUploads =
|
||||
[
|
||||
.. frame.ResourceUploads,
|
||||
new AquariumFieldResourceUpload
|
||||
{
|
||||
ResourceKey = resourceKey,
|
||||
ResourceKey = SpectrumFieldResourceKey,
|
||||
Version = version,
|
||||
Float32Data = samples,
|
||||
},
|
||||
|
|
@ -337,7 +343,7 @@ public sealed class MimirRuntime : IAquariumRuntime
|
|||
new AquariumFieldTubeSplineLowering(
|
||||
LoweringKey: "tube-spline:mimir:spectrum:field-upload",
|
||||
ClaimKey: claimKey,
|
||||
ResourceKey: resourceKey,
|
||||
ResourceKey: SpectrumFieldResourceKey,
|
||||
Width: width,
|
||||
Height: height,
|
||||
StrideBytes: sizeof(float),
|
||||
|
|
@ -357,8 +363,8 @@ public sealed class MimirRuntime : IAquariumRuntime
|
|||
RadiusScale: 0.030f,
|
||||
Alpha: 0.92f,
|
||||
Feather: 0.20f,
|
||||
RampTexturePath: "",
|
||||
RampResourceKey: "",
|
||||
RampTexturePath: SpectrumRampTexturePath,
|
||||
RampResourceKey: SpectrumRampResourceKey,
|
||||
EmissionScale: 10.0f,
|
||||
CatmullRomSubdivisions: 4).Normalized(),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -160,3 +160,5 @@
|
|||
{"ts": "2026-05-26T23:36:00+01:00", "type": "implementation", "status": "ok", "note": "Mimir now feeds spectral frames into the GPU buffer path. Current audio spectra are normalized into a row-major Float32 matrix, declared as mimir:resource:spectrum:field-upload, attached as a field ResourceUpload, and consumed by the TubeField claim/lowering. Fensalir now uploads ResourceUpload Float32 data into resolved structured buffers before TubeField compute runs. Mimir build, Fensalir build/tests/headless reload, and both field smokes passed."}
|
||||
{"ts": "2026-05-26T23:44:26+01:00", "type": "verification", "status": "ok", "note": "Added Mimir.BufferSmoke --mimir-spectrum-upload-smoke to exercise the actual MimirRuntime frame path. The smoke verifies one Float32 spectrum ResourceUpload, one declared GPU structured buffer, one Tube claim/lowering, one planned TubeField packet, and no legacy AquariumSplineFrame or AquariumBufferFieldFrame dashboard input."}
|
||||
{"ts": "2026-05-26T23:48:24+01:00", "type": "verification", "status": "ok", "note": "Headless Fensalir with Mimir.Runtime and MIMIR_SYNTHETIC_SPECTRUM_PREVIEW=1 captured artifacts/runtime/mimir-spectrum-upload-headless.png. The screenshot shows visible TubeField spectrum arcs from the resource-upload path; stderr was empty. Use Mimir.Runtime.csproj, not Mimir.App.csproj, as the dev-reload client assembly because the runtime factory lives there."}
|
||||
{"ts": "2026-05-26T23:49:49+01:00", "type": "implementation", "status": "ok", "note": "Mimir's runtime spectrum FieldEvidence path now declares the blackbody PNG as a GPU-resident Texture2D field resource and binds the TubeSpline lowering to that ramp by resource key, instead of falling back to unbound white/linear material."}
|
||||
{"ts": "2026-05-26T23:51:02+01:00", "type": "verification", "status": "ok", "note": "Runtime blackbody ramp binding verified. Mimir build passed with one unrelated existing Mimir.EveRelay CA2024 warning; --mimir-spectrum-upload-smoke reports resources=2/uploads=1/planned=1/errors=False; both Fensalir field smokes pass; headless Fensalir captured artifacts/runtime/mimir-spectrum-upload-headless-ramp.png with visible ramp-colored TubeField arcs and empty stderr."}
|
||||
|
|
|
|||
|
|
@ -359,6 +359,9 @@ accepted_design:
|
|||
`Mimir.BufferSmoke --mimir-spectrum-upload-smoke` verifies the live
|
||||
`MimirRuntime` frame path emits that Float32 upload and planned TubeField
|
||||
packet while direct spline and buffer-field dashboard inputs remain empty.
|
||||
The runtime spectrum path also declares the local blackbody PNG as a
|
||||
GPU-resident Texture2D field resource and binds the TubeField material by
|
||||
`RampResourceKey`.
|
||||
- `config/perfect-machine.example.json` declares live owners, sensors,
|
||||
reservoir views, and runtime policy.
|
||||
- `src/Mimir.Runtime/Synchronization` now includes the Perfect Machine module
|
||||
|
|
|
|||
Loading…
Reference in a new issue