Generated banner for Omniverse Usd Performance Tuning
Generated logo for Omniverse Usd Performance Tuning

Omniverse Usd Performance Tuning

OpenAIOfficialCreated by NVIDIA OmniverseDistributed by OpenAI

  • Skill
  • Workflow
  • Software development
  • Apache-2.0
  • Medium risk
  • Has scripts

From the author

Top-level workflow skill for USD performance diagnosis and optimization. Use for slow loading, high memory, low FPS, or 'optimize my scene' requests; delegates auth/runtime setup to Phase 0 owners.
— the description by NVIDIA Omniverse

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

The omniverse-usd-performance-tuning skill provides a structured, end-to-end procedure for addressing performance bottlenecks in USD assets. It manages the lifecycle of performance tuning, from initial runtime context setup and baseline profiling to composition auditing, validation, and targeted scene optimization. The skill enforces a rigorous milestone-based approach, ensuring that all destructive operations are planned and approved, and that performance improvements are verified through comparative profiling and standardized reporting.

What it does

  • Orchestrates the end-to-end USD performance tuning lifecycle.
  • Validates runtime environments and handles authentication for remote assets.
  • Conducts composition audits and structural assessments of USD stages.
  • Executes validated optimization operations using Scene Optimizer.
  • Generates structured optimization reports comparing baseline and post-optimization metrics.
  • Enforces safety gates for destructive operations and mutation.

When to use it

  • When a USD scene exhibits slow loading times or low frame rates.
  • When memory usage is excessively high or GPU crashes occur.
  • When you need to optimize a scene for better interactivity or performance.
  • When you need to diagnose CAD conversion quality issues.
  • When you need to validate a scene before and after applying optimizations.

Advantages

  • Ensures consistent performance diagnosis through a standardized workflow.
  • Prevents accidental data loss by requiring approval for destructive operations.
  • Provides clear, evidence-based reporting on performance improvements.
  • Integrates seamlessly with existing Omniverse validation and optimization tools.
  • Maintains strict separation between diagnosis, planning, and execution phases.

Usage examples

“This USD scene loads very slowly; please triage what I should check first.”
The agent will initiate the runtime context gate, perform a composition audit, and provide a structured plan to identify the source of the slow load time.
“Optimize my CAD scene for better performance.”
The agent will verify the runtime, assess the CAD conversion quality, and propose a milestone-based optimization plan including validation and profiling.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/openai/omniverse-usd-performance-tuning/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip omniverse-usd-performance-tuning.zip -d .agents/skills

Documentation by NVIDIA Omniverse

Omniverse USD Performance Tuning

<!-- SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -->

<!-- SPDX-License-Identifier: Apache-2.0 -->

When to Use

Use this workflow for broad performance asks such as slow loading, high memory, low FPS, GPU crashes, conversion-quality triage, or generic requests to optimize a USD scene.

Instructions

  1. Start from the mandatory runtime context gate before producing tuning output, unless the prompt is only asking for a static classification test.

  2. Classify broad optimization requests as ready_to_plan; reserve approval_required for prompts that explicitly name a destructive operation to execute before planning.

  3. Plan the full canonical chain through optimization-report, preserving the structured milestone order and the profile-stage:baseline / profile-stage:after labels when listing milestones.

  4. Invoke downstream skill bodies only when their phase is reached, and keep raw runtime artifacts on disk while reading compact summaries.

Frontmatter keeps version and tools at top level for agentskills.io runtime compatibility. NVCARPS discoverability fields live under metadata.

Output Format

Return a plan or status summary that names the selected entry skill, uses ready_to_plan for generic optimization requests, includes the full milestone chain through optimization-report, and labels profile phases as profile-stage:baseline and profile-stage:after. For structured outputs, the broad-optimization milestone subsequence is omniverse-usd-performance-tuning -> profile-stage:baseline -> usd-structure-assessment -> usd-validation-runner -> restructure-decision -> apply-restructure -> so-run-validators -> so-interpret-validators -> so-run-operations -> profile-stage:after -> compare-profiles -> optimization-report. End-to-end execution should produce an optimized stage when mutation runs and a report conforming to the optimization-report reference's schema (scripts/optimization-report.schema.json within that reference).

Use this workflow for broad performance asks such as slow loading, low FPS, high memory, GPU crashes, conversion quality, or "optimize my scene."

Entry skill rule

This skill is the named entry point for broad performance work whenever the agent has any verified way to do that work. Runtime probing details live in setup-usd-performance-tuning; this rule only decides which skill owns the user-facing performance request.

  • If the setup probe shows any verified runtime path - Kit, standalone, or even a partial stack such as Asset Validator only - enter here. If the user's requested tool is missing, return the specific blocked_code (blocked_missing_scene_optimizer, blocked_missing_so_operation, etc.) instead of substituting another workflow.

  • Enter at setup-usd-performance-tuning only when no runtime path is verified and runtime choice/setup is the first unresolved problem.

  • For omniverse:// assets, enter at omniverse-authentication first. Authentication precedes setup and triage for remote assets.

The decision is about ownership, not order. Setup, authentication, and triage all run in their normal phase order; this rule only fixes which skill the agent names as the entry skill in its response.

Runtime context — session-start gate (mandatory)

Before any other tuning output, follow the mandatory session-start gate in skills/omniverse-usd-performance-tuning/references/setup-usd-performance-tuning/references/runtime-context-header.md. That reference owns output_path, the canonical setup-preflight.json location, Format A/Format B, and the "do not improvise a silent probe" anti-pattern.

Required outcomes:

  • Missing or unreadable preflight: invoke setup-usd-performance-tuning.

  • Present preflight: print Format A and wait for the user to choose Continue, Change Kit, Switch to standalone, or Re-run probe.

  • Confirmed runtime in the same session: use compact Format B for follow-up status.

[Kit: {runtime_context.kit.application} {runtime_context.kit.version}  |  SO: {runtime_context.sceneOptimizer.version}  |  AV: {runtime_context.assetValidator.version}]

Runtime artifact token budget

Before reading Kit logs, Asset Validator CSVs, Scene Optimizer logs, Tracy CSVs, or other runtime output, follow references/runtime-artifact-token-budget.md. Keep raw artifacts on disk, read summary JSON first, and use bounded log snapshots instead of full dumps or live streams.

Plan-time vs execution-time approval

approval_required at planning time is reserved for requests that explicitly name a destructive operation. Use the following rule when deciding between ready_to_plan and approval_required:

  • approval_required at planning time — the user's request itself names a destructive operation: "flatten this stage", "decimate the meshes", "merge prototypes", "delete unused prims", or any specific named mutation that cannot be undone within the same workflow. In this case the agent's first response must be an approval prompt that names the operation, before the agent commits to a plan that executes it.

  • ready_to_plan at planning time — the user's request is general: "optimize this scene", "make it load faster", "reduce GPU memory", "improve interactivity". The agent lays out the full plan, including any destructive operations the plan would invoke (for example so-run-operations with mergeMaterials), without withholding the plan itself. Approval for each destructive operation is requested alongside plan approval.

The distinction is between authorising a plan and authorising a destructive action. A general optimisation request authorises planning; it does not authorise execution of specific destructive operations.

For structured runtime-test responses and similar planning summaries:

  • A future restructure-decision prompt is a planned user-decision gate, not a reason to set the top-level response decision to approval_required for a generic optimization request.

  • For a generic optimization request, set decision: "ready_to_plan" and include the full intended chain in both committed_milestones and planned_phases, through optimization-report.

  • It is valid for gates_observed to include asks_user_for_restructure_decision while the top-level decision remains ready_to_plan.

  • Whenever a chain names profile phases, use the exact labels profile-stage:baseline and profile-stage:after; do not emit the ambiguous bare profile-stage token.

  • Start structured milestone lists with omniverse-usd-performance-tuning as the owning entry skill. Include setup-usd-performance-tuning only as additional Phase 0 context, not as a replacement for the entry skill milestone.

  • For broad optimization requests, preserve the milestone subsequence from Output Format above exactly, with optional extra analysis steps inserted only where they do not reorder it.

  • Do not list so-run-validators or so-interpret-validators before restructure-decision in broad optimization milestone summaries. Phase-aware validator routing still happens through usd-validation-runner; the SO validator executor/interpreter milestones appear after the restructure decision path in the structured plan contract.

Output expectation

End-to-end optimization work should produce both an optimized USD stage, when mutation is executed, and a structured optimization report conforming to the optimization-report reference's scripts/optimization-report.schema.json. The HTML report must be rendered from references/report-templates/optimization-report.html.template via render_preview.py — never hand-write HTML. Diagnosis-only work should still end with a report or summary that states no optimized stage was written.

Purpose

Route digital twin USD performance requests into the right diagnostic and optimization workflow while preserving evidence before mutation.

Prerequisites

  • Stage path or enough context to identify the target asset.

  • User goal: diagnosis only, validation, profiling, or processor execution.

  • Runtime availability status from setup-usd-performance-tuning when not already known.

  • Permission status for in-place mutation vs writing a separate optimized output.

Examples

  • "This USD loads slowly; triage what to check first."

  • "Route a low-FPS CAD scene through the performance workflow."

Triage order

  1. Runtime gate. Follow the mandatory session-start gate above before validation, profiling, or optimization. Do not scan, probe, install, or pick Kit/standalone runtimes directly in this skill; setup-usd-performance-tuning owns probe/chooser/install dispatch and writes the preflight consumed here.

  2. Identify the target problem:

    • Load time.

    • FPS or interactivity.

    • GPU or system memory.

    • Crash or device lost.

    • CAD conversion quality.

    • Validation failure.

  3. Gather minimum context:

    • Stage path and size.

    • Whether the stage is local, mounted, or omniverse:// remote. For remote assets, route through omniverse-authentication before first open.

    • Kit or USD runtime.

    • Whether the workload is CAD, VFI, AIF, Isaac, or generic OpenUSD.

    • Whether in-place mutation is allowed.

    • Whether the user wants diagnosis only or processor execution.

  4. Route:

    • USD composition questions: usd-structure-assessment (composition is now part of the SA umbrella; deeper detail in skills/omniverse-usd-performance-tuning/references/usd-structure-assessment/references/composition-audit.md).

    • Validation and content issues: usd-validation-runner (master router; routes to validate-* family or so-run-validators based on intent).

    • Edit/output decisions: usd-edit-target-planner (also owns variant/payload gates).

    • Repeated copied hierarchy or high mesh count with no instancing: usd-hierarchy-dedupe-candidates.

    • Restructure decision (monolithic stage, asset boundary materialization): restructure-decision.

    • CAD converter settings: read references/cad-conversion/README.md (niche pre-USD concern; see reference for details).

    • Scene Optimizer: so-run-validators, so-interpret-validators, so-run-operations.

Optimization ordering

Follow the canonical ordering in workflow.md § Operation ordering invariants. The high-level rule: prototypes first → per-asset validation → stage-level operations last. The workflow reference owns the full invariant list (meshCleanup before decimateMeshes, deduplication before decimation, never merge if instanced, etc.) and the analysis-only ops catalogue.

Rules

  • Always run composition audit before mutation.

  • Always validate before and after processor execution.

  • Optimize prototypes before per-asset validation.

  • Do not run whole-stage mesh deduplication on very large CAD scenes before checking for hierarchy-level reuse.

  • Do not recommend a fixed optimization stack without bottleneck evidence.

  • Do not invent numeric thresholds or expected percentage wins.

  • Prefer canonical SO ops over specialty / documentary ones. The op curation in references/operations/_curation.json classifies every op as canonical, specialty, analysis, documentary, or deprecated. When more than one op could resolve the same finding, recommend the canonical one first and only reach for a specialty op when the user explicitly asks or the rationale warrants it. Specifically:

    • For vertex welding, prefer canonical meshCleanup with explicit flags over the standalone mergeVertices op. The standalone op is a legacy/specialty surface; use upstream usd-optimize for the operation mechanics and local approval policy before mutating.

    • For hierarchy dedupe, recommend usd-hierarchy-dedupe-candidates + apply-restructure (the USD-authored rewrite path).

    • For per-mesh dedupe, recommend deduplicateGeometry (canonical) over findCoincidingGeometry (analysis — produces a report, not a change).

    • Do not recommend documentary-status ops (e.g., boxClip, deletePrims, removeAttributes, removeUntypedPrims, merge outside its narrow non-instanced case) without an explicit user request. Documentary ops survive in the per-op references/operations/<key>.md routing stubs for completeness but are excluded from agent-initiated recommendations.

    • Specialty ≠ documentary. Ops classified as specialty in _curation.json either (a) have validator-finding evidence that wires them into the so-interpret-validators chain (e.g. sparseMeshes, optimizePrimvars), or (b) are load-bearing escape hatches needed for specific downstream contexts (e.g. primitivesToMeshes when output must be UsdGeomMesh, utilityFunction for instancing toggles and material rebinding, pythonScript for so-create-proxy recipes). Recommend specialty ops when their validator fires OR when their downstream context applies — the suppression above only targets documentary ops.

Limitations

  • Does not replace downstream reference instructions; load each required reference before executing it.

  • Does not install runtimes directly; follow setup or install references when requirements are missing.

  • Does not authorize mutation when the user has not allowed writes.

Troubleshooting

  • If runtime status is unclear, run setup-usd-performance-tuning before profiling or validation.

  • If the reported problem is vague, gather stage path, workload type, and whether diagnosis or execution is requested.

  • If the workflow suggests mutation before evidence, return to baseline profiling and composition audit first.

References

Before routing, read:

  • skills/omniverse-usd-performance-tuning/references/usd-structure-assessment/references/optimization-tradeoffs.md — identify which pipeline phase the scene is in (extraction, structuring, or optimization). The right action depends on the phase.

  • skills/omniverse-usd-performance-tuning/references/usd-structure-assessment/references/factory-level-structuring.md — understand the three pillars (assets, aggregation, animation) and the seven-step structuring pattern.

If you have network access, prefer the live URLs (noted in each reference file) for the most current version.

Required execution flow

Read references/workflow.md for the canonical Phase 0-7 flow, including Kit/standalone branches, validator-stack routing, operation ordering, termination conditions, duration hints, and the optional iteration pattern. The compact root map at references/skill-map.md only routes agents into this workflow.

Do not treat downstream phase names as plain checklist labels. Before executing each step, load that phase's nested README.md reference and follow its instructions. Claude Code only exposes the public catalog skill; it does not recursively inject profile-stage, usd-structure-assessment, or other nested references.

The final deliverable must come from optimization-report: save both the structured JSON report and the generated Markdown summary. Do not substitute an ad hoc SUMMARY.md or chat-only recap for the optimization report.

For deeper subtopic guidance, consult the references:

  • skills/omniverse-usd-performance-tuning/references/usd-structure-assessment/references/composition-audit.md, skills/omniverse-usd-performance-tuning/references/usd-structure-assessment/references/layer-health.md - subtopic detail for SA's Phase 1 checklist.

  • skills/omniverse-usd-performance-tuning/references/usd-structure-assessment/references/instancing-readiness/references/instancing-tradeoffs.md - merge safety, decision tree for instancing choices.

  • skills/omniverse-usd-performance-tuning/references/usd-structure-assessment/references/usd-edit-target-planner/references/variants-payloads.md - deeper variant/payload trade-offs (gates are inline in usd-edit-target-planner).

  • references/cad-conversion/README.md - CAD converter settings.

  • references/upstreams/usd-optimize.md - upstream SO mechanics and prebuilt package resolution.

  • skills/omniverse-usd-performance-tuning/references/usd-validation-runner/references/so-run-validators/references/infrastructure.md - local handoff for SO validator infrastructure.

  • skills/omniverse-usd-performance-tuning/references/usd-validation-runner/references/validation-scoping.md - tier 1/2/3 plan + scene-aware adjustment.

  • skills/omniverse-usd-performance-tuning/references/optimization-report/references/optimization-report-template.md - the data contract every phase populates.

For full Kit runtime profiling (FPS, frame time, Hydra/RTX metrics), refer to the external profiling skills at NVIDIA/omniperf.

Files

references/usd-structure-assessment/references/instancing-readiness/references/instancing-guide.md

<!-- SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -->

<!-- SPDX-License-Identifier: Apache-2.0 -->

Asset Modularity and Instancing

Canonical URLs:

If you have network access, read the live URLs — they may be more current than this local copy.


See also

Learn OpenUSD provides a guided learning experience that covers the topics covered in this guide with a hands-on approach in the Asset Modularity and Instancing module.

Instancing is based on composition

OpenUSD provides instancing as a feature on top of its core composition system.

Instancing is specified by setting the “instanceable” metadata on prims with composition arcs. If “instanceable” resolves to be true, a “prototype” is either retrieved or instantiated. A “prototype” captures the fully composed sub hierarchy at the instanceable prim in a private namespace, invisible to the user. It is identified internally by OpenUSD by hashing the prims’ composition operators as a key.

Note that Prim paths within instances are still addressable via OpenUSD, even though the prototype prims don’t really exist in that location (they exist in the implicitly created prototype, not the instances). OpenUSD will refer to such locations as “instance proxy prims”. This allows clients such as UIs to easily display instance “contents”, without having to perform prototype look ups. OpenUSD also allows “instance proxy” membership in collections.

It is possible to view prototypes in usdview by enabling the “Prototype Prims” option in the “Show” menu on top of the Scene Graph panel.

Opinions directly expressed on descendants of instanceable prims are ignored to preserve the shareability of the prototypes across instances. In other words, the instance proxy prims are read-only or “immutable”.

Only fields of the “instanceable root” prim, such as composition arcs, transforms, primvars, etc. may vary from its underlying “prototype”. See “parameterization” in the “refinement” section below for details.

If no composition arcs are directly authored on an instanceable prim, the prim behaves as if “instanceable” was set to false. A composed prim requires both “instanceable” set to true and direct composition arcs to be authored for a prototype to be generated by composition.

If the instanced prim has variant sets, only instances with the same variant selections will share a prototype. If animation is scattered via referencing on instanced assets, only instances with animation layers and offsets will share a prototype.

Instanceable prim hierarchies can be deinstanced by setting instanceable=False if sparse overrides are needed downstream.

Because the creation of protoypes is performed automatically by OpenUSD, but the choice to do this lies with the user (by authoring the “instanceable” metadata), this style of instancing is referred to as “implicit prototypes” with “explicit instances”.

Assembly of referenced assets

Visualization of implicit prototypes

Instanceable Internal Arcs

Setting the instanceable metadata on prims which hold internal composition arcs, will trigger the creation of implicit prototypes as discussed. For mechanisms to edit or refine instances of the instance, see the “Editing” and “Refining” chapters below.

This style of instancing can be used to model similar approaches in many CAD and DCC applications. A (non-instanceable) prim hierarchy is “internally composed” multiple times onto instanceable prims. In contrast to composing external layers, an internal arc only specifies the target prim path of the reference, omitting the layer.

This approach might be a valuable choice when the goal is “true to source” scene description. It might also be chosen when the referenced data needs to be embedded into the stage.

There are a number of trade-offs to consider with this approach:

  • If the same instanceable subhierarchy (asset) is re-defined in multiple layers, OpenUSD will not be able to identify as being identical and create duplicate prototypes. Examples may be assets such as robots in individually generated “assembly cell” USD layers, car parts which should be reused across multiple “car_trim” USD layers or furniture which is reused across multiple “level” USD layers in a BIM model. To the user, this issue can be unexpected, especially if the process that generated the internal composition arcs offered the creation of “instances”.

To avoid this problem, consider approaches such as Instanceable External Arcs, Globally Refinable Instancing for Internal Arcs or Globally Refinable Instancing for External Arcs.

The example below illustrates the issue, showing the “barrel” asset being defined twice, once in the factory and again, in the loading dock.

  • Because the target hierarchy is not explicitly namespaced, it can be difficult to understand for consumers which parts of the scene graph are composition sources and which are targets. For example, a user may disable “Barrel_0” in the example below which unexpectedly would also prune the hierarchy under “Barrel_1”.

  • Especially for small amounts of data, the associated performance improvements may not be worth the increase of the stages’ structural complexity, especially when principles such as encapsulation are taken into account. Also remember that an instanced hierarchy consists of a root prim which is editable and the internal hierarchy of the instance, which is immutable. This means that an instance has to consist of at least two prims - single prim instancing is not possible.

Instanceable External Arcs

Instancing external arcs works similarly. Setting instanceable to “true” on the source prims will trigger the creation of “Prototypes” - implicitly derived from the composition arcs specified by the “instanceable root”.

All prims which compose the same layer / prims will now share the same underlying composed “prototype” and the composed asset will become immutable - for mechanisms to edit or refine instances of the asset, see the “Editing” and “Refining” chapters below. For mechanisms to edit or refine instances of the asset, see the “Editing References” chapter below.

The “Asset Interface” concept that is outlined in “Principles of scaleable Asset Structures” describes an asset which is well suited for instancing workflows and provisions an explicit editing namespace to provide a target for downstream edits. Also see the External Asset Libraries for a more comprehensive structure.

Reasons to use Instancing

Performance

As instancing generally enables scalability in renderers through shared geometric representations, it commonly is described as a memory optimization. However, the composed OpenUSD stage is only responsible for resolving the location of values and never has to read the entire geometric representation of the scene into memory.

While scene graph instancing generally improves the time and memory required to compose a stage, it primarily does so via optimization of stage traversal.

Consider a script counting the screws in a warehouse with instanced shelves. The naive solution would traverse the entire composed scene, counting each screw. The instancing-aware solution would instead count the screws in each shelf prototype and reuse that count when encountering an instance of the shelf on the stage. A script operating on a warehouse with hundreds of shelves could replace the traversal of hundreds of subgraphs with a simple cache lookup. This effect can be compounded by nested scene graph instancing which is they key to achieving scene scales such as large factories or cities.

As a consequence, it is recommended to orient scene graph instance structures around traversal cost. Attempting to instance too granular subgraphs may result in more prims and complicate traversal without reaping the performance benefits.

Hierarchical Encapsulation

A prototype is an encapsulated subgraph. Relationships (like material bindings) on geometry cannot refer to prims that exist outside the prototype. Component models often are a good granularity for instancing as they encapsulate their materials and geometry.

Consider that materials also constitute “encapsulated subgraphs” - ie, they are represented by hierarchies of nodegraphs and nodes in the materials namespace. Performance benefits from designing instanceable material networks might be substantial and may even outweigh geometry instancing, which is already optimized by file format level deduplication and renderer level mesh deduplication.

Material Instances

In OpenUSD, Materials are fully encapsulated shader nodegraphs. In production environments, materials graphs may often include a large number of shader nodes which may contribute significantly to the total prim count of a composed stage. Additionally, materials are often referenced from a centralized material library and may be specialized further in the context of the asset.

Shader parameters that are intended to be controlled by downstream consumers of the materials (for example, asset paths for textures) should be “promoted” or “exposed” on the material root prim. This provides a convenient interface to users and ensures that parameterization of the material is consolidated in a single location in the scene graph.

These factors make materials a good use case for scene graph instancing with the potential to reduce overal prim count and speeding up render translation (the renderer already “knows” which materials are duplicates, it doesn’t need to de-duplicate transpiled or compiled shader code to detect them).

Editing Instances

Edit Targets

Because instance prototypes are created by OpenUSD implicitly, they can not be edited directly. They are not shown to the user and their naming is not persistent.

However, as prototypes represent the results of fully resolved composition arcs, it is possible to “edit” prototypes by modifying the instances’ arc targets. In other words, if an instanceable prim composes another prim, any change to that prim will be propagated to all instances (either “live” or upon recomposition, depending on the chosen composition arc, see: Internal composition arcs documentation ).

In some cases, finding and editing the target might be fairly simple. For example, if an instance only holds a single internal reference arc. In other cases, a prims composition might be very complex or the composed source data may be read only.

For this reason, assets might be authored upstream with “speculative” composition arcs which are intended to serve as edit targets for “instance refinements”. This is described in the “Refining Instances by composition” sections below.

It is also possible to add internal composition arcs later to individual instances to facilitate refinement. This is referred to as refinement “at the point of assembly”.

Creating new prototypes

If prims need to be deleted or re-parented for individual instances, there is (currently) no way to do this non-destructively in OpenUSD. In orther words, it is necessary to edit (rather than refine) the composed source data..

This can be done by copying the original composition target (however simple or complex that may be) and re-compose it onto new instances as needed. This might also present an opportunity to introduce a variant arc to the asset, so that the new variation can be chosen easily for each instance (see “parameterization” below).

Refining Instances

The term “Refining” is chosen here to denote that the following techniques do not destructively modify instances (ie, it is not possible to perform namespace editing such as re-parenting or deleting). Instead, they provide a mechanism for layered refinements such as attribute value changes, material bindings, creation of additional prims or changes in metadata.

Various techniques exist to refine instances. Some of these can be described as intuitive, but others require a deep understanding of OpenUSDs composition mechanism and will benefit from dedicated tooling to improve the user experience.

De-instancing

The simplest approach to instance editing is to set instanceable on specific instances to “False”. If applied in moderation, this might be a perfectly acceptable approach in many situations. Remember that various de-duplication systems are still operating “behind the scenes” to avoid data duplication.

scenario.usda 1#usda 1.0 2 3def Scope "Factory" 4 ( 5 references = @./factory.usda@ 6 ) 7{ 8 over "AssembledBarrels" () { 9 # Visibility is inherited from the ancestor prim into the instances 10 token visibility = "invisible" 11 } 12}

By hierarchical inheritance

Instances can be spatially varied because transformation operations in OpenUSD are hierarchical. Properties that have computed hierarchical inheritance are expected to work with instancing. For example, an instance with an “invisible” ancestor should never be imaged, regardless of the visibility state of the “prototype”.

scenario.usda 1#usda 1.0 2 3def Scope "Factory" 4 ( 5 references = @./factory.usda@ 6 ) 7{ 8 over "AssembledBarrels" () { 9 # Visibility is inherited from the ancestor prim into the instances 10 token visibility = "invisible" 11 } 12}

Properties that don’t have inheritance semantics must be varied through composition arcs to preserve instancing (see “refining instances” below).

By parameterization

There are two ways instance root prims can be parameterized: primvars and variants.

The example below applies parameterization to an instanced asset.

The root prim of an asset will be the first place where a user goes to figure out if prims have discrete variants. Asset structures may enforce naming conventions and the presence of specific variants. For example, it may be expected that assets provide color_variant to describe supported albedo variations.

def Xform "RaceCar" ( variantSets = ["color_variant"] ) { variantSet "colorVariant" = {

        &quot;red&quot; { ... }
        &quot;blue&quot; { ... }
        &quot;green&quot; { ... }

    }
}

Some variation cannot be effectively or efficiently discretized into variants. For these cases, primvars can be used as another form of asset parameterization. Primvars are extra interpolatable parameters primarily for Gprim prims to provide additional data to shading contexts. In OpenUSD, primvars have inheritance semantics and can be authored on parent scopes, including the entrypoint of an instance. Materials can be constructed to read primvars:asset_base_color or other entrypoint primvars. In the event that multiple prims in a hierarchy author the same primvar, keep in mind that child opinions are stronger than parents. Below, we use asset_ as a prefix to avoid namespace collisions.

def Xform "RaceCar" {

color3f primvars:asset_base_color (
    doc = &quot;primary paint color&quot;
)

color3f primvars:asset_accent_color (
    doc = &quot;color of accent stripe&quot;
)

}

Unless otherwise documented or annotated as internal, variants and primvars authored on an asset entrypoint should be generally considered “public” and safe for downstream contexts to edit and set with an expectation of stability.

Both variant selection and primvars on the asset entrypoint are compatible with scene graph instancing. Variations of variant selections will generate new prototypes for downstream contexts while primvars will not. This generally makes parameterization through primvars the lighter choice for single property parameters, providing upfront memory savings at the cost of additional lookups in materials.

Explicit “Refinement Namespaces”

OpenUSD’s prototypes are implicit and read only. However, because they are keyed off of composition, it is possible to construct arcs in a way that provide a namespace (prim) where explicit prototype edits can be placed. Depending on the use case, the specific placement and contents of the namespace might be different. For example, it may contain the entire definition of the asset or simply provide an opportunity for downstream consumers to add refining edits.

In all cases, it is recommended to utilize abstract prims to provide these explicit “editing namespaces”. They are not part of the default traversal and can be easily identified and filtered through OpenUSD’s traversal predicates. Conventionally, these prims are named “prototypes” and they are of type “scope”.

“Edit Namespaces” can be applied to external and internal referencing scenarios.

Internally Refinable Instancing

This approach extends “Instanceable Internal Arcs” described above and addresses the issue of being non-explicit in declaring the location where reference targets are found.

Internally refineable instancing is desirable when a subgraph is repeatedly used within a layer (or asset) but there’s no expectation that downstream consumers will want to make any edits to the prototype without deinstancing.

Consider some barrel geometry internally referenced into a factory.

factory.usda 1#usda 1.0 2( 3 defaultPrim = "Factory" 4) 5 6class Scope "prototypes" () { 7 def Xform "Barrel" ( 8 kind = "component" 9 ) { 10 def Xform "Geometry" { 11 def Cylinder "barrel" {} 12 } 13 } 14} 15 16def Scope "Factory" ( 17 kind = "assembly" 18) { 19 def Scope "BarrelBundle" ( 20 kind = "group" 21 ) { 22 def "Barrel_0" ( 23 instanceable = True 24 references = </prototypes/Barrel> 25 ) { 26 token[] xformOpOrder = ["xformOp:translate"] 27 double3 xformOp:translate = (100, 0, 0) 28 } 29 def "Barrel_1" ( 30 instanceable = True 31 references = </prototypes/Barrel> 32 ) { 33 token[] xformOpOrder = ["xformOp:translate"] 34 double3 xformOp:translate = (110, 0, 0) 35 } 36 } 37}

Changes to /prototypes/Barrel/Geometry will be reflected in the implicitly generated shared prototype for Barrel_0 and Barrel_1. We describe this pattern as being “internally refinable” because the prototypes can only be refined in the immediate layer stack. If /Factory were to be referenced into another layer stack, /prototypes/Barrel will no longer be available to place edits. Barrel_0 and Barrel_1 can only be edited through deinstancing or adding additional composition arcs. Its construction around the “references” composition arc makes it one of the cheaper patterns of scene graph instancing.

Warning: Some of the trade-offs discussed in Instanceable Internal Arcs still apply, in particular the risk of multiple re-definitions of identical hierarchies.

Locally Refinable Instancing for Internal Arcs

Abstract prims can be nestable underneath an asset’s root prim to bring prototype edit targets along into downstream contexts. However, to remain a live connection, even when referenced in downstream layerstacks, the composition arc needs to be changed from a reference to a “specialize” arc. Specialize arcs remain “live” in any referencing context so any edits that are applied to the prototypes after the asset has been referenced still propagate.

factory.usda 1#usda 1.0 2 3def "Factory_0" (references = @./factory.usda@) { 4 over "prototypes" () { 5 over "Barrel" { 6 over "Geometry" { 7 over "barrel" { 8 color3f[] primvars:displayColor = [(.6, .2, .2)] 9 } 10 } 11 } 12 } 13} 14 15def Xform "Factory_1" (references = @./factory.usda@) { 16 token[] xformOpOrder = ["xformOp:translate"] 17 double3 xformOp:translate = (20, 0, 0) 18}

/Factory/prototypes/Barrel will be available in downstream contexts and can propagate edits to Barrel_0 and Barrel_1 through the specializes arc.

Note that this approach creates the potential for a prototype explosion. Consider a factory where Barrels are aggregated into multiple bundles and locally refinable instancing is used at the bundle level. Prototypes will be shared between barrels if there are no refinements, but as bundles add refinements, new prototypes will proliferate.

Locally Refinable Instancing for External Arcs

Locally refinable instancing can also be combined with externally referenced assets at the point of assembly. This allows for refinements in the context of the assembly, for example to refine all instances of an asset within a particular assembly, but not in others.

loading_dock.usda 1#usda 1.0 2( 3 defaultPrim = "LoadingDock" 4) 5 6def Scope "LoadingDock" { 7 class Scope "prototypes" { 8 def Xform "Barrel" {} # Leave the Barrel asset unchanges 9 } 10 11 def "Barrel_0" ( 12 instanceable = True 13 references = @./barrel.usda@ 14 specializes = </LoadingDock/prototypes/Barrel> 15 ) { 16 token[] xformOpOrder = ["xformOp:translate"] 17 double3 xformOp:translate = (100, 0, 0) 18 } 19 def "Barrel_1" ( 20 instanceable = True 21 references = @./barrel.usda@ 22 specializes = </LoadingDock/prototypes/Barrel> 23 ) { 24 token[] xformOpOrder = ["xformOp:translate"] 25 double3 xformOp:translate = (110, 0, 0) 26 } 27}

factory.usda 1#usda 1.0 2( 3 defaultPrim = "Factory" 4) 5 6def Scope "Factory" ( 7 kind = "assembly" 8) { 9 class Scope "prototypes" { 10 def Xform "Barrel" { 11 color3f[] primvars:displayColor = [(0, 1, 0)] # Color all Barrels in Factories Green. 12 } 13 } 14 15 def Scope "BarrelBundle" ( 16 kind = "group" 17 ) { 18 def "Barrel_0" ( 19 instanceable = True 20 references = @./barrel.usda@ 21 specializes = </Factory/prototypes/Barrel> 22 ) { 23 token[] xformOpOrder = ["xformOp:translate"] 24 double3 xformOp:translate = (100, 0, 0) 25 } 26 def "Barrel_1" ( 27 instanceable = True 28 references = @./barrel.usda@ 29 specializes = </Factory/prototypes/Barrel> 30 ) { 31 token[] xformOpOrder = ["xformOp:translate"] 32 double3 xformOp:translate = (110, 0, 0) 33 } 34 } 35}

scenario.usda 1#usda 1.0 2 3def "Factory_0" (references = @./factory.usda@) { 4 over "prototypes" () { 5 over "Barrel" { 6 over "Geometry" { 7 over "barrel" { 8 # Override the Barrel prototype in this factory to be red 9 color3f[] primvars:displayColor = [(.6, .0, .0)] 10 } 11 } 12 } 13 } 14} 15 16def Xform "LoadingDock_1" (references = @./loading_dock.usda@) { 17 token[] xformOpOrder = ["xformOp:translate"] 18 double3 xformOp:translate = (40, 0, 0) 19} 20 21def Xform "Factory_1" (references = @./factory.usda@) { 22 token[] xformOpOrder = ["xformOp:translate"] 23 double3 xformOp:translate = (20, 0, 0) 24}

Globally Refinable Instancing for Internal arcs

Are there ways that we can guarantee that all barrels share the same prototype? We can specialize our scene with global prototypes.

factory.usda 1#usda 1.0 2( 3 defaultPrim = "Factory" 4) 5 6class Scope "prototypes" () { 7 def Xform "Barrel" ( 8 kind = "component" 9 ) { 10 def Xform "Geometry" { 11 def Cylinder "barrel" {} 12 } 13 } 14} 15 16def Scope "Factory" ( 17 kind = "assembly" 18) { 19 def Scope "BarrelBundle" ( 20 kind = "group" 21 ) { 22 def "Barrel_0" ( 23 instanceable = True 24 specializes = </prototypes/Barrel> 25 ) { 26 token[] xformOpOrder = ["xformOp:translate"] 27 double3 xformOp:translate = (100, 0, 0) 28 } 29 def "Barrel_1" ( 30 instanceable = True 31 specializes = </prototypes/Barrel> 32 ) { 33 token[] xformOpOrder = ["xformOp:translate"] 34 double3 xformOp:translate = (110, 0, 0) 35 } 36 } 37}

This structure is very similar to internally refinable instances, but because the instances are specializing paths outside the model context, Barrel_0 and Barrel_1 can get refinements from /prototypes/Barrel at multiple levels of referencing.

scenario.usda 1#usda 1.0 2 3class Scope "prototypes" { 4 over "Barrel" { 5 over "Geometry" { 6 over "barrel" { 7 color3f[] primvars:displayColor = [(.6, .2, .2)] 8 } 9 } 10 } 11} 12 13def "Factory" (references = @./factory.usda@) {}

Globally refinable instances avoid the issue of locally refinable instances potentially generating multiple prototypes. However, without well defined naming conventions, globally refinable instances can result in unexpected namespace collisions. When pulling data from multiple asset libraries or sources, one should consider additional namespacing to avoid collisions between two similarly named prototypes.

factory.usda class Scope "prototypes" { class Scope "AssetLibrary_v1" { class Xform "Barrel" { def Xform "Geometry" { def Cylinder "barrel" {}

        }
    }
}

}

Abstract prims as “namespace containers” for edit namespaces

Globally Refinable Instancing for External Arcs

In the asset interface When it is anticipated that Assets will be globally refined downstream, it might be advantageous to author the assets’ interface with an empty, “speculative” global refinement namespace.

barrel.usda 1#usda 1.0 2( 3 defaultPrim = "Barrel" 4) 5 6class Scope "prototypes" { 7 over "Barrel" () {} 8} 9 10def Xform "Barrel" ( 11 specializes = </prototypes/Barrel> 12 kind = "component" 13 ) { 14 def Xform "Geometry" { 15 def Cylinder "barrel" {} 16 } 17}

This allows downstream consumers to add edits into all Barrel instances in the stage, regardless of their depth of instancing.

scenario.usda 1#usda 1.0 2 3class Scope "prototypes" { 4 over "Barrel" { 5 over "Geometry" { 6 over "barrel" { 7 color3f[] primvars:displayColor = [(.6, .2, .2)] 8 } 9 } 10 } 11} 12 13def "Factory" (references = @./factory.usda@) {}

At the point of assembly Specialize and inherit arcs are computationally more expensive than references and payloads (because they are evaluated “live”). Projects may also consume assets from external libraries, so it’s not always possible to add the arcs into the assets.

Rather than adding the arcs into each asset, it is also possible to add the arcs to each instance at the point of assembly, similar to the approach shown in “Globally Refinable Instancing for Internal arcs”.

factory.usda 1#usda 1.0 2( 3 defaultPrim = "Factory" 4) 5 6class Scope "prototypes" () { 7 over "Barrel" () {} 8} 9 10 11def Scope "Factory" ( 12 kind = "assembly" 13) { 14 def Scope "BarrelBundle" ( 15 kind = "group" 16 ) { 17 def "Barrel_0" ( 18 instanceable = True 19 references = @./barrel.usda@ 20 specializes = </prototypes/Barrel> 21 ) { 22 token[] xformOpOrder = ["xformOp:translate"] 23 double3 xformOp:translate = (100, 0, 0) 24 } 25 def "Barrel_1" ( 26 instanceable = True 27 references = @./barrel.usda@ 28 specializes = </prototypes/Barrel> 29 ) { 30 token[] xformOpOrder = ["xformOp:translate"] 31 double3 xformOp:translate = (110, 0, 0) 32 } 33 } 34}

scenario.usda 1#usda 1.0 2 3class Scope "prototypes" { 4 over "Barrel" { 5 over "Geometry" { 6 over "barrel" { 7 color3f[] primvars:displayColor = [(.6, .2, .2)] 8 } 9 } 10 } 11} 12 13def "Factory" (references = @./factory.usda@) {}

This makes it possible to “inject” opinions into instanceable, externally referenced assets.

The trade off with this approach is that, in mutli level instancing scenarios, it will be necessary to add the arcs at each level of instancing.

For example, if instanceable barrel assets are referenced into instanceable shelf assets which are referenced into a factory, a new inherit arc will need to be added on the shelfs, which in turn adds the arcs to the to the barrels.

At the point of assembly, asset reference in explicit prototype In this approach, the external reference is placed into the explicit edit context. This approach avoids the multi level instancing issues described with the previous approach.

The downsides are that each prototype creates a duplicate of the asset structure, although the cost for this is likely to be very low as the asset needs to be loaded eventually and the prototypes hierarchy is not traversed for rendering.

A potentially bigger issue might be that instance root prims will also not be “loadable” if the assets have a payload arc in their interface. Instead, users will have to manage load state on the prototypes. One possible work around might be to place the payload arcs on a child prim of the asset interface, for example on the /materials and /geometry scopes.

factory.usda 1#usda 1.0 2( 3 defaultPrim = "Factory" 4) 5 6class Scope "prototypes" { 7 def "Barrel" ( 8 references = @./barrel.usda@ 9 ) { 10 over "Geometry" { 11 over "barrel" { 12 color3f[] primvars:displayColor = [(.2, .2, .6)] 13 } 14 } 15 } 16} 17 18def Scope "Factory" ( 19 kind = "assembly" 20) { 21 def Scope "BarrelBundle" ( 22 kind = "group" 23 ) { 24 def Xform "Barrel_0" ( 25 instanceable = True 26 specializes = </prototypes/Barrel> 27 ) { 28 token[] xformOpOrder = ["xformOp:translate"] 29 double3 xformOp:translate = (100, 0, 0) 30 } 31 def Xform "Barrel_1" ( 32 instanceable = True 33 specializes = </prototypes/Barrel> 34 ) { 35 token[] xformOpOrder = ["xformOp:translate"] 36 double3 xformOp:translate = (110, 0, 0) 37 } 38 } 39}

scenario.usda 1#usda 1.0 2 3class Scope "prototypes" { 4 over "Barrel" { 5 over "Geometry" { 6 over "barrel" { 7 color3f[] primvars:displayColor = [(.6, .2, .2)] 8 } 9 } 10 } 11} 12 13def "Factory" (references = @./factory.usda@) {}

Point Instancing

Point instancing provides a vectorized representation of instances that share the same scene description but may differ in (potentially animated) attributes like position, orientation, or scale. Point Instancing is more efficient than scene graph instancing, as it does not require a prim for each instance and implicit prototypes do not need to be computed. This comes at the expense of decreased flexibility and addressability - the lack of a unique instance namespace does introduce limitations and requires a specialized toolset. For example, it is generally not possible to simply transform an instance in a point instancer with common translate/rotate/scale tools that are intended to modify xform ops. Instead, “instance painting” or particle system tools might need to be used.

Prototypes are explicit and are specified via an array of relationships. They can be of arbitrary complexity, but are oftentimes used for much smaller instances than Scene Graph Instances. For example, leaves on trees or pebbles on a beach.

Prototypes are organized as children of the PointInstancer to uphold the principle of hierarchical encapsulation (if a point instancer is de-activated, all of its children are de-activated as well).

factory.usda 1#usda 1.0 2( 3 defaultPrim = "Factory" 4) 5 6def Scope "Factory" ( 7 kind = "assembly" 8) { 9 def PointInstancer "BarrelBundle" ( 10 kind = "group" 11 ) 12 { 13 quath[] orientations = [(1, 0, 0, 0), (1, 0, 0, 0), (1, 0, 0, 0), (1, 0, 0, 0)] 14 point3f[] positions = [(100, 0, 0), (110, 0, 0), (100, 10, 0), (110, 10, 0)] 15 16 int[] protoIndices = [0, 0, 0, 0] 17 rel prototypes = </Factory/BarrelBundle/Prototypes/Barrel> 18 19 def "Prototypes" ( 20 kind = "group" 21 ) 22 { 23 def "Barrel" ( 24 prepend references = @./barrel.usda@ 25 ) {} 26 } 27 } 28}

scenario.usda 1#usda 1.0 2 3def Scope "Factory" 4 ( 5 references = @./factory.usda@ 6 ) 7{ 8 over "BarrelBundle" () { 9 int64[] invisibleIds = [2] 10 11 color3f[] primvars:displayColor = [(1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0)] ( 12 interpolation = "vertex" 13 ) 14 } 15}

Animation

Because point instancers are based on array attributes, it is quite simple to animate large numbers of instances by setting time samples on the arrays. Note that the “InactiveIds” array can not be animated, so “invisibleIds” needs to be used instead to specify which instances are visible.

Note that the animation can also be set by using value clips, which allow for time scaling, repetition, stitching etc. Use cases include vegetation animation (“keep alive”) or recorded process simulations.

Refinement

Refinement opportunities for individual instances in point instancers are fairly limited. However, the prototypes used by point instancers are regular prim hierarchies and can therefore be modelled with scene graph instances. Consequently, the techniques discussed above for scene graph instancing refinement can still be applied to the prototypes used

By Primvar propagation

Primvars (such as DisplayColor) on point instancers are interpolated across all instances and propagated to each instance as constant values. The primary use case for this is to manipulate shading for each instance vis primvar readers in materials.

By Promotion

Individual Instances can also be de-activated or made invisible, which allows for “promotion” workflows. In this approach, individual instances are de-activated and a new Xform is created at their location. The corresponding prototype is then internally referenced onto the Xform. This “promoted” reference can then be instanced and refined as needed.

Nested Instancing

Nested instancing is the key to achieving massive scene scale. A well organized asset hierarchy with large, instanced assets made of smaller assets that are also instanced keeps the total prim count to a minimum whilst providing a lot of minute detail.

Nested point instancing is also compatible with this method, further reducing the prim count for objects with many instances which may not need to be editable / refinable directly.

factory.usda 1#usda 1.0 2( 3 defaultPrim = "Factory" 4) 5 6def Scope "Factory" ( 7 kind = "assembly" 8 ) 9 { 10 def Scope "BarrelsFront" ( 11 kind = "group" 12 ) { 13 def "BarrelBundle_0" ( 14 instanceable = True 15 references = @./barrel_bundle.usda@ 16 ) { 17 token[] xformOpOrder = ["xformOp:translate"] 18 double3 xformOp:translate = (100, 0, 0) 19 } 20 def "BarrelBundle_1" ( 21 instanceable = True 22 references = @./barrel_bundle.usda@ 23 ) { 24 token[] xformOpOrder = ["xformOp:translate"] 25 double3 xformOp:translate = (110, 0, 0) 26 } 27 } 28 def Scope "BarrelsBack" ( 29 kind = "group" 30 ) { 31 def "BarrelBundle_0" ( 32 instanceable = True 33 references = @./barrel_bundle.usda@ 34 ) { 35 token[] xformOpOrder = ["xformOp:translate"] 36 double3 xformOp:translate = (130, 0, 0) 37 } 38 def "BarrelBundle_1" ( 39 instanceable = True 40 references = @./barrel_bundle.usda@ 41 ) { 42 token[] xformOpOrder = ["xformOp:translate"] 43 double3 xformOp:translate = (140, 0, 0) 44 } 45 } 46}

Statistics

OpenUSD provides “Stat” utilities that can be used to analyze the effectiveness of instancing.

The python API call is:

from pxr import UsdUtils print(UsdUtils.ComputeUsdStageStats(stage))

{'assetCount': 0, 'instancedModelCount': 0, 'modelCount': 0, 'primary': {'primCounts': {'activePrimCount': 11, 'inactivePrimCount': 0, 'instanceCount': 10, 'pureOverCount': 0, 'totalPrimCount': 11}, 'primCountsByType': {'Xform': 11}}, 'prototypeCount': 2, 'prototypes': {'primCounts': {'activePrimCount': 20, 'inactivePrimCount': 0, 'instanceCount': 10, 'pureOverCount': 0, 'totalPrimCount': 20}, 'primCountsByType': {'Cube': 10, 'Xform': 10}}, 'totalInstanceCount': 20, 'totalPrimCount': 31, 'usedLayerCount': 12}

Two sets of relevant prim counts are provided:

  • “Prototypes Prim Counts”: These are primitives that are encapsulated in prototypes and are therefore potentially shared multiple times.

  • “Primary Prim Counts” prims: These are primitives that are not encapsulated in prototypes.

So an external asset with 1000k prims, that has been referenced on instanceable prims under /World three times should result in four “Primary” prims and 1000k prims in Prototypes (1004 total). If instancing was not used, the prim count would be much higher at 3001 prims.

Another example, an asset with 10 mesh prims, instanced 10 times in a larger asset, that is also instanced 10 times results in a stage which only contains 31 prims, but 1,111 instance proxy prims. This stage would load/get translated to the renderer at nearly the same speed that a stage with only 30 prims would.

➤ Next: Practical Examples

Content Reuse

The concepts of reuse and instancing are very closely related. Understanding reuse and modularity is a important before attempting to implement successful instancing strategies.

Composition Arcs

OpenUSD’s composition functionality incorporates a variety of composition arcs to support content reuse. These include reference, payload, inherit, and specialize arcs. These arcs enable the composition of prims and their descendants onto other prims, either from separate external layers/files or internally from prims located elsewhere within the same stage.

In both scenarios, prims can be composed multiple times, thereby facilitating content reuse.

It’s worth noting that while composition through sublayering is also a method for reuse, it doesn’t align as closely with the concept as the aforementioned arcs. This is primarily because sublayers are typically used to amalgamate contributions and overrides from different workstreams, departments, or processes through layerstacks. This differs from the composition of modular and composable content.

Internal Arcs

The following arcs are used to compose prims that exist within the same stage onto other prims that also exist in the same stage.

  • References

  • Specialize

  • Inherit

The difference between these arcs lies in their strength (see LIVRPS) and their “composition encapsulation” – reference arcs only evaluate in the local layer stack of the prim which introduces them. In other words, they do not remain “live” within the composed stage and do not update when their target is modified.

Specialize and Inherit arcs on the other hand do remain “live”. This makes them more costly (in terms of performance) but also opens up additional use cases: Just like reference arcs, they facilitate reuse via composition of one prim onto another. But because they remain live, they are also useful in “refinement” workflows. Ie, an application can refine data at runtime by authoring opinions onto the target of a specialize or inherit arc.

External Arcs

Composing prims from external layers is implemented in these arcs:

  • References

  • Payload

They form the primary building blocks for composition of external layers in OpenUSD (besides sublayers).

Reference arcs are the only arcs which can compose internally and externally. Neither of these arcs remain live like Specialize or Inherit arcs, but they can exist on the same prims as specialize or inherit arcs.

Reuse with point instancers

OpenUSD provides an additional content reuse mechanism via point instancers

Point instancers are somewhat similar to internal references, without requiring separate “anchor” prims for each reuse. Instead, array attributes on point instancer prims hold the paths to the prims which are to be reused, as well as their positions and other attributes. The instances, their properties and their placement is compressed into array attributes.

Point instancers are a lot more compact than internal referencing and may scale to higher instance counts, but come at the cost of flexibility, addressability and legibility.

Just In Time (JIT) De-duplication

At a lower level, there are multiple systems in the OpenUSD data pipeline which facilitate de-duplication of data, without the users needing to take action. Whilst they are not the focus of this document, their existence might steer the decision making process when choosing the best reuse style for a given situation.

  • Deduplication of Array data in binary (crate) OpenUSD files: OpenUSD will automatically detect duplicate arrays, for example for point positions on mesh prims, and de-duplicate them. So a OpenUSD file with 1000 identical polygon meshes might only be marginally larger in size than a OpenUSD file with a single copy of the same mesh.

  • Deduplication in render delegates: strictly speaking, this is not a feature of OpenUSD itself but needs to be implemented in the render delegate for a given renderer. The Storm render delegate for example de-duplicates primvar data by default. This means that, similarly to the deduplication in OpenUSD, 1000s copies of a mesh may not be significantly more costly (in terms of memory).

  • Deduplication by the renderer: a renderer might deduplicate compiled materials for example, after they have been translated and compiled from their OpenUSD description.

Whilst this kind of low level data de-duplication has significant impacts and benefits, it also costs time to compute. This may surface when writing a usdc file with a lot of duplicated data, as OpenUSD needs to hash the data in order to detect duplicates. Similar time costs might occur during scene translation for rendering.

Requirements and compatibility

Written for: OpenAI Codex

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs Python

The author says: Orchestrator skill. Downstream phases may require Kit, Scene Optimizer, Asset Validator, USD Python, writable output paths, and omniverse:// authentication selected by setup-usd-performance-tuning.

Security

What our scanner noticed· Medium risk

  • Large base64-encoded blobs
  • Instructions that use the network
  • Scripts that your agent may run

This skill includes scripts that your agent may run. Read them before you use it.

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
NVIDIA Omniverse
Publisher
OpenAI (Official)
Distributed by
OpenAI
Source
openai/plugins · plugins/nvidia/skills/omniverse-usd-performance-tuning · commit d420d13
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (written by AutoGineer)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by NVIDIA Omniverse or OpenAI.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download omniverse-usd-performance-tuning.zip