LockRect() help!

Started by
7 comments, last by jollyjeffers 17 years, 1 month ago
Well, this really drive me mad. As a lot of articals on the web have said, if you want to do some 2d drawings with dx9, first you should set up a panel, then load image from files as textures. Therefor you can just paint the image on the panel. But what if I want to do some image processint stuff with the image I just loaded. I think I should lock the texture memory with IDirect3DTexture9::LockRect(), something like this: //load the image D3DXCreateTextureFromFileEx( g_pd3dDevice, "banana.bmp", 256, 256, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT , D3DX_DEFAULT, 0, 0, NULL, NULL, &g_pTex); ... ... //now lock it, then I can do something just as I did in dx7 with ddraw g_pTex->LockRect(0, &d3dlock, NULL, D3DLOCK_DONOTWAIT); ... ... g_pTex->UnlockRect(0); But that doesn't work. I just cannot lock the memory successfully. Is anyone who could give me some hints? I am a freshman with dx9. What's more, what's the really difference between IDirect3DSurface9 and IDirect3DTexture9. I think they are so familiar with each other. Thanks!
Advertisement
Try not to use DONOTWAIT.
And don't expect good performance if you use LockRect because you will kill he parallel processing between GPU and CPU (in fact, expect poor performance) You should try to make your image processing with pixel shaders.

In directx realm, a Texture is a collection of surfaces. Typically, a texture holds one surface for each mip level. This is the third parameter you pass to D3DXCreateTextureFromFileEx.

JA
You can't use LockRect with a texture created in D3DPOOL_DEFAULT

From the SDK help:
Quote:Textures created with D3DPOOL_DEFAULT are not lockable. Textures created in video memory are lockable when created with USAGE_DYNAMIC.


HTH
For the love of god, please tell me that you've just omitted your error checking code for brevity, and you don't really assume that all those functions succeed.
Quote:Original post by janta
Try not to use DONOTWAIT.

Quote:Original post by Cambo_frog
You can't use LockRect with a texture created in D3DPOOL_DEFAULT


As you two said, I just twist the parameters a bit. But only in this situation can that work:

D3DXCreateTextureFromFileEx( g_pd3dDevice, "banana.bmp", 256, 256, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT , D3DX_DEFAULT, 0, 0, NULL, NULL, &g_pTex);
... ...

g_pTex->LockRect(0, &d3dlock, NULL, D3DLOCK_DISCARD);
... ...


That(using dynamic texture) means all the contents in the texture are discarded, which is not what exactly I want. By the way, how can I obtain the point to the locked texture?


Quote:Original post by janta
You should try to make your image processing with pixel shaders.

If all the 2D stuff should better be done with pixel shaders, what are the functions like LockRect() typically used for?

[Edited by - jhq on March 17, 2007 10:27:44 PM]
Quote:Original post by jhq
But only in this situation can that work:

D3DXCreateTextureFromFileEx( g_pd3dDevice, "banana.bmp", 256, 256, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT , D3DX_DEFAULT, 0, 0, NULL, NULL, &g_pTex);
... ...

g_pTex->LockRect(0, &d3dlock, NULL, D3DLOCK_DISCARD);
... ...


That(using dynamic texture) means all the contents in the texture are discarded, which is not what exactly I want. By the way, how can I obtain the point to the locked texture?
Edit: I didn't see the managed/dynamic incompatibility.

You're still using the default pool (D3DPOOL_DEFAULT). The correct call would be:
D3DXCreateTextureFromFileEx(g_pd3dDevice, "banana.bmp", 256, 256, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8,                             D3DPOOL_MANAGED, D3DX_DEFAULT, 0, 0, NULL, NULL, &g_pTex);D3DXCreateTextureFromFileEx(g_pd3dDevice, "banana.bmp", 256, 256, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8,                             D3DPOOL_SYSTEMMEM, D3DX_DEFAULT, 0, 0, NULL, NULL, &g_pTex);
Specifying the managed system texture pool will tell Direct3D to keep a local copy of the texture in memory. When you lock the texture, Direct3D will return a pointer to this cached copy, and when you unlock use it, the data will be uploaded to the video card.
But you can't have your cake and eat it. Locking a texture necessarily means keeping it in system memory. All this copying back and forth will hurt processor-parallelism.

Quote:If all the 2D stuff should better be done with pixel shaders, what are the functions like LockRect() typically used for?
Well, they are used exactly for this. The point janta was making is that there is no way to speed your chosen method up to the equivalent of an entirely hardware-based on.

Admiral

[Edited by - TheAdmiral on March 19, 2007 6:58:24 AM]
Ring3 Circus - Diary of a programmer, journal of a hacker.
Quote:Original post by TheAdmiral
The correct call would be:
D3DXCreateTextureFromFileEx(g_pd3dDevice, "banana.bmp", 256, 256, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_DEFAULT, 0, 0, NULL, NULL, &g_pTex);



I think that is incorrect:). According to SDK, D3DPOOL_MANAGED is incompatible with D3DUSAGE_DYNAMIC.
Well, I just cannot understand why something is so nature in dx7 become so strange in dx9. All I want to do is modify texture with CPU, so firstly I load a texture to memory :
D3DXCreateTextureFromFileEx( g_pd3dDevice, "banana.bmp", 256, 256, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT , D3DX_DEFAULT, 0, 0, NULL, NULL, &g_pTex);

then I lock it within BeginScene()&EndScene() pairs:
D3DLOCKED_RECT d3dlock;if( FAILED( g_pTex[0]->LockRect(0, &d3dlock, NULL, 0) ) ){    MessageBox(NULL, "Lock Failed!", "ERROR!", MB_OK);    return E_FAIL;}else{    BYTE *temp = (BYTE*)(d3dlock.pBits);    *(temp + a) = 0xff;    ++a; //static int				   g_pTex[0]->UnlockRect(0);}g_pd3dDevice->EndScene();g_pd3dDevice->Present( NULL, NULL, NULL, NULL );


However it just can't work. I don't know why. Maybe I should fetch some book, say Special Effects Game Programming with DirectX .
You can't use a managed + dynamic texture. You must use D3DPOOL_DEFAULT texture and use the D3DUSAGE_DYNAMIC flag. That will be a hint for the driver not to put the texture data but the AGP memory, which is usually a part of the RAM which the GPU can adress. However, dynamic stuff in D3D is usually not meant for being read back, it's meant for being writen only (like, for example, a particle system.

What would be the "least bad" for you (imho) is to keep your image data in whatever format you like (for example a unsigned int[]...), then every frame update this data, then lock your texture with D3DLOCK_DISCARD | D3DLOCK_WRITEONLY and copy your update data to the texture, then render it.

Don't read back from D3D objects every frame, even if the D3D API gives you the chance to. As I see it, the ability to LockRect() textures is meant for loading data purposes only (which you don't need because you're using the D3DX API)
Load the image as POOL_SYSMEM.

Create a dynamic/default texture to use for rendering, which is the same size as your sysmem texture.

Lock, modify, and unlock the sysmem texture. The pointer to the data is in the lockedrect structure you pass to lock. You cannot assume the number of bytes allocated for each line of the texture, instead you must use the pitch in the lockedrect structure.

ie:
// First, do math on chars so we can use Pitch correctly.
char *pPixel = ((char *)lr.pBits)[y * lr.Pitch + x * bytesPerPixel];
// Second, convert pixel pointer to correct data type,
unsigned long *pPixel32 = (unsigned long *)pPixel;

After unlocking, use UpdateTexture to copy the sysmem texture to the dynamic texture.
Just for design-level consideration:

LockRect() and friends are often used in two situations; firstly to seed initial data into a GPU-accessible resource (under the covers D3DXCreateTextureFromFile() will do this) or to send/retrieve lots of data for a GPGPU-style operation.

Except in the case of really old hardware that doesn't support any programmability you wouldn't want to use LockRect() for the actual image processing and rendering. Unless you're doing something complex that cannot be expressed in an appropriate shader model...

SM1 makes it hard, but SM2, SM3 and especially SM4 are really good for image processing effects. Not only can you implement most of your algorithms they're stupidly fast [grin]

hth
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

This topic is closed to new replies.

Advertisement