PDA

View Full Version : ID3DXSprite is drawing too slow



cronodragon
23-07-2007, 10:18 PM
Hi!

I'm drawing an UI using ID3DXSprite of DX9, but it's rendering too slow and it's using a lot of the processing power. Is that normal?? I'm just drawing a few elements in a 800x600 window. Each element is drawn by cropping and transforming a texture, using the ID3DXSprite methods. First I thought it was my old computer, but recently I bought a new processor, RAM and NVidia card, and it still takes a lot, eating about 50% of processing in the Intel Core Duo 2. Profiling my application I found rendering a cylinder takes about 0.00001 seconds in average, but drawing the UI window with ID3DXSprite takes 0.013 seconds!! How is that possible? A quad shouldn't have more vertices than the cylinder. Also, I'm trying to optimize the rendering by separating the 3D drawing and the 2D drawing, so I call ID3DXSprite::Begin just once per frame, but it doesn't help. Is ID3DXSprite::Begin changing so many states that it dramatically slows
down the performance? I also tested enabling and disabling the vsync delay, but it still kills the processing.

Testing the application with PIX, I found long sequences of IDirect3DTexture9::AddRef() followed by IDirect3DTexture9::Release(). This is an example of those sequences:


3791 <0x02E333E0> IDirect3DDevice9::Release() 412395202
3792 <0x02E02EE0> IDirect3DTexture9::AddRef() 412427029
3793 <0x02E02EE0> IDirect3DTexture9::AddRef() 412430764
3794 <0x02E02EE0> IDirect3DTexture9::AddRef() 412437052
3795 <0x02E02EE0> IDirect3DTexture9::Release() 412440240
3796 <0x02E02EE0> IDirect3DTexture9::Release() 412443948
3797 <0x02E02EE0> IDirect3DTexture9::AddRef() 412447248
3798 <0x02E02EE0> IDirect3DTexture9::AddRef() 412449528
3799 <0x02E02EE0> IDirect3DTexture9::AddRef() 412455032
3800 <0x02E02EE0> IDirect3DTexture9::Release() 412458043
3801 <0x02E02EE0> IDirect3DTexture9::Release() 412460368
3802 <0x02E02EE0> IDirect3DTexture9::AddRef() 412463026

...

3836 <0x02E02EE0> IDirect3DTexture9::Release() 412572413
3837 <0x02E333E0> IDirect3DDevice9::AddRef() 412577404

Could that be related to the slow performance? There are also other long sequences of IDirect3DTexture9::LockRect() and IDirect3DTexture9::UnlockRect() calls which look very expensive, like this:


4380 <0x02E333E0> IDirect3DDevice9::GetDeviceCaps(0x02D5FB14)
431532112
4381 <0x02E333E0> IDirect3DDevice9::CreateTexture(256, 256, 6,
0x00000000, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, 0x0039CCC0 -->
0x02E37900, NULL) 431856312
4389 <0x02E37900> IDirect3DTexture9::LockRect(0, 0x02D5FAA8, NULL, 0)
432621104
4390 <0x02E37900> IDirect3DTexture9::UnlockRect(0) 433392864
4391 <0x02E37900> IDirect3DTexture9::LockRect(1, 0x02D5FAA8, NULL, 0)
434002266
4392 <0x02E37900> IDirect3DTexture9::UnlockRect(1) 434254523

...

4480 <0x02E37900> IDirect3DTexture9::UnlockRect(3) 447923018
4481 <0x02E37900> IDirect3DTexture9::LockRect(4, 0x02D5FAB0, NULL, 0)
447932182
4482 <0x02E37900> IDirect3DTexture9::UnlockRect(4) 447938193
4483 <0x02E37900> IDirect3DTexture9::LockRect(5, 0x02D5FAB0, NULL, 0)
447942055
4484 <0x02E37900> IDirect3DTexture9::UnlockRect(5) 447946941

The time between those Lock()/Unlock() is 0.015325837 seconds, that's a long time!! It seems the most possible reason of the slow performance. But, what could be causing all those expensive calls? Could it be about the texture? I'm loading the texture from disk, and create it with a call like this:


D3DXCreateTextureFromFileInMemoryEx&#40;_Scene.Device, @Transference.Content&#91;1&#93;, Length&#40;Transference.Content&#41;, 0, 0, 1, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_FILTER_NONE, D3DX_FILTER_NONE, 0, nil, nil, _Texture&#41;;

Any ideas? :S

chronozphere
24-07-2007, 10:08 AM
>> Step through your code and determine when the addref/release/lockrect/unlockrect sequences are initiated.

>>Are you using large textures?? Maybe you should try to use a 32x32 texture (just for debugging). If it increases the performance significantly, there are obvious texture problems.

>> You can try D3D debug-runtimes. Maybe you'll descover more suspicious things (memory leaks and other redundant calls etc..).

>>You can also drop ID3DXSprite and render the quads yourself using a vertexbuffer. This will probably not result in lot's of redundant calls.

Hope this helps. :)

cronodragon
24-07-2007, 03:45 PM
Thanks chronozphere!


>> Step through your code and determine when the addref/release/lockrect/unlockrect sequences are initiated.

Is it possible to step through DirectX code? :shock: I mean, in plain Pascal, not assembly.


>>Are you using large textures?? Maybe you should try to use a 32x32 texture (just for debugging). If it increases the performance significantly, there are obvious texture problems.

I'll try that, is an easy test.


>> You can try D3D debug-runtimes. Maybe you'll descover more suspicious things (memory leaks and other redundant calls etc..).

I have to learn how to use them. I know I have to enter the configuration panel and activate DX for debugging, but what then? Where do I get the debug output?


>>You can also drop ID3DXSprite and render the quads yourself using a vertexbuffer. This will probably not result in lot's of redundant calls.

That would be the last solution, I want to give ID3DXSprite an opportunity before dropping it out. On the other hand, how do I setup the projection in DX so the quads are drawn in 2D?... or maybe I should use the transformed vertex format?

Regards!
-Marco

chronozphere
25-07-2007, 08:44 AM
Is it possible to step through DirectX code? Shocked I mean, in plain Pascal, not assembly.

Whaha. :D No, but it's still interesting to see which DX routine is initiating these sequences. ;)


I have to learn how to use them. I know I have to enter the configuration panel and activate DX for debugging, but what then? Where do I get the debug output?

You can see debug output in your event-log. In Delphi 7 it's View->Debug windows->Event log. You can put some breakpoints in your code and step through them as you carefully monitor the Event log. Then you will know when and where the problems start. You might find other bugs, mem leaks etc which are causing the performance drop. :)


That would be the last solution, I want to give ID3DXSprite an opportunity before dropping it out. On the other hand, how do I setup the projection in DX so the quads are drawn in 2D?... or maybe I should use the transformed vertex format?

Transformed vertex format is indeed an easy way to render 2d. But i prefer orthogonal projection using D3DXMatrixOrthoLH (http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Dec_2005/D3DXMatrixOrthoLH.asp).

Ortho projection is very handy for 2d stuff because the size of the meshes you render remain constant, no matter what the distance to the camera is. :)

You can try to set the view matrix to the identity-matrix and enabling ortho projection by using D3DXMatrixOrthoLH's output matrix for the projection.
Use the world matrix to correctly position your object's in 2d space by translating them. Then you should be able to render 2d quads if am not mistakin. 8)

I prefer this because it only requires you to change some matrices. Transformed vertices are created by adding D3DFVF_XYZRHW in the fvf code, which hardcodes the 2d aspect into your mesh. You cannot use it for 3d rendering.

Good luck;)

wodzu
25-07-2007, 10:41 AM
Hello.

I think that you should not worry about your processing power. It's quite normal. I am also using DirectX from time to time and my applications take up to 97% of CPU. Unless it doesn't decrease your FPS why bother?

As goes for LockRect function it's expensive. But its cost depends also from the size of the locked rectangle and flags.

Regards,

Wodzu

cronodragon
25-07-2007, 03:16 PM
Hey late at night I found the problem! It's nothing related to drawing the quads, it's about the text!!! :x

I was rendering text using DX methods. Both the creation of the font interface, and the drawing of the font are incredibly slow. I measured around 0.0013 milliseconds for each, which is several orders of magnitude the time required to draw a 3D cylinder. Even drawing an empty string takes all that time.

I'm not using DX fonts any more!!! :evil: