Added ScheduleEntityParallel and IJobEntityParallel for parallel querying
This commit is contained in:
@@ -111,7 +111,7 @@ public unsafe partial struct EntityQuery
|
||||
var pComp0 = (T0*)(basePtrs[0] + (sizeof(T0) * entityIndex));
|
||||
var pComp1 = (T1*)(basePtrs[1] + (sizeof(T1) * entityIndex));
|
||||
|
||||
action(ref *pComp0,ref *pComp1);
|
||||
action(ref *pComp0, ref *pComp1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,7 +170,7 @@ public unsafe partial struct EntityQuery
|
||||
var pComp1 = (T1*)(basePtrs[1] + (sizeof(T1) * entityIndex));
|
||||
var pComp2 = (T2*)(basePtrs[2] + (sizeof(T2) * entityIndex));
|
||||
|
||||
action(ref *pComp0,ref *pComp1,ref *pComp2);
|
||||
action(ref *pComp0, ref *pComp1, ref *pComp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -231,7 +231,7 @@ public unsafe partial struct EntityQuery
|
||||
var pComp2 = (T2*)(basePtrs[2] + (sizeof(T2) * entityIndex));
|
||||
var pComp3 = (T3*)(basePtrs[3] + (sizeof(T3) * entityIndex));
|
||||
|
||||
action(ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3);
|
||||
action(ref *pComp0, ref *pComp1, ref *pComp2, ref *pComp3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -294,7 +294,7 @@ public unsafe partial struct EntityQuery
|
||||
var pComp3 = (T3*)(basePtrs[3] + (sizeof(T3) * entityIndex));
|
||||
var pComp4 = (T4*)(basePtrs[4] + (sizeof(T4) * entityIndex));
|
||||
|
||||
action(ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3,ref *pComp4);
|
||||
action(ref *pComp0, ref *pComp1, ref *pComp2, ref *pComp3, ref *pComp4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -359,7 +359,7 @@ public unsafe partial struct EntityQuery
|
||||
var pComp4 = (T4*)(basePtrs[4] + (sizeof(T4) * entityIndex));
|
||||
var pComp5 = (T5*)(basePtrs[5] + (sizeof(T5) * entityIndex));
|
||||
|
||||
action(ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3,ref *pComp4,ref *pComp5);
|
||||
action(ref *pComp0, ref *pComp1, ref *pComp2, ref *pComp3, ref *pComp4, ref *pComp5);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -426,7 +426,7 @@ public unsafe partial struct EntityQuery
|
||||
var pComp5 = (T5*)(basePtrs[5] + (sizeof(T5) * entityIndex));
|
||||
var pComp6 = (T6*)(basePtrs[6] + (sizeof(T6) * entityIndex));
|
||||
|
||||
action(ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3,ref *pComp4,ref *pComp5,ref *pComp6);
|
||||
action(ref *pComp0, ref *pComp1, ref *pComp2, ref *pComp3, ref *pComp4, ref *pComp5, ref *pComp6);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -495,7 +495,7 @@ public unsafe partial struct EntityQuery
|
||||
var pComp6 = (T6*)(basePtrs[6] + (sizeof(T6) * entityIndex));
|
||||
var pComp7 = (T7*)(basePtrs[7] + (sizeof(T7) * entityIndex));
|
||||
|
||||
action(ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3,ref *pComp4,ref *pComp5,ref *pComp6,ref *pComp7);
|
||||
action(ref *pComp0, ref *pComp1, ref *pComp2, ref *pComp3, ref *pComp4, ref *pComp5, ref *pComp6, ref *pComp7);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -609,7 +609,7 @@ public unsafe partial struct EntityQuery
|
||||
var pComp1 = (T1*)(basePtrs[1] + (sizeof(T1) * entityIndex));
|
||||
|
||||
var pEntity = (Entity*)(pChunkData + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
action(*pEntity, ref *pComp0,ref *pComp1);
|
||||
action(*pEntity, ref *pComp0, ref *pComp1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -669,7 +669,7 @@ public unsafe partial struct EntityQuery
|
||||
var pComp2 = (T2*)(basePtrs[2] + (sizeof(T2) * entityIndex));
|
||||
|
||||
var pEntity = (Entity*)(pChunkData + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
action(*pEntity, ref *pComp0,ref *pComp1,ref *pComp2);
|
||||
action(*pEntity, ref *pComp0, ref *pComp1, ref *pComp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -731,7 +731,7 @@ public unsafe partial struct EntityQuery
|
||||
var pComp3 = (T3*)(basePtrs[3] + (sizeof(T3) * entityIndex));
|
||||
|
||||
var pEntity = (Entity*)(pChunkData + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
action(*pEntity, ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3);
|
||||
action(*pEntity, ref *pComp0, ref *pComp1, ref *pComp2, ref *pComp3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -795,7 +795,7 @@ public unsafe partial struct EntityQuery
|
||||
var pComp4 = (T4*)(basePtrs[4] + (sizeof(T4) * entityIndex));
|
||||
|
||||
var pEntity = (Entity*)(pChunkData + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
action(*pEntity, ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3,ref *pComp4);
|
||||
action(*pEntity, ref *pComp0, ref *pComp1, ref *pComp2, ref *pComp3, ref *pComp4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -861,7 +861,7 @@ public unsafe partial struct EntityQuery
|
||||
var pComp5 = (T5*)(basePtrs[5] + (sizeof(T5) * entityIndex));
|
||||
|
||||
var pEntity = (Entity*)(pChunkData + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
action(*pEntity, ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3,ref *pComp4,ref *pComp5);
|
||||
action(*pEntity, ref *pComp0, ref *pComp1, ref *pComp2, ref *pComp3, ref *pComp4, ref *pComp5);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -929,7 +929,7 @@ public unsafe partial struct EntityQuery
|
||||
var pComp6 = (T6*)(basePtrs[6] + (sizeof(T6) * entityIndex));
|
||||
|
||||
var pEntity = (Entity*)(pChunkData + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
action(*pEntity, ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3,ref *pComp4,ref *pComp5,ref *pComp6);
|
||||
action(*pEntity, ref *pComp0, ref *pComp1, ref *pComp2, ref *pComp3, ref *pComp4, ref *pComp5, ref *pComp6);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -999,7 +999,7 @@ public unsafe partial struct EntityQuery
|
||||
var pComp7 = (T7*)(basePtrs[7] + (sizeof(T7) * entityIndex));
|
||||
|
||||
var pEntity = (Entity*)(pChunkData + archetype.EntityIDsOffset + (sizeof(Entity) * entityIndex));
|
||||
action(*pEntity, ref *pComp0,ref *pComp1,ref *pComp2,ref *pComp3,ref *pComp4,ref *pComp5,ref *pComp6,ref *pComp7);
|
||||
action(*pEntity, ref *pComp0, ref *pComp1, ref *pComp2, ref *pComp3, ref *pComp4, ref *pComp5, ref *pComp6, ref *pComp7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2103
Ghost.Entities/Templates/EntityQuery.JobEntityParallel.gen.cs
Normal file
2103
Ghost.Entities/Templates/EntityQuery.JobEntityParallel.gen.cs
Normal file
File diff suppressed because it is too large
Load Diff
189
Ghost.Entities/Templates/EntityQuery.JobEntityParallel.tt
Normal file
189
Ghost.Entities/Templates/EntityQuery.JobEntityParallel.tt
Normal file
@@ -0,0 +1,189 @@
|
||||
<#@ template language="C#" #>
|
||||
<#@ output extension="gen.cs" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ import namespace="System.Linq" #>
|
||||
<#@ import namespace="System.Text" #>
|
||||
<#@ include file="Helpers.ttinclude" #>
|
||||
using Ghost.Core;
|
||||
using Misaki.HighPerformance.Jobs;
|
||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
|
||||
namespace Ghost.Entities;
|
||||
|
||||
<# for (var i = 1; i <= Amount; i++)
|
||||
{
|
||||
var generics = AppendGenerics(i);
|
||||
var restrictions = AppendGenericRestrictionsMultiline(i, "unmanaged, IComponent", 1);
|
||||
#>
|
||||
public interface IJobEntityParallel<<#= generics #>>
|
||||
<#= restrictions #>
|
||||
{
|
||||
void Execute(Entity entity, <#= AppendParameters(i, "ref T{0} component{0}") #>);
|
||||
}
|
||||
|
||||
internal unsafe struct JobEntityBatch<TJob, <#= generics #>> : IJobParallelFor
|
||||
where TJob : unmanaged, IJobEntityParallel<<#= generics #>>
|
||||
<#= restrictions #>
|
||||
{
|
||||
public TJob userJob;
|
||||
|
||||
public UnsafeList<IntPtr> chunks;
|
||||
public UnsafeList<int> chunkCount;
|
||||
public UnsafeList<int> entityOffset;
|
||||
|
||||
<# for (var j = 0; j < i; j++){ #>
|
||||
public UnsafeList<int> offsets<#= j #>;
|
||||
public UnsafeList<int> bitsOffsets<#= j #>;
|
||||
|
||||
<# } #>
|
||||
public void Execute(int loopIndex, int threadIndex)
|
||||
{
|
||||
// 1. Get the specific pChunk for this thread
|
||||
var pChunk = (byte*)chunks[loopIndex];
|
||||
var count = chunkCount[loopIndex];
|
||||
|
||||
<# for (var j = 0; j < i; j++){ #>
|
||||
var off<#= j #> = offsets<#= j #>[loopIndex];
|
||||
var enableOff<#= j #> = bitsOffsets<#= j #>[loopIndex];
|
||||
|
||||
<# } #>
|
||||
var pEntity = (Entity*)(pChunk + entityOffset[loopIndex]);
|
||||
<# for (var j = 0; j < i; j++){ #>
|
||||
var ptr<#= j #> = (<#= "T" + j #>*)(pChunk + off<#= j #>);
|
||||
<# } #>
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
<# for (var j = 0; j < i; j++){ #>
|
||||
if (enableOff<#= j #> != -1 && !EntityQuery.CheckBit(pChunk + enableOff<#= j #>, i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
<# } #>
|
||||
userJob.Execute(pEntity[i], <#= AppendParameters(i, "ref ptr{0}[i]") #>);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<# } #>
|
||||
public unsafe partial struct EntityQuery
|
||||
{
|
||||
<# for (var i = 1; i <= Amount; i++)
|
||||
{
|
||||
var generics = AppendGenerics(i);
|
||||
var restrictions = AppendGenericRestrictionsMultiline(i, "unmanaged, IComponent", 2);
|
||||
#>
|
||||
private struct DisposeJobEntity<#= i #> : IJob
|
||||
{
|
||||
public UnsafeList<IntPtr> chunkList;
|
||||
public UnsafeList<int> chunkEntityCounts;
|
||||
public UnsafeList<int> entityOffsets;
|
||||
|
||||
<# for (var j = 0; j < i; j++){ #>
|
||||
public UnsafeList<int> offsets<#= j #>;
|
||||
public UnsafeList<int> bitsOffsets<#= j #>;
|
||||
|
||||
<# } #>
|
||||
public void Execute(int threadIndex)
|
||||
{
|
||||
chunkList.Dispose();
|
||||
chunkEntityCounts.Dispose();
|
||||
entityOffsets.Dispose();
|
||||
|
||||
<# for (var j = 0; j < i; j++){ #>
|
||||
offsets<#= j #>.Dispose();
|
||||
bitsOffsets<#= j #>.Dispose();
|
||||
|
||||
<# } #>
|
||||
}
|
||||
}
|
||||
|
||||
public JobHandle ScheduleEntityParallel<TJob, <#= generics #>>(JobScheduler scheduler, TJob jobData, Allocator allocator, int batchSize, JobHandle dependency)
|
||||
where TJob : unmanaged, IJobEntityParallel<<#= generics #>>
|
||||
<#= restrictions #>
|
||||
{
|
||||
// 1. Flatten the World
|
||||
var chunkList = new UnsafeList<IntPtr>(128, allocator);
|
||||
var chunkEntityCounts = new UnsafeList<int>(128, allocator);
|
||||
var entityOffsets = new UnsafeList<int>(128, allocator);
|
||||
|
||||
<# for (var j = 0; j < i; j++){ #>
|
||||
var offsets<#= j #> = new UnsafeList<int>(128, allocator);
|
||||
var bitsOffsets<#= j #> = new UnsafeList<int>(128, allocator);
|
||||
|
||||
<# } #>
|
||||
// Iterate the Query's matching archetypes
|
||||
foreach (var archID in _matchingArchetypes)
|
||||
{
|
||||
ref var arch = ref World.GetWorld(_worldID)
|
||||
.GetValueOrThrow(ResultStatus.Success)
|
||||
.GetArchetypeReference(archID);
|
||||
|
||||
if (arch.ChunkCount == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get offsets ONCE per archetype
|
||||
<# for (var j = 0; j < i; j++){ #>
|
||||
var layout<#= j #> = arch.GetLayout(ComponentTypeID<T<#= j #>>.value)
|
||||
.GetValueOrThrow(ResultStatus.Success);
|
||||
<# } #>
|
||||
|
||||
// Add all chunks from this archetype
|
||||
for (var i = 0; i < arch.ChunkCount; i++)
|
||||
{
|
||||
ref var chunkRef = ref arch.GetChunkReference(i);
|
||||
|
||||
chunkList.Add((IntPtr)chunkRef.GetUnsafePtr());
|
||||
chunkEntityCounts.Add(chunkRef.Count);
|
||||
entityOffsets.Add(arch.EntityIDsOffset);
|
||||
|
||||
<# for (var j = 0; j < i; j++){ #>
|
||||
offsets<#= j #>.Add(layout<#= j #>.offset);
|
||||
bitsOffsets<#= j #>.Add(layout<#= j #>.enableBitsOffset);
|
||||
|
||||
<# } #>
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Create the Runner
|
||||
var runner = new JobEntityBatch<TJob, <#= generics #>>
|
||||
{
|
||||
userJob = jobData,
|
||||
chunks = chunkList,
|
||||
chunkCount = chunkEntityCounts,
|
||||
entityOffset = entityOffsets,
|
||||
|
||||
<# for (var j = 0; j < i; j++){ #>
|
||||
offsets<#= j #> = offsets<#= j #>,
|
||||
bitsOffsets<#= j #> = bitsOffsets<#= j #>,
|
||||
|
||||
<# } #>
|
||||
};
|
||||
|
||||
var jobHandle = scheduler.ScheduleParallel(ref runner, chunkList.Count, batchSize, dependency);
|
||||
|
||||
// 3. Dispose the temp lists
|
||||
var disposeJob = new DisposeJobEntity<#= i #>
|
||||
{
|
||||
chunkList = chunkList,
|
||||
chunkEntityCounts = chunkEntityCounts,
|
||||
entityOffsets = entityOffsets,
|
||||
|
||||
<# for (var j = 0; j < i; j++){ #>
|
||||
offsets<#= j #> = offsets<#= j #>,
|
||||
bitsOffsets<#= j #> = bitsOffsets<#= j #>,
|
||||
|
||||
<# } #>
|
||||
};
|
||||
|
||||
scheduler.Schedule(ref disposeJob, jobHandle);
|
||||
|
||||
return jobHandle;
|
||||
}
|
||||
|
||||
<# } #>
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
if (i > 0) sb.Append(", ");
|
||||
sb.Append(string.Format(template, i));
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
@@ -27,27 +28,18 @@
|
||||
return AppendGenerics(amount, "T{0}");
|
||||
}
|
||||
|
||||
public StringBuilder AppendGenericRefParameters(int amount)
|
||||
public StringBuilder AppendParameters(int amount, string template)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
for (var localIndex = 0; localIndex < amount; localIndex++)
|
||||
{
|
||||
sb.Append($"ref T{localIndex} t{localIndex}Component,");
|
||||
sb.Append(string.Format(template, localIndex));
|
||||
if (localIndex < amount - 1)
|
||||
{
|
||||
sb.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
sb.Length--;
|
||||
return sb;
|
||||
}
|
||||
|
||||
public StringBuilder AppendRefParameters(int amount, string template)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
for (var localIndex = 0; localIndex < amount; localIndex++)
|
||||
{
|
||||
sb.Append($"ref {string.Format(template, localIndex)},");
|
||||
}
|
||||
|
||||
sb.Length--;
|
||||
return sb;
|
||||
}
|
||||
|
||||
@@ -62,6 +54,7 @@
|
||||
sb.Append(' ');
|
||||
}
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
@@ -83,6 +76,7 @@
|
||||
sb.AppendLine();
|
||||
}
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
@@ -102,6 +96,7 @@
|
||||
sb.Append(" && ");
|
||||
}
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
@@ -116,6 +111,7 @@
|
||||
sb.Append(" && ");
|
||||
}
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
@@ -130,6 +126,7 @@
|
||||
sb.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
@@ -144,6 +141,7 @@
|
||||
sb.Append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
#>
|
||||
Reference in New Issue
Block a user