Slick Forums

Discuss the Slick 2D Library
It is currently Thu May 23, 2013 2:38 pm

All times are UTC




Post new topic Reply to topic  [ 6 posts ] 
Author Message
PostPosted: Thu Mar 29, 2012 8:44 am 
Offline

Joined: Thu Mar 29, 2012 8:26 am
Posts: 3
Hi there!

I got a problem with the performance of my game (developed in slick2d) on Windows Systems. The game is far from beeing done. At the moment i've got an infinite tile based world (where only the small area is rendered that can be seen by the player). On this Worldmap i have different types of tiles (Grass, Dirt, Water etc...). For every type of tile i've got one single spritesheet covering the tile's look in every direction that the game can be viewed.

So to the problem:

If i run this game at home (on a linux 64bit machine) on a map with differnt tiles displayed in differnt directions everything is quite right. I have vsync enabled and i get round 60 fps. (No matter how many differnt images are used for the tiles.

If i run this game at work (on a windows7 64bit machine) the game is lagging and when scrolling i have about 24 fps. And between 20 and 50 fps when doing nothing. But if i make the worldmap to contain only Grass Tiles the game runs as fast as on linux. So it SEEMS to me, that somehow the performance on the windows machine depends on how many differnt images are drawn on the map. (Or loaded or something like that).

(I tried a lot of things to get around this, i'm now cashing all that spritesheets and images so that the retrieval of the sprites is pretty fast and no hard disk access is needed). I also used the java visual vm tool (which helped me a lot with slick so far) to find out where that problem comes from. But since i'm not really into openGL stuff i can't really say whats the problem here. So i attached some screenshots.

Any ideas on this?

Thanks in advance!


Attachments:
File comment: The output of the CPU sampler tool
analysis_sampler.jpg
analysis_sampler.jpg [ 159.29 KiB | Viewed 432 times ]
File comment: The output of the CPU profiler tool
analysis_profiler.jpg
analysis_profiler.jpg [ 139.92 KiB | Viewed 432 times ]
Top
 Profile  
 
PostPosted: Thu Mar 29, 2012 2:39 pm 
Offline
Regular

Joined: Sun Oct 30, 2011 4:47 pm
Posts: 184
Location: Mittweida, Saxony, Germany
The performance always depends on the amount of different images drawn. Because different images require texture switches. And those are rather slow in relation to other OpenGL operations.

Regarding the hotspot analysis: Are those values the total runtime or the runtime per call? I have no problem believing that glBegin is one of the most often called methods. But other then that I fail to see why it should take that much runtime. For the swapBuffers method is after all pretty clear why it takes that much time. That is caused by the vsync because this methods blocks until the synchronization signal of the monitor is received.

Nitram

_________________
http://illarion.org


Top
 Profile  
 
PostPosted: Thu Mar 29, 2012 3:42 pm 
Offline

Joined: Thu Mar 29, 2012 8:26 am
Posts: 3
Thanks!

Yes the values are accumulated. Can you explain more about the texture switches or point me somewhere i can read about it? Is it important how many files i'm using or how many SpriteSheets? Or is it even important how many parts of that SpriteSheets i'm using. Are there ways to avoid texture changes?

Okay so what you said makes a lot of sense to the problem on my windows machine. But what i can't understand is, that this runs smooth like expected on my linux machine and on my windows machine (which is indeed A LOT faster than my home machine) it is lagging. On the linux machine i can't even feel a difference between using one and 30 different images. On the windows machine there's a world between using one image and two.

Now after what you told about that the nSwapBuffer method blocks for the vsync it seems to me like something is going wrong on the windows machine with the vsync.

What i just tested:

If i disable the vsync on windows i get around 120fps (but it's still not smoth because the framerate is alternating between 80 and 120), on the linux machine i get about 400fps. (I mean there is a reason i'm using linux, but how can that be?)

I'll profile this on linux again and see if glBegin takes that much time on the linux machine. What could cause this method to take that much time?

Thank you so far!


Top
 Profile  
 
PostPosted: Thu Mar 29, 2012 5:20 pm 
Offline
Slick Zombie

Joined: Sat Jan 27, 2007 7:10 pm
Posts: 1469
dexter86 wrote:
Yes the values are accumulated. Can you explain more about the texture switches or point me somewhere i can read about it? Is it important how many files i'm using or how many SpriteSheets? Or is it even important how many parts of that SpriteSheets i'm using. Are there ways to avoid texture changes?

The more sprites you can fit into the same texture atlas, the less binds you will need and therefore the faster your rendering will be (i.e. this means ALL image you require in your game, including HUD elements and font glyphs).

Slick's Image class is a thin wrapper around Texture. Different images may point to the same internal texture object -- you can get "shallow" copies with getSubImage(), getFlippedCopy(), getScaledCopy(), and copy().

In other words, you can have as many copies as you like of an image without losing performance as long as they all point to the same Texture object. The more Texture objects you introduce, the more binds you will require, and the more your performance will take a hit (only one Texture can be bound at a time by OpenGL).

Try using the new InternalTextureLoader.getTextureCount() method to get a better idea of what's going on under the hood (in the dev branch on bitbucket). You'll always have 1 texture; the default font.

Also, if you want more performance, don't use Image.draw at all. Instead, always use startUse/drawEmbedded/endUse. It will reduce matrix transforms as well as glBegin/glEnd calls.

To reduce glBegin/glEnd even more, you can try a vertex array renderer -- add the following code before you create your game container:
Code:
Renderer.setRenderer(Renderer.VERTEX_ARRAY_RENDERER);


More information and performance tips:
http://slick.cokeandcode.com/wiki/doku. ... emory_tips
viewtopic.php?p=26686#p26686


Top
 Profile  
 
PostPosted: Fri Mar 30, 2012 1:25 pm 
Offline

Joined: Thu Mar 29, 2012 8:26 am
Posts: 3
davedes wrote:
Also, if you want more performance, don't use Image.draw at all. Instead, always use startUse/drawEmbedded/endUse. It will reduce matrix transforms as well as glBegin/glEnd calls.

To reduce glBegin/glEnd even more, you can try a vertex array renderer -- add the following code before you create your game container:
Code:
Renderer.setRenderer(Renderer.VERTEX_ARRAY_RENDERER);



Thank you davedes for this great tip! The startUse/drawEmbedded/endUse thing removed all the major FPS problems i had on windows and on linux it nearly doubled up the maximum frame rate again.

I will now try to follow your other tips in your linked post. What i saw was, that you wrote a SpriteBatch class. Is it right, that this class collects the rendering calls and issues them at once? If it does this would be the exact right thing for my map rendering. (Could you shortly explain how your SpriteBatch class is supposed to be used?)

I have my tiles organized in chunks with 16x16 tiles. I just tracked how many chunks are rendered at once and i was a bit shocked. I i'm rendering between 25 and 36 Chunks at once which makes 6400 to 9200 tiles to be rendered. These tiles are iterated by there location. At the moment they have a 50% chance that the texture must be changed between two tiles. So we're talking about 3000 to 4500 texture changes in one single render.

So i will defenetly think about an intelligent way for organizing the different tile-spritesheets together in one bigger spritesheet. And i'm very interested in using your SpriteBatch.

Thanks, you helped me a lot so far!

EDIT: I'm sorry i found the infos on how to use SpriteBatch in your other posts!


Top
 Profile  
 
PostPosted: Fri Mar 30, 2012 3:45 pm 
Offline
Slick Zombie

Joined: Sat Jan 27, 2007 7:10 pm
Posts: 1469
It's still a work in progress, and it does more or less the same thing as VERTEX_ARRAY_RENDERER -- it just tries to be a bit more efficient/flexible about it. :)

flush() it once you're done drawing all images, and also be sure to flush() it before calling any regular Slick graphics (like g.drawRect or image.draw). Also, unlike the rest of Slick, there is no color parameter in drawImage, so it uses whatever was last set with setColor. So be sure to reset the color to opaque white before drawing images otherwise you may run into transparency issues. You also need to manually reset the translation transform at the beginning (or end) of each frame if you plan to use translate().


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC


Who is online

Users browsing this forum: Google [Bot], Yuri6037 and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group