Shader System
GLSL cannot be precompiled, which makes OpenGL the only SpeedTree-supported graphics API where precompiled shaders cannot be used. The biggest impact with this is that the SpeedTree Compiler can generate a pretty large bank of shaders for a given forest. As such, it may much longer for OpenGL to load a bank of shaders (e.g. many seconds), than for a platform that supports precompiled shaders (e.g. just a couple hundred milliseconds). ATI OpenGL drivers, especially, are particularly slow when compiling shaders that use Uniform Buffer Objects, which SpeedTree employs to support instancing under OpenGL.
Note: The SpeedTree OpenGL renderer employs a mechanism to save off the compiled shader using a platform-specific format. This will result in much faster shader loading on subsequent runs, but the generated files are videocard vendor-specific. |
---|
Another important area where GLSL differs from HLSL/Cg-type syntax is the ability to assign which constant registers the uniform constants will reside in (this is in fact possible, but requires newer OpenGL extensions). The SDK relies on each shader having the uniform shader constants residing in the same registers so that they don't have to be reassigned each time a new shader is bound (imagine having to upload the projection/view matrix and many other uniforms each time one of possibly dozens of shaders are bound each frame; it's a waste). To get around this restriction, the SpeedTree shader templates allocate one large uniform constant array and assign indices for each of the global variables (see the OpenGL section of ShaderConstants.h for details of how this is implemented). The OpenGL renderer will perform a “sanity check” that this unform array is assigned to register zero for every shader, else the approach will not work.
Two other operations are necessary for GLSL to behave similarly to its HLSL counterpart to be portable in the SpeedTree SDK: