Skip to main content
GameDev.net gamedev.net
🔒 Locked

Performance and Efficiency problems

Started by astagg Sep 8, 2010 at 5:19 AM 7 replies 1.9k views
Original Post
astagg
astagg
Hi,

First off I have been reading around the forums for a while and have found a lot of information that has been helpful while creating my current game so thanks to everyone for that. I was also not sure exactly which area to post this in so apologies if this is incorrect.

I have been creating a game at the moment using DirectX 10 while reading Introduction to 3D Game Programming with Direct 3D 10 by Frank D. Luna. The game I am creating is a cross between Breakout and Pong (smartly named Breakong). My intention is to use this game as part of my portfolio to try and get into the industry.

I have got the game to a reasonable level and have begun to test the code on multiple machines. It runs fine on my desktop (fraps stating 900 – 1000 fps) however when attempting to run my game on a number of laptops the performance has taken a massive dip (down to 15-20 fps). I know that my (and friends) desktops all have a reasonable spec (Quad Core and ATI 4000/5000 cards) and the laptops are lower (dual core and ATI 3000/4000 mobility cards) however this seems a rather drastic performance difference.

The main graphics engine and all DirectX interaction is taken straight from the book, however some small elements have been changed such has adding more light sources to the effects file for each ball. I am really not sure where I should start looking to make my code more efficient. I did start programming this game on my laptop so I know it did run ok up until I added the bricks.

My guess is the problem is either in the way I am drawing the scene or I am spending too much time calculating variables within the update.

I am currently stepping through all the items in the level and drawing them in the same manor objects are drawn in the book. For the bricks as there are multiple textures I check the brick’s life to give the correct colour texture and also if it is a special brick. If it is a special brick I also draw a second texture which is an image of the special ability with alpha clipping to see the texture around the logo.

During the update process I do most the work within the Ball class. The ball will on each update check for collision with walls, players, other balls and bricks. For this I know that with each ball I have to check the position with all bricks (a 14x9 grid) and I have tried to limit as many distance checks to use the square distance to avoid square rooting, I actually find the closest brick to the ball and perform the full check on that brick only.. Also after the position updates of the ball I will go through all the bricks again to check for damage done and destroying bricks. I have also added in a basic AI now that will also perform a check to find the closest brick to aim for. Is there a more efficient algorithm of checking everything that I haven’t thought of?

As I am not sure what area could be the issue and there is a lot of code I thought it would be best to put code up upon request rather than spam too much code. I am also currently at work and can’t get access to my code till I get home.

I would appreciate any advice that could be given or any tools that are available for checking where my bottlenecks are.

If you wish to have a look at my game it can be found on http://www.andytagg.co.uk
An executable is also available at http://www.andytagg.co.uk/Breakong_Alpha.html


Many Thanks in advance,
Andy Tagg
SirViver
SirViver
I can't go any more in depth right now but I have two pieces of advice for you:

  1. Profile your code. Measure which calls take the most time.
    Just looking at the code and blindly trying to optimize it without even knowing which part of your code causes the most slowdown to begin with is pointless.

    It doesn't even need to be a full-fledged profiler. Just use the same time measurement techniques (probably QueryPerformanceCounter?) you're already using for frame-timing. Put one call at the start of the code part you want to measure, one at the end and the difference between the two calls is the time taken to execute (may require some maths to get the amount in milliseconds).

    Ideally write yourself a few helper tools that allow you to create named sections for timing, then at the end of your loop generate a summary report and display it in realtime on the screen too. Just take care to let the measurement tools have as little impact as possible, so they don't influence the result significantly.

    It's also completely sufficient to do rough measurements first, to see where the main performance draws lie. Then once a function is identified as such, you can create other measurements within that function to pin down which code parts actually cause it, etc.

  2. Forget about fps measurements as performance indicator. The only value they have is telling you whether you get a high enough framerate and if it is stable. Realize that fps counts are not linear, either:

    If your update & render code takes for example 1 ms total to execute, you have 1000 fps. If you increase that by just another millisecond to 2 ms, suddenly there was a "massive" loss of 500 fps, which in reality amounts to nothing. If your base loop already takes a more realistic 10 ms, you get 100fps. If you again add 1 ms, the loss is suddenly only 9.1 fps, down to 90.9 fps. Losing high amounts of fps can look dramatic, but may in reality be ultimately meaningless.

astagg
astagg
Thanks for the reply SirViver.

I had not thought of putting in a timer around certain calls I will try this tonight. I had tried commenting out functions and seeing the effects but I was unable to obtain any really information from this. Timing the actual functions seems like it should give some solid results.

Regarding FPS I had read before about the scalability of FPS and was only really giving a rough illustration of the difference between my two systems. Converting this to ms will give my desktop taking 1.05 ms and my laptop 40 ms. This still seems like a drastic difference though. I will try adding in some onscreen times and see if I can pinpoint which functions are changing the most between the two systems.

Thanks again

Andy Tagg
astagg
astagg
I have managed to go through my code and do some profiling around my functions. On my desktop everything runs equally fast. On my laptop most of the times are only slightly slower except for the SwapChain Present call. This is taking almost 40ms to perform.

I have tried messing around with a few things on my laptop and have found that reducing to a very low resolution will speed things up (obviously, however I would rather run the game at a reasonable size). Also if I comment out the code for my ball lights within the pixel shader in the effects file I get a performance increase.

I currently have a fixed point light as a room light, and 4 moveable point lights that will have the same position as each ball (note: to start with there are 2 balls available so the other two lights are set to no colour/brightness level and outside the level box, these are brought in and attached to a ball when someone gets the multiball powerup). Would you consider this too much for a laptop to manage? Am I going about my lights the wrong way?

I am not at my home PC right now but the code for the lights within the PS function is along the lines of:

SurfaceInfo v = {pIn.posW, normalW, diffuse, spec};
float3 litColor = PointLight(v, gLight, gEyePosW);
litColor += PointLight(v, gBallLight, gEyePosW);
litColor += PointLight(v, gBallLight2, gEyePosW);
litColor += PointLight(v, gBallLight3, gEyePosW);
litColor += PointLight(v, gBallLight4, gEyePosW);

return float4(litColor, alpha);


Thanks

Andy Tagg
MaulingMonkey
MaulingMonkey
Quote:
Original post by astagg
I have managed to go through my code and do some profiling around my functions. On my desktop everything runs equally fast. On my laptop most of the times are only slightly slower except for the SwapChain Present call. This is taking almost 40ms to perform.

This means you're probably GPU bound. This alone will bring you down to 25fps max.

Quote:
I have tried messing around with a few things on my laptop and have found that reducing to a very low resolution will speed things up

This means you're probably fill-rate limited. If you're using any sort of anti-aliasing, turning that off should also help.

Quote:
Also if I comment out the code for my ball lights within the pixel shader in the effects file I get a performance increase.

The complexity of your pixel shader is one of the big things that's going to affect performance if you're fill rate limited. The other way to help is to reduce the amount of overdraw (e.g. drawing primitives, and then drawing over top of that)

Even if you can't outright skip drawing anything, if you can draw foreground/near objects first, this means the pixel shader can be skipped for the background bits that have been occluded by the foreground.

Quote:
Would you consider this too much for a laptop to manage? Am I going about my lights the wrong way?

No idea, sorry [lol]
SirViver
SirViver
I unfortunately don't really know about the relative performance of modern mobility GFX chips (I stopped following the whole graphics card circlejerk a few years ago, tbh), but a PixelShader might be a problem if the card has poor support for it. Then again your PS is probably not doing all that much - to get anything useful, the actual implementation of PointLight() would be interesting. In case that's a built-in function forget about that, I have only rudimentary HLSL knowledge so bear with me.

That said, on a hunch, have you checked if maybe VSync is enabled/forced on your laptop? I've had a problem with VSync in the past due to using D3DPRESENT_INTERVAL_DEFAULT instead of D3DPRESENT_INTERVAL_ONE, the difference being that the former uses a less precise timer apparently, which screwed up my framerate big time.
cgrant
cgrant
Cutting and pasting code blindly without understanding the underlying principles is always going to cause issue in the long run. My first suggestion is to go back through the code and understand what each section is doing and the performance implication (which can be obtained through profiling or just consulting the 'best practices' for the API. ) Just like SirViver said and I have being preaching this in any post regarding fps drop...FPS in not a valid performance metric. Do absolute timing and then you can 'correctly' say this is taking n more seconds/ms to complete than on this machine. I code on a Geforce FX 5900 and I have scenes with huge amount of geometry and a couple models all getting lit and with atmospheric scattering and I still get good 'frames rates', even running in debug mode. I use the DX9 SDK, but that shouldn't be a factor. This graphics card is several generations behind...
zedz
zedz
This is part of the reason I recommend having a weak (but capable) GPU on your development machine, if you do this you're less likely to have a nasty surprise when the games done
astagg
astagg
Quote:
Original post by MaulingMonkey

Even if you can't outright skip drawing anything, if you can draw foreground/near objects first, this means the pixel shader can be skipped for the background bits that have been occluded by the foreground.


Unintentional I have just been over my code and the order of objects drawn is as best it could be.


Quote:
This means you're probably fill-rate limited. If you're using any sort of anti-aliasing, turning that off should also help.


There is no anti-aliasing in my program

Quote:
Original post by SirViver
the actual implementation of PointLight() would be interesting.


PointLight is untouched from the books example.

float3 PointLight(SurfaceInfo v, Light L, float3 eyePos){	float3 litColor = float3(0.0f, 0.0f, 0.0f);		// The vector from the surface to the light.	float3 lightVec = L.pos - v.pos;			// The distance from surface to light.	float d = length(lightVec);		if( d > L.range )		return float3(0.0f, 0.0f, 0.0f);			// Normalize the light vector.	lightVec /= d; 		// Add the ambient light term.	litColor += v.diffuse * L.ambient;			// Add diffuse and specular term, provided the surface is in 	// the line of site of the light.		float diffuseFactor = dot(lightVec, v.normal);	[branch]	if( diffuseFactor > 0.0f )	{		float specPower  = max(v.spec.a, 1.0f);		float3 toEye     = normalize(eyePos - v.pos);		float3 R         = reflect(-lightVec, v.normal);		float specFactor = pow(max(dot(R, toEye), 0.0f), specPower);			// diffuse and specular terms		litColor += diffuseFactor * v.diffuse * L.diffuse;		litColor += specFactor * v.spec * L.spec;	}		// attenuate	return litColor / dot(L.att, float3(1.0f, d, d*d));}



Quote:
Have you checked if maybe VSync is enabled/forced on your laptop?


I had already tried running both with and without VSync on. I prefer to run my game on my desktop with VSync on as this stops my gfx card running at 95% and starting turbo fan :)



I am increasingly beginning to just think that my laptop is to underpowered to run what I would consider a very 'simple' game. I have loaded on a few of the SDK samples and anything with more than a simple model is also running slow. I am gonna try and find some computers (of friends) over the weekend that are slightly higher spec and see if I can find at what level the game will run correctly. I could even plug my old gfx card into my desktop and see how that handles it, this could also be something to try out earlier throughout my development thanks zedz



As a slight detour on the subject could I ask if anyone knows what type of PC my game would be run on when I send it out as part of a application for a job? Should I be concerned that my game will not run smoothly due to a basic email PC being used, or would it be passed onto a Dev with a more capable PC?


Thanks to everyone for your advice.

Andy Tagg

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.