tags:

views:

73

answers:

2

I'm really not sure what to do anymore. I'v made my application use VBO's and my cpu usage still goes into the 70's and 80's. My render proceedure works like this:

Set the camera transformation if the shape has not been tesselated, tesselate it. create it's VBO if it has a VBO, use it.

You will notice I have display lists too, I might use these if VBO is not supported. I went and found an OpenGL demo that renders a 32000 poly mesh at 60fps on my PC and uses 4% cpu. I'm rendering about 10,000 polys @ 60fps using vbos and its using 70-80%.

Here is my render proc:

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        POINT hh = controls.MainGlFrame.GetMousePos();
        POINTFLOAT S;
        S.x = static_cast<float>(hh.x);
        S.y = static_cast<float>(hh.y);
        POINTFLOAT t;
        t.x = 256;
        t.y = 256;
        POINT dimensions;
        dimensions.x = 512;
        dimensions.y = 512;
        glDeleteTextures(1,&texName);
        texName = functions.CreateGradient(col,t,S,512,512,true);

        itt = true;
    }
    HDC hdc;
    PAINTSTRUCT ps; 
    glEnable(GL_MULTISAMPLE_ARB);
    glEnable(GL_BLEND);

    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    hdc = BeginPaint(controls.MainGlContext.mhWnd,&ps);

    //start OGL code
    glClearColor( 1.0f, 1.0f, 1.0f, 0.0f );
    if(!current.isdrawing)
    glClear( GL_COLOR_BUFFER_BIT );

    glPushMatrix();
    glTranslatef(controls.MainGlFrame.GetCameraX(),
    controls.MainGlFrame.GetCameraY(),0);
    //glTranslatef(current.ScalePoint.x,current.ScalePoint.y,0);


    glScalef(current.ScaleFactor,current.ScaleFactor,current.ScaleFactor);
    //glTranslatef(-current.ScalePoint.x,-current.ScalePoint.y,0);


    if(!current.isdrawing)
    {
        for(unsigned int currentlayer = 0; currentlayer < layer.size(); ++currentlayer)
        {
            PolygonTesselator.Init(); 
            for(unsigned int i = 0; i < layer[currentlayer].Shapes.size(); i++)
            {
                if(layer[currentlayer].Shapes[i].DisplayListInt == -999)
                {
                    gluTessNormal(PolygonTesselator.tobj, 0, 0, 1);
                    PolygonTesselator.Set_Winding_Rule(layer[currentlayer].Shapes[i].WindingRule); 
                    glEnable(GL_TEXTURE_2D);
                    glBindTexture(GL_TEXTURE_2D, texName);

                    layer[currentlayer].Shapes[i].DisplayListInt = glGenLists(1);
                    glNewList(layer[currentlayer].Shapes[i].DisplayListInt,GL_COMPILE);

                    PolygonTesselator.SetDimensions(layer[currentlayer].Shapes[i].Dimensions,layer[currentlayer].Shapes[i].minima);
                    PolygonTesselator.Begin_Polygon(); 
                    for(unsigned int c = 0; c < layer[currentlayer].Shapes[i].Contour.size(); ++c)
                    {
                        if(layer[currentlayer].Shapes[i].Color.a != 0)
                        {
                            PolygonTesselator.Begin_Contour();

                            for(unsigned int j = 0; j < layer[currentlayer].Shapes[i].Contour[c].DrawingPoints.size(); ++j)
                            {
                                gluTessVertex(PolygonTesselator.tobj,&layer[currentlayer].Shapes[i].Contour[c].DrawingPoints[j][0],
                                    &layer[currentlayer].Shapes[i].Contour[c].DrawingPoints[j][0]);
                            }

                            PolygonTesselator.End_Contour();
                        }
                    }
                    PolygonTesselator.End_Polygon();
                    glEndList();
                    PolygonTesselator.TransferVerticies(layer[currentlayer].Shapes[i].OutPoints);
                    glGenBuffersARB(1,&layer[currentlayer].Shapes[i].VBOInt);
                    glBindBufferARB(GL_ARRAY_BUFFER_ARB,layer[currentlayer].Shapes[i].VBOInt);
                    glBufferDataARB(GL_ARRAY_BUFFER_ARB,sizeof(GLfloat) * layer[currentlayer].Shapes[i].OutPoints.size(),
                        &layer[currentlayer].Shapes[i].OutPoints[0], GL_STATIC_DRAW_ARB);

                    InvalidateRect(controls.MainGlFrame.framehWnd,NULL,false);
                }
                else //run vbo
                {
                    //glEnable(GL_TEXTURE_2D);
                    //glDisable(GL_TEXTURE_2D);
                    //glBindTexture(GL_TEXTURE_2D, texName);
                    glColor4f(layer[currentlayer].Shapes[i].Color.r,
                    layer[currentlayer].Shapes[i].Color.g,
                    layer[currentlayer].Shapes[i].Color.b,
                    layer[currentlayer].Shapes[i].Color.a);
                    //glColor4f(1,1,1,1);

                    glBindBufferARB(GL_ARRAY_BUFFER_ARB, layer[currentlayer].Shapes[i].VBOInt);     
                    //glCallList(layer[currentlayer].Shapes[i].DisplayListInt);
                    glEnableClientState(GL_VERTEX_ARRAY);
                    glVertexPointer(2, GL_FLOAT, 0, 0);
                    glDrawArrays(GL_TRIANGLES, 0, layer[currentlayer].Shapes[i].OutPoints.size() / 2);

                    glDisableClientState(GL_VERTEX_ARRAY);
                    glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
                }

                glDisable(GL_TEXTURE_2D);
                //Draw outlines
                if(layer[currentlayer].Shapes[i].Outline.OutlinePoints.size() > 4)
                {
                    glColor4f(layer[currentlayer].Shapes[i].Outline.OutlineColor.r
                        ,layer[currentlayer].Shapes[i].Outline.OutlineColor.g
                        ,layer[currentlayer].Shapes[i].Outline.OutlineColor.b
                        ,layer[currentlayer].Shapes[i].Outline.OutlineColor.a);
                }

            }
            PolygonTesselator.End();
        }
    }

    glPopMatrix();

    //end OGL code
    glFlush();
    SwapBuffers(hdc);

    glDisable(GL_MULTISAMPLE_ARB);
    EndPaint(controls.MainGlContext.mhWnd,&ps);

}

Why could I be getting such high cpu usage?

Thanks

A: 

Based on the code snippet you have provided, you have (at one point) loops nested four layers deep. You may be seeing high CPU load due to running each of these loops an extremely large number of times. Can you give us any idea how many iterations these loops are having to run through?

Try grabbing a timestamp inside each loop iteration and compare it against the previous to see how long it is taking to run one iteration of each particular loop. This should help you determine what part of the function is taking up the bulk of your CPU time.

bta
Well I removed all those loops and just clearing and swapping gets me up to about 30%.
Milo
Adding Sleep(1) took care of the SwapBuffers issue but with shapes its still a bottleneck
Milo
How many shapes are you trying to use? What happens if you adjust the number of shapes? Does the CPU usage scale with the number of shapes?
bta
it stays around 3-4% then all of a sudden jumps to 30% and never looks back after maybe 15 or so shapes. As a test I created 1 big 30,000 triagle shape and it lagged a lot yet NeHe got 32000 with no lag. Could it be because these are 2D shapes and i'm not using the depth test?
Milo
I would recommend timing the amount of time it takes to run one iteration of your second loop (the one that loops through all shapes in the current layer). See how the time changes between, say, 5/10/15/20 shapes. When you see the CPU usage spike, start narrowing looking inside the loop and timing sections of the code to see what part is taking the longest to run.
bta
A: 

Under what conditions is that first bit of code run? There's a couple of suspicious-looking lines in there:

glDeleteTextures(1,&texName);
texName = functions.CreateGradient(col,t,S,512,512,true);

If you're deleting and recreating a texture every time you paint, that could get expensive. I couldn't say how expensive the OpenGL parts would be -- I'd expect uploading texture data to be reasonably efficient, even if deleting and creating texture names might be less so -- but perhaps CreateGradient is inherently slow. Or maybe you're accidentally hitting some kind of slow path for your graphics card. Or the function is creating all the mipmap levels. And so on.

Aside from that, some random ideas:

  • What is the present interval? If the buffer swap is set to sync with the monitor, you may incur a delay because of that. (You can use the WGL_EXT_swap_control extension to tweak this value.)

  • If all of this is being run in response to a WM_PAINT, check that you aren't getting unexpected extra WM_PAINTs for some reason.

  • Check that the polygon tesselator Init and End functions aren't doing anything, since they're being called every time, even if there's no tesselating to be done.

brone
The texture is only a test, this only runs once. I fixed the Init and end issue, I'm using wgl_ext_swap_control already, and it does a wm paint when I scroll. with 2-3 polygons its very fast but adding more gets exponentially slow ans NeHe renders 32k polys @ 60fps using 2-3% cpu so im puzzled
Milo