Writing Attributes
When to Use
Use this skill when the user asks to write an attribute, set a property, change a material, set a color, or modify mesh data.
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.
- Prim paths, attribute name, USD value type, scalar versus array shape, and desired values.
- Data source location, dtype, semantic conversion, and sync/async behavior when those details are part of the task.
- Whether the write is one-shot, repeated with a stable target, or needs direct mapped-buffer access.
- 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. - Use
attribute-bindingsfor repeated writes to the same prims/attribute, andmapping-attributesfor zero-copy direct writes. - Use
binding-materialswhen the request is specifically to setmaterial:binding.
Instructions
- Identify the target language, prim paths, attribute name, value kind, data shape, memory target, and sync/async requirement.
- Read the matching source snippet and copy its lifecycle pattern rather than inventing equivalent calls.
- Validate dtype, shape, semantic, and ownership rules before proposing or editing code.
- Keep bindings, mapped buffers, operation handles, and C strings alive only for the lifetimes documented by the referenced examples.
- When changing code, run the narrow 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
- Runtime string arrays, asset arrays, and timecode attributes are not supported.
- Use
token[]for string-like arrays. - The referenced snippets remain the source of truth; update or add tested snippets before documenting new API usage.
Overview
Beyond transforms, you can write arbitrary attributes to prims: colors, visibility, mesh geometry, string tokens, and more. ovrtx uses DLTensor as the data format, and the dtype must exactly match the USD attribute schema.
There are two categories:
- Scalar attributes -- one value per prim (e.g., a color, a transform)
- Array attributes -- variable-length per prim (e.g., mesh points, face vertex counts)
Tensor layout
Python and C expose different DLTensor layouts for multi-component attributes:
Python — NumPy-style shapes
Python accepts and returns NumPy-style shapes with dtype.lanes=1. Multi-component values live in trailing shape dimensions:
| USD type | Python shape | dtype |
|---|---|---|
int / float scalar for N prims |
(N,) |
int32 / float32 |
float3 / point3f scalar for N prims |
(N, 3) |
float32 |
float4 / color4f scalar for N prims |
(N, 4) |
float32 |
generic matrix4d attribute for N prims |
(N, 16) |
float64 |
| 4x4 transform semantic for N prims | (N, 4, 4) |
float64 |
int[] array with M elements on one prim |
(M,) |
int32 |
float3[] / point3f[] with M elements on one prim |
(M, 3) |
float32 |
Source:
tests/docs/python/test_attribute_shapes.pysnippetsdoc-shape-scalar-int32,doc-shape-float3-array,doc-shape-mat4-array.
C — lane-based attributes
The C API uses DLDataType::lanes for multi-component attribute reads and writes. The shape counts logical attribute elements; the lane count holds the vector or matrix component count:
| USD type | C DLTensor shape | C DLDataType |
|---|---|---|
int / float scalar for N prims |
[N] |
{kDLInt/kDLFloat, bits, 1} |
float3 / point3f scalar for N prims |
[N] |
{kDLFloat, 32, 3} |
| 4x4 double matrix for N prims | [N] |
{kDLFloat, 64, 16} |
int[] array with M elements on one prim |
[M] |
{kDLInt, 32, 1} |
float3[] / point3f[] with M elements on one prim |
[M] |
{kDLFloat, 32, 3} |
Source:
tests/docs/c/test_attribute_shapes.cppsnippetsdoc-shape-scalar-int32-c,doc-shape-float3-array-c,doc-shape-mat4-array-c.
For a C point3f[] attribute with 10 points, write or read one tensor with shape=[10] and dtype={kDLFloat, 32, 3}. Rendered output/AOV tensors are not attribute tensors; in C they use channel-last shapes such as [height, width, channels] with dtype.lanes=1.
USD Type Lookup
Use this table to answer "how do I write USD type X?" For array-valued USD attributes, use write_array_attribute in Python and set binding.binding_desc.attribute_type.is_array = true in C. Python uses normal shape dimensions; C uses DLDataType::lanes.
| USD type(s) | Python value to write | C tensor dtype | Notes |
|---|---|---|---|
bool / bool[] |
np.bool_, shape (N,) or per-prim (M,) |
{kDLBool, 8, 1} |
|
uchar / uchar[] |
np.uint8 |
{kDLUInt, 8, 1} |
|
int, int2, int3, int4 and arrays |
np.int32, trailing shape (), (2,), (3,), (4,) |
{kDLInt, 32, lanes} |
|
uint / uint[] |
np.uint32 |
{kDLUInt, 32, 1} |
|
int64 / int64[] |
np.int64 |
{kDLInt, 64, 1} |
|
uint64 / uint64[] |
np.uint64 |
{kDLUInt, 64, 1} |
|
half, half2, half3, half4 and arrays |
np.float16, trailing shape by component count |
{kDLFloat, 16, lanes} |
|
float, float2, float3, float4 and arrays |
np.float32, trailing shape by component count |
{kDLFloat, 32, lanes} |
Direct runtime writes to scalar float3 work, but authored scalar USD float3 population is bugged in the current runtime. Prefer role-bearing point3f, normal3f, vector3f, or color3f for USD-authored data. |
double, double2, double3, double4 and arrays |
np.float64, trailing shape by component count |
{kDLFloat, 64, lanes} |
|
point3*, normal3*, vector3*, color3*, color4*, texCoord2f and arrays |
numeric dtype by suffix (h/f/d), trailing role dimensions |
same numeric dtype/lanes as storage | Roles are schema intent; tensor storage is numeric. |
quat* and arrays |
numeric dtype by suffix, shape (N, 4) or (M, 4) |
{kDLFloat, bits, 4} |
Write runtime order (i, j, k, real), not USDA order (real, i, j, k). |
matrix2d, matrix3d, matrix4d, frame4d and arrays |
np.float64, flattened trailing shape (4,), (9,), (16,), (16,) |
{kDLFloat, 64, 4/9/16} |
Generic authored matrix attrs are flattened. Transform semantic writes may use (N, 4, 4) Python arrays or {kDLFloat,64,16} C tensors. |
extent, _worldExtent |
np.float64, shape (N, 6) |
{kDLFloat, 64, 6} |
Usually read-only from population; extent is local-space, _worldExtent is world-space. |
string |
UTF-8 np.uint8 byte array via write_array_attribute |
{kDLUInt, 8, 1} with is_array=true |
String arrays are not supported. Use token[] for string-like arrays. |
token / token[] |
Python strings; pass is_token=True for token[] |
{kDLUInt, 64, 1} raw IDs with OVRTX_SEMANTIC_TOKEN_ID, or string helpers with OVRTX_SEMANTIC_TOKEN_STRING |
|
asset |
np.uint64 shape (N, 2) token pair |
{kDLUInt, 64, 2} |
Scalar asset only. Asset arrays are not supported. Python has no public helper to create asset tokens from strings today; C can use the path dictionary. |
relationship |
supported relationship helpers, usually path arrays | path string/path ID semantics | Custom relationships are ignored today. For material bindings and shader connections, use the relationship-specific helpers/snippets rather than generic custom relationship writes. |
timecode / timecode[] |
unsupported | unsupported |
Python
Array attribute write (mesh points)
Source:
tests/docs/python/test_attribute_shapes.pysnippetdoc-shape-float3-array
Array attribute write (same pattern for other array schemas)
Source:
tests/docs/python/test_attribute_shapes.pysnippetdoc-shape-float3-array
Prim modes
Source:
tests/docs/python/test_attribute_bindings.pysnippetdoc-bind-attribute-write
Token array attribute
Source:
tests/docs/python/test_attribute_bindings.pysnippetdoc-write-token-array
Path/relationship array attribute
Source:
tests/docs/python/test_base.pysnippetdoc-bind-material
Supported authored attribute write snippets
Python raw snippets:
| Type/pattern | Snippet |
|---|---|
bool |
doc-write-usd-bool |
int |
doc-write-usd-int |
float |
doc-write-usd-float |
point3f |
doc-write-usd-point3f |
point3f[] |
doc-write-usd-point3f-array |
normal3f |
doc-write-usd-normal3f |
vector3f |
doc-write-usd-vector3f |
color3f |
doc-write-usd-color3f |
matrix4d |
doc-write-usd-matrix4d |
quatf |
doc-write-usd-quatf |
string |
doc-write-usd-string |
token |
doc-write-usd-token |
token[] |
doc-write-usd-token-array |
The snippets listed in this table live in tests/docs/python/test_all_attributes.py.
Python can write token attributes directly from strings. For scalar asset attributes, Python can write the raw (token, 0) pair only if you already have a valid token ID; there is no public Python path-dictionary token-creation helper for asset strings today. The C snippet below shows the fully supported path-dictionary flow.
C
Generic scalar write in C
Source:
tests/docs/c/test_attribute_bindings.cppsnippetdoc-write-bound-attribute-c
Supported authored attribute write snippets in C
C raw snippets:
| Type/pattern | Snippet |
|---|---|
| scalar numeric | doc-write-usd-float-c |
| lane-3 scalar | doc-write-usd-point3f-c |
| lane-3 array | doc-write-usd-point3f-array-c |
| lane-16 matrix | doc-write-usd-matrix4d-c |
| quaternion | doc-write-usd-quatf-c |
| token | doc-write-usd-token-c |
| token array | doc-write-usd-token-array-c |
| string bytes | doc-write-usd-string-c |
| scalar asset token pair | doc-write-usd-asset-c |
The snippets listed in this table live in tests/docs/c/test_all_attributes.cpp.
Key Types / Functions
| Python | C |
|---|---|
renderer.write_attribute(...) |
ovrtx_write_attribute(renderer, &binding, &buffer, access) → returns ovrtx_enqueue_result_t |
renderer.write_array_attribute(..., is_token=True) |
same, with is_array=true in binding desc |
Semantics (Python: from ovrtx import Semantic; C: ovrtx_attribute_semantic_t):
Semantic.NONE/OVRTX_SEMANTIC_NONE-- generic data. In Python, element shape comes from trailing tensor dimensions. In C, element component count comes fromDLDataType::lanes. Use for colors, visibility, and other non-structured attributes.Semantic.XFORM_MAT4x4/OVRTX_SEMANTIC_XFORM_MAT4x4-- 4x4 double matrixOVRTX_SEMANTIC_XFORM_POS3d_ROT4f_SCALE3f-- decomposed transform (C only)OVRTX_SEMANTIC_XFORM_POS3d_ROT3x3f-- decomposed transform (C only)Semantic.PATH_STRING/OVRTX_SEMANTIC_PATH_STRING-- prim path stringsSemantic.TOKEN_STRING/OVRTX_SEMANTIC_TOKEN_STRING-- token stringsSemantic.TOKEN_ID/OVRTX_SEMANTIC_TOKEN_ID-- raw token IDs that are already present in the runtime path dictionary. In C, create them withpath_dictionary_create_tokens_from_strings()before writing raw token arrays.
In C, ovrtx_write_attribute returns ovrtx_enqueue_result_t which contains both .status (check for OVRTX_API_ERROR) and .op_index (for async tracking via ovrtx_wait_op).
Data access modes (Python: from ovrtx import DataAccess):
DataAccess.SYNC-- copies data during the call, safe to free after returnDataAccess.ASYNC-- data accessed later during stream execution, must keep alive; passcuda_stream=orcuda_event=for GPU synchronization. Not allowed with string data.
Troubleshooting
- Array attribute dtype must exactly match the USD schema. Using numpy's default
float64for afloat3[]attribute (which expectsfloat32) will cause errors. - In the current runtime, authored scalar USD
float3values may be created but populated as zero bypopulateAllAuthoredAttributes. If a value needs to come from USD, author it as a role-bearing type such asvector3f,point3f,normal3f, orcolor3f. Direct runtime writes to scalarfloat3still work. - Quaternion tensors use ovrtx/Fabric lane order
(i, j, k, real). USDAquat*values are authored as(real, i, j, k), so readingquatd,quatf, orquathattributes reorders the components into(i, j, k, real), and writes should use that runtime tensor order. - String attributes (
Semantic.PATH_STRING,Semantic.TOKEN_STRING) only support synchronous data access (DataAccess.SYNC). - String arrays are not supported as runtime attributes. If a workflow needs an array of string-like labels or categories, author and write a
token[]instead and passis_token=Truewhen writinglist[list[str]]data. - Asset arrays are not supported as runtime attributes. Scalar asset attributes may be represented internally, but there is no general string-list replacement for
asset[]. - Timecode attributes are not supported as runtime attributes, including both scalar
timecodeandtimecode[]. - Custom relationships are not populated by the generic authored-attribute path. Specific relationships used by supported schemas, such as
material:bindingand shader connections, are handled by their schema/population code paths; arbitrary custom relationships are ignored today. - Unsupported authored types are covered by negative tests in
tests/docs/python/test_all_attributes.pyandtests/docs/c/test_all_attributes.cpp; if one starts populating, keep this documentation and those tests in sync. - For array attributes in Python, pass a list of tensors (one per prim), not a single tensor. NumPy arrays, Warp arrays, and any
__dlpack__-compatible objects are accepted directly. - When creating attributes from scratch (
prim_mode=PrimMode.CREATE_NEW),semantic=is required for structured types (transforms, packed structs) so the C library knows what USD attribute type to create. - For
write_array_attributewithlist[list[str]]data, strings default to path/relationship arrays. Setis_token=Trueto write token arrays for custom token-list attributes. ovrtx_make_binding_descborrows the C prim path array. Keep anyovx_string_tprim paths and the array passed to the binding descriptor alive until the write operation has completed, or untilovrtx_create_attribute_bindingfinishes for persistent bindings.dirty_bitsis a bitvector with 1 bit per prim -- the byte array size must be(prim_count + 7) / 8.- In C,
dirty_bitssupport three combination modes viaovrtx_write_bits_tin theovrtx_input_buffer_t.dirty_bits_modefield:OVRTX_DIRTY_MASK_REPLACE(default -- replace existing mask),OVRTX_DIRTY_MASK_OR(merge with existing),OVRTX_DIRTY_MASK_AND(intersect with existing).
C convenience helpers for string attributes (#include <ovrtx/ovrtx_attributes.h>):
ovrtx_set_path_attributes(renderer, paths, count, attr_name, path_values)-- write path/relationship attributes. Each prim gets a single-element array (relationships are always arrays in USD).ovrtx_set_token_attributes(renderer, paths, count, attr_name, token_values)-- write token string attributes (one per prim).
Source:
tests/docs/c/test_attribute_helpers.cppsnippetdoc-set-token-attributes-c
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.