/*! \page Page_Hydra_Getting_Started_Guide Hydra 2.0 Getting Started Guide \section Hydra_Getting_Started_What_Is_Hydra What is Hydra 2.0 The Hydra imaging system is based on two core abstractions: a scene abstraction and transformation pipeline, and a renderer abstraction and execution pipeline. Its design goal is to decouple scene processing from rendering, and both from the application, enabling each scene, renderer, or application integration to benefit from other integrations in the ecosystem. Hydra 2.0's abstractions utilize two central concepts: the **scene index** which provides a view of a scene and the **scene index observer** which takes a scene index as input and is informed about scene changes. A **filtering scene index** (or **scene index filter** or **filter** for short) takes an input scene and provides a transformed view of that scene. It is (or has) thus both a scene index observer and a scene index. A **scene index plugin** bundles one or more filtering scene indices together, and enables runtime discovery and usage of these filters by applications and renderers. \section Hydra_Getting_Started_How_Does_Hydra_Compare_To_legacy How does Hydra 2.0 compare to Legacy Hydra 1.0? Hydra 2.0 replaces the following legacy Hydra 1.0 classes with scene indices and scene index observers and components built around the scene index API: - HdSceneDelegate is replaced by one or more scene indices. For example: - UsdImagingDelegate is replaced by a chain of scene indices created with UsdImagingCreateSceneIndices which starts with the UsdImagingStageSceneIndex. Each scene index that follows it is a filtering scene index (that observes the previous scene index). - HdxTaskController (which houses a scene delegate for the free camera) is replaced by HdxTaskControllerSceneIndex. - HdRenderIndex is replaced by the scene index graph, which is a chain of application-specific and renderer-specific filtering scene indices. It is created by the application using the HdSceneIndexPluginRegistry. - HdRenderDelegate is replaced by the HdRenderer which is (or has) a scene index observer. Note that the transition from Hydra 1.0 to 2.0 has been happening in several stages: - The emulation between Hydra 1.0 to 2.0 and back to 1.0 was implemented within the HdRenderIndex itself. This allowed applications to benefit from some of the new Hydra 2.0 features while using the Hydra 1.0 API itself. It also allowed the switch away from the UsdImagingDelegate. This can be disabled by setting the now deprecated \c HD_ENABLE_SCENE_INDEX_EMULATION to \c false. \image html legacy_scene_delegate_emulation.png - The switch from the HdxTaskController to the HdxTaskControllerSceneIndex. - The switch from UsdImagingDelegate to the usd imaging scene indices. This can be disabled by setting \c USDIMAGINGGL_ENGINE_ENABLE_SCENE_INDEX to \c false. - Applications (such as UsdImagingGLEngine) switch to the Hydra 2.0 API but still need to use some legacy API (through HdLegacyRenderControlInterface). This is shown in more detail in \ref Hydra_Getting_Started_Application. An application can still use a renderer implemented by an Hydra 1.0 render delegate since it is automatically wrapped in an HdRenderDelegateAdapterRenderer. An application can still use Hydra 1.0 scene delegates by instantiating the HdRenderIndexAdapterSceneIndex. This can be disabled by setting \c USDIMAGINGGL_ENGINE_ENABLE_SCENE_INDEX_OBSERVERER_RENDERER to \c false. - **The future:** Applications fully switch to a pure Hydra 2.0 API. This requires new API on the HdRenderer for: - Render settings. The HdRenderer will have API to query renderer-specific render settings (such as volume ray-marching size in Storm). The choices for these render settings are communicated in band. That is, by a Hydra prim in a scene index that is either originating from, say, a USD render settings prim or viewer settings in the application. - AOVs and tasks. - Renderer capabilities influencing the scene indices. This is useful for scene indices that use execution and, thus, cannot use lazy evaluation and need to cache all needed data in advance, for example. If a renderer does not support motion blur, such a scene index does not need to cache samples. If such a renderer does not support a particular type of material network (currently communicated through `HdLegacyRenderControlInterface::GetMaterialRenderContexts`), exec does not need to evaluate these networks. \section Hydra_Getting_Started_Scene_Index_API The Scene Index API A scene in the new API is represented by a subclass of the HdSceneIndexBase interface. \snippet examples_hydra_getting_started.cpp HdSceneIndexBaseExcerpt A scene index is responsible for: 1. Sending notifications to the renderer or other listeners on population, invalidation, depopulation, etc. 2. Providing prim data by request. 3. Providing scene topology data by request, so callers can walk the scene. \image html scene_index_1.png The \ref stageSceneIndex.h "USD scene index", for example, implements a Populate() call by traversing the scene and generating a PrimsAdded notification. It implements change notification in terms of PrimsDirtied. It implements \ref HdSceneIndexBase::GetChildPrimPaths() "GetChildPrimPaths()" by querying the USD prim hierarchy. Finally, it implements \ref HdSceneIndexBase::GetPrim "GetPrim()" by returning the appropriate data for the prim in question (transform, geometric data, etc. as appropriate). Consumers (such as renderers, the Hydra Scene Debugger, etc) that want to receive notifications from a scene index can subclass the HdSceneIndexObserver interface. \snippet examples_hydra_getting_started.cpp HdSceneIndexObserverExcerpt PrimsAdded takes individual prim (path, type) tuples. A PrimsAdded notice can be sent for a prim already in the scene, in which case it should be interpreted as a resync; if the notice has a new type, the prim type should be updated, and all prim data should be considered dirty (as if there were a PrimsDirtied message invalidating the root locator). \note Comparison to Hydra 1.0: PrimsAdded conceptually maps to the HdRenderIndex Insert(R,S,B)prim() calls. PrimsRemoved takes a subtree path, rather than a prim path. Sparse removals can be accomplished by resyncing prims to the empty type. \note Comparison to Hydra 1.0: PrimsRemoved conceptually maps to the HdRenderIndex Remove(R,S,B)prim() calls. PrimsRenamed offers a way to rename a subtree, updating all prims under the old subtree to have paths with the old subtree prefix swapped for the new one. This is semantically equivalent to removing the old subtree and adding it in the new location, but provided as a separate notice for optimization purposes since frequently a rename can be handled by updating map keys at much less cost. \note Comparison to Hydra 1.0: Note that the legacy HdRenderIndex does not have any concept of renaming. PrimsDirtied takes an individual prim path, and a set of locators to datasources. Datasources are the attribute model in the scene index API, and are grouped into a multi-level hierarchy; the locator is a path into that hierarchy. A dirty locator on a prim means that attribute and all child attributes are invalidated. Any caches containing a datasource handle for that attribute or any child attributes need to be cleared and re-fetched. \note Comparison to Hydra 1.0: PrimsDirtied conceptually maps to the HdChangeTracker Mark(R,S,B)primDirty() calls. An important invariant of the system is that the list of prim paths produced by evaluating PrimsAdded and PrimsRemoved messages should match the list of prim paths generated by traversing the scene from the root, using GetChildPrimPaths(). Any prims not reachable by traversal should return an empty prim, with an empty type and a null root datasource. \image html scene_index_2.png \subsection Hydra_Getting_Started_Prim_Data Prim Data Prim data is represented by subclasses of HdDataSourceBase or its specializations: HdContainerDataSource, HdVectorDataSource, or HdSampledDataSource. \snippet examples_hydra_getting_started.cpp HdDataSourceBaseSpecializationsExcerpt The basic value datatype of this API is HdSampledDataSource, whose GetValue API retrieves or computes type-erased (i.e. VtValue) data on demand, as with the scene delegate. For attributes with a known type, the subclass \ref HdTypedSampledDataSource "HdTypedSampledDataSource" can be used. Note that, unlike with the scene delegate, all data access is relative to a shutter offset instead of being part of a separate API. For a consumer computing the value of a sampled datasource over a time interval (such as a renderer implementing motion blur), \ref HdSampledDataSource::GetContributingSampleTimesForInterval "GetContributingSampleTimesForInterval()" is responsible for providing a set of notable sample times to reconstruct the signal. For cached data, this can return the times where samples are defined, or for analytical motion blur this can return time samples corresponding to a reasonable linearization. If these time samples are used to populate an HdTimeSampleArray, Hydra can linearly re-sample the signal at arbitrary points as required by a renderer. If \ref HdSampledDataSource::GetContributingSampleTimesForInterval "GetContributingSampleTimesForInterval()" returns false, this indicates an attribute that's constant over the shutter window, and the caller should just use \ref HdSampledDataSource::GetValue "GetValue(0)". The intent of this API is for consumers to call GetValue() on either shutter offsets returned by GetContributingSampleTimesForInterval(), or with shutterOffset equal to 0. Defensive code can interpolate or extrapolate other values of shutterOffset, but behavior might be undefined. Container datasources and vector datasources are both aggregates, and can be used to build up nested structured data. A mesh prim might be represented by a container with a child named "mesh", containing topology and pipeline state, another named "primvars", and others as well, such as transform, visibility, etc. \image html nested_datasources.png Here, the light diamonds represent containers and the dark diamonds represent values. Note that containers can have children that are also containers. The container datasource API introduces \ref HdContainerDataSource::GetNames "GetNames()" as a way for downstream code to enumerate which attributes are available. The use of container datasources instead of structs allows for flexibility of representation of similar concepts (e.g. a mesh, a mesh topology) between different renderers which might want to overlay different data on top of the standard points/index buffers. Named children of a container are retrieved with \ref HdContainerDataSource::Get "Get()" calls. It's expected that `Get()` will return something for all of the names defined by `GetNames()`, and will return null otherwise (but be safe to call). This is useful, for example, if a consumer only wants to check for certain named primvars on a geometry prim, since primvar enumeration at the USD level can sometimes be expensive but it's also lazily deferred to the `GetNames()` call. HdDataSourceLocator is the attribute addressing scheme used in \ref HdSceneIndexObserver::DirtiedPrimEntries "DirtiedPrimEntries". Since container datasources can be nested, the locator needs path semantics, where each path entry represents the next container key to query to ultimately end up at the correct datasource. A locator is relative to a root container, which is usually the top-level container datasource representing prim data. \snippet examples_hydra_getting_started.cpp HdDataSourceLocatorExcerpt For example, you might expect mesh orientation at: `HdDataSourceLocator("mesh", "meshTopology", "orientation");` Locators can identify individual attributes to invalidate, which allows for much more specificity than the HdDirtyBits API. An originating scene can invalidate `primvars/displayColor` and `primvars/displayOpacity` separately. However, to capture some of the conciseness of dirty bits, Hydra will interpret the locators in a DirtiedPrimEntry hierarchically, meaning if `primvars` is dirty on a prim, this implies that `primvars/displayColor` and `primvars/displayOpacity` are also dirty. \subsection Hydra_Getting_Started_Schemas Hydra Schemas Datasource aggregations are inherently unstructured, but to transport data from different scenes to different renderers Hydra needs a consensus data format. Rather than encode this format in C++ structs, the scene index API takes a page from USD by separating data storage from schema interpretation. An HdSchema subclass is applied to an HdContainerDataSource and represents what data Hydra expects to find on a container. Any scene index or render delegate that wants to be compatible with the Hydra ecosystem should provide or consume data accordingly. For example, HdMeshTopologySchema corresponds to the HdMeshTopology C++ struct: \snippet examples_hydra_getting_started.cpp HdMeshTopologySchemaExcerpt Importantly, since the data storage is a container data source, it can transport data not in the schema. If a renderer wants to extend Hydra schemas for renderer-specific data, it can do so, in the above example by sub-classing HdMeshTopologySchema. The schema is just a facade representing the commonly understood structure of a Hydra scene, and all data access is still done through the input container. \image html hdschema.png See \ref Page_Hydra_Prim_Schemas for a list of Hydra prim schemas. \subsection Hydra_Getting_Started_Filters Filtering Scene Indices One last important API concept arises from the architecture above. It's fairly straightforward to implement a scene index by referring to an input scene index for data access, but then selectively overriding the input scene data. This can be thought of as the lazy programming version of running a transformation on the scene at load time. We call such a scene index a **filtering scene index** (or **scene index filter** or just **filter** for short) and provide a base class for this behavior in HdSingleInputFilteringSceneIndexBase. \snippet examples_hydra_getting_started.cpp HdSingleInputFilteringSceneIndexBaseExcerpt This class will register itself as an observer of `inputSceneIndex` and registers handlers for `PrimsAdded()`, etc. notices. Note that it's expected to forward these notices appropriately to its own observers. `GetPrim()` can be implemented with the help of `_GetInputSceneIndex()->GetPrim()`. \image html scene_index_filter.png These scene index filters are a very powerful architectural tool for decoupling different kinds of scene transformations in a scene or renderer pipeline. See \ref Hydra_Getting_Started_App_With_Filters for additional illustrative examples of scene index filters. Hydra provides a way to visualize scene data and filters using the \ref Page_Hydra_Scene_Debugger, available in tools like usdview. You can also add this to your Hydra-enabled application. \section Hydra_Getting_Started_Scene_Data Transporting Scene Data with Scene Indexes As a simple example, let's write a scene index that provides a scene with a single quad. \snippet examples_hydra_getting_started.cpp QuadSceneIndex_Example Multiple scenes can be composed together at the prim and attribute level through the HdMergingSceneIndex. That is, a single prim can have attribute data from multiple input scenes. You can insert this scene into your application by adding it to the application's merging scene index, see \ref Hydra_Getting_Started_Application. \note Comparison to emulation in the legacy render index: For applications not yet managing their own merging scene index, you can insert this scene (as a unit) from a render index by calling HdRenderIndex::InsertSceneIndex, and remove the scene using HdRenderIndex::RemoveSceneIndex. Under the hood, HdRenderIndex::InsertSceneIndex works by using a filtering scene index to re-root the scene, and passes the re-rooted scene to HdMergingSceneIndex. This last scene index takes multiple input scenes and composes them at a prim and attribute level, meaning a single prim can have attribute data from multiple input scenes. Note also that, unlike with scene delegates, a single scene index can be inserted into multiple render indexes without any issues. \note The `scenePathPrefix` is the same as the scene delegate ID concept: if your app-native scene has an embedded USD scene at `/Path/to/USD`, for example, you can set `scenePathPrefix = "/Path/to/USD"` to re-root the USD data at the new prefix. A more sophisticated scene data implementation with the scene index API would be expected to implement \ref HdSceneIndexBase::GetChildPrimPaths() "GetChildPrimPaths()" in terms of native scene traversal, and implement \ref HdSceneIndexBase::GetPrim "GetPrim()" by conforming native scene data to the Hydra prim schemas as necessary. We've found it very helpful to write an originating scene index that's as simple as possible, and represent complicated scene transformations with filters. As an example of this, UsdImagingStageSceneIndex tries to only handle prim traversal, type lookup, and attribute access. Various scene index filters overlay application state or implement complicated features like instancing resolution: - UsdImagingPiPrototypePropagatingSceneIndex: handles point instancer population rules and relationship fix-up. - UsdImagingNiPrototypePropagatingSceneIndex: handles USD instanceable reference aggregation. - UsdImagingDrawModeSceneIndex: handles model:drawMode substitutions, where a subtree of the scene is replaced by standin geometry. - UsdImagingSelectionSceneIndex: overlays per-prim selection state from the application onto scene data. - UsdImagingRootOverridesSceneIndex: overlays a root transform/visibility opinion from the application onto scene data. The flow for UsdImagingStageSceneIndex with these filters looks roughly like this, as of November 2023 (HdRenderIndex is now the application's HdMergingSceneIndex): \image html usdimagingstagesceneindex_filters.png The UsdImaging library provides the method UsdImagingCreateSceneIndices to create a UsdImagingStageSceneIndex and all of its associated filters, and this is the recommended way to create a UsdImagingStageSceneIndex with the correct resolution steps across different USD releases. \section Hydra_Getting_Started_App_With_Filters Working With Filtering Scene Indices For a basic syntactical look at how scene index filters work, the following simple but illustrative examples can be used. A filter that filters out all cubes from the scene: \snippet examples_hydra_getting_started.cpp UnboxingSceneIndexFilter A filter that sets the display color for everything to be green: \snippet examples_hydra_getting_started.cpp GreeningSceneIndexFilter Note here the use of two utility classes: \ref containerDataSourceEditor.h "HdContainerDataSourceEditor" and HdOverlayContainerDataSource. These are both useful for doing datasource-level composition, and can recursively merge and combine their inputs (lazily!) as needed. A measure of caution is required for conditional overrides; due to the PrimsDirtied semantics, if GreeningSceneIndexFilter only overlays data on top of prim.dataSource when _enabled is true, then when the value of _enabled changes GreeningSceneIndexFilter will need to send a dirty message with the root locator, rather than "primvars/displayColor", since the root datasource has changed and we need to notify any listeners (e.g. the flattening scene index) to discard cached copies. A more efficient way to do a conditional override is to unconditionally override the prim datasource, but conditionally override the target datasource, so that only the target datasource needs to be marked dirty. Another noteworthy utility class is HdSceneIndexPrimView: \snippet examples_hydra_getting_started.cpp HdSceneIndexPrimViewExample For an example of more sophisticated filtering scene indices, there are some core architectural examples in `pxr/imaging/hd`: - \ref dependencyForwardingSceneIndex.h "HdDependencyForwardingSceneIndex": allows originating scenes, as well as renderers and other filters, to add data dependencies via the HdDependenciesSchema. This filter will use those dependencies to propagate PrimsDirtied calls. This is especially helpful for managing invalidation across relationships. For an example use case, Storm uses a scene index filter that adds dependencies to meshes from their bound material, so that when the material changes the mesh can re-tessellate. We then run the dependency forwarding scene index to forward those invalidations. - HdFlatteningSceneIndex: does top-down attribute flattening. For example, transform concatenation, inherited attribute resolution, etc. - HdMergingSceneIndex: merges multiple input scenes into a single output scene. - \ref noticeBatchingSceneIndex.h "HdNoticeBatchingSceneIndex": captures, holds, and merges scene index notifications on demand. - HdPrefixingSceneIndex: re-roots the input scene at a new location. There are also a number of common feature-based scene index filters in `pxr/imaging/hdsi`: - HdsiImplicitSurfaceSceneIndex: can be configured to replace spheres, cubes, cylinders, capsules, and cones with tessellated meshes. - HdSiExtComputationPrimvarPruningSceneIndex: runs Hydra external primvar computations and adds the results to the scene as normal primvars. This ensures downstream render delegates or scene indices don't need to be ExtComputation aware. - HdsiPinnedCurveExpandingSceneIndex: turns pinned Catmull-Rom curves into unpinned Catmull-Rom curves, for renderers that don't support the pinned format. These filtering scene indices can be inserted into the Hydra pipeline in different ways based on whether they are scenegraph-specific, renderer-specific, or application-specific. A typical Hydra pipeline has an HdMergingSceneIndex created by the application. This merging scene index also serves as demarcation line between these different filtering scene indices. Scenegraph-specific Scene Index Filters Filters that are associated with a specific originating scene graph (like UsdImaging filters that implement USD semantics) can be appended to the originating scene index (e.g. UsdImagingStageSceneIndex) before they are inserted into the HdMergingSceneIndex. As mentioned earlier, UsdImagingCreateSceneIndices can be used to create a UsdImagingStageSceneIndex and all of its associated filters. \remark The render index maintains its own merging scene index and HdRenderIndex::InsertSceneIndex can be used to add a scene index to it. Renderer-specific Scene Index Filters A renderer can define a subclass of HdSceneIndexPlugin, either compiled in the renderer or in an unrelated library. A Hydra application (such as UsdImagingGLEngine) uses the HdSceneIndexPluginRegistry to insert these between the HdMergingSceneIndex and HdRenderer. The order is defined by the scene index plugins through the HdSceneIndexPluginRegistry::InsertionPhase passed to HdSceneIndexPluginRegistry::RegisterSceneIndexForRenderer. \remark The render index automatically inserted these plugin scene indices between its internal merging scene index and the render delegate. The following example shows a simple scene index filter plugin: \snippet examples_hydra_getting_started.cpp RendererSceneIndexFilterPlugin The following `plugInfo.json` would be used for this example plugin: \code{.unparsed} { "Plugins": [ { "Info": { "Types": { "MyFilterPlugin" : { "bases": ["HdSceneIndexPlugin"], "loadWithRenderer": "GL", "priority": 0, "displayName": "My awesome filter scene index" } } }, "LibraryPath": "@PLUG_INFO_LIBRARY_PATH@", "Name": "myfilter", "ResourcePath": "@PLUG_INFO_RESOURCE_PATH@", "Root": "@PLUG_INFO_ROOT@", "Type": "library" } ] } \endcode Application-specific Scene Index Filters Application-specific transformations can be added at runtime to the same pool used for renderer-specific transformations. This is especially useful for pipeline tools, which might want to segment the scene in ways that aren't appropriate for other applications. The following example demonstrates how an app might register an application-specific scene index filter at startup: \snippet examples_hydra_getting_started.cpp AppSceneIndexFilter It's important to note that the application and renderer-specific scene index filters can be used even if all of the scene data is coming from a scene delegate. Hydra converts internally between the two representations as needed. See \ref Hydra_Getting_Started_Appendix_Scene_Index_Emulation for details. The following shows renderer-specific and application-specific filters participating in a scene index filtering workflow (for a Hydra 2.0 application, HdRenderIndex is the application's HdMergingSceneIndex and HdRenderDelegate is an HdRenderer): \image html app_renderer_filters.png The current priority sort algorithm is to run application-specific filters first (in numerical priority order), and then renderer-specific filters (again in numerical priority order). \section Hydra_Getting_Started_Scene_Index_Bindings USD Scene Index Bindings UsdImagingStageSceneIndex walks a USD stage and dispatches to plugin-based **prim adapters** that know how to turn a certain USD prim type or API schema into a Hydra prim. The following is example code for an adapter for a "MyUSDPrim" USD prim and "MyUSDAPI" USD schema. plugInfo.json for MyUSD library: \code{.unparsed} { "Types": { "MyUSDPrimAdapter" : { "bases": ["UsdImagingPrimAdapter"], "primTypeName": "MyUSDPrim" }, "MyUSDAPIAdapter" : { "bases": ["UsdImagingAPISchemaAdapter"], "apiSchemaName": "MyUSDAPI" } } } \endcode MyUSDPrimAdapter.cpp example: \snippet examples_hydra_getting_started.cpp MyUSDPrimAdapter MyUSDAPIAdapter.cpp example: \snippet examples_hydra_getting_started.cpp MyUSDAPIAdapter USD has a concept of multiple-apply API schemas, where the same API schema can be applied to a prim multiple times with different instance names. An example of this is coordinate systems, where applying UsdShadeCoordSysAPI with instance name "foo" adds a "coordsys:foo:binding" relationship to the prim. In these cases, UsdImagingStageSceneIndex will call into the API schema adapter multiple times, one per instance name. Some API schemas (which aren't multiple-apply) won't have an instance name -- in these cases, the instance name will be the empty token. Other than the instance name, the API schema adapter API follows the prim API. Any USD prim will have a base type and an ordered (possibly empty) list of applied API schemas. USD composes attribute definitions on that prim by looking at the base type definition, and then subsequently looking at the API schema definitions in order. This is the process used to determine attribute fallback values, for example. UsdImagingStageSceneIndex matches this by using an HdOverlayContainerDataSource to compose prim data from the base type adapter, and then from each API schema adapter in order. Composition is performed separately for each subprim. \image html scene_index_adapters.png Adapters should route their value-level scene access through the \ref dataSourceAttribute.h "UsdImagingDataSourceAttribute" and UsdImagingDataSourceRelationship classes, which handle efficiently retrieving attribute data as well as marking time-variability in the `stageGlobals` object. \subsection Hydra_Getting_Started_Legacy_Delegate Comparison to the UsdImagingDelegate The UsdImagingPrimAdapter is used by both the UsdImagingStageSceneIndex and the legacy UsdImagingDelegate. The API on UsdImagingPrimAdapter used by each, however, is disjoint. The UsdImagingStageSceneIndex also differs from the UsdImagingDelegate as follows: - It supports adapters for USD API schemas. - Adapters no longer get the wide UsdImagingDelegate::Populate API, but a single USD prim can be expanded into multiple Hydra prims by returning a list of subprim names. Each of these can have a unique prim type and a datasource providing prim data. \section Hydra_Getting_Started_Application A Hydra 2.0 Application The following diagram shows a typical chain of scene indices for an application rendering an image. The chain terminates with an HdRenderer. You can use the \ref Page_Hydra_Scene_Debugger "Hydra Scene Debugger" to explore the scene index chain in detail. \image html hydra_app.drawio.svg width=90% An application can use legacy Hydra 1.0 scene delegates through the HdRenderIndexAdapterSceneIndex. The USD imaging scene index chain is created through UsdImagingCreateSceneIndices. The HdMergingSceneIndex serves as demarcation line between the scenegraph-specific scene indices and the renderer- and application-specific filtering scene indices. The renderer and application plugin scene indices are instantiated through the HdSceneIndexPluginRegistry. The application might also add a caching scene index. We call the scene index that is last in the chain and feeding into the HdRenderer the terminal scene index. The HdRenderer is created through the HdRendererPluginRegistry and HdRendererPlugin. By default, HdRendererPlugin::CreateRenderer creates a Hydra 1.0 legacy HdRenderDelegate and wraps it in an HdRenderDelegateAdapterRenderer. However, as the diagram shows, renderers can override HdRendererPlugin::_CreateRenderer for a pure Hydra 2.0 implementation. \section Hydra_Getting_Started_Renderer Implementing a Renderer A Hydra 2.0-native HdRenderer implementation can use: - The HdsiPrimTypeNoticeBatchingSceneIndex to customize the order in which to update prims based on the prim type. \note Comparison to Hydra 1.0: This replaces HdRenderIndex::SyncAll updating the b-, s-, and r-prims in that order. The concept of b-, s-, and r-prim is gone in Hydra 2.0. - HdsiPrimManagingSceneIndexObserver instantiates and dirties renderer defined RAII-subclasses of HdsiPrimManagingSceneIndexObserver::PrimBase based on the content and messages from its input scene index. Threading-behavior will be customizable by future input arguments. \note Comparison to Hydra 1.0: An HdRenderer subclasses from HdsiPrimManagingSceneIndexObserver::PrimBase rather than from HdBprim, HdSprim, or HdRprim. Note that there is no pure Hydra 2.0 HdRenderer implementation yet. \section Hydra_Getting_Started_Renderer_Access Hydra 1.0 Legacy Render Delegates Accessing Scene Index Data A legacy render delegate can already access data from the terminal scene index in two ways: - By overriding HdRenderDelegate::SetTerminalSceneIndex. For example, to register a scene index observer for the given terminal scene index. - By calling ``sceneDelegate->GetRenderIndex().GetTerminalSceneIndex()`` when overriding HdRprim::Sync, and similarly for HdSprim and HdBprim. Here is an example: \snippet examples_hydra_getting_started.cpp SyncWithSceneIndexAPI This still limits invalidations to those expressible by dirty bits, and still limits data update to the type-sorted-by-tier, thread-per-prim model of HdRenderIndex::SyncAll(). \section Hydra_Getting_Started_Appendix_Scene_Index_Emulation Appendix: Scene Index Emulation We're planning to maintain the following emulation layers even as we port and deprecate all of our HdSceneDelegate and HdRenderDelegate implementations internally: - The HdRenderIndexAdapterSceneIndex is both an HdSceneIndex and an HdRenderIndex which can be used to instantiate a legacy HdSceneDelegate. Such a scene delegate is then used to populate the scene index. That is, legacy calls such as HdRenderIndex::InsertRprim are translated into scene index messages. The heavy lifting is implemented in the HdLegacyPrimSceneIndex and the HdDataSourceLegacyPrim which is a Hydra 2.0 data source calling scene delegate API. - The HdRenderDelegateAdapterRenderer is an HdRenderer that uses an HdSceneIndexAdapterSceneDelegate, HdRenderIndex and HdRenderDelegate. The HdSceneIndexAdapterSceneDelegate is the scene delegate seen by the render delegate and pulls data from the its input scene index. Typically, this input scene index is the terminal scene index. Both use the HdDirtyBitsTranslator which encodes the mapping between dirty bits (used in the change tracker) and datasource locators (used in PrimsDirtied()). */