Boat Attack使用了Universal RP的许多新图形功能,可以用于探索 Universal RP 的使用方式和技巧。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

166 行
6.4 KiB

using System;
using Unity.Jobs;
using Unity.Jobs.LowLevel.Unsafe;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
namespace Unity.Entities
{
#if !UNITY_DOTSPLAYER
[JobProducerType(typeof(JobChunkExtensions.JobChunk_Process<>))]
#endif
public interface IJobChunk
{
// firstEntityIndex refers to the index of the first entity in the current chunk within the EntityQuery the job was scheduled with
// For example, if the job operates on 3 chunks with 20 entities each, then the firstEntityIndices will be [0, 20, 40] respectively
void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex);
}
public static class JobChunkExtensions
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
[NativeContainer]
internal struct EntitySafetyHandle
{
public AtomicSafetyHandle m_Safety;
}
#endif
internal struct JobChunkData<T> where T : struct
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
#pragma warning disable 414
[ReadOnly] public EntitySafetyHandle safety;
#pragma warning restore
#endif
public T Data;
[DeallocateOnJobCompletion]
[NativeDisableContainerSafetyRestriction]
public NativeArray<byte> PrefilterData;
}
public static unsafe JobHandle Schedule<T>(this T jobData, EntityQuery query, JobHandle dependsOn = default(JobHandle))
where T : struct, IJobChunk
{
return ScheduleInternal(ref jobData, query, dependsOn, ScheduleMode.Batched);
}
public static void Run<T>(this T jobData, EntityQuery query)
where T : struct, IJobChunk
{
ScheduleInternal(ref jobData, query, default(JobHandle), ScheduleMode.Run);
}
#if !UNITY_DOTSPLAYER
internal static unsafe JobHandle ScheduleInternal<T>(ref T jobData, EntityQuery query, JobHandle dependsOn, ScheduleMode mode)
where T : struct, IJobChunk
{
ComponentChunkIterator iterator = query.GetComponentChunkIterator();
var unfilteredChunkCount = query.CalculateNumberOfChunksWithoutFiltering();
var prefilterHandle = ComponentChunkIterator.PreparePrefilteredChunkLists(unfilteredChunkCount,
iterator.m_MatchingArchetypeList, iterator.m_Filter, dependsOn, mode, out var prefilterData,
out var deferredCountData);
JobChunkData<T> fullData = new JobChunkData<T>
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
// All IJobChunk jobs have a EntityManager safety handle to ensure that BeforeStructuralChange throws an error if
// jobs without any other safety handles are still running (haven't been synced).
safety = new EntitySafetyHandle{m_Safety = query.SafetyManager->GetEntityManagerSafetyHandle()},
#endif
Data = jobData,
PrefilterData = prefilterData,
};
var scheduleParams = new JobsUtility.JobScheduleParameters(
UnsafeUtility.AddressOf(ref fullData),
JobChunk_Process<T>.Initialize(),
prefilterHandle,
mode);
#if ENABLE_UNITY_COLLECTIONS_CHECKS
try
{
#endif
if(mode == ScheduleMode.Batched)
return JobsUtility.ScheduleParallelForDeferArraySize(ref scheduleParams, 1, deferredCountData, null);
else
{
var count = unfilteredChunkCount;
return JobsUtility.ScheduleParallelFor(ref scheduleParams, count, 1);
}
#if ENABLE_UNITY_COLLECTIONS_CHECKS
}
catch (InvalidOperationException e)
{
prefilterData.Dispose();
throw e;
}
#endif
}
internal struct JobChunk_Process<T>
where T : struct, IJobChunk
{
public static IntPtr jobReflectionData;
public static IntPtr Initialize()
{
if (jobReflectionData == IntPtr.Zero)
jobReflectionData = JobsUtility.CreateJobReflectionData(typeof(JobChunkData<T>),
typeof(T), JobType.ParallelFor, (ExecuteJobFunction)Execute);
return jobReflectionData;
}
public delegate void ExecuteJobFunction(ref JobChunkData<T> data, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref JobRanges ranges, int jobIndex);
public unsafe static void Execute(ref JobChunkData<T> jobData, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref JobRanges ranges, int jobIndex)
{
ExecuteInternal(ref jobData, ref ranges, jobIndex);
}
internal unsafe static void ExecuteInternal(ref JobChunkData<T> jobData, ref JobRanges ranges, int jobIndex)
{
ComponentChunkIterator.UnpackPrefilterData(jobData.PrefilterData, out var filteredChunks, out var entityIndices, out var chunkCount);
int chunkIndex, end;
while (JobsUtility.GetWorkStealingRange(ref ranges, jobIndex, out chunkIndex, out end))
{
var chunk = filteredChunks[chunkIndex];
var entityOffset = entityIndices[chunkIndex];
jobData.Data.Execute(chunk, chunkIndex, entityOffset);
}
}
}
#else
internal static unsafe JobHandle ScheduleInternal<T>(ref T jobData, EntityQuery query, JobHandle dependsOn, ScheduleMode mode)
where T : struct, IJobChunk
{
using (var chunks = query.CreateArchetypeChunkArray(Allocator.Temp))
{
int currentChunk = 0;
int currentEntity = 0;
foreach (var chunk in chunks)
{
jobData.Execute(chunk, currentChunk, currentEntity);
currentChunk++;
currentEntity += chunk.Count;
}
}
DoDeallocateOnJobCompletion(jobData);
return new JobHandle();
}
static internal void DoDeallocateOnJobCompletion(object jobData)
{
throw new NotImplementedException("This function should have been replaced by codegen");
}
#endif
}
}