SDL Slowness?

Started by
6 comments, last by Evil Steve 19 years, 8 months ago
Hey all, I'm writing my first SDL app at the moment, and it seems to be really slow. I'm only calling SDL_PollEvent() in a loop, followed by a SDL_Flip(). I'm not rendering anything at all. Heres my main loop:

void CApp::Run()
{
SDL_Event theEvent;
bool bExit = false;
U32 dwFrames = 0;
U32 dwStart = SDL_GetTicks();
U32 dwStop = dwStart;

	while(!bExit)
	{
		// Check for events //
		while(SDL_PollEvent(&theEvent))
		{
			switch(theEvent.type)
			{
			case SDL_QUIT:
				Log("SDL_QUIT received\n");
				bExit = true;
				break;

			case SDL_KEYUP:
				m_theKeys[theEvent.key.keysym.sym] = false;
				break;

			case SDL_KEYDOWN:
				m_theKeys[theEvent.key.keysym.sym] = true;
				break;

			case SDL_MOUSEMOTION:
				m_nMouseX = theEvent.motion.x;
				m_nMouseY = theEvent.motion.y;
				break;

			case SDL_MOUSEBUTTONDOWN:
				if(theEvent.button.button == SDL_BUTTON_LEFT)
					m_bMouseButtonStates[0] = 1;
				else if(theEvent.button.button == SDL_BUTTON_MIDDLE)
					m_bMouseButtonStates[1] = 1;
				else if(theEvent.button.button == SDL_BUTTON_RIGHT)
					m_bMouseButtonStates[2] = 1;
				break;

			case SDL_MOUSEBUTTONUP:
				if(theEvent.button.button == SDL_BUTTON_LEFT)
					m_bMouseButtonStates[0] = 0;
				else if(theEvent.button.button == SDL_BUTTON_MIDDLE)
					m_bMouseButtonStates[1] = 0;
				else if(theEvent.button.button == SDL_BUTTON_RIGHT)
					m_bMouseButtonStates[2] = 0;
				break;
			}
		}

		// Flip screen //
		SDL_Flip(m_pSurface);
		dwFrames++;

		if(SDL_GetTicks() > 10000)
		{
			bExit = true;
			Log("DEBUG: Exiting app after 10 seconds\n");
		}
	}

	// Report FPS //
	U32 dwTime = SDL_GetTicks()-dwStart;
	Log("Exiting main loop. Executed "+IntToString(dwFrames)+" frames in "+
		IntToString(dwTime)+"ms ("+
		FloatToString(((float)dwFrames) / (float)(dwTime/1000))+" FPS)\n");
}


And heres my init code:

bool CApp::Init(bool bFullscreen)
{
U32 dwFlags;

	// Create backbuffer //
	dwFlags = SDL_HWSURFACE | SDL_DOUBLEBUF;
	if(bFullscreen) dwFlags |= SDL_FULLSCREEN;
	m_pSurface = SDL_SetVideoMode(800,600,32,dwFlags);
	if(!m_pSurface)
	{
		m_strError = SDL_GetError();
		return false;
	}

	// Done //
	return true;
}


And heres the results: Windowed: "Exiting main loop. Executed 1062 frames in 9932ms (118.000000 FPS)" Fullscreen: "Exiting main loop. Executed 616 frames in 9042ms (68.444443 FPS)" That seems pretty slow to me. If this were a DirectX app, I'd be expecting around 2 or 3 thounsand FPS... Is SDL always like this, or is it something i've got set up wrong? Is this just an initial slowdown, and actually drawing stuff won't lower the frame rate much? Cheers, Steve
Advertisement
Try a software rendering.

dwFlags = SDL_SWSURFACE | SDL_DOUBLEBUF;


Sometimes hardware rendering actually slows SDL down, because most modern video cards are not set up to handle 2d hardware.
~~~~~Screaming Statue Software. | OpenGL FontLibWhy does Data talk to the computer? Surely he's Wi-Fi enabled... - phaseburn
Look at your CPU usage!

On some SDL app I wrote, I experienced a maximum in frame rate at 60 fps under Windows, whereas I could go around 200 fps under Linux. But on the windows version, the CPU was only used at 10%, so I did not experienced any loss of PFS when adding some more CPU consumming tasks.
With software rendering:
Windowed: Exiting main loop. Executed 1066 frames in 9927ms (118.444443 FPS)
Fullscreen: Exiting main loop. Executed 662 frames in 9718ms (73.555557 FPS)

The CPU usage shows between 45% and 55% CPU usage, so that may well be the problem.
I suppose its easy enough to add some sprites and see what happens...

Thanks for the replies,
Steve
From SDL reference for SDL_flip()

On hardware that supports double-buffering, this function sets up a flip and returns. The hardware will wait for vertical retrace, and then swap video buffers before the next video surface blit or lock will return.

Will wait for vertical retrace... so your software runs faster than your monitor can draw.
yeah the flip is the 'problem'

it causes to run your program at maximaly the same speed as your monitor. so basicly when your program is done drawing, its just sitting around doing nothing waiting for the monitor to finish drawing. but in this time you could have done loads of usefull things, so its not like youre wasting any resources in doing so. having your program run faster than your monitor servers no purpose other than benchmarking purposes though, so dont worry about it.

i believe you can disable the wait for vertical sync by passing a false flag to the flip function. i wouldnt do it though because it causes ugly artifacts.
In this case you need to slow down the loop. Yielding the remainder of the timeslice will do it (SDL_Delay(0). Profiling a graphics app that does little more than swap front and back buffers is rather pointless. When your game loop is fleshed out and actually does some work, then you will see meaningful numbers.
Yeah, I just wanted to see what the speed was like in comparison to DirectX. It seems that the double buffering was the problem. I think its a bit odd that using double buffering is slower than single buffering, when in DX double buffered means a pointer spitch, not a blit.
Without double buffering:
Windowed Mode: Exiting main loop. Executed 1009 frames in 9897ms (112.111115 FPS)
Fullscreen: Exiting main loop. Executed 3686100 frames in 9671ms (409566.656250 FPS)
Thats a lot more like it.

Cheers,
Steve

This topic is closed to new replies.

Advertisement