Search Unity

Output list from job?

Discussion in 'Data Oriented Technology Stack' started by vsnry, Dec 11, 2018.

  1. vsnry

    vsnry

    Joined:
    May 4, 2018
    Posts:
    29
    I'm trying to make a job which loops through an array, calculates something and then puts that information into a list which can be read from the main thread after the job is completed, but I can't figure out how to do this at all. All I need to do is just have the job write to this list, I don't need to read it from inside the job itself. Any help?
     
  2. LennartJohansen

    LennartJohansen

    Joined:
    Dec 1, 2014
    Posts:
    2,272
    You make a NativeList<T>. Then add it to the job and in the job add items to it.
    This has to be a IJob not a IJobParallellFor since you can not add to a NativeLists from parallell jobs.

    Lennart
     
  3. vsnry

    vsnry

    Joined:
    May 4, 2018
    Posts:
    29
    Is it not possible to do it from a parallel job at all?
     
  4. LennartJohansen

    LennartJohansen

    Joined:
    Dec 1, 2014
    Posts:
    2,272
    Not with a NativeList. a nativeQueuw.concurrent could be used or you update a NativeArray with the same size and filter this later based on some flag or result.
     
  5. vsnry

    vsnry

    Joined:
    May 4, 2018
    Posts:
    29
    I tried looking up information on NativeQueue, but couldn't find anything.. What is NativeQueue.concurrent and how do I use it? Also, will I be able to turn the NativeQueue into an array after the job is complete?
     
  6. vsnry

    vsnry

    Joined:
    May 4, 2018
    Posts:
    29
    Okay, so I figured out how to use NativeQueue, but for some reason it's giving me an error saying "
    Cannot implicitly convert type `Unity.Collections.NativeQueue<UnityEngine.Vector3>' to `Unity.Collections.NativeQueue<UnityEngine.Vector3>.Concurrent'"

    How come?

    This is a part of my code:

    Code (CSharp):
    1. public struct ChunkUpdateJob : IJobParallelFor {
    2.     public NativeQueue<Vector3>.Concurrent verticesToReturn;
    3.     public NativeQueue<int>.Concurrent trianglesToReturn;
    4.  
    5.     public void Execute(int x) {}
    6. }
    7.  
    8. var returnedVertices = new NativeQueue<Vector3>(Allocator.TempJob);
    9. var returnedTriangles = new NativeQueue<int>(Allocator.TempJob);
    10. var updateJob = new ChunkUpdateJob {
    11.     verticesToReturn = returnedVertices,
    12.     trianglesToReturn = returnedTriangles
    13. };
    14. var updateJobHandle = updateJob.Schedule(voxels.Length, 250);
    15. returnedVertices.Dispose();
    16. returnedTriangles.Dispose();
     
  7. LennartJohansen

    LennartJohansen

    Joined:
    Dec 1, 2014
    Posts:
    2,272
    I think you shoud decleare it as public NativeQueue<int> trianglesToReturn;

    and assign as returnedTriangles.Concurrent

    Lennart
     
  8. vsnry

    vsnry

    Joined:
    May 4, 2018
    Posts:
    29
    Well now it's erroring with "`Concurrent': cannot reference a type through an expression. Consider using `Unity.Collections.NativeQueue<T>.Concurrent' instead".

    Code (CSharp):
    1. public struct ChunkUpdateJob : IJobParallelFor {
    2.     public NativeQueue<Vector3> verticesToReturn;
    3.     public NativeQueue<int> trianglesToReturn;
    4.     public void Execute(int x) {}
    5. }
    6. var returnedVertices = new NativeQueue<Vector3>(Allocator.TempJob);
    7. var returnedTriangles = new NativeQueue<int>(Allocator.TempJob);
    8. var updateJob = new ChunkUpdateJob {
    9.     verticesToReturn = returnedVertices.Concurrent,
    10.     trianglesToReturn = returnedTriangles.Concurrent
    11. };
    12. var updateJobHandle = updateJob.Schedule(voxels.Length, 250);
    13. returnedVertices.Dispose();
    14. returnedTriangles.Dispose();
    I tried to turn

    Code (CSharp):
    1. var returnedVertices = new NativeQueue<Vector3>(Allocator.TempJob);
    2. var returnedTriangles = new NativeQueue<int>(Allocator.TempJob);
    Into

    Code (CSharp):
    1. var returnedVertices = new NativeQueue<Vector3>.Concurrent(Allocator.TempJob);
    2. var returnedTriangles = new NativeQueue<int>.Concurrent(Allocator.TempJob);
    But it errored with "The type `Unity.Collections.NativeQueue<UnityEngine.Vector3>.Concurrent' does not contain a constructor that takes `1' arguments"
     
  9. vsnry

    vsnry

    Joined:
    May 4, 2018
    Posts:
    29
    AH I figured it out. You need to use .ToConcurrent() when sending it to a job, but I still can't figure out how to turn the returned queue to an array as .ToArray() doesn't work.....
     
  10. recursive

    recursive

    Joined:
    Jul 12, 2012
    Posts:
    583
    ToConcurrent() is a multi-writer version of the data structure that can be used across multiple parallel jobs (or a single IJobParallelFor type job with work stealing).

    For reading, you must not use the Concurrent structure, but you can linearize it to a NativeList via an IJob:

    Code (CSharp):
    1.  
    2. [BurstCompile]
    3. struct FillQueueJob : IJobParallelFor // or IJobProcessComponent* or IJobChunk or...
    4. {
    5.     [ReadOnly] public NativeArray<PointAndOffset> Input;
    6.     public NativeQueue<Vector3>.Concurrent Output;
    7.  
    8.     public void Execute(int index)
    9.     {
    10.         PointAndOffset datum = Input[index];
    11.         float3 finalPosition = datum.Origin + datum.Offset;
    12.         Output.Enqueue(finalPosition);
    13.     }
    14. }
    15.  
    16. [BurstCompile]
    17. struct LinearizeJob : IJob
    18. {
    19.     public NativeQueue<float3> Source;
    20.     public NativeList<Vector3> Result;
    21.  
    22.     public void Execute()
    23.     {
    24.         while(Source.TryDequeue(out Vector3 vect))
    25.         {
    26.             Result.Add(vect);
    27.         }
    28.     }
    29. }
    EDIT:
    Do note that float3 is in the new Unity.Mathematics package. The burst compiler tech can natively accelerate it. It's convertible to Vector3 however, so you can still pass back to existing APIs should you need to.
     
  11. vsnry

    vsnry

    Joined:
    May 4, 2018
    Posts:
    29
    I'm trying to use the "LinearizeJob" job, but it's erroring with "Feature `out variable declaration' cannot be used because it is not part of the C# 6.0 language specification" on the "while(Source.TryDequeue(out Vector3 vect))" line. Already tried Google, couldn't find anything that fixes it..
     
  12. recursive

    recursive

    Joined:
    Jul 12, 2012
    Posts:
    583
    Oh snap. I'm using 2018.3 betas and C# 7.X features. If you're on earlier 2018 versions or 2018.3 betas, that won't work correctly.

    Try this:

    Code (CSharp):
    1. [BurstCompile]
    2. struct LinearizeJob : IJob
    3. {
    4.     public NativeQueue<float3> Source;
    5.     public NativeList<Vector3> Result;
    6.     public void Execute()
    7.     {
    8.         Vector3 vect;
    9.         while(Source.TryDequeue(out vect))
    10.         {
    11.             Result.Add(vect);
    12.         }
    13.     }
    14. }
    All that C# 7 feature does is save you defining an out variable on the extra line.
    See this documentation for more info.