Renderer Configuration#

The renderer owns ovrtx’s GPU resources, stream-ordered work queue, and rendering pipeline. In standalone mode it also owns a runtime stage that you load USD into. In attached mode (ovrtx 0.4+) it renders scene state managed by an external ovstage instance instead. Create one renderer before loading USD or stepping RenderProducts.

Creating a Renderer#

# Create the Renderer and attach the stage that owns scene data.
print("Creating renderer. The first run of the application will take some time as shaders are compiled and cached...", file=sys.stderr)
renderer = ovrtx.Renderer()
stage = ovstage.Stage("ovrtx.example.minimal")
renderer.attach_ovstage(stage)
print("Renderer created.", file=sys.stderr)

Configuration entries are passed through RendererConfig:

config = ovrtx.RendererConfig(
    sync_mode=True,
    log_file_path=str(output_dir / "config-test.log"),
    log_level="info",
    sensors_allowed_deprecation_base="0.6.0",
    aftermath_mode=ovrtx.AftermathMode.AUTO,
)
renderer = ovrtx.Renderer(config=config)
assert any(component > 0 for component in renderer.version)
assert renderer.config.sync_mode is True
assert renderer.config.log_level == "info"
assert renderer.config.log_file_path == str(output_dir / "config-test.log")
assert renderer.config.sensors_allowed_deprecation_base == "0.6.0"
assert renderer.config.aftermath_mode is ovrtx.AftermathMode.AUTO
    // Create the renderer, providing configuration settings.
    //
    ovrtx_config_t config {};
#ifdef OVRTX_EXAMPLE_STATIC_LOADERS
    // The static loader needs the package root linked beside the executable.
    ovx_string_t ovrtx_package_root = {
        OVX_CONFIG_EXECUTABLE_DIR_TOKEN "/ovrtx",
        sizeof(OVX_CONFIG_EXECUTABLE_DIR_TOKEN "/ovrtx") - 1};
    ovrtx_config_entry_t config_entries[] = {
        ovrtx_config_entry_binary_package_root_path(ovrtx_package_root),
    };
    config.entries = config_entries;
    config.entry_count = sizeof(config_entries) / sizeof(config_entries[0]);
#endif

    // Publish ovrtx's schema paths before either runtime can initialize OpenUSD.
    result = ovrtx_register_schema_paths(&config);
    if (check_and_print_error(result, "register_schema_paths")) {
        return 1;
    }

    std::cerr << "Creating renderer. The first run of the application will take some time as shaders are compiled and cached..." << std::endl;
    result = ovrtx_create_renderer(&config, &renderer);
    if (check_and_print_error(result, "create_renderer")) {
        return 1;
    }
    std::cerr << "Renderer created." << std::endl;

Version and config-entry setup use ovrtx_config_t:

uint32_t major = 0;
uint32_t minor = 0;
uint32_t patch = 0;
ovrtx_get_version(&major, &minor, &patch);

std::string log_level = "info";
ovrtx_config_entry_t entries[] = {
    ovrtx_config_entry_log_level({ log_level.data(), log_level.size() }),
    ovrtx_config_entry_sync_mode(true),
};
ovrtx_config_t config{entries, 2};

ovrtx_renderer_t* configured_renderer = nullptr;
ovrtx_result_t create_result = ovrtx_create_renderer(&config, &configured_renderer);
ASSERT_API_SUCCESS(create_result.status);
ASSERT_NE(configured_renderer, nullptr);

Python’s renderer.config returns a detached RendererConfig copy. In C, ovrtx_get_config() returns a borrowed view whose entry and payload storage remains valid until the renderer is destroyed. Both surfaces report only entries explicitly supplied at creation; omitted defaults and derived internal settings are not included.

Configuration Entries#

Common configuration entries include:

RendererConfig entry

Description

log_file_path=...

Write renderer logs to a file.

log_level=...

Set log verbosity.

suppress_deprecation_warnings=True

Suppress Python and native runtime warnings from deprecated APIs. Compile-time C/C++ diagnostics are unaffected.

keep_system_alive=True

Keep shared graphics resources alive after the last renderer.

enable_minimal=...

Enable or disable Minimal at startup. Default: None (omitted).

enable_realtimepathtracing=...

Enable or disable real-time path tracing (RT2) at startup. Default: None.

enable_pathtracing=...

Enable or disable PathTracing at startup. Default: None.

enable_mdl_displacement=True

Enable MDL material displacement. Disabled when omitted or None.

enable_crash_reporter=False

Do not start the ovrtx crash reporter, for hosts that own crash handling. Enabled when omitted or None. See Embedding in a Host Application.

active_cuda_gpus="0,1"

Restrict renderer-level CUDA-visible devices.

datastore_cache="grpcdns://host:port"

Configure the UJITSO datastore cache. grpcdns_notls:// and local:// are also supported. When omitted, existing cache defaults and environment configuration remain unchanged.

cache_root_path=...

Choose an absolute directory for writable caches. See Cache Locations.

enable_global_cache_root=True

Use the platform cache directory. Enabled by default. See Cache Locations.

enable_geometry_streaming=True

Opt in to geometry streaming. Disabled by default when omitted or None.

motion_bvh=...

Motion BVH mode: "disable" (default), "enable", or "auto". Sensors that require motion effects (for example, lidar, radar, acoustic, rolling-shutter camera) should use "auto" or "enable".

texture_streaming_mode=...

Texture streaming mode: "disable", "synchronous", or "asynchronous" (default).

Config-entry helper

Description

ovrtx_config_entry_log_file_path()

Write renderer logs to a file.

ovrtx_config_entry_log_level()

Set log verbosity.

ovrtx_config_entry_suppress_deprecation_warnings()

Suppress native runtime warnings from deprecated APIs. Compile-time deprecation diagnostics are unaffected.

ovrtx_config_entry_binary_package_root_path()

Point to a custom binary package root. May include OVX_CONFIG_EXECUTABLE_DIR_TOKEN to anchor the path at the running executable’s directory.

ovrtx_config_entry_keep_system_alive()

Keep shared graphics resources alive after the last renderer.

ovrtx_config_entry_enable_minimal()

Enable or disable Minimal at startup. Omitted by default.

ovrtx_config_entry_enable_realtimepathtracing()

Enable or disable real-time path tracing (RT2) at startup. Omitted by default.

ovrtx_config_entry_enable_pathtracing()

Enable or disable PathTracing at startup. Omitted by default.

ovrtx_config_entry_enable_mdl_displacement()

Enable MDL material displacement. Disabled when omitted.

ovrtx_config_entry_enable_crash_reporter()

Do not start the ovrtx crash reporter when false, for hosts that own crash handling. Enabled when omitted. See Embedding in a Host Application.

ovrtx_config_entry_active_cuda_gpus()

Restrict renderer-level CUDA-visible devices.

ovrtx_config_entry_datastore_cache()

Configure the UJITSO datastore cache with grpcdns://, grpcdns_notls://, or local://.

ovrtx_config_entry_cache_root_path()

Choose an absolute directory for writable caches. See Cache Locations.

ovrtx_config_entry_enable_global_cache_root()

Use the platform cache directory. Enabled by default. See Cache Locations.

ovrtx_config_entry_enable_geometry_streaming()

Opt in to geometry streaming. Disabled by default when omitted.

ovrtx_config_entry_motion_bvh()

Motion BVH mode: OVRTX_MOTION_BVH_DISABLE (default), OVRTX_MOTION_BVH_ENABLE, or OVRTX_MOTION_BVH_AUTO.

ovrtx_config_entry_texture_streaming_mode()

Texture streaming mode: OVRTX_TEXTURE_STREAMING_DISABLE, OVRTX_TEXTURE_STREAMING_SYNCHRONOUS, or OVRTX_TEXTURE_STREAMING_ASYNCHRONOUS (default).

Deprecation warnings remain enabled by default. Suppression is intended for phased migrations where deprecated compatibility APIs must remain temporarily; it does not change their behavior or removal schedule.

Texture streaming mode is process-global and applies to every active renderer instance. Synchronous mode processes texture feedback synchronously; it does not make every texture loading operation synchronous.

MDL material displacement is backed by the process-wide Carb setting /rtx/material/enableMDLDisplacement. Renderer creation writes the configured value, or False when the option is omitted, so it does not inherit stale process state.

Renderer-level active_cuda_gpus must be compatible with any per-RenderProduct deviceIds allow-list. Refer to RenderProduct Device Pinning.

Cache Locations#

ovrtx caches compiled shaders and processed assets on disk so later runs can reuse them. By default, writable caches use a directory for the current user and ovrtx version:

Platform

Default cache directory

Linux

$XDG_CACHE_HOME/ovrtx/<version> when XDG_CACHE_HOME is an absolute path; otherwise $HOME/.cache/ovrtx/<version>.

Windows

%LOCALAPPDATA%/ovrtx/<version>.

<version> is the ovrtx runtime’s major.minor.patch version, for example 0.7.0. On Windows, %LOCALAPPDATA% normally points to C:\Users\<username>\AppData\Local.

Choosing a Cache Directory#

Set cache_root_path in RendererConfig, or use ovrtx_config_entry_cache_root_path() in C. Choose an absolute path to a directory your application can write to. ovrtx creates cache directories as needed. The supplied root is used directly: ovrtx does not append ovrtx or a version directory.

Configure the cache root before creating the first renderer. The location applies to all renderers in the process. If you supply a cache root to both ovrtx_initialize() and ovrtx_create_renderer(), use the same path string in both calls. To change the location, restart the application with the new configuration. Existing caches are not moved to the new location.

The following snippets choose a cache directory before creating a renderer. Replace the example path with a writable location for your application.

import os
import ovrtx

cache_root = "C:/ovrtx-cache" if os.name == "nt" else "/tmp/ovrtx-cache"
# Configure the process-wide location before the first renderer.
config = ovrtx.RendererConfig(cache_root_path=cache_root)
renderer = ovrtx.Renderer(config=config)
# Load your scene and render here.
renderer.destroy()
#include <ovrtx/ovrtx.h>
#include <ovrtx/ovrtx_config.h>

int main(void)
{
    #ifdef _WIN32
    const char cache_root[] = "C:/ovrtx-cache";
    #else
    const char cache_root[] = "/tmp/ovrtx-cache";
    #endif

    // Keep the path alive until renderer creation returns.
    ovx_string_t path = {cache_root, sizeof(cache_root) - 1};
    ovrtx_config_entry_t entries[] = {
        ovrtx_config_entry_cache_root_path(path),
    };
    ovrtx_config_t config = {entries, 1};
    ovrtx_renderer_t* renderer = NULL;
    ovrtx_result_t result = ovrtx_create_renderer(&config, &renderer);
    if (result.status == OVRTX_API_ERROR) {
        // Report ovrtx_get_last_error() in your application's error handler.
        return 1;
    }
    // Load your scene and render here.
    ovrtx_destroy_renderer(renderer);
    return 0;
}

Changing the Linux Cache Base Directory#

On Linux, set XDG_CACHE_HOME to an absolute path before starting the application to choose a different base directory for the default cache. ovrtx appends ovrtx/<version> to this path. An explicit cache_root_path takes precedence over XDG_CACHE_HOME.

XDG_CACHE_HOME has no effect on Windows. Use cache_root_path to choose a different cache directory there.

Clearing Caches#

Stop applications using the cache before deleting its directory. ovrtx recreates writable caches on subsequent runs. The next run can take longer while shaders and assets are processed again.

Preserving the Previous Cache Location#

If you want to preserve the previous behavior of putting caches next to the ovrtx library, set enable_global_cache_root=False in Python, or use ovrtx_config_entry_enable_global_cache_root() with false in C. This disables selection of the per-user cache directory. Existing custom cache locations are preserved if already configured.

This option defaults to enabled when omitted (None in Python). An explicit cache_root_path takes precedence over this option. In C, if either ovrtx_initialize() or ovrtx_create_renderer() explicitly enables it, that takes precedence over false in the other call.

Startup Render Mode Availability#

An ovrtx renderer instance is an ovrtx.Renderer object in Python or an ovrtx_renderer_t* handle returned by ovrtx_create_renderer() in C. The first ovrtx renderer instance initializes graphics resources shared by all ovrtx renderer instances in the process. Configure their available rendering modes through RendererConfig in Python, or pass the corresponding entries to ovrtx_create_renderer() in C. These entries are not applied by ovrtx_initialize(), which initializes the library separately.

For each option, True enables the mode and False disables it. Omission (None in Python) leaves that rendering mode’s availability unchanged. By default, all three rendering modes are enabled. At least one mode must remain enabled; a configuration that disables every mode fails ovrtx renderer instance creation.

The following examples create an ovrtx renderer instance with only Minimal available. Disabling PathTracing and RT2 allows ovrtx to avoid allocating resources needed only by those modes.

config = ovrtx.RendererConfig(
    enable_minimal=True,
    enable_realtimepathtracing=False,
    enable_pathtracing=False,
    # Retain shared graphics resources even after this instance is destroyed.
    keep_system_alive=True,
)
renderer = ovrtx.Renderer(config=config)

Initialize the library with ovrtx_initialize() before this code, and call ovrtx_destroy_renderer() when finished with the renderer.

ovrtx_config_entry_t entries[] = {
    ovrtx_config_entry_enable_minimal(true),
    ovrtx_config_entry_enable_realtimepathtracing(false),
    ovrtx_config_entry_enable_pathtracing(false),
    // Retain shared graphics resources even after this instance is destroyed.
    ovrtx_config_entry_keep_system_alive(true),
};
ovrtx_config_t config = {entries, sizeof(entries) / sizeof(entries[0])};
ovrtx_renderer_t* renderer = nullptr;
ovrtx_result_t result = ovrtx_create_renderer(&config, &renderer);

Each additional ovrtx renderer instance shares the initialized rendering mode availability. Omitted options inherit it; an explicit conflicting value fails creation of the new instance. For example, after the Minimal-only creation above, another ovrtx renderer instance cannot enable RT2. The failed request does not change an existing ovrtx renderer instance, release its memory, or trigger shader recompilation. renderer.config reports the supplied entries rather than inherited values.

The choice remains fixed while any ovrtx renderer instance uses the shared graphics resources, or while keep_system_alive=True retains them after the last instance is destroyed. If every instance is created with keep_system_alive=False, destroying all instances releases the shared graphics resources. The next instance can enable RT2/PathTracing.

If an earlier instance used keep_system_alive=True (the default), first create a temporary ovrtx renderer instance with keep_system_alive=False and omit all enable_* options. Its creation inherits the current rendering mode availability and clears the keep-alive reference. Then destroy every ovrtx renderer instance, including the temporary instance. Do not create another instance with keep_system_alive=True during teardown, as that would retain the resources again.

These examples continue from the Minimal-only instance above, clear retention, destroy all instances, and create a new instance with Minimal, RT2, and PathTracing available. The new instance performs graphics initialization again; this is not an in-place configuration change.

# Omit enable_* so this instance inherits Minimal-only availability.
# Creating it clears retention left by keep_system_alive=True.
release_retention = ovrtx.Renderer(config=ovrtx.RendererConfig(keep_system_alive=False))
renderer.destroy()
# Destroy any other ovrtx renderer instances before this final destroy.
release_retention.destroy()

# No instance or keep-alive reference remains: initialize graphics again.
renderer = ovrtx.Renderer(
    config=ovrtx.RendererConfig(
        enable_minimal=True,
        enable_realtimepathtracing=True,
        enable_pathtracing=True,
        keep_system_alive=False,
    )
)
// Omit enable_* to inherit Minimal-only availability and clear keep-alive retention.
ovrtx_config_entry_t releaseEntry = ovrtx_config_entry_keep_system_alive(false);
ovrtx_config_t releaseConfig = {&releaseEntry, 1};
ovrtx_renderer_t* releaseRetention = nullptr;
result = ovrtx_create_renderer(&releaseConfig, &releaseRetention);
if (result.status != OVRTX_API_SUCCESS)
{
    return 1;
}
result = ovrtx_destroy_renderer(renderer);
if (result.status != OVRTX_API_SUCCESS)
{
    return 1;
}
// Destroy any other ovrtx renderer instances before this final destroy.
result = ovrtx_destroy_renderer(releaseRetention);
if (result.status != OVRTX_API_SUCCESS)
{
    return 1;
}

// No instance or keep-alive reference remains: initialize graphics again.
ovrtx_config_entry_t allModesEntries[] = {
    ovrtx_config_entry_enable_minimal(true),
    ovrtx_config_entry_enable_realtimepathtracing(true),
    ovrtx_config_entry_enable_pathtracing(true),
    ovrtx_config_entry_keep_system_alive(false),
};
ovrtx_config_t allModesConfig = {allModesEntries, sizeof(allModesEntries) / sizeof(allModesEntries[0])};
result = ovrtx_create_renderer(&allModesConfig, &renderer);
if (result.status != OVRTX_API_SUCCESS)
{
    return 1;
}

Destroy the new instance when finished. A C application can also release retained graphics resources by calling ovrtx_shutdown() after destroying its ovrtx renderer instances and matching every ovrtx_initialize() call with a shutdown call.

RenderProduct mode selection is separate: it chooses among the available modes. If both Minimal and RT2 are enabled at startup, different RenderProducts can use either mode. Selecting Minimal on a RenderProduct alone does not provide the same memory savings as disabling PathTracing and RT2 at startup.

If a RenderProduct requests a disabled rendering mode, ovrtx logs a warning and selects the first enabled rendering mode in RT2, PathTracing, then Minimal order. With only Minimal available, an unavailable PathTracing or RT2 request renders in Minimal.

Supported Minimal sensor outputs and motion features remain available.

Backend Support#

ovrtx 0.5 public packages use Vulkan on Windows and Linux. The former use_vulkan Python field, OVRTX_CONFIG_USE_VULKAN C key, and ovrtx_config_entry_use_vulkan() C helper have been removed. Passing the retired C key from a pre-0.5 binary returns OVRTX_API_ERROR with a migration diagnostic; recompile the application against the 0.5 headers and remove the backend selection entry.

Runtime Package Layout#

With the shared-loader model, ovrtx expects the binary package bin layout to stay together next to libovrtx-dynamic.so or ovrtx-dynamic.dll. The runtime package includes directories such as cache, library, libs, mdl, plugins, rendering-data, and usd_plugins.

In C, set binary_package_root_path through ovrtx_config_entry_binary_package_root_path() only when static linking ovrtx or when a custom deployment layout separates the loader library from the package directories. When the package bin/ directory lives next to your executable, pass OVX_CONFIG_EXECUTABLE_DIR_TOKEN ("${executable_dir}") instead of resolving the executable directory in client code.

Multi-Renderer Processes#

For processes that create and destroy multiple renderers, initialize ovrtx once up front when using the C API, then shut it down once all renderers are gone.

// The STATIC ovrtx loader resolves the ${executable_dir} token to the running
// executable's directory; ovrtx_setup_runtime() links the package bin beside
// the exe as "ovrtx/", which we hand the loader as the binary package root.
ovx_string_t ovrtx_package_root = {
    OVX_CONFIG_EXECUTABLE_DIR_TOKEN "/ovrtx",
    sizeof(OVX_CONFIG_EXECUTABLE_DIR_TOKEN "/ovrtx") - 1};
ovx_string_t active_cuda_gpus = {ACTIVE_CUDA_GPUS, sizeof(ACTIVE_CUDA_GPUS) - 1};
ovrtx_config_entry_t ovrtx_config_entries[] = {
    ovrtx_config_entry_binary_package_root_path(ovrtx_package_root),
    ovrtx_config_entry_active_cuda_gpus(active_cuda_gpus),
    ovrtx_config_entry_selection_outline_enabled(true),
    ovrtx_config_entry_selection_outline_width(4),
    ovrtx_config_entry_selection_fill_mode(OVRTX_SELECTION_FILL_MODE_GROUP_FILL_COLOR),
};
ovrtx_config_t ovrtx_config = {};
ovrtx_config.entries = ovrtx_config_entries;
ovrtx_config.entry_count =
    sizeof(ovrtx_config_entries) / sizeof(ovrtx_config_entries[0]);

// Publish OVRTX's USD plugin paths before ovstage initializes the shared USD
// runtime. The process-wide USD schema registry only discovers plugins once.
ovrtx_result_t result = ovrtx_register_schema_paths(&ovrtx_config);
if (check_and_print_error(result, "register_schema_paths")) {
    return 1;
}

// The STATIC ovstage loader resolves ${executable_dir} the same way ovrtx does.
// ovstage_setup_runtime() links the package bin beside the exe as "ovstage/"
// (next to "ovrtx/").
ovx_string_t ovstage_package_root = {
    OVX_CONFIG_EXECUTABLE_DIR_TOKEN "/ovstage",
    sizeof(OVX_CONFIG_EXECUTABLE_DIR_TOKEN "/ovstage") - 1};
ovstage_config_entry_t stage_config_entries[] = {
    ovstage_config_entry_binary_package_root_path(ovstage_package_root),
};
ovstage_config_t stage_config {};
stage_config.entries = stage_config_entries;
stage_config.entry_count = sizeof(stage_config_entries) / sizeof(stage_config_entries[0]);
ovstage_api_status_t stage_init_status = ovstage_initialize(&stage_config);
if (stage_init_status != OVSTAGE_OK) {
    print_ovstage_error(nullptr, stage_init_status, "initialize");
    return 1;
}

result = ovrtx_create_renderer(&ovrtx_config, &renderer);
if (check_and_print_error(result, "create_renderer")) {
    ovstage_shutdown();
    return 1;
}

auto cleanup = [&](int exit_code) {
    int result_code = exit_code;
    if (camera_query != OVSTAGE_INVALID_QUERY_HANDLE) {
        if (wait_ovstage_op(stage,
                            ovstage_release_query(stage, camera_query),
                            "release_query")) {
            result_code = 1;
        }
        camera_query = OVSTAGE_INVALID_QUERY_HANDLE;
    }
    if (stage_attached) {
        result = ovrtx_detach_ovstage(renderer);
        if (check_and_print_error(result, "detach_ovstage")) {
            result_code = 1;
        }
        stage_attached = false;
    }
    // After a detach failure, only renderer destruction is supported.
    if (renderer) {
        result = ovrtx_destroy_renderer(renderer);
        if (check_and_print_error(result, "destroy_renderer")) {
            result_code = 1;
        } else {
            renderer = nullptr;
        }
    }
    if (stage) {
        ovstage_api_status_t stage_result = ovstage_destroy_instance(stage);
        if (stage_result != OVSTAGE_OK) {
            print_ovstage_error(stage, stage_result, "destroy_instance");
            result_code = 1;
        }
        stage = nullptr;
    }
    // Release the ovstage static loader (unloads ovstage.dll). Safe even if
    // ovstage_initialize failed or was never reached.
    ovstage_shutdown();
    return result_code;
};

// Register the per-group outline/fill style before any picking happens.
if (!configure_selection_style(renderer)) {
    return cleanup(1);
}

On Linux headless systems, repeatedly creating and destroying renderers can force shared graphics resources to unload and reload. If that causes native driver crashes, configure keep_system_alive=True and initialize ovrtx before creating renderers. If the issue persists, set VK_LOADER_DISABLE_DYNAMIC_LIBRARY_UNLOADING=1 in the process environment.

Cleanup#

Python releases renderer resources when the Renderer object is destroyed. In C, cleanup is explicit:

// Unmap output
ovrtx_cuda_sync_t no_sync = {};
result = ovrtx_unmap_render_var_output(
    renderer, rendered_output.map_handle, no_sync);
if (check_and_print_error(result, "unmap_render_var_output")) {
    ovrtx_destroy_results(renderer, step_result_handle);
    return cleanup(1);
}

// Clean up resources (ovrtx will warn if results are leaked)
result = ovrtx_destroy_results(renderer, step_result_handle);
if (check_and_print_error(result, "destroy_results")) {
    return cleanup(1);
}

Spectral Startup Configuration#

Python RendererConfig.enable_spectral_rendering and C ovrtx_config_entry_enable_spectral_rendering() prepare spectral shaders, materials, and physical illuminants when the first renderer is created. Spectral rendering defaults to off. The choice persists for the process lifetime; conflicting later values fail. See Spectral Rendering for RenderProduct authoring and limitations.

Embedding in a Host Application#

ovrtx reports initialization failures, such as a missing GPU Foundation or CUDA runtime, as errors from renderer creation; it never ends the host process.

By default the first renderer starts the ovrtx crash reporter, which installs process-wide crash handlers and uploads crash dumps. A host application that owns crash handling should disable it with Python RendererConfig(enable_crash_reporter=False) or C ovrtx_config_entry_enable_crash_reporter() on the first renderer. The choice persists for the process lifetime; conflicting later values fail. ovstage never starts a crash reporter.