Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

#pragma & #ifdef

Discussion in 'Shaders' started by MXAdd, Aug 26, 2015.

  1. MXAdd

    MXAdd

    Joined:
    Apr 23, 2015
    Posts:
    74
    Hi

    As I'm porting our game to linux I'v met following obstacle:
    OpenGL needs all the shaders to be #pragma target 3.0
    and since we have A LOT of them, and almost all of them use DX11 specific features (.Sample, .Load, .Gather) and others) on other platforms (PC-DX11, XBOX-ONE, PS4) all my shaders have #pragma target 4.0 or 5.0 set.

    Ofcourse I could fallback those specific features into HLSL for DX9 in most cases (and in those that I cannot/will hurt performance) or use glsl. But there is one big problem.

    I want all this to be gently handled by #ifdef/#endif blocks of preprocessor, but #pragma is ignored by preprocessor ;(
    so block:

    #ifdef SHADER_API_OPENGL
    #pragma target 3.0
    #else
    #pragma target 4.0
    #endif

    after preprocessing (SHADER_API_OPENGL defined as 1) ends up as

    #pragma target 3.0
    #pragma target 4.0

    from what I'v read on shaderlab lex and yacc-based preprocessor takes the incoming shader string and produces a new string containing the preprocessed shader. This takes care of things like #if, #ifdef, #define, and preprocessor macro invocations. Note that #version, #extension, #pragma and some others are passed straight through.

    Is there any workaround for this one ? Or the only solution is to have separate branch for OpenGL shaders ?
     
  2. Dolkar

    Dolkar

    Joined:
    Jun 8, 2013
    Posts:
    576
    I've slowly gotten to the habit of writing most of my code in a CGINCLUDE block, with passes that have only minimal or no functions in them. You can then solve this by defining another subshader that uses shader model 3.0 and serves as a fallback.
     
    nirvanajie and Plutoman like this.
  3. Plutoman

    Plutoman

    Joined:
    May 24, 2013
    Posts:
    257
    Just going to second this. Quite useful, and you'll notice that most of the major shader authors on the asset store also use this method and style.
     
  4. MXAdd

    MXAdd

    Joined:
    Apr 23, 2015
    Posts:
    74
    My shaders are done in CGINCLUDE blocks to, so no problem with this, it only adds me more work that just simple #ifdef/#endif
     
  5. NoiseFloorDev

    NoiseFloorDev

    Joined:
    May 13, 2017
    Posts:
    104
    Just bit by this a couple years later. I was trying to make tessellation a toggle on a shader, and putting #pragma vertex, etc. in #ifdef just doesn't work. Putting it inside an include doesn't help, since it just throws an error demanding that you put it in the shader directly.

    Does everyone really just copy and paste the whole shader for every combination? Of course you move the logic to a header, but the whole property block and pass list has to be duplicated since the file format has no #include at that level, and you have to change shaders instead of just putting a checkbox in your editor UI. Likewise, SetShaderPassEnabled doesn't seem to work, which compounds this problem.
     
    Semro and guycalledfrank like this.
  6. msue2

    msue2

    Joined:
    Jun 2, 2017
    Posts:
    7
    Found this issue still present in 2020.3.8, when compiling a compute shader.

    In compute shaders, a line like "#pragma kernel CSMain" is required.