the first one will run through chunks and populate some intermediate data into a NativeQueue,
the second job is expected to work on the pass-in NativeQueue and get the final result.
The problem is that the second job (IJobParallelFor) needs the length to schedule, which is not available at the point in main thread. I checked the IJobParallelForDefer but it needs a NativeList, which doesn’t have a Concurrent version to replace the NativeQueue in the first job.
It seems that the only available method is to use a NativeHashMap? Or is there something I’m missing here?
This is a common issue with no single solution. It depends a lot on your data, I have 2 ways that I often go about it, both of which you mentioned, but there are alternatives.
The first way is just an intermezzo job that copies the queue to a list. Common enough that I threw together a generic version of this some point in the past.
// <copyright file="CopyQueueToListJob.cs" company="BovineLabs">
// Copyright (c) BovineLabs. All rights reserved.
// </copyright>
namespace BovineLabs.Common.Jobs
{
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
/// <summary>
/// Copy a <see cref="NativeQueue{T}"/> to a <see cref="NativeList{T}"/>.
/// </summary>
/// <typeparam name="T">The type of the containers.</typeparam>
[BurstCompile]
public struct CopyQueueToListJob<T> : IJob
where T : struct
{
/// <summary>
/// The input queue.
/// </summary>
public NativeQueue<T> Queue;
/// <summary>
/// The output list.
/// </summary>
public NativeList<T> List;
/// <inheritdoc/>
public void Execute()
{
this.List.Clear();
this.List.Capacity = this.Queue.Count;
while (this.Queue.TryDequeue(out var v))
{
this.List.Add(v);
}
}
}
}
It surprisingly takes little time to do this in a burst job even with a lot of elements. However if length is an issue, the other method is to use a hash map if you can figure out an upper limit of its capacity. This is usually from Query.CalculateLength() if each entity in a query will at most add 1 to the map.
{
// Ensure our hash map have capacity
var requiredCapacity = this.allObserversQuery.CalculateLength();
if (requiredCapacity > this.visionMap.Capacity)
{
this.visionMap.Capacity = requiredCapacity;
}
// .. schedule job