Capability reference
Every operation in the catalog, against every backend: which element types it accepts, which memory layouts, which ranks, and whether it runs a dedicated kernel or is composed from others.
What a row here does and does not mean
A row is a capability declaration, not a test result. It says what
this build of Incin would run if the device were present — the registry is
queried from the same declaration that generates this page, and every advertised
operation must also satisfy the compile-time Execute<O> contract.
It is not evidence that the kernel is correct. The runtime suites exercise representative and boundary behaviour; they do not execute every dtype, layout, rank and training boundary shown below. Closing that gap is tracked as open work rather than claimed as done — see issue #83, a CPU-oracle conformance harness for advertised capabilities.
The distinction is why this page exists. A support matrix that cannot tell you which half you are reading is the kind of claim nobody checks.
Select a row for the element types, layouts, rank and training boundary each backend advertises, the public entry point, and a worked example.
Every public struct, trait, enum and type alias in the ten
shipped crates, read from the reviewed cargo public-api baselines this
repository already gates on. Each links to docs.rs where the released version
publishes it; items added since carry no link rather than a dead one.
The nine element types, read from the DTypeId enum that
defines them, with the storage each one actually occupies, the backends that accept it,
and how many operations do. Select a card for a worked example of the type in use.
Storage is a block encoding, not a scalar width. A dtype declares how many
logical values sit in a block, how many bytes that block costs, and its alignment
— so a type is free to pack. q8_0 already does: 32 values in 34
bytes, 8.5 bits each, because a block carries one f16 scale alongside its
32 quantized bytes.
bool does not. It is one byte per element, so a boolean mask costs
eight times what its information content needs. A bit-packed boolean is expressible in
this model today — it would be a block of 8 values in 1 byte — and the gap
is not the encoding but everything downstream of it: strides are counted in elements
and resolved to byte offsets, so a sub-byte element makes every stride computation,
every view, and every kernel index a bit address. That is a change to the layout model
and to each backend's kernels, not to this table.
What each backend advertises across the catalog: how many operations, how many run a kernel of their own, how many accept a strided operand, and which element types it handles anywhere.
A layout is what a tensor's type claims about the memory behind it.
An operation that allocates states what it allocated, so a result can be reshaped as a
view without a runtime stride scan. The claim is checked where it is made, which is why
ChannelsLast is deliberately not Contiguous.
What each backend accepts
A contiguous-only row makes a working strided kernel unreachable through the public API, so the gap between these two numbers is a capability question, not a performance one.
The shape system, by module. Every rule here is discharged at compile time where the extents are known and falls back to a checked runtime rule where they are not, so a shape error is a type error rather than a panic.
What the three kinds look like
Taken from the opening of the shapes chapter: fully static, a named runtime axis, an unnamed one, the fully dynamic form, and a mismatch that fails to compile.
The types
A target is a device and a dtype taken together. TargetExt
is how tensors are allocated on one: every method here returns a
NoGrad tensor except parameter, because making every tensor
track gradients is the one default that silently costs memory on every tensor a program
builds.
Defining a custom operation, end to end: declare the contract, implement the kernel, close the graph, run it backward. Each step shows the corresponding function from the runnable polar-to-Cartesian example -- two inputs, two outputs, its own backward -- written up in the custom operations chapter.
Rule categories
Eight rules per backend are registered against a category rather than a named operation. They are listed separately because mapping them onto member operations would invent a claim the generated document does not make.
| Backend | Category | Element types | Layouts | Rank | Training | Impl |
|---|
Reviewed public surface
Every public item, per crate, from the checked-in baselines in
docs/public-api/. CI diffs these on a pinned nightly, so an unintended
addition fails the build rather than shipping.
Reading a row
Element types are the dtypes the rule covers. A dtype absent from every rule for an operation is refused by the registry — which is what lets a planner ask before it allocates, rather than discovering it from a trait method that errors at run time.
Layouts are LayoutClass values. contiguous is
dense row-major; strided means the kernel handles a non-dense view without a
copy. The gap between CPU and CUDA here is real, and a kernel that exists while its row
says contiguous is unreachable through the public API.
Rank is the tensor rank the rule accepts; any is an
unbounded rule. Training says whether the rule also covers the backward
pass — a rule marked no still runs under inference.
Generated by tools/build-api-site-data.py
from docs/capabilities.md, which is itself generated from the registrations
in crates/incin-backends/src/capability/tables.rs. Nothing on this page is
maintained by hand.