#3538: layer keys and render reads include OCIO files and a config's LUTs

This commit is contained in:
arnav-hiwarkar committed 2026-11-12 14:43:54 +05:30
1 parent ef137cb2ce
commit a700c5c8db
3 files changed
+59 -11

No files matched your search

+40
View File
@@ -186,3 +186,43 @@ fn an_overridden_lut_file_renders_again() {
write(&overridden, WHITE, 2_000);
assert_all(centre(&s), 1.0);
}
/// #3538: OCIO File Transform and a custom OCIO config (and the LUT it names) follow their files
/// through warm layer caches, and a render notes the config's LUT for the disk cache.
#[test]
fn ocio_files_render_again_from_warm_caches() {
let dir = tempfile::tempdir().unwrap();
let (lut, config, grade) = (dir.path().join("file.cube"), dir.path().join("config.ocio"), dir.path().join("luts/grade.cube"));
std::fs::create_dir_all(dir.path().join("luts")).unwrap();
write(&lut, BLACK, 1_000);
write(&grade, BLACK, 1_000);
let text = "ocio_profile_version: 2\nsearch_path: luts\nroles:\n scene_linear: lin\ncolorspaces:\n - !<ColorSpace>\n name: lin\n - !<ColorSpace>\n name: graded\n to_reference: !<FileTransform> {src: grade.cube, interpolation: linear}\n";
write(&config, text, 1_000);
let mut s = session(None);
let file = shot(&mut s, "OCIO File Transform", &[("file", json!(lut.to_string_lossy()))]);
let custom = shot(
&mut s,
"OCIO Color Space Transform",
&[("config", json!(1)), ("configFile", json!(config.to_string_lossy())), ("sourceName", json!("graded")), ("destinationName", json!("lin"))],
);
assert_all(colours(&s, file), 0.0);
assert_all(colours(&s, custom), 0.0);
// (the first key of a config's layer can't know the LUTs it names before it is read)
assert_all(colours(&s, custom), 0.0);
let misses = s.layer_cache.stats().misses;
assert_all(colours(&s, file), 0.0);
assert_all(colours(&s, custom), 0.0);
assert_eq!(s.layer_cache.stats().misses, misses, "unchanged files keep the cached layers");
let log = ReadLog::new();
let mut r = s.renderer(RenderOpts::default());
r.reads = Some(&log);
let _ = r.comp_frame(custom.1, Tick::ZERO);
let files = log.into_files();
assert!(files.get(&grade.to_string_lossy()).is_some(), "the render notes the config's LUT: {files:?}");
let generation = effectcraft_effects::lut_generation();
write(&lut, WHITE, 2_000);
assert_all(colours(&s, file), 1.0);
write(&grade, WHITE, 2_000);
assert_all(colours(&s, custom), 1.0);
assert!(effectcraft_effects::lut_generation() > generation, "the viewer's frames made before are dropped");
}
+2 -5
View File
@@ -175,11 +175,8 @@ impl Dependencies<'_> {
// Properties overrides, which the render applies: a LUT file one of
// them names is read too (#3493).
for o in crate::fx_host::essential_overrides(ctx, layer) {
if let effectcraft_keyframe::Value::Str(src) = &o.value
&& let Some(path) = effectcraft_effects::lut_file(src)
{
crate::reads::ReadFile::new(path, crate::reads::FileStamp::native(path).unwrap_or(crate::reads::FileStamp::Missing))
.hash(self.h);
if let effectcraft_keyframe::Value::Str(src) = &o.value {
crate::reads::source_files(src).hash(self.h);
}
}
let nested = EvalCtx::new(ctx.project, item, comp, time);
+17 -6
View File
@@ -65,20 +65,31 @@ impl ReadFile {
}
}
/// The LUT files effect `g` of `layer` reads at the context time (Apply Color LUT, Lumetri's
/// Input LUT and Look), each with its identity now. A layer's cache key holds them and a render
/// The files effect `g` of `layer` reads at the context time (Apply Color LUT, Lumetri's Input
/// LUT and Look, OCIO File Transform, a custom OCIO config and its LUTs: see
/// [`effectcraft_effects::lut_params`]), each with its identity now. A layer's cache key holds them and a render
/// notes them, so what was made with a file that changed since is not used (#3493).
pub(crate) fn lut_files(ctx: &crate::EvalCtx, layer: &effectcraft_project::Layer, g: &effectcraft_project::PropGroup) -> Vec<ReadFile> {
let effectcraft_project::GroupKind::Effect { effect } = &g.kind else { return Vec::new() };
effectcraft_effects::lut_params(effect)
.iter()
.filter_map(|param| match ctx.value(layer, g.prop(param)?) {
effectcraft_keyframe::Value::Str(src) => {
let path = effectcraft_effects::lut_file(&src)?;
Some(ReadFile::new(path, FileStamp::native(path).unwrap_or(FileStamp::Missing)))
}
effectcraft_keyframe::Value::Str(src) => Some(source_files(&src)),
_ => None,
})
.flatten()
.collect()
}
/// The files a file parameter set to `src` reads (an OCIO config's also the LUTs it names, #3538),
/// each with its identity now.
pub(crate) fn source_files(src: &str) -> Vec<ReadFile> {
effectcraft_effects::lut_files(src)
.into_iter()
.map(|path| {
let stamp = FileStamp::native(&path).unwrap_or(FileStamp::Missing);
ReadFile::new(path, stamp)
})
.collect()
}