Reading texture data back from device memory.

Started by
5 comments, last by bluntman 15 years, 9 months ago
How can I get access to the data of a texture that was created using D3DPOOL_DEFAULT? Preferably I would like to be able to use the GetDC() function of the IDirect3DTexture9 class, but any method that works would be fine!
Advertisement
Quote:Original post by bluntman
How can I get access to the data of a texture that was created using D3DPOOL_DEFAULT?
Preferably I would like to be able to use the GetDC() function of the IDirect3DTexture9 class, but any method that works would be fine!
What is this texture for? Unless it's dynamic, it should be in the managed pool, and if it's dynamic, then GetDC() should work.

Example:
LPDIRECT3DTEXTURE9 pTexture; // You textureLPDIRECT3DSURFACE9 pSurf;HRESULT hResult = pTexture->GetSurfaceLevel(0, &pSurf);if(FAILED(hResult)){   // Error   return false;}HDC hDC;hResult = pSurf->GetDC(&hDC);if(FAILED(hResult)){   // Error   pSurf->Release();   return false;}// Do whatever with hDC here// CleanuppSurf->ReleaseDC(hDC);pSurf->Release();


Note that as per the Docs, only some formats are suitable for GetDC() to work. If it's not in one of those formats, you'll have to use LockRect() instead.
Does storing in the managed pool not mean that a copy is kept in system ram aswell as video ram? I need to avoid this.
Quote:Original post by bluntman
Does storing in the managed pool not mean that a copy is kept in system ram aswell as video ram? I need to avoid this.
Yes - but why do you need to avoid it? It's a good thing.

1. When you lose your device (User alt+tabs for instance), you don't have to load everything from disk again
2. When you run out of VRAM, D3D will swap data in and out of system memory for you - without that you need to make sure that your total resources never exceed the amount of VRAM on the system, and some systems have very low amounts of VRAM (E.g. 32MB).
Thanks, I understand all the implications, all I want to know is how to do what I asked in the OP or if it is possible? From what I can tell it isn't, but maybe I am missing something.
I need my textures to be stored in vid ram only, but be able to read back data from them to system ram. How can I do this?
Quote:Original post by bluntman
Thanks, I understand all the implications, all I want to know is how to do what I asked in the OP or if it is possible? From what I can tell it isn't, but maybe I am missing something.
I need my textures to be stored in vid ram only, but be able to read back data from them to system ram. How can I do this?
You'll need to use IDirect3DDevice9::StretchRect() to copy from the default pool resource to a system memory copy, then use LockRect() or GetDC() the system memory copy.
Doing that is going to have a massive performance penalty, and results in a system memory copy of the data anyway, so you might as well use the managed pool. The only advantage this has is that you only create the system memory copy when you need it (Which will be slow).
Alternatively, you could use a dynamic texture and read from that with LockRect(), but that's going to be very slow as well.

Why on earth do you need to avoid having a system memory copy of the data? All you're doing is making things difficult for yourself, slower, and likely to cause problems on lower end graphics cards.
Thanks for the solution! Its for a tool that is only going to be used internally so lower end cards aren't a concern, I have been forbade from using Managed textures as it will use more system ram. MSDN seems to indicate that one shouldn't use many dynamic textures (they say only one of each size whatever that means). Basically the textures are already loaded into vid ram by another library, but I have to get them back into system ram again so I can display them as HBITMAPs in a custom control, to allow them to be browsed. So I am already storing one system memory copy of the textures (of which there could be 100s).
/edit
Just tried it, works great thanks alot!

This topic is closed to new replies.

Advertisement