From 1beb06ae1053ea79920c1db9899a1cb35472a6d3 Mon Sep 17 00:00:00 2001 From: afrdbaig7 Date: Thu, 8 Jan 2026 16:13:34 +0530 Subject: [PATCH] Fix WGPU out-of-memory crash by caching overlay textures --- desktop/src/render/state.rs | 21 ++++++++++++++----- node-graph/libraries/wgpu-executor/src/lib.rs | 8 +++---- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/desktop/src/render/state.rs b/desktop/src/render/state.rs index 46a919b8b5..acd6e39643 100644 --- a/desktop/src/render/state.rs +++ b/desktop/src/render/state.rs @@ -1,6 +1,7 @@ use crate::window::Window; use crate::wrapper::{Color, WgpuContext, WgpuExecutor}; +use wgpu_executor::TargetTexture; #[derive(derivative::Derivative)] #[derivative(Debug)] @@ -18,6 +19,7 @@ pub(crate) struct RenderState { viewport_offset: [f32; 2], viewport_texture: Option, overlays_texture: Option, + overlays_target_texture: Option, ui_texture: Option, bind_group: Option, #[derivative(Debug = "ignore")] @@ -182,6 +184,7 @@ impl RenderState { viewport_offset: [0.0, 0.0], viewport_texture: None, overlays_texture: None, + overlays_target_texture: None, ui_texture: None, bind_group: None, overlays_scene: None, @@ -236,12 +239,20 @@ impl RenderState { return; }; let size = glam::UVec2::new(viewport_texture.width(), viewport_texture.height()); - let texture = futures::executor::block_on(self.executor.render_vello_scene_to_texture(&scene, size, &Default::default(), Color::TRANSPARENT)); - let Ok(texture) = texture else { - tracing::error!("Error rendering overlays"); + let result = futures::executor::block_on( + self.executor.render_vello_scene_to_target_texture(&scene, size, &Default::default(), Color::TRANSPARENT, &mut self.overlays_target_texture) + ); + if let Err(e) = result { + tracing::error!("Error rendering overlays: {:?}", e); return; - }; - self.bind_overlays_texture(texture); + } + // Extract the texture from the cached TargetTexture + if let Some(target_texture) = &self.overlays_target_texture { + // Create a new texture reference - the actual GPU texture is reused + let texture_view = target_texture.texture.create_view(&wgpu::TextureViewDescriptor::default()); + self.overlays_texture = Some(target_texture.texture.clone()); + self.update_bindgroup(); + } } pub(crate) fn render(&mut self, window: &Window) -> Result<(), RenderError> { diff --git a/node-graph/libraries/wgpu-executor/src/lib.rs b/node-graph/libraries/wgpu-executor/src/lib.rs index 868c73f60e..7c2b640dc1 100644 --- a/node-graph/libraries/wgpu-executor/src/lib.rs +++ b/node-graph/libraries/wgpu-executor/src/lib.rs @@ -49,9 +49,9 @@ pub struct Surface { } pub struct TargetTexture { - texture: wgpu::Texture, - view: wgpu::TextureView, - size: UVec2, + pub texture: wgpu::Texture, + pub view: wgpu::TextureView, + pub size: UVec2, } #[cfg(target_family = "wasm")] @@ -72,7 +72,7 @@ impl WgpuExecutor { Ok(output.unwrap().texture) } - async fn render_vello_scene_to_target_texture(&self, scene: &Scene, size: UVec2, context: &RenderContext, background: Color, output: &mut Option) -> Result<()> { + pub async fn render_vello_scene_to_target_texture(&self, scene: &Scene, size: UVec2, context: &RenderContext, background: Color, output: &mut Option) -> Result<()> { let size = size.max(UVec2::ONE); let target_texture = if let Some(target_texture) = output && target_texture.size == size