does vulkan bindings have to be sequential in shaders - glsl

is it necessary that bindings for uniforms, varyings or the attributes have to be sequential in vulkan?
Let say we have
layout (std140, set = 0, binding = 0) uniform ubo1 {}
layout (std140, set = 0, binding = 3) uniform ubo2 {}
is it allowed? same for the attribute bindings.?

Yes, this is allowed in shader code. Not so certain about implementations.
You can take a look at the documentation for VkDescriptorSetLayoutCreateInfo to get an idea of what is involved in defining a descriptor set layout. You'll notice that VkDescriptorSetLayoutBinding allows the specification of a binding at an arbitrary index.
As a matter of personal preference (and that I didn't find any explicit wording on the matter), I simply do not trust implementations to handle this intuitively. So, I create empty bindings to "fill in the gaps".

No, they don't have to be tightly packed. In the Descriptor Layout description (13.2.1), the spec says:
Bindings that are not specified have a descriptorCount and stageFlags of zero, and the descriptorType is treated as undefined. However, all binding numbers between 0 and the maximum binding number in the VkDescriptorSetLayoutCreateInfo::pBindings array may consume memory in the descriptor set layout even if not all descriptor bindings are used, though it should not consume additional memory from the descriptor pool.
Note: The maximum binding number specified should be as compact as possible to avoid wasted memory.

Related

Reuse vertex attribute buffer as index buffer?

Can I use a VBO which I initialise like this:
GLuint bufferID;
glGenBuffers(1,&BufferID);
glBindBuffer(GL_ARRAY_BUFFER,bufferID);
glBufferData(GL_ARRAY_BUFFER,nBytes,indexData,GL_DYNAMIC_DRAW);
as an index buffer, like this:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,bufferID);
/* ... set up vertex attributes, NOT using bufferID in the process ... */
glDrawElements(...);
I would like to use the buffer mostly as an attribute buffer and occasionally as an index buffer (but never at the same time).
There is nothing in the GL which prevents you from doing such things, your code above is legal GL. You can bind every buffer to every buffer binding target (you can even bind the same buffer to different targets at the same time, so it is even OK if attributes and index data come from the same buffer). However, the GL implementation might do some optimizations based on the observed behavior of the application, so you might end up with sub-optimal performance if you suddenly change the usage of an existing buffer object with such an approach, or use it for two things at once.
Update
The ARB_vertex_buffer_object extension spec, which introduced the concept of buffer objects to OpenGL, mentions this topic in the "Issues" section:
Should this extension include support for allowing vertex indices to be stored in buffer objects?
RESOLVED: YES. It is easily and cleanly added with just the
addition of a binding point for the index buffer object. Since
our approach of overloading pointers works for any pointer in GL,
no additional APIs need be defined, unlike in the various
*_element_array extensions.
Note that it is expected that implementations may have different
memory type requirements for efficient storage of indices and
vertices. For example, some systems may prefer indices in AGP
memory and vertices in video memory, or vice versa; or, on
systems where DMA of index data is not supported, index data must
be stored in (cacheable) system memory for acceptable
performance. As a result, applications are strongly urged to
put their models' vertex and index data in separate buffers, to
assist drivers in choosing the most efficient locations.
The reasoning that some implementations might prefer to keep index buffers in system RAM seems quite outdated, though.
While completely legal, it's sometimes discouraged to have attribute data and index data in the same buffer. I suspect that this is mostly based on a paragraph in the spec document (e.g. page 49 of the OpenGL 3.3 spec, at the end of the section "2.9.7 Array Indices in Buffer Objects"):
In some cases performance will be optimized by storing indices and array data in separate buffer objects, and by creating those buffer objects with the corresponding binding points.
While it seems plausible that it could be harmful to performance, I would be very interested to see benchmark results on actual platforms showing it. Attribute data and index data are used at the same time, and with the same access operations (CPU write, or blit from temporary storage, for filling the buffer with data, GPU read during rendering). So I can't think of a very good reason why they would need to be treated differently.
The only difference I can think of is that the index data is always read sequentially, while the attribute data is read out of order during indexed rendering. So it might be possible to apply different caching attributes for performance tuning the access in both cases.

How can I get automatic unique atomic counter binding points (no hard coded binding=)?

Many articles describe using atomic counters by specifying a fixed binding point:
//Shader:
layout(binding = 0, offset = 0) uniform atomic_uint myAtomicCounter;
//App code
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, myBufferHandle);
Here, the hard coded binding point binding = 0 is specified in both the shader and application code. I guess these articles do it this way because,
Atomic counters are not assigned a location and may not be
modified using the Uniform* commands. The bindings,
offsets, and strides belonging to atomic counters
of a program object are invalidated and new ones
assigned after each successful re-link. [shader_atomic_counters]
The above is fine until you want some more modular shader code. For example I have two shader include files, each needing an atomic counter that I've written as pluggable code that doesn't know about the other. Clearly I don't want to specify hard coded binding points and I'd like the application to handle it automatically. I don't really care which binding points they use, just that they aren't the same.
Vertex shader attributes appear similar. I can force a binding location at runtime (glBindAttribLocation) before shader linking or alternatively let OpenGL choose them for me and then query the result (glGetAttribLocation). I can also search through all attributes (glGetActiveAttrib).
How can I implement automatic unique binding points for atomic counters, so they're not hard coded and I can mix shader code?
I can see a few ways this might be possible, still with the limitation of not changing them after linking:
Don't specify the binding point in the shader and let OpenGL pick one when linking. I don't know if OpenGL will do this. If it does, how do you query to find the binding point used?
Query the shader objects before linking to find atomic counters. Then give them unique binding locations just like glBindAttribLocation for attributes. Is there a mechanism to assign binding points?
Parse all the shader code, looking for atomic counters and replace the binding points with unique indices in the shader code itself, perhaps using #define macros. A last resort. I really don't want to have to do this.
On point 1: The binding layout parameter for atomic counters is not optional.
On point 2: Because binding is not optional, there's no point in being able to set it from OpenGL code.
So your only recourse is #3.
You can query for atomic counters using glGetActiveUniform. Then get the buffer index and finally the binding point:
int atomicCounterIndex;
glGetActiveUniformsiv(programId, count, index,
GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX, &atomicCounterIndex);
glGetActiveAtomicCounterBufferiv(programId, atomicCounterIndex,
GL_ATOMIC_COUNTER_BUFFER_BINDING, &myBufferHandle)
This works since OpenGL 4.2 as stated in the docs

Why samplers cannot be part of uniform blocks in OpenGL, and any ways to get around it?

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.

Is it safe to use the block index as the binding point for UniformBufferObject, ShaderStorageBufferObjects, etc?

I'm curious about the *BlockBinding argument used in several of OpenGLs buffer object related functions.
For example the uniformBlockBinding parameter in glUniformBlockBinding, storageBlockBinding​ in glShaderStorageBlockBinding, and the corresponding index parameter in glBindBufferRange and glBindBufferBase.
I know that calls to glUniformBlockBinding and glShaderStorageBlockBinding aren't necessary if binding points are set in the shaders using layout qualifiers such as:
layout (binding = 0) blockName {...}
and from testing around on my machine I've noticed three things:
1) setting binding points with glUniformBlockBinding and glShaderStorageBlockBinding override binding points set in the shader using layout qualifiers.
2) block indices returned from glGetUniformBlockIndex and glGetProgramResourceIndex are ordered 0 to n for each block of the same type. For example if the shader contains 3 uniform blocks and 2 buffer blocks the indices returned would be [0,1,2] and [0,1] respectively.
3) binding points, set either way, do not conflict across types. For example, setting a uniform block to binding = 0 and a buffer block to binding = 0 is completely safe.
With these assumptions in mind (please correct me if any aren't necessarily true and are simply coincidence), are there any reasons why I shouldn't just have my code automatically set the *BlockBinding argument to the corresponding block index and save myself the trouble of ever specifying them manually via gl*BlockBinding or with layout qualifiers.
I once had the same question. After some exploration, and especially reading the authoritative source of information on GL: https://www.khronos.org/opengl/wiki/Uniform_Buffer_Object]
I'm pretty sure this is why the separation between block index and binding point.
Think of a GL render context as a port, and a glsl program object as a ship. The binding points are harbors of the port and block indices are doors to ship's storage compartments. A ship needs to dock at the port with one of its door aligned with a specific harbor to load cargo onto the ship (or the other way around). Similarly, a block index needs to be associated with a binding point for the data to be transferred between the shader's blocks and the context's buffers.
Due to this design, the block indices and binding points are independent entities. Therefore it's not safe to simply equating binding point to block index, as that may unintentionally overrides binding points (that may have been docked by other ships).
Your observations can be also explained:
The block indices and binding points start counting from 0 contiguously (as what you observed in (2)).
Each type of buffers (since they reside on the context) have a set of binding points that are separate from the other types (hence your observation 3).
As to your observation 1, yes, setting the association on the application side preempts the hard-coded binding in the shader.
With these assumptions in mind (please correct me if any aren't necessarily true and are simply coincidence), are there any reasons why I shouldn't just have my code automatically set the *BlockBinding argument to the corresponding block index and save myself the trouble of ever specifying them manually via gl*BlockBinding or with layout qualifiers.
Because that would be completely useless.
The block index is arbitrarily assigned to a particular block. One one platform, a particular block's index could be 0, while another sorts the names such that it's index 2. So your code will have to query the block indices for each block you plan to use.
Whereas if you specify what binding indices to use for a particular block, you don't have to query anything. Your code knows that binding index 0 is where your matrices go, binding index 1 is where your lighting data goes, etc.
What's worse is that you may have multiple shaders that use the same block. But they're highly unlikely to have the same block index. Whereas if you assign them a binding index, you can give them the same binding index. And therefore, you don't have to re-bind buffers between changes to such programs.

When should I use STD140 in OpenGL?

When do I use the STD140 for uniform blocks in OpenGL?
Although I am not a 100% sure, I believe there is an alternative to it which can achieve the same thing, called "Shared".
Is it just preference for the coder? Or are there reasons to use one over the other?
Uniform buffer objects are described in http://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt
The data storage for a uniform block can be declared to use one of three layouts in memory: packed, shared, or std140.
packed uniform blocks have an implementation-dependent data layout for efficiency, and unused uniforms may be eliminated by the compiler to save space.
shared uniform blocks, the default layout, have an implementation-dependent data layout for efficiency, but the layout will be uniquely determined by the structure of the block, allowing data storage to be shared across programs.
std140 uniform blocks have a standard cross-platform cross-vendor layout. Unused uniforms will not be eliminated.
The std140 uniform block layout, which guarantees specific packing behavior and does not require the application to query for offsets and strides. In this case, the minimum size may still be queried, even though it is determined in advance based only on the uniform block declaration. The offset of each uniform in a uniform block can be derived from the definition of the uniform block by applying the set of rules described in the OpenGL specification.
std140 is most useful when you have a uniform block that you update all at once, for example a collection of matrix and lighting values for rendering a scene. Declare the block with std140 in your shader(s), and you can replicate the memory layout in C with a struct. Instead of having to query and save the offsets for every individual value within the block from C, you can just glBufferData(GL_UNIFORM_BUFFER, sizeof(my_struct), &my_struct, with one call.
You do need to be a little careful with alignment in C, for instance, a vec3 will take up 4 floats, not 3, but it is still much easier IMHO.