#Need some clarifications with EntityCommandBuffer

1 messages · Page 1 of 1 (latest)

quartz quarry
#

I am most definitely using the entity command system completely wrong and I need some clarifications

My ISystem OnUpdate looks like this

EntityCommandBufferSystem ECBSystem = state.World.GetOrCreateSystemManaged<EndSimulationEntityCommandBufferSystem>();

EntityCommandBuffer ECB = ECBSystem.CreateCommandBuffer();

EntityCommandBuffer.ParallelWriter ECBParallel = ECB.AsParallelWriter();

EntityCommandBufferSystem
I'm not completely sure what this does, all ik is that you can create command buffers and you can add a job handle for jobs that include EntityCommandBufferSystem.ParallelWriter with
ECBSystem.AddJobHandleForProducer(handle);. Other than that I'm pretty lost.

EntityCommandBuffer
This is basically a list of commands that the entity manager needs to do, instead of doing each one every time, it'll only do them at certain times. Also, it requires .Playback(EntityManager) in order to actual queue changes, I think that's how it works?

EntityCommandBuffer.ParallelWriter
This is supposedly only used within IJobParallelFor to safely write into the EntityCommandBuffer I'm not exactly sure why I need to:

ECBSystem.AddJobHandleForProducer(handle);
state.Dependency = handle;

TL;DR
Now here's my problem:
I recognize that any EntityCommandBuffer you make needs to be disposed. However, I use EntityCommandBuffer.ParallelWriter in a IJobParallelFor and so when I try to dispose EntityCommandBuffer it expectingly gives me an error that I cannot dispose something currently being read to. If I don't dispose EntityCommandBuffer it'll be a memory leak

A possible solution is to basically force this job to complete within the same frame, but most of my other jobs are independent, and are not strict with completion times, so I wish the job to be completely parallel.

I've also considered using the "World" EntityCommandBuffer but I'm not sure how to gain access to it or how it differs from a normal buffer.

tall jasper
#

EntityCommandBufferSystem ECBSystem = state.World.GetOrCreateSystemManaged<EndSimulationEntityCommandBufferSystem>();
this is wrong or you've read some very out dated information. you should be using
SystemAPI.GetSingleton<EndSimulationEntityCommandBufferSystem.Singleton>();
By doing GetOrCreateSystemManaged you can no longer burst compile your OnUpdate in ISystem (which is the point of using ISystem)

#

You also don't need AddJobHandleForProducer if you use GetSingleton version

#

the getsystem and AddJobHandleForProducer is the old (2+ year ago) way of doing it in entities 0.51 and earlier

#

You also don't dispose the command buffer created via a commandbuffersystem, it uses it's own memory pool and handles it itself

#

You also don't use Playback, that's the responsibility of the EndSimulationEntityCommandBufferSystem

#

Using EntityCommandBufferSystem means you are deferring the entity command buffer playback to when that system updates, avoiding an instant sync point

#

the only time you use Playback and Dispose on an EntityCommandBuffer is if you create it yourself via
new EntityCommandBuffer(Allocator)

lyric swallow
#

Always check for the date of the document. Anything discussing APIs earlier than 2023 is now out of date.

quartz quarry
#

This was super helpful! I can't believe I've been using outdated information. This is what I understand / changed now:

#Instead of 
EntityCommandBufferSystem ECBSystem = state.World.GetOrCreateSystemManaged<EndSimulationEntityCommandBufferSystem>();

#Use
EndSimulationEntityCommandBufferSystem.Singleton ECBSystem = SystemAPI.GetSingleton<EndSimulationEntityCommandBufferSystem.Singleton>();

EntityCommandBuffer made from the EndSimulationEntityCommandBufferSystem do NOT need to be playedback or disposed since it's handled by the system, it's only used when you make an independent EntityCommandBuffer. You also do not need to use AddJobHandleForProducer(handle); since the system handles this

What I'm a bit confused is, surely I still have to register my JobHandle into the EndSimulationEntityCommandBufferSystem? Right now I'm just regularly .Schedule() without any dependencies.

ArgumentException: The previously scheduled job Test:CreationJob writes to the Unity.Entities.EntityCommandBuffer CreationJob.ECBParallel. You must call JobHandle.Complete() on the job Test:CreationJob, before you can write to the Unity.Entities.EntityCommandBuffer safely.
#

Also side note, although .Complete() is valid, my job is independent and does not need to be strictly completed in the same frame ideally

tall jasper
#

You do not need to register the handle, it relies on the default dependency management on the singleton component you got via getsingleton to ensure safety

quartz quarry
#

with like:

state.Dependency = handle

?

#

Shoot, I should've also mentioned that my IJobParallelFor job does use the EntityCommandBuffer.ParallelWriter to make entities

tall jasper
#

you need to ensure you write back your handle

#

for ije this is automatic

#

for everything else, ijobfor etc yes you need to ensure you do state.dependency = new job().scheduleX(state.dependency)

quartz quarry
#

and im guessing if I have multiple IJobParallelFor I just use CombineDependencies(state.Dependency, handle)

tall jasper
#

hmm depends on what theyre accessing

#

usually you'd just pass the handle between them

#

a lto of the times they can't be run at sametime

#
state.Dependency = new Job1().ScheduleParallel(state.Dependency);
state.Dependency = new Job2().ScheduleParallel(state.Dependency);
state.Dependency = new Job3().ScheduleParallel(state.Dependency);
state.Dependency = new Job4().ScheduleParallel(state.Dependency);```
#

so you just schedule them sequentually

quartz quarry
#

hm isnt it defined as.ScheduleParallel(T, int, int, handle), idk if you are just imply the fields

#

I just remember getting an error where .ScheduleParallel doesnt have overloaded arguments of like 3 or something

#

also, by passing the dependency into the job itself, I no longer need to define the dependency of the SystemState correct?

tall jasper
#

i'm just writing a general example

quartz quarry
#

oh right, I'm pretty sure the one I defined was for IJobParallelFor (whoops)

quartz quarry
#

oh wait nvm, I'm actually blind, LOL