Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 2 12 LastLast
Results 1 to 10 of 18

Thread: Forward Declaration of Scoped Variables (Uniform Buffer Objects)

  1. #1
    Junior Member Newbie Kastenfrosch2's Avatar
    Join Date
    May 2012
    Location
    Gemrany
    Posts
    15

    Forward Declaration of Scoped Variables (Uniform Buffer Objects)

    I attach two vertex-shaders to my Program Object

    Vertex Shader1:
    Code :
    uniform BlockName{
      int varName;
    } scopeName;
     
    // ...

    in Vertex Shader2, i want to use varName. So i forward declarate it.
    Code :
    uniform int scopeName.varName; // Compile Error: unexpected syntax Error at "."

    Edit:
    Makes sense, because the compiler doesn't know about scopeName when compiling Shader2.
    But how can i use the scoped uniforms in my second Shader? Can i forward declarate or redeclarate the Scope or the Uniform Buffer?

    I didn't find anything about it in the Uniform_Buffer_Object specification.
    (I use a GeForxe GTX 560 with Driver 296.10)
    Last edited by Kastenfrosch2; 05-18-2012 at 02:34 AM.

  2. #2
    Advanced Member Frequent Contributor
    Join Date
    Apr 2010
    Location
    Germany
    Posts
    892
    If a symbol, in your case scopeName, has already been declared previously in the same scope (in your case user global scope), you'll get a conflict. Second, you cannot use the instance name of an interface block in a variable declaration. When the compiler sees somthing like

    Code :
    uniform int scopeName.varName;
    it sees the uniform qualifier, than a basic type which lets it know you're going to define a uniform variable of type int, and then expects an identifier which hasn't been declared previously. This can either be followed by an assignment or the end of the statement which is the semicolon. Therefore your statement where you select a member of an instance is invalid.

    Why is varName at global scope.
    In the same shader, it's because you shift varName from the uniform block out the global scope by using an instance name, in your case scopeName. Therefore scopeName.varName isn't the same variable as varName.

    If you declare a block in one shader and declare a variable in another shader which bears the name of a block variable there is no conflict because VS1 doesn't know about anthing in VS2. If, however, you declare the following

    Code :
     
     uniform Block
     {
       mat3 blockMat;
     
     };
     
     
     
     mat3 blockMat;

    then you have the same problem as before. blockMat is declared two times at global scope since no instance name(s) is(are) used for Block which implicitly puts variables from the uniform block at global scope.

    Is this expected behavior
    Since it's clearly specified this behaviour is pretty much expected.

    How do I handle Name Conflicts (two scopes that contain the same varName)?
    Use instance names or use different variable names.

    How can i use the scoped uniforms in my second Shader?
    You simply declare the block in both shaders to use the data. Depending on the layout you're using you'll have to query the offsets of the uniform block in either shader. If you use layout(std140) you are guaranteed to have to same layout across all shaders. Consult the spec on layouts.

    Edit: Btw, in GLSL there is no such thing as a forward declartion in the sense of C++'s forward declaration.
    Last edited by thokra; 05-18-2012 at 02:34 AM.

  3. #3
    Junior Member Newbie Kastenfrosch2's Avatar
    Join Date
    May 2012
    Location
    Gemrany
    Posts
    15
    Thanks for your answer and excuse me for editing my initial question (i reformulated it before your answer appeared)

    Another sorry for not being clear about my intentions:
    In my second shader i want to use the value that is stored inside the UniformBufferObject for varName.

    If i omit the instance name ("debugScope") in my first shader and do something like:

    VertexShader1:
    Code :
    uniform BlockName{
      int varName;
    };

    VertexShader2
    Code :
    uniform int varName;

    I can use the uniformBuffers Value for varName in my Shader2. That works for me.
    Isn't this a kind of "forward declaration", because i say "There will be some uniform called varName, you'll hear later about that"?!
    Or is it just some nasty mixing of uniform declarations and UniformBufferObjects-Internal uniforms?
    I couldn't read something about that in the specification.
    But with this "uniform variable names at global scope" everything seems to work. (My "is this expected behavoir" question was meant as
    "Is it specified, that a variable inside a UniformBlock can be refferred to by another shader by declaring it as a >common uniform< with the same name?")


    Now i want to do the same thing for a scoped UniformBlock (one with instance name "debugScope").

    VertexShader1:
    Code :
    uniform BlockName{
      int varName;
    } scopeName;

    You simply declare the block in both shaders to use the data
    If i redeclare the uniform Block like

    VertexShader2
    Code :
    uniform BlockName{
      int varName;
    } scopeName;

    i get an error C1038: declaration of BlockName conflicts with previous declaration at [Declaration Position in VertexShader1]


    Any idea what i am doing wrong?

  4. #4
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,716
    I can use the uniformBuffers Value for varName in my Shader2. That works for me.
    It shouldn't. As far as GLSL is concerned, it's nonsense.

    If i redeclare the uniform Block like
    Then your compiler has a bug in it.

    Personally, I would suggest avoiding this multi-shader approach altogether. If you have several strings you want to compile into a vertex shader, then do that by supplying all of them to `glShaderSource`. Don't try to link multiple vertex shaders into a program.

    Yes, the spec says you can. But most people don't use this functionality, which means that most implementations of this are not well tested. So you're more likely to avoid bugs if you don't do it.

    BTW, can you please stop inserting random bold-face text into your posts? We can decide for ourselves what the important words are.

  5. #5
    Advanced Member Frequent Contributor
    Join Date
    Apr 2010
    Location
    Germany
    Posts
    892
    Personally, I would suggest avoiding this multi-shader approach altogether.
    Agreed. I actually got that wrong and thought he was talking about seperate programs. Now it makes a lot more sense.

    BTW, can you please stop inserting random bold-face text into your posts? We can decide for ourselves what the important words are.
    Please stop! You're making me dizzy...

    Edit:
    "Is it specified, that a variable inside a UniformBlock can be refferred to by another shader by declaring it as a >common uniform< with the same name?"
    One of the main concepts of uniform blocks is sharing of data across multiple stages (i.e. vertex shader, fragment shader ...) of a single shader program and across multiple programs. If you do this in a vertex and a fragment shader

    Code :
     
    layout(std140) uniform BlockName
    {   
      int varName; 
    };

    you can access varName in both shaders and get the same value. However, if you declare the block in two source files which are to be combined to form a single translation unit, the thing you're doing right now, you'll get the redeclaration error.
    Last edited by thokra; 05-18-2012 at 03:42 AM.

  6. #6
    Junior Member Newbie Kastenfrosch2's Avatar
    Join Date
    May 2012
    Location
    Gemrany
    Posts
    15
    Personally, I would suggest avoiding this multi-shader approach altogether
    Thanks for the Tip. I always thought it would be the cleaner approach.
    Perhaps it's the best solution for me to switch over to the glShaderSource-with-multiple-sources approach.

    Thanks again for helping (and sorry for the bolding, i personally prefer it when skimming throug other people's thread, because to me it looks a bit more structured)

  7. #7
    Junior Member Newbie Kastenfrosch2's Avatar
    Join Date
    May 2012
    Location
    Gemrany
    Posts
    15
    Quote Originally Posted by thokra View Post
    However, if you declare the block in two source files which are to be combined to form a single translation unit, the thing you're doing right now, you'll get the redeclaration error.

    Did i get it right, that then there is no possibility for sharing a uniformBlock's data across two vertexShaders that are compiled seperately and then linked together?
    So i have (don't dare bolding anymore ) to stick to the "multiple srcs to one compiled shader" solution?

  8. #8
    Advanced Member Frequent Contributor
    Join Date
    Apr 2010
    Location
    Germany
    Posts
    892
    Think about what you just wrote. If you link code together that has two symbols declared with the same name what does that get you? Right, a redeclaration and thus an error. My understanding of the whole thing is, that multiple sources are compiled as a single translation unit. Thus if you use the source file containing the block declaration as the first one in the array used in glShaderSource() and simply refer to block variables somewhere in the second, I think it should work. After all, the source code either has to be merged before compilation or linked together to form valid object code for the vertex stage. The latter is unlikely I suppose.

    However, why do you want to use multiple shader sources for the vertex shader in the first place?

  9. #9
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,716
    If you link code together that has two symbols declared with the same name what does that get you? Right, a redeclaration and thus an error.
    Um, no. You can have multiple declarations in different translation units just fine. Both C++ and GLSL allow this. The problem is that his GLSL compiler/linker is broken and not doing what it's supposed to.

    There is no workaround for broken GLSL; you just have to rework your code to use it in a way that works in your environment.

  10. #10
    Junior Member Newbie Kastenfrosch2's Avatar
    Join Date
    May 2012
    Location
    Gemrany
    Posts
    15
    Quote Originally Posted by thokra View Post
    If you link code together that has two symbols declared with the same name what does that get you?
    For functions, it works (defining the function in one shader, declaring and using it in another shader of the same type, compiling them separately and then attach both to the program).

    Quote Originally Posted by thokra View Post
    However, why do you want to use multiple shader sources for the vertex shader in the first place?
    If i use glShaderSource with multiple strings (from multiple files), the line-numbers of the error messages from the GLSL-Compiler are from the concatenation of all strings. If i compile the strings separately, i get a sepperate error handling and thus the line numbers start at zero for every string. => Just nicer to debug.

    Quote Originally Posted by Alfonse Reinheart
    you just have to rework your code to use it in a way that works in your environment.
    Sad to hear, but thanks for your help.

Posting Permissions

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