Chapter 6
Control Constructs

C++ control constructs can be used to manipulate Sh programs. These control constructs are not seen or processed by the Sh compiler, which only sees the operation sequences generated by them. However, C++ if statements can be used to selectively include variations in an Sh program, and C++ for, while, and do/until constructs can be used to repeat parts of Sh shaders.

C++ control constructs can only depend on compile-time (C++ run-time) values, not values computed in a shader itself. In this manner, C++ is effectively a macro language for Sh.

To express data-dependent control constructs, Sh supports a set of cpp macros that can encode control construct keywords into the operation stream processed by Sh. These keywords semantically act much like C++ keywords, but have a syntax more in line with that of Algol. In particular, there are special keywords to mark the end of each different kind of control construct. There are also a few other minor differences having to do with the need to encode these keywords as macros: there can be no space between an Sh keyword and its arguments, and the arguments to Sh keywords with multiple arguments, such as SH_FOR , must be separated by commas, not semicolons.

Each statement subsequence inside an Sh control construct automatically is given a new scope, as if it were wrapped in “{}” braces. Additional braces are not necessary; they are already included in the macros. Because of this, Sh control constructs must be properly nested with C++ control constructs. The basic nesting properties of the Sh control constructs will also be checked at C++ compile time. However, detailed syntax checking will not take place until C++ runtime when the shader definition code is actually executed, the shader is built, and Sh runs a recursive-descent parser over the operation sequence to reconstruct the parse tree of the Sh program.

You should include the braces around bodies of Sh control constructs. This is useful partly for ease of reading but also as a hint to code editors to indent the contained lines appropriately. Similarily, putting a semicolon after the SH_END * keywords will avoid confusion on the part of the syntax highlighter.

The arguments to Sh control construct keywords can be arbitrary expressions, including C++ functions which can themselves invoke arbitrary sequences of Sh control constructs.

We plan to support data-dependent control constructs for as many compilation targets as possible, but for some compilation targets it may not be feasible, or may be inefficient. For instance, for GeForceFX and ATI Radeon 9700 GPUs, we have demonstrated that it is possible to support true data-dependent control flow using multiple passes, even though data-dependent branches are not supported in the machine language. Our implementation implements true conditional execution, not just SIMD-style conditional assignment, so computation is actually avoided, as necessary for proper implementation of general iteration. However, our approach is still highly experimental at this point and can only be supported in stream programs at present and not shaders. This latter restriction is due to the way Sh interacts with the graphics API (Sh cannot at present invoke multiple renderings with the same geometry).


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.