Omniverse Kit 107 Migration Guide#

This guide details the steps and considerations necessary for migrating extensions and applications to Omniverse Kit 107. It incorporates essential updates, dependency changes and known issues, ensuring a clear and structured approach to facilitate a upgrading from previous releases.

The Omniverse Kit 107 release includes the following note-worthy dependencies, amongst others:

Component

Reference

OpenUSD 24.05

Changelog

Python 3.11

Release Notes

glibc 2.35 (Linux only)

Release Notes

Table of Contents#

  1. Preparing for Migration

  2. Migrating Extensions to Omniverse Kit 107

    1. Updating Dependencies

    2. Renamed Python APIs and Modules

    3. C++/Python Project Configuration

    4. OpenUSD Project Configuration

    5. Enabling C++17 Features

    6. Introducing Carbonite Events 2.0

    7. Changes to Carbonite Logging

    8. Changes to Fabric Asserts

  3. Additional Resources

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.

Migrating Extensions to Omniverse Kit 107#

Migrating to Omniverse Kit 107 from an earlier version involves performing the following changes to your application and extensions.

Updating Dependencies#

Starting with Omniverse Kit 107, native C++ packages on Linux are provided using the _GLIBCXX_USE_CXX11_ABI=1 option to control whether the C++ Standard Library headers use the new or old Application Binary Interface (ABI) when compiling with GCC. Setting this macro to 1 enables the new ABI, which was introduced in GCC 5.1 to accommodate changes in C++11, such as the addition of std::string and std::list changes. This new ABI is the default for GCC, so setting it to 1 is typically not necessary unless you are working in an environment where the default is set to 0, as in some Linux distributions.

Enabling the new ABI allows for compatibility with C++11 features, and ensures that the compiled code uses the updated library implementations. However, if you need to work with pre-C++11 features or libraries compiled with the old ABI, you would set _GLIBCXX_USE_CXX11_ABI=0.

In order to resolve between packages which may be available in ABI=0 and ABI=1 variants, a new platform flag is now available when specifying platform dependencies. For the ones specified in the XML files located in the /deps folder of your project, ${platform_target} tokens can now be replaced with the new ${platform_target_abi} to resolve to the appropriate variant.

For example, where a project may have previously specified a dependency on the Client Library in the following way:

<project toolsVersion="6.11" chroniclePath="../_build/chronicles">
   <!-- [...] -->
   <dependency name="omni_client_library" linkPath="../_build/target-deps/omni_client_library">
      <package name="omni_client_library.${platform_target}" version="2.57.0" />
   </dependency>
   <!-- [...] -->
</project>

Starting with Omniverse Kit 107, the equivalent naming is now:

<project toolsVersion="6.11" chroniclePath="../_build/chronicles">
   <!-- [...] -->
   <dependency name="omni_client_library" linkPath="../_build/target-deps/omni_client_library">
      <package name="omni_client_library.${platform_target_abi}" version="2.57.0" />
   </dependency>
   <!-- [...] -->
</project>

Renamed Python APIs and Modules#

The following Python APIs deprecated in an earlier Omniverse SDK versions have now been removed. Where applicable, references can be changed to alternative APIs and modules exposing similar features:

Extension/Module Deprecated APIs Replacement Module/APIs (if applicable)

carb.imgui

All

omni.kit.imgui

omni.kit.debug.python

  • breakpoint()

  • wait_for_client()

omni.kit.material.library

  • build_material_combobox_ui()

  • get_instance()

omni.kit.menu.common

  • add_menu()

omni.kit.menu.create

  • get_action_name()

  • get_audio_prim_list()

  • get_geometry_standard_prim_list()

  • get_light_prim_list()

  • N/A

  • usd.schema.audio.get_audio_prim_list()

  • omni.usd.get_geometry_standard_prim_list()

  • omni.usd.get_light_prim_list()

omni.kit.menu.edit

  • toggle_global_visibility()

  • omni.kit.viewport.actions.toggle_global_visibility()

omni.kit.menu.utils

  • set_default_menu_proirity()

  • set_default_menu_priority()

omni.kit.stage_templates

  • get_extension_path()

  • load_templates()

  • unload_templates()

omni.kit.widget.nucleus_connector

  • get_nucleus_connector()

omni.kit.widget.nucleus_info

  • get_instance()

  • get_nucleus_info()

omni.kit.window.toolbar

  • get_data_path()

omni.mdl.neuraylib

  • RegisterExtensionSearchPath()

  • UnregisterExtensionSearchPath()

  • RegisterExtensionContent()

  • UnregisterExtensionContent()

C++/Python Project Configuration#

If your C++ project includes or links against Python features, make sure the premake.lua configuration for your Extension references the new Python 3.11 dependencies for Omniverse Kit 107.

Your Premake configuration may contain references to Python libraries in different ways, most likely when declaring include directories, libraries against which to link, and artifacts to place in build folders. These can take the form of the following (note this does not represent an exhaustive list, depending on the nature of your project):

-- [...]
repo_build.prebuild_copy{
    -- [...]
    {"%{root}/_build/target-deps/carb_sdk_plugins/_build/linux-x86_64/release/scripting-python-3.10/libpython*", lib_dir},
    -- [...]
}
-- [...]
includedirs { target_deps.."/python/include/python3.10" }
-- [...]
links {"python3.10", "boost_python310"}
-- [...]

After migrating to Omniverse Kit 107, the corresponding configurations should be expressed as the following (notice the references to 3.10 being updated to 3.11):

-- [...]
repo_build.prebuild_copy{
    -- [...]
    {"%{root}/_build/target-deps/carb_sdk_plugins/_build/linux-x86_64/release/scripting-python-3.11/libpython*", lib_dir},
    -- [...]
}
-- [...]
includedirs { target_deps.."/python/include/python3.11" }
-- [...]
links {"python3.11", "boost_python311"}
-- [...]

OpenUSD Project Configuration#

With Omniverse Kit 107 now using a stock version of OpenUSD, note that your configuration may require changing references from _build/target-deps/nv_usd to _build/target-deps/usd in a few locations. These include configuration files such as:

  • repo.toml

  • premake5.lua

  • etc.

Depending on your project, references may appear in various source and configuration files. If your project references OpenUSD libraries, you may wish to perform a search and replace operation to update references from nv_usd to their corresponding usd nomenclature for Kit 107.

Additionally, if your project happens to link against OpenUSD features, you can modify its premake.lua configuration to reference the stock OpenUSD libraries by replacing linker statements in the following way:

-- Before Omniverse Kit 107:
-- [...]
links {"ar", "vt", "gf", "pcp", "sdf", --[[ ... ]] "kind", "tbb"}
--- [...]
-- Starting with Omniverse Kit 107:
-- [...]
add_usd {"ar", "vt", "gf", "pcp", "sdf", --[[ ... ]] "kind"}
links {"tbb"} -- NOTE: Link against "tbb" using `links {}`, rather than `add_usd {}`.
-- [...]

Enabling C++17 Features#

You may wish to enable C++17 features for your project by to supplying the cppdialect option in the Premake configuration of your existing C++ Extension. In general, Users moving from C++14 to C++17 should not present any major roadblock as no code change should otherwise be necessary. For details an overview of features added and deprecated in C++17, a changelog is available on cppreference.com.

To enable C++17 for your Extension, simply replace the following snippet at the top of the /premake5.lua script :

-- [...]

-- Insert kit template premake configuration, it creates solution, finds extensions.. Look inside for more details.
dofile("_repo/deps/repo_kit_tools/kit-template/premake5.lua")

-- [...]

With the following Lua snippet:

-- [...]

local options = {
    cppdialect = "C++17" -- Will otherwise default to "C++14" if not specified.
}

-- Insert kit template premake configuration, it creates solution, finds extensions.. Look inside for more details.
kit = require("_repo/deps/repo_kit_tools/kit-template/premake5-kit")
kit.setup_all(options)

-- [...]

Introducing Carbonite Events 2.0#

Starting with version 107, kit-kernel’s RunLoops transition to using Events 2.0. While this is done by creating backwards-compatible EventAdapter objects, general application performance can be improved by performing the changes highlighted below.

With Events 1.0, an event was pushed into the EventStream before the EventStream was pumped (as were the preUpdate and postUpdate event streams). Using C++, the update would take the form of:

// Before updating to Omniverse Kit 107:
if (updateEnabled) {
    CARB_PROFILE_ZONE(kProfilerMask, "[RunLoop: %s] Update Events", name.c_str());
    if (mainThread) {
        this->loop->update->push(
            0,
            std::make_pair("dt", dt),
            std::make_pair("SWHFrameNumber", m_runLoopIterationCount)
        );
    } else {
        this->loop->update->push(
            0, 
            std::make_pair("dt", dt)
        );
    }
    this->loop->update->pump();
}

Using Events 2.0 under Omniverse Kit 107, the equivalent can be expressed as follows:

// After updating to Omniverse Kit 107:
if (updateEnabled) {
    if (mainThread) {
        ed->dispatchEvent(
            updateName,
            std::make_pair(RStringKey("dt"), dt),
            std::make_pair(RStringKey("SWHFrameNumber"), m_runLoopIterationCount)
        );
    } else {
        ed->dispatchEvent(
            updateName,
            std::make_pair(RStringKey("dt"), dt)
        );
    }
}

Similarly, an extension implemented using Python would take a form akin to the example below for subscribing to update events and printing them to the console:

# Before updating to Omniverse Kit 107:
import carb.events
import omni.kit.app

def on_update(e: carb.events.IEvent):
    print(f"Update: {e.payload['dt']}")

event_sub = omni.kit.app.get_app().get_update_event_stream().create_subscription_to_pop(
    on_update,
    name="My Subscription Name"
)

The new form of this Python snippet is now:

# After updating to Omniverse Kit 107:
import carb.eventdispatcher
import omni.kit.app

def on_update(e: carb.eventdispatcher.Event):
    print(f"Update: {e['dt']}")

event_sub = carb.eventdispatcher.get_eventdispatcher().observe_event(
    event_name=omni.kit.app.GLOBAL_EVENT_UPDATE,
    on_event=on_update,
    observer_name="My Subscription Name"
)

Changes to Carbonite Logging#

A new log consumer (Omni logging) and logger (Carb logging) have been added, and implemented as carb::logging::Logger2 and omni::log::ILogMessageConsumer2, respectively.

Instead of taking individual log metadata values as the parameters to their message handler function, these APIs now take a single struct parameter with this struct versioned using the carb::logging::LogMessage::sizeOf member variable. Logger/consumer implementations for this new version will be required to check this field to ensure it is safe to access newer fields.

If the latest carb::logging::ILogging interface is used (that is, carb_logging_ILogging is defined to CARB_HEXVERSION(1,3) or later), this implies the carb::logging::ILogging::addLogger() function has also been deprecated in a way that will force a compile error when adding new loggers or consumers. Features will thus be required to supply new implementations for registering these components.

Adopting these changes should only require changing the base class that the implementation inherits from, and how the various log message values are accessed. A sample illustration of the changes can take the form of the following:

  1. Define carb_logging_ILogging in the project’s premake5.lua configuration:

-- [...]
defines { "carb_logging_ILogging=CARB_HEXVERSION(1,3)" }
-- [...]
  1. Use a logger struct inheriting from carb::logging::Logger2:

- carb::logging::Logger logger{ [](carb::logging::Logger*, const char*, int32_t, const char*, const char*,
-                                  int, const char*) { /* ... */ } };
+ struct SampleLogger : carb::logging::Logger2
+ {
+     void handleMessage(const carb::logging::LogMessage& msg) override
+     {
+         /* ... */
+     }
+ } logger;

 auto logging = carb::logging::getLogging();
 logging->setLevelThreshold(carb::logging::kLevelVerbose);
 logging->addLogger(&logger);

Changes to Fabric Asserts#

Omniverse Kit 107.0 adds a static assert to omni.fabric.plugin’s public headers, which could break compilation (API, not ABI). It asserts that templated pointers returned by getAttribute (and family) are std::is_trivially_copyable to better represent in the Fabric API how Fabric internally manages this memory.

Prior to these changes, one could alias Fabric memory as having type-imbued copy logic, which is disregarded by Fabric. This change was made to help smoke out aggressive use of fabric::Path, fabric::Token, pxr::SdfPath, and pxr::TfToken, which all involve operator= counting logic. Combining types like these with return value pointers into Fabric memory may unfortunately encourage incorrectly bookkeeping the counts of the underlying data (which is identical Path-to-SdfPath and Token-to-TfToken).

Until delivery of a new handle system in an upcoming release, all interactions with BaseDataType::ePath and BaseDataType::eToken attributes need to use fabric::PathC and fabric::TokenC, which avoid performing any referencing counting. This means that read-access pointers to attribute memory will need calls to toSdfPath(), toTfToken(), fabric::Path::Path() and fabric::Token::Token() to make use of these handles (get the string representation, etc.).

Write-access pointers to attribute memory should call through StageReaderWriter::registerPath, StageReaderWriter::registerToken, or omni::fabric::ObjectDirectory to ensure that the PathC and TokenC handles in Fabric’s memory are having their lifetime counted by the Fabric which owns that memory. After registering with the ObjectDirectory, use omni::fabric::asInt as before to convert those classes to PathC and TokenC for storage in Fabric memory.

For an illustration of the changes, consider the following Fabric examples:

// Produces a compile error in Omniverse Kit 107.0:
const omni::fabric::Path* path = stage.getAttributeRd<omni::fabric::Path>(
    omni::fabric::Path("/prim"), omni::fabric::Token("attr")
);

// Fix for 107.0:
const omni::fabric::PathC* pathC = stage.getAttributeRd<omni::fabric::PathC>(
    omni::fabric::Path("/prim"), omni::fabric::Token("attr")
);
// Stack object holds a reference:
const omni::fabric::Path path = omni::fabric::Path(*pathC);
// Produces a compile error in Omniverse Kit 107.0:
omni::fabric::Path* path = stage.getAttribute<omni::fabric::Path>(
    omni::fabric::Path("/prim"), omni::fabric::Token("attr")
);

// Fix for 107.0.
// Stack object holds a reference, but we also want to put this value into a Fabric stage:
const omni::fabric::Path path("/anotherPrim");
omni::fabric::PathC* pathC = stage.getAttribute<omni::fabric::PathC>(
    omni::fabric::Path("/prim"), omni::fabric::Token("attr")
);
// Register the path with the Fabric's `ObjectDirectory`, so it holds a reference to it:
stage.registerPath(path);
*pathC = path.asPathC();

For additional illustrations of the changes, consider the following OpenUSD examples:

// Produces a compile error in Omniverse Kit 107.0:
const omni::fabric::Path* path = stage.getAttributeRd<omni::fabric::Path>(
    omni::fabric::Path("/prim"), omni::fabric::Token("attr")
);

// Fix for 107.0:
const omni::fabric::PathC* pathC = stage.getAttributeRd<omni::fabric::PathC>(
    omni::fabric::Path("/prim"), omni::fabric::Token("attr")
);
const pxr::SdfPath path = toSdfPath(*pathC); // Stack object holds a reference.
// Produces a compile error in Omniverse Kit 107.0:
omni::fabric::Path* path = stage.getAttribute<omni::fabric::Path>(
    omni::fabric::Path("/prim"), omni::fabric::Token("attr")
);

// Fix for 107.0.
// Stack object holds a reference, but we also want to put this value into a Fabric stage:
const pxr::SdfPath path("/anotherPrim");
omni::fabric::PathC* pathC = stage.getAttribute<omni::fabric::PathC>(
    omni::fabric::Path("/prim"), omni::fabric::Token("attr")
);
// Register the path with the Fabric's `ObjectDirectory`, so it holds a reference to it:
omni::fabric::StageReaderWriterUsd::registerPath(stage, path);
*pathC = asInt(path);

Additional Resources#

Should you encounter any issues or require further assistance in upgrading your Omniverse Kit application or extensions to version 107, please refer to the Omniverse community forums.