LockRect fails, but not when ran on PIX

Started by
6 comments, last by dario_ramos 14 years, 1 month ago
This is really weird... I have a texture created with D3DUSAGE_DYNAMIC and D3DPOOL_DEFAULT, which can be locked, according to the D3D9 SDK docs. It works like a charm in our machines, but pTexture->LockRect fails with D3DERR_INVALIDCALL in our client's machine. Unfortunately, we can't use the debug version of D3D there... The thing we noticed recently is that it doesn't fail in the client's machine when we run it from PIX. What could be going on...? Is there a way to get more info than just the HRESULT in release mode?
Advertisement
Is this 100% reproducible, or does it only happen some of the time?
Is there any multithreading going on?
Is there any possibility that the texture pointer is invalid somehow (Been Release()d for instance)?
What are your flags to LockRect()?
If LockRect() fails, and you call GetLevelDesc(0, ...), does that say that the surface is what you expect (Default pool, D3DUSAGE_DYNAMIC)?
Quote:Original post by Evil Steve
Is this 100% reproducible, or does it only happen some of the time?


It happens always, in the client machine and outside of PIX.

Quote:
Is there any multithreading going on?


Yes.

Quote:
Is there any possibility that the texture pointer is invalid somehow (Been
Release()d for instance)?


I could call GetLevelDesc() after failing the call to LockRect, so I'm pretty sure the pointer is valid

Quote:
What are your flags to LockRect()?


D3DLOCKED_RECT rLockedRect;	if( FAILED( pTexture->LockRect(0, &rLockedRect, NULL, D3DLOCK_DISCARD) ) ) {		using BasicTypesTools::toString;		string info;		info = "LockRect failed. Image width: " + toString( cImage.GetWidth() ) + ", ImageHeight: " + toString( cImage.GetHeight() );		Log( LOG_TYPE_ERROR, "CDirect3D", "CopyImageToTexture", info.c_str() );		return E_FAIL;	}


Quote:
If LockRect() fails, and you call GetLevelDesc(0, ...), does that say that the surface is what you expect (Default pool, D3DUSAGE_DYNAMIC)?


Format = 81 (D3DFMT_L16, which is OK as the image is monochrome 16-bits)
Type = 1 (Surface)
Usage = 512 (Dynamic)
Pool = 0 (Default)

More info: What we're doing is rendering a big image using textured quads. LockRect fails in the quads adjacent to the image's borders: it either renders them black, or on the top left corner of the image. What puzzles me the most is that this doesn't happen when running the app from PIX... Perhaps it corrects some wrong sampler/render states we set?
Quote:Original post by dario_ramos
LockRect fails in the quads adjacent to the image's borders: it either renders them black, or on the top left corner of the image.


What do you mean by this, do you have separate LockRect calls and only some of them fails?
In the code you posted you pass NULL for the rect, so it should lock the entire surface. If you provide a rect to LockRect the problem could be it reaches outside of the texture. If you mean LockRect fails only on some texture objects, does it happen if you only try to lock that particular texture, or only if you lock all of them?
Are you using UnlockRect to unlock all the textures after locking them?
Quote:Original post by dario_ramos
Quote:
Is there any multithreading going on?


Yes.
Are you using D3D resources from multiple threads? And if so, did you use the D3DCREATE_MULTITHREADED flag when you created the device?

Quote:Original post by dario_ramos
More info: What we're doing is rendering a big image using textured quads. LockRect fails in the quads adjacent to the image's borders: it either renders them black, or on the top left corner of the image. What puzzles me the most is that this doesn't happen when running the app from PIX... Perhaps it corrects some wrong sampler/render states we set?
What Erik said; are you locking with a RECT in some cases and not in others?
The problem was solved after upgrading the client's video card drivers :). Anyhow, to be on the safe side...

Quote:Original post by Evil Steve
Are you using D3D resources from multiple threads? And if so, did you use the D3DCREATE_MULTITHREADED flag when you created the device?


Yes, but that happens rarely. Would the performance drop too much if I set the flag?

Quote:Original post by Evil Steve
What Erik said; are you locking with a RECT in some cases and not in others?


Exactly: it succeeded for "inner" quads and failed for "outer" ones.
Quote:Original post by dario_ramos
Quote:Original post by Evil Steve
Are you using D3D resources from multiple threads? And if so, did you use the D3DCREATE_MULTITHREADED flag when you created the device?


Yes, but that happens rarely. Would the performance drop too much if I set the flag?
If you're accessing D3D resources from multiple threads, even if it's rarely, you need to use the D3DCREATE_MULTITHREADED flag (Which may come with a noticeable drop in performance). Not doing so is undefined behaviour, and could result in all sorts of "weird things" happening, exactly like you described. Even if it works on current hardware / drivers, there's nothing to say that it won't blow up on a particular version of windows or hardware / driver.
Alright, then I'll refactor so that only one thread accesses the device, since the application is quite a resource hog as it is...

This topic is closed to new replies.

Advertisement