From 02ac81b981476ce5e145c9145326a7922073801a Mon Sep 17 00:00:00 2001 From: Ayush Amawate Date: Wed, 18 Mar 2026 05:44:52 +0530 Subject: [PATCH 1/2] fix Firefox color rendering by respecting surface texture format preference --- editor/src/node_graph_executor/runtime.rs | 24 +++++++------------ node-graph/libraries/wgpu-executor/src/lib.rs | 5 +++- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/editor/src/node_graph_executor/runtime.rs b/editor/src/node_graph_executor/runtime.rs index 26102cda07..80321990bd 100644 --- a/editor/src/node_graph_executor/runtime.rs +++ b/editor/src/node_graph_executor/runtime.rs @@ -348,11 +348,13 @@ impl NodeRuntime { // Configure the surface at physical resolution (for HiDPI displays) let surface_inner = &surface.surface.inner; let surface_caps = surface_inner.get_capabilities(&executor.context.adapter); + // Use the surface's preferred format (Firefox WebGL prefers Bgra8Unorm, Chrome prefers Rgba8Unorm) + let surface_format = surface_caps.formats.iter().copied().find(|f| f.is_srgb()).unwrap_or(surface_caps.formats[0]); surface_inner.configure( &executor.context.device, &vello::wgpu::SurfaceConfiguration { usage: vello::wgpu::TextureUsages::RENDER_ATTACHMENT | vello::wgpu::TextureUsages::COPY_DST, - format: vello::wgpu::TextureFormat::Rgba8Unorm, + format: surface_format, width: physical_resolution.x, height: physical_resolution.y, present_mode: surface_caps.present_modes[0], @@ -365,21 +367,11 @@ 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(), - ); + // Use the blitter to copy the texture to the surface, handling format conversion + // (e.g., Rgba8Unorm source to Bgra8Unorm surface on Firefox) + 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 e98869238d..ec3d858b82 100644 --- a/node-graph/libraries/wgpu-executor/src/lib.rs +++ b/node-graph/libraries/wgpu-executor/src/lib.rs @@ -173,7 +173,10 @@ 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); + // Get the surface's preferred format (Firefox WebGL may prefer Bgra8Unorm, Chrome prefers Rgba8Unorm) + let surface_caps = surface.get_capabilities(&self.context.adapter); + let surface_format = surface_caps.formats.iter().copied().find(|f| f.is_srgb()).unwrap_or(surface_caps.formats[0]); + let blitter = TextureBlitter::new(&self.context.device, surface_format); Ok(SurfaceHandle { window_id, surface: Surface { From fbbeadd703bfa3ea910955645b57ebc396e54181 Mon Sep 17 00:00:00 2001 From: Ayush Amawate Date: Wed, 18 Mar 2026 07:25:47 +0530 Subject: [PATCH 2/2] apply gemini suggestions --- editor/src/node_graph_executor/runtime.rs | 4 +--- node-graph/libraries/wgpu-executor/src/lib.rs | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/editor/src/node_graph_executor/runtime.rs b/editor/src/node_graph_executor/runtime.rs index 80321990bd..59c970d866 100644 --- a/editor/src/node_graph_executor/runtime.rs +++ b/editor/src/node_graph_executor/runtime.rs @@ -348,13 +348,11 @@ impl NodeRuntime { // Configure the surface at physical resolution (for HiDPI displays) let surface_inner = &surface.surface.inner; let surface_caps = surface_inner.get_capabilities(&executor.context.adapter); - // Use the surface's preferred format (Firefox WebGL prefers Bgra8Unorm, Chrome prefers Rgba8Unorm) - let surface_format = surface_caps.formats.iter().copied().find(|f| f.is_srgb()).unwrap_or(surface_caps.formats[0]); surface_inner.configure( &executor.context.device, &vello::wgpu::SurfaceConfiguration { usage: vello::wgpu::TextureUsages::RENDER_ATTACHMENT | vello::wgpu::TextureUsages::COPY_DST, - format: surface_format, + format: surface.surface.format, width: physical_resolution.x, height: physical_resolution.y, present_mode: surface_caps.present_modes[0], diff --git a/node-graph/libraries/wgpu-executor/src/lib.rs b/node-graph/libraries/wgpu-executor/src/lib.rs index ec3d858b82..8319daea8e 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)] @@ -183,6 +184,7 @@ impl WgpuExecutor { inner: surface, target_texture: Mutex::new(None), blitter, + format: surface_format, }, }) }