aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
authorDan Lake2009-10-05 05:35:56 -0700
committerMelanie2009-10-05 12:45:41 +0100
commit6d52974c5f8184c03e3366fdcce03e4ec15c85f6 (patch)
tree7a1c7a7db8446b9f7bf59fcc367d347c5e00a50a /OpenSim/Region/Physics
parentonly cache mesh if meshing was successful (diff)
downloadopensim-SC-6d52974c5f8184c03e3366fdcce03e4ec15c85f6.zip
opensim-SC-6d52974c5f8184c03e3366fdcce03e4ec15c85f6.tar.gz
opensim-SC-6d52974c5f8184c03e3366fdcce03e4ec15c85f6.tar.bz2
opensim-SC-6d52974c5f8184c03e3366fdcce03e4ec15c85f6.tar.xz
Eliminate pinned Mesh data on managed heap by using IntPtrs to memory allocated on the unmanaged heap. This prevents fragmentation of the managed heap and the resulting stress on GC. A region with ~150,000 prims using ODE and Meshmerizer saw memory remain flat around 1.2GB as opposed to 1.5GB and continually growing due to pinned memory. This patch complements the unique mesh dictionary patch applied to Meshmerizer but is independent. The net effect is a 60-75% reduction in memory for our largest regions.
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/Manager/IMesher.cs2
-rw-r--r--OpenSim/Region/Physics/Meshing/Mesh.cs166
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs13
3 files changed, 120 insertions, 61 deletions
diff --git a/OpenSim/Region/Physics/Manager/IMesher.cs b/OpenSim/Region/Physics/Manager/IMesher.cs
index e26c623..ac14292 100644
--- a/OpenSim/Region/Physics/Manager/IMesher.cs
+++ b/OpenSim/Region/Physics/Manager/IMesher.cs
@@ -47,6 +47,8 @@ namespace OpenSim.Region.Physics.Manager
47 int[] getIndexListAsInt(); 47 int[] getIndexListAsInt();
48 int[] getIndexListAsIntLocked(); 48 int[] getIndexListAsIntLocked();
49 float[] getVertexListAsFloatLocked(); 49 float[] getVertexListAsFloatLocked();
50 void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount);
51 void getVertexListAsPtrToFloatArray( out IntPtr vertexList, out int vertexStride, out int vertexCount );
50 void releaseSourceMeshData(); 52 void releaseSourceMeshData();
51 void releasePinned(); 53 void releasePinned();
52 void Append(IMesh newMesh); 54 void Append(IMesh newMesh);
diff --git a/OpenSim/Region/Physics/Meshing/Mesh.cs b/OpenSim/Region/Physics/Meshing/Mesh.cs
index aae8871..ff1f816 100644
--- a/OpenSim/Region/Physics/Meshing/Mesh.cs
+++ b/OpenSim/Region/Physics/Meshing/Mesh.cs
@@ -36,23 +36,27 @@ namespace OpenSim.Region.Physics.Meshing
36{ 36{
37 public class Mesh : IMesh 37 public class Mesh : IMesh
38 { 38 {
39 private Dictionary<Vertex, int> vertices; 39 private Dictionary<Vertex, int> m_vertices;
40 private List<Triangle> triangles; 40 private List<Triangle> m_triangles;
41 GCHandle pinnedVirtexes; 41 GCHandle m_pinnedVertexes;
42 GCHandle pinnedIndex; 42 GCHandle m_pinnedIndex;
43 public float[] normals; 43 IntPtr m_verticesPtr = IntPtr.Zero;
44 int m_vertexCount = 0;
45 IntPtr m_indicesPtr = IntPtr.Zero;
46 int m_indexCount = 0;
47 public float[] m_normals;
44 48
45 public Mesh() 49 public Mesh()
46 { 50 {
47 vertices = new Dictionary<Vertex, int>(); 51 m_vertices = new Dictionary<Vertex, int>();
48 triangles = new List<Triangle>(); 52 m_triangles = new List<Triangle>();
49 } 53 }
50 54
51 public Mesh Clone() 55 public Mesh Clone()
52 { 56 {
53 Mesh result = new Mesh(); 57 Mesh result = new Mesh();
54 58
55 foreach (Triangle t in triangles) 59 foreach (Triangle t in m_triangles)
56 { 60 {
57 result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone())); 61 result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
58 } 62 }
@@ -62,27 +66,27 @@ namespace OpenSim.Region.Physics.Meshing
62 66
63 public void Add(Triangle triangle) 67 public void Add(Triangle triangle)
64 { 68 {
65 if (pinnedIndex.IsAllocated || pinnedVirtexes.IsAllocated) 69 if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
66 throw new NotSupportedException("Attempt to Add to a pinned Mesh"); 70 throw new NotSupportedException("Attempt to Add to a pinned Mesh");
67 // If a vertex of the triangle is not yet in the vertices list, 71 // If a vertex of the triangle is not yet in the vertices list,
68 // add it and set its index to the current index count 72 // add it and set its index to the current index count
69 if (!vertices.ContainsKey(triangle.v1)) 73 if( !m_vertices.ContainsKey(triangle.v1) )
70 vertices[triangle.v1] = vertices.Count; 74 m_vertices[triangle.v1] = m_vertices.Count;
71 if (!vertices.ContainsKey(triangle.v2)) 75 if (!m_vertices.ContainsKey(triangle.v2))
72 vertices[triangle.v2] = vertices.Count; 76 m_vertices[triangle.v2] = m_vertices.Count;
73 if (!vertices.ContainsKey(triangle.v3)) 77 if (!m_vertices.ContainsKey(triangle.v3))
74 vertices[triangle.v3] = vertices.Count; 78 m_vertices[triangle.v3] = m_vertices.Count;
75 triangles.Add(triangle); 79 m_triangles.Add(triangle);
76 } 80 }
77 81
78 public void CalcNormals() 82 public void CalcNormals()
79 { 83 {
80 int iTriangles = triangles.Count; 84 int iTriangles = m_triangles.Count;
81 85
82 this.normals = new float[iTriangles * 3]; 86 this.m_normals = new float[iTriangles * 3];
83 87
84 int i = 0; 88 int i = 0;
85 foreach (Triangle t in triangles) 89 foreach (Triangle t in m_triangles)
86 { 90 {
87 float ux, uy, uz; 91 float ux, uy, uz;
88 float vx, vy, vz; 92 float vx, vy, vz;
@@ -129,9 +133,9 @@ namespace OpenSim.Region.Physics.Meshing
129 //ny /= l; 133 //ny /= l;
130 //nz /= l; 134 //nz /= l;
131 135
132 normals[i] = nx * lReciprocal; 136 m_normals[i] = nx * lReciprocal;
133 normals[i + 1] = ny * lReciprocal; 137 m_normals[i + 1] = ny * lReciprocal;
134 normals[i + 2] = nz * lReciprocal; 138 m_normals[i + 2] = nz * lReciprocal;
135 139
136 i += 3; 140 i += 3;
137 } 141 }
@@ -140,45 +144,70 @@ namespace OpenSim.Region.Physics.Meshing
140 public List<PhysicsVector> getVertexList() 144 public List<PhysicsVector> getVertexList()
141 { 145 {
142 List<PhysicsVector> result = new List<PhysicsVector>(); 146 List<PhysicsVector> result = new List<PhysicsVector>();
143 foreach (Vertex v in vertices.Keys) 147 foreach (Vertex v in m_vertices.Keys)
144 { 148 {
145 result.Add(v); 149 result.Add(v);
146 } 150 }
147 return result; 151 return result;
148 } 152 }
149 153
150 public float[] getVertexListAsFloatLocked() 154 private float[] getVertexListAsFloat()
151 { 155 {
152 if (pinnedVirtexes.IsAllocated) 156 if(m_vertices == null)
153 return (float[])(pinnedVirtexes.Target); 157 throw new NotSupportedException();
154 float[] result; 158 float[] result = new float[m_vertices.Count * 3];
155 159 foreach (KeyValuePair<Vertex, int> kvp in m_vertices)
156 //m_log.WarnFormat("vertices.Count = {0}", vertices.Count);
157 result = new float[vertices.Count * 3];
158 foreach (KeyValuePair<Vertex, int> kvp in vertices)
159 { 160 {
160 Vertex v = kvp.Key; 161 Vertex v = kvp.Key;
161 int i = kvp.Value; 162 int i = kvp.Value;
162 //m_log.WarnFormat("kvp.Value = {0}", i);
163 result[3 * i + 0] = v.X; 163 result[3 * i + 0] = v.X;
164 result[3 * i + 1] = v.Y; 164 result[3 * i + 1] = v.Y;
165 result[3 * i + 2] = v.Z; 165 result[3 * i + 2] = v.Z;
166 } 166 }
167 pinnedVirtexes = GCHandle.Alloc(result, GCHandleType.Pinned);
168 return result; 167 return result;
169 } 168 }
170 169
171 public int[] getIndexListAsInt() 170 public float[] getVertexListAsFloatLocked()
172 { 171 {
173 int[] result; 172 if( m_pinnedVertexes.IsAllocated )
173 return (float[])(m_pinnedVertexes.Target);
174 174
175 result = new int[triangles.Count * 3]; 175 float[] result = getVertexListAsFloat();
176 for (int i = 0; i < triangles.Count; i++) 176 m_pinnedVertexes = GCHandle.Alloc(result, GCHandleType.Pinned);
177
178 return result;
179 }
180
181 public void getVertexListAsPtrToFloatArray(out IntPtr vertices, out int vertexStride, out int vertexCount)
182 {
183 // A vertex is 3 floats
184 vertexStride = 3 * sizeof(float);
185
186 // If there isn't an unmanaged array allocated yet, do it now
187 if (m_verticesPtr == IntPtr.Zero)
177 { 188 {
178 Triangle t = triangles[i]; 189 float[] vertexList = getVertexListAsFloat();
179 result[3 * i + 0] = vertices[t.v1]; 190 // Each vertex is 3 elements (floats)
180 result[3 * i + 1] = vertices[t.v2]; 191 m_vertexCount = vertexList.Length / 3;
181 result[3 * i + 2] = vertices[t.v3]; 192 int byteCount = m_vertexCount * vertexStride;
193 m_verticesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
194 System.Runtime.InteropServices.Marshal.Copy(vertexList, 0, m_verticesPtr, m_vertexCount * 3);
195 }
196 vertices = m_verticesPtr;
197 vertexCount = m_vertexCount;
198 }
199
200 public int[] getIndexListAsInt()
201 {
202 if (m_triangles == null)
203 throw new NotSupportedException();
204 int[] result = new int[m_triangles.Count * 3];
205 for (int i = 0; i < m_triangles.Count; i++)
206 {
207 Triangle t = m_triangles[i];
208 result[3 * i + 0] = m_vertices[t.v1];
209 result[3 * i + 1] = m_vertices[t.v2];
210 result[3 * i + 2] = m_vertices[t.v3];
182 } 211 }
183 return result; 212 return result;
184 } 213 }
@@ -189,19 +218,48 @@ namespace OpenSim.Region.Physics.Meshing
189 /// <returns></returns> 218 /// <returns></returns>
190 public int[] getIndexListAsIntLocked() 219 public int[] getIndexListAsIntLocked()
191 { 220 {
192 if (pinnedIndex.IsAllocated) 221 if (m_pinnedIndex.IsAllocated)
193 return (int[])(pinnedIndex.Target); 222 return (int[])(m_pinnedIndex.Target);
194 223
195 int[] result = getIndexListAsInt(); 224 int[] result = getIndexListAsInt();
196 pinnedIndex = GCHandle.Alloc(result, GCHandleType.Pinned); 225 m_pinnedIndex = GCHandle.Alloc(result, GCHandleType.Pinned);
197 226
198 return result; 227 return result;
199 } 228 }
200 229
230 public void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount)
231 {
232 // If there isn't an unmanaged array allocated yet, do it now
233 if (m_indicesPtr == IntPtr.Zero)
234 {
235 int[] indexList = getIndexListAsInt();
236 m_indexCount = indexList.Length;
237 int byteCount = m_indexCount * sizeof(int);
238 m_indicesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
239 System.Runtime.InteropServices.Marshal.Copy(indexList, 0, m_indicesPtr, m_indexCount);
240 }
241 // A triangle is 3 ints (indices)
242 triStride = 3 * sizeof(int);
243 indices = m_indicesPtr;
244 indexCount = m_indexCount;
245 }
246
201 public void releasePinned() 247 public void releasePinned()
202 { 248 {
203 pinnedVirtexes.Free(); 249 if (m_pinnedVertexes.IsAllocated)
204 pinnedIndex.Free(); 250 m_pinnedVertexes.Free();
251 if (m_pinnedIndex.IsAllocated)
252 m_pinnedIndex.Free();
253 if (m_verticesPtr != IntPtr.Zero)
254 {
255 System.Runtime.InteropServices.Marshal.FreeHGlobal(m_verticesPtr);
256 m_verticesPtr = IntPtr.Zero;
257 }
258 if (m_indicesPtr != IntPtr.Zero)
259 {
260 System.Runtime.InteropServices.Marshal.FreeHGlobal(m_indicesPtr);
261 m_indicesPtr = IntPtr.Zero;
262 }
205 } 263 }
206 264
207 /// <summary> 265 /// <summary>
@@ -209,29 +267,29 @@ namespace OpenSim.Region.Physics.Meshing
209 /// </summary> 267 /// </summary>
210 public void releaseSourceMeshData() 268 public void releaseSourceMeshData()
211 { 269 {
212 triangles = null; 270 m_triangles = null;
213 vertices = null; 271 m_vertices = null;
214 } 272 }
215 273
216 public void Append(IMesh newMesh) 274 public void Append(IMesh newMesh)
217 { 275 {
218 if (pinnedIndex.IsAllocated || pinnedVirtexes.IsAllocated) 276 if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
219 throw new NotSupportedException("Attempt to Append to a pinned Mesh"); 277 throw new NotSupportedException("Attempt to Append to a pinned Mesh");
220 278
221 if (!(newMesh is Mesh)) 279 if (!(newMesh is Mesh))
222 return; 280 return;
223 281
224 foreach (Triangle t in ((Mesh)newMesh).triangles) 282 foreach (Triangle t in ((Mesh)newMesh).m_triangles)
225 Add(t); 283 Add(t);
226 } 284 }
227 285
228 // Do a linear transformation of mesh. 286 // Do a linear transformation of mesh.
229 public void TransformLinear(float[,] matrix, float[] offset) 287 public void TransformLinear(float[,] matrix, float[] offset)
230 { 288 {
231 if (pinnedIndex.IsAllocated || pinnedVirtexes.IsAllocated) 289 if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
232 throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh"); 290 throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh");
233 291
234 foreach (Vertex v in vertices.Keys) 292 foreach (Vertex v in m_vertices.Keys)
235 { 293 {
236 if (v == null) 294 if (v == null)
237 continue; 295 continue;
@@ -252,7 +310,7 @@ namespace OpenSim.Region.Physics.Meshing
252 String fileName = name + "_" + title + ".raw"; 310 String fileName = name + "_" + title + ".raw";
253 String completePath = Path.Combine(path, fileName); 311 String completePath = Path.Combine(path, fileName);
254 StreamWriter sw = new StreamWriter(completePath); 312 StreamWriter sw = new StreamWriter(completePath);
255 foreach (Triangle t in triangles) 313 foreach (Triangle t in m_triangles)
256 { 314 {
257 String s = t.ToStringRaw(); 315 String s = t.ToStringRaw();
258 sw.WriteLine(s); 316 sw.WriteLine(s);
@@ -262,7 +320,7 @@ namespace OpenSim.Region.Physics.Meshing
262 320
263 public void TrimExcess() 321 public void TrimExcess()
264 { 322 {
265 triangles.TrimExcess(); 323 m_triangles.TrimExcess();
266 } 324 }
267 } 325 }
268} 326}
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index 032b5df..c041243 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -813,18 +813,17 @@ namespace OpenSim.Region.Physics.OdePlugin
813 } 813 }
814 } 814 }
815 815
816 float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory 816 IntPtr vertices, indices;
817 int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage 817 int vertexCount, indexCount;
818 int vertexStride, triStride;
819 mesh.getVertexListAsPtrToFloatArray( out vertices, out vertexStride, out vertexCount ); // Note, that vertices are fixed in unmanaged heap
820 mesh.getIndexListAsPtrToIntArray( out indices, out triStride, out indexCount ); // Also fixed, needs release after usage
818 821
819 mesh.releaseSourceMeshData(); // free up the original mesh data to save memory 822 mesh.releaseSourceMeshData(); // free up the original mesh data to save memory
820 823
821 int VertexCount = vertexList.GetLength(0)/3;
822 int IndexCount = indexList.GetLength(0);
823
824 _triMeshData = d.GeomTriMeshDataCreate(); 824 _triMeshData = d.GeomTriMeshDataCreate();
825 825
826 d.GeomTriMeshDataBuildSimple(_triMeshData, vertexList, 3*sizeof (float), VertexCount, indexList, IndexCount, 826 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
827 3*sizeof (int));
828 d.GeomTriMeshDataPreprocess(_triMeshData); 827 d.GeomTriMeshDataPreprocess(_triMeshData);
829 828
830 _parent_scene.waitForSpaceUnlock(m_targetSpace); 829 _parent_scene.waitForSpaceUnlock(m_targetSpace);