2.1 Programs

Instances of the ShProgram type represent compiled shader programs. To create an ShProgram , sequences of Sh operations are wrapped in a pair of SH_BEGIN_PROGRAM and SH_END keywords. Programs are dealt with in depth in Chapter 5.

Each program has a default target, which is a string passed in to SH_BEGIN_PROGRAM . This target specifies the backend and type of program being compiled. Example targets for GPU programs include gpu:vertex, gpu:fragment and gpu:stream. For more detail, refer to Section 5.1.

You can also generate a stream function to run on the CPU using a "cpu:stream" argument to SH_BEGIN_PROGRAM . This can be used to implement run-time just-in-time code generation for the CPU. Typically this option will generate code in a high-level language such as C++, then will compile it and dynamically link it back in. In the future, a more lightweight approach might be used, for instance, using libtcc [?]. However, use of external compilation means that the well-developed optimizers in existing compilers can be exploited.

By specifying a backend directly instead of a general type of backend it is possible to cross-compile programs. For instance, you may want to cross-compile for an NVIDIA GPU from a system with an ATI GPU, in which case you would need to explictly specify the "nv" backend, with possible further elaboration as to the specific video card, rather than use the default (the currently installed GPU) provided by the generic "gpu" option. Of course you cannot run such a shader immediately, but you can save it and restore it later. This might be used, for instance, to avoid start-up shader compilation costs by precompiling a number of shaders for each possible platform an application might run on. In the future there may also be multiple ways to compile a program to the CPU with different performance characteristics (i.e. using branches vs. using multipass SIMD stream execution).

Several functions exist that act on ShProgram objects. The most important for GPU applications is shBind(ShProgram p), which loads a program p into the shader unit for which it was compiled and makes it active. This function also initializes the constant registers of the shading unit with the current values of all the parameters the shader program references, and also binds all the textures the shader uses to the same shading unit and also loads them onto the GPU’s local memory if necessary. To update the textures and uniforms for an already bound shader, an update should be forced using shUpdate(). Parameters may be automatically updated as they are changed if they are used by the currently bound shader, but shUpdate() will force this to be the case. Since texture updates are expensive they are deferred until shUpdate() is called. These calls are only needed when using Sh with a separate rendering interface (as is the case on OpenGL). When running stream computations using Sh, it is not necessary to bind a shader and buffer updates happen automatically. More details on these calls are provided in Section 5.2.


Note: This manual is available as a bound book from AK Peters, including better formatting, in-depth examples, and about 200 pages not available on-line.