//----------------------------------------------------------------------------- protected override void OnUpdate() { // Early out if we have disabled flow field rendering if (!Main.ActiveInitParams.m_drawFlowField) { return; } // We want to iterate over all unique MeshInstanceRenderer shared component data, // that are attached to any entities in the world EntityManager.GetAllUniqueSharedComponentDatas(m_CacheduniqueRendererTypes); var forEachFilter = m_InstanceRendererGroup.CreateForEachFilter(m_CacheduniqueRendererTypes); for (int i = 0; i != m_CacheduniqueRendererTypes.Count; i++) { // For each unique MeshInstanceRenderer data, we want to get all entities with a TransformMatrix // SharedComponentData gurantees that all those entities are packed togehter in a chunk with linear memory layout. // As a result the copy of the matrices out is internally done via memcpy. var renderer = m_CacheduniqueRendererTypes[i]; var transforms = m_InstanceRendererGroup.GetComponentDataArray <TransformMatrix>(forEachFilter, i); // Graphics.DrawMeshInstanced has a set of limitations that are not optimal for working with ECS. // Specifically: // * No way to push the matrices from a job // * no NativeArray API, currently uses Matrix4x4[] // As a result this code is not yet jobified. // We are planning to adjust this API to make it more efficient for this use case. // For now, we have to copy our data into Matrix4x4[] with a specific upper limit of how many instances we can render in one batch. // So we just have a for loop here, representing each Graphics.DrawMeshInstanced batch int beginIndex = 0; while (beginIndex < transforms.Length) { int length = math.min(m_MatricesArray.Length, transforms.Length - beginIndex); CopyMatrices(transforms, beginIndex, length, m_MatricesArray); for (int j = 0; j < m_MatricesArray.Length; ++j) { m_MatricesArray[j].m03 += Main.ActiveInitParams.m_cellSize / 2; m_MatricesArray[j].m23 += Main.ActiveInitParams.m_cellSize / 2; } Graphics.DrawMeshInstanced(renderer.Mesh, renderer.SubMesh, renderer.Material, m_MatricesArray, length, null, renderer.CastShadows, renderer.ReceiveShadows); beginIndex += length; } } m_CacheduniqueRendererTypes.Clear(); forEachFilter.Dispose(); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { //TODO: Is there a cheaper way to do this? It's adding about ~0.15ms var uniquePhysicsObjectComponents = new List <PhysicsObject>(); EntityManager.GetAllUniqueSharedComponentDatas(uniquePhysicsObjectComponents); var preTimeStepHandle = SchedulePreTimeStepJobs(inputDeps); if (uniquePhysicsObjectComponents.Count > 1) { var physicsObjectFilter = _membershipDebugGroup.CreateForEachFilter <PhysicsObject>(uniquePhysicsObjectComponents); return(RunMultipleSimulationTimeStepJobs(preTimeStepHandle, uniquePhysicsObjectComponents, physicsObjectFilter)); } else { return(RunSingleSimulationTimeStep(preTimeStepHandle)); } }
protected override void OnUpdate() { sharedComponents.Clear(); sharedIndices.Clear(); // MeshInstanceRendererSystemを真似て書いている。 // あちらではMatrix4x4[]を用意して1023個ずつEntityをGraphics.DrawMeshInstancedしている。 // その際にTransformMatrixをむりくりMatrix4x4に読み替えたりコピーしたりしているようなので多分遅い。 // あと、preview8のコメント文でDarwMeshInstancedの引数にNativeArray/Sliceが使えないことを嘆いている。 EntityManager.GetAllUniqueSharedComponentDatas(sharedComponents, sharedIndices); IncreaseArgsList(sharedComponents.Count); using (var filter = g.CreateForEachFilter(sharedComponents)) for (int i = 1; i < sharedComponents.Count; i++) { var positionDataArray = g.GetComponentDataArray <Position>(filter, i); var headingDataArray = g.GetComponentDataArray <Heading>(filter, i); Render(i, ref positionDataArray, ref headingDataArray); } }
protected override void OnUpdate() { EntityManager.GetAllUniqueSharedComponentDatas(cacheduniqueRendererTypes); var forEachFilter = renderGroup.CreateForEachFilter(cacheduniqueRendererTypes); for (int i = 0; i != cacheduniqueRendererTypes.Count; i++) { var renderer = cacheduniqueRendererTypes[i]; var transforms = renderGroup.GetComponentDataArray <Transform>(forEachFilter, i); if (renderer.mesh == null) { continue; } for (int temp = 0; temp < transforms.Length; ++temp) { RenderHelpers.CopyMatrices(transforms, temp, 1, RenderHelpers.matricesArray); var materials = new Material[] { renderer.material0, renderer.material1, renderer.material2 }; for (int subpart = 0; subpart < renderer.materialCount; ++subpart) { Graphics.DrawMeshInstanced(renderer.mesh, subpart, materials[subpart], RenderHelpers.matricesArray, 1, null, /*castShadows*/ ShadowCastingMode.On, /*receiveShadows*/ true); } } /* * int beginIndex = 0; * while (beginIndex < transforms.Length) * { * //int length = math.min(RenderHelpers.matricesArray.Length, transforms.Length - beginIndex); * //RenderHelpers.CopyMatrices(transforms, beginIndex, length, RenderHelpers.matricesArray); * //Graphics.DrawMeshInstanced(renderer.mesh, 0, renderer.material, RenderHelpers.matricesArray, length, null, /*castShadows* /ShadowCastingMode.On, /*receiveShadows* /true); * * beginIndex += length; * } */ } cacheduniqueRendererTypes.Clear(); forEachFilter.Dispose(); }
protected override void OnUpdate() { EntityManager.GetAllUniqueSharedComponentDatas <TerrainRenderer> (_cachedUniqueRendererTypes); var foreachFilter = _terrainRenderGroup.CreateForEachFilter(_cachedUniqueRendererTypes); for (int i = 0; i < _cachedUniqueRendererTypes.Count; i++) { var renderer = _cachedUniqueRendererTypes[i]; var transforms = _terrainRenderGroup.GetComponentDataArray <TransformMatrix> (foreachFilter, i); int beginIdx = 0; while (beginIdx < transforms.Length) { int length = math.min(_matrixArray.Length, transforms.Length - beginIdx); CopyMatrices(transforms, beginIdx, length, _matrixArray); Graphics.DrawMeshInstanced( mesh: renderer.Mesh, submeshIndex: renderer.SubMesh, material: renderer.Material, matrices: _matrixArray, count: length, properties: null, castShadows: ShadowCastingMode.Off, receiveShadows: false, layer: renderer.Layer.value, camera: renderer.Camera, lightProbeUsage: LightProbeUsage.Off, lightProbeProxyVolume: null); beginIdx += length; } } _cachedUniqueRendererTypes.Clear(); foreachFilter.Dispose(); }
private JobHandle ScheduleContstraintTraversalJob(JobHandle inputDeps) { var list = new List <ActiveBody>(); _activeBodiesGroup.CreateForEachFilter(list); }
private JobHandle ScheduleCounting(JobHandle inputDeps) { switch (_config.Method) { case TestMethod.InstancedByteComponent: if (_config.InterestingStateCount == 1) { return(new CountSpecificInstancedByteStateJob { Components = _groupWithInstancedByteComponent.Components, StateToCheckFor = 0 }.Schedule(_groupWithInstancedByteComponent.Length, 64, inputDeps)); } else { FillStatesToCheckFor(); return(new CountMultipleInstancedByteStatesJob { Components = _groupWithInstancedByteComponent.Components, StatesToCheckFor = _statesToCheckFor }.Schedule(_groupWithInstancedByteComponent.Length, 64, inputDeps)); } case TestMethod.AddRemoveInstancedComponent: return(new CountExistingComponentsJob { }.Schedule(_groupWithInstancedBinaryComponent.Length, 64, inputDeps)); case TestMethod.AddRemoveSharedComponent: return(new CountExistingComponentsJob { }.Schedule(_groupWithSharedBinaryComponent.Length, 64, inputDeps)); case TestMethod.SetValueSharedComponentForEachFilter: var uniques = new List <SharedByteState>(); EntityManager.GetAllUniqueSharedComponentDatas(uniques); var filter = _byteStateGroup.CreateForEachFilter(uniques); for (int i = 0; i < filter.Length; i++) { if (_config.InterestingStateCount > uniques[i].State) { var interestingCount = _byteStateGroup.GetEntityArray(filter, i).Length; var forEachHandle = new CountExistingComponentsJob { }.Schedule(interestingCount, 64, inputDeps); filter.Dispose(); return(forEachHandle); } } filter.Dispose(); return(inputDeps); case TestMethod.SetValueSharedComponentSetFilter: if (_config.InterestingStateCount == 1) { var handle = ScheduleCountForFilterWithState(0, inputDeps); _byteStateGroup.ResetFilter(); return(handle); } else { var filterHandles = new NativeList <JobHandle>(_config.InterestingStateCount, Allocator.Temp); for (int i = 0; i < _config.InterestingStateCount; i++) { filterHandles.Add(ScheduleCountForFilterWithState(i, inputDeps)); } var combinedFilterHandles = JobHandle.CombineDependencies(filterHandles); _byteStateGroup.ResetFilter(); filterHandles.Dispose(); } return(inputDeps); case TestMethod.SetValueSharedComponentNoFilter: var length = _byteStateGroup.CalculateLength(); if (length > 0) { if (_config.InterestingStateCount == 1) { return(new CountSpecificSharedByteStateJob { Components = _byteStateGroup.GetSharedComponentDataArray <SharedByteState>(), StateToCheckFor = 0 }.Schedule(length, 64, inputDeps)); } else { FillStatesToCheckFor(); return(new CountMultipleSharedByteStatesJob { Components = _byteStateGroup.GetSharedComponentDataArray <SharedByteState>(), StatesToCheckFor = _statesToCheckFor }.Schedule(length, 64, inputDeps)); } } return(inputDeps); default: return(inputDeps); } }
protected override JobHandle OnUpdate(JobHandle inputDeps) { UnityEngine.Profiling.Profiler.BeginSample("System Init"); currentCellDictionary++; if (currentCellDictionary >= cellEntityTypeDictionaryArray.Length) { currentCellDictionary = 0; } //Make sure we cleared all the hash maps allClearCellsJobHandle.Complete(); uniqueEntityTypes.Clear(); EntityManager.GetAllUniqueSharedComponentDatas(uniqueEntityTypes); entityTypeList.Clear(); subsetEntityDictionary.Clear(); subsetMinMaxDataDictionary.Clear(); fillCellJobHandleDictionary.Clear(); JobHandle allBoundGroupDependencies = boundDataGroup.GetDependency(); UnityEngine.Profiling.Profiler.EndSample(); UnityEngine.Profiling.Profiler.BeginSample("FillJobSetup"); JobHandle allocateCellJobDependency = allClearCellsJobHandle; JobHandle allocateCellJobHandle = new JobHandle(); EntityArray[] subsetEntityArrayArray = new EntityArray[uniqueEntityTypes.Count]; ComponentDataArray <EntityBoundMinMaxData>[] subsetMinMaxDataArrayArray = new ComponentDataArray <EntityBoundMinMaxData> [uniqueEntityTypes.Count]; //create the hashMaps if needed and get the subset arrays we will use UnityEngine.Profiling.Profiler.BeginSample("GetEntityArray"); ForEachComponentGroupFilter boundDataforEachFilter = boundDataGroup.CreateForEachFilter(uniqueEntityTypes); for (int i = 0; i != uniqueEntityTypes.Count; i++) { subsetEntityArrayArray[i] = boundDataGroup.GetEntityArray(boundDataforEachFilter, i); subsetMinMaxDataArrayArray[i] = boundDataGroup.GetComponentDataArray <EntityBoundMinMaxData>(boundDataforEachFilter, i); if (subsetEntityArrayArray[i].Length != 0) { CreateCellHashMap(uniqueEntityTypes[i].entityType); } } boundDataforEachFilter.Dispose(); UnityEngine.Profiling.Profiler.EndSample(); //set the cells capacity now UnityEngine.Profiling.Profiler.BeginSample("Resize Hash Map"); for (int i = 0; i != uniqueEntityTypes.Count; i++) { EntityTypeData entityTypeData = uniqueEntityTypes[i]; EntityArray subsetEntityArray = subsetEntityArrayArray[i]; if (subsetEntityArray.Length == 0) { continue; } NativeMultiHashMap <int, HashMapData> tmpOutputCell = cellEntityTypeDictionary[entityTypeData.entityType]; //TODO: Test the memory usage //We are setting the capacity really high to not run out of space while running our jobs if (tmpOutputCell.Capacity < subsetEntityArray.Length * 10) { AllocateCellsJob allocateCellJob = new AllocateCellsJob { outputCells = tmpOutputCell, capacityWanted = subsetEntityArray.Length * 20, }; allocateCellJobHandle = JobHandle.CombineDependencies(allocateCellJob.Schedule(allocateCellJobDependency), allocateCellJobHandle); } } UnityEngine.Profiling.Profiler.EndSample(); JobHandle fillCellJobDependency = JobHandle.CombineDependencies(inputDeps, allBoundGroupDependencies, allocateCellJobHandle); for (int i = 0; i != uniqueEntityTypes.Count; i++) { EntityTypeData entityTypeData = uniqueEntityTypes[i]; EntityArray subsetEntityArray = subsetEntityArrayArray[i]; ComponentDataArray <EntityBoundMinMaxData> subsetMinMaxDataArray = subsetMinMaxDataArrayArray[i]; if (subsetEntityArray.Length == 0) { continue; } NativeMultiHashMap <int, HashMapData> .Concurrent tmpOutputCell = cellEntityTypeDictionary[entityTypeData.entityType]; float3 tmpOutputCellSize = cellSizeEntityDictionary[entityTypeData.entityType]; UnityEngine.Profiling.Profiler.BeginSample("Allocate tmp Array"); NativeArray <Entity> subsetEntityArrayOutput = new NativeArray <Entity>(subsetEntityArray.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); NativeArray <EntityBoundMinMaxData> subsetMinMaxDataArrayOutput = new NativeArray <EntityBoundMinMaxData>(subsetEntityArray.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); UnityEngine.Profiling.Profiler.EndSample(); FillCellJob fillCellJob = new FillCellJob { entityArray = subsetEntityArray, entityBoundMinMaxDataArray = subsetMinMaxDataArray, entityArrayOutput = subsetEntityArrayOutput, entityBoundMinMaxDataArrayOutput = subsetMinMaxDataArrayOutput, outputCells = tmpOutputCell, cellSizes = tmpOutputCellSize, }; JobHandle previousFillJobDependency; boundDataGroup.SetFilter(entityTypeData); JobHandle jobDependency = JobHandle.CombineDependencies(fillCellJobDependency, boundDataGroup.GetDependency()); if (fillCellJobHandleDictionary.TryGetValue(entityTypeData.entityType, out previousFillJobDependency)) { jobDependency = JobHandle.CombineDependencies(jobDependency, previousFillJobDependency); } JobHandle fillCellJobHandle = fillCellJob.Schedule(subsetEntityArray.Length, MonoBehaviourECSBridge.Instance.GetJobBatchCount(subsetEntityArray.Length), jobDependency); entityTypeList.Add(entityTypeData.entityType); subsetEntityDictionary.Add(entityTypeData.entityType, subsetEntityArrayOutput); subsetMinMaxDataDictionary.Add(entityTypeData.entityType, subsetMinMaxDataArrayOutput); fillCellJobHandleDictionary.Add(entityTypeData.entityType, fillCellJobHandle); } UnityEngine.Profiling.Profiler.EndSample(); if (fillCellJobHandleDictionary.Count == 0) { return(inputDeps); } UnityEngine.Profiling.Profiler.BeginSample("CollisionJobSetup"); JobHandle previousCollisionJobHandle = new JobHandle(); previousCollisionJobHandle = scheduleCollisionJob(EntityTypeData.EntityType.Asteroid, EntityTypeData.EntityType.Bolt, previousCollisionJobHandle); previousCollisionJobHandle = scheduleCollisionJob(EntityTypeData.EntityType.Asteroid, EntityTypeData.EntityType.EnemyShip, previousCollisionJobHandle); previousCollisionJobHandle = scheduleCollisionJob(EntityTypeData.EntityType.Asteroid, EntityTypeData.EntityType.AllyShip, previousCollisionJobHandle); previousCollisionJobHandle = scheduleCollisionJob(EntityTypeData.EntityType.EnemyShip, EntityTypeData.EntityType.Bolt, previousCollisionJobHandle); previousCollisionJobHandle = scheduleCollisionJob(EntityTypeData.EntityType.EnemyShip, EntityTypeData.EntityType.AllyShip, previousCollisionJobHandle); previousCollisionJobHandle = scheduleCollisionJob(EntityTypeData.EntityType.AllyShip, EntityTypeData.EntityType.Bolt, previousCollisionJobHandle); previousCollisionJobHandle = scheduleCollisionJob(EntityTypeData.EntityType.PlayerShip, EntityTypeData.EntityType.Asteroid, previousCollisionJobHandle); previousCollisionJobHandle = scheduleCollisionJob(EntityTypeData.EntityType.PlayerShip, EntityTypeData.EntityType.Bolt, previousCollisionJobHandle); previousCollisionJobHandle = scheduleCollisionJob(EntityTypeData.EntityType.PlayerShip, EntityTypeData.EntityType.EnemyShip, previousCollisionJobHandle); UnityEngine.Profiling.Profiler.EndSample(); JobHandle.ScheduleBatchedJobs(); UnityEngine.Profiling.Profiler.BeginSample("DisposeJobSetup"); JobHandle jobHandleToReturn = new JobHandle(); List <JobHandle> clearCellJobHandleList = new List <JobHandle>(entityTypeList.Count); for (int i = 0; i < entityTypeList.Count; i++) { if (subsetEntityDictionary.ContainsKey(entityTypeList[i])) { jobHandleToReturn = JobHandle.CombineDependencies(fillCellJobHandleDictionary[entityTypeList[i]], jobHandleToReturn); ClearCellsJob clearCellsJob = new ClearCellsJob { entityArray = subsetEntityDictionary[entityTypeList[i]], entityBoundMinMaxDataArray = subsetMinMaxDataDictionary[entityTypeList[i]], outputCells = cellEntityTypeDictionary[entityTypeList[i]], }; JobHandle clearCellsJobHandle = clearCellsJob.Schedule(JobHandle.CombineDependencies(fillCellJobHandleDictionary[entityTypeList[i]], previousCollisionJobHandle)); clearCellJobHandleList.Add(clearCellsJobHandle); } } jobHandleToReturn = JobHandle.CombineDependencies(previousCollisionJobHandle, jobHandleToReturn); UnityEngine.Profiling.Profiler.EndSample(); NativeArray <JobHandle> clearCellsJobHandleArray = new NativeArray <JobHandle>(clearCellJobHandleList.ToArray(), Allocator.Temp); allClearCellsJobHandle = JobHandle.CombineDependencies(clearCellsJobHandleArray); clearCellsJobHandleArray.Dispose(); return(jobHandleToReturn); }
//----------------------------------------------------------------------------- protected override void OnUpdate() { // We want to iterate over all unique MeshInstanceRenderer shared component data, // that are attached to any entities in the world EntityManager.GetAllUniqueSharedComponentDatas(m_CacheduniqueRendererTypes); var forEachFilter = m_InstanceRendererGroup.CreateForEachFilter(m_CacheduniqueRendererTypes); int drawIdx = 0; for (int i = 0; i != m_CacheduniqueRendererTypes.Count; i++) { // For each unique MeshInstanceRenderer data, we want to get all entities with a TransformMatrix // SharedComponentData gurantees that all those entities are packed togehter in a chunk with linear memory layout. // As a result the copy of the matrices out is internally done via memcpy. var renderer = m_CacheduniqueRendererTypes[i]; var transforms = m_InstanceRendererGroup.GetComponentDataArray <TransformMatrix>(forEachFilter, i); var selection = m_InstanceRendererGroup.GetComponentDataArray <Selection>(forEachFilter, i); // Graphics.DrawMeshInstanced has a set of limitations that are not optimal for working with ECS. // Specifically: // * No way to push the matrices from a job // * no NativeArray API, currently uses Matrix4x4[] // As a result this code is not yet jobified. // We are planning to adjust this API to make it more efficient for this use case. // For now, we have to copy our data into Matrix4x4[] with a specific upper limit of how many instances we can render in one batch. // So we just have a for loop here, representing each Graphics.DrawMeshInstanced batch int beginIndex = 0; while (beginIndex < transforms.Length) { // Copy Matrices int length = math.min(m_MatricesArray.Length, transforms.Length - beginIndex); CopyMatrices(transforms, beginIndex, length, m_MatricesArray); for (int j = 0; j < m_MatricesArray.Length; ++j) { m_MatricesArray[j].m03 += Main.ActiveInitParams.m_cellSize / 2; m_MatricesArray[j].m23 += Main.ActiveInitParams.m_cellSize / 2; } if (drawIdx + 1 >= m_ComputeBuffers.Count) { var computeBuffer = new ComputeBuffer(512, 3 * sizeof(float)); m_ComputeBuffers.Add(computeBuffer); var material = new Material(renderer.material); m_Materials.Add(material); } for (int x = 0; x < length; ++x) { m_Colors[x] = selection[beginIndex + x].Value == 1 ? new Vector3(0.5f, 1f, 0.5f) : new Vector3(0.5f, 0.5f, 1f); } m_ComputeBuffers[drawIdx].SetData(m_Colors, 0, 0, length); m_Materials[drawIdx].SetBuffer("velocityBuffer", m_ComputeBuffers[drawIdx]); // !!! This will draw all meshes using the last material. Probably need an array of materials. Graphics.DrawMeshInstanced(renderer.mesh, renderer.subMesh, m_Materials[drawIdx], m_MatricesArray, length, null, renderer.castShadows, renderer.receiveShadows); drawIdx++; beginIndex += length; } } m_CacheduniqueRendererTypes.Clear(); forEachFilter.Dispose(); }