From a53af7a35a1c825f07849a940e251cacb8eeb80a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?charlotte=20=F0=9F=8C=B8?= Date: Fri, 24 Apr 2026 18:13:16 -0700 Subject: [PATCH 1/5] Reliably clear to default clear color. --- crates/processing_render/Cargo.toml | 1 + crates/processing_render/src/graphics.rs | 60 +++++++++++++++++++++++- crates/processing_render/src/lib.rs | 21 +++++++-- 3 files changed, 77 insertions(+), 5 deletions(-) diff --git a/crates/processing_render/Cargo.toml b/crates/processing_render/Cargo.toml index a2097a3..5c83a5c 100644 --- a/crates/processing_render/Cargo.toml +++ b/crates/processing_render/Cargo.toml @@ -22,6 +22,7 @@ half = "2.7" crossbeam-channel = "0.5" processing_core = { workspace = true } processing_midi = { workspace = true } +wgpu = { version = "29.0.1", default-features = false } [build-dependencies] wesl = { workspace = true, features = ["package"] } diff --git a/crates/processing_render/src/graphics.rs b/crates/processing_render/src/graphics.rs index ffbc56c..9d64aed 100644 --- a/crates/processing_render/src/graphics.rs +++ b/crates/processing_render/src/graphics.rs @@ -15,7 +15,8 @@ use bevy::{ render::{ RenderApp, render_resource::{ - CommandEncoderDescriptor, Extent3d, MapMode, Origin3d, PollType, TexelCopyBufferInfo, + CommandEncoderDescriptor, Extent3d, LoadOp, MapMode, Operations, Origin3d, PollType, + RenderPassColorAttachment, RenderPassDescriptor, StoreOp, TexelCopyBufferInfo, TexelCopyBufferLayout, TexelCopyTextureInfo, Texture, TextureFormat, TextureUsages, }, renderer::{RenderDevice, RenderQueue}, @@ -36,6 +37,8 @@ use crate::{ }; use processing_core::error::{ProcessingError, Result}; +pub const DEFAULT_CLEAR_COLOR: Color = Color::srgba_u8(208, 208, 208, 255); + pub struct GraphicsPlugin; impl Plugin for GraphicsPlugin { @@ -483,6 +486,61 @@ pub fn end_draw(app: &mut App, entity: Entity) -> Result<()> { present(app, entity) } + +/// Do some work on the GPU to ensure that the render target texture is initialized and can be read +/// from/written to. +/// +/// This is necessary on some platforms (notably macOS) to avoid issues with the first few frames of +/// rendering being corrupted or not appearing at all. +/// +// TODO: why is metal particularly affected by this? can we remove this? +pub fn warmup(app: &mut App, entity: Entity) -> Result<()> { + let main_texture = { + let render_world = app.sub_app_mut(RenderApp).world_mut(); + let mut query = render_world.query::<(&MainEntity, &ViewTarget)>(); + let mut found = None; + for (main_entity, vt) in query.iter(render_world) { + if **main_entity == entity { + found = Some(vt.main_texture().clone()); + break; + } + } + found.ok_or(ProcessingError::GraphicsNotFound)? + }; + + let render_app = app.sub_app(RenderApp); + let render_device = render_app.world().resource::(); + let render_queue = render_app.world().resource::(); + + let view = main_texture.create_view(&bevy::render::render_resource::TextureViewDescriptor { + label: Some("processing_warmup_view"), + ..Default::default() + }); + let mut encoder = render_device.create_command_encoder(&CommandEncoderDescriptor { + label: Some("processing_warmup_encoder"), + }); + { + let _pass = encoder.begin_render_pass(&RenderPassDescriptor { + label: Some("processing_warmup_clear"), + color_attachments: &[Some(RenderPassColorAttachment { + view: &view, + depth_slice: None, + resolve_target: None, + ops: Operations { + load: LoadOp::Clear(wgpu::Color::TRANSPARENT), + store: StoreOp::Store, + }, + })], + depth_stencil_attachment: None, + timestamp_writes: None, + occlusion_query_set: None, + multiview_mask: None, + }); + } + render_queue.submit([encoder.finish()]); + Ok(()) +} + pub fn record_command( In((graphics_entity, cmd)): In<(Entity, DrawCommand)>, mut graphics_query: Query<&mut CommandBuffer>, diff --git a/crates/processing_render/src/lib.rs b/crates/processing_render/src/lib.rs index 27636dd..9a91a69 100644 --- a/crates/processing_render/src/lib.rs +++ b/crates/processing_render/src/lib.rs @@ -27,7 +27,7 @@ use processing_core::config::*; use processing_core::error; use crate::geometry::{AttributeFormat, AttributeValue}; -use crate::graphics::flush; +use crate::graphics::{DEFAULT_CLEAR_COLOR, flush}; use crate::image::gpu_image; use crate::render::command::DrawCommand; @@ -254,13 +254,26 @@ pub fn graphics_create( height: u32, texture_format: TextureFormat, ) -> error::Result { - app_mut(|app| { - app.world_mut() + app_mut(|app| -> error::Result { + let entity = app + .world_mut() .run_system_cached_with( graphics::create, (width, height, surface_entity, texture_format), ) - .unwrap() + .unwrap()?; + + app.update(); + #[cfg(target_os = "macos")] + graphics::warmup(app, entity)?; + + app.world_mut() + .run_system_cached_with( + graphics::record_command, + (entity, DrawCommand::BackgroundColor(DEFAULT_CLEAR_COLOR)), + ) + .unwrap()?; + Ok(entity) }) } From d49fe2cb3d6689b3054fc841174fd00665892a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?charlotte=20=F0=9F=8C=B8?= Date: Fri, 24 Apr 2026 18:58:35 -0700 Subject: [PATCH 2/5] Remove errant test. --- Cargo.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3f4577f..5919779 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,10 +63,6 @@ rand = "0.10.0" [target.'cfg(target_os = "linux")'.dev-dependencies] processing_glfw = { workspace = true, features = ["wayland"] } -[[example]] -name = "test" -path = "examples/test.rs" - [patch."https://github.com/bevyengine/bevy"] bevy = { git = "https://github.com/processing/bevy", branch = "main" } From f6107082a60306a9d6f236785fa84623f37fd975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?charlotte=20=F0=9F=8C=B8?= Date: Fri, 24 Apr 2026 18:58:45 -0700 Subject: [PATCH 3/5] Fmt. --- crates/processing_render/src/graphics.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/processing_render/src/graphics.rs b/crates/processing_render/src/graphics.rs index 9d64aed..bfb7af5 100644 --- a/crates/processing_render/src/graphics.rs +++ b/crates/processing_render/src/graphics.rs @@ -486,13 +486,12 @@ pub fn end_draw(app: &mut App, entity: Entity) -> Result<()> { present(app, entity) } - -/// Do some work on the GPU to ensure that the render target texture is initialized and can be read +/// Do some work on the GPU to ensure that the render target texture is initialized and can be read /// from/written to. -/// -/// This is necessary on some platforms (notably macOS) to avoid issues with the first few frames of +/// +/// This is necessary on some platforms (notably macOS) to avoid issues with the first few frames of /// rendering being corrupted or not appearing at all. -/// +/// // TODO: why is metal particularly affected by this? can we remove this? pub fn warmup(app: &mut App, entity: Entity) -> Result<()> { let main_texture = { From a8bbd82caa5ff15036c5109fe83707f391a33254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?charlotte=20=F0=9F=8C=B8?= Date: Mon, 27 Apr 2026 22:06:35 -0700 Subject: [PATCH 4/5] Re-adjust approach. --- crates/processing_render/Cargo.toml | 1 - crates/processing_render/src/graphics.rs | 63 ++++-------------------- crates/processing_render/src/lib.rs | 9 ---- 3 files changed, 9 insertions(+), 64 deletions(-) diff --git a/crates/processing_render/Cargo.toml b/crates/processing_render/Cargo.toml index 5c83a5c..a2097a3 100644 --- a/crates/processing_render/Cargo.toml +++ b/crates/processing_render/Cargo.toml @@ -22,7 +22,6 @@ half = "2.7" crossbeam-channel = "0.5" processing_core = { workspace = true } processing_midi = { workspace = true } -wgpu = { version = "29.0.1", default-features = false } [build-dependencies] wesl = { workspace = true, features = ["package"] } diff --git a/crates/processing_render/src/graphics.rs b/crates/processing_render/src/graphics.rs index bfb7af5..f885750 100644 --- a/crates/processing_render/src/graphics.rs +++ b/crates/processing_render/src/graphics.rs @@ -15,8 +15,7 @@ use bevy::{ render::{ RenderApp, render_resource::{ - CommandEncoderDescriptor, Extent3d, LoadOp, MapMode, Operations, Origin3d, PollType, - RenderPassColorAttachment, RenderPassDescriptor, StoreOp, TexelCopyBufferInfo, + CommandEncoderDescriptor, Extent3d, MapMode, Origin3d, PollType, TexelCopyBufferInfo, TexelCopyBufferLayout, TexelCopyTextureInfo, Texture, TextureFormat, TextureUsages, }, renderer::{RenderDevice, RenderQueue}, @@ -448,16 +447,6 @@ pub fn begin_draw(In(entity): In, mut state_query: Query<&mut RenderStat } pub fn flush(app: &mut App, entity: Entity) -> Result<()> { - // f there's nothing to render, skip the whole render pass. this avoids some issues on - // macos with msaa resolve where nothing is rendered - let is_empty = graphics_mut!(app, entity) - .get::() - .map(|c| c.commands.is_empty()) - .unwrap_or(true); - if is_empty { - return Ok(()); - } - graphics_mut!(app, entity).insert(Flush); app.update(); graphics_mut!(app, entity).remove::(); @@ -494,49 +483,15 @@ pub fn end_draw(app: &mut App, entity: Entity) -> Result<()> { /// // TODO: why is metal particularly affected by this? can we remove this? pub fn warmup(app: &mut App, entity: Entity) -> Result<()> { - let main_texture = { - let render_world = app.sub_app_mut(RenderApp).world_mut(); - let mut query = render_world.query::<(&MainEntity, &ViewTarget)>(); - let mut found = None; - for (main_entity, vt) in query.iter(render_world) { - if **main_entity == entity { - found = Some(vt.main_texture().clone()); - break; - } - } - found.ok_or(ProcessingError::GraphicsNotFound)? - }; - - let render_app = app.sub_app(RenderApp); - let render_device = render_app.world().resource::(); - let render_queue = render_app.world().resource::(); - - let view = main_texture.create_view(&bevy::render::render_resource::TextureViewDescriptor { - label: Some("processing_warmup_view"), - ..Default::default() - }); - let mut encoder = render_device.create_command_encoder(&CommandEncoderDescriptor { - label: Some("processing_warmup_encoder"), - }); - { - let _pass = encoder.begin_render_pass(&RenderPassDescriptor { - label: Some("processing_warmup_clear"), - color_attachments: &[Some(RenderPassColorAttachment { - view: &view, - depth_slice: None, - resolve_target: None, - ops: Operations { - load: LoadOp::Clear(wgpu::Color::TRANSPARENT), - store: StoreOp::Store, - }, - })], - depth_stencil_attachment: None, - timestamp_writes: None, - occlusion_query_set: None, - multiview_mask: None, - }); + for _ in 0..3 { + app.world_mut() + .run_system_cached_with( + record_command, + (entity, DrawCommand::BackgroundColor(DEFAULT_CLEAR_COLOR)), + ) + .unwrap()?; + flush(app, entity)?; } - render_queue.submit([encoder.finish()]); Ok(()) } diff --git a/crates/processing_render/src/lib.rs b/crates/processing_render/src/lib.rs index 9a91a69..61192c2 100644 --- a/crates/processing_render/src/lib.rs +++ b/crates/processing_render/src/lib.rs @@ -263,16 +263,7 @@ pub fn graphics_create( ) .unwrap()?; - app.update(); - #[cfg(target_os = "macos")] graphics::warmup(app, entity)?; - - app.world_mut() - .run_system_cached_with( - graphics::record_command, - (entity, DrawCommand::BackgroundColor(DEFAULT_CLEAR_COLOR)), - ) - .unwrap()?; Ok(entity) }) } From c77d22d5516aa47a01967e19e285d29ecfcd1e5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moon=20Dav=C3=A9?= Date: Tue, 28 Apr 2026 08:23:51 -0400 Subject: [PATCH 5/5] remove unused import --- crates/processing_render/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/processing_render/src/lib.rs b/crates/processing_render/src/lib.rs index 61192c2..8d40662 100644 --- a/crates/processing_render/src/lib.rs +++ b/crates/processing_render/src/lib.rs @@ -27,7 +27,7 @@ use processing_core::config::*; use processing_core::error; use crate::geometry::{AttributeFormat, AttributeValue}; -use crate::graphics::{DEFAULT_CLEAR_COLOR, flush}; +use crate::graphics::flush; use crate::image::gpu_image; use crate::render::command::DrawCommand;