# Spliting up VAOs?

At the moment I have one vertex/fragment shader, but I am looking to add another shader program to deal with shadow maps. In my "final" shader I have VAO which define positions, normals, texcoords, tangents, bitangents, etc and in my shadow map shader I only need the positions...

Final pass shader:

layout(location = 0) in vec3 vert_position;                                             \n \
layout(location = 1) in vec3 vert_normal;                                               \n \
layout(location = 2) in vec2 vert_texcoord;                                             \n \
layout(location = 3) in vec3 vert_tangent;                                              \n \
layout(location = 4) in vec3 vert_bitangent;                                            \n \


Shadow map shader:

layout(location = 0) in vec3 vert_position;                                             \n \


Code for creating VAOs

OpenGLRenderer::VAO SetupVAO(OpenGLMeshPtr mesh)
{
OpenGLRenderer::VAO vao;

GLCALL(glGenVertexArrays(1, &vao));

GLCALL(glBindVertexArray(vao));
GLCALL(glBindBuffer(GL_ARRAY_BUFFER, mesh->mVBO));
GLCALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->mIndexBuffer));

GLCALL(glEnableVertexAttribArray(0));
GLCALL(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0));
GLCALL(glEnableVertexAttribArray(1));
GLCALL(glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(mesh->mVertexDataSize)));
GLCALL(glEnableVertexAttribArray(2));
GLCALL(glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(mesh->mVertexDataSize + mesh->mNormalDataSize)));
GLCALL(glEnableVertexAttribArray(3));
GLCALL(glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(mesh->mVertexDataSize + mesh->mNormalDataSize + mesh->mTexCoordsSize)));
GLCALL(glEnableVertexAttribArray(4));
GLCALL(glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(mesh->mVertexDataSize + mesh->mNormalDataSize + mesh->mTexCoordsSize + mesh->mTangentsSize)));

GLCALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
GLCALL(glBindVertexArray(0));

return vao;
}


Thus my question is - should I create two VAOs per mesh, one for the shadow map and one for the final pass, or should I use the same VAO in both shaders, leaving all but position parameters unused but avoid creating/binding a new VAO? Does it have any implications doing so?

Thanks

EDIT: In short, is it detrimental to performance to supply the 5 attribute indices and their data to my shadowmap shader but only use the positions?

• Last time I tested your option 2 it crashed on AMD; that may be fixed in more recent drivers but it's always worth considering as a crash case will pretty much make your decision for you. – Maximus Minimus Nov 13 '13 at 22:38
• So glEnableVertexAttribArray on indices not present in shader causes a crash when executing the shader? – KaiserJohaan Nov 14 '13 at 9:14
• Can you measure the performance difference? – ThorinII Nov 14 '13 at 9:24
• @KaiserJohaan - just to clarify, this didn't happen on all hardware, just AMD graphics, and it may have been fixed in more recent drivers. – Maximus Minimus Nov 14 '13 at 9:56
• @ Jimmy Shelter - That's interesting. I just tested making a (valid) call to glEnableVertexAttribArray and glVertexAttribPointer using an index unassigned in the shader and it at least doesn't crash on my Notebook's ATI GPU (running on legacy drivers). I also don't remember any crashes on my newer desktop AMD GPU and I have tendency to use shaders that don't match my VAOs during debugging. Can you maybe elaborate on which AMD card you used? I'm always on the hunt for AMD related bugs, since I mostly use those AMD hardware :) – Invor Nov 14 '13 at 11:12

## 1 Answer

With regard to the VAOs, it's quite possible that the driver will internally disable attributes that aren't used by the vertex shader, so it may or may not make any difference. The only way to tell is to measure it using timer queries.

Another thing you might consider is splitting the VBOs as well, to put positions all in one VBO (packed tightly together) and all the other attributes in a second VBO (interleaved). This improves cache locality when fetching the positions in the shadow pass, which can improve performance since shadow rendering is often vertex-bound. Again, YMMV and you'll have to measure to see if you got any perf gain by doing this.