Mirror of Svelto.ECS because we're a fan of it
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

226 行
10KB

  1. #if UNITY_NATIVE
  2. using System;
  3. using DBC.ECS;
  4. using Svelto.Common;
  5. using Svelto.DataStructures;
  6. using Svelto.ECS.Internal;
  7. using Svelto.ECS.Native;
  8. namespace Svelto.ECS
  9. {
  10. public partial class EnginesRoot
  11. {
  12. NativeEntityRemove ProvideNativeEntityRemoveQueue<T>(string memberName) where T : IEntityDescriptor, new()
  13. {
  14. //DBC.ECS.Check.Require(EntityDescriptorTemplate<T>.descriptor.isUnmanaged(), "can't remove entities with not native types");
  15. //todo: remove operation array and store entity descriptor hash in the return value
  16. //todo I maybe able to provide a _nativeSwap.SwapEntity<entityDescriptor>
  17. //todo make this work with base descriptors too
  18. var descriptorComponentsToRemove = EntityDescriptorTemplate<T>.descriptor.componentsToBuild;
  19. _nativeRemoveOperations.Add(new NativeOperationRemove(
  20. descriptorComponentsToRemove, TypeCache<T>.type
  21. , memberName));
  22. return new NativeEntityRemove(_nativeRemoveOperationQueue, _nativeRemoveOperations.count - 1);
  23. }
  24. NativeEntitySwap ProvideNativeEntitySwapQueue<T>(string memberName) where T : IEntityDescriptor, new()
  25. {
  26. // DBC.ECS.Check.Require(EntityDescriptorTemplate<T>.descriptor.isUnmanaged(), "can't swap entities with not native types");
  27. //todo: remove operation array and store entity descriptor hash in the return value
  28. _nativeSwapOperations.Add(new NativeOperationSwap(EntityDescriptorTemplate<T>.descriptor.componentsToBuild
  29. , TypeCache<T>.type, memberName));
  30. return new NativeEntitySwap(_nativeSwapOperationQueue, _nativeSwapOperations.count - 1);
  31. }
  32. NativeEntityFactory ProvideNativeEntityFactoryQueue<T>(string caller) where T : IEntityDescriptor, new()
  33. {
  34. DBC.ECS.Check.Require(EntityDescriptorTemplate<T>.descriptor.IsUnmanaged()
  35. , "can't build entities with not native types");
  36. DBC.ECS.Check.Require(string.IsNullOrEmpty(caller) == false, "an invalid caller has been provided");
  37. //todo: remove operation array and store entity descriptor hash in the return value
  38. _nativeAddOperations.Add(new NativeOperationBuild(EntityDescriptorTemplate<T>.descriptor.componentsToBuild
  39. , TypeCache<T>.type, caller));
  40. return new NativeEntityFactory(_nativeAddOperationQueue, _nativeAddOperations.count - 1, _entityLocator);
  41. }
  42. void FlushNativeOperations(in PlatformProfiler profiler)
  43. {
  44. using (profiler.Sample("Native Remove Operations"))
  45. {
  46. var removeBuffersCount = _nativeRemoveOperationQueue.count;
  47. //todo, I don't like that this scans all the queues even if they are empty
  48. for (int i = 0; i < removeBuffersCount; i++)
  49. {
  50. ref var buffer = ref _nativeRemoveOperationQueue.GetBag(i);
  51. while (buffer.IsEmpty() == false)
  52. {
  53. var componentsIndex = buffer.Dequeue<uint>();
  54. var entityEGID = buffer.Dequeue<EGID>();
  55. ref NativeOperationRemove nativeRemoveOperation = ref _nativeRemoveOperations[componentsIndex];
  56. CheckRemoveEntityID(entityEGID, nativeRemoveOperation.entityDescriptorType
  57. , nativeRemoveOperation.caller);
  58. QueueRemoveEntityOperation(
  59. entityEGID, FindRealComponents(entityEGID, nativeRemoveOperation.components)
  60. , nativeRemoveOperation.caller);
  61. }
  62. }
  63. }
  64. using (profiler.Sample("Native Swap Operations"))
  65. {
  66. var swapBuffersCount = _nativeSwapOperationQueue.count;
  67. for (int i = 0; i < swapBuffersCount; i++)
  68. {
  69. ref var buffer = ref _nativeSwapOperationQueue.GetBag(i);
  70. while (buffer.IsEmpty() == false)
  71. {
  72. var componentsIndex = buffer.Dequeue<uint>();
  73. var entityEGID = buffer.Dequeue<DoubleEGID>();
  74. ref var nativeSwapOperation = ref _nativeSwapOperations[componentsIndex];
  75. CheckSwapEntityID(entityEGID.@from, entityEGID.to, nativeSwapOperation.entityDescriptorType
  76. , nativeSwapOperation.caller);
  77. QueueSwapEntityOperation(entityEGID.@from, entityEGID.to
  78. , FindRealComponents(entityEGID.@from, nativeSwapOperation.components)
  79. , nativeSwapOperation.caller);
  80. }
  81. }
  82. }
  83. //todo: it feels weird that these builds in the transient entities database while it could build directly to the final one
  84. using (profiler.Sample("Native Add Operations"))
  85. {
  86. var addBuffersCount = _nativeAddOperationQueue.count;
  87. for (int i = 0; i < addBuffersCount; i++)
  88. {
  89. ref var buffer = ref _nativeAddOperationQueue.GetBag(i);
  90. //todo: I don't like to iterate a constant number of buffer and skip the empty ones
  91. while (buffer.IsEmpty() == false)
  92. {
  93. var componentsIndex = buffer.Dequeue<uint>();
  94. var egid = buffer.Dequeue<EGID>();
  95. var reference = buffer.Dequeue<EntityReference>();
  96. var componentCounts = buffer.Dequeue<uint>();
  97. Check.Assert(egid.groupID.isInvalid == false
  98. , "invalid group detected, are you using new ExclusiveGroupStruct() instead of new ExclusiveGroup()?");
  99. ref var nativeOperation = ref _nativeAddOperations[componentsIndex];
  100. #if DEBUG && !PROFILE_SVELTO
  101. var entityDescriptorType = nativeOperation.entityDescriptorType;
  102. CheckAddEntityID(egid, entityDescriptorType, nativeOperation.caller);
  103. #endif
  104. _entityLocator.SetReference(reference, egid);
  105. //todo: I reckon is not necessary to carry the components array in the native operation, it's enough to know the descriptor type
  106. //however I guess this can work only if the type is hashed, which could be done with the burst type hash
  107. var dic = EntityFactory.BuildGroupedEntities(egid, _groupedEntityToAdd
  108. , nativeOperation.components, null
  109. #if DEBUG && !PROFILE_SVELTO
  110. , entityDescriptorType
  111. #endif
  112. );
  113. var init = new EntityInitializer(egid, dic, reference);
  114. //only called if Init is called on the initialized (there is something to init)
  115. while (componentCounts > 0)
  116. {
  117. componentCounts--;
  118. var typeID = buffer.Dequeue<uint>();
  119. IFiller componentBuilder = EntityComponentIDMap.GetBuilderFromID(typeID);
  120. //after the typeID, I expect the serialized component
  121. componentBuilder.FillFromByteArray(init, buffer);
  122. }
  123. }
  124. }
  125. }
  126. }
  127. void AllocateNativeOperations()
  128. {
  129. _nativeRemoveOperations = new FasterList<NativeOperationRemove>();
  130. _nativeSwapOperations = new FasterList<NativeOperationSwap>();
  131. _nativeAddOperations = new FasterList<NativeOperationBuild>();
  132. }
  133. FasterList<NativeOperationRemove> _nativeRemoveOperations;
  134. FasterList<NativeOperationSwap> _nativeSwapOperations;
  135. FasterList<NativeOperationBuild> _nativeAddOperations;
  136. readonly AtomicNativeBags _nativeAddOperationQueue;
  137. readonly AtomicNativeBags _nativeRemoveOperationQueue;
  138. readonly AtomicNativeBags _nativeSwapOperationQueue;
  139. }
  140. readonly struct DoubleEGID
  141. {
  142. internal readonly EGID from;
  143. internal readonly EGID to;
  144. public DoubleEGID(EGID from1, EGID to1)
  145. {
  146. from = from1;
  147. to = to1;
  148. }
  149. }
  150. readonly struct NativeOperationBuild
  151. {
  152. internal readonly IComponentBuilder[] components;
  153. internal readonly Type entityDescriptorType;
  154. internal readonly string caller;
  155. public NativeOperationBuild
  156. (IComponentBuilder[] descriptorComponentsToBuild, Type entityDescriptorType, string caller)
  157. {
  158. this.entityDescriptorType = entityDescriptorType;
  159. components = descriptorComponentsToBuild;
  160. this.caller = caller;
  161. }
  162. }
  163. readonly struct NativeOperationRemove
  164. {
  165. internal readonly IComponentBuilder[] components;
  166. internal readonly Type entityDescriptorType;
  167. internal readonly string caller;
  168. public NativeOperationRemove
  169. (IComponentBuilder[] descriptorComponentsToRemove, Type entityDescriptorType, string caller)
  170. {
  171. this.caller = caller;
  172. components = descriptorComponentsToRemove;
  173. this.entityDescriptorType = entityDescriptorType;
  174. }
  175. }
  176. readonly struct NativeOperationSwap
  177. {
  178. internal readonly IComponentBuilder[] components;
  179. internal readonly Type entityDescriptorType;
  180. internal readonly string caller;
  181. public NativeOperationSwap
  182. (IComponentBuilder[] descriptorComponentsToSwap, Type entityDescriptorType, string caller)
  183. {
  184. this.caller = caller;
  185. components = descriptorComponentsToSwap;
  186. this.entityDescriptorType = entityDescriptorType;
  187. }
  188. }
  189. }
  190. #endif