-
Notifications
You must be signed in to change notification settings - Fork 1
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
Entity Spawner Revamp #259
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good but spawners are no longer ACV compatible now and look much more difficult to bring into task drivers. Can we fix this?
Unfortunately I also don't think this will be of use to the CreateAndIntegrateTaskDriver
since we're not able to patch the reference in the EPD off the ECB.
return m_InstanceIDQueue.Dequeue(); | ||
} | ||
//If we don't, then increment our pool of IDs and return that instead. | ||
m_LargestInstanceIDIssued++; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better served as an IDProvider? UShortIDProvider
if you're feeling fancy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be, I think this is fine for now. decline-cookies/anvil-csharp-core#147 Would make this part go away since the Pool logic would handle adding new ints
if (m_InstanceIDQueue.Count > 0) | ||
{ | ||
return m_InstanceIDQueue.Dequeue(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we have a PooledIDProvider
or use Pool<T>
for this?
I looked at the Pool<T>
implementation and it would be trivial to support value types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I originally wanted to use a Pool but couldn't and it was a tangent to go down.
Added a TODO and linked to: decline-cookies/anvil-csharp-core#147
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like all you have to do is change one line to support value types in Pool<T>
that defaults the acquired value to null
entitySpawner.Playback(EntityManager); | ||
entitySpawner.DisposeECB(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure we should be playing back immediately on an immediate release. Shouldn't we still be waiting for the ECB playback moment that this EntitySpawnSystem
is configured to execute?
If you need a job handle for m_CommandBufferSystem.AddJobHandleForProducer
you can just pass default since your "work" with the ECB is done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I see, this isn't actually an ACV compatible type. Is there a way to require these in jobs without setting up a custom Schedule
function?
Would really like to maintain compatibility with the "Require" pattern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These functions are private.
The public facing ones are
public JobHandle AcquireAsync(out EntitySpawner value)
public void ReleaseAsync(JobHandle releaseAccessDependency)
I'm ok to implement one of the IAccessController
interfaces but they add in a bunch of extra stuff like Dispose
and the synchronous Acquire
functions that don't quite make sense.
I could explicitly implement those functions and just toss a NotSupported
exception but that does feel a bit dirty.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IAccessController
doesn't have Dispose
For the sync interface there's no real benefit over SpawnImmediate but no a problem to support either. Maybe you want to schedule an entity to exist at the system's sync point and not until then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I added support with the JobConfigs for Require
and Fulfill
so you can get an EntitySpawner
.
I don't think the ACV approach really makes sense for an EntitySpawner since it is the underlying Prototypes
hash map that is actually ACV'd.
You can still use the System like usual with SpawnDeferred
or SpawnImmediate
for main thread spawning. Or you can AcquireAsync
for custom job spawning.
TaskDrivers can easily use it via RequireEntitySpawner
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, ok. The way the EntitySpawnWriter's adapted before was the same idea where the writer wasn't actually what required the access control it was the data that backed it.
All these special interfaces just create headaches whenever we need to use them in generic contexts (like JobConfig). I guess we can wait until I hit that some day and convert it then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussed and while not great, it's ok enough for now.
{ | ||
ID = id; | ||
m_ECB = ecb; | ||
m_ECBWriter = m_ECB.AsParallelWriter(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any overhead associated with always asking for a parallel writer?
In most TaskDriver scenarios the writer won't be written to in parallel.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is probably some small amount of overhead just in terms of making the different lanes that a parallel writer can write to but that's a necessary evil.
With EntitySpawner
s being included in jobs to directly spawn, we have to allow for parallel jobs to write otherwise we'd be constraining all jobs to execute on one thread only.
In most TaskDriver scenarios the writer won't be written to in parallel.
I'm not sure that's true? All TaskDriver jobs are designed to go wide with most using BatchStrategy.MaximizeChunk
so with low volume it MIGHT only execute on one thread, but with more than one chunk worth of data it will definitely go on other threads.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With EntitySpawners being included in jobs to directly spawn, we have to allow for parallel jobs to write otherwise we'd be constraining all jobs to execute on one thread only.
We couldn't have an opt in to a parallel writer? Most jobs that I've written so far the spawn are running on a single thread. They tend to be low volume.
I'm not sure that's true? All TaskDriver jobs are designed to go wide with most using BatchStrategy.MaximizeChunk so with low volume it MIGHT only execute on one thread, but with more than one chunk worth of data it will definitely go on other threads.
Are they? Almost all the Task Drivers I've written use Schedule
for the jobs not ScheduleParallel
to avoid clobbering EPD entries. The BatchStrategy is irrelevant in that situation I thought.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmmn good point.
I started down a road here but it's a bunch of work and I feel like the performance overhead isn't a problem right now.
The underlying parallel writer will still work just fine on a single thread.
Once we upgrade to entities 1.0, we can remove the SharedComponent aspects that make duplicating the work across a regular ECB
and a ECB.ParallelWriter
less arduous.
Added a TODO.
@mbaker3 This is ready for re-review |
# Conflicts: # Scripts/Runtime/Entities/TaskDriver/TaskSet/Job/JobConfig/NoOpJobConfig.cs
Entity Spawners are now job structs that allow for creating an Entity in a job and getting back the deferred Entity from the Entity Command Buffer that will create it.
What is the current behaviour?
What is the new behaviour?
EntitySpawner
struct off of anEntitySpawnSystem
and use that in your jobs.EntitySpawner
s can create anyIEntitySpawnDefinition
, no need to have it typed beforehand anymore.Entity
that the underlyingEntityCommandBuffer
creates. You can use the API on theEntitySpawner
to assign relationships that will be patched later on.What issues does this resolve?
What PRs does this depend on?
Does this introduce a breaking change?