Async Operations
When to Use
Use this skill when the user asks about async rendering, non-blocking operations, polling, timeouts, or parallel rendering.
Inputs
Resolve inputs in this order: existing repository files and referenced snippets, explicit user request, then broader agent context.
- Target API surface: Python, C/C++, or both.
- Operation type: USD load/reference, render step, reset, clone, query, attribute read/write, or result fetch.
- Desired control flow: blocking wait, non-blocking poll, finite timeout, progress reporting, or two-stage result fetching.
- Language-specific handle involved: Python
Operation, pending fetch object, C ovrtx_op_id_t, or result handle.
- Repository source snippets referenced below. Treat these snippets as the API source of truth.
Prerequisites
- Use an ovrtx checkout that contains the referenced examples and docs tests.
- Read the relevant
> **Source:** snippet before writing or explaining API usage.
- Know whether the async operation completes directly or returns a second-phase object that must be fetched after wait.
Instructions
- Identify whether the caller needs blocking execution, non-blocking polling, progress reporting, or two-phase result fetching.
- In Python, use the two-stage pattern for result-bearing operations: call the
_async method, wait() for a pending fetch object, then fetch() the final result.
- For non-blocking Python waits, call
wait(timeout_ns=0) first and handle None as "still running"; use a finite or infinite wait only when the workflow is ready to block.
- In C, treat every enqueue result as asynchronous: check the enqueue status, wait on
op_index, inspect operation errors, then fetch or destroy result handles as required.
- When changing code, run the narrow async/status docs test or example that owns the snippet whenever practical.
Output Format
- For explanations, cite the relevant API names, source snippets, and caveats.
- For code changes, summarize the files changed, snippets affected, and validation run.
Scripts
This skill has no scripts.
Limitations
- The referenced snippets remain the source of truth; update or add tested snippets before documenting new API usage.
Overview
All ovrtx enqueue operations (open_usd, add_usd_reference, step, write_attribute, etc.) are internally asynchronous and stream-ordered. In Python, the default methods (e.g., open_usd, add_usd_reference, step) block until completion. The _async variants return Operation objects that support polling and custom timeouts.
In C, all enqueue calls return immediately with an ovrtx_op_id_t that can be polled or waited on.
Python
Non-blocking USD load
Source: tests/docs/python/test_support_api.py snippet doc-open-usd-async
The same polling pattern applies to open_usd_async and add_usd_reference_async — call op.wait(timeout_ns=0) to poll, or op.wait() to block.
Non-blocking step with two-stage timeout
Source: tests/docs/python/test_camera_sensors.py snippet doc-step-async
Infinite wait (default)
Source: examples/python/minimal/main.py snippet step
The synchronous step() is equivalent to step_async().wait().
step_async returns Operation[PendingFetch[RenderProductSetOutputs]]
In 0.3.0 the Python RendererResult return type was removed; step_async() now follows the standard two-phase Operation / PendingFetch lifecycle.
Source: tests/docs/python/test_camera_sensors.py snippet doc-step-async
Query progress on long-running operations
Operation.query_status() returns a point-in-time OperationStatus (state, progress, resource counters). Safe to call repeatedly while the op is PENDING; it becomes unavailable after wait() consumes the operation.
Source: tests/docs/python/test_base.py snippet doc-operation-status
C
Poll with zero timeout
Source: examples/c/minimal/main.cpp snippet load-usd-and-wait
The load snippet demonstrates polling with ovrtx_timeout_t{0}.
Poll loop with sleep
Source: examples/c/minimal/main.cpp snippet load-usd-and-wait
Block indefinitely
Source: examples/c/minimal/main.cpp snippet step-renderer
Uses ovrtx_timeout_infinite to block until completion.
Check for errors after wait
Source: examples/c/minimal/main.cpp snippet load-usd-and-wait
Check wait_result.num_error_ops after any ovrtx_wait_op call.
Query operation progress
For long-running operations (e.g., USD loading), call ovrtx_query_op_status(renderer, op_id, &status) to get progress and named resource counters, then ovrtx_release_op_status(renderer, &status) to release the returned pointers. Counter names are operation-dependent (e.g., "shaders", "textures", "materials" during USD loading). A total of 0 means the total is not yet known.
Source: examples/python/status-queries/main.py snippet wait-operation-with-status
Source: examples/c/status-queries/main.cpp snippet wait-operation-with-status-c
For the full pattern, use the status-queries skill.
Key Types / Functions
| Python |
C |
Operation.wait(timeout_ns=None) |
ovrtx_wait_op(renderer, op_id, timeout, &wait_result) |
Operation.wait(timeout_ns=0) |
ovrtx_wait_op with timeout.time_out_ns = 0 |
Operation.wait() → PendingFetch, then .fetch() |
ovrtx_wait_op + per-op fetch call (ovrtx_fetch_results / ovrtx_fetch_read_result / ovrtx_fetch_query_results) |
Operation.query_status() → OperationStatus |
ovrtx_query_op_status(renderer, op_id, &status) + ovrtx_release_op_status(renderer, &status) |
RuntimeError on failure |
wait_result.num_error_ops > 0 |
| Python copies status into dataclasses |
ovrtx_release_op_status(renderer, &status) -- must call after each successful query |
C timeout constants:
ovrtx_timeout_t{0} -- non-blocking poll
ovrtx_timeout_infinite -- block indefinitely
ovrtx_timeout_t{5000000000} -- 5 seconds in nanoseconds
C wait result fields:
error_op_ids / num_error_ops -- operations that errored since last wait
lowest_pending_op_id -- 0 if all operations complete, nonzero if still pending
Troubleshooting
- In Python,
Operation.wait() with no arguments blocks forever -- this is usually what you want.
wait(timeout_ns=0) returns None on timeout, which is distinct from a successful result. For operations that return None on success (like reset_stage), use the Operation object's state to distinguish.
- In Python, call
Operation.query_status() before Operation.wait() completes; completed operations release their wait-phase context.
- In C,
ovrtx_wait_op waits for all operations up to and including the given op_id, not just that single operation.
- In C, check the
ovrtx_wait_op return status before interpreting wait_result fields.
- In C, release each successful
ovrtx_query_op_status() result with ovrtx_release_op_status().
- Error strings from
ovrtx_get_last_op_error() are valid only until the next ovrtx_wait_op call on the same thread.
References
- Use the
> **Source:** directives in this skill to locate tested snippets before reusing API patterns.
- Keep related skills, docs, and snippets synchronized when changing the workflow.
1---2name: async-operations3description: Asynchronous operation patterns including polling, timeouts, and non-blocking workflows. Use when user asks about async rendering, non-blocking operations, polling, timeouts, or parallel rendering.4license: LicenseRef-NvidiaProprietary5---67# Async Operations89## When to Use1011Use this skill when the user asks about async rendering, non-blocking operations, polling, timeouts, or parallel rendering.1213## Inputs1415Resolve inputs in this order: existing repository files and referenced snippets, explicit user request, then broader agent context.1617- Target API surface: Python, C/C++, or both.18- Operation type: USD load/reference, render step, reset, clone, query, attribute read/write, or result fetch.19- Desired control flow: blocking wait, non-blocking poll, finite timeout, progress reporting, or two-stage result fetching.20- Language-specific handle involved: Python `Operation`, pending fetch object, C `ovrtx_op_id_t`, or result handle.21- Repository source snippets referenced below. Treat these snippets as the API source of truth.2223## Prerequisites2425- Use an ovrtx checkout that contains the referenced examples and docs tests.26- Read the relevant `> **Source:**` snippet before writing or explaining API usage.27- Know whether the async operation completes directly or returns a second-phase object that must be fetched after wait.2829## Instructions30311. Identify whether the caller needs blocking execution, non-blocking polling, progress reporting, or two-phase result fetching.322. In Python, use the two-stage pattern for result-bearing operations: call the `_async` method, `wait()` for a pending fetch object, then `fetch()` the final result.333. For non-blocking Python waits, call `wait(timeout_ns=0)` first and handle `None` as "still running"; use a finite or infinite wait only when the workflow is ready to block.344. In C, treat every enqueue result as asynchronous: check the enqueue status, wait on `op_index`, inspect operation errors, then fetch or destroy result handles as required.355. When changing code, run the narrow async/status docs test or example that owns the snippet whenever practical.3637## Output Format3839- For explanations, cite the relevant API names, source snippets, and caveats.40- For code changes, summarize the files changed, snippets affected, and validation run.4142## Scripts4344This skill has no scripts.4546## Limitations4748- The referenced snippets remain the source of truth; update or add tested snippets before documenting new API usage.4950## Overview5152All ovrtx enqueue operations (`open_usd`, `add_usd_reference`, `step`, `write_attribute`, etc.) are internally asynchronous and stream-ordered. In Python, the default methods (e.g., `open_usd`, `add_usd_reference`, `step`) block until completion. The `_async` variants return `Operation` objects that support polling and custom timeouts.5354In C, all enqueue calls return immediately with an `ovrtx_op_id_t` that can be polled or waited on.5556## Python5758### Non-blocking USD load5960> **Source:** `tests/docs/python/test_support_api.py` snippet `doc-open-usd-async`61>62> The same polling pattern applies to `open_usd_async` and `add_usd_reference_async` — call `op.wait(timeout_ns=0)` to poll, or `op.wait()` to block.6364### Non-blocking step with two-stage timeout6566> **Source:** `tests/docs/python/test_camera_sensors.py` snippet `doc-step-async`6768### Infinite wait (default)6970> **Source:** `examples/python/minimal/main.py` snippet `step`71>72> The synchronous `step()` is equivalent to `step_async().wait()`.7374### step_async returns Operation[PendingFetch[RenderProductSetOutputs]]7576In 0.3.0 the Python `RendererResult` return type was removed; `step_async()` now follows the standard two-phase `Operation` / `PendingFetch` lifecycle.7778> **Source:** `tests/docs/python/test_camera_sensors.py` snippet `doc-step-async`7980### Query progress on long-running operations8182`Operation.query_status()` returns a point-in-time `OperationStatus` (state, progress, resource counters). Safe to call repeatedly while the op is `PENDING`; it becomes unavailable after `wait()` consumes the operation.8384> **Source:** `tests/docs/python/test_base.py` snippet `doc-operation-status`8586## C8788### Poll with zero timeout8990> **Source:** `examples/c/minimal/main.cpp` snippet `load-usd-and-wait`91>92> The load snippet demonstrates polling with `ovrtx_timeout_t{0}`.9394### Poll loop with sleep9596> **Source:** `examples/c/minimal/main.cpp` snippet `load-usd-and-wait`9798### Block indefinitely99100> **Source:** `examples/c/minimal/main.cpp` snippet `step-renderer`101>102> Uses `ovrtx_timeout_infinite` to block until completion.103104### Check for errors after wait105106> **Source:** `examples/c/minimal/main.cpp` snippet `load-usd-and-wait`107>108> Check `wait_result.num_error_ops` after any `ovrtx_wait_op` call.109110### Query operation progress111112For long-running operations (e.g., USD loading), call `ovrtx_query_op_status(renderer, op_id, &status)` to get progress and named resource counters, then `ovrtx_release_op_status(renderer, &status)` to release the returned pointers. Counter names are operation-dependent (e.g., `"shaders"`, `"textures"`, `"materials"` during USD loading). A `total` of 0 means the total is not yet known.113114> **Source:** `examples/python/status-queries/main.py` snippet `wait-operation-with-status`115>116> **Source:** `examples/c/status-queries/main.cpp` snippet `wait-operation-with-status-c`117118For the full pattern, use the `status-queries` skill.119120## Key Types / Functions121122| Python | C |123|--------|---|124| `Operation.wait(timeout_ns=None)` | `ovrtx_wait_op(renderer, op_id, timeout, &wait_result)` |125| `Operation.wait(timeout_ns=0)` | `ovrtx_wait_op` with `timeout.time_out_ns = 0` |126| `Operation.wait()` → `PendingFetch`, then `.fetch()` | `ovrtx_wait_op` + per-op fetch call (`ovrtx_fetch_results` / `ovrtx_fetch_read_result` / `ovrtx_fetch_query_results`) |127| `Operation.query_status()` → `OperationStatus` | `ovrtx_query_op_status(renderer, op_id, &status)` + `ovrtx_release_op_status(renderer, &status)` |128| `RuntimeError` on failure | `wait_result.num_error_ops > 0` |129| Python copies status into dataclasses | `ovrtx_release_op_status(renderer, &status)` -- must call after each successful query |130131C timeout constants:132- `ovrtx_timeout_t{0}` -- non-blocking poll133- `ovrtx_timeout_infinite` -- block indefinitely134- `ovrtx_timeout_t{5000000000}` -- 5 seconds in nanoseconds135136C wait result fields:137- `error_op_ids` / `num_error_ops` -- operations that errored since last wait138- `lowest_pending_op_id` -- 0 if all operations complete, nonzero if still pending139140## Troubleshooting141142- In Python, `Operation.wait()` with no arguments blocks forever -- this is usually what you want.143- `wait(timeout_ns=0)` returns `None` on timeout, which is distinct from a successful result. For operations that return `None` on success (like `reset_stage`), use the `Operation` object's state to distinguish.144- In Python, call `Operation.query_status()` before `Operation.wait()` completes; completed operations release their wait-phase context.145- In C, `ovrtx_wait_op` waits for all operations up to and including the given `op_id`, not just that single operation.146- In C, check the `ovrtx_wait_op` return status before interpreting `wait_result` fields.147- In C, release each successful `ovrtx_query_op_status()` result with `ovrtx_release_op_status()`.148- Error strings from `ovrtx_get_last_op_error()` are valid only until the next `ovrtx_wait_op` call on the same thread.149150## References151152- Use the `> **Source:**` directives in this skill to locate tested snippets before reusing API patterns.153- Keep related skills, docs, and snippets synchronized when changing the workflow.