InjectComponentGroupData(ComponentSystemBase system, FieldInfo groupField, InjectionData[] componentDataInjections, InjectionData[] fixedArrayInjections, InjectionData[] sharedComponentInjections, FieldInfo entityArrayInjection, FieldInfo indexFromEntityInjection, InjectionContext injectionContext, FieldInfo lengthInjection, ComponentType[] componentRequirements) { var requiredComponentTypes = componentRequirements; m_EntityGroup = system.GetComponentGroup(requiredComponentTypes); m_ComponentDataInjections = componentDataInjections; m_FixedArrayInjections = fixedArrayInjections; m_SharedComponentInjections = sharedComponentInjections; m_InjectionContext = injectionContext; PatchGetIndexInComponentGroup(m_ComponentDataInjections); PatchGetIndexInComponentGroup(m_FixedArrayInjections); PatchGetIndexInComponentGroup(m_SharedComponentInjections); injectionContext.PrepareEntries(m_EntityGroup); if (entityArrayInjection != null) { m_EntityArrayOffset = UnsafeUtility.GetFieldOffset(entityArrayInjection); } else { m_EntityArrayOffset = -1; } if (indexFromEntityInjection != null) { m_IndexFromEntityOffset = UnsafeUtility.GetFieldOffset(indexFromEntityInjection); } else { m_IndexFromEntityOffset = -1; } if (lengthInjection != null) { m_LengthOffset = UnsafeUtility.GetFieldOffset(lengthInjection); } else { m_LengthOffset = -1; } m_GroupFieldOffset = UnsafeUtility.GetFieldOffset(groupField); }
unsafe internal static void Initialize(ComponentSystemBase system, Type jobType, Type wrapperJobType, bool isParallelFor, ref JobProcessComponentDataCache cache, out ProcessIterationData iterator) { if ((isParallelFor && cache.JobReflectionDataParallelFor == IntPtr.Zero) || (!isParallelFor && cache.JobReflectionData == IntPtr.Zero)) { var iType = GetIJobProcessComponentDataInterface(jobType); if (cache.Types == null) { cache.Types = GetComponentTypes(jobType, iType, out cache.ProcessTypesCount); } var res = GetJobReflection(jobType, wrapperJobType, iType, isParallelFor); if (isParallelFor) { cache.JobReflectionDataParallelFor = res; } else { cache.JobReflectionData = res; } } if (cache.ComponentSystem != system) { cache.ComponentGroup = system.GetComponentGroup(cache.Types); cache.ComponentSystem = system; } var group = cache.ComponentGroup; // Readonly iterator.IsReadOnly0 = iterator.IsReadOnly1 = iterator.IsReadOnly2 = 0; fixed(int *isReadOnly = &iterator.IsReadOnly0) { for (var i = 0; i != cache.ProcessTypesCount; i++) { isReadOnly[i] = cache.Types[i].AccessModeType == ComponentType.AccessMode.ReadOnly ? 1 : 0; } } // Iterator & length iterator.Iterator0 = default(ComponentChunkIterator); iterator.Iterator1 = default(ComponentChunkIterator); iterator.Iterator2 = default(ComponentChunkIterator); var length = -1; fixed(ComponentChunkIterator *iterators = &iterator.Iterator0) { for (var i = 0; i != cache.ProcessTypesCount; i++) { group.GetComponentChunkIterator(out length, out iterators[i]); iterators[i].IndexInComponentGroup = group.GetIndexInComponentGroup(cache.Types[i].TypeIndex); } } iterator.m_IsParallelFor = isParallelFor; iterator.m_Length = length; #if ENABLE_UNITY_COLLECTIONS_CHECKS iterator.m_MaxIndex = length - 1; iterator.m_MinIndex = 0; // Safety iterator.m_Safety0 = iterator.m_Safety1 = iterator.m_Safety2 = default(AtomicSafetyHandle); iterator.m_SafetyReadOnlyCount = 0; fixed(AtomicSafetyHandle *safety = &iterator.m_Safety0) { for (var i = 0; i != cache.ProcessTypesCount; i++) { if (cache.Types[i].AccessModeType == ComponentType.AccessMode.ReadOnly) { safety[iterator.m_SafetyReadOnlyCount] = group.GetSafetyHandle(group.GetIndexInComponentGroup(cache.Types[i].TypeIndex)); iterator.m_SafetyReadOnlyCount++; } } } iterator.m_SafetyReadWriteCount = 0; fixed(AtomicSafetyHandle *safety = &iterator.m_Safety0) { for (var i = 0; i != cache.ProcessTypesCount; i++) { if (cache.Types[i].AccessModeType == ComponentType.AccessMode.ReadWrite) { safety[iterator.m_SafetyReadOnlyCount + iterator.m_SafetyReadWriteCount] = group.GetSafetyHandle(group.GetIndexInComponentGroup(cache.Types[i].TypeIndex)); iterator.m_SafetyReadWriteCount++; } } } Assert.AreEqual(cache.ProcessTypesCount, iterator.m_SafetyReadWriteCount + iterator.m_SafetyReadOnlyCount); #endif }
public ComponentGroupArrayStaticCache(Type type, EntityManager entityManager, ComponentSystemBase system = null) { var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); var componentFieldOffsetsBuilder = new List <int>(); var componentTypesBuilder = new List <ComponentType>(); var componentDataFieldOffsetsBuilder = new List <int>(); var componentDataTypesBuilder = new List <ComponentType>(); var subtractiveComponentTypesBuilder = new List <ComponentType>(); foreach (var field in fields) { var fieldType = field.FieldType; var offset = UnsafeUtility.GetFieldOffset(field); if (fieldType.IsPointer) { var isReadOnly = field.GetCustomAttributes(typeof(ReadOnlyAttribute), true).Length != 0; var accessMode = isReadOnly ? ComponentType.AccessMode.ReadOnly : ComponentType.AccessMode.ReadWrite; var elementType = fieldType.GetElementType(); #if ENABLE_UNITY_COLLECTIONS_CHECKS if (!typeof(IComponentData).IsAssignableFrom(elementType) && elementType != typeof(Entity)) { throw new ArgumentException($"{type}.{field.Name} is a pointer type but not a IComponentData. Only IComponentData or Entity may be a pointer type for enumeration."); } #endif componentDataFieldOffsetsBuilder.Add(offset); componentDataTypesBuilder.Add(new ComponentType(elementType, accessMode)); } else if (fieldType.IsSubclassOf(TypeManager.UnityEngineComponentType)) { componentFieldOffsetsBuilder.Add(offset); componentTypesBuilder.Add(fieldType); } else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(SubtractiveComponent <>)) { subtractiveComponentTypesBuilder.Add(ComponentType.Subtractive(fieldType.GetGenericArguments()[0])); } #if ENABLE_UNITY_COLLECTIONS_CHECKS else if (typeof(IComponentData).IsAssignableFrom(fieldType)) { throw new ArgumentException($"{type}.{field.Name} must be an unsafe pointer to the {fieldType}. Like this: {fieldType}* {field.Name};"); } else { throw new ArgumentException($"{type}.{field.Name} can not be used in a component enumerator"); } #endif } #if ENABLE_UNITY_COLLECTIONS_CHECKS if (componentTypesBuilder.Count + componentDataTypesBuilder.Count > ComponentGroupArrayData.kMaxStream) { throw new ArgumentException($"{type} has too many component references. A ComponentGroup Array can have up to {ComponentGroupArrayData.kMaxStream}."); } #endif ComponentDataCount = componentDataTypesBuilder.Count; ComponentCount = componentTypesBuilder.Count; componentDataTypesBuilder.AddRange(componentTypesBuilder); componentDataTypesBuilder.AddRange(subtractiveComponentTypesBuilder); ComponentTypes = componentDataTypesBuilder.ToArray(); componentDataFieldOffsetsBuilder.AddRange(componentFieldOffsetsBuilder); ComponentFieldOffsets = componentDataFieldOffsetsBuilder.ToArray(); if (system != null) { ComponentGroup = system.GetComponentGroup(ComponentTypes); SafetyManager = entityManager.ComponentJobSafetyManager; } else { ComponentGroup = entityManager.CreateComponentGroup(ComponentTypes); SafetyManager = entityManager.ComponentJobSafetyManager; } CachedType = type; }