Hi All,
I’m working with DynamicBuffer and having trouble piecing together a solution to get write access to a DynamicBuffer off thread and iterate over its contents in parallel.
For example, the following approach allows me to iterate and modify the DynamicBuffer in parallel but causes the calling system to wait on the main thread for write access to the DynamicBuffer<Grid_Humidity>.
Note: All of the grid layers are on a singleton Entity with a DynamicBuffer for each layer.
SelectionSystem.OnUpdate()
DynamicBuffer<Grid_Selection> selectionGrid = GetBuffer<Grid_Selection>(GetSingletonEntity<Grid_Selection>());
DynamicBuffer<Grid_Humidity> humidityGrid = GetBuffer<Grid_Humidity>(GetSingletonEntity<Grid_Humidity>());
Dependency = new AddHumidityWhereSelectedJob()
{
AddAmount = (int)math.round(ADD_HUMIDITY_PER_SECOND * Time.DeltaTime),
SelectionGrid = selectionGrid.AsNativeArray(),
HumidityGrid = humidityGrid.AsNativeArray()
}.ScheduleParallel(humidityGrid.Length, 64, Dependency);
AddHumidityWhereSelectedJob
[BurstCompile]
private struct AddHumidityWhereSelectedJob : IJobFor
{
[ReadOnly] public int AddAmount;
[ReadOnly] public NativeArray<Grid_Selection> SelectionGrid;
public NativeArray<Grid_Humidity> HumidityGrid;
public void Execute(int index)
{
Grid_Humidity humidity = HumidityGrid[index];
//TODO: Batch 4 at a time and profile
humidity.Value = (ushort)math.mad(SelectionGrid[index].Value, AddAmount, humidity.Value);
HumidityGrid[index] = humidity;
}
}
This works well.
-
The changes are written back to the DynamicBuffer on my grid entity
-
The work is spread across my worker threads.
However, the GetBuffer<…>() calls in SelectionSystem.OnUpdate stall the main thread until write access can be gained (when other jobs stop writing to the buffers). This seems to be confirmed in the profiler. I understand the need to wait for write access but I’d like to wait off of the main thread so that the main thread can continue to progress through other systems.
An Existing Read Only Solution
In other systems where I only need read access to the grid I’ve solved this by scheduling a sequence of jobs that will
- Copy the DynamicBuffer contents into a NativeArray via an IJobEntityBatch
- Perform work that reads from the grid data (NativeArray)
- Dispose the temporary NativeArray
This is great because it allows the system to schedule the three jobs and then get out of the way on the main thread while the jobs wait for data access and dependencies to be resolved.
Question
Knowing that
- We can’t spawn jobs from within jobs
- I want to spend the bare minimum time on the main thread
- I need to write to one of the DynamicBuffers
How can I safely gain reference to a DynamicArray off thread and then modify the contents in parallel?
I almost need some combination of IJobEntityBatch and IJobFor.ScheduleParallel()
or a way to pass a NativeArray reference to a job that won’t be initialized until the previous job completes.
Any thoughts or suggestions would be very much appreciated. There are a ton of tools at our disposal and I’m still getting a feel for how they can come together in useful ways.
Thanks!