# Native Swift and Metal

Use the repository-root Swift package when a macOS or iOS codebase needs direct
HDF5 IO, reusable Metal kernels, or operations on already-resident products.
Pin an exact verified package revision.

## Why Swift is a separate tree

Swift Package Manager requires target-oriented sources, bundled `.metal`
resources, tests, benchmarks, and native library products. This is a packaging
boundary, not separate scientific ownership. The Swift products implement the
same operations, coordinates, dtypes, binning, and provenance as the Python and
WebGPU paths.

## Products and sources

| Product | Responsibility | Source |
|---|---|---|
| `Native4DSTEMIO` | discovery, QH5 indexing, HDF5 access, identities, caches, audits | `native/swift/Sources/Native4DSTEMIO` |
| `Metal4DSTEMKernels` | load plans, decode, binning, BF/DF/ADF, CoM, DPC, iDPC primitives | `.../Metal4DSTEMKernels` |
| `Metal4DSTEMStreamingIO` | bounded QH5 decode, exact `uint64` products, source audit, on-demand native frames | `.../Metal4DSTEMStreamingIO` |
| `MetalDisplayKernels` | range, histogram, transfer function, colormap | `.../MetalDisplayKernels` |
| `MetalImageFFT` | FFT operations on resident 2D products | `.../MetalImageFFT` |
| `MetalImageRuntime` | typed resident surface/statistics state | `.../MetalImageRuntime` |
| `MetalSSBKernels` | exact native 512×512 SSB reconstruction, phase-variance objective, and deterministic fitting | `.../MetalSSBKernels` |

The native package does not provide the Python `screening.prepare` cache
contract. It does provide detector, CoM, DPC/iDPC, display, FFT, load, and SSB
primitives that a native client can compose without changing their scientific
meaning.

## Call and resource path

```text
consumer imports one SwiftPM product
  → public Swift value types validate geometry and provenance
  → product creates or reuses Metal pipelines and buffers
  → bundled .metal resource writes a typed destination buffer
  → caller receives the result without an application-framework dependency
```

`Package.swift` is the build graph. Each library target has one matching source
directory under `native/swift/Sources`. Metal resources are copied by
SwiftPM and resolved from their owning module bundle; clients do not compile a
second copy. Resources the Python package also reads (`colormaps.json`,
`display.metal`, `qh5idx.metal`, `runtime_spatial.msl`, and the `.msl` count
kernels) live once under `src/quantem/gpu`; `Package.swift` points at them
there.

| Product | Kernel/native dependency | Tests |
|---|---|---|
| `Native4DSTEMIO` | `CNativeHDF5` → vendored `CHDF5.xcframework` and zlib | `Native4DSTEMIOTests` plus real-source benchmarks |
| `Metal4DSTEMKernels` | `detector.metal`, `dpc.metal`, `qh5idx.metal` | `Metal4DSTEMKernelsTests` |
| `Metal4DSTEMStreamingIO` | `Native4DSTEMIO` plus `Metal4DSTEMKernels` | synthetic compressed-fixture parity, overflow, cancellation, and opt-in real-source gates |
| `MetalDisplayKernels` | `display.metal`, packaged colormaps | `MetalDisplayKernelsTests` |
| `MetalImageFFT` | `fft.metal`, MPS/MPSGraph frameworks | `MetalImageFFTTests` |
| `MetalImageRuntime` | `MetalDisplayKernels` | `MetalImageRuntimeTests` |
| `MetalSSBKernels` | custom radix-8 FFT, Hermitian SSB reconstruction, fused exact loss | `MetalSSBKernelsTests` plus `metal-ssb-benchmark` |

The package imports no application UI framework. A client owns presentation,
scheduling, and user-visible memory-policy choices; it must not copy or fork
the `.metal` sources.

## Coordinate and buffer contract

Public geometry uses `(row, column) ≡ (r, c)`. Swift properties such as scan
rows/columns and detector rows/columns preserve
$I[R_r,R_c,k_r,k_c]`, even when a Metal buffer uses a private flattened or
detector-major stride.

Load plans record source/output shapes, half-open regions, scan/detector bins,
source/accumulation/output dtypes, bad-pixel policy, and expected bytes. An
automatic detector-bin choice belongs to client policy and must remain visible
in provenance.

## Exact resident summaries

`Native4DSTEMIO` can persist compact, exact products and sufficient statistics
beside a sealed resident cache. This is a prepared-product boundary: it is not a
compressed-source load, and a client must label it accordingly.

| Public type | Contract |
|---|---|
| `Metal4DSTEMResidentSummaryRole` | Names BF, ABF, ADF, total intensity, detector row/column moments, and selected diffraction artifacts |
| `Metal4DSTEMResidentSummaryMetadata` | Schema, source/resident identity, output shape/dtype, scan region/bin, detector bin, count audit, detector bands, selected scan coordinate, and artifact descriptors |
| `Metal4DSTEMResidentSummary` | Validated metadata plus exact artifact bytes |
| `Metal4DSTEMResidentSummaryIO.write(...)` | Atomically creates a new `quantem.gpu.resident-summary/v1` directory; never overwrites an existing summary |
| `Metal4DSTEMResidentSummaryIO.read(...)` | Fails closed on identity, geometry, dtype, bin, audit, size, or SHA-256 mismatch |

The fused
`detector_products_u16_word_major_with_u64_moments` Metal kernel traverses an
exact detector-bin-4 `uint16` resident volume once. It writes BF/ABF/ADF as
`uint32` and total, detector-row, and detector-column moments as `uint64`; the
wider moment dtype prevents overflow before CoM, DPC, or iDPC derivation.

`quantem.gpu` owns the reusable integer artifacts, the reduction kernel, and
strict provenance validation. A native client owns discovery, admission,
scheduling, eviction, memory-pressure response, and the user-visible reason for
any detector bin or prepared reopen. The client must not describe a summary
reopen as a first source encounter or a binned detector as native resolution.
See [Verified benchmark results](../performance/results.md) for the physical
MacBook Pro (M5 Max, 128 GB) and MacBook Air (M2, 8 GB) measurements; this
platform page does not duplicate them.

`MetalSSBEngine` is intentionally narrower than the Python source loader. It
accepts plane-major lossless `uint8` bright-field columns with shape
`[logical_brightfield, scan_row, scan_column]` for a 512×512 scan. It never
crops or bins scan positions. Every result records the logical, executed,
cached, streamed, and proven-zero BF counts plus the exact cache bytes. A client
chooses `cacheBudgetBytes` from its resource policy; a smaller cache streams the
remaining BF terms without changing the objective or normalization.

## Build, profile, and verify

```bash
swift test
swift run -c release native-4dstem-io-benchmark --help
swift run -c release metal-4dstem-indexed-load-benchmark --help
swift run -c release metal-display-benchmark 512
swift run -c release metal-ssb-benchmark \
  METADATA_JSON FULL_BF_U8 REFERENCE_PHASE_F32 7 full 200 3
```

The indexed-load benchmark has an explicit `--uncached-source-reads` diagnostic
mode. On macOS it applies `F_NOCACHE` to source hashing and each indexed source
descriptor and records that control in the emitted raw state. The private
environment seam cannot enable controlled reporting unless the public flag is
also present. This is benchmark instrumentation, not a package load-policy
default and not a claim that source audit, index, or application caches are
absent.

Profile physical-device wall time and Metal command intervals. For unified
memory, distinguish mapped page-in from explicit copies. Acceptance includes
Swift tests, Metal compilation, frozen CPU/CUDA cross-backend fixtures,
rectangular row/column cases, memory-budget failures, and real-device
cold/warm/prepared timings.

Swift tests verify the package boundary; Python parity fixtures adjudicate
cross-runtime numerical meaning. Passing only one of those layers is not a
complete Swift/Metal signoff.

Read [Native 4D-STEM IO](../api/native_4dstem_io.md) and
[Metal image APIs](../api/metal_image.md) for image and IO types. Read the
[SSB API](../api/ssb.md) for `MetalSSBGeometry`, `MetalSSBEngine`, result
provenance, and the application boundary.
