Need some advices in rendering optimization!

Started by
12 comments, last by meh 18 years, 4 months ago
Hi, i'm not sure about the right forum but. My 2D game is almost finished. It uses DirectX 8.1 and my own 2D engine. Now i need to optimize it. My PC is a AMD64 3200+ with WinXP and x800 ATI video. The game shows about 400-500 FPS. I've run it on the Celeron 2.0 Ghz with some build-in intel video. And FPS was about 16. But some other 2D titles on this machine shows 30-40 FPS and even 60 FPS. I've check requirements for that game, and it was P-500. So, i think, i need to optimize my game. Now, my game render every image on the screen for each loop. So, now for each image i do DrawPremitive, SetTexture and some other directx func. calls. Excluding fonts, there only one DrawPremivites for whole string. Now the bigger number of images slows overall performance. But some images are static, and i think, there is no reason to draw them every loop. But i don't know how to implement that. So, there some articles or something else, that i can read and understant about drawing optimization for directX 8.1. P.s. there is way to calculate minimum requirements for the game? I don't have old PCs to check if my game runs on them or not! Thanks!
Advertisement
A screenshot would be nice, so one can see what you are up to!

You should try to use frame-coherence in every possible way.
If you have a background composed of many smaller images, try to pre-render them all into a bigger ( screen-size ) surface, and render the already composed background with that. If the background changes, just update the background surface. You can save much rendering-time, when the surface is reused over mulitple frames.
There are 10 kinds of people,those who understand binaryand those who not.
Quote:Original post by limpacp
Now, my game render every image on the screen for each loop. So, now for each image i do DrawPremitive, SetTexture and some other directx func. calls. Excluding fonts, there only one DrawPremivites for whole string.

That's the first thing you could optimise. Batch geometry (e.g. only one buffer for all quads) and reduce the amount of images by merging smaller ones into bigger textures. This will reduce thenumber of state changes and possibly the amount of consumed video memory.
The latter is important for integrated chipsets, since all textures reside in the main RAM.

HTH,
Pat.



If your game only has small areas that change from frame to frame, then I'd recommend using "dirty rectangles". That means, basically each frame, keep track of which portions of the screen actually change, and then ONLY re-draw those parts of the screen.

When you set up your D3DDISPLAYMODE, you need to do the following:
displayMode.SwapEffect = D3DSWAPEFFECT_COPY;

I'm not an expert with D3D or anything, but I used this for my last 2D game, and it seems to help with performance...
Optimizing 2D engines for Direct3D or any 3D API is a common question. Here's a thread to which I responded from a few weeks ago. Hope it helps.

http://www.gamedev.net/community/forums/topic.asp?topic_id=363325
Quote:Original post by Kuro
If your game only has small areas that change from frame to frame, then I'd recommend using "dirty rectangles". That means, basically each frame, keep track of which portions of the screen actually change, and then ONLY re-draw those parts of the screen.


indeed, you can also use save and restore rectangles.

in the good old dos times you could easily set a viewport that makes up the screen in some larger rectanglar region in memory. this avoids copying to memory every frame.

btw: i assume you're using backbuffers etc.
Be creative, don't copy...Greets from Holland!
Here are some techniques i can give you that i have try and they work flawlesly on my pentium 3 Intel OnBoard chipset. so as you can see it is pretty much a crappy computer and i still managed to get the 60 fps everyframe with a map that can be any size.

So here is how it works.
1-Try to Keep All the Tiles into One Texture then for each one you want you can just modify the uv coord to get to it.
2-After you load the Level and your Tiles, if you are not using D3DXSPRITE then you will need to sort your tiles by textures, so you can set the texture once per frame for all the tiles.
3- Here is where it get Technical, and if you do this wrong you will be back to square one. You must write a algorithm that will check what Tiles are withing your viewport without basically checking if they are. I know it sounds impossible but it is not. Here is How i wrote the Algo.

1-We know what are the screenwidth and screenheight is, and we know what each tiles size is. So with this two we can determined how much tiles we can have across and down. So those numbers that you will get are the amount of tiles that will be visible at all time regardless of the size of your map.
Example: if the screenwidth=640,screenheight=480,tilewidth=16,tileheight=16; then we can just take screenwidth/tilewidth which in this case would give us 40 and we do the same for the height and we get 30. So that basically tells us that the maximum tiles we can have at all time visible is 40X30.

/*2-From there we can just do 2 for loop and iterate trough the first set of tiles and draw them. In this case we can do this.
Example:*/
for(int x=0;x<(screenwidth/tilewidth);x++)
for(int y=0;y<(Screenheight/tileheight);y++)
DrawTiles(t,x*tilewidth,y*tilewidth);

As you can see doing just this does not help because even though you are not doing any checking all it will do is draw tiles from 0 to 39 on the x and 0 to 29 on the y.Unless you have no scrooling in your game then this method is fine. the minute you introduced scrooling then it will not work. So what can we do to make it better. Here goes, we know that when we move the player that the screen will scrool so we need to take that into account as well.

So here is the code for the whole algo.
[source lang=c++]//------------------------------------int screenwidth=640;int screenheight=480;int tilewidth=16;int tileheight=16;int maxX=(screenwidth/tilewidth)+1;    //The +1 is there to prevent Tile Poping  //as you move the screen to the right or to the left.int maxY=(screenheight/tileheight)+1;  //The +1 is there to prevent Tile Poping//as you move the screen up or down//MaximumTilesOnX and MaximumTilesOnY determines how many Tiles tbe MAP is made //out of Example 100x100if(maxX>MaximumTilesOnX)maxX=MaximumTilesOnX;if(maxY>MaximumTilesOnY)maxY=MaximumTilesOnY;//ScroolX is how much we have scrool on the X which is in Pixels//ScroolY is how much we have scrool on the Y which is in Pixelsint yy=ScroolY/tileheight;int xx=ScroolX/tilewidth;for(int y=yy;y<(maxY)+yy;y++)for(int x=xx;x<(maxX)+xx;x++)DrawTiles(tile[y*MaximuTilesOnX+x].id,x*tilewidth,y*tileheight);


//Conclusion.
//if any of these is not clear enough just email me at jeromefabioc@gmail.com
Quote:Original post by darookie
Quote:Original post by limpacp
Now, my game render every image on the screen for each loop. So, now for each image i do DrawPremitive, SetTexture and some other directx func. calls. Excluding fonts, there only one DrawPremivites for whole string.

That's the first thing you could optimise. Batch geometry (e.g. only one buffer for all quads) and reduce the amount of images by merging smaller ones into bigger textures. This will reduce thenumber of state changes and possibly the amount of consumed video memory.
The latter is important for integrated chipsets, since all textures reside in the main RAM.

HTH,
Pat.


Before any of that profile your code! It might not be the rendering that is slowing the whole thing down! Your program will spend 80% of the time in 20% of the code so you need to target you optimisation to the areas that actually require it.

This current thread has info on profilers; http://www.gamedev.net/community/forums/topic.asp?topic_id=365097.

I would do the above first if it is the renderer slowing you down. It's simple to do and should give the quickest immediate benefits. Other things to look at depend on what you are drawing, try to avoid overdraw, minimise the amount you are sending to be rendered and collate as much as possible.
Quote:Original post by meh
Quote:Original post by darookie
Quote:Original post by limpacp
Now, my game render every image on the screen for each loop. So, now for each image i do DrawPremitive, SetTexture and some other directx func. calls. Excluding fonts, there only one DrawPremivites for whole string.

That's the first thing you could optimise. Batch geometry (e.g. only one buffer for all quads) and reduce the amount of images by merging smaller ones into bigger textures. This will reduce thenumber of state changes and possibly the amount of consumed video memory.
The latter is important for integrated chipsets, since all textures reside in the main RAM.

HTH,
Pat.


Before any of that profile your code! It might not be the rendering that is slowing the whole thing down! Your program will spend 80% of the time in 20% of the code so you need to target you optimisation to the areas that actually require it.

This current thread has info on profilers; http://www.gamedev.net/community/forums/topic.asp?topic_id=365097.

I would do the above first if it is the renderer slowing you down. It's simple to do and should give the quickest immediate benefits. Other things to look at depend on what you are drawing, try to avoid overdraw, minimise the amount you are sending to be rendered and collate as much as possible.


Well said that man! ++
Quote:Original post by meh
Quote:Original post by darookie
Quote:Original post by limpacp
Now, my game render every image on the screen for each loop. So, now for each image i do DrawPremitive, SetTexture and some other directx func. calls. Excluding fonts, there only one DrawPremivites for whole string.

That's the first thing you could optimise. Batch geometry (e.g. only one buffer for all quads) and reduce the amount of images by merging smaller ones into bigger textures. This will reduce thenumber of state changes and possibly the amount of consumed video memory.
The latter is important for integrated chipsets, since all textures reside in the main RAM.

HTH,
Pat.


Before any of that profile your code! It might not be the rendering that is slowing the whole thing down! Your program will spend 80% of the time in 20% of the code so you need to target you optimisation to the areas that actually require it.

This current thread has info on profilers; http://www.gamedev.net/community/forums/topic.asp?topic_id=365097.

I would do the above first if it is the renderer slowing you down. It's simple to do and should give the quickest immediate benefits. Other things to look at depend on what you are drawing, try to avoid overdraw, minimise the amount you are sending to be rendered and collate as much as possible.

It's not as if an AMD64 3200+ vs. a 2.0GHz Celeron would cause an overall slowdown by 25x...

This topic is closed to new replies.

Advertisement