Search Unity

Callbacks with Burst?

Discussion in 'Entity Component System' started by LaphicetCrowe, Apr 8, 2021.

  1. LaphicetCrowe

    LaphicetCrowe

    Joined:
    Sep 30, 2020
    Posts:
    17
    When working with plain C, it's often the case that when making structs that might have slightly varying behaviors, to use function pointers. (ie. libpng, glib) and that's pretty much low (or mid?) level interfaces/polymorphism.

    Since C# interfaces are reference types and thus not compatible with Burst, I have noticed Burst's FunctionPointer struct. I'd like to think this might fill that hole, but I think I recall hearing not to use it unless I really need to because of some memory shenanigans. I don't know any other way to do component-based callbacks, if FunctionPointer is what I think it is.
     
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,264
    There's two issues with function pointers. The first is that arguments and return types cannot contain AtomicSafetyHandle or DisposeSentinel, which you'll find inside native containers. The second is that there is a performance overhead for function calls which may or may not be negligible for your use case.

    Fields specified by an interface are references, but interfaces alone don't make things incompatible with Burst. Burst is actually pretty good with generics as long as something knows the concrete type. Generics are generally a lot cleaner and more organized than function pointers and in some cases offer better performance too.

    It would be useful to understand your use cases before continuing this discussion.
     
  3. vildauget

    vildauget

    Joined:
    Mar 10, 2014
    Posts:
    121
    I use function pointers to choose among different noise functions, successfully. As pointed out here and in docs it's important to minimize the number of calls to it because of the overhead.

    Code (CSharp):
    1. [BurstCompile(CompileSynchronously = true)]
    2.     public class NoiseFunctionsBatch
    3.     {
    4.         public unsafe delegate void Delegate(int count, float2* p, float* output, int offset=0);
    5.  
    6.         [BurstCompile(CompileSynchronously = true)] public static unsafe void Cnoise(int count, [NoAlias]float2* p, [NoAlias]float* output, int offset=0)
    7.         { for (int i = 0; i < count; i++) output[i+offset] =noise.cnoise(p[i]); }
    8.        
    9.         [BurstCompile(CompileSynchronously = true)] public static unsafe void Cellular(int count, [NoAlias]float2* p, [NoAlias]float* output, int offset=0)
    10.         { for (int i = 0; i < count; i++) output[i+offset] = noise.cellular(p[i]).x * 2 - 1; }
    11.