Introduce lightweight draw for wgpu::Primitive

This commit is contained in:
Héctor Ramón Jiménez 2025-09-06 21:17:38 +02:00
parent 53a98bf7de
commit 0d05ea56d3
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
2 changed files with 95 additions and 27 deletions

View file

@ -534,7 +534,6 @@ impl Renderer {
if !layer.primitives.is_empty() {
let render_span = debug::render(debug::Primitive::Shader);
let _ = ManuallyDrop::into_inner(render_pass);
let primitive_storage = self
.engine
@ -542,11 +541,30 @@ impl Renderer {
.read()
.expect("Read primitive storage");
let mut need_render = Vec::new();
for instance in &layer.primitives {
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,
frame,
&clip_bounds,
);
if !drawn {
need_render.push((instance, clip_bounds));
}
}
}
if !need_render.is_empty() {
let _ = ManuallyDrop::into_inner(render_pass);
for (instance, clip_bounds) in need_render {
instance.primitive.render(
&primitive_storage,
encoder,
@ -554,29 +572,29 @@ impl Renderer {
&clip_bounds,
);
}
render_pass = ManuallyDrop::new(encoder.begin_render_pass(
&wgpu::RenderPassDescriptor {
label: Some("iced_wgpu render pass"),
color_attachments: &[Some(
wgpu::RenderPassColorAttachment {
view: frame,
depth_slice: None,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Load,
store: wgpu::StoreOp::Store,
},
},
)],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
},
));
}
render_span.finish();
render_pass = ManuallyDrop::new(encoder.begin_render_pass(
&wgpu::RenderPassDescriptor {
label: Some("iced_wgpu render pass"),
color_attachments: &[Some(
wgpu::RenderPassColorAttachment {
view: frame,
depth_slice: None,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Load,
store: wgpu::StoreOp::Store,
},
},
)],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
},
));
}
#[cfg(any(feature = "svg", feature = "image"))]

View file

@ -42,14 +42,39 @@ pub trait Primitive: Debug + MaybeSend + MaybeSync + 'static {
viewport: &Viewport,
);
/// Renders the [`Primitive`].
/// Draws the [`Primitive`] in the given [`wgpu::RenderPass`].
///
/// When possible, this should be implement over [`render`](Self::render)
/// since reusing the existing render pass should be considerably more
/// efficient than issuing a completely new one.
///
/// If you have complex composition needs, then you can leverage
/// [`render`](Self::render) by returning `false` here.
///
/// By default, it does nothing and returns `false`.
fn draw(
&self,
_renderer: &Self::Renderer,
_render_pass: &mut wgpu::RenderPass<'_>,
_target: &wgpu::TextureView,
_clip_bounds: &Rectangle<u32>,
) -> bool {
false
}
/// Renders the [`Primitive`], using the given [`wgpu::CommandEncoder`].
///
/// This will only be called if [`draw`](Self::draw) returns `false`.
///
/// By default, it does nothing.
fn render(
&self,
renderer: &Self::Renderer,
encoder: &mut wgpu::CommandEncoder,
target: &wgpu::TextureView,
clip_bounds: &Rectangle<u32>,
);
_renderer: &Self::Renderer,
_encoder: &mut wgpu::CommandEncoder,
_target: &wgpu::TextureView,
_clip_bounds: &Rectangle<u32>,
) {
}
}
pub(crate) trait Stored:
@ -65,6 +90,14 @@ pub(crate) trait Stored:
viewport: &Viewport,
);
fn draw(
&self,
storage: &Storage,
render_pass: &mut wgpu::RenderPass<'_>,
target: &wgpu::TextureView,
clip_bounds: &Rectangle<u32>,
) -> bool;
fn render(
&self,
storage: &Storage,
@ -105,6 +138,23 @@ impl<P: Primitive> Stored for BlackBox<P> {
.prepare(renderer, device, queue, bounds, viewport);
}
fn draw(
&self,
storage: &Storage,
render_pass: &mut wgpu::RenderPass<'_>,
target: &wgpu::TextureView,
clip_bounds: &Rectangle<u32>,
) -> bool {
let renderer = storage
.get::<P>()
.expect("renderer should be initialized")
.downcast_ref::<P::Renderer>()
.expect("renderer should have the proper type");
self.primitive
.draw(renderer, render_pass, target, clip_bounds)
}
fn render(
&self,
storage: &Storage,