Jump to content

HolovizOp

From RidgeRun Developer Wiki

🚧 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.

Contents Pin





HolovizOp

HolovizOp composes image and geometry layers and presents them in a window. Layers may update at different rates: the operator's clock controls when composition is considered, and capture-time rules determine which samples can contribute.

The operator belongs to holoscan::visualization. Include <holoscan/visualization/holoviz_op.hpp> and link holoscan::visualization::op_holoviz. It is a sink with one tensor input per declared layer and no output ports.

Input arguments

Build a LayerStack and pass it with a WindowSinkDesc to the constructor. Layer index zero is backmost; higher indices composite above it. Each layer's name becomes its input port name, accessed through layer_input(index).

Argument What to Choose
layer_stack At most eight layers. Give each image positive maximum width/height and each geometry layer a finite maximum primitive count.
sink Use WindowSinkDesc. Window width/height zero use the backend defaults for a windowed sink, currently 1280 × 720. Fullscreen monitor selection has its own rules in the descriptor.
display_rate A positive period, despite the name. Default is approximately 16.67 ms, or 60 Hz.
max_input_age Defaults to the display period. Choose a freshness bound that accounts for the source period and acceptable latency.

These are captured constructor arguments. To change the stack, bounds, sink or timing, author a new operator and compile a new plan. Declared layer inputs have queue depth eight; buffering changes belong in the graph's connection policy.


Supported Presentation
WindowSinkDesc needs a usable Vulkan/CUDA graphics environment and the board's active display session. ExclusiveDisplaySinkDesc, CudaPitchLinearSinkDesc and CudaArraySinkDesc are declared API variants but fail at startup because their presentation paths are not implemented.


Ports and data contract

Port Memory Queue Trigger Contract
Image layer input (layer_input(index)) Host or CUDA device 8 OnClock Supported unsigned single-plane image selected within max_input_age; the latest image may be reused while it remains fresh.
Geometry layer input (layer_input(index)) Host 8 OnClock Host rank-one F32 geometry data. Missing geometry uses the default policy and is omitted from the frame.

Image dimensions must fit the layer descriptor. Supported image formats are:

ImageFormat Accepted Tensor
kR8Unorm U8 [H,W] or [H,W,1].
kR8G8B8A8Unorm, kB8G8R8A8Unorm U8 [H,W,4], with channel meaning matching the declaration.
kR16Unorm U16 [H,W] or [H,W,1]; also packed U8 [H,W,2].
kR16G16B16A16Unorm U16 [H,W,4]; also packed U8 [H,W,8].

Planar CHW, batched NHWC, signed types, floating-point tensors, kNV12 and kYUYV422 are not supported by the current image path. Use one of the listed single-plane formats and keep image dimensions within the configured bounds.

Geometry configuration

GeometryLayerDesc requires a host, rank-one F32 tensor. Use one topology per layer: only the first entry in topologies is rendered. Rectangle, oval and line-list primitives consume four floats each; crosses consume three; a line strip is an even sequence of (x,y) pairs with at least two points, producing one fewer segment than points. The primitive count must fit max_primitives.

Image and geometry validation failures log and omit that layer for the activation. Synchronization or copy failures propagate as callback errors. Text and LUT descriptors are present in the API, but this operator's frame-processing branches do not render their payloads.

Timing and input selection

The contract() uses OnClock with LatestWithin(max_input_age) on every layer. Images additionally use bounded ReuseLast; geometry, text and LUT use SafeDefault and are omitted when missing. An upstream arrival alone does not trigger rendering.

For a 30 Hz image source feeding a 60 Hz display clock, the image may be selected again on the intervening tick while it remains fresh. A 100 ms bound accommodates that cadence, but also permits that much image age; choose it deliberately. Reuse does not freeze an image indefinitely. The runtime's aggregate missing-data policy decides whether a clock activation is admitted; the operator then renders its selected, non-missing layers.

Example

This configuration fragment assumes an existing graph. Include <chrono>, <utility> and the operator header:

holoscan::visualization::LayerStack layers;
layers.add_image_layer("image", holoscan::visualization::ImageLayerDesc{
    .format = holoscan::visualization::ImageFormat::kR8G8B8A8Unorm,
    .max_width = 1920,
    .max_height = 1080,
});
const auto display_period = std::chrono::duration_cast<std::chrono::nanoseconds>(
    std::chrono::duration<double>{1.0 / 60.0});
auto display = graph.op<holoscan::visualization::HolovizOp>(
    "display", std::move(layers),
    holoscan::visualization::WindowSinkDesc{
        .title = "Holoscan", .width = 1280, .height = 720},
    display_period, std::chrono::milliseconds{100});

Connect a compatible RGBA source to display->layer_input(0). Supply the graph's clock and deployment/partition configuration before compiling. This declares the display; it does not define a camera or constitute a complete application. A period of 60 ms produces about 16.67 Hz, not 60 Hz.

Build

Follow Build the SDK on AGX Orin for the SDK build and installation. Link the installed holoscan::visualization target in the application.


Related examples and concepts

Examples

Concepts

Source You can find the source code at HolovizOp.

Official documentation

NVIDIA Holoscan SDK User Guide provides the official operator and application reference.


Cookies help us deliver our services. By using our services, you agree to our use of cookies.