Cache bars: cached frames show at 1/3 resolution (#595)

The cache bars count the frames of `shown_series`, which rebuilds the
series from the frame key's scale in thousandths (333 -> 0.333). The key's
`opts` hashed the render options with the f64 scale, and the frames had been
rendered at 0.3333..., so the series never matched and the bars stayed empty
at Third (and any resolution that isn't a whole number of thousandths, such
as Custom 1/7).

`opts_hash` now hashes the scale rounded to the key's thousandths, which the
key carries anyway.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
This commit is contained in:
Claude committed 2026-10-10 19:32:18 +00:00
1 parent e96638093c
commit fbe0f7e1ce
2 files changed
+24 -1

No files matched your search

+4 -1
View File
@@ -280,8 +280,11 @@ fn comp_content_with(project: &Project, comp: ItemId, addr: impl Fn(ItemId, &Arc
h.finish()
}
/// Hash of render options (part of [`FrameKey`] and of the disk key).
/// Hash of render options (part of [`FrameKey`] and of the disk key). The scale counts as the
/// key's thousandths ([`FrameKey::scale`]): a series rebuilt from the key (the cache bars) has
/// the same options as the frames rendered at 1/3 = 0.333… (#595).
pub fn opts_hash(o: &RenderOpts) -> u64 {
let o = RenderOpts { scale: (o.scale * 1000.0).round() / 1000.0, ..*o };
let mut h = disk_cache::Hash128::default();
h.write(format!("{o:?}").as_bytes());
h.finish() as u64
+20
View File
@@ -125,3 +125,23 @@ fn prefetch_waits_while_edits_keep_coming() {
let series = h.state().shown_series(ItemId(c));
assert!(h.state().frames.cached_frames(&series).len() > 1, "prefetch resumed");
}
/// #595: at Third (and other resolutions that aren't a whole number of thousandths) the cache
/// bars find the rendered frames. The series they count was rebuilt from the frame key's scale
/// (333 → 0.333), whose render options hashed apart from the frames rendered at 0.3333….
#[test]
fn cached_frames_are_counted_at_one_third_resolution() {
use effectcraft_ui_egui::state::Resolution;
for res in [Resolution::Third, Resolution::Custom(7)] {
let mut s = Session::default();
let c = s.execute("comp.new", json!({"name": "Third", "width": 64, "height": 36, "duration": 1})).unwrap()["comp"].as_u64().unwrap();
s.execute("layer.newSolid", json!({"color": "#3080ff"})).unwrap();
let mut h = Harness::builder().with_size(egui::vec2(1400.0, 900.0)).build_eframe(|_| EffectcraftApp::new(s));
h.state_mut().ui.viewer.res = res;
settle(&mut h);
let series = h.state().shown_series(ItemId(c));
assert_eq!(series.scale, (res.scale(1.0, 1.0) * 1000.0).round() as u32, "{res:?}");
assert!(shown_cached(&h, c), "{res:?}: the shown frame counts as cached");
assert!(!h.state().frames.cached_frames(&series).is_empty(), "{res:?}");
}
}