### Compile Job with Burst Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/QuickStart.md Demonstrates how to compile a Unity Job using the Burst compiler by applying the [BurstCompile] attribute. The example shows synchronous compilation for immediate execution and includes setup for input/output NativeArrays. ```csharp using Unity.Burst; using Unity.Collections; using Unity.Jobs; using UnityEngine; public class MyBurst2Behavior : MonoBehaviour { void Start() { var input = new NativeArray(10, Allocator.Persistent); var output = new NativeArray(1, Allocator.Persistent); for (int i = 0; i < input.Length; i++) input[i] = 1.0f * i; var job = new MyJob { Input = input, Output = output }; job.Schedule().Complete(); Debug.Log("The result of the sum is: " + output[0]); input.Dispose(); output.Dispose(); } // Using BurstCompile to compile a Job with Burst // Set CompileSynchronously to true to make sure that the method will not be compiled asynchronously // but on the first schedule [BurstCompile(CompileSynchronously = true)] private struct MyJob : IJob { [ReadOnly] public NativeArray Input; [WriteOnly] public NativeArray Output; public void Execute() { float result = 0.0f; for (int i = 0; i < Input.Length; i++) { result += Input[i]; } Output[0] = result; } } } ``` -------------------------------- ### Burst Intrinsics - Unity.Burst.Intrinsics Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/TableOfContents.md Provides examples of using the `Unity.Burst.Intrinsics` namespace for accessing low-level SIMD (Single Instruction, Multiple Data) operations and processor-specific instructions. ```C# using Unity.Burst; using Unity.Burst.Intrinsics; using Unity.Mathematics; public struct VectorAddJob : IJob { [ReadOnly] public NativeArray inputA; [ReadOnly] public NativeArray inputB; [WriteOnly] public NativeArray output; public void Execute() { // Using Burst intrinsic for vector addition (SSE/AVX) for (int i = 0; i < inputA.Length; i++) { output[i] = Sse.add_ps(inputA[i], inputB[i]); } } } ``` -------------------------------- ### Burst Command-Line Options Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/QuickStart.md Control Burst compilation behavior using command-line arguments when launching the Unity Editor. These options allow disabling Burst or forcing synchronous compilation. ```bash --burst-disable-compilation --burst-force-sync-compilation ``` -------------------------------- ### Burst Compile Attribute Example Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines.md Provides an example of how to use the `[BurstCompile]` attribute in C# to configure compiler options. This snippet shows setting `FloatPrecision` to `Med` and `FloatMode` to `Fast` for optimizing floating-point calculations. ```csharp [BurstCompile(FloatPrecision.Med, FloatMode.Fast)] ``` -------------------------------- ### C# Loop Vectorization Example Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines.md Demonstrates a C# code snippet where Burst can automatically vectorize a scalar loop for performance improvement. The example shows a simple addition operation within a loop that Burst can optimize by processing multiple values simultaneously. ```csharp [MethodImpl(MethodImplOptions.NoInlining)] private static unsafe void Bar([NoAlias] int* a, [NoAlias] int* b, int count) { for (var i = 0; i < count; i++) { a[i] += b[i]; } } public static unsafe void Foo(int count) { var a = stackalloc int[count]; var b = stackalloc int[count]; Bar(a, b, count); } ``` -------------------------------- ### String Padding and Formatting Specifiers in Burst Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/CSharpLanguageSupport_Lang.md Provides examples of using padding and standard numeric format specifiers (like hexadecimal and decimal with leading zeros) with string interpolation in Burst. ```csharp int value = 256; // Padding left: "This value ` 256` Debug.Log($"This value `{value,5}`"); // Padding right: "This value `256 ` Debug.Log($"This value `{value,-5}`"); // Hexadecimal uppercase: "This value `00FF` Debug.Log($"This value `{value:X4}`"); // Hexadecimal lowercase: "This value `00ff` Debug.Log($"This value `{value:x4}`"); // Decimal with leading-zero: "This value `0256` Debug.Log($"This value `{value:D4}`"); ``` -------------------------------- ### Assembly: Burst Compiler LUT Optimization Example Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines.md This assembly code snippet illustrates a Burst compiler optimization where a `memset` call is removed. The developer assures the compiler that the operation is safe, allowing for potential performance gains. This is a power-user feature. ```assembly .LBB0_6: mov dword ptr [rcx + 4*r10], r10d inc r10 cmp r8, r10 jne .LBB0_6 .LBB0_7: sub rsp, 32 movabs rax, offset "DoSomethingWithLUT" call rax nop mov rsp, rbp pop rbp ret ``` -------------------------------- ### C# Function Cloning Example Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines-Aliasing.md Illustrates function cloning in Unity Burst for better aliasing deduction. The example shows a C# function `Bar` with reference parameters and a calling function `Foo`, demonstrating how Burst optimizes the call by cloning `Bar` to understand parameter aliasing. ```C# using System.Runtime.CompilerServices; [MethodImpl(MethodImplOptions.NoInlining)] int Bar(ref int a, ref int b) { a = 42; b = 13; return a; } int Foo() { var a = 53; var b = -2; return Bar(ref a, ref b); } ``` -------------------------------- ### Burst Compilation Failure with Generic Function Pointers Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines.md Shows an example of a generic delegate and the attempt to compile it into a Burst function pointer. This operation fails due to limitations in the .NET runtime's ability to interoperate with such generic delegates. ```csharp public delegate void MyGenericDelegate(ref TData data) where TData: struct; var myGenericDelegate = new MyGenericDelegate(MyIntDelegateImpl); // Will fail to compile this function pointer. var myGenericFunctionPointer = BurstCompiler.CompileFunctionPointer>(myGenericDelegate); ``` -------------------------------- ### Example Job Struct with Aliasing Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines-Aliasing.md Demonstrates a Unity Job struct with NativeArray and NativeSlice members, including a member with [NativeDisableContainerSafetyRestriction] to illustrate aliasing rules. ```csharp using Unity.Burst; using Unity.Collections; using Unity.Jobs; [BurstCompile] private struct MyJob : IJob { public NativeArray a; public NativeArray b; public NativeSlice c; [NativeDisableContainerSafetyRestriction] public NativeArray d; public void Execute() { /* ... */ } } ``` -------------------------------- ### C# Loop with Branch Breaking Vectorization Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines.md Illustrates a C# code snippet where the introduction of a conditional branch within a loop prevents Burst from vectorizing it. This example highlights the fragility of auto-vectorization and the potential performance degradation. ```csharp [MethodImpl(MethodImplOptions.NoInlining)] private static unsafe void Bar([NoAlias] int* a, [NoAlias] int* b, int count) { for (var i = 0; i < count; i++) { if (a[i] > b[i]) { break; } a[i] += b[i]; } } ``` -------------------------------- ### C# Burst Constant IsConstantExpression Custom Pow Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines.md Provides an example of using IsConstantExpression to implement a custom power function in C# with Burst, optimizing for specific constant exponents like 2. ```C# using static Unity.Burst.CompilerServices.Constant; public static float MyAwesomePow(float f, int i) { if (IsConstantExpression(i) && (2 == i)) { return f * f; } else { return math.pow(f, (float)i); } } ``` -------------------------------- ### Using Vector Types and Intrinsics for SIMD Operations Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/CSharpLanguageSupport_BurstIntrinsics.md Illustrates the usage of Burst's vector types (`v128`, `v256`) and intrinsic functions for performing SIMD operations. This example demonstrates loading data into vectors, performing a comparison, generating a mask, shuffling elements, and storing the result, along with updating an index based on the population count. ```C# v128 a = Input.ReinterpretLoad(i); v128 mask = cmplt_ps(a, Limit); int m = movemask_ps(a); v128 packed = shuffle_epi8(a, Lut[m]); Output.ReinterpretStore(outputIndex, packed); outputIndex += popcnt_u32((uint)m); ``` -------------------------------- ### CircularList Struct C# Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines-Aliasing.md An example of a struct (CircularList) where a pointer to the struct itself is accessible within the struct, making the [NoAlias] assumption invalid. ```C# unsafe struct CircularList { public CircularList* next; public CircularList() { // The 'empty' list just points to itself. next = this; } } ``` -------------------------------- ### BurstDiscard Attribute Example Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/AdvancedUsages.md Demonstrates how to use the [BurstDiscard] attribute to prevent a method from being compiled by Burst. This is useful when you need to use managed objects or specific C# features within a Burst-compiled job that are not supported by Burst. ```csharp using Unity.Burst; using Unity.Jobs; using UnityEngine; public struct MyJob : IJob { public void Execute() { // Only executed when running from a full .NET runtime // this method call will be discard when compiling this job with // [BurstCompile] attribute MethodToDiscard(5); } [BurstDiscard] private static void MethodToDiscard(int arg) { Debug.Log($"This is a test: {arg}"); } } ``` -------------------------------- ### C# Bump Allocator with NoAlias Attribute Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines-Aliasing.md Demonstrates a C# bump allocator function that returns a unique pointer, utilizing the [return: NoAlias] attribute to inform the Burst compiler about the unique nature of the returned pointer for optimization. The example includes the function definition, usage within another function, and the resulting assembly code. ```C# using System.Runtime.CompilerServices; // Only ever returns a unique address into the stackalloc'ed memory. // We've made this no-inline as the compiler will always try and inline // small functions like these, which would defeat the purpose of this // example! [MethodImpl(MethodImplOptions.NoInlining)] [return: NoAlias] unsafe int* BumpAlloc(int* alloca) { int location = alloca[0]++; return alloca + location; } unsafe int Func() { int* alloca = stackalloc int[128]; // Store our size at the start of the alloca. alloca[0] = 1; int* ptr1 = BumpAlloc(alloca); int* ptr2 = BumpAlloc(alloca); *ptr1 = 42; *ptr2 = 13; return *ptr1; } ``` -------------------------------- ### C# Burst Job for Data Copying Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines-Aliasing.md A Unity Burst job that copies data from an input NativeArray to an output NativeArray. This serves as a base example to demonstrate memory aliasing effects. It requires the Burst package and Unity's Job System. ```C# using Unity.Burst; using Unity.Jobs; using Unity.Collections; [BurstCompile] private struct CopyJob : IJob { [ReadOnly] public NativeArray Input; [WriteOnly] public NativeArray Output; public void Execute() { for (int i = 0; i < Input.Length; i++) { Output[i] = Input[i]; } } } ``` -------------------------------- ### C# Function Without [NoAlias] Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines-Aliasing.md Illustrates a C# function where two reference parameters might alias, causing the compiler to reload a value due to uncertainty. This example shows the generated assembly. ```csharp int Foo(ref int a, ref int b) { b = 13; a = 42; return b; } ``` ```assembly mov dword ptr [rdx], 13 mov dword ptr [rcx], 42 mov eax, dword ptr [rdx] ret ``` -------------------------------- ### x64 AVX2 Vectorized Copy Loop Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines-Aliasing.md Example of x64 assembly code generated by Unity Burst for a vectorized copy loop using AVX2 instructions. This code efficiently copies data in batches, demonstrating the performance benefits of non-aliased memory awareness. It targets the AVX2 instruction set. ```Assembly .LBB0_4: vmovups ymm0, ymmword ptr [rcx - 96] vmovups ymm1, ymmword ptr [rcx - 64] vmovups ymm2, ymmword ptr [rcx - 32] vmovups ymm3, ymmword ptr [rcx] vmovups ymmword ptr [rdx - 96], ymm0 vmovups ymmword ptr [rdx - 64], ymm1 vmovups ymmword ptr [rdx - 32], ymm2 vmovups ymmword ptr [rdx], ymm3 sub rdx, -128 sub rcx, -128 add rsi, -32 jne .LBB0_4 test r10d, r10d je .LBB0_8 ``` -------------------------------- ### System.Threading.Interlocked Atomic Operation Example Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/CSharpLanguageSupport_Intrinsics.md Demonstrates the correct and incorrect usage of Interlocked methods with naturally aligned and unaligned memory locations within a struct. It highlights potential undefined behavior when accessing unaligned fields atomically. ```C# using System.Runtime.InteropServices; [StructLayout(LayoutKind.Explicit)] struct Foo { [FieldOffset(0)] public long a; [FieldOffset(5)] public long b; public long AtomicReadAndAdd() { return Interlocked.Read(ref a) + Interlocked.Read(ref b); } } ``` -------------------------------- ### Handle Burst Warning BC1371: Discarded Method Arguments Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/Warnings.md This example illustrates Burst compiler warning BC1371, which occurs when a method argument is passed to a `[BurstDiscard]` method and the argument itself is optimized away. It shows how to prevent this by ensuring the variable has multiple uses or by ignoring the warning. ```csharp using Unity.Burst; public class BurstDiscardExample { [BurstDiscard] static void DoSomeManagedStuff(int x) { // ... only run when Burst compilation is disabled } // A function that computes some result which we need to pass to managed code int BurstCompiledCode(int x, int y) { return y + 2 * x; } [BurstCompile] void BurstMethod() { var myValue = BurstCompiledCode(1, 3); DoSomeManagedStuff(myValue); } // Workaround: Ensure the variable has multiple uses void IsUsed(ref int x) { // Dummy function to prevent removal } [BurstCompile] void BurstMethodWithWorkaround() { var myValue = BurstCompiledCode(1, 3); DoSomeManagedStuff(myValue); IsUsed(ref myValue); } // Alternative: Ignore the warning [IgnoreWarning(1371)] [BurstCompile] void BurstMethodWithIgnore() { var myValue = BurstCompiledCode(1, 3); DoSomeManagedStuff(myValue); } } ``` -------------------------------- ### Suppress Burst Warning BC1370 with IgnoreWarningAttribute Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/Warnings.md This example demonstrates how to use the `IgnoreWarningAttribute` to suppress Burst compiler warning BC1370 for a specific function. This is useful when intentionally causing an abort in Burst, though generally discouraged. ```csharp using Unity.Burst; using System; public class BurstWarnings { [IgnoreWarning(1370)] int DoSomethingMaybe(int x) { if (x < 0) throw new Exception("Dang - sorry I crashed your game!"); return x * x; } } ``` -------------------------------- ### x64 Scalar Copy Loop (Aliasing Aware Disabled) Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines-Aliasing.md Example of x64 assembly code generated when Burst's aliasing awareness is disabled, resulting in a scalar loop. This code processes elements one by one, significantly impacting performance compared to the vectorized version. It highlights the negative consequences of the compiler not being aware of memory aliasing. ```Assembly .LBB0_2: mov r8, qword ptr [rcx] mov rdx, qword ptr [rcx + 16] cdqe mov edx, dword ptr [rdx + 4*rax] mov dword ptr [r8 + 4*rax], edx inc eax cmp eax, dword ptr [rcx + 8] jl .LBB0_2 ``` -------------------------------- ### Assembly for Method With SkipLocalsInit Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines.md Presents the X86 assembly generated for the C# method after applying the `[SkipLocalsInit]` attribute. The key difference is the absence of the explicit zero-initialization code (like `burst.memset.inline.X64_SSE4.i32@@32`), resulting in more efficient assembly. ```C push rbp .seh_pushreg rbp mov rbp, rsp .seh_setframe rbp, 0 .seh_endprologue mov edx, ecx lea eax, [4*rdx] add rax, 15 and rax, -16 movabs r11, offset __chkstk call r11 sub rsp, rax mov rcx, rsp test edx, edx jle .LBB0_7 mov r8d, edx cmp edx, 8 jae .LBB0_3 xor r10d, r10d jmp .LBB0_6 .LBB0_3: mov r10d, r8d and r10d, -8 movabs rax, offset __xmm@00000003000000020000000100000000 movdqa xmm0, xmmword ptr [rax] mov rax, rcx add rax, 16 movabs rdx, offset __xmm@00000004000000040000000400000004 movdqa xmm1, xmmword ptr [rdx] movabs rdx, offset __xmm@00000008000000080000000800000008 movdqa xmm2, xmmword ptr [rdx] mov r9, r10 .p2align 4, 0x90 .LBB0_4: movdqa xmm3, xmm0 paddd xmm3, xmm1 movdqu xmmword ptr [rax - 16], xmm0 movdqu xmmword ptr [rax], xmm3 paddd xmm0, xmm2 add rax, 32 add r9, -8 jne .LBB0_4 cmp r10, r8 ``` -------------------------------- ### Schedule Resolved Generic Jobs Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines.md Shows how to schedule instances of generic Jobs with fully resolved type arguments. This approach allows the Burst compiler to detect and compile these specific Job instantiations for standalone player builds. ```csharp // Direct Generic Job var myJob = new MyGenericJob(); myJob.Schedule(); // Nested Generic Job var myJobSystem = new MyGenericSystem(); myJobSystem.Run(); ``` -------------------------------- ### Burst Compilation Target Requirements Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/StandalonePlayerSupport.md This section details the requirements for Burst compilation across different host and target platforms. It specifies the supported CPU architectures and the necessary external toolchains, such as Visual Studio, Android NDK, Xcode, and specific SDKs. This information is crucial for setting up the development environment correctly. ```text Host Editor Platform | Target Player Platform | Supported CPU Architectures | External Toolchain Requirements -------------------- | ------------------------ | --------------------------- | ---------------------------- Windows | Windows | x86 (SSE2, SSE4), x64 (SSE2, SSE4) | Visual Studio and C++ Build Tools, Windows 10 SDK Windows | Universal Windows Platform | x86 (SSE2, SSE4), x64 (SSE2, SSE4), ARM32 Thumb2/Neon32, ARMv8 AARCH64 | Visual Studio 2017, Universal Windows Platform Development Workflow, C++ Universal Platform Tools Windows | Android | x86 SSE2, ARM32 Thumb2/Neon32, ARMv8 AARCH64 | Android NDK 13 or higher (Unity's or ANDROID_NDK_ROOT) Windows | Magic Leap | ARMv8 AARCH64 | Lumin SDK Windows | Xbox One | x64 SSE4 | Visual Studio 2015 or 2017, Microsoft XDK Windows | PS4 | x64 SSE4 | Minimum PS4 SDK version 5.0.0 Windows | Nintendo Switch | ARMv8 AARCH64 | Minimum Nintendo Switch NDK 8.2.0, Unity Editor 2019.3+ macOS | macOS | x86 (SSE2, SSE4), x64 (SSE2, SSE4) | Xcode with command line tools macOS | iOS | ARM32 Thumb2/Neon32, ARMv8 AARCH64 | Xcode with command line tools, Unity 2018.3.6f1+ or 2019.1.0b4+ macOS | Android | x86 SSE2, ARM32 Thumb2/Neon32, ARMv8 AARCH64 | Android NDK 13 or higher (Unity's or ANDROID_NDK_ROOT) macOS | Magic Leap | ARMv8 AARCH64 | Lumin SDK Linux | Linux | x86 (SSE2, SSE4), x64 (SSE2, SSE4) | Clang or Gcc tool chains. ``` -------------------------------- ### C# Burst Hint Assume Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines.md Shows how to use Unity.Burst.CompilerServices.Hint.Assume to assert that a boolean condition is always true, enabling aggressive optimizations by the Burst compiler. ```C# Unity.Burst.CompilerServices.Hint.Assume(b); if (b) { // The compiler has been told that b is always true, so this branch will always be taken. } else { // Any code in here will be removed from the program because b is always true! } ``` -------------------------------- ### Importing Intel and Arm SIMD Intrinsics in C# Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/CSharpLanguageSupport_BurstIntrinsics.md Demonstrates how to statically import various Intel SIMD intrinsics (SSE, AVX, etc.) and Arm Neon intrinsics using the `Unity.Burst.Intrinsics` namespace. This allows direct access to processor-specific instructions within Burst-compiled code. ```C# using static Unity.Burst.Intrinsics.X86; using static Unity.Burst.Intrinsics.X86.Sse; using static Unity.Burst.Intrinsics.X86.Sse2; using static Unity.Burst.Intrinsics.X86.Sse3; using static Unity.Burst.Intrinsics.X86.Ssse3; using static Unity.Burst.Intrinsics.X86.Sse4_1; using static Unity.Burst.Intrinsics.X86.Sse4_2; using static Unity.Burst.Intrinsics.X86.Popcnt; using static Unity.Burst.Intrinsics.X86.Avx; using static Unity.Burst.Intrinsics.X86.Avx2; using static Unity.Burst.Intrinsics.X86.Fma; using static Unity.Burst.Intrinsics.X86.F16C; using static Unity.Burst.Intrinsics.X86.Bmi1; using static Unity.Burst.Intrinsics.X86.Bmi2; using static Unity.Burst.Intrinsics.Arm.Neon; ``` -------------------------------- ### Compile a Job with Burst Compiler Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/TableOfContents.md Demonstrates how to compile a C# job using the Burst compiler in Unity. This involves applying the [BurstCompile] attribute to a job struct. ```C# using Unity.Jobs; using Unity.Burst; public struct MyJob : IJob { public void Execute() { // Job logic here } } // To compile: // var jobHandle = new MyJob().Schedule(); ``` -------------------------------- ### x64 AVX2 Assembly for Vectorized Loop Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines.md Presents the x64 assembly code generated by Burst using AVX2 instructions for the vectorized loop. This assembly illustrates how the loop is unrolled and vectorized to perform multiple integer additions per iteration, significantly boosting performance. ```assembly .LBB1_4: vmovdqu ymm0, ymmword ptr [rdx + 4*rax] vmovdqu ymm1, ymmword ptr [rdx + 4*rax + 32] vmovdqu ymm2, ymmword ptr [rdx + 4*rax + 64] vmovdqu ymm3, ymmword ptr [rdx + 4*rax + 96] vpaddd ymm0, ymm0, ymmword ptr [rcx + 4*rax] vpaddd ymm1, ymm1, ymmword ptr [rcx + 4*rax + 32] vpaddd ymm2, ymm2, ymmword ptr [rcx + 4*rax + 64] vpaddd ymm3, ymm3, ymmword ptr [rcx + 4*rax + 96] vmovdqu ymmword ptr [rcx + 4*rax], ymm0 vmovdqu ymmword ptr [rcx + 4*rax + 32], ymm1 vmovdqu ymmword ptr [rcx + 4*rax + 64], ymm2 vmovdqu ymmword ptr [rcx + 4*rax + 96], ymm3 add rax, 32 cmp r8, rax jne .LBB1_4 ``` -------------------------------- ### Logging with String Literal in Burst Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/CSharpLanguageSupport_Lang.md Demonstrates how to log a simple string literal using Debug.Log within a Burst-compatible context. This is a basic usage scenario for string output. ```csharp Debug.Log("This a string literal"); ``` -------------------------------- ### C# Method With SkipLocalsInit Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines.md Illustrates the same C# method but with the `[SkipLocalsInit]` attribute applied. This attribute informs the Burst compiler that the stack-allocated data does not need to be zero-initialized, potentially leading to performance gains. ```C# using Unity.Burst.CompilerServices; static unsafe int DoSomethingWithLUT(int* data); [SkipLocalsInit] static unsafe int DoSomething(int size) { int* data = stackalloc int[size]; // Initialize every field of data to be an incrementing set of values. for (int i = 0; i < size; { data[i] = i; } // Use the data elsewhere. return DoSomethingWithLUT(data); } ``` -------------------------------- ### Define Mod Interface (C#) Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/ModdingSupport.md Defines a common interface 'PluginModule' that all mods must implement. This interface includes 'Startup' and 'Update' methods, each taking a GameObject as input, allowing mods to interact with the game. ```csharp using UnityEngine; public interface PluginModule { void Startup(GameObject gameObject); void Update(GameObject gameObject); } ``` -------------------------------- ### Assembly for Method Without SkipLocalsInit Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines.md Shows the X86 assembly generated for a C# method that does not use the SkipLocalsInit attribute. The assembly includes instructions for zero-initializing the stack-allocated array, highlighted by the `burst.memset.inline.X64_SSE4.i32@@32` call. ```C push rbp .seh_pushreg rbp push rsi .seh_pushreg rsi push rdi .seh_pushreg rdi mov rbp, rsp .seh_setframe rbp, 0 .seh_endprologue mov edi, ecx lea r8d, [4*rdi] lea rax, [r8 + 15] and rax, -16 movabs r11, offset __chkstk call r11 sub rsp, rax mov rsi, rsp sub rsp, 32 movabs rax, offset burst.memset.inline.X64_SSE4.i32@@32 mov rcx, rsi xor edx, edx xor r9d, r9d call rax add rsp, 32 test edi, edi jle .LBB0_7 mov eax, edi cmp edi, 8 jae .LBB0_3 xor ecx, ecx jmp .LBB0_6 .LBB0_3: mov ecx, eax and ecx, -8 movabs rdx, offset __xmm@00000003000000020000000100000000 movdqa xmm0, xmmword ptr [rdx] mov rdx, rsi add rdx, 16 movabs rdi, offset __xmm@00000004000000040000000400000004 movdqa xmm1, xmmword ptr [rdi] movabs rdi, offset __xmm@00000008000000080000000800000008 movdqa xmm2, xmmword ptr [rdi] mov rdi, rcx .p2align 4, 0x90 .LBB0_4: movdqa xmm3, xmm0 paddd xmm3, xmm1 movdqu xmmword ptr [rdx - 16], xmm0 movdqu xmmword ptr [rdx], xmm3 paddd xmm0, xmm2 add rdx, 32 add rdi, -8 jne .LBB0_4 cmp rcx, rax je .LBB0_7 .p2align 4, 0x90 .LBB0_6: mov dword ptr [rsi + 4*rcx], ecx inc rcx cmp rax, rcx jne .LBB0_6 .LBB0_7: sub rsp, 32 movabs rax, offset "DoSomethingWithLUT" mov rcx, rsi call rax nop mov rsp, rbp pop rdi pop rsi pop rbp ret ``` -------------------------------- ### Modding Manager (C#) Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/ModdingSupport.md A Unity MonoBehaviour script that manages loading and running mods. It scans a 'Mods' folder for DLLs, loads managed assemblies, and uses BurstRuntime to load additional Burst compiled libraries. It then calls 'Startup' and 'Update' methods on loaded plugins. ```csharp using System; using System.Collections.Generic; using System.IO; using System.Reflection; using UnityEngine; using Unity.Burst; public class PluginManager : MonoBehaviour { public bool modsEnabled; public GameObject objectForPlugins; List plugins; void Start() { plugins = new List(); // If mods are disabled, early out - this allows us to disable mods, enter Play Mode, exit Play Mode //and be sure that the managed assemblies have been unloaded (assuming DomainReload occurs) if (!modsEnabled) return; var folder = Path.GetFullPath(Path.Combine(Application.dataPath, "..", "Mods")); if (Directory.Exists(folder)) { var mods = Directory.GetDirectories(folder); foreach (var mod in mods) { var modName = Path.GetFileName(mod); var monoAssembly = Path.Combine(mod, $"{modName}_managed.dll"); if (File.Exists(monoAssembly)) { var managedPlugin = Assembly.LoadFile(monoAssembly); var pluginModule = managedPlugin.GetType("MyPluginModule"); var plugin = Activator.CreateInstance(pluginModule) as PluginModule; plugins.Add(plugin); } var burstedAssembly = Path.Combine(mod, $"{modName}_win_x86_64.dll"); // Burst dll (assuming windows 64bit) if (File.Exists(burstedAssembly)) { BurstRuntime.LoadAdditionalLibrary(burstedAssembly); } } } foreach (var plugin in plugins) { plugin.Startup(objectForPlugins); } } // Update is called once per frame void Update() { foreach (var plugin in plugins) { plugin.Update(objectForPlugins); } } } ``` -------------------------------- ### Managed Debugging in Burst Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/TableOfContents.md Explains the process of debugging Burst-compiled code using managed debugging tools within the Unity environment. This allows setting breakpoints and inspecting variables in C# code. ```Unity Editor // Ensure 'Enable Debugging' is checked in Burst AOT compilation settings. // Use standard C# debugging techniques (e.g., Visual Studio, Rider) to attach to the Unity Editor process. ``` -------------------------------- ### Assembly-Level BurstCompile Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/TableOfContents.md Describes how to apply Burst compilation at the assembly level using attributes. This allows for broader application of Burst optimization across multiple types and methods within an assembly. ```C# // Apply this attribute to your AssemblyInfo.cs or similar file // Note: This is a conceptual example, the exact mechanism might vary. // [assembly: Unity.Burst.BurstCompile] // Or apply to specific types: // [assembly: Unity.Burst.BurstCompile] // namespace MyAssembly { ... } ``` -------------------------------- ### Optimization Choices for BurstCompile Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/AdvancedUsages.md Demonstrates how to specify optimization goals for the Burst compiler using the OptimizeFor field in the [BurstCompile] attribute. Options include Balanced, Performance, Size, and FastCompilation, each with different trade-offs. ```csharp using Unity.Burst; using Unity.Jobs; [BurstCompile(OptimizeFor = OptimizeFor.FastCompilation)] public struct MyJob : IJob { // ... job implementation ... } ``` -------------------------------- ### Dynamic Dispatch with CPU Features Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/TableOfContents.md Details how to implement dynamic dispatch in Burst code based on runtime CPU features (e.g., SIMD instruction sets like SSE, AVX). This allows selecting the most performant code path automatically. ```C# using Unity.Burst; using Unity.Burst.Intrinsics; using Unity.Mathematics; public struct DynamicDispatchJob : IJob { public float input; public float output; public void Execute() { if (X86.Sse2.IsSse2Supported()) { // Use SSE2 optimized code output = math.sqrt(input); } else { // Fallback to scalar code output = (float)Math.Sqrt(input); } } } ``` -------------------------------- ### Logging Vector Types with Interpolation in Burst Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/CSharpLanguageSupport_Lang.md Shows how to log vector types, such as float3, using string interpolation with Debug.Log in Burst. This demonstrates support for common Unity vector types. ```csharp var value = new float3(1.0f, 2.0f, 3.0f); // Logs "This value float3(1f, 2f, 3f)" Debug.Log($"This value `{value}`"); ``` -------------------------------- ### Function Pointers in Burst Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/TableOfContents.md Illustrates the use of function pointers within Burst-compiled code. This allows for dynamic dispatch and passing functions as arguments, enabling more flexible and optimized code patterns. ```C# using Unity.Jobs; using Unity.Burst; using System; public struct FunctionPointerJob : IJob { public delegate int MathOperation(int a, int b); public MathOperation operation; public int inputA; public int inputB; public int result; public void Execute() { // Using the function pointer passed to the job result = operation(inputA, inputB); } } public class FunctionPointerExample { [BurstCompile] public static int Add(int a, int b) => a + b; public static void RunJob() { var job = new FunctionPointerJob { operation = Add, inputA = 10, inputB = 5 }; JobHandle handle = job.Schedule(); handle.Complete(); // job.result will contain 15 } } ``` -------------------------------- ### Optimization Guidelines - Aliasing Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/TableOfContents.md Provides guidelines on memory aliasing for Burst compiler optimization. It explains the problems caused by aliasing, especially with auto-vectorization, and how to structure code to avoid these issues. ```C# // To avoid aliasing issues with auto-vectorizer: // Ensure that pointers or references passed to Burst compiled functions do not alias memory regions // that are accessed in a way that would break vectorization assumptions. // Use restrict qualifiers or specific attributes if available to inform the compiler. ``` -------------------------------- ### Synchronous Compilation in Burst Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/TableOfContents.md Explains how to enable synchronous compilation for Burst jobs. This means the job will be compiled and executed immediately when scheduled, which can be useful for debugging or specific performance scenarios. ```C# using Unity.Jobs; using Unity.Burst; // To enable synchronous compilation, you might use a specific Burst configuration or attribute, // though typically Burst is asynchronous. For debugging, you might force compilation. public struct SyncJob : IJob { public void Execute() { // Job logic } } // Example of forcing compilation (for debugging purposes): // var jobHandle = new SyncJob().Schedule(); // jobHandle.Complete(); // Forces compilation and execution if not already done. ``` -------------------------------- ### Compile Function Pointers using BurstCompiler Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/AdvancedUsages.md Demonstrates how to compile static functions into `FunctionPointer` objects using `BurstCompiler.CompileFunctionPointer`. This allows these functions to be invoked efficiently from C# or Unity Jobs. ```C# // Contains a compiled version of MultiplyFloat with Burst FunctionPointer mulFunctionPointer = BurstCompiler.CompileFunctionPointer(MultiplyFloat); // Contains a compiled version of AddFloat with Burst FunctionPointer addFunctionPointer = BurstCompiler.CompileFunctionPointer(AddFloat); ``` -------------------------------- ### Logging with string.Format in Burst Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/CSharpLanguageSupport_Lang.md Illustrates the equivalent of string interpolation using string.Format directly with Debug.Log in Burst. This method is supported for formatting messages with arguments. ```csharp int value = 256; Debug.Log(string.Format("This is an integer value {0}", value)); ``` -------------------------------- ### Scalar Assembly for Loop with Branch Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines.md Shows the scalar assembly code generated for a loop containing a conditional branch. This assembly demonstrates that the loop is no longer vectorized and performs operations one element at a time, resulting in reduced performance. ```assembly .LBB1_3: mov r9d, dword ptr [rcx + 4*r10] mov eax, dword ptr [rdx + 4*r10] cmp r9d, eax jg .LBB1_4 add eax, r9d mov dword ptr [rcx + 4*r10], eax inc r10 cmp r8, r10 jne .LBB1_3 ``` -------------------------------- ### Native Debugging in Burst Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/TableOfContents.md Details how to perform native-level debugging on Burst-compiled code, typically using external debuggers like Visual Studio or LLDB. This is useful for deep performance analysis and low-level issues. ```C/C++ // Compile Burst code with debug symbols enabled. // Attach a native debugger (e.g., Visual Studio Debugger, LLDB) to the Unity Editor or a standalone build. ``` -------------------------------- ### Unity Burst: Optimal Job Implementation for Math Operations Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/AdvancedUsages.md Presents the most performant way to implement the square root operation using Unity Burst by directly utilizing a job. This method provides the compiler with the most visibility for optimization, including vectorization and aliasing information. ```csharp [BurstCompile] struct MyJob : IJobParallelFor { [ReadOnly] public NativeArray Input; [WriteOnly] public NativeArray Output; public unsafe void Execute(int index) { Output[index] = math.sqrt(Input[index]); } } ``` -------------------------------- ### Define Direct Generic Job with BurstCompile Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines.md Demonstrates how to define a generic Job struct that can be compiled by the Burst compiler. The Job must implement the IJob interface and have its generic type parameter constrained to struct. ```csharp struct MyGenericJob : IJob where TData : struct { public void Execute() { ... } } ``` -------------------------------- ### Unity Burst: Optimized Function Pointer Usage with Batching Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/AdvancedUsages.md Illustrates an improved method for using Burst function pointers by processing batches of data. This approach enables vectorization and reduces the overhead per element, leading to better performance. ```csharp [BurstCompile] public class MyFunctionPointers { public unsafe delegate void MyFunctionPointerDelegate(int count, float* input, float* output); [BurstCompile] public static unsafe void MyFunctionPointer(int count, float* input, float* output) { for (int i = 0; i < count; i++) { output[i] = math.sqrt(input[i]); } } } [BurstCompile] struct MyJob : IJobParallelForBatch { public FunctionPointer FunctionPointer; [ReadOnly] public NativeArray Input; [WriteOnly] public NativeArray Output; public unsafe void Execute(int index, int count) { var inputPtr = (float*)Input.GetUnsafeReadOnlyPtr() + index; var outputPtr = (float*)Output.GetUnsafePtr() + index; FunctionPointer.Invoke(count, inputPtr, outputPtr); } } ``` -------------------------------- ### Burst Compilation Instruction Set Gating Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/StandalonePlayerSupport.md This section explains how Burst manages multiple target compilations by gating certain instruction sets. It details the dependencies for SSE4.2 and AVX2, specifying the required underlying processor instruction sets for each. This ensures efficient compilation by consolidating targets. ```text Instruction Set | Required Instruction Sets ----------------- | ------------------------- SSE4.2 | SSE4.2, POPCNT AVX2 | AVX2, FMA, F16C, BMI1, BMI2 ``` -------------------------------- ### Define Nested Generic Job with BurstCompile Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines.md Illustrates defining a Burst-compiled Job within a generic system class. The nested Job can be scheduled from the outer generic system, and Burst can compile specific instantiations if the generic arguments are resolved. ```csharp public class MyGenericSystem where TData : struct { [BurstCompile] struct MyGenericJob : IJob { public void Execute() { ... } } public void Run() { var myJob = new MyGenericJob(); // implicitly MyGenericSystem.MyGenericJob myJob.Schedule(); } } ``` -------------------------------- ### Constrain Integer Range with AssumeRange Source: https://github.com/needle-mirror/com.unity.burst/blob/master/Documentation~/docs/OptimizationGuidelines.md Demonstrates how to use the AssumeRange attribute on a method parameter and its return value to inform the Burst compiler about integer constraints. This allows for potential optimizations based on the specified ranges. ```csharp [return:AssumeRange(0u, 13u)] static uint WithConstrainedRange([AssumeRange(0, 26)] int x) { return (uint)x / 2u; } ```