[fixed]TextureMatrix bug

You discovered a bug in the engine, and you are sure that it is not a problem of your code? Just post it in here. Please read the bug posting guidelines first.
NoName4ever
Posts: 10
Joined: Fri Dec 01, 2006 5:38 am

[fixed]TextureMatrix bug

Post by NoName4ever »

Hi!

I was playing with Irr 1.3 for sometime and in love with its simplicity. But I can't use it for my project now because of TextureMatrix bug.

How to reproduce:

1. Download Irr 1.3
2. Load Irrlicht8.0.sln using VS.NET 2005 SP1 (Vista box)
3. Add Examples/Movement demo
4. Go to line 123 and add this line after it:

Code: Select all

node->getMaterial(0).getTextureMatrix(0).setTextureScale(30,30);
5. Compile and run in Debug mode.

The bugs:

1. It always crash upon exit.
The SS of Visual Studio:

Image

2. The texture showed is erroneous in D3D9 and OpenGL 1.5 but it seem to look fine in Burning Software Renderer.

Erroneous texture SS:

Image
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

The problem is that the memory for the texture matrix is allocated from a different heap than it is freed to. The call node->getMaterial(0).getTextureMatrix(0).setTextureScale(30,30) results in a call to the inline function...

Code: Select all

core::matrix4& getTextureMatrix(u32 i)
{
  if (i<MATERIAL_MAX_TEXTURES && !TextureMatrix[i])
    TextureMatrix[i] = new core::matrix4(core::matrix4::EM4CONST_IDENTITY);
  return *TextureMatrix[i];
}
So the call to new is compiled into the executable.

The CMeshBuffer and SMaterial destructors are inline, so they are likely compiled into the function that calls them. The CCubeSceneNode/CSphereSceneNode destructor is compiled into the Irrlicht.dll.

So the allocation comes from the heap that is in the executable, but the deallocation is being done by the heap that is in the dll. To fix, you would end up writing some of the SMaterial methods out of line so that they are compiled into the Irrlicht dll.

Travis
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Ah, that's why I could not reproduce it. Linux handles even libraries inside each process context. Is there any other chance besides making the allocation/deallocation methods part of the dll? What about compiler decisions about inline - methods can even be inlined without the keyword in front (or being part of the class definition).
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Well, the inline keyword is just a hint to the compiler that you'd like a method inlined where it is used. If you write a function inside a class declaration, it is implicitly inlined.

You could write a function to allocate memory from the Irrlicht.dll heap and a matching function to release memory to the Irrlicht.dll heap. Then call those functions. I don't think it makes sense for the material to own an allocator, and even if it did, I'm not absolutely convinced that the irrAllocator actually solves the dll boundary problem.

Travis
robarnold
Posts: 1
Joined: Wed Jun 20, 2007 6:15 am

Post by robarnold »

I came across this bug as well. Another solution is to recompile Irrlicht.dll with the multithreaded dll crt instead of the multithreaded crt. Now all allocations between irrlicht and your executable (assuming you use the multithreaded dll crt) will use the same heap.

You can change this setting in visual studio by going to the project properties, C/C++, Code Generation, Runtime Library.

As for the second problem, I ran across this too. In each hardware driver (ogl/d3d)'s setTransform method, there is a check made against texture matrices for the identity matrix and the call returns early if the given matrix is the identity. This seems like it was intended to be an optimization for the common case (since SMaterial::getTextureMatrix will return an identity matrix) where no texture matrix is set. However in my own project (and presumably the example), the texture matrix needs to be set to the identity because the current texture transform is not the identity.

I see two quick workarounds: comment out the check or twiddle your identity matrices (assuming you know when they are the identity) so that they appear to not be the identity matrix; this is actually rather difficult since matrix4::isIdentity tries hard to get the right answer. I feel much better about the former solution than the latter.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

The reset has been fixed recently. It did not make it into the 1.3.1 release, but it's at least fixed in SVN. Seems indeed like an optimization, but a proper reset is definitely needed.
NoName4ever
Posts: 10
Joined: Fri Dec 01, 2006 5:38 am

Post by NoName4ever »

Thanks for all replies. I will try them today.
NoName4ever
Posts: 10
Joined: Fri Dec 01, 2006 5:38 am

Post by NoName4ever »

Thanks guys! It works like charm now.

But I felt that those kind of bug should be well eliminated in 1.31. Maybe we need more defensive update? (Test more before releasing). I've been using OGRE for years without any major issues.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

The thing is that we do not have examples for all features of Irrlicht. Moreover, the bug did not show up in my example. At least not all the time. I saw it some time ago, but since I'm not constantly working at the same machine I did not track it down to the end. But as you see, if someone reproduces this problem it's often fixed quite fast. the reason it was not fixed in 1.3.1 was simply the overlapping of the test phase of 1.3.1 and the bug fix. I was some days late.
Yustme
Posts: 107
Joined: Sat Dec 01, 2007 10:50 pm

Post by Yustme »

Hi guys,

I'm having this problem too at the moment and i'm using version 1.4.

I was trying to scale a texture.

This is how i tried it:

Code: Select all

if(wall)
	{
		CMatrix4<f32> scaleTexture;
		scaleTexture.makeIdentity();
		scaleTexture.setTextureScale(16,16);
		wall->setMaterialFlag(video::EMF_LIGHTING, false);
		wall->setMaterialTexture(0, driver->getTexture("poolTabel.jpg"));
		wall->getMaterial(0).setTextureMatrix(0, scaleTexture);
		wall->setVisible(visible);
	}
Works fine, but when i'm trying to exit the game, it crashes and pointing to line 119 "delete this" in header file: ireferencecounted.h.

Runtime error message:
Windows has triggered a breakpoint in game.exe.

This may be due to a corruption of the heap, and indicates a bug in game.exe or any of the DLLs it has loaded.

The output window may have more diagnostic information
I dont quite understand the work arounds previously mentioned.

Can somebody explain me how to fix this?

Thanks in advance!
Last edited by Yustme on Wed Jan 02, 2008 7:16 pm, edited 1 time in total.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

I suggest you try commenting out the call to setTexureMatrix(). If the failure goes away, then you have a pretty good indicator of what is causing the problem. If the failure remains, then you need to look elsewhere.

It might also help if you had a look at the stack trace. It will tell you what functions were called that led up to the failure.

Honestly, I don't think the problem is actually fixed. A correct solution would require the deallocation routine to use the same heap as the allocation routine. The destructor of some of the Irrlicht provided scene nodes will delete the texture matrices, and this delete happens inside the dll heap. The call to setTextureMatrix() is still inlined, and it is still in the user executable, so the call to allocate the matrix can still be inlined.

Of course the other solution would be to make sure that the user executable and the dll both use the same shared runtime library flag [/MD in MSVC].

Travis
Yustme
Posts: 107
Joined: Sat Dec 01, 2007 10:50 pm

Post by Yustme »

Hi Travis,

I've looked a few times in the stacktrace, but i found nothing useful.

Stacktrace:

Code: Select all

 	ntdll.dll!7c901230() 	
 	[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]	
 	ntdll.dll!7c96c943() 	
 	ntdll.dll!7c96cd80() 	
 	ntdll.dll!7c96df66() 	
 	ntdll.dll!7c96e0f0() 	
 	ntdll.dll!7c94a5d0() 	
 	ntdll.dll!7c96e0d4() 	
 	ntdll.dll!7c94a5d0() 	
 	ntdll.dll!7c926abe() 	
 	ntdll.dll!7c91056d() 	
 	ntdll.dll!7c926abe() 	
 	ntdll.dll!7c9268ad() 	
 	ntdll.dll!7c91056d() 	
 	ntdll.dll!7c9268ad() 	
 	ntdll.dll!7c926abe() 	
 	ntdll.dll!7c9268ad() 	
 	ntdll.dll!7c91056d() 	
 	ntdll.dll!7c91056d() 	
 	kernel32.dll!7c80997a() 	
 	kernel32.dll!7c80998d() 	
 	d3d9.dll!4fdfb208() 	
 	Irrlicht.dll!00544882() 	
 	Irrlicht.dll!00498bfc() 	
 	Irrlicht.dll!004dced1() 	
 	Irrlicht.dll!0049e3b2() 	
 	Irrlicht.dll!0049df1a() 	
 	Irrlicht.dll!004a03f7() 	
 	Irrlicht.dll!0049ff05() 	
 	Irrlicht.dll!00515ec9() 	
 	Irrlicht.dll!00517028() 	
>	game.exe!irr::IReferenceCounted::drop()  Line 119 + 0x34 bytes	C++
 	game.exe!main(int argc=1, char * * argv=0x003a5e70)  Line 369	C++
 	game.exe!__tmainCRTStartup()  Line 597 + 0x19 bytes	C
 	game.exe!mainCRTStartup()  Line 414	C
 	kernel32.dll!7c816ff7() 	
This runtime error happens right after "device->drop".

If i comment the line:

wall->getMaterial(0).setTextureMatrix(0, scaleTexture);

Then the error doesn't show up.

The "runtime library flag [/MD in MSVC]" is standard set on this value, that didn't fixed the bug either.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

How about you make it so that TextureMatrices are initialised at startup regardless of whether they are in use or not, instead of when they are first modified. 64 bytes is really not something to fuss over, especially when it introduces this kind of inconvenience.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

It's 64*4*#materials (or 64*8 if you want more textures). Since materials are reproduced for each meshbuffer this will lead to quite some memory consumption.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

Ok I will have to think of a better solution for this. How about a helper function that returns the texture matrices through irrlicht? Like:

Code: Select all

driver->getTextureMatrixOfMaterial(SMaterial& material);
That should fix it right?

The reason I want to get this sorted out is because I plan to use the TextureLayer TextureMatrix as the interface for supplying the projective matrix in my projective texturing addition.
Last edited by BlindSide on Tue Jul 08, 2008 5:53 am, edited 1 time in total.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Post Reply