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 4 of 4

Thread: Geometry shader output streams (for binning instances)

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

    Geometry shader output streams (for binning instances)

    Need some help from GLSL syntax gurus. I'm looking for a generic way to output to multiple streams without having to hard-code explicit logic for each stream in the geometry shader.

    For example, I know you can do this:

    Code glsl:
      #version 400
     
      layout( points )                   in ;
      layout( points, max_vertices = 1 ) out;
     
      // Outputs
      layout( stream=0 ) out float data0;
      layout( stream=1 ) out float data1;
      layout( stream=2 ) out float data2;
      layout( stream=3 ) out float data3;
      ...
     
      void main(void)
      {
        int output = determineOutput();
     
        switch ( output )
        { 
          case 0  : data0 = my_data; EmitStreamVertex(0); break;
          case 1  : data1 = my_data; EmitStreamVertex(1); break;
          case 2  : data2 = my_data; EmitStreamVertex(2); break;
          case 3  : data3 = my_data; EmitStreamVertex(3); break;
          ...
        }
      };

    But this copy/paste/modify code is undesirable, and I might have 10, 20, or 30+ different output streams with 4 or 5 outputs per stream.

    Any tips? Trying to avoid re-sifting the list N times.

    What I really want is something like this:

    Code glsl:
    #version 400
     
    layout( points ) in ;
    layout( points, max_vertices = 1 ) out;
     
    // Outputs
    layout( streams ) out float data;
     
    void main(void)
    {
      int output = determineOutput();
     
      data = my_data;
      EmitStreamVertex( output );
    };

    where I don't have to hard-code the number of streams in the shader. But EmitStreamVertex explicitly says it only takes a constant integral argument, and I don't see a way to define an output that applies to any requested stream.

    Thanks.
    Last edited by Dark Photon; 12-06-2012 at 01:29 PM.

  2. #2
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,220
    Just noticed that GL_MAX_VERTEX_STREAMS is 4 even on this relatively recent GL 4.x hardware (which is what GL 4.3 requires). That's inconvenient.

    Could multipass, but probably time for a different approach. Thoughts?
    Last edited by Dark Photon; 12-06-2012 at 07:27 PM.

  3. #3
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    I don't think there is a way to avoid the crux of your problem: wanting to arbitrarily choose where to output which data, without having a switch statement.

    Every method for outputting data, whether it's streams, regular shader outputs, or even writing to image variables, ultimately requires either an integral constant expression or a dynamically uniform expression.

    Through the use of image variables, you can avoid the limited stream count issue. You'll of course need your own atomic variable to figure out how to insert it into the next slot in the image variable. But while image variable arrays are allowed, the array index has to be a dynamically uniform expression. And even then, you can only have a limited number of image variables. It's required to be at least 8 (but only in the fragment/compute shader).

    So ultimately, you're going to need to use a switch statement.

  4. #4
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,220
    I don't think there is a way to avoid the crux of your problem: wanting to arbitrarily choose where to output which data, without having a switch statement.
    Hmm. Ok, thanks.

    Quote Originally Posted by Alfonse Reinheart
    Every method for outputting data, whether it's streams, regular shader outputs, or even writing to image variables, ultimately requires either an integral constant expression or a dynamically uniform expression.
    Reading up a bit on what's out there for GPU binning, one common method (popularized 4 years back by ATI) which gets you past this limitation seems to be computing the bin index in the vertex shader (gl_Position) and then using normal point rasterization to toss the data in that bin. Has its own shortcomings though. Have a few other options to explore as well.

    Through the use of image variables, you can avoid the limited stream count issue. You'll of course need your own atomic variable to figure out how to insert it into the next slot in the image variable. But while image variable arrays are allowed, the array index has to be a dynamically uniform expression. And even then, you can only have a limited number of image variables. It's required to be at least 8 (but only in the fragment/compute shader).
    Thanks for the tip.

Posting Permissions

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