Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge upstream #18

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Arch.Benchmarks/Arch.Benchmarks.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
<PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.2" />
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="7.0.0" />
<PackageReference Include="ZeroAllocJobScheduler" Version="1.0.2" />
<PackageReference Include="ZeroAllocJobScheduler" Version="1.1.1" />
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion src/Arch.Samples/Arch.Samples.csproj
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>

<!--<AllowUnsafeBlocks>true</AllowUnsafeBlocks>-->
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<Configurations>Debug;Release;Release-Pure;Release-PureECS;Release-Events;Debug-PureECS;Debug-Events</Configurations>
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<!--<TreatWarningsAsErrors>true</TreatWarningsAsErrors>-->
</PropertyGroup>

Expand Down
21 changes: 17 additions & 4 deletions src/Arch.Samples/Game.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using Arch.Core;
using Arch.Core.Extensions;
using Arch.Core.Utils;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Schedulers;

namespace Arch.Samples;

Expand All @@ -13,7 +15,7 @@ public sealed class Game : Microsoft.Xna.Framework.Game
{
// The world and a job scheduler for multithreading.
private World _world;
private JobScheduler.JobScheduler _jobScheduler;
private JobScheduler _jobScheduler;

// Our systems processing entities.
private MovementSystem _movementSystem;
Expand Down Expand Up @@ -60,15 +62,26 @@ protected override void BeginRun()
{
base.BeginRun();

// Create world & systems
// Create world & Job Scheduler
_world = World.Create();
_jobScheduler = new("SampleWorkerThreads");
_jobScheduler = new(
new JobScheduler.Config
{
ThreadPrefixName = "Arch.Samples",
ThreadCount = 0,
MaxExpectedConcurrentJobs = 64,
StrictAllocationMode = false,
}
);
World.SharedJobScheduler = _jobScheduler;

// Create systems
_movementSystem = new MovementSystem(_world, GraphicsDevice.Viewport.Bounds);
_colorSystem = new ColorSystem(_world);
_drawSystem = new DrawSystem(_world, _spriteBatch);

// Spawn in entities with position, velocity and sprite
for (var index = 0; index < 1002; index++)
for (var index = 0; index < 150_000; index++)
{
_world.Create(
new Position { Vec2 = _random.NextVector2(GraphicsDevice.Viewport.Bounds) },
Expand Down
7 changes: 6 additions & 1 deletion src/Arch.SourceGen/Fundamentals/StructuralChanges.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ public static StringBuilder AppendWorldAdd(this StringBuilder sb, int amount)
var inParameters = new StringBuilder().InsertGenericInParams(amount);
var types = new StringBuilder().GenericTypeParams(amount);

var getIds = new StringBuilder();
var setIds = new StringBuilder();
var addEvents = new StringBuilder();
for (var index = 0; index <= amount; index++)
{
setIds.AppendLine($"spanBitSet.SetBit(Component<T{index}>.ComponentType.Id);");
getIds.AppendLine($"var id{index} = Component<T{index}>.ComponentType.Id;");
setIds.AppendLine($"spanBitSet.SetBit(id{index});");
addEvents.AppendLine($"OnComponentAdded<T{index}>(entity);");
}

Expand All @@ -36,6 +38,9 @@ public static StringBuilder AppendWorldAdd(this StringBuilder sb, int amount)
{
var oldArchetype = EntityInfo.GetArchetype(entity.Id);

// Get all the ids here just in case we are adding a new component as this will grow the ComponentRegistry.Size
{{getIds}}

// BitSet to stack/span bitset, size big enough to contain ALL registered components.
Span<uint> stack = stackalloc uint[BitSet.RequiredLength(ComponentRegistry.Size)];
oldArchetype.BitSet.AsSpan(stack);
Expand Down
2 changes: 1 addition & 1 deletion src/Arch.SourceGen/Queries/AddWithQueryDescription.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public static void AppendAddWithQueryDescription(this StringBuilder sb, int amou
public void Add<{{generics}}>(in QueryDescription queryDescription, {{parameters}})
{
// BitSet to stack/span bitset, size big enough to contain ALL registered components.
Span<uint> stack = stackalloc uint[BitSet.RequiredLength(ComponentRegistry.Size)];
Span<uint> stack = stackalloc uint[BitSet.RequiredLength(ComponentRegistry.Size + {{amount + 1}})];

var query = Query(in queryDescription);
foreach (var archetype in query.GetArchetypeIterator())
Expand Down
64 changes: 2 additions & 62 deletions src/Arch.SourceGen/Queries/InlineParallelQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,37 +24,7 @@ public static void AppendHpParallelQuery(this StringBuilder builder, int amount)
var innerJob = new IForEachJob<T,{{generics}}>();
innerJob.ForEach = iForEach;

var pool = JobMeta<ChunkIterationJob<IForEachJob<T,{{generics}}>>>.Pool;
var query = Query(in description);
foreach (var archetype in query.GetArchetypeIterator())
{
var archetypeSize = archetype.ChunkCount;
var part = new RangePartitioner(Environment.ProcessorCount, archetypeSize);
foreach (var range in part)
{
var job = pool.Get();
job.Start = range.Start;
job.Size = range.Length;
job.Chunks = archetype.Chunks;
job.Instance = innerJob;
JobsCache.Add(job);
}

IJob.Schedule(JobsCache, JobHandles);
JobScheduler.JobScheduler.Instance.Flush();
JobHandle.Complete(JobHandles);
JobHandle.Return(JobHandles);

// Return jobs to pool
for (var jobIndex = 0; jobIndex < JobsCache.Count; jobIndex++)
{
var job = Unsafe.As<ChunkIterationJob<IForEachJob<T,{{generics}}>>>(JobsCache[jobIndex]);
pool.Return(job);
}

JobHandles.Clear();
JobsCache.Clear();
}
InlineParallelChunkQuery(in description, innerJob);
}
""";

Expand Down Expand Up @@ -83,37 +53,7 @@ public static void AppendHpeParallelQuery(this StringBuilder builder, int amount
var innerJob = new IForEachWithEntityJob<T,{{generics}}>();
innerJob.ForEach = iForEach;

var pool = JobMeta<ChunkIterationJob<IForEachWithEntityJob<T,{{generics}}>>>.Pool;
var query = Query(in description);
foreach (var archetype in query.GetArchetypeIterator()) {

var archetypeSize = archetype.ChunkCount;
var part = new RangePartitioner(Environment.ProcessorCount, archetypeSize);
foreach (var range in part)
{
var job = pool.Get();
job.Start = range.Start;
job.Size = range.Length;
job.Chunks = archetype.Chunks;
job.Instance = innerJob;
JobsCache.Add(job);
}

IJob.Schedule(JobsCache, JobHandles);
JobScheduler.JobScheduler.Instance.Flush();
JobHandle.Complete(JobHandles);
JobHandle.Return(JobHandles);

// Return jobs to pool
for (var jobIndex = 0; jobIndex < JobsCache.Count; jobIndex++)
{
var job = Unsafe.As<ChunkIterationJob<IForEachWithEntityJob<T,{{generics}}>>>(JobsCache[jobIndex]);
pool.Return(job);
}

JobHandles.Clear();
JobsCache.Clear();
}
InlineParallelChunkQuery(in description, innerJob);
}
""";

Expand Down
14 changes: 7 additions & 7 deletions src/Arch.SourceGen/Queries/Job.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ public struct ForEachJob<{{generics}}> : IChunkJob
public ForEach<{{generics}}> ForEach;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Execute(int index, ref Chunk chunk)
public void Execute(ref Chunk chunk)
{
var chunkSize = chunk.Size;
{{getFirstElement}}

for (var entityIndex = chunkSize - 1; entityIndex >= 0; --entityIndex)
foreach(var entityIndex in chunk)
{
{{getComponents}}
ForEach({{insertParams}});
Expand Down Expand Up @@ -63,7 +63,7 @@ public struct ForEachWithEntityJob<{{generics}}> : IChunkJob
public ForEachWithEntity<{{generics}}> ForEach;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Execute(int index, ref Chunk chunk)
public void Execute(ref Chunk chunk)
{
ref var entityFirstElement = ref chunk.Entity(0);
{{getFirstElement}}
Expand Down Expand Up @@ -104,12 +104,12 @@ public struct IForEachJob<T,{{generics}}> : IChunkJob where T : struct, IForEach
public T ForEach;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Execute(int index, ref Chunk chunk)
public void Execute(ref Chunk chunk)
{
var chunkSize = chunk.Size;
{{getFirstElement}}

for (var entityIndex = chunkSize - 1; entityIndex >= 0; --entityIndex)
foreach(var entityIndex in chunk)
{
{{getComponents}}
ForEach.Update({{insertParams}});
Expand Down Expand Up @@ -143,13 +143,13 @@ public struct IForEachWithEntityJob<T,{{generics}}> : IChunkJob where T : struct
public T ForEach;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Execute(int index, ref Chunk chunk)
public void Execute(ref Chunk chunk)
{
var chunkSize = chunk.Size;
ref var entityFirstElement = ref chunk.Entity(0);
{{getFirstElement}}

for (var entityIndex = chunkSize - 1; entityIndex >= 0; --entityIndex)
foreach(var entityIndex in chunk)
{
var entity = Unsafe.Add(ref entityFirstElement, entityIndex);
{{getComponents}}
Expand Down
64 changes: 2 additions & 62 deletions src/Arch.SourceGen/Queries/ParallelQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,37 +24,7 @@ public static StringBuilder AppendParallelQuery(this StringBuilder sb, int amoun
var innerJob = new ForEachJob<{{generics}}>();
innerJob.ForEach = forEach;

var pool = JobMeta<ChunkIterationJob<ForEachJob<{{generics}}>>>.Pool;
var query = Query(in description);
foreach (var archetype in query.GetArchetypeIterator()) {

var archetypeSize = archetype.ChunkCount;
var part = new RangePartitioner(Environment.ProcessorCount, archetypeSize);
foreach (var range in part)
{
var job = pool.Get();
job.Start = range.Start;
job.Size = range.Length;
job.Chunks = archetype.Chunks;
job.Instance = innerJob;
JobsCache.Add(job);
}

IJob.Schedule(JobsCache, JobHandles);
JobScheduler.JobScheduler.Instance.Flush();
JobHandle.Complete(JobHandles);
JobHandle.Return(JobHandles);

// Return jobs to pool
for (var jobIndex = 0; jobIndex < JobsCache.Count; jobIndex++)
{
var job = Unsafe.As<ChunkIterationJob<ForEachJob<{{generics}}>>>(JobsCache[jobIndex]);
pool.Return(job);
}

JobHandles.Clear();
JobsCache.Clear();
}
InlineParallelChunkQuery(in description, innerJob);
}
""";

Expand Down Expand Up @@ -84,37 +54,7 @@ public static StringBuilder AppendParallelEntityQuery(this StringBuilder sb, int
var innerJob = new ForEachWithEntityJob<{{generics}}>();
innerJob.ForEach = forEach;

var pool = JobMeta<ChunkIterationJob<ForEachWithEntityJob<{{generics}}>>>.Pool;
var query = Query(in description);
foreach (var archetype in query.GetArchetypeIterator())
{
var archetypeSize = archetype.ChunkCount;
var part = new RangePartitioner(Environment.ProcessorCount, archetypeSize);
foreach (var range in part)
{
var job = pool.Get();
job.Start = range.Start;
job.Size = range.Length;
job.Chunks = archetype.Chunks;
job.Instance = innerJob;
JobsCache.Add(job);
}

IJob.Schedule(JobsCache, JobHandles);
JobScheduler.JobScheduler.Instance.Flush();
JobHandle.Complete(JobHandles);
JobHandle.Return(JobHandles);

// Return jobs to pool
for (var jobIndex = 0; jobIndex < JobsCache.Count; jobIndex++)
{
var job = Unsafe.As<ChunkIterationJob<ForEachWithEntityJob<{{generics}}>>>(JobsCache[jobIndex]);
pool.Return(job);
}

JobHandles.Clear();
JobsCache.Clear();
}
InlineParallelChunkQuery(in description, innerJob);
}
""";

Expand Down
2 changes: 1 addition & 1 deletion src/Arch.SourceGen/QueryGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
var accessors = new StringBuilder();
accessors.AppendLine("using System;");
accessors.AppendLine("using System.Runtime.CompilerServices;");
accessors.AppendLine("using JobScheduler;");
accessors.AppendLine("using Schedulers;");
accessors.AppendLine("using Arch.Core.Utils;");
accessors.AppendLine("using System.Diagnostics.Contracts;");
accessors.AppendLine("using Arch.Core.Extensions;");
Expand Down
11 changes: 9 additions & 2 deletions src/Arch.Tests/CommandBufferTest.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Arch.CommandBuffer;
using Arch.Core;
using Arch.Core.Utils;
using Schedulers;
using static NUnit.Framework.Assert;

namespace Arch.Tests;
Expand Down Expand Up @@ -222,12 +223,18 @@ public void CommandBufferCombined()
public partial class CommandBufferTest
{

private JobScheduler.JobScheduler _jobScheduler;
private JobScheduler _jobScheduler;

[OneTimeSetUp]
public void Setup()
{
_jobScheduler = new JobScheduler.JobScheduler("CommandBuffer");
_jobScheduler = new JobScheduler(
new JobScheduler.Config{
ThreadPrefixName = "CommandBuffer",
ThreadCount = 0,
MaxExpectedConcurrentJobs = 64,
StrictAllocationMode = false,
});
}

[OneTimeTearDown]
Expand Down
Loading