• Advertisement
Sign in to follow this  

D3DXLoadSurfaceFromSurface function is slow...SOLVED READ!!

This topic is 4483 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I'm back again and a little confused as to why the DirectX function D3DXLoadSurfaceFromSurface is stalling the cpu when copying and converting the backbuffer surface to another surface. I'm using D3DXLoadSurfaceFromSurface with the D3DX_FILTER_BOX flag set in order to stretch and copy the backbuffer surface to another surface which is exactly half the width/height as the screensize. It all works fine and dandy but the actual call to this function is way to too slow. Is there anyway of optimizing this function or am I not using it correctly by using the backbuffer surface as the source ??? I obtain the backbuffer surface (800x600) via a call to: d3ddevice.GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,d3dbackbuffer); I then create another surface (400x300) with a call to: d3ddevice.CreateImageSurface(400,300, D3DFMT_X8R8G8B8 ,d3dscreensurface); Finally I copy the backbuffer surface into the other surface: D3DXLoadSurfaceFromSurface(d3dscreensurface,nil,nil,d3dbackbuffer,nil,nil,D3DX_FILTER_BOX,0); I have done a little tweaking and testing and found that the D3DX_FILTER_BOX is the fastest convertor, but only when the destination surface is exactly half the dimensions of the source surface. Whilst googling I read somewhere that using the backbuffer surface as a source in this funtion would be slow as the cpu is reading from the video memory. Since I can only obtain a pointer reference to the backbuffer how can I access it any other way. How can I copy the backbuffer surface to system memory in order to improve the performance of the surface copy. Any suggestions anyone...... thanks all. [Edited by - Bedlamuk on October 9, 2005 11:10:18 PM]

Share this post


Link to post
Share on other sites
Advertisement
Are you doing this every frame? If so, you are going to really murder performance, not matter how it is done. Your way is particularly bad, because (1) you are transfering the backbuffer from video memory back into system memory (always extremely slow) and (2) you create a new Surface every frame (I may be a little confused by your code - perhaps you are only doing that once at load time?).

The bottom line is, there is no fast way to copy the backbuffer, since any type of operation is gonna require it to be transfered over the agp bus. You should only be doing this for very isolated events (ie the user wants to take a screenshot).

Share this post


Link to post
Share on other sites
thanks...


The above code was just example of how I use the functions.
Both surfaces are created at runtime. Yes. I execute the D3DXLoadSurfaceFromSurface after every 10 frames are presented. Yes,
capturing every frames is very very slow.

I need a similar operation of FRAPS or PIX within my application. How do programs such as FRAPS or PIX capture the frames ???

Is there a secret function within directx that nobody or MS want to disclose :)

Share this post


Link to post
Share on other sites
Ok, I've finally managed to get the results I've been trying achieve for the past 2 weeks.

Running in 800x600 Windowed mode I have managed to capture the frames to bitmap files at 25fps whilst still maintaining 150fps in the DirectX application.

By creating a surface of exactly half the dimensions of the backbuffer I can increase the performance a further 50% (50fps bitmap capture and 300fps in application) by saving stretched(D3D_FILTER_BOX) bitmaps of 400x300 instead of 800x600.

I'm now looking to creating threads for some of the routines and I will let you know how far I can push this frame capturing.

Now here's the secret to the speed increase......

I'm just a bit puzzled, as to why adding a CopyRects call before
the call to D3DXLoadSurfaceFromSurface would increase the performance by 50% ???

When I run in Fullscreen, it's the opposite. I have to remove the call to CopyRects and just call D3DXLoadSurfaceFromSurface, otherwise the performance falls by 50%.

This is strange ???? Need to find out why ??? could this possibly be a bug in directx ????

Share this post


Link to post
Share on other sites
Quote:
Original post by Bedlamuk
I'm now looking to creating threads for some of the routines and I will let you know how far I can push this frame capturing.

I've heard good things about the use of threads for loading of texture/image resources. Apparently much of the time taken to load data is spent on "I/O Waiting", which stalls the calling thread.

I guess by the same logic that farming out the save-to-disk routine to worker threads might well be a good plan.

Quote:
Original post by Bedlamuk
This is strange ???? Need to find out why ??? could this possibly be a bug in directx ????

I don't think thats a bug in DX, I think it's just a characteristic of the way that Windowed Mode versus Fullscreen mode interacts with the underlying system. Windowed mode has to "play nice" with all the other applications running, so can/will store resources slightly differently.

There are lots of performance characteristics to take into consideration when you want to grab surfaces back from the GPU (e.g. pool, usage) and these are even more applicable when you want to grab a "core" resource such as the frame buffer. Without seeing your exact code, it's quite possible that you've just found one of these characteristics [smile]

hth
Jack

Share this post


Link to post
Share on other sites
here's the code:

I obtain the backbuffer surface (800x600) via a call to:
d3ddevice.GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,d3dbackbuffer);

I then create another surface (400x300) with a call to:
d3ddevice.CreateImageSurface(400,300, D3DFMT_X8R8G8B8 ,d3dscreensurface);

**Adding this call increases performance of next call by 50%**:
d3ddevice.CopyRects(d3dbackbuffer,nil,0,d3dscreensurface,nil));

Then I copy the backbuffer surface into the a surface for stretching:
D3DXLoadSurfaceFromSurface(d3dscreensurface,nil,nil,d3dbackbuffer,nil,nil,D3DX_FILTER_BOX,0);

Finally, save it to Bitmap file:
D3DXSaveSurfaceToFile(PChar(filename),D3DXIFF_BMP, d3dscreensurface, nil, nil);

Overcourse, I do not do this for every frame, I save at 25fps.
ie: application runs at 300fps, divide this by 25 = 12. I save file
every 12 frames to get 25fps image sequence.

I know DirectX8 is shunned by many developers and directx9 is the way forward, but the app I use is Directx8 so I'm not going waste my time re-developing. I could be faced with poorer performance in Directx9, take Direct7 to Directx8 is an example of this.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement