0
\$\begingroup\$

I was running visual studio's CPU profiling tool when I noticed that of my RenderScene call, my skybox was taking up 30% of the frame time.

Skybox takes a lot of ms

This is particularly weird, as as you can see the Object3D::draw call is much less, and I have just one Skybox and 35 Object3Ds.

I went in further and found that glBindVertexArray was taking all of the time. What could be causing this? The VAO in question is defined here:

    glGenVertexArrays(1, &thisVAO);
glBindVertexArray(thisVAO);

//Setup the Vertex buffer
glGenBuffers(1, &vertsVBO);
glBindBuffer(GL_ARRAY_BUFFER, vertsVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*36, skyboxVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0);
glEnableVertexAttribArray(0);

and the Skybox Draw call here:

//Shader uniform setting....
    glUseProgram(thisConfig.skyboxShaders->getProgramID());
// ... set view and projection matrix

thisConfig.skyboxShaders->setMats(rs->angle, thisConfig.currLighting->persp);

thisConfig.skyboxShaders->setClipPlane(rs->clipPlane, rs->useClipPlane);

//Actually draw the skybox
glBindVertexArray(thisVAO);

glActiveTexture(GL_TEXTURE0);

glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);

glDrawArrays(GL_TRIANGLES, 0, 36);

Here is visual studio's take on the draw call:

breakdown

VAOs for Object3D have 5 VBOs and an elements buffer, as opposed to skybox's one VBO, and skyboxVerticies has 96 entries in it for 36 verticies. Most meshes for object3Ds are 1000+ verticies plus, and the Terrain has 48,000. Anything obvious I am missing? The vertex co-ordinates are very large, would that affect the call time for glBindVertexArray()?

Edit : skybox shader

#version 330 core
layout (location = 0) in vec3 aPos;

out of TexCoords;

uniform mat4 projection;
uniform mat4 view;
uniform vec4 clipPlane; // The Plane Clipping
uniform int usePlane; // PLane bool

void main ()
{
    TexCoords = aPos;
    gl_Position = view * vec4 (aPos, 1.0);
}  

Edit : Changing the order has changed things completely, It appears the first glBindVertexArray() per frame has significant overhead (30% of each frame), regardless of shader or vertex array size. Why is this? How can I fix it?

\$\endgroup\$
  • \$\begingroup\$ Whats your frame time? 30% could mean anything. The driver might need to flush some draw calls before new state changes and commands can be buffered or your profiler was just unlucky. \$\endgroup\$ – tkausl Feb 23 at 1:56
  • \$\begingroup\$ About 10ms per frame, varies a little depending on what physics is doing. And it does this consistently \$\endgroup\$ – Will Hain Feb 23 at 2:03
  • \$\begingroup\$ How simple is the skybox shader? \$\endgroup\$ – HolyBlackCat Feb 23 at 9:03
  • \$\begingroup\$ Added the skybox vertex shader to question. Fragment shader is literally 3 lines \$\endgroup\$ – Will Hain Feb 23 at 15:13
1
\$\begingroup\$

Could just be some flush that gets triggered.

What happens if you switch the order or drawing? First drawing sky then objects, versus first the objects and then the sky?

Also, what does the fragment shader look like for the sky? Maybe it takes a lot of texture samples? Are the objects textured as well?

Last, the skybox covers a lot of pixels, so the fragment shader will be busier than the fragment shader of an object that is small on screen.

\$\endgroup\$
  • \$\begingroup\$ I'm not home right now so I can't get code, but the fragshader takes one sample, and even if it was complex, surely glDrawArrays would be the method hit in performance, not glBindVertexArray()? I'll try change the order when I'm home. Also every object is textured, all object3Ds have 3 textures and the terrain has 12. The skybox has 1 texture, but is the only Cubemap texture. But again, don't think these things will affect the time for glBindVertexArray() \$\endgroup\$ – Will Hain Feb 24 at 19:22
  • \$\begingroup\$ Editted question as changing the order has changed things considerably \$\endgroup\$ – Will Hain Feb 24 at 21:29
  • \$\begingroup\$ @WillHain: the problem is that GL (and D3D) lie to you. :) When you compile a shader or create a VAO or whatnot, the driver isn't actually doing (all of) that work. It delays as much of it as possible to the point of first use. This is for a number of reasons, mostly all boiling down to the fact the older graphics APIs don't at all reflect how hardware actually works, so your API calls can't be executed immediately. This is a good part of the reason for Vulkan and D3D12, and though those APIs also still lie to you they at least do less of it. :) \$\endgroup\$ – Sean Middleditch Feb 24 at 22:52
  • \$\begingroup\$ Ah. Well that does suck. I'd still like to reduce the time it takes from me ;) maybe I should just move to vulkan... \$\endgroup\$ – Will Hain Feb 25 at 13:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.