Skip to content

Commit f79c30c

Browse files
committed
Avoid unwraps and zero sized textures
1 parent ad0db08 commit f79c30c

File tree

1 file changed

+20
-9
lines changed

1 file changed

+20
-9
lines changed

node-graph/nodes/gstd/src/render_cache.rs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -334,18 +334,19 @@ pub async fn render_output_cache<'a: 'n>(
334334
#[data] tile_cache: TileCache,
335335
) -> RenderOutput {
336336
let footprint = ctx.footprint();
337-
let render_params = ctx
338-
.vararg(0)
339-
.expect("Did not find var args")
340-
.downcast_ref::<RenderParams>()
341-
.expect("Downcasting render params yielded invalid type");
337+
let Some(render_params) = ctx.vararg(0).ok().and_then(|v| v.downcast_ref::<RenderParams>()) else {
338+
log::warn!("render_output_cache: missing or invalid render params, falling back to direct render");
339+
let context = OwnedContextImpl::empty().with_footprint(*footprint);
340+
return data.eval(context.into_context()).await;
341+
};
342342

343-
if !matches!(render_params.render_output_type, RenderOutputTypeRequest::Vello) {
343+
// Fall back to direct render for non-Vello or zero-size viewports
344+
let physical_resolution = footprint.resolution;
345+
if !matches!(render_params.render_output_type, RenderOutputTypeRequest::Vello) || physical_resolution.x == 0 || physical_resolution.y == 0 {
344346
let context = OwnedContextImpl::empty().with_footprint(*footprint).with_vararg(Box::new(render_params.clone()));
345347
return data.eval(context.into_context()).await;
346348
}
347349

348-
let physical_resolution = footprint.resolution;
349350
let logical_scale = footprint.decompose_scale().x;
350351
let device_scale = render_params.scale;
351352
let physical_scale = logical_scale * device_scale;
@@ -368,13 +369,23 @@ pub async fn render_output_cache<'a: 'n>(
368369

369370
let mut new_regions = Vec::new();
370371
for missing_region in &cache_query.missing_regions {
372+
if missing_region.tiles.is_empty() {
373+
continue;
374+
}
371375
let region = render_missing_region(missing_region, |ctx| data.eval(ctx), ctx.clone(), render_params, logical_scale, device_scale).await;
372376
new_regions.push(region);
373377
}
374378

375379
tile_cache.store_regions(new_regions.clone());
376380

377381
let all_regions: Vec<_> = cache_query.cached_regions.into_iter().chain(new_regions.into_iter()).collect();
382+
383+
// If no regions, fall back to direct render
384+
if all_regions.is_empty() {
385+
let context = OwnedContextImpl::empty().with_footprint(*footprint).with_vararg(Box::new(render_params.clone()));
386+
return data.eval(context.into_context()).await;
387+
}
388+
378389
let exec = editor_api.application_io.as_ref().unwrap().gpu_executor().unwrap();
379390
let (output_texture, combined_metadata) = composite_cached_regions(&all_regions, &viewport_bounds, physical_resolution, logical_scale, physical_scale, exec);
380391

@@ -406,7 +417,7 @@ where
406417
// Use round() on boundaries to ensure adjacent tiles share the same edge
407418
let pixel_start = (min_tile.as_dvec2() * TILE_SIZE as f64 * device_scale).round().as_ivec2();
408419
let pixel_end = ((max_tile + IVec2::ONE).as_dvec2() * TILE_SIZE as f64 * device_scale).round().as_ivec2();
409-
let region_pixel_size = (pixel_end - pixel_start).as_uvec2();
420+
let region_pixel_size = (pixel_end - pixel_start).max(IVec2::ONE).as_uvec2();
410421

411422
let region_transform = glam::DAffine2::from_scale(DVec2::splat(logical_scale)) * glam::DAffine2::from_translation(-region_world_start);
412423
let region_footprint = Footprint {
@@ -421,7 +432,7 @@ where
421432
let mut result = render_fn(region_ctx).await;
422433

423434
let RenderOutputType::Texture(rendered_texture) = result.data else {
424-
panic!("Expected texture output from render");
435+
unreachable!("render_missing_region: expected texture output from Vello render");
425436
};
426437

427438
// Transform metadata from region pixel space to document space

0 commit comments

Comments
 (0)