Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 2 of 2

Thread: Block/struct scoping for varyings

Threaded View

  1. #1
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,188

    Block/struct scoping for varyings

    So I was playing a bit more with stream out geometry shaders (link), and gave another go at avoiding the needless copy/paste/modify for declaring all the stream outputs and for populating those outputs when you want to send the exact same list of 5 to 10 output values to 1 of 4 output streams. That is, to avoid:

    Code glsl:
    layout( stream=0 ) out float stream0var1;
    layout( stream=1 ) out float stream1var1;
    layout( stream=2 ) out float stream2var1;
    layout( stream=3 ) out float stream3var1;
     
    layout( stream=0 ) out float stream0var2;
    layout( stream=1 ) out float stream1var2;
    ...
    layout( stream=0 ) out float stream0var10;

    Using a struct to group the output vars seemed promising. It compiles with no problems.
    Code glsl:
    // Outputs
    struct OutStruct
    { 
      float var1;
      float var2;
    };
     
    layout( stream=0 ) out OutStruct out0;
    layout( stream=1 ) out OutStruct out1;
     
    ...
    out0 = OutStruct( 1234, -1 );
    EmitStreamVertex(0);
    ...

    However, the link fails because it can't find out0.var1, out0.var2, etc. (registered with glTransformFeedbackVaryings). Apparently while the struct scopes the struct members properly in the shader, the compiler loses this scoping info. You can register "var1" and "var2" with glTransformFeedbackVaryings, but who knows which stream output it's attaching to. There's no way AFAICT to designate "which" stream you're referring to when you use those unscoped vars.

    So I tried another approach: structs in blocks.

    Code glsl:
    layout( stream=0 ) out Out0 { OutStruct out0; };
    layout( stream=1 ) out Out1 { OutStruct out1; };

    Same as above but with changed varying declarations. This compiles and links (with varyings registered being out0.var1, out0.var2, etc.). However, anything the shader tries to output on stream other than 0 (for instance, stream 1:

    Code glsl:
    out1 = OutStruct( 5678, -1 );
    EmitStreamVertex(1);

    is never registered as a primitive output by GL. That is, never bumps the GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN count for that stream output. But stream 0 works fine -- I get all the primitive outputs that should have gone to stream 0, and only those outputs.

    Am I doing something obviously wrong here?

    Here's the full shader in case someone wants to run it through the compiler:

    Code glsl:
    #version 400
    layout( points ) in ;
    layout( points, max_vertices = 1 ) out;
     
    // Inputs
    in vec3 pos[1];
     
    // Outputs
    struct OutStruct
    { 
      float var1;
      float var2;
    };
     
    layout( stream=0 ) out OutStruct out0;
    layout( stream=1 ) out OutStruct out1;
     
    //layout( stream=0 ) out Out0 { OutStruct out0; };
    //layout( stream=1 ) out Out1 { OutStruct out1; };
     
    void main(void)
    {
      int route = ( pos[0].z >= 1 ) ? 1 : 0;
     
      switch ( route )
      { 
        case 0 : out0 = OutStruct( 1234, -1 ); EmitStreamVertex(0); break;
        case 1 : 
        default : out1 = OutStruct( 5678, -1 ); EmitStreamVertex(1); break;
      }
    };
    Last edited by Dark Photon; 01-11-2013 at 07:39 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •