Introduce lightweight draw for wgpu::Primitive
This commit is contained in:
parent
53a98bf7de
commit
0d05ea56d3
2 changed files with 95 additions and 27 deletions
|
|
@ -534,7 +534,6 @@ impl Renderer {
|
||||||
|
|
||||||
if !layer.primitives.is_empty() {
|
if !layer.primitives.is_empty() {
|
||||||
let render_span = debug::render(debug::Primitive::Shader);
|
let render_span = debug::render(debug::Primitive::Shader);
|
||||||
let _ = ManuallyDrop::into_inner(render_pass);
|
|
||||||
|
|
||||||
let primitive_storage = self
|
let primitive_storage = self
|
||||||
.engine
|
.engine
|
||||||
|
|
@ -542,11 +541,30 @@ impl Renderer {
|
||||||
.read()
|
.read()
|
||||||
.expect("Read primitive storage");
|
.expect("Read primitive storage");
|
||||||
|
|
||||||
|
let mut need_render = Vec::new();
|
||||||
|
|
||||||
for instance in &layer.primitives {
|
for instance in &layer.primitives {
|
||||||
if let Some(clip_bounds) = (instance.bounds * scale)
|
if let Some(clip_bounds) = (instance.bounds * scale)
|
||||||
.intersection(&physical_bounds)
|
.intersection(&physical_bounds)
|
||||||
.and_then(Rectangle::snap)
|
.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(
|
instance.primitive.render(
|
||||||
&primitive_storage,
|
&primitive_storage,
|
||||||
encoder,
|
encoder,
|
||||||
|
|
@ -554,29 +572,29 @@ impl Renderer {
|
||||||
&clip_bounds,
|
&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_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"))]
|
#[cfg(any(feature = "svg", feature = "image"))]
|
||||||
|
|
|
||||||
|
|
@ -42,14 +42,39 @@ pub trait Primitive: Debug + MaybeSend + MaybeSync + 'static {
|
||||||
viewport: &Viewport,
|
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(
|
fn render(
|
||||||
&self,
|
&self,
|
||||||
renderer: &Self::Renderer,
|
_renderer: &Self::Renderer,
|
||||||
encoder: &mut wgpu::CommandEncoder,
|
_encoder: &mut wgpu::CommandEncoder,
|
||||||
target: &wgpu::TextureView,
|
_target: &wgpu::TextureView,
|
||||||
clip_bounds: &Rectangle<u32>,
|
_clip_bounds: &Rectangle<u32>,
|
||||||
);
|
) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait Stored:
|
pub(crate) trait Stored:
|
||||||
|
|
@ -65,6 +90,14 @@ pub(crate) trait Stored:
|
||||||
viewport: &Viewport,
|
viewport: &Viewport,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
fn draw(
|
||||||
|
&self,
|
||||||
|
storage: &Storage,
|
||||||
|
render_pass: &mut wgpu::RenderPass<'_>,
|
||||||
|
target: &wgpu::TextureView,
|
||||||
|
clip_bounds: &Rectangle<u32>,
|
||||||
|
) -> bool;
|
||||||
|
|
||||||
fn render(
|
fn render(
|
||||||
&self,
|
&self,
|
||||||
storage: &Storage,
|
storage: &Storage,
|
||||||
|
|
@ -105,6 +138,23 @@ impl<P: Primitive> Stored for BlackBox<P> {
|
||||||
.prepare(renderer, device, queue, bounds, viewport);
|
.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(
|
fn render(
|
||||||
&self,
|
&self,
|
||||||
storage: &Storage,
|
storage: &Storage,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue