Use a StagingBelt in iced_wgpu for regular buffer uploads
This commit is contained in:
parent
1df1cf82f4
commit
2bb53ad6e7
10 changed files with 113 additions and 41 deletions
|
|
@ -129,7 +129,7 @@ cosmic-text = "0.10"
|
||||||
dark-light = "1.0"
|
dark-light = "1.0"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
glam = "0.25"
|
glam = "0.25"
|
||||||
glyphon = "0.5"
|
glyphon = { git = "https://github.com/hecrj/glyphon.git", branch = "use-staging-belt" }
|
||||||
guillotiere = "0.6"
|
guillotiere = "0.6"
|
||||||
half = "2.2"
|
half = "2.2"
|
||||||
image = "0.24"
|
image = "0.24"
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ pub struct Backend {
|
||||||
pipeline_storage: pipeline::Storage,
|
pipeline_storage: pipeline::Storage,
|
||||||
#[cfg(any(feature = "image", feature = "svg"))]
|
#[cfg(any(feature = "image", feature = "svg"))]
|
||||||
image_pipeline: image::Pipeline,
|
image_pipeline: image::Pipeline,
|
||||||
|
staging_belt: wgpu::util::StagingBelt,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Backend {
|
impl Backend {
|
||||||
|
|
@ -61,6 +62,11 @@ impl Backend {
|
||||||
|
|
||||||
#[cfg(any(feature = "image", feature = "svg"))]
|
#[cfg(any(feature = "image", feature = "svg"))]
|
||||||
image_pipeline,
|
image_pipeline,
|
||||||
|
|
||||||
|
// TODO: Resize belt smartly (?)
|
||||||
|
// It would be great if the `StagingBelt` API exposed methods
|
||||||
|
// for introspection to detect when a resize may be worth it.
|
||||||
|
staging_belt: wgpu::util::StagingBelt::new(1024 * 100),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,6 +111,8 @@ impl Backend {
|
||||||
&layers,
|
&layers,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self.staging_belt.finish();
|
||||||
|
|
||||||
self.render(
|
self.render(
|
||||||
device,
|
device,
|
||||||
encoder,
|
encoder,
|
||||||
|
|
@ -123,12 +131,17 @@ impl Backend {
|
||||||
self.image_pipeline.end_frame();
|
self.image_pipeline.end_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
pub fn recall(&mut self) {
|
||||||
|
self.staging_belt.recall();
|
||||||
|
}
|
||||||
|
|
||||||
fn prepare(
|
fn prepare(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
queue: &wgpu::Queue,
|
queue: &wgpu::Queue,
|
||||||
format: wgpu::TextureFormat,
|
format: wgpu::TextureFormat,
|
||||||
_encoder: &mut wgpu::CommandEncoder,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
target_size: Size<u32>,
|
target_size: Size<u32>,
|
||||||
transformation: Transformation,
|
transformation: Transformation,
|
||||||
|
|
@ -144,7 +157,8 @@ impl Backend {
|
||||||
if !layer.quads.is_empty() {
|
if !layer.quads.is_empty() {
|
||||||
self.quad_pipeline.prepare(
|
self.quad_pipeline.prepare(
|
||||||
device,
|
device,
|
||||||
queue,
|
encoder,
|
||||||
|
&mut self.staging_belt,
|
||||||
&layer.quads,
|
&layer.quads,
|
||||||
transformation,
|
transformation,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
|
|
@ -157,7 +171,8 @@ impl Backend {
|
||||||
|
|
||||||
self.triangle_pipeline.prepare(
|
self.triangle_pipeline.prepare(
|
||||||
device,
|
device,
|
||||||
queue,
|
encoder,
|
||||||
|
&mut self.staging_belt,
|
||||||
&layer.meshes,
|
&layer.meshes,
|
||||||
scaled,
|
scaled,
|
||||||
);
|
);
|
||||||
|
|
@ -171,8 +186,8 @@ impl Backend {
|
||||||
|
|
||||||
self.image_pipeline.prepare(
|
self.image_pipeline.prepare(
|
||||||
device,
|
device,
|
||||||
queue,
|
encoder,
|
||||||
_encoder,
|
&mut self.staging_belt,
|
||||||
&layer.images,
|
&layer.images,
|
||||||
scaled,
|
scaled,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
|
|
@ -184,6 +199,7 @@ impl Backend {
|
||||||
self.text_pipeline.prepare(
|
self.text_pipeline.prepare(
|
||||||
device,
|
device,
|
||||||
queue,
|
queue,
|
||||||
|
encoder,
|
||||||
&layer.text,
|
&layer.text,
|
||||||
layer.bounds,
|
layer.bounds,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
|
|
|
||||||
|
|
@ -61,12 +61,22 @@ impl<T: bytemuck::Pod> Buffer<T> {
|
||||||
/// Returns the size of the written bytes.
|
/// Returns the size of the written bytes.
|
||||||
pub fn write(
|
pub fn write(
|
||||||
&mut self,
|
&mut self,
|
||||||
queue: &wgpu::Queue,
|
device: &wgpu::Device,
|
||||||
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
|
belt: &mut wgpu::util::StagingBelt,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
contents: &[T],
|
contents: &[T],
|
||||||
) -> usize {
|
) -> usize {
|
||||||
let bytes: &[u8] = bytemuck::cast_slice(contents);
|
let bytes: &[u8] = bytemuck::cast_slice(contents);
|
||||||
queue.write_buffer(&self.raw, offset as u64, bytes);
|
|
||||||
|
belt.write_buffer(
|
||||||
|
encoder,
|
||||||
|
&self.raw,
|
||||||
|
offset as u64,
|
||||||
|
(bytes.len() as u64).try_into().expect("Non-empty write"),
|
||||||
|
device,
|
||||||
|
)
|
||||||
|
.copy_from_slice(bytes);
|
||||||
|
|
||||||
self.offsets.push(offset as u64);
|
self.offsets.push(offset as u64);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,21 +83,31 @@ impl Layer {
|
||||||
fn prepare(
|
fn prepare(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
queue: &wgpu::Queue,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
|
belt: &mut wgpu::util::StagingBelt,
|
||||||
nearest_instances: &[Instance],
|
nearest_instances: &[Instance],
|
||||||
linear_instances: &[Instance],
|
linear_instances: &[Instance],
|
||||||
transformation: Transformation,
|
transformation: Transformation,
|
||||||
) {
|
) {
|
||||||
queue.write_buffer(
|
let uniforms = Uniforms {
|
||||||
|
transform: transformation.into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let bytes = bytemuck::bytes_of(&uniforms);
|
||||||
|
|
||||||
|
belt.write_buffer(
|
||||||
|
encoder,
|
||||||
&self.uniforms,
|
&self.uniforms,
|
||||||
0,
|
0,
|
||||||
bytemuck::bytes_of(&Uniforms {
|
(bytes.len() as u64).try_into().expect("Sized uniforms"),
|
||||||
transform: transformation.into(),
|
device,
|
||||||
}),
|
)
|
||||||
);
|
.copy_from_slice(bytes);
|
||||||
|
|
||||||
self.nearest.upload(device, queue, nearest_instances);
|
self.nearest
|
||||||
self.linear.upload(device, queue, linear_instances);
|
.upload(device, encoder, belt, nearest_instances);
|
||||||
|
|
||||||
|
self.linear.upload(device, encoder, belt, linear_instances);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) {
|
fn render<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) {
|
||||||
|
|
@ -158,7 +168,8 @@ impl Data {
|
||||||
fn upload(
|
fn upload(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
queue: &wgpu::Queue,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
|
belt: &mut wgpu::util::StagingBelt,
|
||||||
instances: &[Instance],
|
instances: &[Instance],
|
||||||
) {
|
) {
|
||||||
self.instance_count = instances.len();
|
self.instance_count = instances.len();
|
||||||
|
|
@ -168,7 +179,7 @@ impl Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = self.instances.resize(device, instances.len());
|
let _ = self.instances.resize(device, instances.len());
|
||||||
let _ = self.instances.write(queue, 0, instances);
|
let _ = self.instances.write(device, encoder, belt, 0, instances);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) {
|
fn render<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) {
|
||||||
|
|
@ -383,8 +394,8 @@ impl Pipeline {
|
||||||
pub fn prepare(
|
pub fn prepare(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
queue: &wgpu::Queue,
|
|
||||||
encoder: &mut wgpu::CommandEncoder,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
|
belt: &mut wgpu::util::StagingBelt,
|
||||||
images: &[layer::Image],
|
images: &[layer::Image],
|
||||||
transformation: Transformation,
|
transformation: Transformation,
|
||||||
_scale: f32,
|
_scale: f32,
|
||||||
|
|
@ -501,7 +512,8 @@ impl Pipeline {
|
||||||
|
|
||||||
layer.prepare(
|
layer.prepare(
|
||||||
device,
|
device,
|
||||||
queue,
|
encoder,
|
||||||
|
belt,
|
||||||
nearest_instances,
|
nearest_instances,
|
||||||
linear_instances,
|
linear_instances,
|
||||||
transformation,
|
transformation,
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,8 @@ impl Pipeline {
|
||||||
pub fn prepare(
|
pub fn prepare(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
queue: &wgpu::Queue,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
|
belt: &mut wgpu::util::StagingBelt,
|
||||||
quads: &Batch,
|
quads: &Batch,
|
||||||
transformation: Transformation,
|
transformation: Transformation,
|
||||||
scale: f32,
|
scale: f32,
|
||||||
|
|
@ -67,7 +68,7 @@ impl Pipeline {
|
||||||
}
|
}
|
||||||
|
|
||||||
let layer = &mut self.layers[self.prepare_layer];
|
let layer = &mut self.layers[self.prepare_layer];
|
||||||
layer.prepare(device, queue, quads, transformation, scale);
|
layer.prepare(device, encoder, belt, quads, transformation, scale);
|
||||||
|
|
||||||
self.prepare_layer += 1;
|
self.prepare_layer += 1;
|
||||||
}
|
}
|
||||||
|
|
@ -162,7 +163,8 @@ impl Layer {
|
||||||
pub fn prepare(
|
pub fn prepare(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
queue: &wgpu::Queue,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
|
belt: &mut wgpu::util::StagingBelt,
|
||||||
quads: &Batch,
|
quads: &Batch,
|
||||||
transformation: Transformation,
|
transformation: Transformation,
|
||||||
scale: f32,
|
scale: f32,
|
||||||
|
|
@ -171,15 +173,25 @@ impl Layer {
|
||||||
let _ = info_span!("Wgpu::Quad", "PREPARE").entered();
|
let _ = info_span!("Wgpu::Quad", "PREPARE").entered();
|
||||||
|
|
||||||
let uniforms = Uniforms::new(transformation, scale);
|
let uniforms = Uniforms::new(transformation, scale);
|
||||||
|
let bytes = bytemuck::bytes_of(&uniforms);
|
||||||
|
|
||||||
queue.write_buffer(
|
belt.write_buffer(
|
||||||
|
encoder,
|
||||||
&self.constants_buffer,
|
&self.constants_buffer,
|
||||||
0,
|
0,
|
||||||
bytemuck::bytes_of(&uniforms),
|
(bytes.len() as u64).try_into().expect("Sized uniforms"),
|
||||||
);
|
device,
|
||||||
|
)
|
||||||
|
.copy_from_slice(bytes);
|
||||||
|
|
||||||
self.solid.prepare(device, queue, &quads.solids);
|
if !quads.solids.is_empty() {
|
||||||
self.gradient.prepare(device, queue, &quads.gradients);
|
self.solid.prepare(device, encoder, belt, &quads.solids);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !quads.gradients.is_empty() {
|
||||||
|
self.gradient
|
||||||
|
.prepare(device, encoder, belt, &quads.gradients);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,11 +46,12 @@ impl Layer {
|
||||||
pub fn prepare(
|
pub fn prepare(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
queue: &wgpu::Queue,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
|
belt: &mut wgpu::util::StagingBelt,
|
||||||
instances: &[Gradient],
|
instances: &[Gradient],
|
||||||
) {
|
) {
|
||||||
let _ = self.instances.resize(device, instances.len());
|
let _ = self.instances.resize(device, instances.len());
|
||||||
let _ = self.instances.write(queue, 0, instances);
|
let _ = self.instances.write(device, encoder, belt, 0, instances);
|
||||||
|
|
||||||
self.instance_count = instances.len();
|
self.instance_count = instances.len();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,11 +40,12 @@ impl Layer {
|
||||||
pub fn prepare(
|
pub fn prepare(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
queue: &wgpu::Queue,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
|
belt: &mut wgpu::util::StagingBelt,
|
||||||
instances: &[Solid],
|
instances: &[Solid],
|
||||||
) {
|
) {
|
||||||
let _ = self.instances.resize(device, instances.len());
|
let _ = self.instances.resize(device, instances.len());
|
||||||
let _ = self.instances.write(queue, 0, instances);
|
let _ = self.instances.write(device, encoder, belt, 0, instances);
|
||||||
|
|
||||||
self.instance_count = instances.len();
|
self.instance_count = instances.len();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ impl Pipeline {
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
queue: &wgpu::Queue,
|
queue: &wgpu::Queue,
|
||||||
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
sections: &[Text<'_>],
|
sections: &[Text<'_>],
|
||||||
layer_bounds: Rectangle,
|
layer_bounds: Rectangle,
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
|
|
@ -262,6 +263,7 @@ impl Pipeline {
|
||||||
let result = renderer.prepare(
|
let result = renderer.prepare(
|
||||||
device,
|
device,
|
||||||
queue,
|
queue,
|
||||||
|
encoder,
|
||||||
font_system,
|
font_system,
|
||||||
&mut self.atlas,
|
&mut self.atlas,
|
||||||
glyphon::Resolution {
|
glyphon::Resolution {
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,8 @@ impl Layer {
|
||||||
fn prepare(
|
fn prepare(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
queue: &wgpu::Queue,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
|
belt: &mut wgpu::util::StagingBelt,
|
||||||
solid: &solid::Pipeline,
|
solid: &solid::Pipeline,
|
||||||
gradient: &gradient::Pipeline,
|
gradient: &gradient::Pipeline,
|
||||||
meshes: &[Mesh<'_>],
|
meshes: &[Mesh<'_>],
|
||||||
|
|
@ -103,33 +104,47 @@ impl Layer {
|
||||||
let uniforms =
|
let uniforms =
|
||||||
Uniforms::new(transformation * mesh.transformation());
|
Uniforms::new(transformation * mesh.transformation());
|
||||||
|
|
||||||
index_offset +=
|
index_offset += self.index_buffer.write(
|
||||||
self.index_buffer.write(queue, index_offset, indices);
|
device,
|
||||||
|
encoder,
|
||||||
|
belt,
|
||||||
|
index_offset,
|
||||||
|
indices,
|
||||||
|
);
|
||||||
|
|
||||||
self.index_strides.push(indices.len() as u32);
|
self.index_strides.push(indices.len() as u32);
|
||||||
|
|
||||||
match mesh {
|
match mesh {
|
||||||
Mesh::Solid { buffers, .. } => {
|
Mesh::Solid { buffers, .. } => {
|
||||||
solid_vertex_offset += self.solid.vertices.write(
|
solid_vertex_offset += self.solid.vertices.write(
|
||||||
queue,
|
device,
|
||||||
|
encoder,
|
||||||
|
belt,
|
||||||
solid_vertex_offset,
|
solid_vertex_offset,
|
||||||
&buffers.vertices,
|
&buffers.vertices,
|
||||||
);
|
);
|
||||||
|
|
||||||
solid_uniform_offset += self.solid.uniforms.write(
|
solid_uniform_offset += self.solid.uniforms.write(
|
||||||
queue,
|
device,
|
||||||
|
encoder,
|
||||||
|
belt,
|
||||||
solid_uniform_offset,
|
solid_uniform_offset,
|
||||||
&[uniforms],
|
&[uniforms],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Mesh::Gradient { buffers, .. } => {
|
Mesh::Gradient { buffers, .. } => {
|
||||||
gradient_vertex_offset += self.gradient.vertices.write(
|
gradient_vertex_offset += self.gradient.vertices.write(
|
||||||
queue,
|
device,
|
||||||
|
encoder,
|
||||||
|
belt,
|
||||||
gradient_vertex_offset,
|
gradient_vertex_offset,
|
||||||
&buffers.vertices,
|
&buffers.vertices,
|
||||||
);
|
);
|
||||||
|
|
||||||
gradient_uniform_offset += self.gradient.uniforms.write(
|
gradient_uniform_offset += self.gradient.uniforms.write(
|
||||||
queue,
|
device,
|
||||||
|
encoder,
|
||||||
|
belt,
|
||||||
gradient_uniform_offset,
|
gradient_uniform_offset,
|
||||||
&[uniforms],
|
&[uniforms],
|
||||||
);
|
);
|
||||||
|
|
@ -237,7 +252,8 @@ impl Pipeline {
|
||||||
pub fn prepare(
|
pub fn prepare(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
queue: &wgpu::Queue,
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
|
belt: &mut wgpu::util::StagingBelt,
|
||||||
meshes: &[Mesh<'_>],
|
meshes: &[Mesh<'_>],
|
||||||
transformation: Transformation,
|
transformation: Transformation,
|
||||||
) {
|
) {
|
||||||
|
|
@ -252,7 +268,8 @@ impl Pipeline {
|
||||||
let layer = &mut self.layers[self.prepare_layer];
|
let layer = &mut self.layers[self.prepare_layer];
|
||||||
layer.prepare(
|
layer.prepare(
|
||||||
device,
|
device,
|
||||||
queue,
|
encoder,
|
||||||
|
belt,
|
||||||
&self.solid,
|
&self.solid,
|
||||||
&self.gradient,
|
&self.gradient,
|
||||||
meshes,
|
meshes,
|
||||||
|
|
|
||||||
|
|
@ -243,6 +243,7 @@ pub fn present<T: AsRef<str>>(
|
||||||
|
|
||||||
// Submit work
|
// Submit work
|
||||||
let _submission = compositor.queue.submit(Some(encoder.finish()));
|
let _submission = compositor.queue.submit(Some(encoder.finish()));
|
||||||
|
backend.recall();
|
||||||
frame.present();
|
frame.present();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue