public void BlobPerOwnerTest() { var go0 = new GameObject("GO 0"); var go1 = new GameObject("GO 1"); var k0 = FromInt(0); var k1 = FromInt(1); var k2 = FromInt(2); var k3 = FromInt(3); var k4 = FromInt(4); // Associate k0, k2, k4 with GO0, k0, k1, k2 with GO1 using (var context = new BlobAssetComputationContext <int, int>(m_Store, 16, Allocator.Temp)) using (var processList = new NativeList <Hash128>(16, Allocator.Temp)) { // Simulate BlobAsset operations with GO0 processList.Add(k0); Assert.IsTrue(context.NeedToComputeBlobAsset(k0)); var blobAsset = BlobAssetReference <int> .Create(0); context.AddComputedBlobAsset(k0, blobAsset); processList.Add(k2); Assert.IsTrue(context.NeedToComputeBlobAsset(k2)); blobAsset = BlobAssetReference <int> .Create(2); context.AddComputedBlobAsset(k2, blobAsset); processList.Add(k4); Assert.IsTrue(context.NeedToComputeBlobAsset(k4)); blobAsset = BlobAssetReference <int> .Create(4); context.AddComputedBlobAsset(k4, blobAsset); // Simulate BlobAsset operation with GO1 processList.Add(k0); Assert.IsFalse(context.NeedToComputeBlobAsset(k0)); processList.Add(k1); Assert.IsTrue(context.NeedToComputeBlobAsset(k1)); blobAsset = BlobAssetReference <int> .Create(1); context.AddComputedBlobAsset(k1, blobAsset); processList.Add(k2); Assert.IsFalse(context.NeedToComputeBlobAsset(k2)); // Associate the BlobAssets with GO0 context.AssociateBlobAssetWithGameObject(k0, go0); context.AssociateBlobAssetWithGameObject(k2, go0); context.AssociateBlobAssetWithGameObject(k4, go0); // Associate the BlobAssets with GO1 context.AssociateBlobAssetWithGameObject(k0, go1); context.AssociateBlobAssetWithGameObject(k1, go1); context.AssociateBlobAssetWithGameObject(k2, go1); // Check the BlobAsset are retrieved correctly var replayIndex = 0; context.GetBlobAsset(processList[replayIndex++], out var res); Assert.AreEqual(0, res.Value); context.GetBlobAsset(processList[replayIndex++], out res); Assert.AreEqual(2, res.Value); context.GetBlobAsset(processList[replayIndex++], out res); Assert.AreEqual(4, res.Value); context.GetBlobAsset(processList[replayIndex++], out res); Assert.AreEqual(0, res.Value); context.GetBlobAsset(processList[replayIndex++], out res); Assert.AreEqual(1, res.Value); context.GetBlobAsset(processList[replayIndex++], out res); Assert.AreEqual(2, res.Value); } // Check the GO-BlobAsset associations m_Store.GetBlobAssetsOfGameObject(go0, Allocator.Temp, out var hashes); Assert.AreEqual(3, hashes.Length); Assert.IsTrue(hashes.Contains(k0)); Assert.IsTrue(hashes.Contains(k2)); Assert.IsTrue(hashes.Contains(k4)); hashes.Dispose(); m_Store.GetBlobAssetsOfGameObject(go1, Allocator.Temp, out hashes); Assert.AreEqual(3, hashes.Length); Assert.IsTrue(hashes.Contains(k0)); Assert.IsTrue(hashes.Contains(k1)); Assert.IsTrue(hashes.Contains(k2)); hashes.Dispose(); // 2, 1, 2, 0, 1 as expected RefCounter for k0...4 Assert.AreEqual(2, m_Store.GetBlobAssetRefCounter(k0)); Assert.AreEqual(1, m_Store.GetBlobAssetRefCounter(k1)); Assert.AreEqual(2, m_Store.GetBlobAssetRefCounter(k2)); Assert.AreEqual(0, m_Store.GetBlobAssetRefCounter(k3)); Assert.AreEqual(1, m_Store.GetBlobAssetRefCounter(k4)); // Associate k1, k2, k3 with GO0 and k3, k4 with GO1 using (var context = new BlobAssetComputationContext <int, int>(m_Store, 16, Allocator.Temp)) using (var processList = new NativeList <Hash128>(16, Allocator.Temp)) { // Simulate BlobAsset operations with GO0 processList.Add(k1); Assert.IsFalse(context.NeedToComputeBlobAsset(k1)); processList.Add(k2); Assert.IsFalse(context.NeedToComputeBlobAsset(k2)); processList.Add(k3); Assert.IsTrue(context.NeedToComputeBlobAsset(k3)); var blobAsset = BlobAssetReference <int> .Create(3); context.AddComputedBlobAsset(k3, blobAsset); // Simulate BlobAsset operations with GO1 processList.Add(k3); Assert.IsFalse(context.NeedToComputeBlobAsset(k3)); processList.Add(k4); Assert.IsFalse(context.NeedToComputeBlobAsset(k4)); // Associate the BlobAssets with GO0 context.AssociateBlobAssetWithGameObject(k1, go0); context.AssociateBlobAssetWithGameObject(k2, go0); context.AssociateBlobAssetWithGameObject(k3, go0); // Associate the BlobAssets with GO1 context.AssociateBlobAssetWithGameObject(k3, go1); context.AssociateBlobAssetWithGameObject(k4, go1); // Check BlobAsset are retrieved correctly var replayIndex = 0; context.GetBlobAsset(processList[replayIndex++], out var res); Assert.AreEqual(1, res.Value); context.GetBlobAsset(processList[replayIndex++], out res); Assert.AreEqual(2, res.Value); context.GetBlobAsset(processList[replayIndex++], out res); Assert.AreEqual(3, res.Value); context.GetBlobAsset(processList[replayIndex++], out res); Assert.AreEqual(3, res.Value); context.GetBlobAsset(processList[replayIndex++], out res); Assert.AreEqual(4, res.Value); } // Check the GO-BlobAsset associations m_Store.GetBlobAssetsOfGameObject(go0, Allocator.Temp, out hashes); Assert.AreEqual(3, hashes.Length); Assert.IsTrue(hashes.Contains(k1)); Assert.IsTrue(hashes.Contains(k2)); Assert.IsTrue(hashes.Contains(k3)); hashes.Dispose(); m_Store.GetBlobAssetsOfGameObject(go1, Allocator.Temp, out hashes); Assert.AreEqual(2, hashes.Length); Assert.IsTrue(hashes.Contains(k3)); Assert.IsTrue(hashes.Contains(k4)); hashes.Dispose(); // 0, 1, 1, 2, 1 as expected RefCounter for k0...4 Assert.AreEqual(0, m_Store.GetBlobAssetRefCounter(k0)); Assert.AreEqual(1, m_Store.GetBlobAssetRefCounter(k1)); Assert.AreEqual(1, m_Store.GetBlobAssetRefCounter(k2)); Assert.AreEqual(2, m_Store.GetBlobAssetRefCounter(k3)); Assert.AreEqual(1, m_Store.GetBlobAssetRefCounter(k4)); // BlobAsset of k0 is not used by any UnityObject anymore, is should have been removed from the store Assert.IsFalse(m_Store.Contains <int>(k0)); // Cleanup Object.DestroyImmediate(go0); }
protected override void OnUpdate() { var blobFactoryPoints = new NativeList <float3>(Allocator.TempJob); int curPointIndex = 0; var vertices = new List <Vector3>(4096); var processBlobAssets = new NativeList <Hash128>(32, Allocator.Temp); Profiler.BeginSample("Conv_BuildHashAndPush"); using (var context = new BlobAssetComputationContext <MeshBBFactorySettings, MeshBBBlobAsset>(BlobAssetStore, 128, Allocator.Temp)) { // First step: for all changed GameObjects we compute the hash of their blob asset then get the asset or register its computation Entities.ForEach((MeshToBoundingBoxsAuthoring auth) => { // Compute the blob asset hash based on Authoring properties var hasMesh = auth.Mesh != null; var meshHashCode = hasMesh ? auth.Mesh.GetHashCode() : 0; var hash = new Hash128((uint)meshHashCode, (uint)auth.MeshScale.GetHashCode(), 0, 0); // Query the context to determine if we need to build the BlobAsset processBlobAssets.Add(hash); context.AssociateBlobAssetWithGameObject(hash, auth.gameObject); if (context.NeedToComputeBlobAsset(hash)) { Profiler.BeginSample("CopyVertices"); float xp = float.MinValue, yp = float.MinValue, zp = float.MinValue; float xn = float.MaxValue, yn = float.MaxValue, zn = float.MaxValue; // Copy the mesh vertices into the point array if (hasMesh) { auth.Mesh.GetVertices(vertices); for (int i = 0; i < vertices.Count; i++) { var p = vertices[i]; xp = math.max(p.x, xp); yp = math.max(p.y, yp); zp = math.max(p.z, zp); xn = math.min(p.x, xn); yn = math.min(p.y, yn); zn = math.min(p.z, zn); blobFactoryPoints.Add(new float3(p.x, p.y, p.z)); } } else { xp = yp = zp = xn = yn = zn = 0; } Profiler.EndSample(); // Record this blob asset for computation var vertexCount = hasMesh ? auth.Mesh.vertexCount : 0; var setting = new MeshBBFactorySettings { Hash = hash, MeshScale = auth.MeshScale, PointStartIndex = curPointIndex, PointCount = vertexCount, MinBoundingBox = new float3(xn, yn, zn), MaxBoundingBox = new float3(xp, yp, zp) }; curPointIndex += vertexCount; context.AddBlobAssetToCompute(hash, setting); } }); Profiler.EndSample(); Profiler.BeginSample("Conv_CreateBlobAssets"); using (var settings = context.GetSettings(Allocator.TempJob)) { // Step two, compute BlobAssets var job = new ComputeMeshBBAssetJob(settings, blobFactoryPoints.AsArray()); job.Schedule(job.Settings.Length, 1).Complete(); for (int i = 0; i < settings.Length; i++) { context.AddComputedBlobAsset(settings[i].Hash, job.BlobAssets[i]); } job.BlobAssets.Dispose(); } Profiler.EndSample(); Profiler.BeginSample("Conv_CreateECS"); // Third step, create the ECS component with the associated blob asset var index = 0; Entities.ForEach((MeshToBoundingBoxsAuthoring auth) => { context.GetBlobAsset(processBlobAssets[index++], out var blob); // Create the ECS component for the given GameObject var entity = GetPrimaryEntity(auth); DstEntityManager.AddComponentData(entity, new MeshBBComponent(blob)); }); Profiler.EndSample(); blobFactoryPoints.Dispose(); processBlobAssets.Dispose(); } }