From 36a1248b317cd80717fef6bc7c8fab318172a075 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Mon, 6 Aug 2012 09:06:46 +0100 Subject: [PATCH] ** DANGER someone should stress test more ** release unused physics meshs, including unmanaged memory allocations (allocated by managed code) --- OpenSim/Region/Physics/Manager/IMesher.cs | 2 + OpenSim/Region/Physics/Manager/ZeroMesher.cs | 2 + OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 2 + OpenSim/Region/Physics/UbitMeshing/Mesh.cs | 55 ++++---- .../Region/Physics/UbitMeshing/Meshmerizer.cs | 117 ++++++++++++++++-- .../Region/Physics/UbitOdePlugin/ODEPrim.cs | 32 ++--- .../Region/Physics/UbitOdePlugin/OdeScene.cs | 19 ++- 7 files changed, 174 insertions(+), 55 deletions(-) diff --git a/OpenSim/Region/Physics/Manager/IMesher.cs b/OpenSim/Region/Physics/Manager/IMesher.cs index c32cf38e5d..19aa74706d 100644 --- a/OpenSim/Region/Physics/Manager/IMesher.cs +++ b/OpenSim/Region/Physics/Manager/IMesher.cs @@ -37,6 +37,8 @@ namespace OpenSim.Region.Physics.Manager IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod); IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical); IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical,bool convex); + void ReleaseMesh(IMesh mesh); + void ExpireReleaseMeshs(); } // Values for level of detail to be passed to the mesher. diff --git a/OpenSim/Region/Physics/Manager/ZeroMesher.cs b/OpenSim/Region/Physics/Manager/ZeroMesher.cs index 8a3b50bdad..f555cb9253 100644 --- a/OpenSim/Region/Physics/Manager/ZeroMesher.cs +++ b/OpenSim/Region/Physics/Manager/ZeroMesher.cs @@ -79,5 +79,7 @@ namespace OpenSim.Region.Physics.Manager return null; } + public void ReleaseMesh(IMesh mesh) { } + public void ExpireReleaseMeshs() { } } } diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 825b858a92..3c4f737f9e 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -763,5 +763,7 @@ namespace OpenSim.Region.Physics.Meshing return mesh; } + public void ReleaseMesh(IMesh imesh) { } + public void ExpireReleaseMeshs() { } } } diff --git a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs index c715642bac..0727802080 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 3b1bdfb633..a894e5fe80 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(); + } + } + } } } diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs index a3534a49b5..fbc61342af 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs @@ -57,7 +57,6 @@ using OdeAPI; using OpenSim.Framework; using OpenSim.Region.Physics.Manager; - namespace OpenSim.Region.Physics.OdePlugin { public class OdePrim : PhysicsActor @@ -538,24 +537,6 @@ namespace OpenSim.Region.Physics.OdePlugin { set { -/* - IMesh mesh = null; - if (_parent_scene.needsMeshing(value)) - { - bool convex; - if (m_shapetype == 0) - convex = false; - else - convex = true; - mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true, convex); - } - - if (mesh != null) - { - lock (m_meshlock) - m_mesh = mesh; - } -*/ AddChange(changes.Shape, value); } } @@ -1357,7 +1338,6 @@ namespace OpenSim.Region.Physics.OdePlugin IMesh mesh = null; - lock (m_meshlock) { if (m_mesh == null) @@ -1403,7 +1383,7 @@ namespace OpenSim.Region.Physics.OdePlugin hasOOBoffsetFromMesh = true; mesh.releaseSourceMeshData(); - m_mesh = null; + m_mesh = mesh; } IntPtr geo = IntPtr.Zero; @@ -1545,7 +1525,10 @@ namespace OpenSim.Region.Physics.OdePlugin d.GeomTriMeshDataDestroy(_triMeshData); _triMeshData = IntPtr.Zero; } + } + + // catch (System.AccessViolationException) catch (Exception e) { @@ -1559,6 +1542,13 @@ namespace OpenSim.Region.Physics.OdePlugin { m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name); } + + if (m_mesh != null) + { + _parent_scene.mesher.ReleaseMesh(m_mesh); + m_mesh = null; + } + Body = IntPtr.Zero; hasOOBoffsetFromMesh = false; } diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs index f3ac3ca3c1..3ee519845f 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs @@ -194,7 +194,8 @@ namespace OpenSim.Region.Physics.OdePlugin private float metersInSpace = 25.6f; private float m_timeDilation = 1.0f; - DateTime m_lastframe; + private DateTime m_lastframe; + private DateTime m_lastMeshExpire; public float gravityx = 0f; public float gravityy = 0f; @@ -203,6 +204,8 @@ namespace OpenSim.Region.Physics.OdePlugin private float waterlevel = 0f; private int framecount = 0; + private int m_meshExpireCntr; + // private IntPtr WaterGeom = IntPtr.Zero; // private IntPtr WaterHeightmapData = IntPtr.Zero; // private GCHandle WaterMapHandler = new GCHandle(); @@ -263,7 +266,6 @@ namespace OpenSim.Region.Physics.OdePlugin const int maxContactsbeforedeath = 4000; private volatile int m_global_contactcount = 0; - private IntPtr contactgroup; public ContactData[] m_materialContactsData = new ContactData[8]; @@ -594,6 +596,7 @@ namespace OpenSim.Region.Physics.OdePlugin } m_lastframe = DateTime.UtcNow; + m_lastMeshExpire = m_lastframe; } internal void waitForSpaceUnlock(IntPtr space) @@ -1768,9 +1771,9 @@ namespace OpenSim.Region.Physics.OdePlugin { DateTime now = DateTime.UtcNow; - TimeSpan SinceLastFrame = now - m_lastframe; + TimeSpan timedif = now - m_lastframe; m_lastframe = now; - timeStep = (float)SinceLastFrame.TotalSeconds; + timeStep = (float)timedif.TotalSeconds; // acumulate time so we can reduce error step_time += timeStep; @@ -1972,6 +1975,14 @@ namespace OpenSim.Region.Physics.OdePlugin _badCharacter.Clear(); } } + + timedif = now - m_lastMeshExpire; + + if (timedif.Seconds > 10) + { + mesher.ExpireReleaseMeshs(); + m_lastMeshExpire = now; + } /* int nactivegeoms = d.SpaceGetNumGeoms(ActiveSpace); int nstaticgeoms = d.SpaceGetNumGeoms(StaticSpace);