├── .gitignore ├── BurstAction.cs ├── BurstFunction.cs ├── BurstFunctionTest.cs ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | \.vs/ 3 | -------------------------------------------------------------------------------- /BurstAction.cs: -------------------------------------------------------------------------------- 1 | using Unity.Burst; 2 | using Unity.Collections.LowLevel.Unsafe; 3 | using Unity.Jobs; 4 | using System; 5 | using System.Reflection; 6 | using System.Runtime.CompilerServices; 7 | using UnityEngine.Bindings; 8 | 9 | namespace Vella.Common 10 | { 11 | 12 | public interface IBurstRefAction : IBurstOperation 13 | { 14 | void Execute(ref T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); 15 | } 16 | 17 | public interface IBurstAction : IBurstOperation 18 | { 19 | void Execute(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); 20 | } 21 | 22 | public interface IBurstAction : IBurstOperation 23 | { 24 | void Execute(T1 arg1, T2 arg2, T3 arg3, T4 arg4); 25 | } 26 | 27 | public interface IBurstAction : IBurstOperation 28 | { 29 | void Execute(T1 arg1, T2 arg2, T3 arg3); 30 | } 31 | 32 | public interface IBurstAction : IBurstOperation 33 | { 34 | void Execute(T1 arg1, T2 arg2); 35 | } 36 | 37 | public interface IBurstAction : IBurstOperation 38 | { 39 | void Execute(T1 arg1); 40 | } 41 | 42 | public interface IBurstAction : IBurstOperation 43 | { 44 | void Execute(); 45 | } 46 | 47 | [BurstCompile] 48 | public struct BurstRefAction : IJob 49 | where TFunc : struct, IBurstRefAction 50 | where T1 : unmanaged 51 | where T2 : struct 52 | where T3 : struct 53 | where T4 : struct 54 | where T5 : struct 55 | { 56 | [NativeDisableUnsafePtrRestriction] 57 | public unsafe void* FunctionPtr; 58 | [NativeDisableUnsafePtrRestriction] 59 | public unsafe T1* Argument1Ptr; 60 | [NativeDisableUnsafePtrRestriction] 61 | public unsafe void* Argument2Ptr; 62 | [NativeDisableUnsafePtrRestriction] 63 | public unsafe void* Argument3Ptr; 64 | [NativeDisableUnsafePtrRestriction] 65 | public unsafe void* Argument4Ptr; 66 | [NativeDisableUnsafePtrRestriction] 67 | public unsafe void* Argument5Ptr; 68 | 69 | public unsafe void Execute() 70 | { 71 | UnsafeUtility.CopyPtrToStructure(FunctionPtr, out TFunc func); 72 | UnsafeUtility.CopyPtrToStructure(Argument2Ptr, out T2 arg2); 73 | UnsafeUtility.CopyPtrToStructure(Argument3Ptr, out T3 arg3); 74 | UnsafeUtility.CopyPtrToStructure(Argument4Ptr, out T4 arg4); 75 | UnsafeUtility.CopyPtrToStructure(Argument5Ptr, out T5 arg5); 76 | 77 | func.Execute(ref *Argument1Ptr, arg2, arg3, arg4, arg5); 78 | } 79 | 80 | public static unsafe void Run(TFunc func, ref T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) 81 | { 82 | new BurstRefAction 83 | { 84 | FunctionPtr = UnsafeUtility.AddressOf(ref func), 85 | Argument1Ptr = (T1*)UnsafeUtility.AddressOf(ref arg1), 86 | Argument2Ptr = UnsafeUtility.AddressOf(ref arg2), 87 | Argument3Ptr = UnsafeUtility.AddressOf(ref arg3), 88 | Argument4Ptr = UnsafeUtility.AddressOf(ref arg4), 89 | Argument5Ptr = UnsafeUtility.AddressOf(ref arg5), 90 | 91 | }.Run(); 92 | } 93 | } 94 | 95 | [BurstCompile] 96 | public struct BurstAction : IJob 97 | where TFunc : struct, IBurstAction 98 | where T1 : struct 99 | where T2 : struct 100 | where T3 : struct 101 | where T4 : struct 102 | where T5 : struct 103 | { 104 | [NativeDisableUnsafePtrRestriction] 105 | public unsafe void* FunctionPtr; 106 | [NativeDisableUnsafePtrRestriction] 107 | public unsafe void* Argument1Ptr; 108 | [NativeDisableUnsafePtrRestriction] 109 | public unsafe void* Argument2Ptr; 110 | [NativeDisableUnsafePtrRestriction] 111 | public unsafe void* Argument3Ptr; 112 | [NativeDisableUnsafePtrRestriction] 113 | public unsafe void* Argument4Ptr; 114 | [NativeDisableUnsafePtrRestriction] 115 | public unsafe void* Argument5Ptr; 116 | 117 | public unsafe void Execute() 118 | { 119 | UnsafeUtility.CopyPtrToStructure(FunctionPtr, out TFunc func); 120 | UnsafeUtility.CopyPtrToStructure(Argument1Ptr, out T1 arg1); 121 | UnsafeUtility.CopyPtrToStructure(Argument2Ptr, out T2 arg2); 122 | UnsafeUtility.CopyPtrToStructure(Argument3Ptr, out T3 arg3); 123 | UnsafeUtility.CopyPtrToStructure(Argument4Ptr, out T4 arg4); 124 | UnsafeUtility.CopyPtrToStructure(Argument5Ptr, out T5 arg5); 125 | func.Execute(arg1, arg2, arg3, arg4, arg5); 126 | } 127 | 128 | public static unsafe void Run(TFunc func, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) 129 | { 130 | new BurstAction 131 | { 132 | FunctionPtr = UnsafeUtility.AddressOf(ref func), 133 | Argument1Ptr = UnsafeUtility.AddressOf(ref arg1), 134 | Argument2Ptr = UnsafeUtility.AddressOf(ref arg2), 135 | Argument3Ptr = UnsafeUtility.AddressOf(ref arg3), 136 | Argument4Ptr = UnsafeUtility.AddressOf(ref arg4), 137 | Argument5Ptr = UnsafeUtility.AddressOf(ref arg5), 138 | 139 | }.Run(); 140 | } 141 | } 142 | 143 | [BurstCompile] 144 | public struct BurstAction : IJob 145 | where TFunc : struct, IBurstAction 146 | where T1 : struct 147 | where T2 : struct 148 | where T3 : struct 149 | where T4 : struct 150 | { 151 | [NativeDisableUnsafePtrRestriction] 152 | public unsafe void* FunctionPtr; 153 | [NativeDisableUnsafePtrRestriction] 154 | public unsafe void* Argument1Ptr; 155 | [NativeDisableUnsafePtrRestriction] 156 | public unsafe void* Argument2Ptr; 157 | [NativeDisableUnsafePtrRestriction] 158 | public unsafe void* Argument3Ptr; 159 | [NativeDisableUnsafePtrRestriction] 160 | public unsafe void* Argument4Ptr; 161 | 162 | public unsafe void Execute() 163 | { 164 | UnsafeUtility.CopyPtrToStructure(FunctionPtr, out TFunc func); 165 | UnsafeUtility.CopyPtrToStructure(Argument1Ptr, out T1 arg1); 166 | UnsafeUtility.CopyPtrToStructure(Argument2Ptr, out T2 arg2); 167 | UnsafeUtility.CopyPtrToStructure(Argument3Ptr, out T3 arg3); 168 | UnsafeUtility.CopyPtrToStructure(Argument4Ptr, out T4 arg4); 169 | func.Execute(arg1, arg2, arg3, arg4); 170 | } 171 | 172 | public static unsafe void Run(TFunc func, T1 arg1, T2 arg2, T3 arg3, T4 arg4) 173 | { 174 | new BurstAction 175 | { 176 | FunctionPtr = UnsafeUtility.AddressOf(ref func), 177 | Argument1Ptr = UnsafeUtility.AddressOf(ref arg1), 178 | Argument2Ptr = UnsafeUtility.AddressOf(ref arg2), 179 | Argument3Ptr = UnsafeUtility.AddressOf(ref arg3), 180 | Argument4Ptr = UnsafeUtility.AddressOf(ref arg4), 181 | 182 | }.Run(); 183 | } 184 | } 185 | 186 | [BurstCompile] 187 | public struct BurstAction : IJob 188 | where TFunc : struct, IBurstAction 189 | where T1 : struct 190 | where T2 : struct 191 | where T3 : struct 192 | { 193 | [NativeDisableUnsafePtrRestriction] 194 | public unsafe void* FunctionPtr; 195 | [NativeDisableUnsafePtrRestriction] 196 | public unsafe void* Argument1Ptr; 197 | [NativeDisableUnsafePtrRestriction] 198 | public unsafe void* Argument2Ptr; 199 | [NativeDisableUnsafePtrRestriction] 200 | public unsafe void* Argument3Ptr; 201 | 202 | public unsafe void Execute() 203 | { 204 | UnsafeUtility.CopyPtrToStructure(FunctionPtr, out TFunc func); 205 | UnsafeUtility.CopyPtrToStructure(Argument1Ptr, out T1 arg1); 206 | UnsafeUtility.CopyPtrToStructure(Argument2Ptr, out T2 arg2); 207 | UnsafeUtility.CopyPtrToStructure(Argument3Ptr, out T3 arg3); 208 | func.Execute(arg1, arg2, arg3); 209 | } 210 | 211 | public static unsafe void Run(TFunc func, T1 arg1, T2 arg2, T3 arg3) 212 | { 213 | new BurstAction 214 | { 215 | FunctionPtr = UnsafeUtility.AddressOf(ref func), 216 | Argument1Ptr = UnsafeUtility.AddressOf(ref arg1), 217 | Argument2Ptr = UnsafeUtility.AddressOf(ref arg2), 218 | Argument3Ptr = UnsafeUtility.AddressOf(ref arg3), 219 | 220 | }.Run(); 221 | } 222 | } 223 | 224 | [BurstCompile] 225 | public struct BurstAction : IJob 226 | where TFunc : struct, IBurstAction 227 | where T1 : struct 228 | where T2 : struct 229 | { 230 | [NativeDisableUnsafePtrRestriction] 231 | public unsafe void* FunctionPtr; 232 | [NativeDisableUnsafePtrRestriction] 233 | public unsafe void* Argument1Ptr; 234 | [NativeDisableUnsafePtrRestriction] 235 | public unsafe void* Argument2Ptr; 236 | [NativeDisableUnsafePtrRestriction] 237 | public unsafe void* Argument3Ptr; 238 | 239 | public unsafe void Execute() 240 | { 241 | UnsafeUtility.CopyPtrToStructure(FunctionPtr, out TFunc func); 242 | UnsafeUtility.CopyPtrToStructure(Argument1Ptr, out T1 arg1); 243 | UnsafeUtility.CopyPtrToStructure(Argument2Ptr, out T2 arg2); 244 | func.Execute(arg1, arg2); 245 | } 246 | 247 | public static unsafe void Run(TFunc func, T1 arg1, T2 arg2) 248 | { 249 | new BurstAction 250 | { 251 | FunctionPtr = UnsafeUtility.AddressOf(ref func), 252 | Argument1Ptr = UnsafeUtility.AddressOf(ref arg1), 253 | Argument2Ptr = UnsafeUtility.AddressOf(ref arg2), 254 | 255 | }.Run(); 256 | } 257 | } 258 | 259 | [BurstCompile] 260 | public struct BurstAction : IJob 261 | where TFunc : struct, IBurstAction 262 | where T1 : struct 263 | { 264 | [NativeDisableUnsafePtrRestriction] 265 | public unsafe void* FunctionPtr; 266 | [NativeDisableUnsafePtrRestriction] 267 | public unsafe void* Argument1Ptr; 268 | [NativeDisableUnsafePtrRestriction] 269 | public unsafe void* Argument2Ptr; 270 | [NativeDisableUnsafePtrRestriction] 271 | public unsafe void* Argument3Ptr; 272 | 273 | public unsafe void Execute() 274 | { 275 | UnsafeUtility.CopyPtrToStructure(FunctionPtr, out TFunc func); 276 | UnsafeUtility.CopyPtrToStructure(Argument1Ptr, out T1 arg1); 277 | func.Execute(arg1); 278 | } 279 | 280 | public static unsafe void Run(TFunc func, T1 arg1) 281 | { 282 | new BurstAction 283 | { 284 | FunctionPtr = UnsafeUtility.AddressOf(ref func), 285 | Argument1Ptr = UnsafeUtility.AddressOf(ref arg1), 286 | 287 | }.Run(); 288 | } 289 | } 290 | 291 | [BurstCompile] 292 | public struct BurstAction : IJob 293 | where TFunc : struct, IBurstAction 294 | { 295 | [NativeDisableUnsafePtrRestriction] 296 | public unsafe void* FunctionPtr; 297 | 298 | public unsafe void Execute() 299 | { 300 | UnsafeUtility.CopyPtrToStructure(FunctionPtr, out TFunc func); 301 | func.Execute(); 302 | } 303 | 304 | public static unsafe void Run(TFunc func) 305 | { 306 | new BurstAction 307 | { 308 | FunctionPtr = UnsafeUtility.AddressOf(ref func), 309 | 310 | }.Run(); 311 | } 312 | } 313 | } 314 | -------------------------------------------------------------------------------- /BurstFunction.cs: -------------------------------------------------------------------------------- 1 | using Unity.Burst; 2 | using Unity.Collections.LowLevel.Unsafe; 3 | using Unity.Jobs; 4 | 5 | namespace Vella.Common 6 | { 7 | public interface IBurstOperation 8 | { 9 | 10 | } 11 | 12 | public interface IBurstFunction : IBurstOperation 13 | { 14 | TResult Execute(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); 15 | } 16 | 17 | public interface IBurstFunction : IBurstOperation 18 | { 19 | TResult Execute(T1 arg1, T2 arg2, T3 arg3, T4 arg4); 20 | } 21 | 22 | public interface IBurstFunction : IBurstOperation 23 | { 24 | TResult Execute(T1 arg1, T2 arg2, T3 arg3); 25 | } 26 | 27 | public interface IBurstFunction : IBurstOperation 28 | { 29 | TResult Execute(T1 arg1, T2 arg2); 30 | } 31 | 32 | public interface IBurstFunction : IBurstOperation 33 | { 34 | TResult Execute(T1 arg1); 35 | } 36 | 37 | public interface IBurstFunction : IBurstOperation 38 | { 39 | TResult Execute(); 40 | } 41 | 42 | [BurstCompile] 43 | public struct BurstFunction : IJob 44 | where TFunc : struct, IBurstFunction 45 | where T1 : struct 46 | where T2 : struct 47 | where T3 : struct 48 | where T4 : struct 49 | where T5 : struct 50 | where TResult : struct 51 | { 52 | [NativeDisableUnsafePtrRestriction] 53 | public unsafe void* FunctionPtr; 54 | [NativeDisableUnsafePtrRestriction] 55 | public unsafe void* Argument1Ptr; 56 | [NativeDisableUnsafePtrRestriction] 57 | public unsafe void* Argument2Ptr; 58 | [NativeDisableUnsafePtrRestriction] 59 | public unsafe void* Argument3Ptr; 60 | [NativeDisableUnsafePtrRestriction] 61 | public unsafe void* Argument4Ptr; 62 | [NativeDisableUnsafePtrRestriction] 63 | public unsafe void* Argument5Ptr; 64 | [NativeDisableUnsafePtrRestriction] 65 | public unsafe void* ResultPtr; 66 | 67 | public unsafe void Execute() 68 | { 69 | UnsafeUtility.CopyPtrToStructure(ResultPtr, out TResult result); 70 | UnsafeUtility.CopyPtrToStructure(FunctionPtr, out TFunc func); 71 | UnsafeUtility.CopyPtrToStructure(Argument1Ptr, out T1 arg1); 72 | UnsafeUtility.CopyPtrToStructure(Argument2Ptr, out T2 arg2); 73 | UnsafeUtility.CopyPtrToStructure(Argument3Ptr, out T3 arg3); 74 | UnsafeUtility.CopyPtrToStructure(Argument4Ptr, out T4 arg4); 75 | UnsafeUtility.CopyPtrToStructure(Argument5Ptr, out T5 arg5); 76 | 77 | result = func.Execute(arg1, arg2, arg3, arg4, arg5); 78 | UnsafeUtility.CopyStructureToPtr(ref result, ResultPtr); 79 | } 80 | 81 | public static unsafe TResult Run(TFunc func, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) 82 | { 83 | TResult result = default; 84 | new BurstFunction 85 | { 86 | ResultPtr = UnsafeUtility.AddressOf(ref result), 87 | FunctionPtr = UnsafeUtility.AddressOf(ref func), 88 | Argument1Ptr = UnsafeUtility.AddressOf(ref arg1), 89 | Argument2Ptr = UnsafeUtility.AddressOf(ref arg2), 90 | Argument3Ptr = UnsafeUtility.AddressOf(ref arg3), 91 | Argument4Ptr = UnsafeUtility.AddressOf(ref arg4), 92 | Argument5Ptr = UnsafeUtility.AddressOf(ref arg5), 93 | 94 | }.Run(); 95 | return result; 96 | } 97 | } 98 | 99 | [BurstCompile] 100 | public struct BurstFunction : IJob 101 | where TFunc : struct, IBurstFunction 102 | where T1 : struct 103 | where T2 : struct 104 | where T3 : struct 105 | where T4 : struct 106 | where TResult : struct 107 | { 108 | [NativeDisableUnsafePtrRestriction] 109 | public unsafe void* FunctionPtr; 110 | [NativeDisableUnsafePtrRestriction] 111 | public unsafe void* Argument1Ptr; 112 | [NativeDisableUnsafePtrRestriction] 113 | public unsafe void* Argument2Ptr; 114 | [NativeDisableUnsafePtrRestriction] 115 | public unsafe void* Argument3Ptr; 116 | [NativeDisableUnsafePtrRestriction] 117 | public unsafe void* Argument4Ptr; 118 | [NativeDisableUnsafePtrRestriction] 119 | public unsafe void* ResultPtr; 120 | 121 | public unsafe void Execute() 122 | { 123 | UnsafeUtility.CopyPtrToStructure(ResultPtr, out TResult result); 124 | UnsafeUtility.CopyPtrToStructure(FunctionPtr, out TFunc func); 125 | UnsafeUtility.CopyPtrToStructure(Argument1Ptr, out T1 arg1); 126 | UnsafeUtility.CopyPtrToStructure(Argument2Ptr, out T2 arg2); 127 | UnsafeUtility.CopyPtrToStructure(Argument3Ptr, out T3 arg3); 128 | UnsafeUtility.CopyPtrToStructure(Argument4Ptr, out T4 arg4); 129 | 130 | result = func.Execute(arg1, arg2, arg3, arg4); 131 | UnsafeUtility.CopyStructureToPtr(ref result, ResultPtr); 132 | } 133 | 134 | public static unsafe TResult Run(TFunc func, T1 arg1, T2 arg2, T3 arg3, T4 arg4) 135 | { 136 | TResult result = default; 137 | new BurstFunction 138 | { 139 | ResultPtr = UnsafeUtility.AddressOf(ref result), 140 | FunctionPtr = UnsafeUtility.AddressOf(ref func), 141 | Argument1Ptr = UnsafeUtility.AddressOf(ref arg1), 142 | Argument2Ptr = UnsafeUtility.AddressOf(ref arg2), 143 | Argument3Ptr = UnsafeUtility.AddressOf(ref arg3), 144 | Argument4Ptr = UnsafeUtility.AddressOf(ref arg4), 145 | 146 | }.Run(); 147 | return result; 148 | } 149 | } 150 | 151 | [BurstCompile] 152 | public struct BurstFunction : IJob 153 | where TFunc : struct, IBurstFunction 154 | where T1 : struct 155 | where T2 : struct 156 | where T3 : struct 157 | where TResult : struct 158 | { 159 | [NativeDisableUnsafePtrRestriction] 160 | public unsafe void* FunctionPtr; 161 | [NativeDisableUnsafePtrRestriction] 162 | public unsafe void* Argument1Ptr; 163 | [NativeDisableUnsafePtrRestriction] 164 | public unsafe void* Argument2Ptr; 165 | [NativeDisableUnsafePtrRestriction] 166 | public unsafe void* Argument3Ptr; 167 | [NativeDisableUnsafePtrRestriction] 168 | public unsafe void* ResultPtr; 169 | 170 | public unsafe void Execute() 171 | { 172 | UnsafeUtility.CopyPtrToStructure(ResultPtr, out TResult result); 173 | UnsafeUtility.CopyPtrToStructure(FunctionPtr, out TFunc func); 174 | UnsafeUtility.CopyPtrToStructure(Argument1Ptr, out T1 arg1); 175 | UnsafeUtility.CopyPtrToStructure(Argument2Ptr, out T2 arg2); 176 | UnsafeUtility.CopyPtrToStructure(Argument3Ptr, out T3 arg3); 177 | 178 | result = func.Execute(arg1, arg2, arg3); 179 | UnsafeUtility.CopyStructureToPtr(ref result, ResultPtr); 180 | } 181 | 182 | public static unsafe TResult Run(TFunc func, T1 arg1, T2 arg2, T3 arg3) 183 | { 184 | TResult result = default; 185 | new BurstFunction 186 | { 187 | ResultPtr = UnsafeUtility.AddressOf(ref result), 188 | FunctionPtr = UnsafeUtility.AddressOf(ref func), 189 | Argument1Ptr = UnsafeUtility.AddressOf(ref arg1), 190 | Argument2Ptr = UnsafeUtility.AddressOf(ref arg2), 191 | Argument3Ptr = UnsafeUtility.AddressOf(ref arg3), 192 | 193 | }.Run(); 194 | return result; 195 | } 196 | } 197 | 198 | [BurstCompile] 199 | public struct BurstFunction : IJob 200 | where TFunc : struct, IBurstFunction 201 | where T1 : struct 202 | where T2 : struct 203 | where TResult : struct 204 | { 205 | [NativeDisableUnsafePtrRestriction] 206 | public unsafe void* FunctionPtr; 207 | [NativeDisableUnsafePtrRestriction] 208 | public unsafe void* Argument1Ptr; 209 | [NativeDisableUnsafePtrRestriction] 210 | public unsafe void* Argument2Ptr; 211 | [NativeDisableUnsafePtrRestriction] 212 | public unsafe void* ResultPtr; 213 | 214 | public unsafe void Execute() 215 | { 216 | UnsafeUtility.CopyPtrToStructure(ResultPtr, out TResult result); 217 | UnsafeUtility.CopyPtrToStructure(FunctionPtr, out TFunc func); 218 | UnsafeUtility.CopyPtrToStructure(Argument1Ptr, out T1 arg1); 219 | UnsafeUtility.CopyPtrToStructure(Argument2Ptr, out T2 arg2); 220 | 221 | result = func.Execute(arg1, arg2); 222 | UnsafeUtility.CopyStructureToPtr(ref result, ResultPtr); 223 | } 224 | 225 | public static unsafe TResult Run(TFunc func, T1 arg1, T2 arg2) 226 | { 227 | TResult result = default; 228 | new BurstFunction 229 | { 230 | ResultPtr = UnsafeUtility.AddressOf(ref result), 231 | FunctionPtr = UnsafeUtility.AddressOf(ref func), 232 | Argument1Ptr = UnsafeUtility.AddressOf(ref arg1), 233 | Argument2Ptr = UnsafeUtility.AddressOf(ref arg2), 234 | 235 | }.Run(); 236 | return result; 237 | } 238 | } 239 | 240 | [BurstCompile] 241 | public struct BurstFunction : IJob 242 | where TFunc : struct, IBurstFunction 243 | where T1 : struct 244 | where TResult : struct 245 | { 246 | [NativeDisableUnsafePtrRestriction] 247 | public unsafe void* FunctionPtr; 248 | [NativeDisableUnsafePtrRestriction] 249 | public unsafe void* Argument1Ptr; 250 | [NativeDisableUnsafePtrRestriction] 251 | public unsafe void* ResultPtr; 252 | 253 | public unsafe void Execute() 254 | { 255 | UnsafeUtility.CopyPtrToStructure(ResultPtr, out TResult result); 256 | UnsafeUtility.CopyPtrToStructure(FunctionPtr, out TFunc func); 257 | UnsafeUtility.CopyPtrToStructure(Argument1Ptr, out T1 arg1); 258 | 259 | result = func.Execute(arg1); 260 | UnsafeUtility.CopyStructureToPtr(ref result, ResultPtr); 261 | } 262 | 263 | public static unsafe TResult Run(TFunc func, T1 arg1) 264 | { 265 | TResult result = default; 266 | new BurstFunction 267 | { 268 | ResultPtr = UnsafeUtility.AddressOf(ref result), 269 | FunctionPtr = UnsafeUtility.AddressOf(ref func), 270 | Argument1Ptr = UnsafeUtility.AddressOf(ref arg1), 271 | 272 | }.Run(); 273 | return result; 274 | } 275 | } 276 | 277 | [BurstCompile] 278 | public struct BurstFunction : IJob 279 | where TFunc : struct, IBurstFunction 280 | where TResult : struct 281 | { 282 | [NativeDisableUnsafePtrRestriction] 283 | public unsafe void* FunctionPtr; 284 | [NativeDisableUnsafePtrRestriction] 285 | public unsafe void* ResultPtr; 286 | 287 | public unsafe void Execute() 288 | { 289 | UnsafeUtility.CopyPtrToStructure(ResultPtr, out TResult result); 290 | UnsafeUtility.CopyPtrToStructure(FunctionPtr, out TFunc func); 291 | 292 | result = func.Execute(); 293 | UnsafeUtility.CopyStructureToPtr(ref result, ResultPtr); 294 | } 295 | 296 | public static unsafe TResult Run(TFunc func) 297 | { 298 | TResult result = default; 299 | new BurstFunction 300 | { 301 | ResultPtr = UnsafeUtility.AddressOf(ref result), 302 | FunctionPtr = UnsafeUtility.AddressOf(ref func), 303 | 304 | }.Run(); 305 | return result; 306 | } 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /BurstFunctionTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using Assets.UnityXBurst.Helpers; 7 | using Unity.Burst; 8 | using Unity.Collections; 9 | using Unity.Collections.LowLevel.Unsafe; 10 | using Unity.Jobs; 11 | using UnityEngine; 12 | using Debug = UnityEngine.Debug; 13 | 14 | 15 | namespace Assets 16 | { 17 | public class BurstFunctionTest : MonoBehaviour 18 | { 19 | public unsafe void Start() 20 | { 21 | var timer = new Timer(); 22 | 23 | for (int i = 0; i < 1000; i++) 24 | { 25 | if (i == 20) timer.IsEnabled = true; 26 | 27 | using (var input1 = new NativeArray(100000, Allocator.TempJob)) 28 | using (var input2 = new NativeArray(100000, Allocator.TempJob)) 29 | { 30 | timer.Restart(); 31 | timer.Stop(); 32 | timer.Save("Timer No Work Baseline"); 33 | 34 | var sw1 = new Stopwatch(); 35 | sw1.Start(); 36 | sw1.Stop(); 37 | timer.Timings.Add(("StopWatch No Work Baseline", sw1.Elapsed)); 38 | 39 | // ----------------------------------- 40 | // Standard C# method. 41 | 42 | 43 | var instance = new MyFunctions.AddIntegersCSharp(); 44 | timer.Restart(); 45 | var result0 = instance.Execute(5, 7); 46 | timer.Stop(); 47 | timer.Save("AddIntegers(PureC#)"); 48 | 49 | // ----------------------------------- 50 | // Normal Burst Job construction. 51 | 52 | int intResult1 = 0; 53 | var addIntegersJobWithResult = new MyFunctions.AddIntegersJobWithResult 54 | { 55 | arg1 = 5, 56 | arg2 = 7, 57 | resultPtr = &intResult1 58 | }; 59 | timer.Restart(); 60 | addIntegersJobWithResult.Schedule().Complete(); 61 | timer.Stop(); 62 | timer.Save("AddIntegersJob(NonBurst): with result"); 63 | 64 | // ----------------------------------- 65 | // Normal Burst job without a return result; 66 | 67 | var addIntegersJob = new MyFunctions.AddIntegersJob 68 | { 69 | arg1 = 5, 70 | arg2 = 7, 71 | }; 72 | timer.Restart(); 73 | addIntegersJob.Schedule().Complete(); 74 | timer.Stop(); 75 | timer.Save("AddIntegersJob(NonBurst): no result"); 76 | 77 | // ----------------------------------- 78 | // Function in burst, maintains references, uses GetAddress/CopyPtrToStructure. 79 | 80 | timer.Restart(); 81 | var intResult3 = MyFunctions.AddIntegersFuncX2.Invoke(5, 7); 82 | timer.Stop(); 83 | timer.Save("AddIntegersFunc(Burst):"); 84 | 85 | // ----------------------------------- 86 | // Uses no jobs code, just pure c# performing the same logic. 87 | 88 | var instanceArr = new MyFunctions.ArrayTestCSharp(); 89 | timer.Restart(); 90 | instanceArr.Execute(input1, input2); 91 | timer.Stop(); 92 | timer.Save("ArrayTest(PureC#)"); 93 | 94 | // ----------------------------------- 95 | // Uses the Function Job 96 | 97 | NativeArray arrResult; 98 | timer.Restart(); 99 | arrResult = MyFunctions.ArrayTestFunc.Invoke(input1, input2); 100 | timer.Stop(); 101 | timer.Save("ArrayTestFunc(Burst)"); 102 | 103 | // ----------------------------------- 104 | // Uses a standard Job construction, same as Function version except it has no result. 105 | 106 | var compiledArr = new MyFunctions.ArrayTestJob 107 | { 108 | arg1 = input1, 109 | arg2 = input2, 110 | }; 111 | timer.Restart(); 112 | compiledArr.Schedule().Complete(); 113 | timer.Stop(); 114 | timer.Save("ArrayTestJob(Burst):ScheduleComplete"); 115 | 116 | // ----------------------------------- 117 | // Uses a standard Job construction fired with Run(); returns no result. 118 | 119 | compiledArr = new MyFunctions.ArrayTestJob 120 | { 121 | arg1 = input1, 122 | arg2 = input2, 123 | }; 124 | timer.Restart(); 125 | compiledArr.Run(); 126 | timer.Stop(); 127 | timer.Save("ArrayTestJob(Burst):Run"); 128 | 129 | } 130 | 131 | } 132 | 133 | timer.LogAverages(); 134 | 135 | } 136 | } 137 | 138 | public class Timer : IEnumerable<(string, TimeSpan)> 139 | { 140 | public Stopwatch Stopwatch = new Stopwatch(); 141 | 142 | public List<(string, TimeSpan)> Timings = new List<(string, TimeSpan)>(); 143 | 144 | public void Start() => Stopwatch.Start(); 145 | 146 | public void Restart() => Stopwatch.Restart(); 147 | 148 | public void Stop() => Stopwatch.Stop(); 149 | 150 | public TimeSpan Elapsed => Stopwatch.Elapsed; 151 | 152 | public void Save(string name) 153 | { 154 | if (IsEnabled) 155 | { 156 | Timings.Add((name, Stopwatch.Elapsed)); 157 | } 158 | } 159 | 160 | public void Save(string name, TimeSpan time) 161 | { 162 | if (IsEnabled) 163 | { 164 | Timings.Add((name, time)); 165 | } 166 | } 167 | 168 | public void LogAverages() 169 | { 170 | foreach (var group in Timings.GroupBy(t => t.Item1)) 171 | { 172 | Debug.Log($"{group.Key}: {group.Average(t => t.Item2.TotalMilliseconds):N8} ms"); 173 | } 174 | } 175 | 176 | public bool IsEnabled { get; set; } 177 | 178 | public IEnumerator<(string, TimeSpan)> GetEnumerator() => Timings.GetEnumerator(); 179 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 180 | } 181 | 182 | public class MyFunctions 183 | { 184 | public struct AddIntegersCSharp 185 | { 186 | public int Execute(int a, int b) 187 | { 188 | return a + b; 189 | } 190 | } 191 | 192 | [BurstCompile] 193 | public struct AddIntegersJob : IJob 194 | { 195 | public int arg1; 196 | public int arg2; 197 | 198 | public void Execute() 199 | { 200 | arg1 = arg1 + arg2; 201 | } 202 | } 203 | 204 | [BurstCompile] 205 | public struct AddIntegersJobWithResult : IJob 206 | { 207 | public int arg1; 208 | public int arg2; 209 | 210 | [NativeDisableUnsafePtrRestriction] 211 | public unsafe int* resultPtr; 212 | 213 | public unsafe void Execute() 214 | { 215 | ref var result = ref *resultPtr; 216 | result = arg1 + arg2; 217 | } 218 | } 219 | 220 | [BurstCompile] 221 | public struct ArrayTestJob : IJob 222 | { 223 | public NativeArray arg1; 224 | public NativeArray arg2; 225 | 226 | public void Execute() 227 | { 228 | for (int i = 0; i < 100000; i++) 229 | { 230 | arg1[i] = i; 231 | } 232 | for (int i = 0; i < 100000; i++) 233 | { 234 | arg2[i] = arg1[i]; 235 | } 236 | } 237 | } 238 | 239 | [BurstCompile] 240 | public struct AddIntegersFuncX2 : IBurstFunction 241 | { 242 | public int Execute(int a, int b) 243 | { 244 | return a + b; 245 | } 246 | 247 | public static int Invoke(int a, int b) 248 | { 249 | return BurstFunction.Run(Instance, a, b); 250 | } 251 | 252 | private static readonly AddIntegersFuncX2 Instance = new AddIntegersFuncX2(); 253 | } 254 | 255 | 256 | [BurstCompile] 257 | public struct ArrayTestFunc : IBurstFunction, NativeArray, NativeArray> 258 | { 259 | public NativeArray Execute(NativeArray arg1, NativeArray arg2) 260 | { 261 | for (int i = 0; i < 100000; i++) 262 | { 263 | arg1[i] = i; 264 | } 265 | for (int i = 0; i < 100000; i++) 266 | { 267 | arg2[i] = arg1[i]; 268 | } 269 | return arg2; 270 | } 271 | 272 | public static NativeArray Invoke(NativeArray a, NativeArray b) 273 | { 274 | return BurstFunction, NativeArray, NativeArray>.Run(Instance, a, b); 275 | } 276 | 277 | public static ArrayTestFunc Instance { get; } = new ArrayTestFunc(); 278 | } 279 | 280 | public struct ArrayTestCSharp 281 | { 282 | public NativeArray Execute(NativeArray arg1, NativeArray arg2) 283 | { 284 | for (int i = 0; i < 100000; i++) 285 | { 286 | arg1[i] = i; 287 | } 288 | for (int i = 0; i < 100000; i++) 289 | { 290 | arg2[i] = arg1[i]; 291 | } 292 | return arg2; 293 | } 294 | } 295 | } 296 | 297 | 298 | 299 | } 300 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UnityBurstFunctions 2 | Pattern and helpers for writing Unity Burst jobs as generic Functions/Actions. 3 | 4 | Write burst compiled jobs with easy arguments and return values. 5 | 6 | [BurstCompile] 7 | public struct AddIntegersFuncX2 : IBurstFunction 8 | { 9 | public int Execute(int a, int b) 10 | { 11 | return a + b; 12 | } 13 | 14 | public static int Invoke(int a, int b) 15 | { 16 | return BurstFunction.Run(Instance, a, b); 17 | } 18 | 19 | private static readonly AddIntegersFuncX2 Instance = new AddIntegersFuncX2(); 20 | } 21 | 22 | then call it like a normal function. 23 | 24 | var intResult3 = MyFunctions.AddIntegersFuncX2.Invoke(5, 7); 25 | 26 | #### View as normal in the Burst Inspector 27 | 28 | 29 | 30 | #### Still reasonably fast. 31 | 32 | 33 | 34 | #### Pass complicated arguments 35 | 36 | [BurstCompile] 37 | public struct ArrayTestFunc : IBurstFunction, NativeArray, NativeArray> 38 | { 39 | public NativeArray Execute(NativeArray arg1, NativeArray arg2) 40 | { 41 | for (int i = 0; i < 100000; i++) 42 | { 43 | arg1[i] = i; 44 | } 45 | for (int i = 0; i < 100000; i++) 46 | { 47 | arg2[i] = arg1[i]; 48 | } 49 | return arg2; 50 | } 51 | 52 | public static NativeArray Invoke(NativeArray a, NativeArray b) 53 | { 54 | return BurstFunction, NativeArray, NativeArray>.Run(Instance, a, b); 55 | } 56 | 57 | public static ArrayTestFunc Instance { get; } = new ArrayTestFunc(); 58 | } 59 | 60 | 61 | #### Pass by reference ('unmanaged' types only) 62 | 63 | Interface: 64 | 65 | public interface IBurstRefAction : IBurstOperation 66 | { 67 | void Execute(ref T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); 68 | } 69 | 70 | Implementation: 71 | 72 | [BurstCompile] 73 | public struct TryGetContact : IBurstRefAction 74 | { 75 | public void Execute(ref NativeManifold manifold, RigidTransform t1, NativeHull hull1, RigidTransform t2, NativeHull hull2) 76 | { 77 | HullIntersection.NativeHullHullContact(ref manifold, t1, hull1, t2, hull2); 78 | } 79 | 80 | public static bool Invoke(out NativeManifold result, RigidTransform t1, NativeHull hull1, RigidTransform t2, NativeHull hull2) 81 | { 82 | // Can only allocate as 'temp' within Burst Jobs 83 | result = new NativeManifold(Allocator.Persistent); 84 | 85 | BurstRefAction.Run(Instance, ref result, t1, hull1, t2, hull2); 86 | return result.Length > 0; 87 | } 88 | 89 | public static TryGetContact Instance { get; } = new TryGetContact(); 90 | } 91 | 92 | Calling Example: 93 | 94 | var burstResult = HullOperations.TryGetContact.Invoke(out NativeManifold manifold, t1, hull1, t2, hull2); --------------------------------------------------------------------------------