Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 60 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ rustc-hash = "2"
hashbrown = "0.17"
num_enum = "0.7.6"
enum_dispatch = "0.3.13"
enumset = "1.1.14"
strum = { version = "0.28", features = ["derive"] }
unicode_names2 = "3.1.0"
unicode-script = "0.5"
Expand Down
1 change: 1 addition & 0 deletions crates/neomacs-display-runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ tracing.workspace = true
tracing-subscriber.workspace = true
serde_json.workspace = true
strum.workspace = true
enumset.workspace = true
num_enum.workspace = true
thiserror.workspace = true
bitflags.workspace = true
Expand Down
42 changes: 4 additions & 38 deletions crates/neomacs-display-runtime/src/render_thread/frame_sched.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ macro_rules! demand_reasons {
// Interface variants/fields defined by the scheduling plan; consumed as
// later stages migrate effects onto the coordinator.
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, enumset::EnumSetType)]
#[enumset(no_super_impls, no_ops)]
pub(crate) enum DemandReason {
$($(#[$variant_meta])* $variant,)+
}
Expand Down Expand Up @@ -221,43 +222,8 @@ impl DemandReason {

/// Set of [`DemandReason`]s, carried by value on a [`FramePlan`] so a frame can
/// be attributed to what asked for it ("why did this present happen?").
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub(crate) struct DemandReasonSet(u32);

impl DemandReasonSet {
pub(crate) const fn empty() -> Self {
DemandReasonSet(0)
}

fn insert(&mut self, reason: DemandReason) {
self.0 |= 1 << reason.index();
}

pub(crate) fn contains(self, reason: DemandReason) -> bool {
self.0 & (1 << reason.index()) != 0
}

pub(crate) fn is_empty(self) -> bool {
self.0 == 0
}

/// Reasons in [`DemandReason::ALL`] order.
pub(crate) fn iter(self) -> impl Iterator<Item = DemandReason> {
DemandReason::ALL
.into_iter()
.filter(move |r| self.contains(*r))
}
}

impl FromIterator<DemandReason> for DemandReasonSet {
fn from_iter<I: IntoIterator<Item = DemandReason>>(iter: I) -> Self {
let mut set = DemandReasonSet::empty();
for reason in iter {
set.insert(reason);
}
set
}
}
/// Iteration follows declaration order, matching [`DemandReason::ALL`].
pub(crate) type DemandReasonSet = enumset::EnumSet<DemandReason>;

Comment on lines +226 to 227
/// A declaration that pixels need to change, with reason, scope, and cadence.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1253,3 +1253,20 @@ fn servicing_twice_at_one_timestamp_is_idempotent() {
"nothing ripe survives one service"
);
}

#[test]
fn demand_reason_sets_deduplicate_and_iterate_in_declaration_order() {
let reasons: DemandReasonSet = DemandReason::ALL
.into_iter()
.rev()
.chain(DemandReason::ALL)
.collect();
assert!(reasons.iter().eq(DemandReason::ALL));
for reason in DemandReason::ALL {
assert!(reasons.contains(reason), "missing {reason:?}");
}
let empty = DemandReasonSet::default();
assert!(empty.is_empty());
assert!(empty.iter().next().is_none());
assert!(!empty.contains(DemandReason::EditorCommit));
}
Loading