AYON Usd Resolver
1.0.0
|
INFO Currently, we only support specific set of DCCs and their versions, and AyonUsd for building revolvers (other software packages and stand-alone setups will follow).
Welcome to the Developer Docs. This document will be split into 2 portions.
1: the Resolver Developer part. Lets take a look at what tools and library's we use and how we use them.
2: documentation for AYON developers that want to use the resolver but don't want to work on the source code. it will outline all the things the resolver offers and how you can control them.
We utilize the ayon automator to initiate our underlying CMake setup. Although you can manually set environment variables and trigger CMake, using the automator streamlines this process and enhances compatibility with CI/CD pipelines.
Getting Started Before commencing with the automator, ensure that its virtual environment (venv) and output folder are set up. Use the --setup
flag in the CLI along with python Project.py
:
You can run Project.py
directly using Python or use the --help
flag to access detailed information about the script, including available stages.
Available Stages Here are some key stages you can employ via the --runStageGRP
flag:
--execSingleStage
): This function enables building a range or selected resolver during development. To select a resolver, use the --Target
flag alongside the target name from your config.yaml
file.Setting Build Configuration You can set build configuration via CLI arguments as JSON or using a build config file. To specify the build config file, employ this function:
Though not mandatory to set these variables in each run, they will be stored persistently unless you rerun the --setup
command.
Example: Running Generate Release Here's an example of how to execute the Generate Release
stage:
config.yaml Format The build_conf.yaml
file defines build targets on your machine and specifies necessary paths. The internal configuration will be read and validated to ensure compliance with standards:
The --Target
flag triggers on RUN_NAME
, converting variables beneath it into environment variables within subprocesses to avoid modifying your environment directly.
COMPILEPLUGIN
= Set this variable to the relative path of the desired build plugin, found within the BuildPlugins
folder in the repository root. For example, if using HouLinux/LinuxPy310Houdini20
.
The USD Resolver currently does not employ Red-Green development. However, post-alpha release, we plan to integrate Ayon Automator.
Issue Tracking We maintain all our work in GitHub (GH) issues and create branches from these issues. Here are the three types of issue options:
Choose your Issue Type Depending on the scale of work, you can pick the issue type that best fits. However, for substantial features with high complexity, it's crucial to create a Proposal. This ensures thoughtful debate around technical implementation and allows us to revisit older proposals for context.
Build Plugins Naming schema is as follows: {AppName}{PlatfromName}/{AppName}{AppVersion}_Py{pythonVersion}_{PlatfromName}.cmake
PlatformName options = {Win, Linux, Mac, specific Os Name}
On USD Init:
When a USD file is opened:
When a USD AssetIdentifier is found.
_Resolve()
gets called with the data between the '@' symbols._Resolve()
checks if the path is an AYON URI path.getAsset()
function in the resolverContextCache.The AssetIdentifier or AssetPath converts an AYON path to a disk path for the resolver:
ayon:
signifies an AYON asset (detected via string view comparison).//{ProjectName}/{path/to/ayon/folder}?product={FileName}
defines the desired Ayon folder.latest
: Uses latest version available.hero
: Searches for pinned hero version, if configured.v001
): Uses specified product version.The complete asset path format is: ayon://{ProjectName}/{path/to/ayon/folder}?product={FileName}&version=latest&representation=usd
CPP files may contain
TF_DEBUG().Msg();
and one of the enum values (AYONUSDRESOLVER_RESOLVER
,AYONUSDRESOLVER_RESOLVER_CONTEXT
). These control debug message output. Keep these in your environment variables for flexibility.
First of all, if you setup the resolver via the AyonUsd addon usd will automatically use it as the default resolver meaning every time you call a resolver AyonUsdResolver will be used.
But you have more fine grained control if you want to:
note When you get a resolver via
Usd.Ar
API you will need to get an explicit context to edit the global context asAr.GetResolver
will return a higher order class and notAyonUsdResolver
class.
If you want fine control over the resolver you will be able to get the connected context via GetConnectedContext
tip Dropping cache entries Using the resolver.GetConnectedContext()
is also the recommended way to access the dropCache
function for the resolver.
To access the Python bindings for the AyonUsdResolver:
Ar.SetPreferredResolver("AyonUsdResolver")
this command allows you to set a preferred Resolver. If you use the AyonUsd addon you wont need to set this line as we register the resolver as the main resolver. But if you have a different resolver set as Main you might need to use this command.
resolver = Ar.GetResolver()
there are multiple ways to get access to a resolver instance but using the "Default" Usd option is usually the best idea as it will return the resolver for the current context.
context = AyonUsdResolver.ResolverContext()
accessing an ResolverContext instance is useful if you want to manipulate the Global resolver cache.
the AyonUsdResolver has a feature called Pinning Support.
In short pinning support allows you to load a pinning file and disconnect the AyonCppApi.
In the implementation this boils down to a static Memory cache that bypasses the resolver Logic.
note Why use pinning? When running a resolver on a farm with many workers (render nodes) you might not want them all to call the Ayon server to avoid impacting the server performance. This is because USD Resolvers will resolve paths one by one, potentially resulting in many calls.
How to use it ?
There are 3 Env variables that control the Pinning file support
ENABLE_STATIC_GLOBAL_CACHE
Enables or Disables static Cache creation. This effectively allows you to enable or disable Pinning file support.
as you might want to have a pinning file in your env vars but for e.g debugging you don't want to activate the feature.
PINNING_FILE_PATH
This is a path to the pinning file.
PROJECT_ROOTS
When running the resolver against the AYON server the CppApi will query the Get Project Site Roots
endpoint and get a Dict[str,str]
of {root[RootOverwriteKey]}=Val overwrites.
when running with a pinning file you will need to set this Dict[str,str] as an ENV variable. e.g:{Key}:{Path},{Key}:{Path}
it's not a problem to have duplicates in the keys but the Cache stores the data as an Unordered_Map so it will end up deduplicating the Keys. But you can't have spaces in the list as they are not removed and will be interpreted as part of the Key or Value.
example
setup the resolver for pinning support. we empty all the AYON c++ api keys just for example you can simply not set them.
PS: its interesting to know that when you generate a pinning file via the AYON-USD addon the json file will have a key named
ayon_pinning_data_entry_scene
.
This should always be the path used to open the stage Otherwise the pinning file might not have the correct AssetIdentifier stored.
aka: if this key points to a local path and you use an URI that points to the local path the resolver wont be able to resolve.
context = AyonUsdResolver.ResolverContext()
there are multiple ways to control the cache of a resolver. but if your resolver uses the global cache you can simply create a new ResolverContext and access the cache control functions to
affect the global cache.
This does not work if you disconnected the Global cache from your resolver.
context.deleteFromCache(AssetIdentifier)
delete an individual cached entry. context.clearCache()
clear the connected cache.
note It is important to understand that by default a Resolver will be connected to the global cache and this call will delete all entries in the global cache not just the ones that where added by this resolver.
context.dropCache()
allows you do disconnect from the current cache object and initialize a new one. This can be useful if you want to disconnect from the global cache and have a Resolver local cache instead.
explicit_resolver = AyonUsdResolver.Resolver()
if you need to create an explicit resolver because you want to e.g pass a specific instance into a stage or you want to disconnect from the Global Cache you should access the Context
connected to this specific resolver.
explicit_resolver_context = explicit_resolver.GetConnectedContext()
all the other functions stay the same.
Examples
Deleting cached entry's
Disconnecting from the global cache