Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
rust-usd
OpenUSD ships as a hefty C++ library in the pxr namespace. There has not been a usable Rust binding for it. This repository is one. It contains two crates that together cover what a USD aware tool needs to read assets, edit them without mutating the original, and hand them off to Hydra for rendering.
The split is intentional. rust-usd is the core. It opens stages, walks prims, reads typed mesh attributes, follows payloads, switches variants, authors edits into a sidecar layer, and emits material graphs that render in usdview, Karma, or RenderMan. hydra-rs is the renderer plumbing. It feeds a stage into a UsdImagingStageSceneIndex, enumerates registered render delegates, and exposes a render_to_rgba call wired up through UsdImagingGLEngine. The Hydra side builds and links cleanly. The render call segfaults headlessly on macOS until the graphics context plumbing is finished. The README is honest about that state.
What works today
The eight examples under examples/ are the proof for rust-usd.
open_stage walks the prim tree of a .usda, .usdc, or .usdz file. dump_meshes reads points, face vertex counts and indices, normals with their interpolation, primvars st with optional indices, the world space transform from UsdGeomXformCache, and the subdivision scheme. dump_textures walks a bound material's shader graph and surfaces the inputs:file paths from any UsdUVTexture nodes. payload_control opens a stage with InitialLoadSet::None and then loads paths on demand. forge_demo installs a Rust side resolver for forge:// URIs through an AssetResolver trait that USD calls back into during stage composition.
The interesting half is the authoring side. variants_demo opens an asset with Stage::open_for_painting, which mounts the asset as a sublayer of an empty edit layer and points the edit target at the edit layer. Switching the active variant writes to the edit layer. save_edit_layer writes only the edit layer to disk. The asset stays byte identical. paint_demo does the same dance for arbitrary primvars, authoring primvars:wear and primvars:dustColor into a sidecar. shade_demo builds a UsdPreviewSurface plus a UsdUVTexture whose inputs:file carries a <UDIM> token, binds the material to the cube, saves, and the asset file still hashes the same as before. The generated edit layer is renderable USD that any compliant renderer can open directly.
How to build it
There is no vendored USD here. You point the build script at an existing OpenUSD install through environment variables. The crate has been verified against the USD that ships with Houdini 21.0.631 on macOS, which is upstream USD 25.05.
For Houdini on macOS the variables look like this.
USD_INCLUDE_DIR=/Applications/Houdini/Houdini21.0.631/Frameworks/Houdini.framework/Versions/21.0/Resources/toolkit/include
USD_LIB_DIR=/Applications/Houdini/Houdini21.0.631/Frameworks/Houdini.framework/Versions/21.0/Libraries
USD_LIB_PREFIX=pxr_
USD_PYTHON_INCLUDE_DIR=/Applications/Houdini/Houdini21.0.631/Frameworks/Houdini.framework/Versions/21.0/Resources/toolkit/include/python3.11
USD_LINK_PYTHON=framework
USD_PYTHON_FRAMEWORK_DIR=/Applications/Houdini/Houdini21.0.631/Frameworks
For a vanilla build_usd.py install you can usually get away with USD_INSTALL_DIR pointing at the install root, leaving the prefix empty, and skipping the Python framework variables.
The Python variables are not optional even if your code never touches Python. USD's headers transitively include Python.h through tf/pyLock.h, and template instantiations pull pxr_boost::python converters into your object files. Rather than fight this we link pxr_python and pxr_boost and feed the build a CPython include directory. On macOS we also embed an rpath that points inside Python.framework, because Houdini's libpxr_python.dylib install name is the bare @rpath/Python rather than the framework style path.
Once the variables are set, cargo build --examples should build everything. Each example writes its output next to the input asset, so cargo run --example shade_demo from the rust-usd crate root produces examples/paint_edits_shade.usda that you can open in usdview or any USD aware renderer.
hydra-rs
The Hydra crate sits in hydra-rs/ as a workspace member. Its hydra_inspect example opens a stage, enumerates render delegate plugins, and walks the prim paths that Hydra's scene index actually exposes. On the test machine that prints HdStormRendererPlugin and six prim paths for a stage that has eight authored prims, because Hydra's scene index correctly hides shaders inside materials.
render_to_rgba is the next step. It opens a stage, constructs UsdImagingGLEngine, configures a free camera and a color AOV, runs a convergence loop, and reads the render buffer back as RGBA8. On macOS without an active Metal or GL context the Storm delegate segfaults inside the render task. The example is therefore gated behind HYDRA_RENDER_ENABLE=1. Until that is sorted out the Hydra crate is useful for ingestion and inspection but not yet for production rendering. Wiring up Hgi::CreatePlatformDefaultHgi together with an offscreen Metal texture is the obvious next move.
What this repo also is
A written record of the unobvious things you trip over when you bind USD from another language. A short list, with apologies for the density.
USD's AR_DEFINE_RESOLVER macro emits unqualified TfType and friends, so you have to call it from a scope that has issued PXR_NAMESPACE_USING_DIRECTIVE. USD 25 also refuses to instantiate a registered ArResolver derived TfType unless a plugInfo.json claims ownership, even when the type is registered through static initialization. The fix in this crate is to write the json next to the running executable and call PlugRegistry::RegisterPlugins lazily on first stage open, with LibraryPath pointing at current_exe(). On macOS that works because dlopen of an already loaded Mach O image is a no op and the type is already in the registry.
cxx's self: &T becomes const T& on the C++ side. Several pxr handle types like UsdVariantSet and UsdShadeShader have non const mutating methods that author opinions on the underlying layer rather than mutating the wrapper. You can call them from a const Rust method by declaring the wrapped pxr handle mutable. A few pxr handles also have private default constructors, which means std::make_unique<Wrapper>() does not compile. Give the wrapper an explicit Wrapper(Handle) constructor and call std::make_unique<Wrapper>(std::move(handle)) instead.
Status
rust-usd is at 0.0.1 and covers Tiers 1, 2, and 3 of the painter spec end to end. hydra-rs is at 0.0.1 and covers Tier 4 plumbing, with the actual render path stubbed out. Both crates have publish = false in their Cargo.toml. Flip that and run cargo publish when you are ready.