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§
Sourcefn output_descriptor(
&self,
inputs: &[ImageDescriptor],
) -> Result<ImageDescriptor>
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.
Sourcefn input_regions(
&self,
output: Region,
inputs: &[ImageDescriptor],
) -> Result<Vec<Region>>
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.
Sourcefn compute(&self, inputs: &[Tile<'_>], output: &mut TileMut<'_>) -> Result<()>
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§
Sourcefn rescaled(&self) -> Option<Arc<dyn Op>>
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:
- 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. - The returned instance carries no state bound to the old input.
Ops may memoize tables keyed to the shape they first saw —
resizebuilds 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.
Sourcefn access_pattern(&self) -> AccessPattern
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".