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);
        }
Exemplo n.º 2
0
        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
        }
Exemplo n.º 3
0
        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;
        }