Modifiying the Resolver context of a Given stage at runtime

Hello USD Users,

I’m currently working on a USD resolver that implements a custom context, and i would like to call a function on the context to modify the reselution at runtime.

Overview

Our context supports thinks like URIs, startup pinning, and now we want to introduce runtime redirection. The idea is to let departments like lighting load a redirection file at runtime, which dynamically load whatever the redirection specifies instead of what the sceene defined.

Problem

If a stage is created from scratch (e.g., Usd.Stage.CreateNew), there’s no redirection file initially tied to it. We want to:

  1. Get the resolver context from the stage.
  2. Modify the context to include a redirection file.
  3. Reload the stage so that the redirection rules take effect.

However, I haven’t been able to find a way to get a resolver context that is subsequently used in further resolution.

Here’s an example of what I’ve tried:

# Create a stage
stage = Usd.Stage.CreateNew(usd_path)

# Get the resolver
res = Ar.GetResolver()

# Get the resolver context from the stage
ctx = stage.GetPathResolverContext().Get()[0]

# Add the redirection file to the context
ctx.setRedirectionFile(str(rdf_path))

# Modify the redirection file
rdf = ctx.getRedirectionFile()
rdf.addRedirection("missingRef.usda", "./sphere.usda")

# Define a prim that references data in the redirection file
# This reference should resolve based on the updated context
prim = stage.DefinePrim("/test", "Xform")
prim.GetReferences().AddReference("missingRef.usda")

Issue

When running the above code:

  • The resolver context obtained from the stage doesn’t seem to affect resolution when modified.
    • i assume that im getting a copy or simmilar and not the context for the stage.
    • i know that GetPathResolverContext is defined for consumers to resolve the same way as the stage so i guess this wont help.
    • i also read that context can be thread dependend so modifiying for “the stage” sounds a bit imposible ?

Questions

  1. How can I modify the resolver context for a newly created stage (not loaded from disk) and ensure it’s used in further resolution?
  2. Is there a standard way to reload or recompute a stage’s composition to reflect changes in the context or redirection file? (maybe via AR::Notice on the cpp side?)
  3. are there problems known with eg houdini and the multi node system they use regarding context changes ?

Any insights, suggestions, or best practices would be greatly appreciated. Thank you in advance!

1 Like

You can try using Ar.ResolverContextBinder to bind your resolver context, i.e.,

with Ar.ResolverContextBinder(ctx):
    prim = stage.DefinePrim("/test", "Xform")
    prim.GetReferences().AddReference("missingRef.usda")

That would technically just override the context - temporarily, no? It wouldn’t give say access to the Resolver Context that Houdini itself initialized, etc?

Anyway, I believe @Root42 ended up investigating a different route by attaching a UUID to each resolved context and through that find the relevant redirection instance. Not sure if that makes any sense at all.

Seems like something others must have handled in both Maya, Houdini, etc. before.

I don’t believe this is possible. Houdini always creates a new stage when you ask to change the asset resolver context.

Sorry, I don’t have time right now for a fuller answer, but I do want to clarify @mtucker 's statement; at the USD level, it is possible to update the Context held by a Stage (which is the context it will always use, regardless of what context you have bound in your program). You can do this by mutating the state held by the stage’s Context (while the stage is safe to write to, i.e. no readers active), and then calling ArResolver::RefreshContext(). You might then also need to call Reload() on the Stage (we wanted to make that automatic, but I’m not sure if we’ve gotten there, yet).

You could create an RAII pattern around this. However, whether this is feasible to do in any given DCC is another question.