mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-14 19:27:05 -04:00
GPU: a declined precomp falls back for that layer only; the decline warning is once per comp and reason (#641 follow-up)
A nested comp too deep or too large for a GPU texture now takes the CPU path for its layer, as before #641, instead of failing the whole frame; only a device failure does. The warning no longer fires every frame (which pushed every other warning out of the System Report's log), and names the no-readback case and regions of interest. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
This commit is contained in:
2 files changed
+21
-5
No files matched your search
+15
-4
@@ -102,6 +102,8 @@ pub struct Gpu {
|
||||
ctx: Arc<GpuContext>,
|
||||
/// Backend::Auto's per-comp CPU / GPU timings.
|
||||
auto: Arc<effectcraft_render::AutoPick>,
|
||||
/// (comp, reason) pairs already warned about when the GPU declined a frame.
|
||||
declined: Arc<std::sync::Mutex<std::collections::HashSet<(u64, String)>>>,
|
||||
}
|
||||
|
||||
/// A viewer frame left on the GPU: premultiplied RGBA8 (`wgpu::TextureFormat::Rgba8Unorm`) with
|
||||
@@ -133,7 +135,7 @@ impl Gpu {
|
||||
}
|
||||
|
||||
pub fn from_context(ctx: GpuContext) -> Gpu {
|
||||
Gpu { ctx: Arc::new(ctx), auto: Default::default() }
|
||||
Gpu { ctx: Arc::new(ctx), auto: Default::default(), declined: Default::default() }
|
||||
}
|
||||
|
||||
/// A device of its own without blocking, with deferred readbacks (a browser worker, see
|
||||
@@ -291,8 +293,9 @@ impl Gpu {
|
||||
fn decline_reason(&self) -> String {
|
||||
match self.ctx.check_health() {
|
||||
Err(e) => format!("device failure / out of memory: {e}"),
|
||||
Ok(()) if !self.ctx.can_readback() => "no GPU readback is available here".into(),
|
||||
Ok(()) => format!(
|
||||
"the GPU compositor did not handle the frame (unsupported content, a frame over the {} px texture limit, or an allocation failed)",
|
||||
"the GPU compositor did not handle the frame (a region of interest, unsupported content, a frame over the {} px texture limit, or an allocation failed)",
|
||||
self.ctx.max_dim
|
||||
),
|
||||
}
|
||||
@@ -313,8 +316,16 @@ impl Accelerator for Gpu {
|
||||
let img = self.render(r, comp, t);
|
||||
if img.is_none() {
|
||||
// The caller renders the frame on the CPU; say so and why, or an export that falls
|
||||
// back frame after frame (a nested comp the GPU declines) is only mysteriously slow.
|
||||
log::warn!(target: "effectcraft_gpu", "GPU declined the frame at {:.3} s, the CPU renders it: {}", t.seconds(), self.decline_reason());
|
||||
// back frame after frame is only mysteriously slow. Once per comp and reason as a
|
||||
// warning (the log keeps only the last few hundred, for the System Report), then at
|
||||
// debug level.
|
||||
let reason = self.decline_reason();
|
||||
let first = self.declined.lock().map(|mut seen| seen.len() < 256 && seen.insert((comp.0, reason.clone()))).unwrap_or(false);
|
||||
if first {
|
||||
log::warn!(target: "effectcraft_gpu", "GPU declined the frame at {:.3} s, the CPU renders it: {reason}", t.seconds());
|
||||
} else {
|
||||
log::debug!(target: "effectcraft_gpu", "GPU declined the frame at {:.3} s: {reason}", t.seconds());
|
||||
}
|
||||
}
|
||||
img
|
||||
}
|
||||
|
||||
@@ -258,7 +258,12 @@ fn draw_precomp(e: &mut Enc, r: &Renderer, ctx: &EvalCtx, layer: &Layer, canvas:
|
||||
return None;
|
||||
}
|
||||
let (sub, item, lt, bs) = r.precomp_source(ctx, layer)?;
|
||||
let Some(mut src) = render(e, &sub, item, lt) else { return Some(None) };
|
||||
// A nested comp the GPU can't take (nested too deep, over the texture limit, content it
|
||||
// declines) goes back to the CPU path for this layer only; only a device failure fails the
|
||||
// frame.
|
||||
let Some(mut src) = render(e, &sub, item, lt) else {
|
||||
return if e.g.check_health().is_ok() { None } else { Some(None) };
|
||||
};
|
||||
let pipe = r.pipe();
|
||||
// `masked_source` quantises a non-solid source to the project's depth.
|
||||
if let Some(l) = pipe.levels {
|
||||
|
||||
Reference in new issue
Block a user