I've recently been experimenting with using ID3DXSprite for rendering some UI elements, mostly to save myself the trouble of writing my own custom code for them. However I've found that performance is most definitely not up to scratch.
My own code is totally straightforward, a Begin, followed by a bunch of Draws, followed by an End. I've arranged the UI elements by texture where possible, and also have many of the textures already batched in an atlas.
Looking behind the scenes in PIX I see that each time the texture changes ID3DXSprite does a GetLevelDesc, which it obviously needs for to calculate the texture coords, but which takes some time. One of the slowest operations in the interface. It doesn't cache the results in any way (although I can see cases where doing so would break it.)
It also uses it's own vertex and index buffers; creation is a one-time only operation, when the sprite itself is created, and the correct flags are used (index buffer is static, vertex buffer is dynamic, both are in pool default with writeonly specified). Lock operations on the vertex buffer are with D3DLOCK_NOOVERWRITE, but unlock operations on it are the slowest operation in the interface, with an average time of about 2183242. All in all, a small handful of UI elements take almost as long to draw (23420293) as the (admittedly relatively simple) 3D scene (29367592).
Tested this with both the debug and the release runtimes, tested with the 2 versions of the SDK I have handy at the moment (June 2008 and June 2010), and results are consistent across the board.
Is what I'm seeing normal behaviour? Would I be better off ditching ID3DXSprite and investing the time in writing my own code to handle this? I expect that the UI elements are going to be a lot more complex than the fairly lightweight test content I'm using at the moment and I'm suspecting that even DrawPrimitiveUP would have been a better choice.....
(D3D9) ID3DXSprite horrifically slow?
ID3DXSprite is pretty much as fast as you're going to get. If Unlock() is slow in ID3DXSprite, it'll be slow in your own code, and GetLevelDesc should be extremely quick to do, it doesn't make a driver call, it's cached in the D3D runtime.
Are you passing the correct flags to ID3DXSprite::Begin()? You probably want D3DXSPRITE_SORT_TEXTURE and either D3DXSPRITE_SORT_DEPTH_BACKTOFRONT or D3DXSPRITE_SORT_DEPTH_FRONTTOBACK depending on if you're using alpha blending (in which case you need to sort back-to-front, and use D3DXSPRITE_ALPHABLEND too).
I'd be surprised if you manage to write a system that substantially out-performs ID3DXSprite in the general case (I.e. rendering several textured, non-rotated quads).
Are you passing the correct flags to ID3DXSprite::Begin()? You probably want D3DXSPRITE_SORT_TEXTURE and either D3DXSPRITE_SORT_DEPTH_BACKTOFRONT or D3DXSPRITE_SORT_DEPTH_FRONTTOBACK depending on if you're using alpha blending (in which case you need to sort back-to-front, and use D3DXSPRITE_ALPHABLEND too).
I'd be surprised if you manage to write a system that substantially out-performs ID3DXSprite in the general case (I.e. rendering several textured, non-rotated quads).
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement