opengl memory leak + high cpu usage

Started by
5 comments, last by Vortez 12 years, 5 months ago
Greetings.
I am currently learning opengl with c++ and are tasked with making an application that displays more than 30k polys at screen.
The vertices and faces information are retrieved from text files.
I've no problem displaying them on screen, however the program consumes a lot of memory and cpu usage when I look at task manager.

Here is my display method :


static void
display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPushMatrix();

glTranslatef(0, -1, 0);
glScalef(sX, sY, sZ);

if(rY > 179)
rY = -180;
if (rY < -180)
rY = 179;

glRotatef(rX,1,0,0);
glRotatef(rY,0,1,0);
glRotatef(rZ,0,0,1);

if (wireframe == false)
{
for(int i=0;i<nFace;i++)
{
glColor4f(cA, cB, cC, 0.75f);
glNormal3f(norm.a, norm.b, norm.c);
glBegin(GL_POLYGON);
glVertex3f(vert[face.A].x, vert[face.A].y,vert[face.A].z) ;
glVertex3f(vert[face.B].x, vert[face.B].y,vert[face.B].z) ;
glVertex3f(vert[face.C].x, vert[face.C].y,vert[face.C].z) ;
glEnd();
}
}
else
{
for(int i=0;i<nFace;i++)
{
glColor3d(cA, cB, cC);
glBegin(GL_LINE_LOOP);
glVertex3f(vert[face.A].x, vert[face.A].y,vert[face.A].z) ;
glVertex3f(vert[face.B].x, vert[face.B].y,vert[face.B].z) ;
glVertex3f(vert[face.C].x, vert[face.C].y,vert[face.C].z) ;
glEnd();
}
}

glPopMatrix();

glutSwapBuffers();
/*delete [] vert;
delete [] face;
delete [] norm;*/
}


I don't think it's normal for the cpu to reach almost 100% usage all the time.
The fps took a dip after I applied a few transformation. I noticed this even when I'm drawing only about 100 polys.

About the memory leak, I thought it may be because of this?



/* Object declarations */
myVertex* vert = NULL;
myFace* face = NULL;
myNormals* norm = NULL;
/* --------------------- */

...


void getVertex()
{
float x,y,z;
int count=0;

ifstream myfile (dir1);

if (myfile.is_open())
{
while ( myfile.good() )
{
myfile >> x >> y >> z;
count++;
}
}

/* Dynamic array of vert declaration */
vert = new myVertex[count];

for (int i=0; i<count; i++)
{
vert.x = 0;
vert.y = 0;
vert.z = 0;
}
/* --------------------- */

myfile.clear(); // clear fstream buffer
myfile.seekg(0); // return to first character
count=0;
int g = 0;

if (myfile.is_open())
{
while ( myfile.good() )
{
myfile >> x >> y >> z;
vert[count].x = x;
vert[count].y = y;
vert[count].z = z;
vert[count].g = g;
count++;
}

myfile.close();
nVert = count;
}
else
{
cout << "Vertex file not found in specified directory.\n\n";
system("PAUSE");
exit(0);
}
}


I made it like that because the text files doesn't include how many vertices and faces are there, so I have to calculate them first.
I don't really know, I'm not that experienced with c++. Is there a better way to this?

I tried to free the memory like this


delete [] vert;
delete [] face;
delete [] norm;


but I don't really have the idea of where to actually put it.

If anyone of you wanted to look at the whole code, feel free to ask and I will upload them.
Kindly help me with this. I would be very grateful if you were to.
Live by your actions, die by its consequences.
Advertisement
Hi,

First of all, you should not call glBegin and glEnd for every polygon, as they are triangles. You should call glBegin with GL_TRIANGLE_LIST before the loop and glEnd after. You could look at glDrawElements to improve the performance even more, as you are drawing indexed triangles.

About the memory, what makes you think you have a leak? The memory usage is always growing? If you're not calling getVertex more than one time during your program execution, it should not leak.

And for the 100% CPU usage, I think it's normal if you're not in sync with the vBlank and drawing all the frames as fast as the CPU can.
Well if your using immediate mode it's sure gonna be slow as hell, take a look at VBOs on nehe. For the memory, just allocate the buffers when you load the file, the delete them when you no longer need them, it can be anywhere you want, for example, just before closing the application.

Also, what's that?

static void
display(void)

you dont need to put void in there if there's nothing to pass to the function. And for the static void, i have no idea what this is.

Also, what's that?

static void
display(void)

you dont need to put void in there if there's nothing to pass to the function.

In C (as opposed to C++), you do in fact need to put the void there, to declare that your function takes no arguments. Presumably this is why the OP did so, although it is unnecessary in C++.

And for the static void, i have no idea what this is.[/quote]
Void is the return type of the function, that much should be obvious.

Static when applied to functions outside of a class (a 'free' function), causes the function to be visible only to other functions within the same file - this is a hold over from C, and not terribly useful. The equivalent C++ technique would be to place the function within an anonymous namespace.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]


First of all, you should not call glBegin and glEnd for every polygon, as they are triangles. You should call glBegin with GL_TRIANGLE_LIST before the loop and glEnd after.

The correct token is GL_TRIANGLES, not [s]GL_TRIANGLE_LIST[/s].

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]


Hi,

First of all, you should not call glBegin and glEnd for every polygon, as they are triangles. You should call glBegin with GL_TRIANGLE_LIST before the loop and glEnd after. You could look at glDrawElements to improve the performance even more, as you are drawing indexed triangles.

About the memory, what makes you think you have a leak? The memory usage is always growing? If you're not calling getVertex more than one time during your program execution, it should not leak.

And for the 100% CPU usage, I think it's normal if you're not in sync with the vBlank and drawing all the frames as fast as the CPU can.


Ok I've put the glBegin/End outside of the loop and performance is greatly increased and usage are halved. biggrin.gif

About the memory leak, I think it's one because after running the code windows notify me that it cannot access a certain address in the memory and then windows gets very sluggish after that. *Edit : Oh and I also have another function getFace() that is similar to getVertex(). So that might also be the problem?



Well if your using immediate mode it's sure gonna be slow as hell, take a look at VBOs on nehe. For the memory, just allocate the buffers when you load the file, the delete them when you no longer need them, it can be anywhere you want, for example, just before closing the application.

Also, what's that?

static void
display(void)

you dont need to put void in there if there's nothing to pass to the function. And for the static void, i have no idea what this is.


I don't know about VBOs and so I googled it. Seems like it puts the stress to the GPU instead of CPU? Or is it something else? Ok now I've put the delete code just before exiting.
I fixed the display(void), thanks for pointing that out. About the static void, I cannot explain. Both are leftovers from a code template that I used.



[quote name='Faelenor' timestamp='1321986313' post='4886633']
First of all, you should not call glBegin and glEnd for every polygon, as they are triangles. You should call glBegin with GL_TRIANGLE_LIST before the loop and glEnd after.

The correct token is GL_TRIANGLES, not [s]GL_TRIANGLE_LIST[/s].
[/quote]

Thanks.

You've all been a great help biggrin.gif. I really appreciate it.


One more question if I may, how do you actually calculate FPSs? This is what I have in mind;


finish = clock() ;
duration += (double)(finish - start) / CLOCKS_PER_SEC ;
frames ++ ;
FPS = frames / duration ;
start = clock() ;


it's modified from someone else's code on the Net. I don't really get the idea of how to check whether one second has passed before I display the FPS, and how to display the FPS count only for that one second.
Live by your actions, die by its consequences.
@Swiftcoder: Thx for the static explanation, but the op said he was working in c++ that's why i said this code was useless.

@Ikazrima: Well you can use vertex array in 2 different way, the easier way is to simply put alls vertices in an array like you did, then call glDrawArrays or glDrawElements (Since you don't have an index array you should use glDrawArrays). What it does is that it send every vertices at once to the GPU instead of 1 by 1, increasing performance. VBO is used to store those vertices in the gpu memory instead of ram, so it's even more faster when rendering. There's a nice tutorial here.

As for the fps question, you could use my Timer class, with build in fps counter, or look how it's done:


#ifndef CTIMER_H
#define CTIMER_H

#pragma comment(lib, "winmm.lib")

#include <Windows.h>

class EXP_FUNC CTimer
{
private:
bool m_PerfCounterAvailable;
float m_TimeScale;
__int64 m_PerfCounterFrequency;

__int64 m_LastTime;
__int64 m_CurrentTime;

float m_FPS;
float m_FPS_ElapsedTime;

public:
CTimer();
float g_ElapsedTime; // Holds the elapsed time (StartTime - CurrentTime)

void Reset(); // Reset The timer
void Tick(); // Count how many time has pass since the last Tick() call

float GetFPS();
};

#endif //--CTIMER_H



#include "Timer.h"

CTimer::CTimer()
{
//Check if a High resolution timer is available
if(QueryPerformanceFrequency((LARGE_INTEGER *)&m_PerfCounterFrequency)){
m_PerfCounterAvailable = true;
QueryPerformanceCounter((LARGE_INTEGER *) &m_CurrentTime);
m_TimeScale = 1.0f / m_PerfCounterFrequency;
} else { // no performance counter, read in using timeGetTime
m_PerfCounterAvailable = false;
m_CurrentTime = timeGetTime();
m_TimeScale = 0.001f;
}

Reset();
}


void CTimer::Reset()
{
// Is performance hardware available?
if(m_PerfCounterAvailable){
// Query high-resolution performance hardware
QueryPerformanceCounter((LARGE_INTEGER *)&m_CurrentTime);
} else {
// Fall back to less accurate timer
m_CurrentTime = timeGetTime();
}

// Initialization
m_LastTime = m_CurrentTime;
g_ElapsedTime = 0.0f;

m_FPS = 0;
m_FPS_ElapsedTime = 0.0f;
}


void CTimer::Tick()
{
// This will be used to compare how many time has pass since the last Tick()
m_LastTime = m_CurrentTime;

// Is performance hardware available?
if(m_PerfCounterAvailable){
// Query high-resolution performance hardware
QueryPerformanceCounter((LARGE_INTEGER *)&m_CurrentTime);
} else {
// Fall back to less accurate timer
m_CurrentTime = timeGetTime();
}

// Calculate the elapsed time
g_ElapsedTime = (m_CurrentTime - m_LastTime) * m_TimeScale;

// Calculate the elapsed time for our fps
static int Frame = 0;
Frame++;
m_FPS_ElapsedTime += g_ElapsedTime;
if(m_FPS_ElapsedTime >= 1.0f){
m_FPS = (float)Frame / m_FPS_ElapsedTime;
Frame = 0;
while(m_FPS_ElapsedTime >= 1.0f)
m_FPS_ElapsedTime -= 1.0f;
}
}

float CTimer::GetFPS()
{
return m_FPS;
}


All you have to do is call Reset() once, when initializing your program, then call Tick() every frame you render, followed by GetFPS(), which return the fps in a float for more accuracy than simple integer.

This topic is closed to new replies.

Advertisement