3 Replies Latest reply on Aug 28, 2012 8:14 AM by gsellers

    [compute shader] efficient way to fetch values from buffer object




      in OpenCL big non fixed size arrays of data are commonly passed as cl_mem objects (unformatted byte buffers within  global memory scope) which are seen in the OpenCL kernel as pointers, like traditional C arrays: typeName* varName Thus, accessing a value from this array is simply done by using the operator []: typeName a = varName[2]. How about GLSL, specially for compute shaders? In my experience with vertex shaders, I pass generic buffers as texture buffers like


      glGenBuffers(1, &tex_Buffer);


      glBindTexture(GL_TEXTURE_BUFFER, tex_Buffer);


      glBindBuffer(GL_TEXTURE_BUFFER, tex_Buffer);.

      glBufferData(GL_TEXTURE_BUFFER, data_size_in_bytes, data_array, GL_STATIC_DRAW);

      glTexBuffer(GL_TEXTURE_BUFFER, GL_DATA_TYPE, tex_Buffer);


      and in the shader program I use uniform (TYPE)samplerBuffer varName and fetch values from array with texelFetch. Is that the best way to do it for generic type non fixed size and random read/write access data buffers?


      I heard about buffers, instead of samplerBuffer, but it seems to be intended to other usages, since they are more limited in size and not well designed for random access.





        • Re: [compute shader] efficient way to fetch values from buffer object



          It depends on your use case. For small amounts of read-only data, we recommend that you use a uniform buffer. Declare an interface block as uniform in your shader:


          uniform FooBarBlock


              vec4 foo[42];

              vec4 bar[91];



          Then bind the buffer to the indexed uniform buffer binding point:


          glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniform_buffer);


          In your shader, you can access foo and bar like any other variable (although they would be constant). Keep in mind though, that the maximum size of a uniform buffer is 64KB, and that there are some pretty funky layout restrictions for uniform blocks.


          For larger amounts of homogenous data, your use of buffer textures may be the best way to go.


          In OpenGL 4.3, structured buffer support was added, which allows read and write access to buffers, including support for atomic operations. They work a lot like uniform buffers - rather than declare your interface block with the 'uniform' keyword, declare it with the 'buffer' keyword and then bind the buffer to one of the GL_SHADER_STORAGE_BUFFER binding points.





            • Re: [compute shader] efficient way to fetch values from buffer object

              thank you again mister Sellers!


              in my case, I really need to store a lot of data into VRAM (could be up to the entire VRAM global memory), and for both read and write data access, which makes uniform buffers not an option to me.


              since the amd drivers for opengl 4.3 are not yet released, can you tell me what are the typical values for GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS (say, for HD7900 series cards)? Specially, how much bytes would it represent, can I store as many bytes as I could do with buffer textures?


              and a last question about accessing VBO's into the shader program, specially for compute shader, would it be possible to pass an array of (texture) buffers with an unconstrained number of buffers in this array (given that the total amount of memory allocated do not exceed the VRAM space)? I think today the limit is 32 texture buffers. Is this something that you consider for a future extension?





                • Re: [compute shader] efficient way to fetch values from buffer object



                  The minimum requirement for OpenGL 4.3 is that GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS be at least 8. We will expose at least 8 in our initial implementation and although it may be possible to expose more, I would not recommend that you write an application that relies in there being more available.


                  There shouldn't be a practical upper limit on the size of a shader storage blocks. Thinks start to get a bit messy beyond 2GB due to overflows in 32-bit arithmetic. If you really need a lot of data, I would recommend that you stick with multiple buffers of a gigabyte or so at a time.


                  Accessing buffers with buffer textures will still work fine. The upper size for those is also around 2GB. There is a limit of 32 buffer textures per stage as well. Also, even if you create a large array of buffer textures, you might run into issues if you use a divergent value to index into it. You wouldn't need an extension to increase the number of supported buffer textures as the limit is already queryable through glGetIntegerv.