OpenGL Pool Uniformity

Can someone tell me about the seemingly uselessly complex Uniform Buffers? I read the section in OpenGL Superbible 5, I looked at some examples on blogs, and I read the official specification, and I still don't understand.

In particular, for all the examples, apparently, you need to start with a shader program in order to first create a single buffer using glGetActiveUniformsiv. I do not understand this. Why the interface does not allow you to determine the structure without accessing the shader program, checking the / s buffer formats for the program during the connection?

Secondly, if I get the structure structure from one program, assuming that the structure structure is the same for all programs using a set of uniforms, is the structure guaranteed by the same offsets, data sizes, etc.? I would suggest so.

Thirdly, I do not understand the bindings. I need to call glBindBufferBase with an index, and then call glUniformBlockBinding with the block index and index that I passed to glBindBufferBase. I find it difficult to understand what is happening here. Superbible is not clear, as are the specs and samples I've seen.

+6
source share
1 answer
  • Why exactly do you want? Personally, if you don't have a serious data shortage problem and you need every byte, I see no reason to use anything other than std140 . This makes the code much cleaner.

    However, if you are dead avoiding std140 , read on.

  • The specification fully explained this: all of this is in layout qualifiers.

    There are exactly 3 qualifying layouts: packed , shared and std140 . packed means that the implementation can freely organize whatever it wants. This includes removing uniforms that the current program is not using. Thus, the layout is determined by the implementation, and some uniforms inside this layout may have been optimized.

    shared means that an implementation can order data in the same way as packed . However, must provide storage for each uniform. This allows you to share a single layout among programs, hence the name. shared also requires the implementation to provide a consistent layout for sequential definitions between programs. Therefore, you only need to fulfill the request for one layout.

    To answer your first question, you could, if you want, create a fake program with a shared layout. You can use it only to request a layout for a single block. Then, while the layout is consistent between other programs (with the shared layout), the layouts will be the same. Therefore, there is no need for a special API for it.

    std140 however means that the layout of a homogeneous block is determined explicitly by the OpenGL implementation, byte for byte. This implies the possibility of sharing, since two identical identical blocks according to this specification will have an identical layout. And since the implementation cannot optimize the form in the std140 layout std140 , everything is perfect.

    Again, there is almost no reason to avoid std140 . Unless you are under very severe memory restrictions.

  • This is the same mechanism as for textures. The only difference is that the same block names are not common forms.

    Texture objects are attached to units of a texture image using glActiveTexture(GL_TEXTURE0 + i);glBindTexture() , where i is the unit index of the texture image. Now you need to tell the shader that the sampler uses this image module. However, OpenGL does not allow you to directly associate with a name; you need to convert the sampler name to the index location. This way you get a uniform layout for a particular sampler with glGetUniformLocation . Once you have a single location, you can associate the texture image block with that location by calling glUniform1i(loc, i) , where again i is the unit of the texture image into which you linked the texture.

    Unified buffer objects are bound to single buffer anchor points using glBindBufferRange(GL_UNIFORM_BUFFER, i, ...) , where i is a single buffer anchor point. Now you need to specify a shader that uses a single block of this anchor point. However, OpenGL does not allow you to directly associate with a name; you need to convert a single block to an index location. Thus, you get an index to a specific single block with glGetUniformBlockIndex . Once you have an index, you can associate a single buffer anchor point with that index by calling glUniformBlockBinding(program, index, i) , where again i are the single buffer anchor points to which you bound the uniform buffer.

    Cm? Similar. They use different terms, but structurally, they are the same. If you need a picture, you can find a more detailed discussion, which includes a diagram here .

+11
source

Source: https://habr.com/ru/post/897013/


All Articles