SuperPoint
SuperPoint turns a detector-logit grid and a coarse descriptor grid into native keypoint, score and descriptor tensors. It executes on A65; requesting EV74 returns an unsupported-target error. It does not infer a profile from a model name and does not consume JSON or a serialized feature-point payload.
Contract
| Port | Shape | Dtype | Meaning |
|---|---|---|---|
| Input 0 | [H,W,65] | INT8, BF16, FP32 | Raw detector logits; channel 64 is dustbin |
| Input 1 | [H,W,D] | INT8, BF16, FP32 | Coarse descriptors before L2 normalization |
| Output 0 | [K,2] | FP32 | (x,y) coordinates in model pixels |
| Output 1 | [K] | FP32 | Detection scores |
| Output 2 | [K,D] | INT8, BF16, FP32 | Sampled, normalized descriptors |
| Output 3 | [1] | INT32 | Number of valid entries |
Input ranks 3–6 are accepted, with only unit leading dimensions: one image per
invocation. D is 1–65535. K is Params::topk_capacity and must be positive.
The detector and descriptor grids must have equal H/W. Their stride is eight
model pixels, and the grids must cover the explicit model dimensions.
Dense input is contiguous HWC or explicit Strided HWC with scalar channel
strides, per-pixel channel padding and tight rows. Singleton outer strides
do not affect addressing. The required span ends after the last logical channel
of the final pixel; trailing padding after that channel is not required. The
prepared dense reader skips padding directly for INT8, BF16 and FP32; no repacking
or widening tensor is needed. INT8/BF16 additionally support MlaCBlocked and
MlaTiled with HWC axes, unit absent D axis and PadTo16 channels. Channel
slices before the final slice end on C16 boundaries. Arbitrary strides, FP32
MLA storage, and compact MLA channel tails are rejected. Outputs are contiguous;
all unused entries are zeroed. Each binding needs scalar alignment and its full
physical capacity, including input tiles and channel padding. Outputs must not
alias one another or either input; read-only inputs may share storage.
INT8 inputs require explicit quantization. With reciprocal=false, decoding is
(q-zero_point)*scale; with reciprocal=true, it is
(q-zero_point)/scale. The distinction preserves the arithmetic of existing
compiled-model contracts. Floating inputs must not supply quantization.
Parameters
profile selects the numerical contract. model_width and model_height are
explicit model-pixel dimensions, not original-camera coordinates.
topk_capacity fixes output capacity. detection_threshold is finite in
[0,1]. nms_radius and border_margin use -1 for profile defaults; explicit
values range from zero to the larger model dimension. Quantization is separately
specified for each INT8 input; its scale is finite and positive and its zero
point lies in [-128,127].
C++ call
Place the includes and namespace aliases at file scope; the remaining statements
belong in a simaai::kernels::Status-returning caller function. input_views and
output_views are caller-supplied arrays of ConstHostBuffer and HostBuffer
in port order, with accessible capacities and alignment from the checked plan.
Keep their storage alive until synchronous execution returns.
services is a caller-supplied HostServices with a valid parallel_for.
Handle allocation exceptions during preparation/context creation at the caller boundary.
#include <utility>
#include <array>
#include <simaai/kernels/ops/superpoint.h>
namespace k = simaai::kernels;
namespace sp = k::ops::superpoint;
const std::array<k::TensorSpec, 2> inputs{
{{{2, 2, 65}, k::DType::Float32}, {{2, 2, 32}, k::DType::Float32}}};
const std::array<k::TensorSpec, 4> outputs{{{{4, 2}, k::DType::Float32},
{{4}, k::DType::Float32},
{{4, 32}, k::DType::Float32},
{{1}, k::DType::Int32}}};
sp::Params params;
params.model_width = params.model_height = 16;
params.topk_capacity = 4;
params.detection_threshold = 0.1F;
auto checked = sp::check_inference({inputs, outputs, params});
if (const auto *error = std::get_if<k::Error>(&checked)) return *error;
const auto plan = std::get<sp::Plan>(std::move(checked));
auto context = sp::create_context(plan, services); // Caller supplies HostServices.
if (!context) return k::Error{k::ErrorCode::UnsupportedEnvironment, "context",
"context preparation failed"};
return sp::execute(plan, *context, input_views, output_views);
See the correctness tests (A65/superpoint/tests/correctness.cpp) for concrete storage,
independent expected results and failure cases.
Memory and lifecycle
Typed request ── check_inference ── immutable Plan
│
HostServices ── create_context
│
Borrowed tensor views ────────────── execute ── four native outputs
check_inference owns metadata validation and storage requirements. It retains
its own tensor descriptions. create_context builds lookup tables, indexing
maps and bounded scratch before the first invocation. Each concurrent execution
needs a distinct context created from that same plan; a context from a different
plan is rejected. A successful execution allocates no heap memory.
make_executable(request, Target::A65) packages the plan for the generic runner. The
runner provisions contexts through its resource recipe and retains the shared
host task service. No operation-specific runner adapter is necessary.
The host service is explicit and borrowed. It synchronously executes task sets,
retiring all started tasks on failure. SuperPoint partitions substantial phases
into at most 16 indexed tasks, requesting at most four concurrent participants;
small phases remain serial. It never creates a private thread pool. The service
provider must outlive all contexts using it. The direct latency catalogue uses
an explicitly serial service (workers1); it does not claim to measure the
production parallel runner.
Numerical behavior
The caller selects A65V1, LightGlueV1 or MagicLeapDemoV1. Unknown or reserved profile values are rejected.
- Read logical channels directly from dense or MLA storage; reconstruct BF16 byte planes where required. Padding is not a detector class.
- Compute profile-specific detector scores and expand coarse cells to model coordinates.
- Apply the profile's threshold, suppression, border and deterministic Top-K rules. Ties order by score descending, then y, x and source bin ascending.
- Prepare unique descriptor-corner work, normalize/cache eligible corners, interpolate descriptors and normalize the selected result.
- Write native tensors directly, zero unused capacity, and publish count only after descriptor computation succeeds.
A65V1
For each cell, select the first maximum among channels 0–63 and compute
The stable sigmoid branch avoids unnecessary overflow. INT8 uses a prepared 511-entry difference table. The profile uses strict threshold comparison and greedy Euclidean suppression (default radius 4, border 0).
The difference tables scale each integer delta in double precision before converting it to FP32. Reciprocal quantization divides the delta by the supplied scale; it does not multiply by a precomputed reciprocal. Thus equal logits keep a zero difference even for the smallest admitted positive scale.
Descriptor coordinates use the established Q4 mapping. INT8 descriptors retain centered integer interpolation with integer rounding before final normalization; this path does not normalize coarse corners first. Floating descriptors use normalized coarse corners and the same profile-specific coordinates.
LightGlueV1
The detector uses a 65-way stabilized softmax, drops dustbin, applies the
LightGlue suppression/refinement policy and uses its descriptor coordinate
mapping (default radius/border 4). INT8 exponentials come from a prepared
max-minus-value table with the same delta-first scaling described above.
The INT8 path accumulates its denominator and rounds its quotient in FP32. Its
multiplication-based prefilter admits equality because the rounded product can
equal a numerator whose quotient rounds above the threshold. The final comparison
remains strictly score > detection_threshold; equal scores are still rejected.
The prefilter boundary is at least the smallest positive FP32 value, rejecting
zero numerators without division while retaining positive subnormals.
The A65 floating SIMD exponential path retains a scalar
recheck near threshold boundaries. Its evaluation order is not interchangeable
with a blanket rewrite to a different softmax implementation.
At threshold zero, a zero approximate foreground exponential also triggers the scalar recheck: its exact FP32 value may be a positive subnormal that must pass the strict threshold. Truly underflowed zero scores remain excluded. Positive exponentials do not trigger this zero-threshold fallback.
MagicLeapDemoV1
The detector evaluates
with double-precision exponentials/denominator. The quotient is rounded to FP32
before the inclusive comparison score >= detection_threshold. A prepared
prefilter uses the threshold's preceding FP32 value, so it can skip divisions
for clearly rejected candidates without discarding scores that round up to
equality. The final comparison uses the original threshold, including at zero.
Greedy Chebyshev suppression defaults to radius/border 4. This formula is
deliberately not substituted by the LightGlue stabilized formula.
Descriptor output
Floating interpolation is followed by L2 normalization, with a 1e-12 norm
floor where the floating path applies. A65 INT8 uses its dedicated integer
interpolation/normalization path. FP32 writes the resulting values. BF16 rounds
to nearest, ties to even. INT8 performs normalization, multiplication by 127,
nearest-even rounding and saturation to [-127,127] in that order.
When the A65 FP32 sum of squares overflows, normalization falls back to a double-precision norm and reciprocal, narrowing only the reciprocal to FP32. This keeps large finite descriptors normalizable even when their norm exceeds the FP32 range. The portable path uses the same double-precision calculation.
INT8 floating readers use NEON only when the prepared FP32 scaling multiplier is normal (finite, nonzero and not subnormal) and the full centered INT8 range stays within FP32's finite range under both the original scale and the rounded multiplier. Preparation checks these bounds once: even a normal multiplier can round upward enough to overflow a product that double-precision scaling keeps finite. Otherwise, dense and tiled reads use the prepared lookup table, computed with double-precision multiplication or division before conversion to FP32. In particular, a zero-point sample remains zero even when a reciprocal multiplier would overflow FP32.
Nearest rounding and gradual underflow are required. Execution checks the calling thread and numerical task workers rather than silently changing their FP state. Nonfinite detector/descriptor data is handled by the retained profile-specific numerical checks; content failures are not transactional rollback. Invalid metadata and buffer bindings are rejected before output writes.
Implementation notes
Logical input reads use prepared tile indexing rather than materializing dense intermediates. Native descriptor output writes directly to its requested tensor: no serialized header, interleaved detection record, or packing copy is involved. Detector candidate buckets, unique descriptor-corner work and task-local scratch are provisioned before execution. Preserve per-profile arithmetic and tie order when changing these implementation choices.
Tests and qualification
tests/correctness.cpp covers admitted ranks, three profiles, input/output
precisions, tiled channel tails, explicit independent physical packing,
normalization, zeroed capacity, guards, reuse and binding rejection.
tests/latency.cpp measures the public checked execution path and reports
preparation separately. Baseline-free reports are measurements, not performance
qualification. Target SIMD and parallel-runner evidence must come from A65 runs;
a successful host build is not target qualification.