From 36a1248b317cd80717fef6bc7c8fab318172a075 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Mon, 6 Aug 2012 09:06:46 +0100 Subject: ** DANGER someone should stress test more ** release unused physics meshs, including unmanaged memory allocations (allocated by managed code) --- OpenSim/Region/Physics/UbitMeshing/Mesh.cs | 55 +++++----- OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs | 117 ++++++++++++++++++++-- 2 files changed, 142 insertions(+), 30 deletions(-) (limited to 'OpenSim/Region/Physics/UbitMeshing') diff --git a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs index c715642..0727802 100644 --- a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs +++ b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs @@ -46,8 +46,8 @@ namespace OpenSim.Region.Physics.Meshing IntPtr m_indicesPtr = IntPtr.Zero; int m_indexCount = 0; public float[] m_normals; - Vector3 _centroid; - int _centroidDiv; + Vector3 m_centroid; + int m_centroidDiv; private class vertexcomp : IEqualityComparer { @@ -65,7 +65,6 @@ namespace OpenSim.Region.Physics.Meshing int c = v.Z.GetHashCode(); return (a << 16) ^ (b << 8) ^ c; } - } public Mesh() @@ -74,8 +73,18 @@ namespace OpenSim.Region.Physics.Meshing m_vertices = new Dictionary(vcomp); m_triangles = new List(); - _centroid = Vector3.Zero; - _centroidDiv = 0; + m_centroid = Vector3.Zero; + m_centroidDiv = 0; + } + + public int RefCount { get; set; } + + public ulong Key { get; set; } + + public void Scale(Vector3 scale) + { + + } public Mesh Clone() @@ -86,8 +95,8 @@ namespace OpenSim.Region.Physics.Meshing { result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone())); } - result._centroid = _centroid; - result._centroidDiv = _centroidDiv; + result.m_centroid = m_centroid; + result.m_centroidDiv = m_centroidDiv; return result; } @@ -109,41 +118,41 @@ namespace OpenSim.Region.Physics.Meshing if (m_vertices.Count == 0) { - _centroidDiv = 0; - _centroid = Vector3.Zero; + m_centroidDiv = 0; + m_centroid = Vector3.Zero; } if (!m_vertices.ContainsKey(triangle.v1)) { m_vertices[triangle.v1] = m_vertices.Count; - _centroid.X += triangle.v1.X; - _centroid.Y += triangle.v1.Y; - _centroid.Z += triangle.v1.Z; - _centroidDiv++; + m_centroid.X += triangle.v1.X; + m_centroid.Y += triangle.v1.Y; + m_centroid.Z += triangle.v1.Z; + m_centroidDiv++; } if (!m_vertices.ContainsKey(triangle.v2)) { m_vertices[triangle.v2] = m_vertices.Count; - _centroid.X += triangle.v2.X; - _centroid.Y += triangle.v2.Y; - _centroid.Z += triangle.v2.Z; - _centroidDiv++; + m_centroid.X += triangle.v2.X; + m_centroid.Y += triangle.v2.Y; + m_centroid.Z += triangle.v2.Z; + m_centroidDiv++; } if (!m_vertices.ContainsKey(triangle.v3)) { m_vertices[triangle.v3] = m_vertices.Count; - _centroid.X += triangle.v3.X; - _centroid.Y += triangle.v3.Y; - _centroid.Z += triangle.v3.Z; - _centroidDiv++; + m_centroid.X += triangle.v3.X; + m_centroid.Y += triangle.v3.Y; + m_centroid.Z += triangle.v3.Z; + m_centroidDiv++; } m_triangles.Add(triangle); } public Vector3 GetCentroid() { - if (_centroidDiv > 0) - return new Vector3(_centroid.X / _centroidDiv, _centroid.Y / _centroidDiv, _centroid.Z / _centroidDiv); + if (m_centroidDiv > 0) + return new Vector3(m_centroid.X / m_centroidDiv, m_centroid.Y / m_centroidDiv, m_centroid.Z / m_centroidDiv); else return Vector3.Zero; } diff --git a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs index 3b1bdfb..a894e5f 100644 --- a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs @@ -83,6 +83,7 @@ namespace OpenSim.Region.Physics.Meshing private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh private Dictionary m_uniqueMeshes = new Dictionary(); + private Dictionary m_uniqueReleasedMeshes = new Dictionary(); public Meshmerizer(IConfigSource config) { @@ -986,6 +987,8 @@ namespace OpenSim.Region.Physics.Meshing return CreateMesh(primName, primShape, size, lod, false,false); } + private static Vector3 m_MeshUnitSize = new Vector3(0.5f, 0.5f, 0.5f); + public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) { #if SPAM @@ -995,17 +998,60 @@ namespace OpenSim.Region.Physics.Meshing Mesh mesh = null; ulong key = 0; - // If this mesh has been created already, return it instead of creating another copy - // For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory - key = primShape.GetMeshKey(size, lod, convex); - if (m_uniqueMeshes.TryGetValue(key, out mesh)) - return mesh; - if (size.X < 0.01f) size.X = 0.01f; if (size.Y < 0.01f) size.Y = 0.01f; if (size.Z < 0.01f) size.Z = 0.01f; + // try to find a identical mesh on meshs in use + key = primShape.GetMeshKey(size, lod, convex); + + lock (m_uniqueMeshes) + { + m_uniqueMeshes.TryGetValue(key, out mesh); + + if (mesh != null) + { + mesh.RefCount++; + return mesh; + } + } + + // try to find a identical mesh on meshs recently released + lock (m_uniqueReleasedMeshes) + { + m_uniqueReleasedMeshes.TryGetValue(key, out mesh); + if (mesh != null) + { + m_uniqueReleasedMeshes.Remove(key); + lock (m_uniqueMeshes) + m_uniqueMeshes.Add(key, mesh); + mesh.RefCount = 1; + return mesh; + } + } +/* + Mesh UnitSizeMesh = null; + ulong unitsizekey = 0; + + unitsizekey = primShape.GetMeshKey(m_MeshUnitSize, lod, convex); + + lock(m_uniqueMeshes) + m_uniqueMeshes.TryGetValue(unitsizekey, out UnitSizeMesh); + + if (UnitSizeMesh !=null) + { + UnitSizeMesh.RefCount++; + mesh = UnitSizeMesh.Clone(); + mesh.Key = key; + mesh.Scale(size); + mesh.RefCount++; + lock(m_uniqueMeshes) + m_uniqueMeshes.Add(key, mesh); + return mesh; + } +*/ mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod,convex); +// mesh.Key = unitsizekey; if (mesh != null) { @@ -1021,11 +1067,68 @@ namespace OpenSim.Region.Physics.Meshing // trim the vertex and triangle lists to free up memory mesh.TrimExcess(); + mesh.Key = key; + mesh.RefCount++; - m_uniqueMeshes.Add(key, mesh); + lock(m_uniqueMeshes) + m_uniqueMeshes.Add(key, mesh); } return mesh; } + + public void ReleaseMesh(IMesh imesh) + { + if (imesh == null) + return; + + Mesh mesh = (Mesh)imesh; + + int curRefCount = mesh.RefCount; + curRefCount--; + + if (curRefCount > 0) + { + mesh.RefCount = curRefCount; + return; + } + + lock (m_uniqueMeshes) + { + mesh.RefCount = 0; + m_uniqueMeshes.Remove(mesh.Key); + lock (m_uniqueReleasedMeshes) + m_uniqueReleasedMeshes.Add(mesh.Key, mesh); + } + } + + public void ExpireReleaseMeshs() + { + if (m_uniqueMeshes.Count == 0) + return; + + List meshstodelete = new List(); + int refcntr; + + lock (m_uniqueReleasedMeshes) + { + foreach (Mesh m in m_uniqueReleasedMeshes.Values) + { + refcntr = m.RefCount; + refcntr--; + if (refcntr > -6) + m.RefCount = refcntr; + else + meshstodelete.Add(m); + } + + foreach (Mesh m in meshstodelete) + { + m_uniqueReleasedMeshes.Remove(m.Key); + m.releaseSourceMeshData(); + m.releasePinned(); + } + } + } } } -- cgit v1.1