Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[Request] RaycastCommand.ScheduleBatch with AsDeferredJobArray support

Discussion in 'Entity Component System' started by julian-moschuering, Mar 12, 2019.

  1. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    Dear Unity,

    currently RaycastCommand.ScheduleBatch synchronously reads the addresses and lenghts of the passed NativeArrays, which means I can't generate the raycast commands in a Job without synching with the main thread.
    As ScheduleBatch uses the Job system I guess it should be doable to make it support 'NativeArrays' received from NativeList<T>.AsDeferredJobArray() too?

    Thank you!
     
    OndrejP and Dinamytes like this.
  2. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    417
    You could schedule a job that creates the RaycastCommands, then pass the commands into ScheduleBatch making sure to pass in the previous job's handle as a dependency. This way you don't break the dependency chain. Here is some of my project's code that does this (Ignore the NativeList<int> and substitute in a normal IJobParallelFor):

    Code (CSharp):
    1. public static JobHandle CreateParallelRaycasts(
    2.         JobHandle inputDeps,
    3.         NativeArray<LineOfSightRequest> requests,
    4.         NativeList<int> requestsMissesIndices,
    5.         int length,
    6.         LayerMask mask,
    7.         out NativeArray<RaycastHit> results,
    8.         out NativeArray<RaycastCommand> commands
    9.     )
    10.     {
    11.         var commandsOut = new NativeArray<RaycastCommand>(length, Allocator.TempJob);
    12.         var resultsOut = new NativeArray<RaycastHit>(length, Allocator.TempJob);
    13.         var createRaycasts = new CreateRaycastsJob
    14.         {
    15.             losRequests = requests,
    16.             commands = commandsOut,
    17.             mask = mask
    18.         };
    19.         inputDeps = createRaycasts.ScheduleFilter(requestsMissesIndices, INNER_LOOP_BATCH_COUNT, inputDeps);
    20.  
    21.         inputDeps = RaycastCommand.ScheduleBatch(commandsOut, resultsOut, 1, inputDeps);
    22.         results = resultsOut;
    23.         commands = commandsOut;
    24.         return inputDeps;
    25.     }
     
  3. LennartJohansen

    LennartJohansen

    Joined:
    Dec 1, 2014
    Posts:
    2,394
    This works if you know how many rays you are going to cast but not if the number of rays changes based on other jobs and you have your info in NativeLists with variable length.
     
    julian-moschuering likes this.
  4. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    In my current case the raycast count is dependent on a ComponentGroup using a change filter. Getting the count of this ComponentGroup requires the main thread to wait for any dependent writes on the filtered component which I would like to avoid.
    Alternatively to AsDeferredJobArray a kind of ScheduleBatchIndirect which receives the raycast count using a native container would work... although I would prefer AsDeferredJobArray as then I wouldn't need to preallocate a large enough buffer for all cases... maybe querying extra raycasts with maxHits=0 is nearly free ...?
     
  5. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Setting an entry to new RaycastCommand() will make that entry be ignored. My experience has been that a buffer big enough to handle more then you can do in a single frame is usually not enough memory to be an issue. If you haven't noticed raycast commands will be force completed by Unity now before fixed update if they are still running, so there is a practical limit here anyways.
     
  6. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    No, it's just never hitting anything. Getting 'ignored' is still slower than not being there and as they are processed in ParallelForBatches unused raycasts have an additional overhead.

    Quicktest with 100k raycasts: 'empty' commands (distance=0, maxHits=0, mask=0) cost around 8% of a 'valid' raycast with infinite ray length. (World with 10k static cube colliders)
     
  7. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    That is likely a bug then. I don't do enough raycasts where they are particularly expensive anyways, but Unity specifically said setting it to a new entry will make it be ignored.
     
  8. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Or they just kick them out really late, so maybe not a bug just not really optimized.
     
  9. julian-moschuering

    julian-moschuering

    Joined:
    Apr 15, 2014
    Posts:
    529
    They can not be ignored without looking at the data. It has to check each value.
    That is cheap but unnecessary.