Fix onion ghosts: show on blank cels + fault in on seek
- Removed the early `continue` that skipped a layer with no resident content — it also skipped the active raster layer's onion ghosts when the current cel was blank (the exact case you trace a new cel from neighbours). Each render arm already guards its own empty case, so the skip was redundant. - Ghost texture resolution now falls through cache → resident raw_pixels (upload) → in-memory proxy → request fault-in, so neighbours that were paged out (e.g. after a seek, or saved-this-session with no decoded proxy) page in and ghost in, instead of silently rendering nothing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4dc937f9c0
commit
78109cda93
|
|
@ -1250,12 +1250,6 @@ impl egui_wgpu::CallbackTrait for VelloCallback {
|
|||
None
|
||||
};
|
||||
|
||||
if !rendered_layer.has_content && gpu_canvas_kf.is_none() && raster_cache_kf.is_none()
|
||||
&& raster_proxy_blit.is_none()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
match &rendered_layer.layer_type {
|
||||
RenderedLayerType::Vector => {
|
||||
// Vector/group layer — render Vello scene → sRGB → linear → composite.
|
||||
|
|
@ -1343,26 +1337,44 @@ impl egui_wgpu::CallbackTrait for VelloCallback {
|
|||
&instance_resources.hdr_texture_view,
|
||||
) {
|
||||
let mut drew = false;
|
||||
let mut need_fault = false;
|
||||
if let Ok(mut gpu_brush) = shared.gpu_brush.lock() {
|
||||
let has_full = gpu_brush.raster_layer_cache.contains_key(&kf_id);
|
||||
if !has_full {
|
||||
// Upload the proxy on demand from the keyframe's pixels.
|
||||
if let Some(lightningbeam_core::layer::AnyLayer::Raster(rl)) =
|
||||
self.ctx.document.get_layer(&rendered_layer.layer_id)
|
||||
{
|
||||
if let Some(p) = rl.keyframes.iter().find(|k| k.id == kf_id)
|
||||
.and_then(|k| k.proxy.as_ref())
|
||||
{
|
||||
gpu_brush.ensure_proxy_texture(device, queue, kf_id, &p.pixels, p.width, p.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
let src = if has_full {
|
||||
gpu_brush.raster_layer_cache.get(&kf_id).map(|c| (c, c.width, c.height, false))
|
||||
// Resolve a texture, in priority order:
|
||||
// 1) cached full texture
|
||||
// 2) resident raw_pixels → upload full (e.g. an
|
||||
// unsaved neighbour whose GPU texture evicted)
|
||||
// 3) in-memory proxy → upload proxy
|
||||
// 4) none → request a fault-in (seek to a paged-out frame)
|
||||
let resolved: Option<(u32, u32, bool)> =
|
||||
if gpu_brush.raster_layer_cache.contains_key(&kf_id) {
|
||||
gpu_brush.raster_layer_cache.get(&kf_id).map(|c| (c.width, c.height, false))
|
||||
} else {
|
||||
gpu_brush.get_proxy_texture(&kf_id).map(|c| (c, lw, lh, true))
|
||||
let kf = match self.ctx.document.get_layer(&rendered_layer.layer_id) {
|
||||
Some(lightningbeam_core::layer::AnyLayer::Raster(rl)) =>
|
||||
rl.keyframes.iter().find(|k| k.id == kf_id),
|
||||
_ => None,
|
||||
};
|
||||
if let Some((canvas, sw, sh, is_proxy)) = src {
|
||||
match kf {
|
||||
Some(kf) if kf.raw_pixels.len() == (kf.width * kf.height * 4) as usize => {
|
||||
gpu_brush.ensure_layer_texture(device, queue, kf_id, &kf.raw_pixels, kf.width, kf.height, false);
|
||||
Some((kf.width, kf.height, false))
|
||||
}
|
||||
Some(kf) if kf.proxy.is_some() => {
|
||||
let p = kf.proxy.as_ref().unwrap();
|
||||
gpu_brush.ensure_proxy_texture(device, queue, kf_id, &p.pixels, p.width, p.height);
|
||||
Some((lw, lh, true))
|
||||
}
|
||||
Some(kf) if kf.needs_fault_in => { need_fault = true; None }
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
if let Some((sw, sh, is_proxy)) = resolved {
|
||||
let tex = if is_proxy {
|
||||
gpu_brush.get_proxy_texture(&kf_id)
|
||||
} else {
|
||||
gpu_brush.raster_layer_cache.get(&kf_id)
|
||||
};
|
||||
if let Some(canvas) = tex {
|
||||
let bt = crate::gpu_brush::BlitTransform::new(*layer_transform, sw, sh, width, height)
|
||||
.with_tint(tint[0], tint[1], tint[2]);
|
||||
if is_proxy {
|
||||
|
|
@ -1373,6 +1385,12 @@ impl egui_wgpu::CallbackTrait for VelloCallback {
|
|||
drew = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if need_fault {
|
||||
if let Ok(mut reqs) = self.ctx.raster_fault_requests.lock() {
|
||||
reqs.insert(kf_id);
|
||||
}
|
||||
}
|
||||
if drew {
|
||||
let cl = lightningbeam_core::gpu::CompositorLayer::new(
|
||||
gh, rendered_layer.opacity * opacity, rendered_layer.blend_mode,
|
||||
|
|
|
|||
Loading…
Reference in New Issue