Skip to main content

Op

Trait Op 

Source
pub trait Op:
    Send
    + Sync
    + Debug {
    // Required methods
    fn name(&self) -> &'static str;
    fn output_descriptor(
        &self,
        inputs: &[ImageDescriptor],
    ) -> Result<ImageDescriptor>;
    fn input_regions(
        &self,
        output: Region,
        inputs: &[ImageDescriptor],
    ) -> Result<Vec<Region>>;
    fn compute(
        &self,
        inputs: &[Tile<'_>],
        output: &mut TileMut<'_>,
    ) -> Result<()>;

    // Provided methods
    fn arity(&self) -> usize { ... }
    fn rescaled(&self) -> Option<Arc<dyn Op>> { ... }
    fn access_pattern(&self) -> AccessPattern { ... }
}
Expand description

A node in the op graph.

Ops are immutable, shared (Arc<dyn Op>), and evaluated concurrently, hence Send + Sync. An op holds its own parameters; the graph supplies the input descriptors, which is what lets one op instance be evaluated against different input shapes.

§Relationship to ARCHITECTURE §Layer 3

Op::input_regions and Op::output_descriptor take the input descriptors explicitly, where ARCHITECTURE writes them in shorthand as input_region(out_region) and output_descriptor(). The semantics are unchanged — an op still cannot know its input shapes without being told them, and passing them keeps ops free of duplicated graph state.

Required Methods§

Source

fn name(&self) -> &'static str

A short, stable name for this op, used in diagnostics.

Source

fn output_descriptor( &self, inputs: &[ImageDescriptor], ) -> Result<ImageDescriptor>

Compute the output shape from the input shapes.

This runs at graph-build time, not evaluation time: descriptors flow forward as the graph is chained, which is what makes Image::metadata free of pixel work (SPEC §Guarantees 3).

§Errors

Returns PixelsError::InvalidArgument if the op’s parameters are incompatible with these inputs (for example a crop outside the image), or PixelsError::Unsupported if the op cannot handle the input pixel format.

Source

fn input_regions( &self, output: Region, inputs: &[ImageDescriptor], ) -> Result<Vec<Region>>

The input regions needed to produce output.

This is the inverse mapping that demand propagation walks backwards (ARCHITECTURE §Layer 4). The returned vector has one region per input, in input order. A pointwise op returns output unchanged; a 5×5 convolution returns it grown by 2px; a resize returns the scaled region plus filter support.

Returned regions must be clamped to their input’s bounds — an op asking for pixels outside its input is a defect, and edge handling (clamp, reflect, …) is the op’s own business.

§Errors

Returns an error if output is not a region this op can produce.

Source

fn compute(&self, inputs: &[Tile<'_>], output: &mut TileMut<'_>) -> Result<()>

Fill output from inputs — the kernel entry point.

inputs holds one tile per input, covering exactly the regions Op::input_regions asked for. output covers the region that was passed to it.

Per ADR-0002 the pixel format is a runtime value here: dispatch once on it into a monomorphized kernel (see dispatch_sample!) rather than branching per pixel.

§Errors

Returns an error if the supplied tiles do not match what Op::input_regions requested, or if the pixel format is one this op does not implement.

Provided Methods§

Source

fn arity(&self) -> usize

The number of inputs this op consumes.

Source

fn rescaled(&self) -> Option<Arc<dyn Op>>

A copy of this op fit for a graph rebuilt at a reduced input resolution, or None if this op must not be.

This is what licenses shrink-on-load: a JPEG can be decoded at 1/8 and fed to resize with the same result. Returning Some asserts two separate things, which is why they are one method — an op that got only the first right would be silently wrong:

  1. The op means the same thing against a smaller input. Three kinds do not, and all three still produce a correctly-shaped image: ops carrying coordinates in input pixels (crop(1000, 1000, ..) names a different part of a source eight times smaller), ops carrying a distance in input pixels (a 3x3 convolution over a 1/8 decode is eight times the blur relative to content), and ops whose second input is a separate image that would not be reduced with it.
  2. The returned instance carries no state bound to the old input. Ops may memoize tables keyed to the shape they first saw — resize builds its filter weights that way — and reusing such an instance against a new shape is at best an error and at worst a resample against the wrong scale.

The default is None, so an op is presumed unsafe until it says otherwise. Declaring it wrongly does not corrupt memory or change the output shape; it silently changes the picture, which is worse, so the conservative default is the right one.

Source

fn access_pattern(&self) -> AccessPattern

How this op reads its inputs; drives tile negotiation (ADR-0003).

Defaults to AccessPattern::Sequential, the safe-and-fast case for pointwise ops. Override it for anything reading a neighbourhood.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§