Jump to content
  • Advertisement
Sign in to follow this  
Scet

[MDX] Memory exceptions when locking/unlocking textures

This topic is 4449 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello. I'm having some trouble with a function I've created to join two textures together:
protected void Add( TextureDefinition.PatchDescriptor DescriptorReference )
        {
		Patch Patch = Resources.GetPatch( DescriptorReference.PatchNumber );
        	if( Patch == null )
        	{
        		return;
        	}
        	int R, G, B, A;
        	DirectX.GraphicsStream Stream = Texture.LockRectangle( 0, Direct3D.LockFlags.None );
        	DirectX.GraphicsStream PatchStream = Patch.Texture.LockRectangle( 0, Direct3D.LockFlags.None );
        	for( int y = 0, ty = DescriptorReference.Y; y < Patch.Height && ty < Height; y++, ty++ )
        	{
        		for( int x = 0, tx = DescriptorReference.X; x < Patch.Width && tx < Width; x++, tx++ )
        		{
        			PatchStream.Position = ( ( y * Patch.Width ) + x ) * 4;
        			R = PatchStream.ReadByte();
        			G = PatchStream.ReadByte();
        			B = PatchStream.ReadByte();
        			A = PatchStream.ReadByte();
        			if( A == 255 )
        			{
        				Stream.Position = ( ( ty * Width ) + tx ) * 4;
        				Stream.WriteByte( (byte)R );
        				Stream.WriteByte( (byte)G );
        				Stream.WriteByte( (byte)B );
        				Stream.WriteByte( (byte)A );
        			}
        		}
        	}
        	PatchStream.Close();
        	Patch.Texture.UnlockRectangle( 0 );
		Stream.Close();	
        	Texture.UnlockRectangle( 0 );
        	return;
        }

The problem is that sometimes one of the UnlockRectangle calls will cause an exception "Exception System.AccessViolationException was thrown in debuggee: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.". Also occasionally I get the same exception on one of the Stream.WriteByte calls, which seems odd considering all the bounds checking I checked the MSDN and as usual there wasn't much there(this exception isn't even listed under the possible Exceptions). My textures are created like this: Texture = new Direct3D.Texture( Game.Device, Width, Height, 1, Direct3D.Usage.SoftwareProcessing, Direct3D.Format.A8R8G8B8, Direct3D.Pool.Managed ); Any help is appreciated.

Share this post


Link to post
Share on other sites
Advertisement
I can see a couple things here:
1) You're not using the pitch returned by lock call. You'll need to use a different overload to have it returned, but it is highly recommended you use the pitch value when writing/reading from textures or surfaces.

2) Does GraphicsStream::Position take a value in bytes? I wouldn't be surprised if it took an index of the item to set it to, in which case your * 4 would make you go out of bounds.

Also, you mention it only fails some of the times. What happens when you get no error? Do the results match what you expect it to do?

Hope this helps [smile].

Share this post


Link to post
Share on other sites
Almost forgot, I once had a hellish time trying to lock two buffers at the same time with MDX2. One of my conclusions was that it might not be possible. If none of the options I mentioned works, perhaps you could try locking the read first, copying the data to a temporary array, and then writing it after unlocking the read texture.

Hope this helps.

Share this post


Link to post
Share on other sites
Quote:
Original post by sirob
I can see a couple things here:
1) You're not using the pitch returned by lock call. You'll need to use a different overload to have it returned, but it is highly recommended you use the pitch value when writing/reading from textures or surfaces.


But then how would I use it? Add it to GraphicsStream.Position?

Quote:
Original post by sirob
2) Does GraphicsStream::Position take a value in bytes? I wouldn't be surprised if it took an index of the item to set it to, in which case your * 4 would make you go out of bounds.


I'm pretty sure it does since that part is based on the IO.Stream class. See the next point.

Quote:
Original post by sirob
Also, you mention it only fails some of the times. What happens when you get no error? Do the results match what you expect it to do?


When I get no error everything appears as it should.

Also I've sort of solved this by setting the textures usage to Usage.Dynamic and the pool to Pool.Default, but I'd like a more "proper" solution. I don't need them to be dynamic since they're only written to when the level loads.

Share this post


Link to post
Share on other sites
Quote:
Original post by Scet
Quote:
Original post by sirob
I can see a couple things here:
1) You're not using the pitch returned by lock call. You'll need to use a different overload to have it returned, but it is highly recommended you use the pitch value when writing/reading from textures or surfaces.


But then how would I use it? Add it to GraphicsStream.Position?


You'd use the pitch returned as the width of the surface. DX might return a surface larger than what you requested when you lock, and you have no control over this. The pitch is returned to allow you to skip an entire row on a surface who's width you wouldn't have any other way of knowing. The pitch's minimum value is the width you specify, and would most likely be equal to your surface's width.

As for the actual problem, I can't say I have any ideas. AFAIK, managed textures should be lockable, and shouldn't behave differently. As I said, my only idea is avoiding two locks at once, but considering it works with Default + Dynamic this is now sounding less likely.

Perhaps someone else will have an idea.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!