Redesign iced_wgpu layering architecture
This commit is contained in:
parent
99a904112c
commit
b05e61f5c8
36 changed files with 2781 additions and 2048 deletions
286
wgpu/src/quad.rs
286
wgpu/src/quad.rs
|
|
@ -12,11 +12,37 @@ use bytemuck::{Pod, Zeroable};
|
|||
|
||||
use std::mem;
|
||||
|
||||
#[cfg(feature = "tracing")]
|
||||
use tracing::info_span;
|
||||
|
||||
const INITIAL_INSTANCES: usize = 2_000;
|
||||
|
||||
/// The properties of a quad.
|
||||
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
|
||||
#[repr(C)]
|
||||
pub struct Quad {
|
||||
/// The position of the [`Quad`].
|
||||
pub position: [f32; 2],
|
||||
|
||||
/// The size of the [`Quad`].
|
||||
pub size: [f32; 2],
|
||||
|
||||
/// The border color of the [`Quad`], in __linear RGB__.
|
||||
pub border_color: color::Packed,
|
||||
|
||||
/// The border radii of the [`Quad`].
|
||||
pub border_radius: [f32; 4],
|
||||
|
||||
/// The border width of the [`Quad`].
|
||||
pub border_width: f32,
|
||||
|
||||
/// The shadow color of the [`Quad`].
|
||||
pub shadow_color: color::Packed,
|
||||
|
||||
/// The shadow offset of the [`Quad`].
|
||||
pub shadow_offset: [f32; 2],
|
||||
|
||||
/// The shadow blur radius of the [`Quad`].
|
||||
pub shadow_blur_radius: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Pipeline {
|
||||
solid: solid::Pipeline,
|
||||
|
|
@ -54,7 +80,7 @@ impl Pipeline {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn prepare(
|
||||
pub fn prepare_batch(
|
||||
&mut self,
|
||||
device: &wgpu::Device,
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
|
|
@ -73,7 +99,64 @@ impl Pipeline {
|
|||
self.prepare_layer += 1;
|
||||
}
|
||||
|
||||
pub fn render<'a>(
|
||||
pub fn prepare_cache(
|
||||
&self,
|
||||
device: &wgpu::Device,
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
belt: &mut wgpu::util::StagingBelt,
|
||||
cache: &mut Cache,
|
||||
transformation: Transformation,
|
||||
scale: f32,
|
||||
) {
|
||||
match cache {
|
||||
Cache::Staged(_) => {
|
||||
let Cache::Staged(batch) =
|
||||
std::mem::replace(cache, Cache::Staged(Batch::default()))
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let mut layer = Layer::new(device, &self.constant_layout);
|
||||
layer.prepare(
|
||||
device,
|
||||
encoder,
|
||||
belt,
|
||||
&batch,
|
||||
transformation,
|
||||
scale,
|
||||
);
|
||||
|
||||
*cache = Cache::Uploaded {
|
||||
layer,
|
||||
batch,
|
||||
needs_reupload: false,
|
||||
}
|
||||
}
|
||||
|
||||
Cache::Uploaded {
|
||||
batch,
|
||||
layer,
|
||||
needs_reupload,
|
||||
} => {
|
||||
if *needs_reupload {
|
||||
layer.prepare(
|
||||
device,
|
||||
encoder,
|
||||
belt,
|
||||
batch,
|
||||
transformation,
|
||||
scale,
|
||||
);
|
||||
|
||||
*needs_reupload = false;
|
||||
} else {
|
||||
layer.update(device, encoder, belt, transformation, scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_batch<'a>(
|
||||
&'a self,
|
||||
layer: usize,
|
||||
bounds: Rectangle<u32>,
|
||||
|
|
@ -81,38 +164,59 @@ impl Pipeline {
|
|||
render_pass: &mut wgpu::RenderPass<'a>,
|
||||
) {
|
||||
if let Some(layer) = self.layers.get(layer) {
|
||||
render_pass.set_scissor_rect(
|
||||
bounds.x,
|
||||
bounds.y,
|
||||
bounds.width,
|
||||
bounds.height,
|
||||
);
|
||||
self.render(bounds, layer, &quads.order, render_pass);
|
||||
}
|
||||
}
|
||||
|
||||
let mut solid_offset = 0;
|
||||
let mut gradient_offset = 0;
|
||||
pub fn render_cache<'a>(
|
||||
&'a self,
|
||||
cache: &'a Cache,
|
||||
bounds: Rectangle<u32>,
|
||||
render_pass: &mut wgpu::RenderPass<'a>,
|
||||
) {
|
||||
if let Cache::Uploaded { layer, batch, .. } = cache {
|
||||
self.render(bounds, layer, &batch.order, render_pass);
|
||||
}
|
||||
}
|
||||
|
||||
for (kind, count) in &quads.order {
|
||||
match kind {
|
||||
Kind::Solid => {
|
||||
self.solid.render(
|
||||
render_pass,
|
||||
&layer.constants,
|
||||
&layer.solid,
|
||||
solid_offset..(solid_offset + count),
|
||||
);
|
||||
fn render<'a>(
|
||||
&'a self,
|
||||
bounds: Rectangle<u32>,
|
||||
layer: &'a Layer,
|
||||
order: &Order,
|
||||
render_pass: &mut wgpu::RenderPass<'a>,
|
||||
) {
|
||||
render_pass.set_scissor_rect(
|
||||
bounds.x,
|
||||
bounds.y,
|
||||
bounds.width,
|
||||
bounds.height,
|
||||
);
|
||||
|
||||
solid_offset += count;
|
||||
}
|
||||
Kind::Gradient => {
|
||||
self.gradient.render(
|
||||
render_pass,
|
||||
&layer.constants,
|
||||
&layer.gradient,
|
||||
gradient_offset..(gradient_offset + count),
|
||||
);
|
||||
let mut solid_offset = 0;
|
||||
let mut gradient_offset = 0;
|
||||
|
||||
gradient_offset += count;
|
||||
}
|
||||
for (kind, count) in order {
|
||||
match kind {
|
||||
Kind::Solid => {
|
||||
self.solid.render(
|
||||
render_pass,
|
||||
&layer.constants,
|
||||
&layer.solid,
|
||||
solid_offset..(solid_offset + count),
|
||||
);
|
||||
|
||||
solid_offset += count;
|
||||
}
|
||||
Kind::Gradient => {
|
||||
self.gradient.render(
|
||||
render_pass,
|
||||
&layer.constants,
|
||||
&layer.gradient,
|
||||
gradient_offset..(gradient_offset + count),
|
||||
);
|
||||
|
||||
gradient_offset += count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -124,7 +228,49 @@ impl Pipeline {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Layer {
|
||||
pub enum Cache {
|
||||
Staged(Batch),
|
||||
Uploaded {
|
||||
batch: Batch,
|
||||
layer: Layer,
|
||||
needs_reupload: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl Cache {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
Cache::Staged(batch) | Cache::Uploaded { batch, .. } => {
|
||||
batch.is_empty()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, new_batch: Batch) {
|
||||
match self {
|
||||
Self::Staged(batch) => {
|
||||
*batch = new_batch;
|
||||
}
|
||||
Self::Uploaded {
|
||||
batch,
|
||||
needs_reupload,
|
||||
..
|
||||
} => {
|
||||
*batch = new_batch;
|
||||
*needs_reupload = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Cache {
|
||||
fn default() -> Self {
|
||||
Self::Staged(Batch::default())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Layer {
|
||||
constants: wgpu::BindGroup,
|
||||
constants_buffer: wgpu::Buffer,
|
||||
solid: solid::Layer,
|
||||
|
|
@ -169,9 +315,26 @@ impl Layer {
|
|||
transformation: Transformation,
|
||||
scale: f32,
|
||||
) {
|
||||
#[cfg(feature = "tracing")]
|
||||
let _ = info_span!("Wgpu::Quad", "PREPARE").entered();
|
||||
self.update(device, encoder, belt, transformation, scale);
|
||||
|
||||
if !quads.solids.is_empty() {
|
||||
self.solid.prepare(device, encoder, belt, &quads.solids);
|
||||
}
|
||||
|
||||
if !quads.gradients.is_empty() {
|
||||
self.gradient
|
||||
.prepare(device, encoder, belt, &quads.gradients);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
device: &wgpu::Device,
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
belt: &mut wgpu::util::StagingBelt,
|
||||
transformation: Transformation,
|
||||
scale: f32,
|
||||
) {
|
||||
let uniforms = Uniforms::new(transformation, scale);
|
||||
let bytes = bytemuck::bytes_of(&uniforms);
|
||||
|
||||
|
|
@ -183,47 +346,9 @@ impl Layer {
|
|||
device,
|
||||
)
|
||||
.copy_from_slice(bytes);
|
||||
|
||||
if !quads.solids.is_empty() {
|
||||
self.solid.prepare(device, encoder, belt, &quads.solids);
|
||||
}
|
||||
|
||||
if !quads.gradients.is_empty() {
|
||||
self.gradient
|
||||
.prepare(device, encoder, belt, &quads.gradients);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The properties of a quad.
|
||||
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
|
||||
#[repr(C)]
|
||||
pub struct Quad {
|
||||
/// The position of the [`Quad`].
|
||||
pub position: [f32; 2],
|
||||
|
||||
/// The size of the [`Quad`].
|
||||
pub size: [f32; 2],
|
||||
|
||||
/// The border color of the [`Quad`], in __linear RGB__.
|
||||
pub border_color: color::Packed,
|
||||
|
||||
/// The border radii of the [`Quad`].
|
||||
pub border_radius: [f32; 4],
|
||||
|
||||
/// The border width of the [`Quad`].
|
||||
pub border_width: f32,
|
||||
|
||||
/// The shadow color of the [`Quad`].
|
||||
pub shadow_color: [f32; 4],
|
||||
|
||||
/// The shadow offset of the [`Quad`].
|
||||
pub shadow_offset: [f32; 2],
|
||||
|
||||
/// The shadow blur radius of the [`Quad`].
|
||||
pub shadow_blur_radius: f32,
|
||||
}
|
||||
|
||||
/// A group of [`Quad`]s rendered together.
|
||||
#[derive(Default, Debug)]
|
||||
pub struct Batch {
|
||||
|
|
@ -233,10 +358,13 @@ pub struct Batch {
|
|||
/// The gradient quads of the [`Layer`].
|
||||
gradients: Vec<Gradient>,
|
||||
|
||||
/// The quad order of the [`Layer`]; stored as a tuple of the quad type & its count.
|
||||
order: Vec<(Kind, usize)>,
|
||||
/// The quad order of the [`Layer`].
|
||||
order: Order,
|
||||
}
|
||||
|
||||
/// The quad order of a [`Layer`]; stored as a tuple of the quad type & its count.
|
||||
type Order = Vec<(Kind, usize)>;
|
||||
|
||||
impl Batch {
|
||||
/// Returns true if there are no quads of any type in [`Quads`].
|
||||
pub fn is_empty(&self) -> bool {
|
||||
|
|
@ -276,6 +404,12 @@ impl Batch {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.solids.clear();
|
||||
self.gradients.clear();
|
||||
self.order.clear();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue