Merge branch 'fix/f4': community issue fixes

This commit is contained in:
Claude
2026-10-10 20:00:37 +00:00
16 changed files with 368 additions and 19 deletions
+14 -2
View File
@@ -328,7 +328,10 @@ pub fn system_report(s: &Session) -> Value {
let budgets = s.prefs.cache_budgets(mem.or(s.sys_memory));
let mut issues = vec![];
if gpu.is_none() {
issues.push("No GPU compositor: rendering uses the CPU (all features still work).".to_string());
issues.push(match &s.accel_note {
Some(why) => format!("No GPU compositor ({why}): rendering uses the CPU (all features still work)."),
None => "No GPU compositor: rendering uses the CPU (all features still work).".to_string(),
});
}
if mem.is_some_and(|m| m.total < 8 << 30) {
issues.push("Less than 8 GB of memory: use lower preview resolutions for long or large comps.".to_string());
@@ -344,6 +347,8 @@ pub fn system_report(s: &Session) -> Value {
"cores": crate::sysinfo::cpu_cores(),
"memory": mem.map(|m| json!({"total": gb(m.total), "available": gb(m.available)})),
"gpu": gpu,
"gpuNote": if gpu.is_none() { s.accel_note.clone() } else { None },
"windowGraphics": s.window_adapter,
"caches": {"layer": gb(budgets.layer as u64), "footage": gb(budgets.media as u64), "preview": gb(budgets.preview as u64)},
"import": IMPORT_FORMATS,
"export": export,
@@ -369,7 +374,14 @@ pub fn report_text(r: &Value) -> String {
Some(m) => t.push_str(&format!("Memory: {} ({} available)\n", m["total"].as_str().unwrap_or("?"), m["available"].as_str().unwrap_or("?"))),
None => t.push_str("Memory: unknown\n"),
}
t.push_str(&format!("GPU: {}\n", r.get("gpu").and_then(Value::as_str).unwrap_or("none (CPU compositing)")));
match (r.get("gpu").and_then(Value::as_str), r.get("gpuNote").and_then(Value::as_str)) {
(Some(gpu), _) => t.push_str(&format!("GPU: {gpu}\n")),
(None, Some(why)) => t.push_str(&format!("GPU: none (CPU compositing): {why}\n")),
(None, None) => t.push_str("GPU: none (CPU compositing)\n"),
}
if let Some(w) = r.get("windowGraphics").and_then(Value::as_str) {
t.push_str(&format!("Window graphics: {w}\n"));
}
let c = &r["caches"];
t.push_str(&format!(
"Cache budgets: layer {}, footage {}, preview {}\n",
+9 -1
View File
@@ -577,6 +577,14 @@ fn project_settings(s: &mut Session, p: &Value) -> Result<Value> {
),
};
}
if let Some(g) = p.get("workingGamma") {
// After Effects takes 2.2 or 2.4 only (`app.project.workingGamma`).
proj.settings.working_gamma = match g.as_f64() {
Some(g) if (g - 2.2).abs() < 1e-6 => 2.2,
Some(g) if (g - 2.4).abs() < 1e-6 => 2.4,
_ => return Err(bad(cmd, format!("workingGamma: 2.2|2.4, not `{g}`"))),
};
}
if proj.settings.color_engine == ColorEngine::Ocio && !proj.settings.working_space.is_some_and(|w| w.is_linear()) {
return Err(bad(cmd, "the OCIO built-in config's working spaces are acescg and aces2065"));
}
@@ -689,7 +697,7 @@ pub fn specs() -> Vec<CommandSpec> {
"Project Settings...",
["File"],
Some("Cmd+Alt+Shift+K"),
"{bitDepth?: 8|16|32, colorEngine?: adobe|ocio, workingSpace?: none|srgb|rec709|rec2020|p3|acescg|aces2065, linearize?, blendLinear?, hdr?: clip|compand|toneMap, outputSpace?: srgb|rec709|rec2020|p3|rec2100pq|rec2100hlg, renderer?: gpu|software, timeDisplay?: timecode|frames|feet35|feet16}",
"{bitDepth?: 8|16|32, colorEngine?: adobe|ocio, workingSpace?: none|srgb|rec709|rec2020|p3|acescg|aces2065, workingGamma?: 2.2|2.4 (with no working space), linearize?, blendLinear?, hdr?: clip|compand|toneMap, outputSpace?: srgb|rec709|rec2020|p3|rec2100pq|rec2100hlg, renderer?: gpu|software, timeDisplay?: timecode|frames|feet35|feet16}",
always,
project_settings
),
+4
View File
@@ -372,6 +372,9 @@ pub struct Session {
/// Why there is no [`Session::accel`] (`render.backend`'s `why`): the host's reason, e.g. a
/// headless start without `--gpu` or the compositor's setup error.
pub accel_note: Option<String>,
/// The graphics adapter and backend the window draws with (`NVIDIA GeForce RTX 4070
/// (Vulkan)`), as the host reports it: the System Compatibility Report shows it.
pub window_adapter: Option<String>,
/// Expression syntax checker (set by the host that links the expression engine).
pub expr_check: Option<fn(&str) -> std::result::Result<(), String>>,
pub importer: Option<Arc<dyn Importer>>,
@@ -523,6 +526,7 @@ impl Default for Session {
expr: None,
accel: None,
accel_note: None,
window_adapter: None,
expr_check: None,
importer: None,
exporter: None,
+9
View File
@@ -455,6 +455,15 @@ fn compatibility_report_and_logging() {
}
let text = crate::commands::report_text_for_tests(&r);
assert!(text.contains("Operating system") && text.contains("Import:"));
// #596: without a GPU compositor the report says why, and names the window's adapter.
s.accel_note = Some("GPU compositor unavailable: no storage textures".into());
s.window_adapter = Some("NVIDIA GeForce RTX 4070 (Gl, DiscreteGpu)".into());
let r = s.execute("help.systemReport", json!({"quiet": true})).unwrap();
assert_eq!(r["gpuNote"], "GPU compositor unavailable: no storage textures");
let text = crate::commands::report_text_for_tests(&r);
assert!(text.contains("GPU: none (CPU compositing): GPU compositor unavailable: no storage textures"), "{text}");
assert!(text.contains("Window graphics: NVIDIA GeForce RTX 4070 (Gl, DiscreteGpu)"), "{text}");
assert!(r["issues"][0].as_str().is_some_and(|i| i.contains("no storage textures")), "{r}");
s.drain_events();
s.execute("help.systemReport", json!({})).unwrap();
assert!(s.drain_events().iter().any(|e| matches!(e, crate::Event::Frontend { command, .. } if command == "app.showReport")));