API Guide > Viewport 2.0 API > Maya Viewport 2.0 API Guide > 2. API constructs >

# 2.3 Shader Instances

For each render item (MRenderItem), there is a 1:1 relationship with a shader. As the entire framework is based on programmable shading, an MShaderInstance is a wrapper around a hardware programmable shader. In this section it is assumed that you are already familiar with hardware Effects.

This particular interface aims to provide the most integrated solution for the usage of Effect based shaders with the rendering framework. The key properties of this interface are: simplicity, flexibility, management, and interoperability.

The closest match in the old interface is a hardware shader plug-in interface (MPxHwShaderNode). Below is a table contrasting MPxHwShaderNode versus MShaderInstance.

Characteristic | MPxHwShaderNode interface | MShaderInstance interface
Interface | A new node type needs to be created and can only act as a surface shader override. | Does not require a DG node to be created and assigned to a surface shader. It can thus be (re)used for more than just one API interface.
Parameters | Custom code needs to be written as part of the plug-in. | Uniform parameter definition and update is supported internally. Both simple and complex data types are supported and parameter binding works with all exposed API resources types such as textures and targets.
Effects support | Separate plug-ins have been used to support different languages with little or no commonality between them. All loading, parsing, compiling and maintenance is up to the plug-in code. | The shaders supported are Effects file based. Effect files on disk can be read and compiled to return shader instances. Effects on disk are automatically monitored for modifications. No additional coding support is required by the plug-in. Both DirectX11 HLSL and OpenGL CgFX effect files are supported.
Semantic binding | Custom code needs to be written as part of the plug-in | A set of SAS semantics are supported for automatically binding various uniform and varying parameters. Semantics supported include those required for surface shading and screen space rendering. The semantics supported between CgFx and HLSL are mostly equivalent but can differ due to shading language differences
Internal shaders access | This concept does not exist in this interface. | There are a number of internally provided preset shaders available. These provide automatic integration with the rendering framework. Features such as light binding, full screen effects, and transparency require no additional work. Implementations of MPxShadingNodeOverride can access shaders built by Maya through this interface.
Shader Management |  | All shaders are managed by the internal resource manager and as such can be shared and reused.
State Management |  | Technique, pass and other state management is tracked internally within the rendering framework. Any optimizations are automatically provided without changes to any plug-in source code.

The “eco-system” of each can be shown diagrammatically:

Figure 24 | Figure 25

On the left, MShaderInstance is integrated as part of the framework. The MShaderManager class is shown. This is the API interface to the shader resources maintained by the internal resource management system. On the right, a possible setup for MPxHwShaderNode is shown. All “custom” boxes need to be written by the plug-in writer.

Note that we are using the term shader instance versus shader. This distinction is made as the shader provides the definition of the algorithm and the definition of input and output parameters. A shader instance defines the parameter input values or bindings for a given instance of the shader.

To acquire a shader instance, use the manager interfaces to either load in an Effects file from disk, or acquire an internally created instance. Some key properties of the manager include:

- Shader compiler macros may be defined when using Effects files on disk
- It is not mandatory to use the internal caching mechanism. While caching is enabled, if an Effect on disk is changed it is automatically reloaded.
- Search paths for Effects files can be added.
- When acquiring a shader instance a specific technique needs to be specified. To use a different technique another shader instance needs to be acquired. If no technique is specified then the default technique specified in the Effects file is used.

It is possible to specify pre or post callback functions for each shader instance. This is useful, for example, to update parameters based on the current drawing context. Custom callbacks can be derived from the MShaderInstance::DrawCallback interface.

Parameters can also be set at any time, either within the callback or outside. There is a range of parameter types which are supported, including: Booleans, integers, float tuples, matrices, textures and texture samplers, and render targets. The general process for updating parameters is to query the parameter list, and then for each parameter of interest, set its value using the appropriate method on MShaderInstance.

Any semantic associated with a parameter can also be queried. In general, any parameters with system defined semantics are automatically updated. This includes uniforms such as the object-to-world matrix.

There is a natural separation between shading and rendering geometry. As such, varying parameters (geometry attributes) are not exposed as shader parameters. The render phase of the pipeline automatically handles binding of geometric data and making the draw calls for rendering.

As varying parameter binding relies upon semantics, any custom Effects must be written with the appropriate semantic tagging for the varying parameters. The following is an example vertex shader input structure which tags position and normal requirements.

    struct VS_INPUT {
        float4 Pos : POSITION; // Position semantic to bind positional data streams
        float4 Norm : NORMAL; // Normal semantic to bind normal data streams
    };

As part of the integration of a shader instance, an instance can specify whether it draws with any transparency. This helps with the categorization of render items (MRenderItems) as they flow through the pipeline.

Revisiting the Update Phase, the main pieces can now be filled in as follows:

Figure 26

Instead of a “shader”, an MShaderInstance instance is referenced by an MRenderItem. The geometric attributes of the shader represented by the MShaderInstance provides set of vertex and index descriptors which specify the requirements to be used during update.

The pipeline in which the update and draw phases reside could look as follows:

Figure 27

In the figure above, some of the abstract constructs from the previous diagram have been replaced with constructs exposed in the API. The Update Phase produces MRenderItems (and their associated MShaderInstances). The transparency indicator on the MShaderInstance is taken into account during the consolidation and categorization phases so that the render item may be being transferred to a “transparent” render item list. During the Draw Phase, the MRenderItem is examined. The corresponding MShaderInstance sets up the shader and updates the actual hardware shader based on the parameter values of the MShaderInstance. Geometry referenced in the MGeometry will be bound and drawn. Any pre or post callback associated with the MShaderInstance would be invoked at the appropriate times.

There is one older interface which is used for fixed-function material setting. This is the MMaterial interface, which is used in conjunction with the UI DAG object interface (MPxSurfaceShapeUI). There is no connection between MShaderInstance and UI objects, as there is no mixing of programmable shaders with the fixed function legacy drawing framework.