Complete Operator Patterns
🚧 Documentation is under development
The Holoscan SDK guide is currently under active development. Some sections may be incomplete or change without notice.
Questions? Contact RidgeRun or email to support@ridgerun.com.
-
Overview
-
Build, Run, and Validate
-
Core Concepts
-
Operators and Graphs
-
Tensor Data and Memory
-
Interprocess Communication
-
-
Application and Operator Development
- Building an HSDK Application
- Writing a Minimal Operator
- Typed Parameters and Configuration
- Reading, Writing, and Forwarding Data
- Writing Tensor Operators
- Complete Operator Patterns
- Authoring Runtime Behavior
- Runtime Parameter Updates
- Lifecycle Callbacks and Restart Control
- Performance and Debugging
- SDK Source Map
-
Operator Reference
-
Core Operators
-
Holoscan Camera
-
Holoscan RidgeRun
- Overview
- Build and Installation
- ArgusCameraOp
- V4L2SourceOp
- V4L2UserPtrSourceOp
- BgraToPlanarTensorOp
- RawBayerToBgraOp
- RawBayerToYoloTensorOp
- YuyvToBgraOp
- TensorRtInferenceOp
- DrmDisplayOp
- DrmBgraDisplayOp
- X11DisplayOp
- CudaCompositorOp
- DepthColorizerOp
- FakesinkOp
- FrameSkipperOp
- InterprocessSrcOp
- TestPatternOp
-
-
Migration from Holoscan 4.x
-
Examples
-
Core
-
Holoscan Camera
-
Holoscan RidgeRun
-
-
Benchmark and Use Cases
-
Holoscan vs GStreamer
- Overview
-
Capture and Display
-
Capture and Inference
- Compare the workloads
- Implemented Applications
- Framework Selection
- Interprocess
-
Complete Operator Patterns
Once the operator flow is familiar, start from the complete example that matches the data your application needs to move. Each pattern connects the operator declarations, graph, compilation, run control, result checks, and shutdown in one program. Adapt the smallest matching pattern, then return to the focused guides when a design choice needs more explanation.
Choose a complete pattern
Use the application outcome to choose a starting point:
| Application need | Start with | What it demonstrates |
|---|---|---|
| A small scalar pipeline | Writing a Minimal Operator or First Pipeline | Operator declarations, graph wiring, compilation, and run control. |
| A host Tensor produced and inspected in one process | Tensors 101 | Runtime-owned host storage, checked writes, publication, and bounded inspection. |
| A device Tensor with a separate inspection branch | Tensors in Depth | CUDA-stream writes, device processing, explicit host readback, and resource cleanup. |
| Structured sensor measurements | Schema Payloads | Generated schema payloads, sensor metadata, validation, and bounded completion. |
| An existing Tensor should pass through unchanged | Forward an existing Tensor sample | A pass-through output and sample-preserving publication. |
| A fixed binary control contract is required | Raw POD payloads | Explicit identity and byte-layout compatibility for a narrow integration boundary. |
The official Your First Operator in the NVIDIA Holoscan SDK documentation is the shortest external introduction. For Tensor applications, continue with Tensors 101 in the NVIDIA Holoscan SDK documentation.
Follow the complete application flow
All of the patterns follow the same user-visible sequence:
| Stage | Application decision | Continue with |
|---|---|---|
| Describe | Declare operators, typed ports, parameters, and Tensor or schema contracts. | Reading and Writing Values and Samples |
| Connect | Build the graph and choose the input that drives each activation. | Building Graphs and Queue Policies |
| Compile | Check that the authored graph and resource bounds form an accepted plan. | Automatic Partitioning and Plan Inspection |
| Run | Choose blocking or asynchronous control, then observe results and shutdown. | Running and Stopping |
| Adapt | Change the payload path, ownership, or preparation boundary to match the application. | Allocation Ownership and Tensor Pools |
The complete source files below are the runnable reference for each path. The snippets on this page point to the decision being demonstrated; they are not replacements for the full program.
Start with a host Tensor round trip
Tensors 101 is a compact host-Tensor application. A periodic producer creates a fixed float32 array, a downstream inspector receives it, and the application checks the observations before shutting down. It is a useful first Tensor pattern when the application needs runtime-owned storage and CPU access.
The producer declares a host output with finite capacity and writes each result before publishing it. The inspector checks the received representation, readiness, byte count, and values before releasing its read claim. The main() connects the graph, compiles it, runs it asynchronously, and verifies observations, termination, and diagnostics.
Use Writing Tensor Operators when the producer must transform the Tensor, and Allocation Ownership and Tensor Pools when retained samples or pool capacity affect the design.
Add device storage and an inspection branch
Tensors in Depth is the next step when processing belongs on a CUDA device. Its source writes device storage on the runtime stream, sends the result to a device consumer, and adds a separate inspection branch that copies selected data to host memory.
The source checks the assigned stream and every allocation, write, commit, and publication result. The device consumer receives ready data and performs a device-to-device copy for its work. The inspection sink owns the private readback resources until the copy completes.
Use Zero-Copy Data Flow and CUDA Stream Ordering for readiness and private-stream obligations. A shared Tensor handle preserves the backing identity; the example's device computation and host inspection still make their own explicit data movements.
Carry structured sensor measurements
Schema Payloads shows three independent schema lanes, including an IMU measurement path. The IMU producer fills a generated value with frame, timestamp, sequence, and measurement fields. The IMU sink checks the received value and its nested metadata before interpreting it. The main() compiles the lanes, waits for bounded completion, and checks the expected observations.
Use Sensor Payloads and Schemas to choose the sensor payload shape. That page introduces image and IMU schema types, acquisition metadata, and the relationship between a schema value and its Tensor fields.
Build and run a complete program
Each example directory includes an installed-consumer CMake file. Choose one pattern, copy its source and CMake file into an application workspace, then configure and build it with the SDK installation that your application uses:
sdk_source=/path/to/holoscan-sdk sdk_install=/opt/nvidia/holoscan example=tensors_101 workspace="$PWD/operator-patterns/$example" mkdir -p "$workspace" cp "$sdk_source/examples/$example/cpp/$example.cpp" "$workspace/" cp "$sdk_source/examples/$example/cpp/CMakeLists.min.txt" "$workspace/CMakeLists.txt" cmake -S "$workspace" -B "$workspace/build" \ -DCMAKE_PREFIX_PATH="$sdk_install" cmake --build "$workspace/build" ctest --test-dir "$workspace/build" --output-on-failure
Use tensors_101 for a host-only application path. Select tensors_in_depth when a usable CUDA device is available, and select schema_payloads when the application needs generated sensor values. The example source and the installed SDK must come from the same SDK build family.
Forward an existing Tensor sample
Use a pass-through output when the next operator should receive the existing Tensor and its sample metadata. The output declares TensorOutputStorage::kPassThrough so the graph validates a compatible representation without requesting new backing.
With compatible Input<Tensor> and Output<Tensor> ports, the compute method can forward the owning sample:
holoscan::expected<void, holoscan::Error> compute(
holoscan::ExecutionContext&) override {
auto sample = input.receive();
if (!sample) {
return holoscan::make_unexpected(std::move(sample).error());
}
return output.emit(std::move(*sample));
}
The sample overload of emit() preserves the sample's capture, source clock, trace, frame identity, and semantic flags. Forwarding does not authorize the operator to modify the received Tensor. See Reading and Writing Values and Samples for the read and publication choices.
Use a raw POD only when its contract is appropriate
An application-defined C++ struct does not become a port payload just because it is copyable. A generated schema is the usual choice for structured sensor messages. The raw-POD path fits a narrow, coordinated binary contract where the producer and consumer control the identity and layout together.
The declaration requires ChannelTypeIdentity<T> and ChannelPodLayout<T> specializations. The layout validator checks identity and byte coverage. Pointer members, implicit padding, and a size-only identity do not form a portable contract.
Use the Experimental POD Payloads example for the complete producer and consumer. Keep this path separate from the Tensor and generated-schema paths so the receiving application knows exactly which binary layout it accepts.