passes.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. use anymap::AnyMap;
  2. use parking_lot::RwLock;
  3. use rustc_hash::{FxHashMap, FxHashSet};
  4. use shipyard::{
  5. BorrowInfo, Component, IntoBorrow, IntoWorkloadSystem, Unique, UniqueView, View,
  6. WorkloadSystem, World,
  7. };
  8. use std::any::{Any, TypeId};
  9. use std::collections::BTreeMap;
  10. use std::marker::PhantomData;
  11. use std::sync::Arc;
  12. use crate::node::FromAnyValue;
  13. use crate::node_ref::{NodeMaskBuilder, NodeView};
  14. use crate::real_dom::{DirtyNodesResult, SendAnyMapWrapper};
  15. use crate::tree::{TreeMut, TreeRef, TreeRefView};
  16. use crate::{FxDashSet, SendAnyMap};
  17. use crate::{NodeId, NodeMask};
  18. #[derive(Default)]
  19. struct DirtyNodes {
  20. passes_dirty: Vec<u64>,
  21. }
  22. impl DirtyNodes {
  23. pub fn add_node(&mut self, node_id: NodeId) {
  24. let node_id = node_id.uindex();
  25. let index = node_id / 64;
  26. let bit = node_id % 64;
  27. let encoded = 1 << bit;
  28. if let Some(passes) = self.passes_dirty.get_mut(index) {
  29. *passes |= encoded;
  30. } else {
  31. self.passes_dirty.resize(index + 1, 0);
  32. self.passes_dirty[index] |= encoded;
  33. }
  34. }
  35. pub fn is_empty(&self) -> bool {
  36. self.passes_dirty.iter().all(|dirty| *dirty == 0)
  37. }
  38. pub fn pop(&mut self) -> Option<usize> {
  39. let index = self.passes_dirty.iter().position(|dirty| *dirty != 0)?;
  40. let passes = self.passes_dirty[index];
  41. let node_id = passes.trailing_zeros();
  42. let encoded = 1 << node_id;
  43. self.passes_dirty[index] &= !encoded;
  44. Some((index * 64) + node_id as usize)
  45. }
  46. }
  47. #[derive(Clone, Unique)]
  48. pub struct DirtyNodeStates {
  49. dirty: Arc<FxHashMap<TypeId, RwLock<BTreeMap<u16, DirtyNodes>>>>,
  50. }
  51. impl DirtyNodeStates {
  52. pub fn with_passes(passes: impl Iterator<Item = TypeId>) -> Self {
  53. Self {
  54. dirty: Arc::new(
  55. passes
  56. .map(|pass| (pass, RwLock::new(BTreeMap::new())))
  57. .collect(),
  58. ),
  59. }
  60. }
  61. pub fn insert(&self, pass_id: TypeId, node_id: NodeId, height: u16) {
  62. if let Some(btree) = self.dirty.get(&pass_id) {
  63. let mut write = btree.write();
  64. if let Some(entry) = write.get_mut(&height) {
  65. entry.add_node(node_id);
  66. } else {
  67. let mut entry = DirtyNodes::default();
  68. entry.add_node(node_id);
  69. write.insert(height, entry);
  70. }
  71. }
  72. }
  73. fn pop_front(&self, pass_id: TypeId) -> Option<(u16, usize)> {
  74. let mut values = self.dirty.get(&pass_id)?.write();
  75. let mut value = values.first_entry()?;
  76. let height = *value.key();
  77. let ids = value.get_mut();
  78. let id = ids.pop()?;
  79. if ids.is_empty() {
  80. value.remove_entry();
  81. }
  82. Some((height, id))
  83. }
  84. fn pop_back(&self, pass_id: TypeId) -> Option<(u16, usize)> {
  85. let mut values = self.dirty.get(&pass_id)?.write();
  86. let mut value = values.last_entry()?;
  87. let height = *value.key();
  88. let ids = value.get_mut();
  89. let id = ids.pop()?;
  90. if ids.is_empty() {
  91. value.remove_entry();
  92. }
  93. Some((height, id))
  94. }
  95. }
  96. pub trait State<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
  97. /// This is a tuple of (T: Pass, ..) of states read from the parent required to run this pass
  98. type ParentDependencies: Dependancy;
  99. /// This is a tuple of (T: Pass, ..) of states read from the children required to run this pass
  100. type ChildDependencies: Dependancy;
  101. /// This is a tuple of (T: Pass, ..) of states read from the node required to run this pass
  102. type NodeDependencies: Dependancy;
  103. /// A tuple of all the dependencies combined
  104. type CombinedDependencies: Dependancy;
  105. /// This is a mask of what aspects of the node are required to run this pass
  106. const NODE_MASK: NodeMaskBuilder<'static>;
  107. /// Update this state in a node, returns if the state was updated
  108. fn update<'a>(
  109. &mut self,
  110. node_view: NodeView<V>,
  111. node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
  112. parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
  113. children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
  114. context: &SendAnyMap,
  115. ) -> bool;
  116. /// Create a new instance of this state
  117. fn create<'a>(
  118. node_view: NodeView<V>,
  119. node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
  120. parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
  121. children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
  122. context: &SendAnyMap,
  123. ) -> Self;
  124. /// Create a workload system for this state
  125. fn workload_system(dependants: FxHashSet<TypeId>) -> WorkloadSystem;
  126. }
  127. pub struct RunPassView<'a> {
  128. type_id: TypeId,
  129. dependants: FxHashSet<TypeId>,
  130. pass_direction: PassDirection,
  131. tree: TreeRefView<'a>,
  132. nodes_updated: UniqueView<'a, DirtyNodesResult>,
  133. dirty: UniqueView<'a, DirtyNodeStates>,
  134. ctx: UniqueView<'a, SendAnyMapWrapper>,
  135. }
  136. impl<'a> RunPassView<'a> {
  137. pub fn borrow(
  138. type_id: TypeId,
  139. dependants: FxHashSet<TypeId>,
  140. pass_direction: PassDirection,
  141. world: &'a World,
  142. ) -> Self {
  143. Self {
  144. type_id,
  145. dependants,
  146. pass_direction,
  147. tree: world.borrow().unwrap(),
  148. nodes_updated: world.borrow().unwrap(),
  149. dirty: world.borrow().unwrap(),
  150. ctx: world.borrow().unwrap(),
  151. }
  152. }
  153. }
  154. pub fn run_pass(view: RunPassView, mut update_node: impl FnMut(NodeId, &SendAnyMap) -> bool) {
  155. let RunPassView {
  156. type_id,
  157. dependants,
  158. pass_direction,
  159. tree,
  160. nodes_updated,
  161. dirty,
  162. ctx,
  163. } = view;
  164. let ctx = ctx.as_ref();
  165. match pass_direction {
  166. PassDirection::ParentToChild => {
  167. while let Some((height, id)) = dirty.pop_front(type_id) {
  168. let id = tree.id_at(id).unwrap();
  169. if (update_node)(id, ctx) {
  170. nodes_updated.insert(id);
  171. for id in tree.children_ids(id).unwrap() {
  172. for dependant in &dependants {
  173. dirty.insert(*dependant, id, height + 1);
  174. }
  175. }
  176. }
  177. }
  178. }
  179. PassDirection::ChildToParent => {
  180. while let Some((height, id)) = dirty.pop_back(type_id) {
  181. let id = tree.id_at(id).unwrap();
  182. if (update_node)(id, ctx) {
  183. nodes_updated.insert(id);
  184. if let Some(id) = tree.parent_id(id) {
  185. for dependant in &dependants {
  186. dirty.insert(*dependant, id, height - 1);
  187. }
  188. }
  189. }
  190. }
  191. }
  192. PassDirection::AnyOrder => {
  193. while let Some((height, id)) = dirty.pop_back(type_id) {
  194. let id = tree.id_at(id).unwrap();
  195. if (update_node)(id, ctx) {
  196. nodes_updated.insert(id);
  197. for dependant in &dependants {
  198. dirty.insert(*dependant, id, height);
  199. }
  200. }
  201. }
  202. }
  203. }
  204. }
  205. pub trait AnyState<V: FromAnyValue + Send + Sync = ()>: State<V> {
  206. fn to_type_erased() -> TypeErasedPass<V>
  207. where
  208. Self: Sized,
  209. {
  210. let node_mask = Self::NODE_MASK.build();
  211. TypeErasedPass {
  212. this_type_id: TypeId::of::<Self>(),
  213. combined_dependancy_type_ids: Self::all_dependanices().iter().copied().collect(),
  214. parent_dependant: !Self::parent_type_ids().is_empty(),
  215. child_dependant: !Self::child_type_ids().is_empty(),
  216. dependants: FxHashSet::default(),
  217. mask: node_mask,
  218. pass_direction: Self::pass_direction(),
  219. workload: Self::workload_system,
  220. phantom: PhantomData,
  221. }
  222. }
  223. fn parent_type_ids() -> Box<[TypeId]> {
  224. Self::ParentDependencies::type_ids()
  225. }
  226. fn child_type_ids() -> Box<[TypeId]> {
  227. Self::ChildDependencies::type_ids()
  228. }
  229. fn node_type_ids() -> Box<[TypeId]> {
  230. Self::NodeDependencies::type_ids()
  231. }
  232. fn all_dependanices() -> Box<[TypeId]> {
  233. let mut dependencies = Self::parent_type_ids().to_vec();
  234. dependencies.extend(Self::child_type_ids().iter());
  235. dependencies.extend(Self::node_type_ids().iter());
  236. dependencies.into_boxed_slice()
  237. }
  238. fn pass_direction() -> PassDirection {
  239. if Self::child_type_ids()
  240. .iter()
  241. .any(|type_id| *type_id == TypeId::of::<Self>())
  242. {
  243. PassDirection::ChildToParent
  244. } else if Self::parent_type_ids()
  245. .iter()
  246. .any(|type_id| *type_id == TypeId::of::<Self>())
  247. {
  248. PassDirection::ParentToChild
  249. } else {
  250. PassDirection::AnyOrder
  251. }
  252. }
  253. }
  254. pub struct TypeErasedPass<V: FromAnyValue + Send = ()> {
  255. pub(crate) this_type_id: TypeId,
  256. pub(crate) parent_dependant: bool,
  257. pub(crate) child_dependant: bool,
  258. pub(crate) combined_dependancy_type_ids: FxHashSet<TypeId>,
  259. pub(crate) dependants: FxHashSet<TypeId>,
  260. pub(crate) mask: NodeMask,
  261. pub(crate) workload: fn(FxHashSet<TypeId>) -> WorkloadSystem,
  262. pub(crate) pass_direction: PassDirection,
  263. phantom: PhantomData<V>,
  264. }
  265. #[derive(Debug)]
  266. pub enum PassDirection {
  267. ParentToChild,
  268. ChildToParent,
  269. AnyOrder,
  270. }
  271. pub trait AnyMapLike<'a> {
  272. fn get<T: Any + Sync + Send>(self) -> Option<&'a T>;
  273. }
  274. impl<'a> AnyMapLike<'a> for &'a AnyMap {
  275. fn get<T: Any + Sync + Send>(self) -> Option<&'a T> {
  276. self.get()
  277. }
  278. }
  279. impl<'a> AnyMapLike<'a> for &'a SendAnyMap {
  280. fn get<T: Any + Sync + Send>(self) -> Option<&'a T> {
  281. todo!()
  282. }
  283. }
  284. pub trait Dependancy {
  285. type ElementBorrowed<'a>: IntoBorrow + BorrowInfo;
  286. fn type_ids() -> Box<[TypeId]> {
  287. Box::new([])
  288. }
  289. }
  290. macro_rules! impl_dependancy {
  291. ($($t:ident),*) => {
  292. impl< $($t: Send + Sync + Component),* > Dependancy for ($($t,)*) {
  293. type ElementBorrowed<'a> = ($(View<'a, $t>,)*);
  294. fn type_ids() -> Box<[TypeId]> {
  295. Box::new([$(TypeId::of::<$t>()),*])
  296. }
  297. }
  298. };
  299. }
  300. impl_dependancy!();
  301. impl_dependancy!(A);
  302. impl_dependancy!(A, B);
  303. impl_dependancy!(A, B, C);
  304. impl_dependancy!(A, B, C, D);
  305. impl_dependancy!(A, B, C, D, E);
  306. impl_dependancy!(A, B, C, D, E, F);
  307. impl_dependancy!(A, B, C, D, E, F, G);
  308. impl_dependancy!(A, B, C, D, E, F, G, H);
  309. impl_dependancy!(A, B, C, D, E, F, G, H, I);
  310. impl_dependancy!(A, B, C, D, E, F, G, H, I, J);