Prepare an operation by name
Use KernelRequest when an application or framework must select an operation
without including its typed header. Link SimaKernels::request and include
<simaai/kernels/request.h>. Runtime can expose these same types through its own
public header; there is no second tensor representation.
#include <simaai/kernels/request.h>
#include <array>
namespace k = simaai::kernels;
// Inside the application's preparation function:
const std::array inputs{k::TensorSpec{{1, 224, 224, 3}, k::DType::Float32}};
const std::array outputs{k::TensorSpec{{1, 224, 224, 3}, k::DType::Int8}};
const std::array params{
k::Parameter{"multiplier", 0.25F},
k::Parameter{"zero_point", -3},
k::Parameter{"rounding", "nearest_even"}};
auto result = k::make_executable(
{"quant", k::Target::EV74, inputs, outputs, params});
// Check Result<Executable>, then give the executable to Runtime preparation.
// This call does not allocate device buffers or submit device work.
One preparation path, unchanged execution
The generated resolver selects an operation-local request.cpp, which decodes
its fields and calls its typed make_executable(). The typed factory and
check_inference() remain authoritative for shapes, dtypes, layouts, numerical
parameters and backend availability. No operation-name lookup, string parsing or
parameter decoding occurs in submission, completion or numerical loops.
Tensor specifications are the canonical TensorSpec: explicit inputs and
outputs, actual rank up to six, dtype separate from physical layout. Prepared
executables retain everything they need; caller spans need only remain valid
until make_executable() returns. Parameter names, strings, arrays and records
own their storage. Device allocation, binding lifetime, scheduling and cache
coherency remain Runtime responsibilities.
The build registers only its available operations: the host profile excludes
BoxDecode; the EV74-only profile excludes A65-only operations. Unknown names
return InvalidOperation; unsupported targets return UnsupportedTarget when
the operation exists. There is no hidden backend fallback. This is a
version-matched C++ API, not a serialized format or stable binary ABI.
Discover compiled implementations
operations() returns immutable operation names and their compiled targets;
find_operation(name) returns an entry or nullptr. Names and target spans
have library lifetime. Enumeration order is not an operation identity.
Use this catalogue during graph preparation to select an explicit target. It is generated from the same registrations and linked providers as the resolver, not a second support matrix. A listed EV74 provider does not prove that the connected device has matching firmware. Discovery does not replace canonical admission or Runtime's device-capability checks.
Inspect a checked executable
inspect_executable(executable) returns Result<ExecutableInspection>. Check
the result, then retain the inspection while using its input/output specs,
physical requirements, workspace, ownership flags or preparation facts. It
retains the executable, so releasing the original handle does not invalidate
these spans.
Inspection validates structural consistency; it does not repeat numerical inference, authorize actual buffers or provision resources. Moved-from inspections are empty and cannot authorize preparation. Numerical operations still obtain their contracts from canonical factories.
Two identity checks serve different purposes:
a == bmeans both handles retain the exact same immutable checked state. Independently prepared equivalent requests are different states.same_contract_resources(a, b)compares retained target, tensor-contract and resource-recipe identities without allocation or deep comparison. It returns false for empty handles and is not permission to reuse another executor's resources.
Bind dynamic geometry once
bind_variant(executable, capability) returns a retained operation-owned
ExecutableVariant. Bind it during graph preparation, inspect its fields()
and contract_policy(), then retain it. On a geometry-cache miss, call
apply_variant(capability, request) with explicit specifications and positional
values in that field order. Cache the resulting prepared operation in the
execution service; ordinary hits reuse it without name lookup or parameter
decoding.
| Operation/capability | Policy | Ordered fields |
|---|---|---|
EV74 Preproc geometry | FullRecheck | source_roi, source_rois, destination, padding |
A65 BoxDecode image_size | PreserveContract | image_size |
Preproc requires new input/output specs and explicit destination/padding values. It retains static format, interpolation, color, normalization and quantization policy, checks the new geometry canonically, and regenerates accepted-ROI facts. An absent optional value clears that field; an empty ROI list remains an empty batch rather than an ordinary full-frame request.
BoxDecode accepts integer [width, height] and forbids port overrides. It
validates geometry while retaining the exact checked contract, model tables,
execution entry and resource recipe. Runtime separately decides whether its own
prepared resources can be reused.
Unsupported capabilities and invalid values fail explicitly. Applying a variant never mutates the base or an in-flight executable. New geometry can allocate and require preparation; a cache miss may occur every frame when geometry changes continuously. This interface does not promise allocation-free cache misses or replace buffer-binding and lifetime checks.
Strict values
- Fields are case-sensitive. Unknown names and duplicate names are errors, including inside records. Enums use the exact strings below, not numeric IDs.
- Integers preserve signedness until checked against the destination type. Floating values are never truncated into integers; booleans are not integers.
- Float fields accept floating values, not strings or integers. Double-to-float rounding follows normal C++ conversion, but finite overflow and nonzero underflow-to-zero are rejected. NaN/Inf admission is operation-specific.
ParameterArraycontains scalars and is checked for the required length and element types.ParameterRecordscontains flat named scalar records only; recursive dictionaries and JSON are not part of this API.- Absent optional values keep the typed operation defaults. Supplying an invalid
value never falls back to a default.
Errorfield/message pointers refer to static strings and remain valid after request destruction. Unknown/duplicate fields reportparameters, rather than retaining an unsafe caller string.
Parameter names
The operation pages and typed headers define numerical semantics and port roles. This table defines only their named spelling. Unless marked required, fields retain typed defaults. All floating fields below require floating C++ values.
| Operation | Named fields |
|---|---|
cast, casttess, detesscast, detess, histogram | None; tensor specifications select conversion/storage. |
quant, quanttess | Required float multiplier; integer zero_point (default 0); rounding (default nearest_even): nearest_even, toward_zero, toward_positive, toward_negative. |
dequant, detessdequant | Required float scale; integer zero_point (default 0). |
tess | Optional integer int8_channel_padding; typed admission decides when required/forbidden. |
argmax | Integer axis (default -1); bool keepdims (default false). |
fast, fast_brief | Integer threshold (default 30); output_encoding: separate (default) or packed; optional unsigned-range integers grid_columns, grid_rows, minimum_distance (see below). |
tracker | Unsigned-range integers window_half (default 7), max_iterations (20), pyramid_levels (0). |
FAST grid selection
Omit all grid fields to keep raster-first selection. Supplying any grid field
enables grid selection, including an explicit minimum_distance = 0. Omitted
grid fields default to one column, one row and zero minimum distance.
grid_columns must be in 1..W, grid_rows in 1..H, and minimum_distance
in 0..65535 pixels. The grid covers the full input image.
The FAST contract defines cell quotas, score ordering, ties and greedy spacing. FAST+BRIEF uses the same selection before computing descriptors for the retained points.
Preproc
| Field | Value |
|---|---|
input_format | gray, rgb (default), bgr, nv12, i420, nv16 |
output_format | gray, rgb (default), bgr |
interpolation | identity, nearest, bilinear (default), bicubic, box_average |
color_matrix | bt601_full (default), bt709_full |
source_roi | Optional integer [x, y, width, height]; absent means full source frame |
destination | Required integer [x, y, width, height] within output canvas |
source_rois | Flat record list; each record requires integer source_index, x, y, width, height |
affine_offset, affine_multiplier | Three float values; defaults [0,0,0] and [1,1,1], respectively |
padding | Three integers in [0, 255], semantic RGB raw pixels; default [0,0,0] |
quantization_multiplier | Optional float; enables typed quantization |
quantization_zero_point | Integer, default 0; requires quantization_multiplier |
source_rois absence selects ordinary preprocessing; an explicit empty list
selects an empty ROI batch. The typed contract owns conflict checks, invalid-ROI
filtering and output-capacity limits; the decoder only validates record fields.
Each record may also provide destination_x, destination_y,
destination_width and destination_height, all together. Omit all four to
inherit the common destination. Rectangles are checked against the output
canvas; the caller, not the kernel, chooses any aspect-ratio policy.
Per-plane pitch remains in TensorSpec.layout, not a parameter or a buffer
address. Plane offsets are Runtime bindings. Dynamic image geometry is a new
checked request/variant, not mutation of an in-flight executable.
BoxDecode
Required fields are profile, heads, model_input_size,
original_image_size, num_classes, max_detections and
detection_threshold. Sizes are integer
[width, height] arrays. The two limits are class count and final output limit,
not implicit output allocation.
profile:yolo26_v1,yolov5_v1,yolov7_v1,yolo_dfl_v1,yolov6_v1,yolox_v1,decoded_v1,efficientdet_v1,detr_v1,centernet_v1,rcnn_proposals_v1,ssd_v1.heads: record list with required integerboxes_input,scores_input, and optional integerextra_input,auxiliary_input.- Optional
quantization: record list with required integerinput, required floatdequant_scale, and optional integerzero_point. Duplicate input records fail; absence remains distinct from scale one. - Required float
detection_threshold; optional floatnms_iou_threshold(default0). score_activation:identity,sigmoid,softmax. Omission retains the typed recipe's default resolution/required-field checks.task:detection(default),pose,segmentation.resize:centered_letterbox(default),stretch(required for SSD/DETR).ssd_recipe:none(default),ssd300,mobilenet300,mobilenet320,torchvision_lite320.- Integer
mask_basis_input,keypoints,decoded_anchors_per_cell; booldecoded_objectness,decoded_split_extents. Their defaults are absent,17,1,falseandfalse, respectively.
For example, an explicit two-port head is represented as:
k::Parameter heads{"heads", k::ParameterRecords{
{{"boxes_input", 0U}, {"scores_input", 1U}}}};
SuperPoint
Required integer-array model_input_size is [width, height]; integer
topk_capacity is required. Optional profile is a65_v1, lightglue_v1 or
magicleap_demo_v1 (default a65_v1). Other optional fields are float
detection_threshold (default 0), integer nms_radius, and integer
border_margin (both default -1, resolved by the selected profile).
Each of detector_quantization_scale and descriptor_quantization_scale
enables that port's optional quantization. Its accompanying _zero_point is an
integer (default 0) and _reciprocal is a bool (default false); either
requires its corresponding scale.
Scales retain double precision, as in the typed contract.
Add an operation
Keep request.cpp beside the operation's semantic header. Use the private
common/request/reader.h for strict field decoding, call the typed factory, and
register with sima_register_operation(). CMake generates resolver membership
from these registrations: no central enum, static-initializer registry, Runtime
switch or plugin file is needed for ordinary math.
tests/request_contract.cpp compares named and typed preparation, verifies EV
packet equality, exercises rejection cases and checks retained host execution.
The installed-package consumer separately compiles the generic header and links
the preparation APIs using only SimaKernels::request. The package exports
SimaKernels_REQUEST_CATALOGUE_API_REVISION as 1 for this preparation contract;
it is not the release version or a stable binary ABI. A matching declaration or
revision value alone is not proof that the implementations link. These are
contract checks, not EV device
numerical or latency qualification.
Kernel-owned preparation facts
preparation_facts(executable) returns a read-only span<const Parameter>.
The executable owns these values; retain it while using the span. These are cold,
immutable results of canonical validation, not per-inference output data.
Runtime exposes the same accessor for a PreparedOperation. Other operations,
ordinary single-ROI Preproc and empty executable handles currently return no facts.
Preproc ROI-batch preparation publishes:
| Fact | Value | Meaning |
|---|---|---|
requested_rois | unsigned integer | All supplied records, including later drops. |
valid_rois | unsigned integer | Accepted output slots, after capacity filtering. |
dropped_invalid | unsigned integer | Invalid source index or nonpositive extent. |
dropped_overflow | unsigned integer | Valid records beyond output capacity. |
source_indices | signed integer array | Source frame index for each accepted output slot, in order. |
accepted_rois | scalar records | Accepted source index, source rectangle and resolved destination rectangle for each output slot. |
An explicitly empty source_rois list publishes zero counts and an empty index
array. Consumers use these checked facts rather than repeating ROI filtering.
No fact lookup occurs in kernel submission, completion or numerical loops.