[Mesa-users] glDrawElements much slower than glDrawArrays
Russell Strong
russell at strong.id.au
Wed Dec 26 20:09:21 PST 2012
Hi,
As a learning exercise I'm rendering a uv sphere with glDrawArrays using buffer
objects, I then change this over to glDrawElements with indices 0,1,2,...n also
in a buffer object. What I found was that the glDrawElements version was
consuming 16% cpu compared with 4% for glDrawArrays.
I've looked around and can't seem to find any reason why it would be slower.
Both "should" be storing everything in the gpu's ram as far as I can see, but I
suspect the draw elements version is not.
I'm using an older version of mesa 7.11.2 ( Fedora 16 ) intel driver, anyone
remember any problems with glDrawElements then?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include "shader.h"
GLuint prog, vbo, ibo;
GLint attrib_vertex, attrib_colour;
#define SLICES 80
#define STACKS 40
#define GL_DRAW_ELEMENTS 0
struct sphere_vertex {
GLfloat x,y,z;
GLfloat r,g,b;
};
GLfloat colours[18] = {
1,0,0,
0,1,0,
0,0,1,
1,1,0,
1,0,1,
0,1,1,
};
int colour_idx = 0;
void sphere(float radius, int slices, int stacks)
{
int i = 0;
int n = 2 * (slices + 1) * stacks;
GLuint indices[n];
struct sphere_vertex points[n];
float theta, phi;
for (theta = -M_PI / 2; theta < M_PI / 2 - 0.0001; theta += M_PI / stacks) {
for (phi = -M_PI; phi <= M_PI + 0.0001; phi += 2 * M_PI / slices) {
points[i].x = cos(theta) * sin(phi) * radius;
points[i].y = -sin(theta) * radius;
points[i].z = cos(theta) * cos(phi) * radius;
points[i].r = colours[colour_idx];
points[i].g = colours[colour_idx+1];
points[i].b = colours[colour_idx+2];
colour_idx = (colour_idx + 3) % 18;
i++;
points[i].x = cos(theta + M_PI / stacks) * sin(phi) * radius;
points[i].y = -sin(theta + M_PI / stacks) * radius;
points[i].z = cos(theta + M_PI / stacks) * cos(phi) * radius;
points[i].r = colours[colour_idx];
points[i].g = colours[colour_idx+1];
points[i].b = colours[colour_idx+2];
colour_idx = (colour_idx + 3) % 18;
i++;
}
}
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
for(i=0;i<n;i++)
indices[i]=i;
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
}
void setup()
{
prog = create_program("test.v", "test.f", NULL);
glEnableClientState(GL_VERTEX_ARRAY);
sphere(0.8, SLICES, STACKS);
attrib_vertex = glGetAttribLocation(prog, "vertex");
attrib_colour = glGetAttribLocation(prog, "colour");
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
// Wire frame
//glPolygonMode(GL_FRONT, GL_LINE);
//glPolygonMode(GL_BACK, GL_POINT);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glUseProgram(prog);
glEnableVertexAttribArray(attrib_vertex);
glEnableVertexAttribArray(attrib_colour);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glVertexAttribPointer(
attrib_vertex, // attribute
3, // elements per vertex (x,y,z)
GL_FLOAT, // type of each element
GL_FALSE, // take our value as-is
6*sizeof(GLfloat), // next x,y,z appears every 6 floats
(GLvoid *)0 // offset of first element
);
glVertexAttribPointer(
attrib_colour, // attribute
3, // elements per colour (r,g,b)
GL_FLOAT, // type of each element
GL_FALSE, // take our value as-is
6*sizeof(GLfloat), // next r,g,b appears every 6 floats
(GLvoid *)(3*sizeof(GLfloat)) // offset of first element
);
}
void render(void)
{
int i, num_in_slice = 2*(SLICES+1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glRotatef(0.4,1,0,0);
for(i=1;i<STACKS-1;i++)
#if GL_DRAW_ELEMENTS
glDrawElements(GL_TRIANGLE_STRIP, num_in_slice, GL_UNSIGNED_INT, (GLvoid
*)(i*sizeof(GLuint)*num_in_slice));
#else
glDrawArrays(GL_TRIANGLE_STRIP, i*num_in_slice, num_in_slice);
#endif
glutSwapBuffers();
}
void timer(int data)
{
render();
glutTimerFunc(10,timer,0);
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(320,320);
glutCreateWindow("Window");
glutDisplayFunc(render);
glutTimerFunc(10, timer, 0);
setup();
glutMainLoop();
return 0;
}
More information about the mesa-users
mailing list