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);
        }
예제 #2
0
    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();
        }
    }