From efae3860bc3e2197eea39d30d756f93fb14c98d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Sun, 7 Sep 2025 04:55:45 +0200 Subject: [PATCH] Set `wgpu` viewport and scissoring before `Primitive::draw` --- wgpu/src/lib.rs | 40 ++++++++++++++++++++++++++++++++++++---- wgpu/src/primitive.rs | 8 ++++---- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 3e2e3ea8..3d8ee265 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -544,22 +544,54 @@ impl Renderer { let mut need_render = Vec::new(); for instance in &layer.primitives { + let bounds = instance.bounds * scale; + if let Some(clip_bounds) = (instance.bounds * scale) .intersection(&physical_bounds) .and_then(Rectangle::snap) { - let drawn = instance.primitive.draw( - &primitive_storage, - &mut render_pass, - &clip_bounds, + render_pass.set_viewport( + bounds.x, + bounds.y, + bounds.width, + bounds.height, + 0.0, + 1.0, ); + render_pass.set_scissor_rect( + clip_bounds.x, + clip_bounds.y, + clip_bounds.width, + clip_bounds.height, + ); + + let drawn = instance + .primitive + .draw(&primitive_storage, &mut render_pass); + if !drawn { need_render.push((instance, clip_bounds)); } } } + render_pass.set_viewport( + 0.0, + 0.0, + viewport.physical_width() as f32, + viewport.physical_height() as f32, + 0.0, + 1.0, + ); + + render_pass.set_scissor_rect( + 0, + 0, + viewport.physical_width(), + viewport.physical_height(), + ); + if !need_render.is_empty() { let _ = ManuallyDrop::into_inner(render_pass); diff --git a/wgpu/src/primitive.rs b/wgpu/src/primitive.rs index b5a73032..dd661e7e 100644 --- a/wgpu/src/primitive.rs +++ b/wgpu/src/primitive.rs @@ -48,6 +48,9 @@ pub trait Primitive: Debug + MaybeSend + MaybeSync + 'static { /// since reusing the existing render pass should be considerably more /// efficient than issuing a new one. /// + /// The viewport and scissor rect of the render pass provided is set + /// to the bounds and clip bounds of the [`Primitive`], respectively. + /// /// If you have complex composition needs, then you can leverage /// [`render`](Self::render) by returning `false` here. /// @@ -56,7 +59,6 @@ pub trait Primitive: Debug + MaybeSend + MaybeSync + 'static { &self, _renderer: &Self::Renderer, _render_pass: &mut wgpu::RenderPass<'_>, - _clip_bounds: &Rectangle, ) -> bool { false } @@ -93,7 +95,6 @@ pub(crate) trait Stored: &self, storage: &Storage, render_pass: &mut wgpu::RenderPass<'_>, - clip_bounds: &Rectangle, ) -> bool; fn render( @@ -140,7 +141,6 @@ impl Stored for BlackBox

{ &self, storage: &Storage, render_pass: &mut wgpu::RenderPass<'_>, - clip_bounds: &Rectangle, ) -> bool { let renderer = storage .get::

() @@ -148,7 +148,7 @@ impl Stored for BlackBox

{ .downcast_ref::() .expect("renderer should have the proper type"); - self.primitive.draw(renderer, render_pass, clip_bounds) + self.primitive.draw(renderer, render_pass) } fn render(