### IJobParallelForBatch Interface Definition - Unity Jobs Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/manual/scheduling_a_job_from_a_job Defines the interface for jobs that process parallel workloads in batches. The Execute method receives a start index and a count, allowing for efficient processing of chunks of data. ```csharp public interface IJobParallelForBatch { void Execute(int startIndex, int count); } ``` -------------------------------- ### Concurrent NativeCounter Get and Set Operations Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/manual/custom_job_types Provides thread-safe access to the concurrent counter. The 'get' operation sums values from all thread-local caches, while 'set' clears local caches and sets the primary value. ```csharp public int Count { get { // Verify that the caller has read permission on this data. // This is the race condition protection, without these checks the AtomicSafetyHandle is useless #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckReadAndThrow(m_Safety); #endif int count = 0; for (int i = 0; i < JobsUtility.MaxJobThreadCount; ++i) count += m_Counter[IntsPerCacheLine * i]; return count; } set { // Verify that the caller has write permission on this data. // This is the race condition protection, without these checks the AtomicSafetyHandle is useless #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); #endif // Clear all locally cached counts, // set the first one to the required value for (int i = 1; i < JobsUtility.MaxJobThreadCount; ++i) m_Counter[IntsPerCacheLine * i] = 0; *m_Counter = value; } } ``` -------------------------------- ### Create and Manage a NativeCounter in C# Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/manual/custom_job_types This C# code defines a custom NativeContainer called 'NativeCounter' for Unity jobs. It allows for thread-safe incrementing, getting, and setting of an integer count. The container manages native memory allocation and deallocation, and includes safety checks for multi-threaded access. ```csharp // Mark this struct as a NativeContainer, usually this would be a generic struct for containers, but a counter does not need to be generic // TODO - why does a counter not need to be generic? - explain the argument for this reasoning please. [StructLayout(LayoutKind.Sequential)] [NativeContainer] unsafe public struct NativeCounter { // The actual pointer to the allocated count needs to have restrictions relaxed so jobs can be schedled with this container [NativeDisableUnsafePtrRestriction] int* m_Counter; #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle m_Safety; // The dispose sentinel tracks memory leaks. It is a managed type so it is cleared to null when scheduling a job // The job cannot dispose the container, and no one else can dispose it until the job has run, so it is ok to not pass it along // This attribute is required, without it this NativeContainer cannot be passed to a job; since that would give the job access to a managed object [NativeSetClassTypeToNullOnSchedule] DisposeSentinel m_DisposeSentinel; #endif // Keep track of where the memory for this was allocated Allocator m_AllocatorLabel; public NativeCounter(Allocator label) { // This check is redundant since we always use an int that is blittable. // It is here as an example of how to check for type correctness for generic types. #if ENABLE_UNITY_COLLECTIONS_CHECKS if (!UnsafeUtility.IsBlittable) throw new ArgumentException(string.Format("{0} used in NativeQueue<{0}> must be blittable", typeof(int))); #endif m_AllocatorLabel = label; // Allocate native memory for a single integer m_Counter = (int*)UnsafeUtility.Malloc(UnsafeUtility.SizeOf(), 4, label); // Create a dispose sentinel to track memory leaks. This also creates the AtomicSafetyHandle #if ENABLE_UNITY_COLLECTIONS_CHECKS DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, 0); #endif // Initialize the count to 0 to avoid uninitialized data Count = 0; } public void Increment() { // Verify that the caller has write permission on this data. // This is the race condition protection, without these checks the AtomicSafetyHandle is useless #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); #endif (*m_Counter)++; } public int Count { get { // Verify that the caller has read permission on this data. // This is the race condition protection, without these checks the AtomicSafetyHandle is useless #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckReadAndThrow(m_Safety); #endif return *m_Counter; } set { // Verify that the caller has write permission on this data. This is the race condition protection, without these checks the AtomicSafetyHandle is useless #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); #endif *m_Counter = value; } } public bool IsCreated { get { return m_Counter != null; } } public void Dispose() { // Let the dispose sentinel know that the data has been freed so it does not report any memory leaks #if ENABLE_UNITY_COLLECTIONS_CHECKS DisposeSentinel.Dispose(m_Safety, ref m_DisposeSentinel); #endif UnsafeUtility.Free(m_Counter, m_AllocatorLabel); m_Counter = null; } } ``` -------------------------------- ### JobParallelIndexListExtensions.JobStructProduce Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/api/Unity.Jobs.JobParallelIndexListExtensions Details about the JobStructProduce struct, its type parameters, fields, and methods for job execution and initialization. ```APIDOC ## Struct JobParallelIndexListExtensions.JobStructProduce ### Description Represents a structure used in the Unity Jobs system for parallel processing, specifically related to filtering and producing results based on parallel indices. ### Namespace Unity.Jobs ### Syntax ```csharp public struct JobStructProduce where T : struct, IJobParallelForFilter ``` ### Type Parameters * **T** - The type parameter for the struct, which must be a struct implementing `IJobParallelForFilter`. ### Fields * **jobReflectionData** (`System.IntPtr`) * Declaration: ```csharp public static IntPtr jobReflectionData ``` * Description: Static field storing reflection data for the job. ### Methods * **Execute** * Declaration: ```csharp public static void Execute(ref JobParallelIndexListExtensions.JobStructProduce.JobDataWithFiltering jobData, IntPtr additionalPtr, IntPtr bufferRangePatchData, ref JobRanges ranges, int jobIndex) ``` * Description: Executes the job logic for a given range of indices. * Parameters: * `jobData` (JobParallelIndexListExtensions.JobStructProduce.JobDataWithFiltering<>) - The data structure containing job-specific information and filtering. * `additionalPtr` (System.IntPtr) - Pointer for additional data. * `bufferRangePatchData` (System.IntPtr) - Pointer for buffer range modifications. * `ranges` (JobRanges) - Information about the parallel job ranges. * `jobIndex` (System.Int32) - The index of the current job instance. * **ExecuteAppend** * Declaration: ```csharp public static void ExecuteAppend(ref JobParallelIndexListExtensions.JobStructProduce.JobDataWithFiltering jobData, IntPtr bufferRangePatchData) ``` * Description: Appends results or performs actions after the main execution phase. * Parameters: * `jobData` (JobParallelIndexListExtensions.JobStructProduce.JobDataWithFiltering<>) - The data structure containing job-specific information. * `bufferRangePatchData` (System.IntPtr) - Pointer for buffer range modifications. * **ExecuteFilter** * Declaration: ```csharp public static void ExecuteFilter(ref JobParallelIndexListExtensions.JobStructProduce.JobDataWithFiltering jobData, IntPtr bufferRangePatchData) ``` * Description: Executes the filtering logic for the job. * Parameters: * `jobData` (JobParallelIndexListExtensions.JobStructProduce.JobDataWithFiltering<>) - The data structure containing job-specific information and filtering. * `bufferRangePatchData` (System.IntPtr) - Pointer for buffer range modifications. * **Initialize** * Declaration: ```csharp public static IntPtr Initialize() ``` * Description: Initializes the job system or related components. * Returns: * `System.IntPtr` - A pointer to the initialized data or component. ``` -------------------------------- ### Scheduling and Completing a ParallelFor Job with NativeCounter (C#) Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/manual/custom_job_types This snippet shows the typical workflow for using the `CountZeros` job. It initializes a `NativeCounter`, creates and configures the job, schedules it for execution, waits for it to complete using `handle.Complete()`, logs the result, and disposes of the counter. ```csharp var counter = new NativeCounter(Allocator.Temp); var jobData = new CountZeros(); jobData.input = input; jobData.counter = counter; counter.Count = 0; var handle = jobData.Schedule(input.Length, 8); handle.Complete(); Debug.Log("The array countains " + counter.Count + " zeros"); counter.Dispose(); ``` -------------------------------- ### Unity C# - JobStructProduce Structure Definition Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/api/Unity.Jobs.JobParallelIndexListExtensions This code defines the JobStructProduce struct in C# for the Unity Jobs system. It includes generic type parameter constraints and static fields/methods for managing parallel jobs with filtering. ```csharp public struct JobStructProduce where T : struct, IJobParallelForFilter { public static IntPtr jobReflectionData; public static void Execute(ref JobParallelIndexListExtensions.JobStructProduce.JobDataWithFiltering jobData, IntPtr additionalPtr, IntPtr bufferRangePatchData, ref JobRanges ranges, int jobIndex); public static void ExecuteAppend(ref JobParallelIndexListExtensions.JobStructProduce.JobDataWithFiltering jobData, IntPtr bufferRangePatchData); public static void ExecuteFilter(ref JobParallelIndexListExtensions.JobStructProduce.JobDataWithFiltering jobData, IntPtr bufferRangePatchData); public static IntPtr Initialize(); } ``` -------------------------------- ### Unity Jobs: ExecuteJobFunction Delegate Signature Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/manual/custom_job_types The signature for the job execution entry point delegate in Unity's job system. It receives job data, additional pointers, buffer range patch data, job ranges, and the job index. ```csharp public delegate void ExecuteJobFunction(ref T data, IntPtr additionalPtr, IntPtr bufferRangePatchData, ref JobRanges ranges, int jobIndex); ``` -------------------------------- ### Create Job Reflection Data for Custom Jobs Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/manual/custom_job_types Creates reflection data necessary for scheduling custom job types. This data informs the Jobs System about the job's struct type, execution method, and job type (Single or ParallelFor). ```csharp JobsUtility.CreateJobReflectionData(typeof(T), JobType.ParallelFor, (ExecuteJobFunction)Execute); ``` -------------------------------- ### ScheduleAppend Job - Unity Jobs Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/api/Unity.Jobs Schedules an append operation for a parallel job. This method is an extension for types implementing IJobParallelForFilter. It takes job data, a NativeList of indices, array length, inner loop batch count, and an optional dependency handle. It returns a JobHandle to manage the job's execution. ```csharp public static JobHandle ScheduleAppend(this T jobData, NativeList indices, int arrayLength, int innerloopBatchCount, JobHandle dependsOn = null) where T : struct, IJobParallelForFilter ``` -------------------------------- ### Unity Jobs Scheduling Functions Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/manual/custom_job_types Demonstrates the primary functions for scheduling jobs within the Unity Jobs System. These functions vary based on the job type (Single or ParallelFor) and whether transform data needs to be accessed. ```csharp JobHandle Schedule(ref JobScheduleParameters parameters); JobHandle ScheduleParallelFor(ref JobScheduleParameters parameters, int arrayLength, int innerLoopBatchCount); JobHandle ScheduleParallelForTransform(ref JobScheduleParameters parameters, IntPtr transfromAccessArray); ``` -------------------------------- ### ScheduleFilter Job - Unity Jobs Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/api/Unity.Jobs Schedules a filter operation for a parallel job. This method is an extension for types implementing IJobParallelForFilter. It takes job data, a NativeList of indices, inner loop batch count, and an optional dependency handle. It returns a JobHandle to manage the job's execution. ```csharp public static JobHandle ScheduleFilter(this T jobData, NativeList indices, int innerloopBatchCount, JobHandle dependsOn = null) where T : struct, IJobParallelForFilter ``` -------------------------------- ### Implementing IJobParallelFor with NativeCounter.Concurrent (C#) Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/manual/custom_job_types This code demonstrates how to implement the `IJobParallelFor` interface to work with `NativeCounter.Concurrent`. The `CountZeros` job iterates through a `NativeArray`, and if an element is zero, it calls `counter.Increment()`, which is a thread-safe operation. ```csharp struct CountZeros : IJobParallelFor { [ReadOnly] public NativeArray input; public NativeCounter.Concurrent counter; public void Execute (int i) { if (input[i] == 0) { counter.Increment(); } } } ``` -------------------------------- ### ScheduleAppend Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/api/Unity.Jobs Schedules a job that appends indices to a NativeList. This method is an extension method for types implementing IJobParallelForFilter. ```APIDOC ## ScheduleAppend ### Description Schedules a job to append indices to a NativeList. This is an extension method for jobs implementing IJobParallelForFilter. ### Method `public static JobHandle ScheduleAppend(this T jobData, NativeList indices, int arrayLength, int innerloopBatchCount, JobHandle dependsOn = null)` ### Endpoint N/A (This is a C# method, not a REST endpoint) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```csharp // Example Usage (Conceptual): MyJobData job = new MyJobData(); NativeList indices = new NativeList(Allocator.Temp); JobHandle handle = JobParallelIndexListExtensions.ScheduleAppend(job, indices, 100, 32); ``` ### Response #### Success Response (200) N/A (This is a C# method, not an API response) #### Response Example ```csharp // Example Return Value: JobHandle handle; ``` ### Type Parameters * **T**: The type of the job data, which must implement `struct` and `IJobParallelForFilter`. ``` -------------------------------- ### ScheduleFilter Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/api/Unity.Jobs Schedules a job that filters indices into a NativeList. This method is an extension method for types implementing IJobParallelForFilter. ```APIDOC ## ScheduleFilter ### Description Schedules a job to filter indices into a NativeList. This is an extension method for jobs implementing IJobParallelForFilter. ### Method `public static JobHandle ScheduleFilter(this T jobData, NativeList indices, int innerloopBatchCount, JobHandle dependsOn = null)` ### Endpoint N/A (This is a C# method, not a REST endpoint) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```csharp // Example Usage (Conceptual): MyJobData job = new MyJobData(); NativeList indices = new NativeList(Allocator.Temp); JobHandle handle = JobParallelIndexListExtensions.ScheduleFilter(job, indices, 32); ``` ### Response #### Success Response (200) N/A (This is a C# method, not an API response) #### Response Example ```csharp // Example Return Value: JobHandle handle; ``` ### Type Parameters * **T**: The type of the job data, which must implement `struct` and `IJobParallelForFilter`. ``` -------------------------------- ### Define Cache Line Size for Integers Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/manual/custom_job_types Defines the number of integers that fit within a single cache line. This is crucial for calculating memory layout to avoid false sharing in concurrent data structures. ```csharp public const int IntsPerCacheLine = JobsUtility.CacheLineSize / sizeof(int); ``` -------------------------------- ### Schedule IJobParallelForBatch Custom Job Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/manual/custom_job_types Schedules a custom job that implements `IJobParallelForBatch`. This method is useful for processing data in batches rather than individual indices, optimizing scenarios like temporary array creation. ```csharp unsafe static public JobHandle ScheduleBatch(this T jobData, int arrayLength, int minIndicesPerJobCount, JobHandle dependsOn = new JobHandle()) where T : struct, IJobParallelForBatch { var scheduleParams = new JobsUtility.JobScheduleParameters(UnsafeUtility.AddressOf(ref jobData), ParallelForBatchJobStruct.Initialize(), dependsOn, ScheduleMode.Batched); return JobsUtility.ScheduleParallelFor(ref scheduleParams, arrayLength, minIndicesPerJobCount); } ``` -------------------------------- ### Allocate Memory for Thread-Local Caches Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/manual/custom_job_types Allocates memory for the counter, ensuring one full cache line per potential worker thread. This prevents false sharing by giving each thread its own dedicated memory segment on a cache line. ```csharp // One full cache line (integers per cacheline * size of integer) for each potential worker index, JobsUtility.MaxJobThreadCount m_Counter = (int*)UnsafeUtility.Malloc(UnsafeUtility.SizeOf()*IntsPerCacheLine*JobsUtility.MaxJobThreadCount, 4, label); ``` -------------------------------- ### Unity Jobs: PatchBufferMinMaxRanges for NativeContainer Safety Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/manual/custom_job_types Conditional code snippet to patch `NativeContainers` for safe access within a specified range of items during `ParallelFor` job execution. This is enabled by the `ENABLE_UNITY_COLLECTIONS_CHECKS` preprocessor directive. ```csharp #if ENABLE_UNITY_COLLECTIONS_CHECKS JobsUtility.PatchBufferMinMaxRanges(bufferRangePatchData, UnsafeUtility.AddressOf(ref jobData), begin, end - begin); #endif ``` -------------------------------- ### Concurrent Struct for Thread-Local Counter Access Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/manual/custom_job_types A thread-local struct that allows direct, non-atomic increments to a worker's local counter. It uses the injected thread index to access the correct memory location, eliminating the need for atomic operations within jobs. ```csharp [NativeContainer] [NativeContainerIsAtomicWriteOnly] // Let the job system know that it should inject the current worker index into this container unsafe public struct Concurrent { [NativeDisableUnsafePtrRestriction] int* m_Counter; #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle m_Safety; #endif // The current worker thread index; it must use this exact name since it is injected [NativeSetThreadIndex] int m_ThreadIndex; public static implicit operator NativeCacheCounter.Concurrent (NativeCacheCounter cnt) { NativeCacheCounter.Concurrent concurrent; #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckWriteAndThrow(cnt.m_Safety); concurrent.m_Safety = cnt.m_Safety; AtomicSafetyHandle.UseSecondaryVersion(ref concurrent.m_Safety); #endif concurrent.m_Counter = cnt.m_Counter; concurrent.m_ThreadIndex = 0; return concurrent; } public void Increment() { #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); #endif // No need for atomics any more since we are just incrementing the local count ++m_Counter[IntsPerCacheLine*m_ThreadIndex]; } } ``` -------------------------------- ### Unity Jobs: GetWorkStealingRange for ParallelFor Jobs Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/manual/custom_job_types A method used within `ParallelFor` jobs to retrieve the next work stealing range. It returns `true` if a range is available, populating `begin` and `end` indices, and `false` otherwise. ```csharp JobsUtility.GetWorkStealingRange(ref ranges, jobIndex, out begin, out end) ``` -------------------------------- ### NativeCounter.Concurrent Struct for Atomic Writes in Parallel Jobs (C#) Source: https://docs.unity3d.com/Packages/com.unity.jobs@0.0/Packages/com.unity.jobs%400.0/manual/custom_job_types The `NativeCounter.Concurrent` struct is designed for atomic write operations within parallel jobs. It uses `NativeContainerIsAtomicWriteOnly` and `Interlocked.Increment` to ensure thread-safe increments. It can be implicitly converted from a `NativeCounter` and is restricted to write-only access during job execution. ```csharp [NativeContainer] // This attribute is what makes it possible to use NativeCounter.Concurrent in a ParallelFor job [NativeContainerIsAtomicWriteOnly] unsafe public struct Concurrent { // Copy of the pointer from the full NativeCounter [NativeDisableUnsafePtrRestriction] int* m_Counter; // Copy of the AtomicSafetyHandle from the full NativeCounter. The dispose sentinel is not copied since this inner struct does not own the memory and is not responsible for freeing it. #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle m_Safety; #endif // This is what makes it possible to assign to NativeCounter.Concurrent from NativeCounter public static implicit operator NativeCounter.Concurrent (NativeCounter cnt) { NativeCounter.Concurrent concurrent; #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckWriteAndThrow(cnt.m_Safety); concurrent.m_Safety = cnt.m_Safety; AtomicSafetyHandle.UseSecondaryVersion(ref concurrent.m_Safety); #endif concurrent.m_Counter = cnt.m_Counter; return concurrent; } public void Increment () { // Increment still needs to check for write permissions #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); #endif // The actual increment is implemented with an atomic, since it can be incremented by multiple threads at the same time Interlocked.Increment(ref *m_Counter); } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.