diff --git a/editor/src/node_graph_executor/runtime.rs b/editor/src/node_graph_executor/runtime.rs index 26102cda07..eadc9aba96 100644 --- a/editor/src/node_graph_executor/runtime.rs +++ b/editor/src/node_graph_executor/runtime.rs @@ -352,7 +352,7 @@ impl NodeRuntime { &executor.context.device, &vello::wgpu::SurfaceConfiguration { usage: vello::wgpu::TextureUsages::RENDER_ATTACHMENT | vello::wgpu::TextureUsages::COPY_DST, - format: vello::wgpu::TextureFormat::Rgba8Unorm, + format: surface.surface.format, width: physical_resolution.x, height: physical_resolution.y, present_mode: surface_caps.present_modes[0], @@ -365,21 +365,30 @@ impl NodeRuntime { let surface_texture = surface_inner.get_current_texture().expect("Failed to get surface texture"); self.current_viewport_texture = Some(image_texture.clone()); - encoder.copy_texture_to_texture( - vello::wgpu::TexelCopyTextureInfoBase { - texture: image_texture.texture.as_ref(), - mip_level: 0, - origin: Default::default(), - aspect: Default::default(), - }, - vello::wgpu::TexelCopyTextureInfoBase { - texture: &surface_texture.texture, - mip_level: 0, - origin: Default::default(), - aspect: Default::default(), - }, - image_texture.texture.size(), - ); + // Only use the blitter if formats differ, otherwise use efficient direct copy + if surface.surface.format == vello::wgpu::TextureFormat::Rgba8Unorm { + // Same format as Vello's output - use direct texture copy + encoder.copy_texture_to_texture( + vello::wgpu::TexelCopyTextureInfoBase { + texture: image_texture.texture.as_ref(), + mip_level: 0, + origin: Default::default(), + aspect: Default::default(), + }, + vello::wgpu::TexelCopyTextureInfoBase { + texture: &surface_texture.texture, + mip_level: 0, + origin: Default::default(), + aspect: Default::default(), + }, + image_texture.texture.size(), + ); + } else { + // Different format (e.g., Firefox's Bgra8Unorm on Mac) - use blitter for conversion + let source_view = image_texture.texture.create_view(&vello::wgpu::TextureViewDescriptor::default()); + let target_view = surface_texture.texture.create_view(&vello::wgpu::TextureViewDescriptor::default()); + surface.surface.blitter.copy(&executor.context.device, &mut encoder, &source_view, &target_view); + } executor.context.queue.submit([encoder.finish()]); surface_texture.present(); diff --git a/node-graph/libraries/wgpu-executor/src/lib.rs b/node-graph/libraries/wgpu-executor/src/lib.rs index 011da195e4..fb50134f44 100644 --- a/node-graph/libraries/wgpu-executor/src/lib.rs +++ b/node-graph/libraries/wgpu-executor/src/lib.rs @@ -49,6 +49,7 @@ pub struct Surface { pub inner: wgpu::Surface<'static>, pub target_texture: Mutex>, pub blitter: TextureBlitter, + pub format: wgpu::TextureFormat, } #[derive(Clone, Debug)] @@ -173,13 +174,17 @@ impl WgpuExecutor { } pub fn create_surface_inner(&self, surface: wgpu::Surface<'static>, window_id: SurfaceId) -> Result> { - let blitter = TextureBlitter::new(&self.context.device, VELLO_SURFACE_FORMAT); + // Use the surface's preferred format (Firefox prefers Bgra8Unorm, Chrome prefers Rgba8Unorm) + let surface_caps = surface.get_capabilities(&self.context.adapter); + let surface_format = surface_caps.formats[0]; + let blitter = TextureBlitter::new(&self.context.device, surface_format); Ok(SurfaceHandle { window_id, surface: Surface { inner: surface, target_texture: Mutex::new(None), blitter, + format: surface_format, }, }) }