Releases: NVIDIA-Omniverse/ovstage
Release list
Release 0.1.1
Patch release. The C ABI is unchanged apart from one enumerator value: no
exported symbol was added, removed, or renamed, and no vtable slot or struct
layout moved, but the ovstage_config_uint64_t count sentinel advances from
0 to 1 now that the enum has a key. The headers add
OVSTAGE_ERROR_OUT_OF_RANGE, the runtime-default hierarchy computation model
selector, its configuration key, and two static inline configuration-entry
helpers; Python adds StageConfig, ErrorCode.OUT_OF_RANGE, and
HierarchyComputationModel.RUNTIME_DEFAULT. Some read and write validations
became stricter, others became less restrictive, and several now report a
different code and message, so callers that branch on status codes should read
the notes below.
Added
- Process configuration can select the runtime-default hierarchy computation
model, which automatic transform updates use and which callers can request
explicitly withOVSTAGE_HIERARCHY_COMPUTATION_MODEL_RUNTIME_DEFAULT. C
callers build the entry with either of two new helpers,
ovstage_config_entry_runtime_default_hierarchy_computation_model()or the
genericovstage_config_entry_uint64(), and pass it toovstage_initialize;
Python callers set it throughStageConfigwhen creating aStage. The
setting is process-scoped and defaults to
OVSTAGE_HIERARCHY_COMPUTATION_MODEL_CPU_INCREMENTAL. - Python:
make_dltensoraccepts adtypelayout override for a non-NumPy
DLPack producer, folding complete trailing dimensions intodtype.lanes. A
Warpvec3fbuffer exported as(N, 3)with one lane can be re-described as
(N,)with 3 lanes without copying the producer buffer. A fold that consumes
every producer axis normalizes to a one-element shape, so a component-only
producer shaped(3,)with one lane becomes(1,)with 3 lanes. 0.1.0
rejected every override on this path withValueError.
Changed
- Reads now enforce the sealing rule the API has always specified: an ordinal
must be sealed before data written at it can be read back. Ordinal-range reads
were not gated at all in 0.1.0 and returned data from ordinals that were still
open; they now validate the changes a range selects. Both read kinds also now
validate while the write floor is still at its initial value of0, a case
0.1.0 skipped, so a write at a positive ordinal is not readable until the
floor advances to cover it. Either failure reports
OVSTAGE_ERROR_WRITE_FLOOR_VIOLATION. Snapshot validation is at the same time
narrowed from the whole attribute column to the paths a query selects, so an
unsealed write to one prim no longer vetoes a read of untouched prims and
reads that 0.1.0 rejected can now succeed. Pending overlaps continue to report
OVSTAGE_ERROR_OP_FAILED, and a range that selects no change still returns
zero groups. - An ordinal-range read can now fail with the new
OVSTAGE_ERROR_OUT_OF_RANGE
status. The current implementation stores only the latest payload per key, so
when a selected(attribute, path)changed again after the range's end, the
only stored value is newer than the range and the interval cannot be
materialized, whether or not that later change is sealed. Latest-snapshot
reads never report this status: theirend_ordinalis not a historical
payload bound, so the current value is exactly what they ask for. ovstage_initializenow validates process configuration instead of ignoring
it. A malformed, duplicate, or unknown entry, or a runtime setting that
conflicts with one already active in the process, returns
OVSTAGE_ERROR_INVALID_ARGUMENT.- When ovstage starts its own runtime, it supplies a fixed internal argument
list, so host process arguments are no longer parsed as runtime options.
Configuration arrives throughOVSTAGE_*environment variables and
ovstage_initialize. A runtime the host started stays host-owned and keeps
whatever configuration the host gave it. - Clone retargets relationship targets, scalar and array path values, and USD
attribute connections that point inside the source subtree; paths outside it
are copied unchanged, so clones keep referencing shared materials and other
shared resources. Cloned attribute values, including relationship targets, are
ordinal-change-tracked. Scene hierarchy changes, such as parent child lists,
still are not. - Fixed-size reads and maps expose a canonical lane-based layout:
ndim == 1, a
leading dimension equal to the transported data-row count, and the complete
per-row tuple width indtype.lanes. Convenience write inputs such as
(N, 3)or(N, 4, 4)are still accepted, but their trailing shape is folded
into lanes and is no longer echoed back on read. A fixed-size write without
index_mapmust now haveshape[0]equal to the logical element count; a
flat(N * L,)one-lane tensor is not inferred asNrows of widthL. - Python: a
ManagedDLTensorreleases what it retains when the capsule is
destroyed, not when the consumer releases the tensor — for a consumed capsule,
as soon as the consumer takes ownership, which is generally earlier.
np.from_dlpack(group.dlpack(0))remains valid while the owning read/map
operation is alive; only a custom producer whosemanager_ctxsolely owns the
backing memory must keep theManagedDLTensoralive as long as the consumer's
view is used. - The headers and guides now specify the
maskbuffer contract (elementiis
biti % 64of wordi / 64; a non-NULL mask must address at least
ceil(count / 64)uint64_twords, because exactly that many are read), the
distinct roles ofcount,index_map, andmask, and that array writes do
not fold trailing dimensions intodtype.lanesthe way fixed-size writes do.
Seeovstage_write_data_tand the writing-attributes guide. - Documented the read representation for scalar
assetattributes populated
through the RENDERING population domain: each prim's value is one fixed
{kDLUInt, 64, 2}element carrying the
{authored-path token, resolved-path token}pair (resolved token0when
unresolved), with attribute semanticNONE. Decode tokens through the shared
path dictionary (path_dictionary_get_strings_from_tokens, Python
PathDictionary.token_to_string). This is transitional and is planned to
change toOVSTAGE_SEMANTIC_ASSET_STRINGbyte rows in a future release.
Fixed
write_attributederived a write's transported row count fromindex_map
rather than from the payload, so a map entry past the payload's rows invented
extra rows and the resulting row width was reported as though the caller had
declared it: a 4-bytefloat32scalar was rejected as
OVSTAGE_ERROR_NOT_SUPPORTEDwith "dtype code=2 bits=32 lanes=1 and 2
byte(s)". Fixed-size writes now take their row count from the tensor's
shape[0]and per-row array writes fromtensor_count, and both range-check
index_mapagainst it. Packed array transport declares no row count, so there
the map still defines the partition; a partition the payload cannot support is
nowOVSTAGE_ERROR_INVALID_ARGUMENTwith a message naming the map.- Most write payload rejections no longer return a bare error code with an empty
message. Missingcount, mutually exclusiveindex_map/mask, an oversized
count, a malformed single source tensor, an out-of-range row selection, and a
payload that does not divide evenly across its rows each now carry a
diagnostic naming the offending input. Per-row (tensor_count > 1) tensor
validation still reports a bareOVSTAGE_ERROR_INVALID_ARGUMENT. - A row width that is not a whole number of
dtypeelements is now
OVSTAGE_ERROR_INVALID_ARGUMENTrather thanOVSTAGE_ERROR_NOT_SUPPORTED: it
reflects a payload cut into the wrong number of rows, not a capability the
build lacks. Genuinely unrepresentable dtypes and over-wide fixed rows remain
OVSTAGE_ERROR_NOT_SUPPORTED. - A write that declares
OVSTAGE_SEMANTIC_MATRIXis no longer restricted to
non-array values with the fixed{kDLFloat, 64, 16}layout. The matrix role
is represented independently of the numeric layout, somatrix3f,matrix4f,
and matrix-valued arrays write and read back with the layout the caller
declared. 0.1.0 rejected them withOVSTAGE_ERROR_OP_FAILED. read_attributeson a USD-populated scalarassetattribute returned
OVSTAGE_ERROR_END_OF_ITERATIONwith no groups when the read covered a single
prim, even though the attribute was discoverable with anOVSTAGE_FILTER_OP_HAS
query and the same read succeeded across more than one prim. Single-prim reads
now return the representation multi-prim reads already produced.- A write whose source tensor lives in CUDA device memory reached storage but
did not mark the written elements as changed, so downstream consumers such as
a renderer never observed the new values; a CUDA-sourcedomni:xformupdate
left the rendered scene unchanged. Such writes now flag the elements they
touch, and wait for their device-side copy to complete before the operation
reports done, where previously it could report completion with the copy still
in flight. - Population no longer drops a render settings
camerarelationship whose
camera prim does not exist yet, so that relationship survives population and
cloning. Other relationships still require their targets to exist.
Relationship targets are now also taken as authored rather than forwarded
through relationship chains. - USD scene-graph instance proxies now carry the reset-transform-stack state of
the prim they stand in for, so a proxy whose source prim resets its transform
stack is populated with the correct transform. - ovstage initializes reliably however the host process was launched. ...
Release 0.1.0
Initial pre-release of ovstage (builds published as 0.1.0.<build>). API,
behavior, and packaging may change before GA.
Added
- Asynchronous, ordinal-keyed C data-plane API (
include/ovstage/): writes,
reads, queries, zero-copy map/unmap, cloning, deletion, hierarchy queries,
and instancing queries, with DLPackDLTensortensor interchange. This
build retains the latest committed snapshot only. - USD population C API (
ovstage_population.h): load composed USD scenes into
the runtime stage, add/remove references, and propagate USD edits and time
samples at application-owned ordinals. - Shared path dictionary (
include/ovx/path_dictionary/) for interned prim
paths and tokens exchanged across OV libraries. - Python bindings package (
python/ovstage/, ctypes over the C data plane). - Runnable C and Python example pairs (
examples/), task-oriented agent
skills (skills/), Sphinx documentation sources (docs/), and the
public-contract test suites (tests/).
Limitations
- Payload reads return the latest committed payload or tombstone, not historical
payload versions. Ordinal ranges retain bounded change membership only; query
ovstage_get_oldest_preserved_ordinalbefore consuming older ranges. - Map/unmap is staging-backed and write-only: mapped buffers are not initialized
from current storage, and unmap copies or scatters staged data into storage. - Submission may perform synchronous preparation or wait for prerequisite
handles, and accepted work executes through one serialized lane per instance. - Overlapping reads, writes, deletes, and maps may be rejected while conflicting
operations or borrowed groups remain live; release or finish them and retry. - Query predicates support only the documented operator/attribute matrix;
other operators exposed by the headers or bindings returnNOT_SUPPORTED. write_attributesgroups completion under one operation but is not atomic;
individual entries may apply incrementally.- Clone copies relationships verbatim without retargeting references inside the
cloned subtree. Only value attributes are ordinal-change-tracked for clones. - USD-populated derived transforms are not available through
read_attributes;
directly authored transform columns remain readable. - Python writes do not expose
managed_tensorsownership transfer; callers must
keep client-managed source tensors alive until the operation completes.