Omniverse Kit 109 Migration Guide#
This guide details the steps and considerations necessary for migrating extensions and applications to Omniverse Kit 109. It incorporates essential updates, dependency changes and known issues, ensuring a clear and structured approach to facilitate upgrading from previous releases.
The Omniverse Kit 109 release includes the following updated dependencies:
Component |
Reference |
|---|---|
NumPy 2.3.1 |
|
CUDA 12.4.1 |
Table of Contents#
Preparing for Migration#
Before starting any update process, please ensure that you have the following prerequisites in order to minimize disruptions during migration:
Ensure you have access to the latest Omniverse Kit SDK.
You are familiar with your application’s architecture, and existing dependencies.
You have a backup of your current project, to prevent any potential data loss during migration.
A process in place to confirm all functionalities of your application and extensions behave as expected after upgrading.
This process can vary depending on your organization, but typically includes elements such as automated builds, unit or integration tests, documentation about your feature’s behavior, reviewing log information, etc.
Carbonite#
carb::thread::shared_lockhas been removed.std::shared_lockcan be used as a drop-in replacement.IDictionary::MakeAtPathS(...)function has been renamed toIDictionary::MakeAtPath, and returns anItem*of the dictionary entry just created.carb::extras::compareStringsNoCase(a, b)has been removed. Now you can use the functioncarb::extras::caseInsensitiveCompare(a, b)if eitheraorbis a safe string type (i.e. one of the following types:std::string_view,std::string,carb::cpp::string_view,carb::cpp::zstring_view,omni::string,char[N], or a string literal). If both parameters are unsafe string types (char*s pointing to a null-terminated string), it must be replaced with the overloadcarb::extras::caseInsensitiveCompare(carb::cpp::unsafe_length, a, b).ILoggerinterface has changed,Loggerclass has been replaced withLogger2and the older functions have been deprecated.handleMaessageis now a virtual function instead of a pointer.Potential
fmtnamespace conflict. Carbonite introducescarb/Format.hthat adds a namespacecarb::fmt, which in some cases (e.g. whenusing namespace carb;is used) can conflict with thefmtnamespace provided by thefmtlibrary. To fix this, disambiguate the function calls with the full namespace (either::fmtor::carb::fmt).
Fabric Token and Path Changes#
Overview#
Kit 109 introduces breaking changes to Fabric’s token and path handling system. The legacy fabric::TokenC, fabric::PathC, fabric::TokenId, and fabric::PathId types have been removed in favor of modernized fabric::Token and fabric::Path types that are trivially copyable and use weak references.
These changes were made to make storage of pxr::TfToken and pxr::SdfPath data in Fabric safe. Typically these pxr types are “incrementally refcounted” meaning that operator=, destructors, etc bookkeep the reference counts automatically. Fabric treats all attribute memory as trivially copyable for performance reasons, and memcpy-ing pxr::TfToken and pxr::SdfPath into trivially copyable memory is tricky to handle correctly, particularly when the underlying memory is shared between multiple Fabrics. The new fabric::Token and fabric::Path handles become invalid safely, and remain valid so long as the Fabrics they are registered to still exist. Make sure to register any handles stored in attribute to the appropriate Fabrics to ensure they validity.
Key Changes:
fabric::TokenCandfabric::PathChave been removedfabric::TokenIdandfabric::PathIdhave been removedfabric::Tokenandfabric::Pathare now the standard types for all use casesfabric::Tokenandfabric::Pathare weak references and trivially copyable (no reference counting on assignment)Token and Path cannot be reinterpret-casted to
TfTokenandSdfPathas they represent different handles to different backing storagesFabric attribute buffers of type
BaseDataType::eTokenandePathare nowfabric::Tokenandfabric::Path
Required Code Updates#
Token and Path Validity Checking#
The legacy kUninitializedToken and kUninitializedPath constants have been removed.
Checking Validity:
Each Token and Path can be checked for validity using one of the following methods:
Compare to default-initialized value
Call
isNull()to check if never initializedCall
isExpired()to check if backing storage has been released. Prefer callingisNull()for performance unless this function is required. Calling getString() on an expired Path will no longer crash, so knowledge of expiration is generally less important.Call
validate()to check both (not null and not expired)
Note: validate() is a non-trivial operation (hence the name), and the validity state can change immediately after the function returns if another thread releases the backing storage.
Migration Examples:
Before (Kit 108) |
After (Kit 109) |
|---|---|
|
|
|
|
- |
|
Creating Fabric Tokens and Paths#
To obtain fabric::Token or fabric::Path instances, you must use one of the following construction methods:
Direct Construction with FabricId:
omni::fabric::Token token(fabricId, "tokenString");
omni::fabric::Path path(fabricId, "/path/string");
Using StageReaderWriter:
// Register single token
Token token = stageReaderWriter->registerToken("tokenString");
// Register multiple tokens (batched - preferred for performance)
const char* tokenStrings[] = {"token1", "token2", "token3"};
Token tokens[3];
stageReaderWriter->registerTokens(
carb::cpp::Span<const char*>(tokenStrings, 3),
carb::cpp::Span<Token>(tokens, 3)
);
Using StageReaderWriterUsd (for TfToken/SdfPath):
// Register single TfToken
Token token = stageReaderWriterUsd->registerToken(tfToken);
// Register multiple TfTokens (batched - preferred for performance)
TfToken usdTokens[] = {TfToken("token1"), TfToken("token2")};
Token fabricTokens[2];
stageReaderWriterUsd->registerTokens(
carb::cpp::Span<const PXR_NS::TfToken>(usdTokens, 2),
carb::cpp::Span<Token>(fabricTokens, 2)
);
// Path works the same way
Path path = stageReaderWriterUsd->registerPath(sdfPath);
Creating Immortal Tokens (Use with Caution):
// Only use for tokens that:
// 1. Will always have the same string across multiple runs
// 2. Will not cause leaks if a scene is reloaded multiple times
Token immortalToken = omni::fabric::Token::createImmortal("constantToken");
Important Notes:
Tokens and paths are reference-counted with the fabrics they are registered with
The lifetime is at least as long as the specified fabric
Storing TfToken and SdfPath in Fabric#
When you need to store USD tokens and paths in Fabric attributes:
Use
StageReaderWriterUsd::registerTokenorregisterPathto convert from USD types.Store the resulting
fabric::Tokenorfabric::Pathin the Fabric attribute.Each lineage of fabrics (fabrics copied from each other) shares a cluster of Token and Path handles.
The internal registry is only released when the last fabric in the lineage is destroyed.
Cross-Lineage Considerations:
When copying a Token or Path between fabrics that are not from the same lineage, you must register them again.
Without re-registration, handles remain safe but become invalid when the old lineage is destroyed.
There is currently no API to split a fabric from its lineage (by design).
Example:
// Convert and store TfToken in fabric
TfToken usdToken("myAttribute");
Token fabricToken = stageReaderWriterUsd->registerToken(usdToken);
// Store in fabric attribute
// (attribute of type BaseDataType::eToken now uses fabric::Token)
fabricAttribute.set(fabricToken);
Conversion Between USD and Fabric Types#
Prefer Batched Conversion:
All individual conversion functions internally call batched versions, so prefer batched APIs for performance:
// ✅ Good - Batched conversion
std::vector<TfToken> usdTokens = {...};
std::vector<Token> fabricTokens(usdTokens.size());
stageReaderWriterUsd->registerTokens(
carb::cpp::Span<const TfToken>(usdTokens.data(), usdTokens.size()),
carb::cpp::Span<Token>(fabricTokens.data(), fabricTokens.size())
);
// ❌ Less efficient - Individual conversions in loop
for (const auto& usdToken : usdTokens) {
fabricTokens.push_back(stageReaderWriterUsd->registerToken(usdToken));
}
Conversion Function Guidelines:
Prefer using
getSdfPathandgetTfTokenmethods onStageReaderWriterUsdwhen availableFree-floating conversion functions without a fabric ID parameter create “immortal” tokens/paths stored in a global cache
Use methods on
StageReaderWriter(Usd)or functions with a fabric ID parameter to limit lifetime to specific fabrics
StageReaderWriterUSD Direct Access#
StageReaderWriterUSD can now access primitives using SdfPath/TfToken directly without explicit conversion:
// Direct primitive lookup using SdfPath
auto prim = stageReaderWriterUsd->getPrimAtPath(sdfPath);
// Separate prim lookup table using SdfPath is maintained
This provides more convenient access patterns when working primarily with USD types.
Migration Checklist#
[ ] Replace
kUninitializedTokenandkUninitializedPathwith.isNull()or.validate()checks[ ] Update code that creates tokens/paths to use registration methods
[ ] Replace
TokenCandPathCtypes withTokenandPath[ ] Replace
TokenIdandPathIdtypes withTokenandPath[ ] Remove any
reinterpret_castbetweenToken/TfTokenorPath/SdfPath[ ] Update attribute buffer code expecting old token/path types
[ ] Prefer batched conversion functions over individual conversions
[ ] Review cross-fabric token/path usage and add re-registration where needed
[ ] Test fabric attribute operations involving tokens and paths
[ ] Rebuild all C++ extensions (ABI breaking change)
NumPy 2.x Update#
Kit 109 upgrades from NumPy 1.x to NumPy 2.3.1. This update enables seamless integration with Isaac-Newton and modern robotics frameworks, and brings improved performance and new capabilities from the NumPy 2.x series.
Breaking Changes#
NumPy 2.0 introduced several breaking changes that may affect your extensions:
1. API Changes
Some deprecated NumPy 1.x APIs have been removed
Type promotion rules have changed
C API functions may have different signatures
2. Data Type Changes
Default integer size on Windows changed from
int32toint64String dtype handling has changed
Datetime64 behavior updates
3. C API Updates
If your extension includes NumPy C headers, review the NumPy 2.0 C API changes
Migration Steps#
Review NumPy Usage: Audit your code for deprecated NumPy 1.x APIs
Update Type Assumptions: Check code that assumes specific integer sizes or types
Test Thoroughly: NumPy type changes can cause subtle bugs
Update Dependencies: Ensure other Python packages are NumPy 2.x compatible
For detailed migration guidance, see the NumPy 2.0 Migration Guide.
CUDA Update#
Kit 109 updates CUDA SDK to version 12.4.1, providing the latest GPU compute capabilities and optimizations.
Driver Requirements#
This update requires minimum driver versions:
Linux: >= 550.54.15
Windows: >= 551.78
Action Required: Verify your driver versions before upgrading to Kit 109. Applications will fail to start with older drivers.
Compatibility Notes#
Extensions using CUDA APIs should be rebuilt against CUDA 12.4.1
Review CUDA 12.4 release notes for API changes if you use CUDA directly
RTX rendering improvements leverage new CUDA 12.4 features
Carbonite String Safety#
Kit 109 introduces comprehensive string safety upgrades throughout Carbonite and Kit, replacing unsafe string functions with secure alternatives.
Interface Changes#
New safe-only interfaces have been introduced for core Carbonite systems:
ISettings- Settings dictionary interfaceIError- Error handling interfaceIDictionary- Dictionary interface
Migration Required: Code using legacy string-based methods on these interfaces may need updates to use string_view-based alternatives.
String View Migration#
Many Carbonite APIs now accept carb::cpp::string_view instead of const char*:
// ✅ New - String view based (preferred)
settings->setString("/my/setting", carb::cpp::string_view("value"));
// Still supported but prefer string_view where available
settings->setString("/my/setting", "value");
Benefits:
Eliminates buffer overflow vulnerabilities
Improves performance by avoiding unnecessary string copies
Enables safer string handling across API boundaries
Action Items#
Review Compiler Warnings: New string safety checks may produce warnings
Update String Handling: Migrate to
string_viewwhere recommendedTest String Operations: Ensure string handling behaves correctly with new interfaces
Other Breaking Changes#
Fabric Scene Delegate Default Enabled#
Fabric Scene Delegate (FSD) is now enabled by default in Kit 109. Applications no longer need to explicitly enable FSD in .kit configuration files.
Action Required: If your application explicitly disables FSD, test compatibility and performance with FSD enabled.
Memory Allocator Change (Windows)#
Kit on Windows now uses mimalloc as the default memory allocator. For compatibility scenarios, the system allocator remains available via kit-sysalloc.exe.
Impact: Most applications will see improved memory performance. If you experience memory-related issues, the system allocator fallback is available for troubleshooting.
Previous Release Migration Guides#
For migration from earlier Kit versions:
Kit 108 Migration Guide - OpenUSD 25.02, Python 3.12, Carbonite Path changes, Live Streaming 2.0