[Bug?]xxxSharedPtr Class in Mogre will be disposed by GC?

issingle

26-03-2010 06:44:53

After two days test,i doubt that xxxSharedPtr(such as HardwareVertexBufferSharedPtr) instance will be collect by .net GC at runtime.
it's unbelievable,right? :(

What steps will reproduce the problem?
1. run the GetMeshInformation function ( see http://www.ogre3d.org/wiki/index.php/Raycasting_to_the_polygon_level_%28Mogre%29#GetMeshInformation) or MMOC's raycast function http://www.ogre3d.org/addonforums/viewtopic.php?f=8&t=8615&start=0 at main loop.
2. after some seconds( or minutes,or hours),a AccessViolationException will be throw,then we can found the xxxSharedPtr's "Target" data was lost.

What version of the product am i using? On what operating system?
mogre 1.4.8,mogre1.6.5,WinXp Sp2

ps:
i added a log in ~VertexData ~IndexData(at MogreVertexIndexData.h ) and compiled mogre. Befor app crash,the vertex or index data was destroyed,then app crash.

if i keep a reference of xxxSharedPtr's instance in myowen class(such as a Dictionary<id,xxxSharedPtr>),when i post this bug report,the demo has been run five hours and it looks fine.

//test code from SDK's MogreForm,take some modify,use MMOC for raycast
mogreWin.Paint();
Random rnd = new Random();
float x = Convert.ToSingle(rnd.NextDouble());
float y = Convert.ToSingle(rnd.NextDouble());
float z = Convert.ToSingle(rnd.NextDouble());
mogreWin.m_Entity.ParentSceneNode.Position = new Vector3(x, y, z);

Vector3 ori = new Vector3(50, 50, 50);
Ray ray = new Ray(ori, (Vector3.ZERO - ori).NormalisedCopy);
MMOC.CollisionTools.RaycastResult rt = ct.Raycast(ray, SceneManager.ENTITY_TYPE_MASK);

if (rt != null) {
string s = rt.Position.ToString();
}



// GetMeshInformation function ,see http://www.ogre3d.org/wiki/index.php/Raycasting_to_the_polygon_level_%28Mogre%29#GetMeshInformation
// Get the mesh information for the given mesh.
public unsafe void GetMeshInformation(MeshPtr mesh,
ref uint vertex_count,
ref Vector3[] vertices,
ref uint index_count,
ref UInt64[] indices,
Vector3 position,
Quaternion orientation,
Vector3 scale)
{
bool added_shared = false;
uint current_offset = 0;
uint shared_offset = 0;
uint next_offset = 0;
uint index_offset = 0;

vertex_count = index_count = 0;

for (ushort i = 0; i < mesh.NumSubMeshes; ++i)
{
SubMesh submesh = mesh.GetSubMesh(i);
if (submesh.useSharedVertices)
{
if (!added_shared)
{
vertex_count += mesh.sharedVertexData.vertexCount;
added_shared = true;
}
}
else
{
vertex_count += submesh.vertexData.vertexCount;
}

index_count += submesh.indexData.indexCount;
}

vertices = new Vector3[vertex_count];
indices = new UInt64[index_count];
added_shared = false;

for (ushort i = 0; i < mesh.NumSubMeshes; ++i)
{
SubMesh submesh = mesh.GetSubMesh(i);
VertexData vertex_data = submesh.useSharedVertices ? mesh.sharedVertexData : submesh.vertexData;

if (!submesh.useSharedVertices || (submesh.useSharedVertices && !added_shared))
{
if (submesh.useSharedVertices)
{
added_shared = true;
shared_offset = current_offset;
}

VertexElement posElem =
vertex_data.vertexDeclaration.FindElementBySemantic(VertexElementSemantic.VES_POSITION);
HardwareVertexBufferSharedPtr vbuf =
vertex_data.vertexBufferBinding.GetBuffer(posElem.Source);

byte* vertex = (byte*)vbuf.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY);
float* pReal;

for (int j = 0; j < vertex_data.vertexCount; ++j, vertex += vbuf.VertexSize)
{
posElem.BaseVertexPointerToElement(vertex, &pReal);
Vector3 pt = new Vector3(pReal[0], pReal[1], pReal[2]);
vertices[current_offset + j] = (orientation * (pt * scale)) + position;
}
vbuf.Unlock();
next_offset += vertex_data.vertexCount;
}

IndexData index_data = submesh.indexData;
uint numTris = index_data.indexCount / 3;
HardwareIndexBufferSharedPtr ibuf = index_data.indexBuffer;

bool use32bitindexes = (ibuf.Type == HardwareIndexBuffer.IndexType.IT_32BIT);

ulong* pLong = (ulong*)ibuf.Lock(HardwareBuffer.LockOptions.HBL_READ_ONLY);
ushort* pShort = (ushort*)pLong;
uint offset = submesh.useSharedVertices ? shared_offset : current_offset;
if (use32bitindexes)
{
for (int k = 0; k < index_data.indexCount; ++k)
{
indices[index_offset++] = (UInt64)pLong[k] + (UInt64)offset;
}
}
else
{
for (int k = 0; k < index_data.indexCount; ++k)
{
indices[index_offset++] = (UInt64)pShort[k] + (UInt64)offset;
}
}
ibuf.Unlock();
current_offset = next_offset;
}

} // GetMeshInformation

smiley80

26-03-2010 07:06:06

You have to dispose the buffer after you unlock them.

issingle

26-03-2010 10:18:33

Dispose() will speed up crash.
the issue still exists.

smiley80

26-03-2010 10:55:13

Please try the GetMeshInformation method from:
http://code.google.com/p/minimal-ogre-c ... onTools.cs

issingle

27-03-2010 00:31:39

en..i did use the code from MMOC in the test. :(