Conditionals

Outside HLSL blocks

if, else, else if directives are used to perform conditional compilation of different shader variants in DSHL.

Example:

texture tex;
texture fallback;
int test_interval = 0;
interval test_interval:negative<0, less_than_two<2, more_than_two;

shader test_shader
{
  if (tex != NULL)
  {
    (ps) { tex@smp2d = tex; }
  }
  else
  {
    (ps) { tex@smp2d = fallback; }
  }

  if (test_interval == positive)
  {
    (vs) { var@f4 = (0, 0, 0, 0); }
  }
  else if (test_interval == less_than_two)
  {
    (vs) { var@f4 = (1, 0, 0, 0); }
  }
  else
  {
    (vs) { var@f4 = (1, 0, 1, 0); }
  }
}

For each branch of the conditional statement, there will be created some number of shader variants (determined by combinatorics). If branch is an exact duplicate of another, no variants will be created. These variants are to be switched in runtime, based on the values in the conditionals.

Inside HLSL blocks

It is possible to use similar directives ##if, ##elif, ##else, ##endif inside hlsl{...} blocks too with a special ## preprocessor tag. In this case, however, you need to close them with ##endif in the end. Example:

hlsl
{
##if tex != NULL
  float somefloat = 1.0;
##endif
}

maybe intrinsic

maybe() intrinsic can be used in a bool-expression. Its argument is any identifier. If this identifier is not a boolean variable, the intrinsic will return false, otherwise the value of this boolean variable.

if (wsao_tex != NULL) {
  if (shader == ssao) {
    bool use_wsao = true;
  }
}

(ps) {
  if (maybe(use_wsao)) {
    foo@f4 = foo;
  }
}
hlsl(ps) {
  ##if maybe(use_wsao)
    return foo;
  ##endif
}

If you try to remove the maybe() in this example, it will cause a compilation error, because the use_wsao is not declared in all variants.

Creating multiple shaders with conditionals

Conditionals can also be used to define multiple shaders at once (for convenience). You just declare multiple shaders with the shader keyword and do a conditional statement on the shader’s name:

shader one, two, three
{
  if (shader == one)
  {
    float var = 1.0;
  }
  else if (shader == two)
  {
    float var = 2.0;
  }
  else
  {
    float var = 0.0;
  }
}

This example will result in compilation of 3 different shaders, namely one, two and three, which will have different values assigned to var.

Note

Do not confuse this feature with intervals Intervals. It does not create variants of a single shader, but creates different shaders with different names.