Ver Fonte

Merge pull request #166 from MeltyPlayer/master

Set _StaticBufferBuilder capacity via constructor when merging buffers to optimize memory allocations.
Vicente Penades há 2 anos atrás
pai
commit
29d6f507b4

+ 2 - 1
src/SharpGLTF.Core/Schema2/gltf.Buffer.cs

@@ -220,7 +220,8 @@ namespace SharpGLTF.Schema2
 
 
             // begin merge
             // begin merge
 
 
-            var sbbuilder = new _StaticBufferBuilder(0);
+            var reservedMemory = (int) (totalLen * 1.01); // increase by 1%
+            var sbbuilder = new _StaticBufferBuilder(0, reservedMemory);
 
 
             foreach (var bv in views) bv._IsolateBufferMemory(sbbuilder);
             foreach (var bv in views) bv._IsolateBufferMemory(sbbuilder);
 
 

+ 3 - 2
src/SharpGLTF.Core/Schema2/gltf.BufferView.cs

@@ -347,9 +347,10 @@ namespace SharpGLTF.Schema2
     {
     {
         #region lifecycle
         #region lifecycle
 
 
-        public _StaticBufferBuilder(int bufferIndex)
+        public _StaticBufferBuilder(int bufferIndex, int initialCapacity = 0)
         {
         {
             _BufferIndex = bufferIndex;
             _BufferIndex = bufferIndex;
+            _Data = new List<byte>(initialCapacity);
         }
         }
 
 
         #endregion
         #endregion
@@ -360,7 +361,7 @@ namespace SharpGLTF.Schema2
         private readonly int _BufferIndex;
         private readonly int _BufferIndex;
 
 
         // accumulated data
         // accumulated data
-        private readonly List<Byte> _Data = new List<byte>();
+        private readonly List<Byte> _Data;
 
 
         #endregion
         #endregion
 
 

+ 101 - 4
tests/SharpGLTF.ThirdParty.Tests/MeltyPlayerTests.cs

@@ -1,13 +1,18 @@
 using System;
 using System;
-using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
 using System.Linq;
 using System.Linq;
 using System.Numerics;
 using System.Numerics;
-using System.Text;
-using System.Threading.Tasks;
 
 
 using NUnit.Framework;
 using NUnit.Framework;
-
+using SharpGLTF.Geometry;
+using SharpGLTF.Geometry.VertexTypes;
+using SharpGLTF.Materials;
+using SharpGLTF.Memory;
+using SharpGLTF.Scenes;
 using SharpGLTF.Schema2;
 using SharpGLTF.Schema2;
+using SharpGLTF.Transforms;
 
 
 namespace SharpGLTF.ThirdParty
 namespace SharpGLTF.ThirdParty
 {
 {
@@ -76,5 +81,97 @@ namespace SharpGLTF.ThirdParty
 
 
             Assert.AreEqual(4, satellites.Length);
             Assert.AreEqual(4, satellites.Length);
         }
         }
+
+        [Test]
+        public void TestHugeSceneViaBuilders() 
+        {
+            // create a scene
+
+            var mesh = new MeshBuilder<VertexPositionNormal, VertexColor2Texture2, VertexJoints8>();
+
+            var gridSize = 1000;
+
+            // generate texture
+            var diffuseImageSize = 2 * gridSize;
+            var occlusionImageSize = gridSize;
+
+            MemoryImage diffuseImage, occlusionImage;
+            {
+                var img = new Bitmap(diffuseImageSize, diffuseImageSize, PixelFormat.Format32bppArgb);
+
+                using var mem = new MemoryStream();
+                img.Save(mem, ImageFormat.Png);
+
+                mem.TryGetBuffer(out var bytes);
+                diffuseImage = new MemoryImage(bytes);
+            }
+            {
+                var img = new Bitmap(occlusionImageSize, occlusionImageSize, PixelFormat.Format32bppArgb);
+
+                using var mem = new MemoryStream();
+                img.Save(mem, ImageFormat.Png);
+
+                mem.TryGetBuffer(out var bytes);
+                occlusionImage = new MemoryImage(bytes);
+            }
+
+            var material = MaterialBuilder.CreateDefault().WithSpecularGlossinessShader();
+            material.UseChannel(KnownChannel.Diffuse)
+                    .UseTexture()
+                    .WithPrimaryImage(ImageBuilder.From(diffuseImage))
+                    .WithCoordinateSet(0);
+            material.UseChannel(KnownChannel.Occlusion)
+                    .UseTexture()
+                    .WithPrimaryImage(ImageBuilder.From(occlusionImage))
+                    .WithCoordinateSet(0);
+
+            // generate heightmap
+
+            for (var y = 0; y < gridSize; ++y) {
+                for (var x = 0; x < gridSize; ++x) {
+                    var vertices = new (float X, float Y)[]
+                    {
+                        (x, y),
+                        (x + 1, y),
+                        (x, y + 1),
+                        (x + 1, y + 1)
+                    }.Select(pos => VertexBuilder<VertexPositionNormal, VertexColor2Texture1, VertexJoints8>
+                             .Create(new Vector3(pos.X, pos.Y, 0), new Vector3(x, y, 0))
+                             .WithMaterial(new Vector4(pos.X / gridSize, pos.Y / gridSize, 0, 1),
+                                           new Vector4(0, pos.X / gridSize, pos.Y / gridSize, 1),
+                                           new Vector2(pos.X / gridSize, pos.Y / gridSize),
+                                           new Vector2(pos.X / gridSize, pos.Y / gridSize))
+                             .WithSkinning(SparseWeight8.Create((0, 1))))
+                     .ToArray();
+
+                    mesh.UsePrimitive(material).AddTriangle(vertices[0], vertices[1], vertices[2]);
+                    mesh.UsePrimitive(material).AddTriangle(vertices[1], vertices[2], vertices[3]);
+                }
+            }
+
+            var scene = new SceneBuilder();
+            scene.AddSkinnedMesh(mesh, Matrix4x4.Identity, new NodeBuilder());
+
+            // convert to gltf
+
+            var gltf = scene.ToGltf2();
+
+            Assert.AreEqual(1, gltf.LogicalMeshes.Count);
+
+            var outFiles = new[]
+            {
+                "huge_scene.glb",
+                "huge_scene.gltf",
+                "huge_scene.obj",
+            };
+
+            foreach (var outFile in outFiles) {
+                gltf.AttachToCurrentTest(outFile);
+
+                GC.WaitForPendingFinalizers();
+                GC.Collect();
+                GC.WaitForFullGCComplete();
+            }
+        }
     }
     }
 }
 }

+ 2 - 1
tests/SharpGLTF.ThirdParty.Tests/SharpGLTF.ThirdParty.Tests.csproj

@@ -18,7 +18,8 @@
   <ItemGroup>
   <ItemGroup>
     <PackageReference Include="NUnit" Version="3.13.3" />
     <PackageReference Include="NUnit" Version="3.13.3" />
     <PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
     <PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />    
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
+    <PackageReference Include="System.Drawing.Common" Version="6.0.0" />    
   </ItemGroup>
   </ItemGroup>
 
 
   <ItemGroup>
   <ItemGroup>