5.1 Defining Programs

Program definitions are enclosed by a pair of SH_BEGIN_PROGRAM and SH_END keyword macros. The SH_BEGIN_PROGRAM keyword macro returns an ShProgram object.

The SH_BEGIN_PROGRAM keyword macro takes an argument specifying the compilation target for the program. This target is used to match the program to a backend and in some cases specify the kind of program being compiled. Valid choices include "gpu:vertex" and "gpu:fragment" for vertex and fragment programs to be run on a (generic) GPU. These particular modes are also supported by macros:


#define SH_BEGIN_VERTEX_PROGRAM   SH_BEGIN_PROGRAM("gpu:vertex")
#define SH_BEGIN_FRAGMENT_PROGRAM SH_BEGIN_PROGRAM("gpu:fragment")

Using an empty string as a target indicates that the program does not (yet) have a specific target. This is useful in conjunction with the shader algebra operators (see Section 5.4).

The target identifier is split into two parts by a colon. The first part, before the colon, gives the backend name or type. / E   Backends register themselves with a particular name and a set of more generic backend types for which they are instances. For instance, all backends which involve running code on the GPU are also instances of the gpu backend type. Those running code on the CPU (e.g. with dynamic compilation or interpretation) will be instances of the cpu type.

The second part of the target specifies the kind of program being defined. Valid choices currently include vertex, fragment and stream. In the future there may be more possibilities, such as "shader", to support a unified vertex and fragment program automatically virtualized across both shader units. However, this is currently not supported.

/ E  If no colon is present in the target, the string given is assumed to be the kind of program to compile, and any available backend is matched to the program, starting with GPU backends (if available) and then CPU backends.

Once SH_BEGIN_PROGRAM has been called Sh changes from immediate mode to retained mode. In retained mode, any Sh expression, such as an arithmetic operation, a library function call, or a texture access, is not evaluated but collected. A list of computations is built and attached to the currently being constructed program. Chapter ?? provides more details on how this is done. Once SH_END is called, control constructs in the program are parsed, optimized, and possibly compiled if a matching backend has been specified.

5.1.1 Compiling Programs

If a program has been defined and it has been given a target which can be directly compiled on the current backend, it will be compiled right away as soon as SH_END is called. In our terminology we call the initial step of parsing and optimization definition and the act of translating the Sh intermediate representation to real GPU or CPU assembly or another high-level language compilation.

It is possible to force compilation of a program by invoking the shCompile function, which take an ShProgram as an argument. This compiles the given program object under the backend selected by its definition target. This forces recompilation of the program, even if it has been previously compiled.

By passing an optional second string argument to the shCompile function, a program can be recompiled for a particular target different from its original definition target. The internal representation of the program is designed to be platform independent to support this. Users should avoid using metaprogramming to put in hooks to particular platforms, unless they are willing to redefine shaders from scratch every time. To support platform-dependent features, it is better to extend the intermediate representation instead. Metaprogramming can be used to adapt programs to target platforms, but it is recommended that this only be used to adapt to performance, not features.

/ E  By calling the is_compiled member function with a string argument on a program object, it is possible to tell whether or not that program object has been successfully compiled to a particular target. Although Sh makes every effort to compile program objects to all platforms, compilation currently can fail if certain features are used that cannot yet be supported on a all platforms, for instance, unbounded data-dependent iteration.


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.