Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


opengl memory leak + high cpu usage


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
6 replies to this topic

#1 Ikazrima   Members   -  Reputation: 122

Like
0Likes
Like

Posted 22 November 2011 - 10:43 AM

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[i].a, norm[i].b, norm[i].c);
          glBegin(GL_POLYGON);
 			glVertex3f(vert[face[i].A].x, vert[face[i].A].y,vert[face[i].A].z) ; 
 			glVertex3f(vert[face[i].B].x, vert[face[i].B].y,vert[face[i].B].z) ;
 			glVertex3f(vert[face[i].C].x, vert[face[i].C].y,vert[face[i].C].z) ;
          glEnd();
        }
    }
    else 
    {  
        for(int i=0;i<nFace;i++)    
        {
          glColor3d(cA, cB, cC);
          glBegin(GL_LINE_LOOP);
 			glVertex3f(vert[face[i].A].x, vert[face[i].A].y,vert[face[i].A].z) ; 
 			glVertex3f(vert[face[i].B].x, vert[face[i].B].y,vert[face[i].B].z) ;
 			glVertex3f(vert[face[i].C].x, vert[face[i].C].y,vert[face[i].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[i].x = 0;
          vert[i].y = 0;
          vert[i].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.

Sponsor:

#2 Faelenor   Members   -  Reputation: 396

Like
2Likes
Like

Posted 22 November 2011 - 12:25 PM

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.

#3 Vortez   Crossbones+   -  Reputation: 2705

Like
1Likes
Like

Posted 22 November 2011 - 03:33 PM

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.

#4 swiftcoder   Senior Moderators   -  Reputation: 12415

Like
0Likes
Like

Posted 22 November 2011 - 03:58 PM

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.

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 - Software Engineer @Amazon - [swiftcoding]


#5 swiftcoder   Senior Moderators   -  Reputation: 12415

Like
2Likes
Like

Posted 22 November 2011 - 04:08 PM

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 GL_TRIANGLE_LIST.

Tristam MacDonald - Software Engineer @Amazon - [swiftcoding]


#6 Ikazrima   Members   -  Reputation: 122

Like
0Likes
Like

Posted 22 November 2011 - 06:56 PM

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. Posted Image

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.



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 GL_TRIANGLE_LIST.


Thanks.

You've all been a great help Posted Image. 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.

#7 Vortez   Crossbones+   -  Reputation: 2705

Like
1Likes
Like

Posted 22 November 2011 - 10:47 PM

@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.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS