Should I disable a vertex attrib array if a program doesn't use it?

Hi everyone,

If I had an application where each drawable entity is associated with a VAO where all the vertex attrib arrays I’ll ever need in my application are enabled: positions, normals, tex coords, colors, tangents, … (is it a good idea?).
An entity could be drawn with different shaders, some of which will only use a subset of all the vertex attributes the VAOs are configured to provide from vertex arrays.

Should I glEnable/DisableVertexAttribArray depending on the program being used? Is there a performance penalty if I don’t disable arrays that are not required by the program or will OpenGL understand that an attribute is not required by looking at the program input signature?

Enabled means you’re going to provide an array for the GPU/driver to pull vertex attribute data from during draw calls.
If you were going to pull from a constant vertex attribute value instead (for that attribute), you’d disable the array.

I would think there’d be a stability penalty, with the GPU/driver going off and pulling from data pointers you hadn’t setup properly.

As far as looking at the program input signature, the driver’s shader compiler/linker will likely not include code that references a declared vertex attr if it’s not used to produce outputs for the compiled-and-linked shader program. But you have no guarantees as to whether vertex attr fetch is handled by the shader or functionality outside the shader that knows nothing about the shader. In most cases, the “prep for fetch” logic is likely not handled “in” the shader, and that code might not know anything about your shader.

I say “most” here because, at least with NVIDIA bindless buffers vertex array access, the app can grease-the-skids and get the array pretty near 100% ready for the GPU to pull from. At draw time, you just pass in a GPU address, and it works. But even then, if you don’t want the vertex attr array pull, you disable it.

But all the pointers are set up correctly, it’s just that some attributes are not required. Let’s say the current VAO has attributes A, B, and C enabled and for all 3 a call to glVertexAttribPointer has been made. The program I’m using, however, requires only attribute A.

I wondered if there was a performance penalty if I didn’t disable attribs B and C in this scenario, assuming the more attributes need to be fetched from arrays the more work someone (the driver?) needs to do, or if that additional work for attributes B and C would be skipped anyway since one could know that those attributes are not required for the program in use for a draw call.

Blockquote
In most cases, the “prep for fetch” logic is likely not handled “in” the shader, and that code might not know anything about your shader.

I guess this is the answer to that question?

That kind of depends. First, what is the buffer relationship involved here?

If A, B, and C are all interleaved, then the really expensive part (fetching from memory) is going to be done regardless of how much of A, B, and/or C get used, since they’re interleaved.

If these are separate, then now it depends on what hardware you’re using. Hardware with dedicated vertex fetching logic will generally follow what your VAO says. Hardware that does vertex fetching in the vertex shader (which these days seems to be, on desktop platforms, everyone not-NVIDIA) will probably follow what your vertex shader actually uses, since it has to effectively compile the VAO into the vertex shader when you render with it.

Personally, unless I had actual profiling data that said otherwise, I wouldn’t bother to disable them. Modifying vertex format state is something that most implementations hate to do; it’s a substantial state change the forces the driver to do a lot of work.

1 Like