Unity-Technologies / EntityComponentSystemSamples

Other
7.22k stars 1.62k forks source link

Closest Target scene crashes if 8 or less targets and using KD tree #234

Open kstars111 opened 1 year ago

fagenorn commented 1 year ago

Had the same issue. For anybody wanting to fix it, the following has to be modified in KDTree.cs:

Modify BuildTree so it correctly creates the leafnodes needed.

public JobHandle BuildTree(int numEntries, JobHandle inputDeps)
        {
            var dep = inputDeps;

            m_NumEntries = numEntries;

            if ( m_NumEntries == 0 )
            {
                return dep;
            }

            SetNode(k_RootNodeIndex, m_EntriesPtr, m_EntriesPtr + (m_NumEntries - 1) * sizeof(Entry));

            // if ( m_NumEntries > k_MaxLeafSize )
            // {
            // calculate how many workers we need based on entries
            var entryNumWorkers = CalculateNumWorkers(m_NumEntries, JobsUtility.JobWorkerCount, k_MaxLeafSize, k_MinLeavesPerWorker);
            entryNumWorkers = math.min(m_NumWorkers, entryNumWorkers);
            var maxDepthOnPreProcess = (int)math.log2(entryNumWorkers);

            // preprocess tree for parallel work
            for ( var depth = 0; depth < maxDepthOnPreProcess; depth++ )
            {
                var numNodesToProcess = (int)math.pow(2, depth);

                var preProcessJob = new PreprocessJob { This = this, Depth = depth };
                dep = preProcessJob.Schedule(numNodesToProcess, 1, dep);
            }

            //build tree on workers
            var buildSubTreeJob = new BuildSubTreeJob { This = this, Depth = maxDepthOnPreProcess };
            dep = buildSubTreeJob.Schedule(entryNumWorkers, 1, dep);
            // }

            return dep;
        }

TreeNode struct has to be modified since it is being packed incorrectly (40 bytes instead of 32)

 public struct TreeNode
        {
            public uint count; // 4

            private int padding; // 4

            [NoAlias] internal byte* beginPtr; // 8

            internal SphereBounds bounds; // 16;

            // 32B (2 per cacheline)

            public uint Count => count & k_CountBitMask;

            public bool IsLeaf
            {
                get => (count & k_IsLeafNodeBitFlag) > 0;
                set
                {
                    if ( value )
                    {
                        count |= k_IsLeafNodeBitFlag;
                    }
                }
            }
        }
SuChengCode commented 1 year ago

Had the same issue. For anybody wanting to fix it, the following has to be modified in KDTree.cs:有同样的问题。对于任何想要修复它的人,必须在 KDTree.cs 中修改以下内容:

Modify BuildTree so it correctly creates the leafnodes needed.进行修改 BuildTree ,使其正确创建所需的叶节点。

public JobHandle BuildTree(int numEntries, JobHandle inputDeps)
        {
            var dep = inputDeps;

            m_NumEntries = numEntries;

            if ( m_NumEntries == 0 )
            {
                return dep;
            }

            SetNode(k_RootNodeIndex, m_EntriesPtr, m_EntriesPtr + (m_NumEntries - 1) * sizeof(Entry));

            // if ( m_NumEntries > k_MaxLeafSize )
            // {
            // calculate how many workers we need based on entries
            var entryNumWorkers = CalculateNumWorkers(m_NumEntries, JobsUtility.JobWorkerCount, k_MaxLeafSize, k_MinLeavesPerWorker);
            entryNumWorkers = math.min(m_NumWorkers, entryNumWorkers);
            var maxDepthOnPreProcess = (int)math.log2(entryNumWorkers);

            // preprocess tree for parallel work
            for ( var depth = 0; depth < maxDepthOnPreProcess; depth++ )
            {
                var numNodesToProcess = (int)math.pow(2, depth);

                var preProcessJob = new PreprocessJob { This = this, Depth = depth };
                dep = preProcessJob.Schedule(numNodesToProcess, 1, dep);
            }

            //build tree on workers
            var buildSubTreeJob = new BuildSubTreeJob { This = this, Depth = maxDepthOnPreProcess };
            dep = buildSubTreeJob.Schedule(entryNumWorkers, 1, dep);
            // }

            return dep;
        }

TreeNode struct has to be modified since it is being packed incorrectly (40 bytes instead of 32)必须修改 TreeNode 结构,因为它打包不正确(40 字节而不是 32 字节)

public struct TreeNode
       {
           public uint count; // 4

           private int padding; // 4

           [NoAlias] internal byte* beginPtr; // 8

           internal SphereBounds bounds; // 16;

           // 32B (2 per cacheline)

           public uint Count => count & k_CountBitMask;

           public bool IsLeaf
           {
               get => (count & k_IsLeafNodeBitFlag) > 0;
               set
               {
                   if ( value )
                   {
                       count |= k_IsLeafNodeBitFlag;
                   }
               }
           }
       }

still crash,Invalid memory pointer was detected in ThreadsafeLinearAllocator::Deallocate!

matteomarca99 commented 8 months ago

To solve the memory pointer error with 8 or less targets:

Replace this line:

return numEntries > k_MaxLeafSize ? (int)math.pow(2f, 1 + maxDepth) : 1;

With this:

return (int)math.pow(2f, 1 + maxDepth);

Inside the CalculateNumNodes method.