I have an float RGBA buffer that I want to pass to my compute shader as a Uniform Texel Buffer (for read-only access with no sampling).
Can someone tell me how to do this in GLSL?
All examples I can find seem to be skipping that topic or have a at best weak nomenclature.
The descriptor type that Vulkan calls "uniform texel buffer" represents a concept that, in OpenGL parlance, is called a "buffer texture". While normally the GLSL type for this would be samplerBuffer, the Vulkan flavor of GLSL uses textureBuffer instead.
The corresponding descriptor for this type should of course use the VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER type. However, since Vulkan doesn't share OpenGL's notion that this is some kind of texture, the descriptor's data is a VkBufferView, not a VkImage or VkImageView. Specifically, VkWriteDescriptorSet::pTexelBufferView.
Related
I am looking into OpenGL Uniform Buffer Objects and Shader Storage Buffers. I think the question applies to both of them, but let's just focus on UBOs.
Tutorials seem to be saying that "block index" and "binding point index" are different things, and if I have more than one UBO in a shader, I need to specify the binding index
layout(binding = 0) uniform first_buffer {...};
layout(binding = 1) uniform second_buffer {...};
I get the impression that the block index is determined by the linker and can be read from glGetUniformBlockIndex, but the binding point index has to be hard-coded with arbitrary distinct binding=N in the layout, and a corresponding glBindBufferBase(GL_UNIFORM_BUFFER, N, ubo_handle), which strikes me as fragile and a nuisance.
What is the difference between a block index and a binding point?
Can I omit the binding=N in the layout? What happens then with glBindBufferBase?
Is this all the same for SSBOs?
See OpenGL 4.6 API Core Profile Specification - 7.6 Uniform Variables
Named uniform blocks, as described in the OpenGL Shading Language Specification, store uniform values in the data store of a buffer object corresponding to
the uniform block. Such blocks are assigned a uniform block index.
The block index is the "handle" for the active program resource of a shader program. If you have different shader programs with the "same" uniform block, then they may have different buffer indices.
A buffer is bound to the uniform block of a shader program the binding point (e.g. in shader by a Binding point Layout Qualifier). On the one side a uniform block (index) is associated to a binding point and on the other side a buffer is bound to the binding point (by glBindBufferBase). So one buffer can be bound to the uniform blocks of different programs.
While the buffer index is fixed and and can't be changed after the program is linked, the binding point is a dynamic value and can be changed by glUniformBlockBinding. When the program is linked, then the binding point is initialized by 0 or by the value which is set by the Binding point Layout Qualifier.
This principle is the same for a Shader Storage Buffer Object.
Related questions are:
Difference between glBindBuffer and glBindBufferBase
Is it safe to use the block index as the binding point for UniformBufferObject, ShaderStorageBufferObjects, etc?
How do I query the alignment/stride for an SSBO struct?
I'm trying to make an array of vec3 available to a fragment shader. In the targeted application, there could be several hundred elements.
I tested transferring data in the form of a shader storage buffer object, declared as
layout(binding = 0) buffer voxels { vec3 xyz[]; }
and set using glBufferData, but I found that my fragment shader becomes very slow, even with only 33 elements.
Moreover, when I convert the same data into the GLSL code of a const vec3[] and include it in the shader code, the shader becomes noticeably faster.
Is there a better way – faster than an SSBO and more elegant than creating shader code?
As might already be apparent from the above, the array is only read from in the shader. It is constant within the shader as well as over shader invocations for different fragments, so effectively a uniform, and it is set only once or a few times over the runtime of the program.
I'd recommend using std430 layout specifier on the SSBO given that you are using vec3 data types, otherwise you'll be forced to pad the data, which isn't going to be great. In general, if the buffer is a fixed size, then prefer using glBufferSubData instead of glBufferData (the latter may reallocate memory on the GPU).
As yet another alternative, if you are able to target GL 4.4+, consider using glBufferStorage instead (or even better, if GL4.5 is available, use glCreateuffers, and glNamedBufferStorage). This let's you pass a few more hints to the GL driver about the way in which the buffer will be consumed. I'd try out a few options (e.g. mapping v.s. sub-data v.s. recreating each time).
I use glGetActiveUniform to query uniforms from the shaders.But I also use uniform buffers (regular and std140).Querying them returns an arrays with the primitive type of the uniform in the buffer.But I need a way to identify those are uniform buffers and not uniforms.
Examples of uniform buffers in a shader:
layout(std140, binding = LIGHTS_UBO_INDEX) uniform LightsBuffer {
LightInfo lights[MAX_LIGHTS];
};
Is it possible to query only buffers from GLSL shader?
Technically, what you actually have here is a uniform block. It has a name, but no type; its members (which are uniforms) have types, and I think that is what you are actually describing.
It is a pretty important distinction because of the way program introspection works. Using OpenGL 4.3+ (or GL_ARB_program_interface_query), you will find that you cannot query a type for GL_UNIFORM_BLOCK interfaces.
glGetActiveUniformBlockiv (...) can be used to query information about the uniform block, but "LightsBuffer" is still a block and not a buffer. By that I mean even though it has an attribute called GL_BUFFER_BINDING, that is really the binding location of the uniform block and not the buffer that is currently bound to that location. Likewise, GL_BUFFER_DATA_SIZE is the size of the data required by the uniform block and not the size of the buffer currently bound.
I want to render a scene to texture, and share the texture sampler in several programs. Similar to share the project view matrix in multiple programs. Unlike project view matrix, which can be put into uniform blocks, "Samplers cannot be part of uniform blocks". https://www.opengl.org/wiki/Uniform_(GLSL)
Some discussion here describes why:
multiple issues:
GLSL samplers embody two things: source of texture data and how to filter from it (nearest, linear, mipmapping, anisotropic, etc)
Samples are opaque things, and to place them into a uniform buffer object requires they have a well defined (and cross-platform) size.
Those issues together make it dicey.
I want to see some explanation of why this cannot be handled and any other ways to achieve sharing texture samplers.
The explanation is right here:
Samples are opaque things, and to place them into a uniform buffer object requires they have a well defined (and cross-platform) size.
The purpose of uniform blocks is, that you can set then with a single OpenGL call from a single structure in your (client) program. But for this to work the memory layout of this structure must be known, so that the memory layout produced by the compiler matches that of the shader uniform block.
But since the memory layout of samplers is not defined a memory layout can not be determined. Without a definitive memory layout no structure, without a structure no block.
When doing multitexturing in GLSL, is there anyway to have an indexable array of samplers where each texture is a different size? This syntax isn't valid:
uniform sampler2D texArray[5];
Right now it seems like the only option is to individually create the samplers:
uniform sampler2D tex1;
uniform sampler2D tex2;
uniform sampler2D tex3;
uniform sampler2D tex4;
uniform sampler2D tex5;
But then I can't iterate through them, which is a real pain in the ass. Is there a solution?
This syntax isn't valid:
Says who? Arrays of samplers most certainly are valid (depending on the version). How you use them is a different matter.
GLSL 1.20 and below do not allow sampler arrays.
In GLSL 1.30 to 3.30, you can have sampler arrays, but with severe restrictions on the index. The index must be an integral constant expression. Thus, while you can declare a sampler array, you can't loop over it.
GLSL 4.00 and above allow the index to be a "dynamically uniform integral expression". That term basically means that all instantiations of the shader (within the same draw call) must get the same values.
So you can loop over a constant range in GLSL 4.00+, and index a sampler array with the loop counter. You can even get the index from a uniform variable. What you can't do is have the index depend on an input to the shader stage (unless that value is the same across all instances caused by the rendering command), or come from a value derived from a texture access (unless that value is the same across all instances caused by the rendering command), or something.
The only requirement on the textures placed in arrays of samplers is that they match the sampler type. So you have to use a GL_TEXTURE_2D on all the elements of a sampler2D array. Beyond that, the textures can have any number of differences, including size. The array exists to make coding easier; it doesn't change the semantics of what is there.
And remember: each individual element in the sampler array needs to be bound to its own texture image unit.
is there anyway to have an indexable array of samplers where each texture is a different size?
Not yet. Maybe this gets added to a later OpenGL version down the road, but I doubt it.
But then I can't iterate through them, which is a real pain in the ass. Is there a solution?
As a workaround you could use Array Textures and use only subregions of each layer. Use a vec4 array to store the boudaries of each picture on each layer.