Skill v1.0.2
currentAutomated scan100/1003 files
SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
SPDX-License-Identifier: LicenseRef-NvidiaProprietary
#
NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
property and proprietary rights in and to this material, related
documentation and any modifications thereto. Any use, reproduction,
disclosure or distribution of this material and related documentation
without an express license agreement from NVIDIA CORPORATION or
its affiliates is strictly prohibited.
name: async-operations description: > 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. license: LicenseRef-NvidiaProprietary author: NVIDIA ovrtx tags:
- ovrtx
- async
- operations
tools:
- Read
- Grep
metadata: version: "1.0.2"
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, Covrtx_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
_asyncmethod,wait()for a pending fetch object, thenfetch()the final result. - For non-blocking Python waits, call
wait(timeout_ns=0)first and handleNoneas "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.pysnippetdoc-open-usd-asyncThe same polling pattern applies toopen_usd_asyncandadd_usd_reference_async— callop.wait(timeout_ns=0)to poll, orop.wait()to block.
Non-blocking step with two-stage timeout
Source:tests/docs/python/test_camera_sensors.pysnippetdoc-step-async
Infinite wait (default)
Source:examples/python/minimal/main.pysnippetstepThe synchronousstep()is equivalent tostep_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.pysnippetdoc-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.pysnippetdoc-operation-status
C
Poll with zero timeout
Source:examples/c/minimal/main.cppsnippetload-usd-and-waitThe load snippet demonstrates polling withovrtx_timeout_t{0}.
Poll loop with sleep
Source:examples/c/minimal/main.cppsnippetload-usd-and-wait
Block indefinitely
Source:examples/c/minimal/main.cppsnippetstep-rendererUsesovrtx_timeout_infiniteto block until completion.
Check for errors after wait
Source:examples/c/minimal/main.cppsnippetload-usd-and-waitCheckwait_result.num_error_opsafter anyovrtx_wait_opcall.
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.pysnippetwait-operation-with-statusSource:examples/c/status-queries/main.cppsnippetwait-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 pollovrtx_timeout_infinite-- block indefinitelyovrtx_timeout_t{5000000000}-- 5 seconds in nanoseconds
C wait result fields:
error_op_ids/num_error_ops-- operations that errored since last waitlowest_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)returnsNoneon timeout, which is distinct from a successful result. For operations that returnNoneon success (likereset_stage), use theOperationobject's state to distinguish.- In Python, call
Operation.query_status()beforeOperation.wait()completes; completed operations release their wait-phase context. - In C,
ovrtx_wait_opwaits for all operations up to and including the givenop_id, not just that single operation. - In C, check the
ovrtx_wait_opreturn status before interpretingwait_resultfields. - In C, release each successful
ovrtx_query_op_status()result withovrtx_release_op_status(). - Error strings from
ovrtx_get_last_op_error()are valid only until the nextovrtx_wait_opcall on the same thread.
In Attached Mode (ovrtx 0.4+)
When ovrtx is attached to ovstage, the write side of the async model moves to ovstage's ordinal-keyed submit/observe: ovstage enqueues return an `op_index immediately. Enqueue acceptance does not guarantee successful admission or publication. Wait for each mutation to complete successfully, then advance and wait for the write floor (ovstage_advance_write_floor) before rendering. For data-plane mutations, the STRICTLY_INCREASING admission policy requires a newer ordinal for repeated changes to an affected cell or prim lifecycle, even before sealing; disjoint cells may share an ordinal. Other policies change retained-history admission but still enforce the operation's write floors. ovrtx observes the sealed state by passing the same ordinal to ovrtx_step_with_stage(..., ordinal) and ovrtx_update_from_stage(ordinal)`. See the admission-policy summary and ovstage's authoritative asynchronous submit/observe model.
See docs/core/ovstage_integration.rst, skills/update-0_3-0_4-c/SKILL.md and skills/update-0_3-0_4-python/SKILL.md.
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.