Refactor triangle::Pipeline into prepare and render architecture
And get rid of the staging belt! 🎉
This commit is contained in:
parent
23ed352e83
commit
b8c1809ea1
7 changed files with 358 additions and 291 deletions
|
|
@ -125,9 +125,6 @@ pub fn main() {
|
|||
|
||||
let mut resized = false;
|
||||
|
||||
// Initialize staging belt
|
||||
let mut staging_belt = wgpu::util::StagingBelt::new(5 * 1024);
|
||||
|
||||
// Initialize scene and GUI controls
|
||||
let scene = Scene::new(&device, format);
|
||||
let controls = Controls::new();
|
||||
|
|
@ -252,7 +249,6 @@ pub fn main() {
|
|||
backend.present(
|
||||
&device,
|
||||
&queue,
|
||||
&mut staging_belt,
|
||||
&mut encoder,
|
||||
&view,
|
||||
primitive,
|
||||
|
|
@ -262,7 +258,6 @@ pub fn main() {
|
|||
});
|
||||
|
||||
// Then we submit the work
|
||||
staging_belt.finish();
|
||||
queue.submit(Some(encoder.finish()));
|
||||
frame.present();
|
||||
|
||||
|
|
@ -272,10 +267,6 @@ pub fn main() {
|
|||
state.mouse_interaction(),
|
||||
),
|
||||
);
|
||||
|
||||
// And recall staging buffers
|
||||
staging_belt.recall();
|
||||
|
||||
}
|
||||
Err(error) => match error {
|
||||
wgpu::SurfaceError::OutOfMemory => {
|
||||
|
|
|
|||
|
|
@ -70,7 +70,6 @@ impl Backend {
|
|||
&mut self,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
staging_belt: &mut wgpu::util::StagingBelt,
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
frame: &wgpu::TextureView,
|
||||
primitives: &[Primitive],
|
||||
|
|
@ -95,7 +94,6 @@ impl Backend {
|
|||
scale_factor,
|
||||
transformation,
|
||||
&layer,
|
||||
staging_belt,
|
||||
encoder,
|
||||
frame,
|
||||
target_size,
|
||||
|
|
@ -104,6 +102,7 @@ impl Backend {
|
|||
|
||||
self.quad_pipeline.end_frame();
|
||||
self.text_pipeline.end_frame();
|
||||
self.triangle_pipeline.end_frame();
|
||||
|
||||
#[cfg(any(feature = "image", feature = "svg"))]
|
||||
self.image_pipeline.end_frame(device, queue, encoder);
|
||||
|
|
@ -116,7 +115,6 @@ impl Backend {
|
|||
scale_factor: f32,
|
||||
transformation: Transformation,
|
||||
layer: &Layer<'_>,
|
||||
staging_belt: &mut wgpu::util::StagingBelt,
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
target: &wgpu::TextureView,
|
||||
target_size: Size<u32>,
|
||||
|
|
@ -159,15 +157,20 @@ impl Backend {
|
|||
let scaled = transformation
|
||||
* Transformation::scale(scale_factor, scale_factor);
|
||||
|
||||
self.triangle_pipeline.draw(
|
||||
self.triangle_pipeline.prepare(
|
||||
device,
|
||||
queue,
|
||||
&layer.meshes,
|
||||
scaled,
|
||||
);
|
||||
|
||||
self.triangle_pipeline.render(
|
||||
device,
|
||||
staging_belt,
|
||||
encoder,
|
||||
target,
|
||||
target_size,
|
||||
scaled,
|
||||
scale_factor,
|
||||
&layer.meshes,
|
||||
scale_factor,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -112,25 +112,8 @@ impl<T: ShaderType + WriteInto> Buffer<T> {
|
|||
}
|
||||
|
||||
/// Write the contents of this dynamic buffer to the GPU via staging belt command.
|
||||
pub fn write(
|
||||
&mut self,
|
||||
device: &wgpu::Device,
|
||||
staging_belt: &mut wgpu::util::StagingBelt,
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
) {
|
||||
let size = self.cpu.get_ref().len();
|
||||
|
||||
if let Some(buffer_size) = wgpu::BufferSize::new(size as u64) {
|
||||
let mut buffer = staging_belt.write_buffer(
|
||||
encoder,
|
||||
&self.gpu,
|
||||
0,
|
||||
buffer_size,
|
||||
device,
|
||||
);
|
||||
|
||||
buffer.copy_from_slice(self.cpu.get_ref());
|
||||
}
|
||||
pub fn write(&mut self, queue: &wgpu::Queue) {
|
||||
queue.write_buffer(&self.gpu, 0, self.cpu.get_ref());
|
||||
}
|
||||
|
||||
// Gets the aligned offset at the given index from the CPU buffer.
|
||||
|
|
@ -184,7 +167,7 @@ impl Internal {
|
|||
}
|
||||
|
||||
/// Returns bytearray of aligned CPU buffer.
|
||||
pub(super) fn get_ref(&self) -> &Vec<u8> {
|
||||
pub(super) fn get_ref(&self) -> &[u8] {
|
||||
match self {
|
||||
Internal::Uniform(buf) => buf.as_ref(),
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::marker::PhantomData;
|
|||
use std::mem;
|
||||
|
||||
//128 triangles/indices
|
||||
const DEFAULT_STATIC_BUFFER_COUNT: wgpu::BufferAddress = 128;
|
||||
const DEFAULT_STATIC_BUFFER_COUNT: wgpu::BufferAddress = 1_000;
|
||||
|
||||
/// A generic buffer struct useful for items which have no alignment requirements
|
||||
/// (e.g. Vertex, Index buffers) & no dynamic offsets.
|
||||
|
|
@ -71,28 +71,15 @@ impl<T: Pod + Zeroable> Buffer<T> {
|
|||
/// Returns the size of the written bytes.
|
||||
pub fn write(
|
||||
&mut self,
|
||||
device: &wgpu::Device,
|
||||
staging_belt: &mut wgpu::util::StagingBelt,
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
queue: &wgpu::Queue,
|
||||
offset: u64,
|
||||
content: &[T],
|
||||
) -> u64 {
|
||||
let bytes = bytemuck::cast_slice(content);
|
||||
let bytes_size = bytes.len() as u64;
|
||||
|
||||
if let Some(buffer_size) = wgpu::BufferSize::new(bytes_size) {
|
||||
let mut buffer = staging_belt.write_buffer(
|
||||
encoder,
|
||||
&self.gpu,
|
||||
offset,
|
||||
buffer_size,
|
||||
device,
|
||||
);
|
||||
|
||||
buffer.copy_from_slice(bytes);
|
||||
|
||||
self.offsets.push(offset);
|
||||
}
|
||||
queue.write_buffer(&self.gpu, offset, bytes);
|
||||
self.offsets.push(offset);
|
||||
|
||||
bytes_size
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use crate::buffer::Buffer;
|
||||
use crate::Transformation;
|
||||
use crate::{Buffer, Transformation};
|
||||
use iced_graphics::layer;
|
||||
use iced_native::Rectangle;
|
||||
|
||||
|
|
@ -228,7 +227,7 @@ impl Layer {
|
|||
let instances = Buffer::new(
|
||||
device,
|
||||
"iced_wgpu::quad instance buffer",
|
||||
MAX_INSTANCES,
|
||||
INITIAL_INSTANCES,
|
||||
wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||
);
|
||||
|
||||
|
|
@ -302,7 +301,7 @@ const QUAD_VERTS: [Vertex; 4] = [
|
|||
},
|
||||
];
|
||||
|
||||
const MAX_INSTANCES: usize = 100_000;
|
||||
const INITIAL_INSTANCES: usize = 10_000;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Zeroable, Pod)]
|
||||
|
|
|
|||
|
|
@ -14,50 +14,56 @@ use tracing::info_span;
|
|||
#[derive(Debug)]
|
||||
pub struct Pipeline {
|
||||
blit: Option<msaa::Blit>,
|
||||
index_buffer: Buffer<u32>,
|
||||
index_strides: Vec<u32>,
|
||||
solid: solid::Pipeline,
|
||||
|
||||
/// Gradients are currently not supported on WASM targets due to their need of storage buffers.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
gradient: gradient::Pipeline,
|
||||
|
||||
layers: Vec<Layer>,
|
||||
prepare_layer: usize,
|
||||
render_layer: usize,
|
||||
}
|
||||
|
||||
impl Pipeline {
|
||||
pub fn new(
|
||||
#[derive(Debug)]
|
||||
struct Layer {
|
||||
index_buffer: Buffer<u32>,
|
||||
index_strides: Vec<u32>,
|
||||
solid: solid::Layer,
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
gradient: gradient::Layer,
|
||||
}
|
||||
|
||||
impl Layer {
|
||||
fn new(
|
||||
device: &wgpu::Device,
|
||||
format: wgpu::TextureFormat,
|
||||
antialiasing: Option<settings::Antialiasing>,
|
||||
) -> Pipeline {
|
||||
Pipeline {
|
||||
blit: antialiasing.map(|a| msaa::Blit::new(device, format, a)),
|
||||
solid: &solid::Pipeline,
|
||||
#[cfg(not(target_arch = "wasm32"))] gradient: &gradient::Pipeline,
|
||||
) -> Self {
|
||||
Self {
|
||||
index_buffer: Buffer::new(
|
||||
device,
|
||||
"iced_wgpu::triangle vertex buffer",
|
||||
wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST,
|
||||
),
|
||||
index_strides: Vec::new(),
|
||||
solid: solid::Pipeline::new(device, format, antialiasing),
|
||||
solid: solid::Layer::new(device, &solid.constants_layout),
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
gradient: gradient::Pipeline::new(device, format, antialiasing),
|
||||
gradient: gradient::Layer::new(device, &gradient.constants_layout),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(
|
||||
fn prepare(
|
||||
&mut self,
|
||||
device: &wgpu::Device,
|
||||
staging_belt: &mut wgpu::util::StagingBelt,
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
target: &wgpu::TextureView,
|
||||
target_size: Size<u32>,
|
||||
transformation: Transformation,
|
||||
scale_factor: f32,
|
||||
queue: &wgpu::Queue,
|
||||
solid: &solid::Pipeline,
|
||||
#[cfg(not(target_arch = "wasm32"))] gradient: &gradient::Pipeline,
|
||||
meshes: &[Mesh<'_>],
|
||||
transformation: Transformation,
|
||||
) {
|
||||
#[cfg(feature = "tracing")]
|
||||
let _ = info_span!("Wgpu::Triangle", "DRAW").entered();
|
||||
|
||||
// Count the total amount of vertices & indices we need to handle
|
||||
let count = mesh::attribute_count_of(meshes);
|
||||
|
||||
|
|
@ -75,6 +81,7 @@ impl Pipeline {
|
|||
.resize(device, count.gradient_vertices);
|
||||
|
||||
// Prepare dynamic buffers & data store for writing
|
||||
self.index_buffer.clear();
|
||||
self.index_strides.clear();
|
||||
self.solid.vertices.clear();
|
||||
self.solid.uniforms.clear();
|
||||
|
|
@ -99,13 +106,8 @@ impl Pipeline {
|
|||
let transform =
|
||||
transformation * Transformation::translate(origin.x, origin.y);
|
||||
|
||||
let new_index_offset = self.index_buffer.write(
|
||||
device,
|
||||
staging_belt,
|
||||
encoder,
|
||||
index_offset,
|
||||
indices,
|
||||
);
|
||||
let new_index_offset =
|
||||
self.index_buffer.write(queue, index_offset, indices);
|
||||
|
||||
index_offset += new_index_offset;
|
||||
self.index_strides.push(indices.len() as u32);
|
||||
|
|
@ -116,9 +118,7 @@ impl Pipeline {
|
|||
self.solid.uniforms.push(&solid::Uniforms::new(transform));
|
||||
|
||||
let written_bytes = self.solid.vertices.write(
|
||||
device,
|
||||
staging_belt,
|
||||
encoder,
|
||||
queue,
|
||||
solid_vertex_offset,
|
||||
&buffers.vertices,
|
||||
);
|
||||
|
|
@ -130,9 +130,7 @@ impl Pipeline {
|
|||
buffers, gradient, ..
|
||||
} => {
|
||||
let written_bytes = self.gradient.vertices.write(
|
||||
device,
|
||||
staging_belt,
|
||||
encoder,
|
||||
queue,
|
||||
gradient_vertex_offset,
|
||||
&buffers.vertices,
|
||||
);
|
||||
|
|
@ -196,14 +194,14 @@ impl Pipeline {
|
|||
let uniforms_resized = self.solid.uniforms.resize(device);
|
||||
|
||||
if uniforms_resized {
|
||||
self.solid.bind_group = solid::Pipeline::bind_group(
|
||||
self.solid.constants = solid::Layer::bind_group(
|
||||
device,
|
||||
self.solid.uniforms.raw(),
|
||||
&self.solid.bind_group_layout,
|
||||
&solid.constants_layout,
|
||||
)
|
||||
}
|
||||
|
||||
self.solid.uniforms.write(device, staging_belt, encoder);
|
||||
self.solid.uniforms.write(queue);
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
|
|
@ -218,22 +216,169 @@ impl Pipeline {
|
|||
let storage_resized = self.gradient.storage.resize(device);
|
||||
|
||||
if uniforms_resized || storage_resized {
|
||||
self.gradient.bind_group = gradient::Pipeline::bind_group(
|
||||
self.gradient.constants = gradient::Layer::bind_group(
|
||||
device,
|
||||
self.gradient.uniforms.raw(),
|
||||
self.gradient.storage.raw(),
|
||||
&self.gradient.bind_group_layout,
|
||||
&gradient.constants_layout,
|
||||
);
|
||||
}
|
||||
|
||||
// Write to GPU
|
||||
self.gradient.uniforms.write(device, staging_belt, encoder);
|
||||
self.gradient.storage.write(device, staging_belt, encoder);
|
||||
self.gradient.uniforms.write(queue);
|
||||
self.gradient.storage.write(queue);
|
||||
|
||||
// Cleanup
|
||||
self.gradient.color_stop_offset = 0;
|
||||
self.gradient.color_stops_pending_write.color_stops.clear();
|
||||
}
|
||||
}
|
||||
|
||||
fn render<'a>(
|
||||
&'a mut self,
|
||||
solid: &'a solid::Pipeline,
|
||||
#[cfg(not(target_arch = "wasm32"))] gradient: &'a gradient::Pipeline,
|
||||
meshes: &[Mesh<'_>],
|
||||
scale_factor: f32,
|
||||
render_pass: &mut wgpu::RenderPass<'a>,
|
||||
) {
|
||||
let mut num_solids = 0;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let mut num_gradients = 0;
|
||||
let mut last_is_solid = None;
|
||||
|
||||
for (index, mesh) in meshes.iter().enumerate() {
|
||||
let clip_bounds = (mesh.clip_bounds() * scale_factor).snap();
|
||||
|
||||
render_pass.set_scissor_rect(
|
||||
clip_bounds.x,
|
||||
clip_bounds.y,
|
||||
clip_bounds.width,
|
||||
clip_bounds.height,
|
||||
);
|
||||
|
||||
match mesh {
|
||||
Mesh::Solid { .. } => {
|
||||
if !last_is_solid.unwrap_or(false) {
|
||||
render_pass.set_pipeline(&solid.pipeline);
|
||||
|
||||
last_is_solid = Some(true);
|
||||
}
|
||||
|
||||
render_pass.set_bind_group(
|
||||
0,
|
||||
&self.solid.constants,
|
||||
&[self.solid.uniforms.offset_at_index(num_solids)],
|
||||
);
|
||||
|
||||
render_pass.set_vertex_buffer(
|
||||
0,
|
||||
self.solid.vertices.slice_from_index(num_solids),
|
||||
);
|
||||
|
||||
num_solids += 1;
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
Mesh::Gradient { .. } => {
|
||||
if last_is_solid.unwrap_or(true) {
|
||||
render_pass.set_pipeline(&gradient.pipeline);
|
||||
|
||||
last_is_solid = Some(false);
|
||||
}
|
||||
|
||||
render_pass.set_bind_group(
|
||||
0,
|
||||
&self.gradient.constants,
|
||||
&[self
|
||||
.gradient
|
||||
.uniforms
|
||||
.offset_at_index(num_gradients)],
|
||||
);
|
||||
|
||||
render_pass.set_vertex_buffer(
|
||||
0,
|
||||
self.gradient.vertices.slice_from_index(num_gradients),
|
||||
);
|
||||
|
||||
num_gradients += 1;
|
||||
}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
Mesh::Gradient { .. } => {}
|
||||
};
|
||||
|
||||
render_pass.set_index_buffer(
|
||||
self.index_buffer.slice_from_index(index),
|
||||
wgpu::IndexFormat::Uint32,
|
||||
);
|
||||
|
||||
render_pass.draw_indexed(0..self.index_strides[index], 0, 0..1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pipeline {
|
||||
pub fn new(
|
||||
device: &wgpu::Device,
|
||||
format: wgpu::TextureFormat,
|
||||
antialiasing: Option<settings::Antialiasing>,
|
||||
) -> Pipeline {
|
||||
Pipeline {
|
||||
blit: antialiasing.map(|a| msaa::Blit::new(device, format, a)),
|
||||
solid: solid::Pipeline::new(device, format, antialiasing),
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
gradient: gradient::Pipeline::new(device, format, antialiasing),
|
||||
|
||||
layers: Vec::new(),
|
||||
prepare_layer: 0,
|
||||
render_layer: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prepare(
|
||||
&mut self,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
meshes: &[Mesh<'_>],
|
||||
transformation: Transformation,
|
||||
) {
|
||||
#[cfg(feature = "tracing")]
|
||||
let _ = info_span!("Wgpu::Triangle", "PREPARE").entered();
|
||||
|
||||
if self.layers.len() <= self.prepare_layer {
|
||||
self.layers.push(Layer::new(
|
||||
device,
|
||||
&self.solid,
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
&self.gradient,
|
||||
));
|
||||
}
|
||||
|
||||
let layer = &mut self.layers[self.prepare_layer];
|
||||
layer.prepare(
|
||||
device,
|
||||
queue,
|
||||
&self.solid,
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
&self.gradient,
|
||||
meshes,
|
||||
transformation,
|
||||
);
|
||||
|
||||
self.prepare_layer += 1;
|
||||
}
|
||||
|
||||
pub fn render(
|
||||
&mut self,
|
||||
device: &wgpu::Device,
|
||||
encoder: &mut wgpu::CommandEncoder,
|
||||
target: &wgpu::TextureView,
|
||||
target_size: Size<u32>,
|
||||
meshes: &[Mesh<'_>],
|
||||
scale_factor: f32,
|
||||
) {
|
||||
#[cfg(feature = "tracing")]
|
||||
let _ = info_span!("Wgpu::Triangle", "DRAW").entered();
|
||||
|
||||
// Configure render pass
|
||||
{
|
||||
|
|
@ -268,87 +413,29 @@ impl Pipeline {
|
|||
depth_stencil_attachment: None,
|
||||
});
|
||||
|
||||
let mut num_solids = 0;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let mut num_gradients = 0;
|
||||
let mut last_is_solid = None;
|
||||
let layer = &mut self.layers[self.render_layer];
|
||||
|
||||
for (index, mesh) in meshes.iter().enumerate() {
|
||||
let clip_bounds = (mesh.clip_bounds() * scale_factor).snap();
|
||||
|
||||
render_pass.set_scissor_rect(
|
||||
clip_bounds.x,
|
||||
clip_bounds.y,
|
||||
clip_bounds.width,
|
||||
clip_bounds.height,
|
||||
);
|
||||
|
||||
match mesh {
|
||||
Mesh::Solid { .. } => {
|
||||
if !last_is_solid.unwrap_or(false) {
|
||||
render_pass.set_pipeline(&self.solid.pipeline);
|
||||
|
||||
last_is_solid = Some(true);
|
||||
}
|
||||
|
||||
render_pass.set_bind_group(
|
||||
0,
|
||||
&self.solid.bind_group,
|
||||
&[self.solid.uniforms.offset_at_index(num_solids)],
|
||||
);
|
||||
|
||||
render_pass.set_vertex_buffer(
|
||||
0,
|
||||
self.solid.vertices.slice_from_index(num_solids),
|
||||
);
|
||||
|
||||
num_solids += 1;
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
Mesh::Gradient { .. } => {
|
||||
if last_is_solid.unwrap_or(true) {
|
||||
render_pass.set_pipeline(&self.gradient.pipeline);
|
||||
|
||||
last_is_solid = Some(false);
|
||||
}
|
||||
|
||||
render_pass.set_bind_group(
|
||||
0,
|
||||
&self.gradient.bind_group,
|
||||
&[self
|
||||
.gradient
|
||||
.uniforms
|
||||
.offset_at_index(num_gradients)],
|
||||
);
|
||||
|
||||
render_pass.set_vertex_buffer(
|
||||
0,
|
||||
self.gradient
|
||||
.vertices
|
||||
.slice_from_index(num_gradients),
|
||||
);
|
||||
|
||||
num_gradients += 1;
|
||||
}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
Mesh::Gradient { .. } => {}
|
||||
};
|
||||
|
||||
render_pass.set_index_buffer(
|
||||
self.index_buffer.slice_from_index(index),
|
||||
wgpu::IndexFormat::Uint32,
|
||||
);
|
||||
|
||||
render_pass.draw_indexed(0..self.index_strides[index], 0, 0..1);
|
||||
}
|
||||
layer.render(
|
||||
&self.solid,
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
&self.gradient,
|
||||
meshes,
|
||||
scale_factor,
|
||||
&mut render_pass,
|
||||
);
|
||||
}
|
||||
|
||||
self.index_buffer.clear();
|
||||
self.render_layer += 1;
|
||||
|
||||
if let Some(blit) = &mut self.blit {
|
||||
blit.draw(encoder, target);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn end_frame(&mut self) {
|
||||
self.prepare_layer = 0;
|
||||
self.render_layer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fn fragment_target(
|
||||
|
|
@ -390,10 +477,62 @@ mod solid {
|
|||
#[derive(Debug)]
|
||||
pub struct Pipeline {
|
||||
pub pipeline: wgpu::RenderPipeline,
|
||||
pub constants_layout: wgpu::BindGroupLayout,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Layer {
|
||||
pub vertices: Buffer<triangle::ColoredVertex2D>,
|
||||
pub uniforms: dynamic::Buffer<Uniforms>,
|
||||
pub bind_group_layout: wgpu::BindGroupLayout,
|
||||
pub bind_group: wgpu::BindGroup,
|
||||
pub constants: wgpu::BindGroup,
|
||||
}
|
||||
|
||||
impl Layer {
|
||||
pub fn new(
|
||||
device: &wgpu::Device,
|
||||
constants_layout: &wgpu::BindGroupLayout,
|
||||
) -> Self {
|
||||
let vertices = Buffer::new(
|
||||
device,
|
||||
"iced_wgpu::triangle::solid vertex buffer",
|
||||
wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||
);
|
||||
|
||||
let uniforms = dynamic::Buffer::uniform(
|
||||
device,
|
||||
"iced_wgpu::triangle::solid uniforms",
|
||||
);
|
||||
|
||||
let constants =
|
||||
Self::bind_group(device, uniforms.raw(), constants_layout);
|
||||
|
||||
Self {
|
||||
vertices,
|
||||
uniforms,
|
||||
constants,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind_group(
|
||||
device: &wgpu::Device,
|
||||
buffer: &wgpu::Buffer,
|
||||
layout: &wgpu::BindGroupLayout,
|
||||
) -> wgpu::BindGroup {
|
||||
device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: Some("iced_wgpu::triangle::solid bind group"),
|
||||
layout,
|
||||
entries: &[wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Buffer(
|
||||
wgpu::BufferBinding {
|
||||
buffer,
|
||||
offset: 0,
|
||||
size: Some(Uniforms::min_size()),
|
||||
},
|
||||
),
|
||||
}],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, ShaderType)]
|
||||
|
|
@ -416,18 +555,7 @@ mod solid {
|
|||
format: wgpu::TextureFormat,
|
||||
antialiasing: Option<settings::Antialiasing>,
|
||||
) -> Self {
|
||||
let vertices = Buffer::new(
|
||||
device,
|
||||
"iced_wgpu::triangle::solid vertex buffer",
|
||||
wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||
);
|
||||
|
||||
let uniforms = dynamic::Buffer::uniform(
|
||||
device,
|
||||
"iced_wgpu::triangle::solid uniforms",
|
||||
);
|
||||
|
||||
let bind_group_layout = device.create_bind_group_layout(
|
||||
let constants_layout = device.create_bind_group_layout(
|
||||
&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("iced_wgpu::triangle::solid bind group layout"),
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
|
|
@ -443,13 +571,10 @@ mod solid {
|
|||
},
|
||||
);
|
||||
|
||||
let bind_group =
|
||||
Self::bind_group(device, uniforms.raw(), &bind_group_layout);
|
||||
|
||||
let layout = device.create_pipeline_layout(
|
||||
&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("iced_wgpu::triangle::solid pipeline layout"),
|
||||
bind_group_layouts: &[&bind_group_layout],
|
||||
bind_group_layouts: &[&constants_layout],
|
||||
push_constant_ranges: &[],
|
||||
},
|
||||
);
|
||||
|
|
@ -501,33 +626,9 @@ mod solid {
|
|||
|
||||
Self {
|
||||
pipeline,
|
||||
vertices,
|
||||
uniforms,
|
||||
bind_group_layout,
|
||||
bind_group,
|
||||
constants_layout,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind_group(
|
||||
device: &wgpu::Device,
|
||||
buffer: &wgpu::Buffer,
|
||||
layout: &wgpu::BindGroupLayout,
|
||||
) -> wgpu::BindGroup {
|
||||
device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: Some("iced_wgpu::triangle::solid bind group"),
|
||||
layout,
|
||||
entries: &[wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Buffer(
|
||||
wgpu::BufferBinding {
|
||||
buffer,
|
||||
offset: 0,
|
||||
size: Some(Uniforms::min_size()),
|
||||
},
|
||||
),
|
||||
}],
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -545,15 +646,90 @@ mod gradient {
|
|||
#[derive(Debug)]
|
||||
pub struct Pipeline {
|
||||
pub pipeline: wgpu::RenderPipeline,
|
||||
pub constants_layout: wgpu::BindGroupLayout,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Layer {
|
||||
pub vertices: Buffer<Vertex2D>,
|
||||
pub uniforms: dynamic::Buffer<Uniforms>,
|
||||
pub storage: dynamic::Buffer<Storage>,
|
||||
pub constants: wgpu::BindGroup,
|
||||
pub color_stop_offset: i32,
|
||||
//Need to store these and then write them all at once
|
||||
//or else they will be padded to 256 and cause gaps in the storage buffer
|
||||
pub color_stops_pending_write: Storage,
|
||||
pub bind_group_layout: wgpu::BindGroupLayout,
|
||||
pub bind_group: wgpu::BindGroup,
|
||||
}
|
||||
|
||||
impl Layer {
|
||||
pub fn new(
|
||||
device: &wgpu::Device,
|
||||
constants_layout: &wgpu::BindGroupLayout,
|
||||
) -> Self {
|
||||
let vertices = Buffer::new(
|
||||
device,
|
||||
"iced_wgpu::triangle::gradient vertex buffer",
|
||||
wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||
);
|
||||
|
||||
let uniforms = dynamic::Buffer::uniform(
|
||||
device,
|
||||
"iced_wgpu::triangle::gradient uniforms",
|
||||
);
|
||||
|
||||
// Note: with a WASM target storage buffers are not supported. Will need to use UBOs & static
|
||||
// sized array (eg like the 32-sized array on OpenGL side right now) to make gradients work
|
||||
let storage = dynamic::Buffer::storage(
|
||||
device,
|
||||
"iced_wgpu::triangle::gradient storage",
|
||||
);
|
||||
|
||||
let constants = Self::bind_group(
|
||||
device,
|
||||
uniforms.raw(),
|
||||
storage.raw(),
|
||||
constants_layout,
|
||||
);
|
||||
|
||||
Self {
|
||||
vertices,
|
||||
uniforms,
|
||||
storage,
|
||||
constants,
|
||||
color_stop_offset: 0,
|
||||
color_stops_pending_write: Storage {
|
||||
color_stops: vec![],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind_group(
|
||||
device: &wgpu::Device,
|
||||
uniform_buffer: &wgpu::Buffer,
|
||||
storage_buffer: &wgpu::Buffer,
|
||||
layout: &wgpu::BindGroupLayout,
|
||||
) -> wgpu::BindGroup {
|
||||
device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: Some("iced_wgpu::triangle::gradient bind group"),
|
||||
layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Buffer(
|
||||
wgpu::BufferBinding {
|
||||
buffer: uniform_buffer,
|
||||
offset: 0,
|
||||
size: Some(Uniforms::min_size()),
|
||||
},
|
||||
),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: storage_buffer.as_entire_binding(),
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, ShaderType)]
|
||||
|
|
@ -584,25 +760,7 @@ mod gradient {
|
|||
format: wgpu::TextureFormat,
|
||||
antialiasing: Option<settings::Antialiasing>,
|
||||
) -> Self {
|
||||
let vertices = Buffer::new(
|
||||
device,
|
||||
"iced_wgpu::triangle::gradient vertex buffer",
|
||||
wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
|
||||
);
|
||||
|
||||
let uniforms = dynamic::Buffer::uniform(
|
||||
device,
|
||||
"iced_wgpu::triangle::gradient uniforms",
|
||||
);
|
||||
|
||||
//Note: with a WASM target storage buffers are not supported. Will need to use UBOs & static
|
||||
// sized array (eg like the 32-sized array on OpenGL side right now) to make gradients work
|
||||
let storage = dynamic::Buffer::storage(
|
||||
device,
|
||||
"iced_wgpu::triangle::gradient storage",
|
||||
);
|
||||
|
||||
let bind_group_layout = device.create_bind_group_layout(
|
||||
let constants_layout = device.create_bind_group_layout(
|
||||
&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some(
|
||||
"iced_wgpu::triangle::gradient bind group layout",
|
||||
|
|
@ -634,19 +792,12 @@ mod gradient {
|
|||
},
|
||||
);
|
||||
|
||||
let bind_group = Pipeline::bind_group(
|
||||
device,
|
||||
uniforms.raw(),
|
||||
storage.raw(),
|
||||
&bind_group_layout,
|
||||
);
|
||||
|
||||
let layout = device.create_pipeline_layout(
|
||||
&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some(
|
||||
"iced_wgpu::triangle::gradient pipeline layout",
|
||||
),
|
||||
bind_group_layouts: &[&bind_group_layout],
|
||||
bind_group_layouts: &[&constants_layout],
|
||||
push_constant_ranges: &[],
|
||||
},
|
||||
);
|
||||
|
|
@ -694,44 +845,8 @@ mod gradient {
|
|||
|
||||
Self {
|
||||
pipeline,
|
||||
vertices,
|
||||
uniforms,
|
||||
storage,
|
||||
color_stop_offset: 0,
|
||||
color_stops_pending_write: Storage {
|
||||
color_stops: vec![],
|
||||
},
|
||||
bind_group_layout,
|
||||
bind_group,
|
||||
constants_layout,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind_group(
|
||||
device: &wgpu::Device,
|
||||
uniform_buffer: &wgpu::Buffer,
|
||||
storage_buffer: &wgpu::Buffer,
|
||||
layout: &wgpu::BindGroupLayout,
|
||||
) -> wgpu::BindGroup {
|
||||
device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: Some("iced_wgpu::triangle::gradient bind group"),
|
||||
layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Buffer(
|
||||
wgpu::BufferBinding {
|
||||
buffer: uniform_buffer,
|
||||
offset: 0,
|
||||
size: Some(Uniforms::min_size()),
|
||||
},
|
||||
),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: storage_buffer.as_entire_binding(),
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,14 +16,11 @@ pub struct Compositor<Theme> {
|
|||
adapter: wgpu::Adapter,
|
||||
device: wgpu::Device,
|
||||
queue: wgpu::Queue,
|
||||
staging_belt: wgpu::util::StagingBelt,
|
||||
format: wgpu::TextureFormat,
|
||||
theme: PhantomData<Theme>,
|
||||
}
|
||||
|
||||
impl<Theme> Compositor<Theme> {
|
||||
const CHUNK_SIZE: u64 = 10 * 1024;
|
||||
|
||||
/// Requests a new [`Compositor`] with the given [`Settings`].
|
||||
///
|
||||
/// Returns `None` if no compatible graphics adapter could be found.
|
||||
|
|
@ -98,15 +95,12 @@ impl<Theme> Compositor<Theme> {
|
|||
.next()
|
||||
.await?;
|
||||
|
||||
let staging_belt = wgpu::util::StagingBelt::new(Self::CHUNK_SIZE);
|
||||
|
||||
Some(Compositor {
|
||||
instance,
|
||||
settings,
|
||||
adapter,
|
||||
device,
|
||||
queue,
|
||||
staging_belt,
|
||||
format,
|
||||
theme: PhantomData,
|
||||
})
|
||||
|
|
@ -228,7 +222,6 @@ impl<Theme> iced_graphics::window::Compositor for Compositor<Theme> {
|
|||
backend.present(
|
||||
&self.device,
|
||||
&self.queue,
|
||||
&mut self.staging_belt,
|
||||
&mut encoder,
|
||||
view,
|
||||
primitives,
|
||||
|
|
@ -238,13 +231,9 @@ impl<Theme> iced_graphics::window::Compositor for Compositor<Theme> {
|
|||
});
|
||||
|
||||
// Submit work
|
||||
self.staging_belt.finish();
|
||||
let _submission = self.queue.submit(Some(encoder.finish()));
|
||||
frame.present();
|
||||
|
||||
// Recall staging buffers
|
||||
self.staging_belt.recall();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Err(error) => match error {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue