   About Video Memory
  There are few questions while processing images with GPU.The desktop environment is as below.---------------------------------------------------------------------------PC Spec.CPU : 3.2GhzRAM : 2GBGraphic Card : NVidia Geforce 7800 GTX(128MB) - PCI Express- DirectX Version : 9(2005)- Raw Image Size : 896 X 252(8bit)- Source Texture Format : D3DFMT_L8- BackBuffer Format : D3DFMT_A8R8G8B8---------------------------------------------------------------------------A GoalI would like to upload raw image to texture by using DirectX 9 SDK and retrieve raw data of rendering result from GPU.Rendering is stored in Backbuffer, and I tested Backbuffer data as below.----1. Using Backbuffer to retrieve data.GetBackBufferbackbuffer.Lock ... memory copy ...backbuffer.UnLockThere seems to be some problems.From the code above, it takes about 7ms to lock, and 24ms to save data.The whole process takes over 30ms, which is a problem.The locking and memory copy process time takes to long.2. Drawing to Bitmap DC by Buffer DC and retrieving data.I used another method, which is storing BMP DC by getting Backbuffer's DC.Byte* RawData[MAX_SIZE];device.GetDC(backDC)BitBlt(Bmp.Canvas.Handle, width, height, backDC, 0, 0, SRCCOPY)memcpy(RawData, Bmp.ScanLine[height - 1], width, height)If I use the procedure written above, it takes about 10-11ms to get DC and copy memory.This also takes too much time.3. Rendering on the RenderTarget.I tried to create Texture by D3DUSAGE_RENDERTARGET, performing rendering on Texture, and retrieve data,but since D3DUSAGE_RENDERTARGET needs to create Texture by D3DPOOL_DEFAULT type, Texture could not be locked.So I tested accessing by creating Texture as D3DPOOL_SYSTEMM Type, perform texture copy, and then locking.It took about 10ms, which is also a problem. ----If we do not consider the above situations, upload time is less than 1ms.texture.Lock... memory copy ...texture.UnLockI would like to know if the problems above is caused by some physical reasons of Upload/Download speed from Graphic Card, or if the problems can be resolved by other methods in DirectX   
  Short answer: What you're doing is always slow.Long answer:The way the AGP (or PCI-E) bus is structured as well as the pipeline/GPU construction means that pulling back (or even uploading) any resources is pretty slow. It is also largely independent of your hardware specification - PCI-E/AGP will make a difference, but the CPU and GPU less so.In my experience, the best you can do is to use render targets (D3DUSAGE_RENDERTARGET in D3DPOOL_DEFAULT) and then use GetRenderTargetData() to copy it to a D3DPOOL_SYSTEMMEM texture.2 Important things:Read/Write in one go. When you've acquired your lock do a single memory copy to/from a system memory array. Reading byte-by-byte through the locked pointer often means the lock is held for longer, stalling the GPU. Also, once you've got a CPU copy you could use threading and offload the work accordingly.Dont (re-)create resources on each iteration, reuse the same texture/surface pointers and/or create a pool of them at application start. Creating a new IDirect3DSurface9 each time you want to call GetRenderTargetData() will be much slower than re-using an existing one.Implementing some sort of bounded buffer and using a producer/consumer approach is also very efficient provided you dont mind an initial delay ("warm up" the buffers) and you can render/process subsequent results before you get back previous ones.Bottom line is that you can't really improve the latency (its more latency than actual bandwidth) of this sort of work, but you can try and hide it....hthJack   ;  I want to add two things:1.  An additional reason to use GetRenderTargetData instead of lock/Unlock is that most modern GPUs support a faster copy from video to system ram. This is used by the runtime when available but only together with GetRenderTargetData.2. If you render something and than call GetRenderTargetData for the currently active render target you have to wait a “long” time until the GPU have done all the queued work. To work around this problem it is recommended to use two or more render target as a ring buffer.;  Thank you for answer~I have some question.I don't know about answer 2."To work around this problem it is recommended to use two or more render target as a ring buffer."How make the ring buffer use by few render target.And I used by GetRenderTargetData. but it took about 10ms.Anything else?;Quote:Original post by SukjinleeI don't know about answer 2."To work around this problem it is recommended to use two or more render target as a ring buffer."How make the ring buffer use by few render target.Have an array of multiple textures and cycle through them. Something like:int index = 0;LPDIRECT3DTEXTURE9 *pRingBuffer = new LPDIRECT3DTEXTURE9[ size ];// On a device reset:for( int i = 0; i < size; i++ ){    device->CreateTexture( ... D3DUSAGE_RENDERTARGET, ... , &pRingBuffer );}// On each subsequent frame of rendering...device->SetRenderTarget( pRingBuffer[ index++ ] );// You can now lock/manipulate the preceeding bufferint preceeding = (index - 1) % size;device->GetRenderTargetData( pRingBuffer[ preceeding ], pSysMemSurface );The exact size of the ring buffer is subject to how much VRAM you have and how many frames of latency you can tolerate - a value of 2-3 should be sufficient.Quote:Original post by SukjinleeAnd I used by GetRenderTargetData. but it took about 10ms.As mentioned - it will always be slow, but the trick is hiding the latency... perform your operation when latency will be at a minimum (its not in, or dependent on, anything in the command queue) and where that latency wont "hurt" so much.hthJack   