Sign in to follow this  
nullptr

[DX9] texture lockrect returns bad pointer

Recommended Posts

Hello all, I am quite new to d3d programming and I was wondering if anyone knows the circumstances under which a call to lockrect can return a bad pointer. I am using a dynamic (default pool, usage dynamic) font texture I am updating when needed; this usually works fine, but on some old nvidia cards the call succeeds but a bad pointer is returned and the following memcpy fails. I suppose the texture has been swapped through the agp bus but I guess the driver should take care of keeping data alive. Unfortunately updating the driver is not an option, the latest releases are several years old. Has anyone experienced anything similar? How could I take control of this situation? Forgot to say I am running Windows XP Pro. Thanks for any help you may provide.

Share this post


Link to post
Share on other sites
Thanks for your reply but... from the docs:

Keep the following things in mind when working with dynamic textures.

They cannot be managed. For example, their pool cannot be D3DPOOL_MANAGED.
Dynamic textures can be locked, even if they are created in D3DPOOL_DEFAULT.
D3DLOCK_DISCARD is a valid lock flag for dynamic textures.

Anyway I am checking all return codes, in this case I get S_OK.

Share this post


Link to post
Share on other sites
What flags are you locking with?
Is there any multithreading going on?
Is there any chance that you could be locking the texture twice, or unlocking it before the memcpy()?
Do the Debug Runtimes say anything?
What value is the bad pointer? Is it null, 0xcccccccc, or some other "pattern" address?
When you say "memcpy() fails", do you mean it causes an access violation?
Are you sure you're not writing too much data in (I.e. causing a buffer overflow)?
Have you tried using the reference rasterizer?

Share this post


Link to post
Share on other sites
Thanks Steve,

I've tried locking a sub-region alternatively with 0, nosyslock, nosyslock | nodirtyupdate; doesn't seem to make any difference.
Multithreading is NOT enabled in my application, so there is no chance that anyone else is repeating or releasing the lock before the memcpy.
As for the Debug Runtime, it is currently disabled, I'll have to fix a number of warnings before I can switch it back on.
The pointer actually appears to be a valid address but as you say it causes an access violation.
I am quite sure I am not writing too much data, I am uploading data in rows (I get a pitch of 2048 which is correct in my case) and it fails on the very first row; say I have a 512*256 rgba texture, I am locking a subrect from 100,100 to 120,120 and writing 20*4 bytes each row.
Haven't tried the reference rasterizer yet, but surely will; the weird thing is everything seems to work fine on most cards, I am using the very same machine and switching cards as needed.

Thanks again.

Share this post


Link to post
Share on other sites
Quote:
Original post by nullptr
The pointer actually appears to be a valid address but as you say it causes an access violation.
I am quite sure I am not writing too much data, I am uploading data in rows (I get a pitch of 2048 which is correct in my case) and it fails on the very first row; say I have a 512*256 rgba texture, I am locking a subrect from 100,100 to 120,120 and writing 20*4 bytes each row.
If the pointer looks valid, there's a good chance it's an issue with the way you're using the pitch - can we see your code from LockRect() to UnlockRect()? Are you aware that the pointer you get in the D3DLOCKED_RECT is the pointer to the top left of the locked rectangle; not the top left of the surface (So you shouldn't be offsetting by 100 rows + 100 columns in your example).

Share this post


Link to post
Share on other sites
Steve,

yes I am treating the returned ptr as the topleft corner of the locked area, here's the code:


hResult = pkDXTexture->LockRect(0,&kLockRect,
&kUpdateRect,D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK);
assert( SUCCEEDED(hResult) );
unsigned char* pvData = (unsigned char*)kLockRect.pBits;
unsigned char* aucD = aucData;
const int iSize = iWidth * 4;
for (int i = 0; i < iHeight; ++i, pvData += kLockRect.Pitch,
aucD += iSize)
memcpy(pvData,aucD,iSize);
hResult = pkDXTexture->UnlockRect(0);
assert( SUCCEEDED(hResult) );

Share this post


Link to post
Share on other sites
Yup, that all looks good.

What if you lock the entire surface instead of a subrect? And when you get the access violation, what's the exact message you get and what is the value of kLockRect.pBits?

Share this post


Link to post
Share on other sites
Thanks for your reply, I will try and lock the whole surface tranferring only the required data and eventually get back to you to let you know what happened with details about error messages and pointer values.

Share this post


Link to post
Share on other sites
According to the debug runtime it turns out I am saturating texture memory...
Here is the output, debug runtime shows nothing but a large number of the following:

Direct3D9: (INFO) :Removed texture with timestamp 0,116154 (current = 632666).
Direct3D9: (INFO) :Removed texture with timestamp 0,116162 (current = 632666).
...
Direct3D9: (INFO) :Removed texture with timestamp 0,116374 (current = 632666).
Direct3D9: (WARN) :Allocated surface after 2 tries.

This is before the lock + memcpy occurs, in which case:

First-chance exception at 0x1026ed6a in xxx.exe: 0xC0000005: Access violation writing location 0xe2963854.
Unhandled exception at 0x1026ed6a in xxx.exe: 0xC0000005: Access violation writing location 0xe2963854.

This is on a GeForce GO 6600 with 128 MB dedicated VRAM, latest drivers; won't happen on ATi cards with the very same VRAM amount. Something very similar happens on an old Quadro4 550 XGL with 64 MB VRAM, but obviously it fails much faster.

What would help in this case? Texture compression maybe? And shouldn't the driver automatically cope with this situation?

Thanks.

Share this post


Link to post
Share on other sites
Quote:
Original post by nullptr
First-chance exception at 0x1026ed6a in xxx.exe: 0xC0000005: Access violation writing location 0xe2963854.
Unhandled exception at 0x1026ed6a in xxx.exe: 0xC0000005: Access violation writing location 0xe2963854.
What is the value of kLockRect.pBits when you get that access violation (So I can tell how far that address is from the lock)? And what size is the texture, what format, and what RECT are you locking with?

Share this post


Link to post
Share on other sites
Sorry, forgot to mention that apart form being terribly slow and apprently not supporting cubemaps in a feasable way, the reference rasterizer works fine.
Have no access to full details right now (will do, promise) but the pBits pointer is just a handful of a bytes away, the texture is a 512x256 D3DFMT_A8R8G8B8, the rect can be something like 20,20 to 40,40. Also tried locking the whole surface, same result,
so I blame it on texture trashing (got messages about MRU texture being removed as well).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this