public void Execute() { var batchCounter = 0; for (var m = 0; m < MatchingArchetypes.Length; ++m) { var match = MatchingArchetypes.Ptr[m]; if (match->Archetype->EntityCount <= 0) { continue; } var archetype = match->Archetype; int chunkCount = archetype->Chunks.Count; for (int chunkIndex = 0; chunkIndex < chunkCount; ++chunkIndex) { var chunk = archetype->Chunks.p[chunkIndex]; for (int batchIndex = 0; batchIndex < BatchesPerChunk; ++batchIndex) { if (match->ChunkMatchesFilter(chunkIndex, ref Filter)) { Batches[batchCounter++] = ArchetypeChunk.EntityBatchFromChunk(chunk, BatchesPerChunk, batchIndex, EntityComponentStore); } } } } }
internal unsafe static void ExecuteInternal( ref JobEntityBatchWrapper <T> jobWrapper, ref JobRanges ranges, int jobIndex) { var chunks = jobWrapper.CachedChunks; bool isParallel = jobWrapper.IsParallel == 1; bool isFiltering = jobWrapper.Filter.RequiresMatchesFilter; while (true) { int beginBatchIndex = 0; int endBatchIndex = chunks.Length; // If we are running the job in parallel, steal some work. if (isParallel) { // If we have no range to steal, exit the loop. if (!JobsUtility.GetWorkStealingRange(ref ranges, jobIndex, out beginBatchIndex, out endBatchIndex)) { break; } } // Do the actual user work. for (int batchIndex = beginBatchIndex; batchIndex < endBatchIndex; ++batchIndex) { var chunkIndex = batchIndex / jobWrapper.JobsPerChunk; var batchIndexInChunk = batchIndex % jobWrapper.JobsPerChunk; var chunk = chunks.Ptr[chunkIndex]; if (isFiltering && chunk->MatchesFilter(jobWrapper.MatchingArchetypes.Ptr[chunks.PerChunkMatchingArchetypeIndex.Ptr[chunkIndex]], ref jobWrapper.Filter)) { continue; } jobWrapper.JobData.Execute(ArchetypeChunk.EntityBatchFromChunk(chunk, jobWrapper.JobsPerChunk, batchIndexInChunk, chunks.EntityComponentStore), batchIndex); } // If we are not running in parallel, our job is done. if (!isParallel) { break; } } }
public void Execute() { var batches = (ArchetypeChunk *)PrefilterData; var entityIndices = (int *)(batches + FilteredChunkCount * BatchesPerChunk); var filteredBatchCounter = 0; var entityIndexAggregate = 0; for (var m = 0; m < MatchingArchetypes.Length; ++m) { var match = MatchingArchetypes.Ptr[m]; if (match->Archetype->EntityCount <= 0) { continue; } var archetype = match->Archetype; int chunkCount = archetype->Chunks.Count; for (int chunkIndex = 0; chunkIndex < chunkCount; ++chunkIndex) { var chunk = archetype->Chunks[chunkIndex]; for (int batchIndex = 0; batchIndex < BatchesPerChunk; ++batchIndex) { if (match->ChunkMatchesFilter(chunkIndex, ref Filter)) { var batch = ArchetypeChunk.EntityBatchFromChunk(chunk, BatchesPerChunk, batchIndex, EntityComponentStore); batches[filteredBatchCounter] = batch; entityIndices[filteredBatchCounter] = entityIndexAggregate; ++filteredBatchCounter; entityIndexAggregate += batch.BatchEntityCount; } } } } var chunkCounter = entityIndices + FilteredChunkCount * BatchesPerChunk; *chunkCounter = filteredBatchCounter; }
internal unsafe static void ExecuteInternal( ref JobEntityBatchWrapper <T> jobWrapper, IntPtr bufferRangePatchData, ref JobRanges ranges, int jobIndex) { var chunks = jobWrapper.CachedChunks; var prebuiltBatches = (ArchetypeChunk *)jobWrapper.PrebuiltBatchList.Ptr; bool isParallel = jobWrapper.IsParallel == 1; bool isFiltering = jobWrapper.Filter.RequiresMatchesFilter; while (true) { int beginBatchIndex = 0; int endBatchIndex = jobWrapper.UsePrebuiltBatchList == 1 ? jobWrapper.PrebuiltBatchList.Length : chunks.Length; // If we are running the job in parallel, steal some work. if (isParallel) { // If we have no range to steal, exit the loop. if (!JobsUtility.GetWorkStealingRange(ref ranges, jobIndex, out beginBatchIndex, out endBatchIndex)) { break; } JobsUtility.PatchBufferMinMaxRanges(bufferRangePatchData, UnsafeUtility.AddressOf(ref jobWrapper), 0, 0); } // Do the actual user work. if (jobWrapper.UsePrebuiltBatchList == 1) { for (int batchIndex = beginBatchIndex; batchIndex < endBatchIndex; ++batchIndex) { var batch = prebuiltBatches[batchIndex]; if (isFiltering && !batch.m_Chunk->MatchesFilter(jobWrapper.MatchingArchetypes.Ptr[jobWrapper.PrebuiltBatchListMatchingArchetypeIndices.Ptr[batchIndex]], ref jobWrapper.Filter)) { continue; } Assert.AreNotEqual(0, batch.Count); jobWrapper.JobData.Execute(batch, batchIndex); } } else { if (jobWrapper.JobsPerChunk == 1) { // 1 batch per chunk, with/without filtering for (int batchIndex = beginBatchIndex; batchIndex < endBatchIndex; ++batchIndex) { var chunkIndex = batchIndex; var chunk = chunks.Ptr[chunkIndex]; if (isFiltering && !chunk->MatchesFilter(jobWrapper.MatchingArchetypes.Ptr[chunks.PerChunkMatchingArchetypeIndex.Ptr[chunkIndex]], ref jobWrapper.Filter)) { continue; } var batch = new ArchetypeChunk(chunk, chunks.EntityComponentStore); Assert.AreNotEqual(0, batch.Count); jobWrapper.JobData.Execute(batch, batchIndex); } } else { // 2+ batches per chunk, with/without filtering // This is the most general case; if only one code path survives, it should be this one. for (int batchIndex = beginBatchIndex; batchIndex < endBatchIndex; ++batchIndex) { var chunkIndex = batchIndex / jobWrapper.JobsPerChunk; var batchIndexInChunk = batchIndex % jobWrapper.JobsPerChunk; var chunk = chunks.Ptr[chunkIndex]; if (isFiltering && !chunk->MatchesFilter( jobWrapper.MatchingArchetypes.Ptr[ chunks.PerChunkMatchingArchetypeIndex.Ptr[chunkIndex]], ref jobWrapper.Filter)) { continue; } if (ArchetypeChunk.EntityBatchFromChunk(chunk, chunk->Count, jobWrapper.JobsPerChunk, batchIndexInChunk, chunks.EntityComponentStore, out var batch)) { jobWrapper.JobData.Execute(batch, batchIndex); } } } } // If we are not running in parallel, our job is done. if (!isParallel) { break; } } }
public void Execute() { var batches = (ArchetypeChunk *)PrefilterData; var entityIndices = (int *)(batches + FilteredChunkCount * BatchesPerChunk); var filteredBatchCounter = 0; var entityIndexAggregate = 0; if (BatchesPerChunk == 1) { if (Filter.RequiresMatchesFilter) { // one batch per chunk, filtering enabled for (var m = 0; m < MatchingArchetypes.Length; ++m) { var match = MatchingArchetypes.Ptr[m]; if (match->Archetype->EntityCount <= 0) { continue; } var archetype = match->Archetype; int chunkCount = archetype->Chunks.Count; var chunkEntityCountArray = archetype->Chunks.GetChunkEntityCountArray(); for (int chunkIndex = 0; chunkIndex < chunkCount; ++chunkIndex) { var chunk = archetype->Chunks[chunkIndex]; if (match->ChunkMatchesFilter(chunkIndex, ref Filter)) { var batch = new ArchetypeChunk(chunk, EntityComponentStore); batches[filteredBatchCounter] = batch; entityIndices[filteredBatchCounter] = entityIndexAggregate; ++filteredBatchCounter; entityIndexAggregate += chunkEntityCountArray[chunkIndex]; } } } } else { // one batch per chunk, filtering disabled for (var m = 0; m < MatchingArchetypes.Length; ++m) { var match = MatchingArchetypes.Ptr[m]; if (match->Archetype->EntityCount <= 0) { continue; } var archetype = match->Archetype; int chunkCount = archetype->Chunks.Count; var chunkEntityCountArray = archetype->Chunks.GetChunkEntityCountArray(); for (int chunkIndex = 0; chunkIndex < chunkCount; ++chunkIndex) { var chunk = archetype->Chunks[chunkIndex]; var batch = new ArchetypeChunk(chunk, EntityComponentStore); batches[filteredBatchCounter] = batch; entityIndices[filteredBatchCounter] = entityIndexAggregate; ++filteredBatchCounter; entityIndexAggregate += chunkEntityCountArray[chunkIndex]; } } } } else { if (Filter.RequiresMatchesFilter) { // 2+ batches per chunk, filtering enabled. // This is the most general case; if only one code path survives, it should be this one. for (var m = 0; m < MatchingArchetypes.Length; ++m) { var match = MatchingArchetypes.Ptr[m]; if (match->Archetype->EntityCount <= 0) { continue; } var archetype = match->Archetype; int chunkCount = archetype->Chunks.Count; var chunkEntityCountArray = archetype->Chunks.GetChunkEntityCountArray(); for (int chunkIndex = 0; chunkIndex < chunkCount; ++chunkIndex) { if (match->ChunkMatchesFilter(chunkIndex, ref Filter)) { var chunk = archetype->Chunks[chunkIndex]; var chunkEntityCount = chunkEntityCountArray[chunkIndex]; for (int batchIndex = 0; batchIndex < BatchesPerChunk; ++batchIndex) { if (ArchetypeChunk.EntityBatchFromChunk(chunk, chunkEntityCount, BatchesPerChunk, batchIndex, EntityComponentStore, out var batch)) { batches[filteredBatchCounter] = batch; entityIndices[filteredBatchCounter] = entityIndexAggregate; ++filteredBatchCounter; entityIndexAggregate += batch.Count; } } } } } } else { // 2+ batches per chunk, filtering disabled for (var m = 0; m < MatchingArchetypes.Length; ++m) { var match = MatchingArchetypes.Ptr[m]; if (match->Archetype->EntityCount <= 0) { continue; } var archetype = match->Archetype; int chunkCount = archetype->Chunks.Count; var chunkEntityCountArray = archetype->Chunks.GetChunkEntityCountArray(); for (int chunkIndex = 0; chunkIndex < chunkCount; ++chunkIndex) { var chunk = archetype->Chunks[chunkIndex]; var chunkEntityCount = chunkEntityCountArray[chunkIndex]; for (int batchIndex = 0; batchIndex < BatchesPerChunk; ++batchIndex) { if (ArchetypeChunk.EntityBatchFromChunk(chunk, chunkEntityCount, BatchesPerChunk, batchIndex, EntityComponentStore, out var batch)) { batches[filteredBatchCounter] = batch; entityIndices[filteredBatchCounter] = entityIndexAggregate; ++filteredBatchCounter; entityIndexAggregate += batch.Count; } } } } } } var chunkCounter = entityIndices + FilteredChunkCount * BatchesPerChunk; *chunkCounter = filteredBatchCounter; }