Sign in to follow this  
jnye

DirectX sprite performance

Recommended Posts

I've written my own 2D sprite class using pre-transformed vertex coordinates. Everything works great, but it just doesn't seem like I can get the perfomance I need out of DirectX. I need to display over 100 sprites on screen (each with a different coordinates and different texture). It seems like DirectX should be able to handle this, but I can't seem to do anything to improve the performance. I've heard locking/unlocking the vertex buffer is a performance hit, but I've rewritten everything to eliminate this and still no change. Just for testing, I've pretty much minimized the calls to SetTexture, SetStreamSource, etc. and still no improvement. I've tried 1 vertex buffer vs. a vertex buffer for each sprite, hardware/software processing, and different memory pools...all to no avail. It seems that calling DrawPrimitive over 100 times is too slow, not matter what I do with everything else. Is there any way to reduce the DrawPrimitive calls even though I need to change textures often? Any recommendations or ideas? Thanks.

Share this post


Link to post
Share on other sites
I'm trying that now, but would prefer not to use it.

I would like to maintain a little more control over my class. Do anyone know if D3DXSprite automatically handles breaking textures down if they are larger than the video card supports? Also, doesn't D3DXSprite blur the sprite...I want an exact image of my source file.

Share this post


Link to post
Share on other sites
Yeah, I read that and it all makes sense. But still doesn't solve the performance issue.

I did notice this posted in the forum discussing the article:

6. Try to use as little DrawPrimitive as possible. I.e. to draw 100 spries on screen dont call DrawPrimitive 100 times. Instead create and fill an array of 100x3x2 vertices and DrawPrimitive( TRIANLELIST ) once with those.

Is there a way to do this with multiple textures? Or is this assuming one big tuxture for the call to DrawPrimitive (which is not very realistic with 100 sprites).

Share this post


Link to post
Share on other sites
If all your sprites use the same texture you only need one call to drawprimitive

1. Put all your sprite bitmaps in the same texture and use texture coordinates to access the various sprite.

2. Create a vertex buffer that can hold all 100 sprites. Use a temp array, something like vector<VertexType> Temp. Draw functions save verticies to this array.

3. When all drawing is done lock your vertex buffer and copy the temp array to the vertex buffer.

4. set states, ect and then call
DrawPrimitive(D3DPT_TRIANGLELIST,0,(m_verBatch.size()/3));
I use trianglelist because I want to, others use D3DPT_TRIANGLESTRIP which uses fewer vertex.

Share this post


Link to post
Share on other sites
If you can't combine all sprites into one texture use as few as possible and use one drawprimitive call for each texture.

Share this post


Link to post
Share on other sites
I tried D3DXSprite and it increased performance a little bit, but far from acceptable.

I guess I need to get all of my sprites onto 1 texture to really get the performance I need.

However, this would require a larger texture and I need to guarantee my game will run on older video cards. If I stick to 256 x 256 textures, I will still need to switch textures and call DrawPrimitive almost as often as I am now.

Any additional suggestions?

Share this post


Link to post
Share on other sites
Sorry, I posted that last message at the same time as you.

Even with my sprites on a few different textures, I will need to switch back and forth constantly because of drawing order. I'm not sure if this solves my problem.

Share this post


Link to post
Share on other sites
I use a 512 x 512 texture to hold all sprites on my app. Also look up drawindexedprimitives as this can help reduce vertex count. Also if you use a z coordinate in the vertex data that way sprites are drawn at various levels. I am not sure exactly what your trying to do though.

Share this post


Link to post
Share on other sites
Quote:
Original post by jnye
I'm trying that now, but would prefer not to use it.

I would like to maintain a little more control over my class. Do anyone know if D3DXSprite automatically handles breaking textures down if they are larger than the video card supports? Also, doesn't D3DXSprite blur the sprite...I want an exact image of my source file.


The "blurring" can be disabled in the code when you call D3DXSprite->Begin by setting these device sampler states:

D3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
D3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
D3DDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);

I would encourage you to use D3DXSprite interface.

Share this post


Link to post
Share on other sites
Even locking/unlocking/settexture each sprite each frame you should be able to get near 10000 quads before noticing a slowdown. [assuming 128x128 textures, geforce2 or so level card].

My first naive DirectX code did this, and it was certainly acceptable.

Share this post


Link to post
Share on other sites
What sort of performance do you need? Doing 100 DP calls with SetTextures between them is considerably slower than a single call, but it'll still run way over 60fps on all but really low end systems.

Share this post


Link to post
Share on other sites
Ok, I reduced my minimum texture size to 64 x 64 since most of my sprites are small and I'm getting a much better frame rate now (90fps).

I still may try some of the other optimizations mentioned here.

Thanks.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this