summaryrefslogtreecommitdiffstats
path: root/wgpu
diff options
context:
space:
mode:
Diffstat (limited to 'wgpu')
-rw-r--r--wgpu/Cargo.toml11
-rw-r--r--wgpu/README.md2
-rw-r--r--wgpu/src/backend.rs42
-rw-r--r--wgpu/src/image.rs129
-rw-r--r--wgpu/src/image/atlas.rs41
-rw-r--r--wgpu/src/image/vector.rs27
-rw-r--r--wgpu/src/quad.rs134
-rw-r--r--wgpu/src/settings.rs58
-rw-r--r--wgpu/src/shader/blit.frag12
-rw-r--r--wgpu/src/shader/blit.frag.spvbin684 -> 0 bytes
-rw-r--r--wgpu/src/shader/blit.vert26
-rw-r--r--wgpu/src/shader/blit.vert.spvbin1384 -> 0 bytes
-rw-r--r--wgpu/src/shader/blit.wgsl43
-rw-r--r--wgpu/src/shader/image.frag12
-rw-r--r--wgpu/src/shader/image.frag.spvbin684 -> 0 bytes
-rw-r--r--wgpu/src/shader/image.vert27
-rw-r--r--wgpu/src/shader/image.vert.spvbin2504 -> 0 bytes
-rw-r--r--wgpu/src/shader/image.wgsl47
-rw-r--r--wgpu/src/shader/quad.frag66
-rw-r--r--wgpu/src/shader/quad.frag.spvbin4212 -> 0 bytes
-rw-r--r--wgpu/src/shader/quad.vert47
-rw-r--r--wgpu/src/shader/quad.vert.spvbin3604 -> 0 bytes
-rw-r--r--wgpu/src/shader/quad.wgsl122
-rw-r--r--wgpu/src/shader/triangle.frag8
-rw-r--r--wgpu/src/shader/triangle.frag.spvbin372 -> 0 bytes
-rw-r--r--wgpu/src/shader/triangle.vert15
-rw-r--r--wgpu/src/shader/triangle.vert.spvbin1256 -> 0 bytes
-rw-r--r--wgpu/src/shader/triangle.wgsl31
-rw-r--r--wgpu/src/text.rs95
-rw-r--r--wgpu/src/triangle.rs125
-rw-r--r--wgpu/src/triangle/msaa.rs81
-rw-r--r--wgpu/src/widget.rs3
-rw-r--r--wgpu/src/widget/pane_grid.rs2
-rw-r--r--wgpu/src/widget/toggler.rs9
-rw-r--r--wgpu/src/window/compositor.rs185
35 files changed, 798 insertions, 602 deletions
diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml
index aa39f068..a904fe87 100644
--- a/wgpu/Cargo.toml
+++ b/wgpu/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "iced_wgpu"
-version = "0.3.0"
+version = "0.4.0"
authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
edition = "2018"
description = "A wgpu renderer for Iced"
@@ -24,10 +24,11 @@ farbfeld = ["image_rs/farbfeld"]
canvas = ["iced_graphics/canvas"]
qr_code = ["iced_graphics/qr_code"]
default_system_font = ["iced_graphics/font-source"]
+spirv = ["wgpu/spirv"]
[dependencies]
-wgpu = "0.7"
-wgpu_glyph = "0.11"
+wgpu = "0.10"
+wgpu_glyph = "0.14"
glyph_brush = "0.7"
raw-window-handle = "0.3"
log = "0.4"
@@ -39,11 +40,11 @@ version = "1.4"
features = ["derive"]
[dependencies.iced_native]
-version = "0.3"
+version = "0.4"
path = "../native"
[dependencies.iced_graphics]
-version = "0.1"
+version = "0.2"
path = "../graphics"
features = ["font-fallback", "font-icons"]
diff --git a/wgpu/README.md b/wgpu/README.md
index e8cb0a43..a9d95ea7 100644
--- a/wgpu/README.md
+++ b/wgpu/README.md
@@ -29,7 +29,7 @@ Currently, `iced_wgpu` supports the following primitives:
Add `iced_wgpu` as a dependency in your `Cargo.toml`:
```toml
-iced_wgpu = "0.3"
+iced_wgpu = "0.4"
```
__Iced moves fast and the `master` branch can contain breaking changes!__ If
diff --git a/wgpu/src/backend.rs b/wgpu/src/backend.rs
index 534c6cb7..b31bf92c 100644
--- a/wgpu/src/backend.rs
+++ b/wgpu/src/backend.rs
@@ -2,6 +2,7 @@ use crate::quad;
use crate::text;
use crate::triangle;
use crate::{Settings, Transformation};
+
use iced_graphics::backend;
use iced_graphics::font;
use iced_graphics::layer::Layer;
@@ -30,18 +31,24 @@ pub struct Backend {
impl Backend {
/// Creates a new [`Backend`].
- pub fn new(device: &wgpu::Device, settings: Settings) -> Self {
- let text_pipeline =
- text::Pipeline::new(device, settings.format, settings.default_font);
- let quad_pipeline = quad::Pipeline::new(device, settings.format);
- let triangle_pipeline = triangle::Pipeline::new(
+ pub fn new(
+ device: &wgpu::Device,
+ settings: Settings,
+ format: wgpu::TextureFormat,
+ ) -> Self {
+ let text_pipeline = text::Pipeline::new(
device,
- settings.format,
- settings.antialiasing,
+ format,
+ settings.default_font,
+ settings.text_multithreading,
);
+ let quad_pipeline = quad::Pipeline::new(device, format);
+ let triangle_pipeline =
+ triangle::Pipeline::new(device, format, settings.antialiasing);
+
#[cfg(any(feature = "image_rs", feature = "svg"))]
- let image_pipeline = image::Pipeline::new(device, settings.format);
+ let image_pipeline = image::Pipeline::new(device, format);
Self {
quad_pipeline,
@@ -268,6 +275,25 @@ impl backend::Text for Backend {
) -> (f32, f32) {
self.text_pipeline.measure(contents, size, font, bounds)
}
+
+ fn hit_test(
+ &self,
+ contents: &str,
+ size: f32,
+ font: Font,
+ bounds: Size,
+ point: iced_native::Point,
+ nearest_only: bool,
+ ) -> text::Hit {
+ self.text_pipeline.hit_test(
+ contents,
+ size,
+ font,
+ bounds,
+ point,
+ nearest_only,
+ )
+ }
}
#[cfg(feature = "image_rs")]
diff --git a/wgpu/src/image.rs b/wgpu/src/image.rs
index 5511565e..a59dc04b 100644
--- a/wgpu/src/image.rs
+++ b/wgpu/src/image.rs
@@ -61,7 +61,7 @@ impl Pipeline {
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
- visibility: wgpu::ShaderStage::VERTEX,
+ visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
@@ -73,7 +73,7 @@ impl Pipeline {
},
wgpu::BindGroupLayoutEntry {
binding: 1,
- visibility: wgpu::ShaderStage::FRAGMENT,
+ visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: true,
@@ -86,7 +86,7 @@ impl Pipeline {
let uniforms_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("iced_wgpu::image uniforms buffer"),
size: mem::size_of::<Uniforms>() as u64,
- usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
+ usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
@@ -97,11 +97,13 @@ impl Pipeline {
entries: &[
wgpu::BindGroupEntry {
binding: 0,
- resource: wgpu::BindingResource::Buffer {
- buffer: &uniforms_buffer,
- offset: 0,
- size: None,
- },
+ resource: wgpu::BindingResource::Buffer(
+ wgpu::BufferBinding {
+ buffer: &uniforms_buffer,
+ offset: 0,
+ size: None,
+ },
+ ),
},
wgpu::BindGroupEntry {
binding: 1,
@@ -115,7 +117,7 @@ impl Pipeline {
label: Some("iced_wgpu::image texture atlas layout"),
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
- visibility: wgpu::ShaderStage::FRAGMENT,
+ visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
sample_type: wgpu::TextureSampleType::Float {
filterable: true,
@@ -134,86 +136,67 @@ impl Pipeline {
bind_group_layouts: &[&constant_layout, &texture_layout],
});
- let vs_module = device.create_shader_module(&wgpu::include_spirv!(
- "shader/image.vert.spv"
- ));
-
- let fs_module = device.create_shader_module(&wgpu::include_spirv!(
- "shader/image.frag.spv"
- ));
+ let shader =
+ device.create_shader_module(&wgpu::ShaderModuleDescriptor {
+ label: Some("iced_wgpu::image::shader"),
+ source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(
+ include_str!("shader/image.wgsl"),
+ )),
+ });
let pipeline =
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("iced_wgpu::image pipeline"),
layout: Some(&layout),
vertex: wgpu::VertexState {
- module: &vs_module,
- entry_point: "main",
+ module: &shader,
+ entry_point: "vs_main",
buffers: &[
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<Vertex>() as u64,
- step_mode: wgpu::InputStepMode::Vertex,
+ step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[wgpu::VertexAttribute {
shader_location: 0,
- format: wgpu::VertexFormat::Float2,
+ format: wgpu::VertexFormat::Float32x2,
offset: 0,
}],
},
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<Instance>() as u64,
- step_mode: wgpu::InputStepMode::Instance,
- attributes: &[
- wgpu::VertexAttribute {
- shader_location: 1,
- format: wgpu::VertexFormat::Float2,
- offset: 0,
- },
- wgpu::VertexAttribute {
- shader_location: 2,
- format: wgpu::VertexFormat::Float2,
- offset: 4 * 2,
- },
- wgpu::VertexAttribute {
- shader_location: 3,
- format: wgpu::VertexFormat::Float2,
- offset: 4 * 4,
- },
- wgpu::VertexAttribute {
- shader_location: 4,
- format: wgpu::VertexFormat::Float2,
- offset: 4 * 6,
- },
- wgpu::VertexAttribute {
- shader_location: 5,
- format: wgpu::VertexFormat::Uint,
- offset: 4 * 8,
- },
- ],
+ step_mode: wgpu::VertexStepMode::Instance,
+ attributes: &wgpu::vertex_attr_array!(
+ 1 => Float32x2,
+ 2 => Float32x2,
+ 3 => Float32x2,
+ 4 => Float32x2,
+ 5 => Sint32,
+ ),
},
],
},
fragment: Some(wgpu::FragmentState {
- module: &fs_module,
- entry_point: "main",
+ module: &shader,
+ entry_point: "fs_main",
targets: &[wgpu::ColorTargetState {
format,
- color_blend: wgpu::BlendState {
- src_factor: wgpu::BlendFactor::SrcAlpha,
- dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
- operation: wgpu::BlendOperation::Add,
- },
- alpha_blend: wgpu::BlendState {
- src_factor: wgpu::BlendFactor::One,
- dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
- operation: wgpu::BlendOperation::Add,
- },
- write_mask: wgpu::ColorWrite::ALL,
+ blend: Some(wgpu::BlendState {
+ color: wgpu::BlendComponent {
+ src_factor: wgpu::BlendFactor::SrcAlpha,
+ dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
+ operation: wgpu::BlendOperation::Add,
+ },
+ alpha: wgpu::BlendComponent {
+ src_factor: wgpu::BlendFactor::One,
+ dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
+ operation: wgpu::BlendOperation::Add,
+ },
+ }),
+ write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
front_face: wgpu::FrontFace::Cw,
- cull_mode: wgpu::CullMode::None,
..Default::default()
},
depth_stencil: None,
@@ -228,20 +211,20 @@ impl Pipeline {
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("iced_wgpu::image vertex buffer"),
contents: bytemuck::cast_slice(&QUAD_VERTS),
- usage: wgpu::BufferUsage::VERTEX,
+ usage: wgpu::BufferUsages::VERTEX,
});
let indices =
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("iced_wgpu::image index buffer"),
contents: bytemuck::cast_slice(&QUAD_INDICES),
- usage: wgpu::BufferUsage::INDEX,
+ usage: wgpu::BufferUsages::INDEX,
});
let instances = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("iced_wgpu::image instance buffer"),
size: mem::size_of::<Instance>() as u64 * Instance::MAX as u64,
- usage: wgpu::BufferUsage::VERTEX | wgpu::BufferUsage::COPY_DST,
+ usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
@@ -423,16 +406,14 @@ impl Pipeline {
let mut render_pass =
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("iced_wgpu::image render pass"),
- color_attachments: &[
- wgpu::RenderPassColorAttachmentDescriptor {
- attachment: target,
- resolve_target: None,
- ops: wgpu::Operations {
- load: wgpu::LoadOp::Load,
- store: true,
- },
+ color_attachments: &[wgpu::RenderPassColorAttachment {
+ view: target,
+ resolve_target: None,
+ ops: wgpu::Operations {
+ load: wgpu::LoadOp::Load,
+ store: true,
},
- ],
+ }],
depth_stencil_attachment: None,
});
diff --git a/wgpu/src/image/atlas.rs b/wgpu/src/image/atlas.rs
index 660ebe44..c1347e55 100644
--- a/wgpu/src/image/atlas.rs
+++ b/wgpu/src/image/atlas.rs
@@ -4,6 +4,8 @@ mod allocation;
mod allocator;
mod layer;
+use std::num::NonZeroU32;
+
pub use allocation::Allocation;
pub use entry::Entry;
pub use layer::Layer;
@@ -24,7 +26,7 @@ impl Atlas {
let extent = wgpu::Extent3d {
width: SIZE,
height: SIZE,
- depth: 1,
+ depth_or_array_layers: 1,
};
let texture = device.create_texture(&wgpu::TextureDescriptor {
@@ -34,9 +36,9 @@ impl Atlas {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Bgra8UnormSrgb,
- usage: wgpu::TextureUsage::COPY_DST
- | wgpu::TextureUsage::COPY_SRC
- | wgpu::TextureUsage::SAMPLED,
+ usage: wgpu::TextureUsages::COPY_DST
+ | wgpu::TextureUsages::COPY_SRC
+ | wgpu::TextureUsages::TEXTURE_BINDING,
});
let texture_view = texture.create_view(&wgpu::TextureViewDescriptor {
@@ -105,7 +107,7 @@ impl Atlas {
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("iced_wgpu::image staging buffer"),
contents: &padded_data,
- usage: wgpu::BufferUsage::COPY_SRC,
+ usage: wgpu::BufferUsages::COPY_SRC,
});
match &entry {
@@ -294,19 +296,19 @@ impl Atlas {
let extent = wgpu::Extent3d {
width,
height,
- depth: 1,
+ depth_or_array_layers: 1,
};
encoder.copy_buffer_to_texture(
- wgpu::BufferCopyView {
+ wgpu::ImageCopyBuffer {
buffer,
- layout: wgpu::TextureDataLayout {
+ layout: wgpu::ImageDataLayout {
offset: offset as u64,
- bytes_per_row: 4 * image_width + padding,
- rows_per_image: image_height,
+ bytes_per_row: NonZeroU32::new(4 * image_width + padding),
+ rows_per_image: NonZeroU32::new(image_height),
},
},
- wgpu::TextureCopyView {
+ wgpu::ImageCopyTexture {
texture: &self.texture,
mip_level: 0,
origin: wgpu::Origin3d {
@@ -314,6 +316,7 @@ impl Atlas {
y,
z: layer as u32,
},
+ aspect: wgpu::TextureAspect::default(),
},
extent,
);
@@ -334,15 +337,15 @@ impl Atlas {
size: wgpu::Extent3d {
width: SIZE,
height: SIZE,
- depth: self.layers.len() as u32,
+ depth_or_array_layers: self.layers.len() as u32,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Bgra8UnormSrgb,
- usage: wgpu::TextureUsage::COPY_DST
- | wgpu::TextureUsage::COPY_SRC
- | wgpu::TextureUsage::SAMPLED,
+ usage: wgpu::TextureUsages::COPY_DST
+ | wgpu::TextureUsages::COPY_SRC
+ | wgpu::TextureUsages::TEXTURE_BINDING,
});
let amount_to_copy = self.layers.len() - amount;
@@ -355,7 +358,7 @@ impl Atlas {
}
encoder.copy_texture_to_texture(
- wgpu::TextureCopyView {
+ wgpu::ImageCopyTexture {
texture: &self.texture,
mip_level: 0,
origin: wgpu::Origin3d {
@@ -363,8 +366,9 @@ impl Atlas {
y: 0,
z: i as u32,
},
+ aspect: wgpu::TextureAspect::default(),
},
- wgpu::TextureCopyView {
+ wgpu::ImageCopyTexture {
texture: &new_texture,
mip_level: 0,
origin: wgpu::Origin3d {
@@ -372,11 +376,12 @@ impl Atlas {
y: 0,
z: i as u32,
},
+ aspect: wgpu::TextureAspect::default(),
},
wgpu::Extent3d {
width: SIZE,
height: SIZE,
- depth: 1,
+ depth_or_array_layers: 1,
},
);
}
diff --git a/wgpu/src/image/vector.rs b/wgpu/src/image/vector.rs
index ab0f67d0..cd511a45 100644
--- a/wgpu/src/image/vector.rs
+++ b/wgpu/src/image/vector.rs
@@ -1,7 +1,8 @@
-use crate::image::atlas::{self, Atlas};
use iced_native::svg;
use std::collections::{HashMap, HashSet};
+use crate::image::atlas::{self, Atlas};
+
pub enum Svg {
Loaded(usvg::Tree),
NotFound,
@@ -74,8 +75,8 @@ impl Cache {
let id = handle.id();
let (width, height) = (
- (scale * width).round() as u32,
- (scale * height).round() as u32,
+ (scale * width).ceil() as u32,
+ (scale * height).ceil() as u32,
);
// TODO: Optimize!
@@ -111,29 +112,17 @@ impl Cache {
let width = img.width();
let height = img.height();
- let mut rgba = img.take().into_iter();
-
- // TODO: Perform conversion in the GPU
- let bgra: Vec<u8> = std::iter::from_fn(move || {
- use std::iter::once;
-
- let r = rgba.next()?;
- let g = rgba.next()?;
- let b = rgba.next()?;
- let a = rgba.next()?;
-
- Some(once(b).chain(once(g)).chain(once(r)).chain(once(a)))
- })
- .flatten()
- .collect();
+ let mut rgba = img.take();
+ rgba.chunks_exact_mut(4).for_each(|rgba| rgba.swap(0, 2));
let allocation = texture_atlas.upload(
width,
height,
- bytemuck::cast_slice(bgra.as_slice()),
+ bytemuck::cast_slice(rgba.as_slice()),
device,
encoder,
)?;
+ log::debug!("allocating {} {}x{}", id, width, height);
let _ = self.svg_hits.insert(id);
let _ = self.rasterized_hits.insert((id, width, height));
diff --git a/wgpu/src/quad.rs b/wgpu/src/quad.rs
index e0a6e043..148d0f6a 100644
--- a/wgpu/src/quad.rs
+++ b/wgpu/src/quad.rs
@@ -23,12 +23,12 @@ impl Pipeline {
label: Some("iced_wgpu::quad uniforms layout"),
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
- visibility: wgpu::ShaderStage::VERTEX,
+ visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: wgpu::BufferSize::new(
- mem::size_of::<Uniforms>() as u64,
+ mem::size_of::<Uniforms>() as wgpu::BufferAddress,
),
},
count: None,
@@ -37,8 +37,8 @@ impl Pipeline {
let constants_buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("iced_wgpu::quad uniforms buffer"),
- size: mem::size_of::<Uniforms>() as u64,
- usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
+ size: mem::size_of::<Uniforms>() as wgpu::BufferAddress,
+ usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
@@ -47,11 +47,7 @@ impl Pipeline {
layout: &constant_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
- resource: wgpu::BindingResource::Buffer {
- buffer: &constants_buffer,
- offset: 0,
- size: None,
- },
+ resource: constants_buffer.as_entire_binding(),
}],
});
@@ -62,91 +58,68 @@ impl Pipeline {
bind_group_layouts: &[&constant_layout],
});
- let vs_module = device.create_shader_module(&wgpu::include_spirv!(
- "shader/quad.vert.spv"
- ));
-
- let fs_module = device.create_shader_module(&wgpu::include_spirv!(
- "shader/quad.frag.spv"
- ));
+ let shader =
+ device.create_shader_module(&wgpu::ShaderModuleDescriptor {
+ label: Some("iced_wgpu::quad::shader"),
+ source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(
+ include_str!("shader/quad.wgsl"),
+ )),
+ });
let pipeline =
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("iced_wgpu::quad pipeline"),
layout: Some(&layout),
vertex: wgpu::VertexState {
- module: &vs_module,
- entry_point: "main",
+ module: &shader,
+ entry_point: "vs_main",
buffers: &[
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<Vertex>() as u64,
- step_mode: wgpu::InputStepMode::Vertex,
+ step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[wgpu::VertexAttribute {
shader_location: 0,
- format: wgpu::VertexFormat::Float2,
+ format: wgpu::VertexFormat::Float32x2,
offset: 0,
}],
},
wgpu::VertexBufferLayout {
array_stride: mem::size_of::<layer::Quad>() as u64,
- step_mode: wgpu::InputStepMode::Instance,
- attributes: &[
- wgpu::VertexAttribute {
- shader_location: 1,
- format: wgpu::VertexFormat::Float2,
- offset: 0,
- },
- wgpu::VertexAttribute {
- shader_location: 2,
- format: wgpu::VertexFormat::Float2,
- offset: 4 * 2,
- },
- wgpu::VertexAttribute {
- shader_location: 3,
- format: wgpu::VertexFormat::Float4,
- offset: 4 * (2 + 2),
- },
- wgpu::VertexAttribute {
- shader_location: 4,
- format: wgpu::VertexFormat::Float4,
- offset: 4 * (2 + 2 + 4),
- },
- wgpu::VertexAttribute {
- shader_location: 5,
- format: wgpu::VertexFormat::Float,
- offset: 4 * (2 + 2 + 4 + 4),
- },
- wgpu::VertexAttribute {
- shader_location: 6,
- format: wgpu::VertexFormat::Float,
- offset: 4 * (2 + 2 + 4 + 4 + 1),
- },
- ],
+ step_mode: wgpu::VertexStepMode::Instance,
+ attributes: &wgpu::vertex_attr_array!(
+ 1 => Float32x2,
+ 2 => Float32x2,
+ 3 => Float32x4,
+ 4 => Float32x4,
+ 5 => Float32,
+ 6 => Float32,
+ ),
},
],
},
fragment: Some(wgpu::FragmentState {
- module: &fs_module,
- entry_point: "main",
+ module: &shader,
+ entry_point: "fs_main",
targets: &[wgpu::ColorTargetState {
format,
- color_blend: wgpu::BlendState {
- src_factor: wgpu::BlendFactor::SrcAlpha,
- dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
- operation: wgpu::BlendOperation::Add,
- },
- alpha_blend: wgpu::BlendState {
- src_factor: wgpu::BlendFactor::One,
- dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
- operation: wgpu::BlendOperation::Add,
- },
- write_mask: wgpu::ColorWrite::ALL,
+ blend: Some(wgpu::BlendState {
+ color: wgpu::BlendComponent {
+ src_factor: wgpu::BlendFactor::SrcAlpha,
+ dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
+ operation: wgpu::BlendOperation::Add,
+ },
+ alpha: wgpu::BlendComponent {
+ src_factor: wgpu::BlendFactor::One,
+ dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
+ operation: wgpu::BlendOperation::Add,
+ },
+ }),
+ write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
front_face: wgpu::FrontFace::Cw,
- cull_mode: wgpu::CullMode::None,
..Default::default()
},
depth_stencil: None,
@@ -161,20 +134,20 @@ impl Pipeline {
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("iced_wgpu::quad vertex buffer"),
contents: bytemuck::cast_slice(&QUAD_VERTS),
- usage: wgpu::BufferUsage::VERTEX,
+ usage: wgpu::BufferUsages::VERTEX,
});
let indices =
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("iced_wgpu::quad index buffer"),
contents: bytemuck::cast_slice(&QUAD_INDICES),
- usage: wgpu::BufferUsage::INDEX,
+ usage: wgpu::BufferUsages::INDEX,
});
let instances = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("iced_wgpu::quad instance buffer"),
size: mem::size_of::<layer::Quad>() as u64 * MAX_INSTANCES as u64,
- usage: wgpu::BufferUsage::VERTEX | wgpu::BufferUsage::COPY_DST,
+ usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
@@ -237,16 +210,14 @@ impl Pipeline {
let mut render_pass =
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("iced_wgpu::quad render pass"),
- color_attachments: &[
- wgpu::RenderPassColorAttachmentDescriptor {
- attachment: target,
- resolve_target: None,
- ops: wgpu::Operations {
- load: wgpu::LoadOp::Load,
- store: true,
- },
+ color_attachments: &[wgpu::RenderPassColorAttachment {
+ view: target,
+ resolve_target: None,
+ ops: wgpu::Operations {
+ load: wgpu::LoadOp::Load,
+ store: true,
},
- ],
+ }],
depth_stencil_attachment: None,
});
@@ -309,6 +280,9 @@ const MAX_INSTANCES: usize = 100_000;
struct Uniforms {
transform: [f32; 16],
scale: f32,
+ // Uniforms must be aligned to their largest member,
+ // this uses a mat4x4<f32> which aligns to 16, so align to that
+ _padding: [f32; 3],
}
impl Uniforms {
@@ -316,6 +290,7 @@ impl Uniforms {
Self {
transform: *transformation.as_ref(),
scale,
+ _padding: [0.0; 3],
}
}
}
@@ -325,6 +300,7 @@ impl Default for Uniforms {
Self {
transform: *Transformation::identity().as_ref(),
scale: 1.0,
+ _padding: [0.0; 3],
}
}
}
diff --git a/wgpu/src/settings.rs b/wgpu/src/settings.rs
index 26763e22..23b55904 100644
--- a/wgpu/src/settings.rs
+++ b/wgpu/src/settings.rs
@@ -6,16 +6,14 @@ pub use crate::Antialiasing;
/// [`Backend`]: crate::Backend
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Settings {
- /// The output format of the [`Backend`].
- ///
- /// [`Backend`]: crate::Backend
- pub format: wgpu::TextureFormat,
-
/// The present mode of the [`Backend`].
///
/// [`Backend`]: crate::Backend
pub present_mode: wgpu::PresentMode,
+ /// The internal graphics backend to use.
+ pub internal_backend: wgpu::Backends,
+
/// The bytes of the font that will be used by default.
///
/// If `None` is provided, a default system font will be chosen.
@@ -26,18 +24,66 @@ pub struct Settings {
/// By default, it will be set to 20.
pub default_text_size: u16,
+ /// If enabled, spread text workload in multiple threads when multiple cores
+ /// are available.
+ ///
+ /// By default, it is disabled.
+ pub text_multithreading: bool,
+
/// The antialiasing strategy that will be used for triangle primitives.
+ ///
+ /// By default, it is `None`.
pub antialiasing: Option<Antialiasing>,
}
+impl Settings {
+ /// Creates new [`Settings`] using environment configuration.
+ ///
+ /// Specifically:
+ ///
+ /// - The `internal_backend` can be configured using the `WGPU_BACKEND`
+ /// environment variable. If the variable is not set, the primary backend
+ /// will be used. The following values are allowed:
+ /// - `vulkan`
+ /// - `metal`
+ /// - `dx12`
+ /// - `dx11`
+ /// - `gl`
+ /// - `webgpu`
+ /// - `primary`
+ pub fn from_env() -> Self {
+ Settings {
+ internal_backend: backend_from_env()
+ .unwrap_or(wgpu::Backends::all()),
+ ..Self::default()
+ }
+ }
+}
+
impl Default for Settings {
fn default() -> Settings {
Settings {
- format: wgpu::TextureFormat::Bgra8UnormSrgb,
present_mode: wgpu::PresentMode::Mailbox,
+ internal_backend: wgpu::Backends::all(),
default_font: None,
default_text_size: 20,
+ text_multithreading: false,
antialiasing: None,
}
}
}
+
+fn backend_from_env() -> Option<wgpu::Backends> {
+ std::env::var("WGPU_BACKEND").ok().map(|backend| {
+ match backend.to_lowercase().as_str() {
+ "vulkan" => wgpu::Backends::VULKAN,
+ "metal" => wgpu::Backends::METAL,
+ "dx12" => wgpu::Backends::DX12,
+ "dx11" => wgpu::Backends::DX11,
+ "gl" => wgpu::Backends::GL,
+ "webgpu" => wgpu::Backends::BROWSER_WEBGPU,
+ "primary" => wgpu::Backends::PRIMARY,
+ other => panic!("Unknown backend: {}", other),
+ }
+ })
+}
diff --git a/wgpu/src/shader/blit.frag b/wgpu/src/shader/blit.frag
deleted file mode 100644
index dfed960f..00000000
--- a/wgpu/src/shader/blit.frag
+++ /dev/null
@@ -1,12 +0,0 @@
-#version 450
-
-layout(location = 0) in vec2 v_Uv;
-
-layout(set = 0, binding = 0) uniform sampler u_Sampler;
-layout(set = 1, binding = 0) uniform texture2D u_Texture;
-
-layout(location = 0) out vec4 o_Color;
-
-void main() {
- o_Color = texture(sampler2D(u_Texture, u_Sampler), v_Uv);
-}
diff --git a/wgpu/src/shader/blit.frag.spv b/wgpu/src/shader/blit.frag.spv
deleted file mode 100644
index 2c5638b5..00000000
--- a/wgpu/src/shader/blit.frag.spv
+++ /dev/null
Binary files differ
diff --git a/wgpu/src/shader/blit.vert b/wgpu/src/shader/blit.vert
deleted file mode 100644
index 899cd39d..00000000
--- a/wgpu/src/shader/blit.vert
+++ /dev/null
@@ -1,26 +0,0 @@
-#version 450
-
-layout(location = 0) out vec2 o_Uv;
-
-const vec2 positions[6] = vec2[6](
- vec2(-1.0, 1.0),
- vec2(-1.0, -1.0),
- vec2(1.0, -1.0),
- vec2(-1.0, 1.0),
- vec2(1.0, 1.0),
- vec2(1.0, -1.0)
-);
-
-const vec2 uvs[6] = vec2[6](
- vec2(0.0, 0.0),
- vec2(0.0, 1.0),
- vec2(1.0, 1.0),
- vec2(0.0, 0.0),
- vec2(1.0, 0.0),
- vec2(1.0, 1.0)
-);
-
-void main() {
- o_Uv = uvs[gl_VertexIndex];
- gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
-}
diff --git a/wgpu/src/shader/blit.vert.spv b/wgpu/src/shader/blit.vert.spv
deleted file mode 100644
index e0b436ce..00000000
--- a/wgpu/src/shader/blit.vert.spv
+++ /dev/null
Binary files differ
diff --git a/wgpu/src/shader/blit.wgsl b/wgpu/src/shader/blit.wgsl
new file mode 100644
index 00000000..694f192e
--- /dev/null
+++ b/wgpu/src/shader/blit.wgsl
@@ -0,0 +1,43 @@
+var positions: array<vec2<f32>, 6> = array<vec2<f32>, 6>(
+ vec2<f32>(-1.0, 1.0),
+ vec2<f32>(-1.0, -1.0),
+ vec2<f32>(1.0, -1.0),
+ vec2<f32>(-1.0, 1.0),
+ vec2<f32>(1.0, 1.0),
+ vec2<f32>(1.0, -1.0)
+);
+
+var uvs: array<vec2<f32>, 6> = array<vec2<f32>, 6>(
+ vec2<f32>(0.0, 0.0),
+ vec2<f32>(0.0, 1.0),
+ vec2<f32>(1.0, 1.0),
+ vec2<f32>(0.0, 0.0),
+ vec2<f32>(1.0, 0.0),
+ vec2<f32>(1.0, 1.0)
+);
+
+[[group(0), binding(0)]] var u_sampler: sampler;
+[[group(1), binding(0)]] var u_texture: texture_2d<f32>;
+
+struct VertexInput {
+ [[builtin(vertex_index)]] vertex_index: u32;
+};
+
+struct VertexOutput {
+ [[builtin(position)]] position: vec4<f32>;
+ [[location(0)]] uv: vec2<f32>;
+};
+
+[[stage(vertex)]]
+fn vs_main(input: VertexInput) -> VertexOutput {
+ var out: VertexOutput;
+ out.uv = uvs[input.vertex_index];
+ out.position = vec4<f32>(positions[input.vertex_index], 0.0, 1.0);
+
+ return out;
+}
+
+[[stage(fragment)]]
+fn fs_main(input: VertexOutput) -> [[location(0)]] vec4<f32> {
+ return textureSample(u_texture, u_sampler, input.uv);
+}
diff --git a/wgpu/src/shader/image.frag b/wgpu/src/shader/image.frag
deleted file mode 100644
index 2809e9e6..00000000
--- a/wgpu/src/shader/image.frag
+++ /dev/null
@@ -1,12 +0,0 @@
-#version 450
-
-layout(location = 0) in vec3 v_Uv;
-
-layout(set = 0, binding = 1) uniform sampler u_Sampler;
-layout(set = 1, binding = 0) uniform texture2DArray u_Texture;
-
-layout(location = 0) out vec4 o_Color;
-
-void main() {
- o_Color = texture(sampler2DArray(u_Texture, u_Sampler), v_Uv);
-}
diff --git a/wgpu/src/shader/image.frag.spv b/wgpu/src/shader/image.frag.spv
deleted file mode 100644
index 65b08aa3..00000000
--- a/wgpu/src/shader/image.frag.spv
+++ /dev/null
Binary files differ
diff --git a/wgpu/src/shader/image.vert b/wgpu/src/shader/image.vert
deleted file mode 100644
index dab53cfe..00000000
--- a/wgpu/src/shader/image.vert
+++ /dev/null
@@ -1,27 +0,0 @@
-#version 450
-
-layout(location = 0) in vec2 v_Pos;
-layout(location = 1) in vec2 i_Pos;
-layout(location = 2) in vec2 i_Scale;
-layout(location = 3) in vec2 i_Atlas_Pos;
-layout(location = 4) in vec2 i_Atlas_Scale;
-layout(location = 5) in uint i_Layer;
-
-layout (set = 0, binding = 0) uniform Globals {
- mat4 u_Transform;
-};
-
-layout(location = 0) out vec3 o_Uv;
-
-void main() {
- o_Uv = vec3(v_Pos * i_Atlas_Scale + i_Atlas_Pos, i_Layer);
-
- mat4 i_Transform = mat4(
- vec4(i_Scale.x, 0.0, 0.0, 0.0),
- vec4(0.0, i_Scale.y, 0.0, 0.0),
- vec4(0.0, 0.0, 1.0, 0.0),
- vec4(i_Pos, 0.0, 1.0)
- );
-
- gl_Position = u_Transform * i_Transform * vec4(v_Pos, 0.0, 1.0);
-}
diff --git a/wgpu/src/shader/image.vert.spv b/wgpu/src/shader/image.vert.spv
deleted file mode 100644
index 21f5db2d..00000000
--- a/wgpu/src/shader/image.vert.spv
+++ /dev/null
Binary files differ
diff --git a/wgpu/src/shader/image.wgsl b/wgpu/src/shader/image.wgsl
new file mode 100644
index 00000000..a63ee8f6
--- /dev/null
+++ b/wgpu/src/shader/image.wgsl
@@ -0,0 +1,47 @@
+[[block]]
+struct Globals {
+ transform: mat4x4<f32>;
+};
+
+[[group(0), binding(0)]] var<uniform> globals: Globals;
+[[group(0), binding(1)]] var u_sampler: sampler;
+[[group(1), binding(0)]] var u_texture: texture_2d_array<f32>;
+
+struct VertexInput {
+ [[location(0)]] v_pos: vec2<f32>;
+ [[location(1)]] pos: vec2<f32>;
+ [[location(2)]] scale: vec2<f32>;
+ [[location(3)]] atlas_pos: vec2<f32>;
+ [[location(4)]] atlas_scale: vec2<f32>;
+ [[location(5)]] layer: i32;
+};
+
+struct VertexOutput {
+ [[builtin(position)]] position: vec4<f32>;
+ [[location(0)]] uv: vec2<f32>;
+ [[location(1)]] layer: f32; // this should be an i32, but naga currently reads that as requiring interpolation.
+};
+
+[[stage(vertex)]]
+fn vs_main(input: VertexInput) -> VertexOutput {
+ var out: VertexOutput;
+
+ out.uv = vec2<f32>(input.v_pos * input.atlas_scale + input.atlas_pos);
+ out.layer = f32(input.layer);
+
+ var transform: mat4x4<f32> = mat4x4<f32>(
+ vec4<f32>(input.scale.x, 0.0, 0.0, 0.0),
+ vec4<f32>(0.0, input.scale.y, 0.0, 0.0),
+ vec4<f32>(0.0, 0.0, 1.0, 0.0),
+ vec4<f32>(input.pos, 0.0, 1.0)
+ );
+
+ out.position = globals.transform * transform * vec4<f32>(input.v_pos, 0.0, 1.0);
+
+ return out;
+}
+
+[[stage(fragment)]]
+fn fs_main(input: VertexOutput) -> [[location(0)]] vec4<f32> {
+ return textureSample(u_texture, u_sampler, input.uv, i32(input.layer));
+}
diff --git a/wgpu/src/shader/quad.frag b/wgpu/src/shader/quad.frag
deleted file mode 100644
index ad1af1ad..00000000
--- a/wgpu/src/shader/quad.frag
+++ /dev/null
@@ -1,66 +0,0 @@
-#version 450
-
-layout(location = 0) in vec4 v_Color;
-layout(location = 1) in vec4 v_BorderColor;
-layout(location = 2) in vec2 v_Pos;
-layout(location = 3) in vec2 v_Scale;
-layout(location = 4) in float v_BorderRadius;
-layout(location = 5) in float v_BorderWidth;
-
-layout(location = 0) out vec4 o_Color;
-
-float distance(in vec2 frag_coord, in vec2 position, in vec2 size, float radius)
-{
- // TODO: Try SDF approach: https://www.shadertoy.com/view/wd3XRN
- vec2 inner_size = size - vec2(radius, radius) * 2.0;
- vec2 top_left = position + vec2(radius, radius);
- vec2 bottom_right = top_left + inner_size;
-
- vec2 top_left_distance = top_left - frag_coord;
- vec2 bottom_right_distance = frag_coord - bottom_right;
-
- vec2 distance = vec2(
- max(max(top_left_distance.x, bottom_right_distance.x), 0),
- max(max(top_left_distance.y, bottom_right_distance.y), 0)
- );
-
- return sqrt(distance.x * distance.x + distance.y * distance.y);
-}
-
-void main() {
- vec4 mixed_color;
-
- // TODO: Remove branching (?)
- if(v_BorderWidth > 0) {
- float internal_border = max(v_BorderRadius - v_BorderWidth, 0);
-
- float internal_distance = distance(
- gl_FragCoord.xy,
- v_Pos + vec2(v_BorderWidth),
- v_Scale - vec2(v_BorderWidth * 2.0),
- internal_border
- );
-
- float border_mix = smoothstep(
- max(internal_border - 0.5, 0.0),
- internal_border + 0.5,
- internal_distance
- );
-
- mixed_color = mix(v_Color, v_BorderColor, border_mix);
- } else {
- mixed_color = v_Color;
- }
-
- float d = distance(
- gl_FragCoord.xy,
- v_Pos,
- v_Scale,
- v_BorderRadius
- );
-
- float radius_alpha =
- 1.0 - smoothstep(max(v_BorderRadius - 0.5, 0), v_BorderRadius + 0.5, d);
-
- o_Color = vec4(mixed_color.xyz, mixed_color.w * radius_alpha);
-}
diff --git a/wgpu/src/shader/quad.frag.spv b/wgpu/src/shader/quad.frag.spv
deleted file mode 100644
index 519f5f01..00000000
--- a/wgpu/src/shader/quad.frag.spv
+++ /dev/null
Binary files differ
diff --git a/wgpu/src/shader/quad.vert b/wgpu/src/shader/quad.vert
deleted file mode 100644
index 09a278b1..00000000
--- a/wgpu/src/shader/quad.vert
+++ /dev/null
@@ -1,47 +0,0 @@
-#version 450
-
-layout(location = 0) in vec2 v_Pos;
-layout(location = 1) in vec2 i_Pos;
-layout(location = 2) in vec2 i_Scale;
-layout(location = 3) in vec4 i_Color;
-layout(location = 4) in vec4 i_BorderColor;
-layout(location = 5) in float i_BorderRadius;
-layout(location = 6) in float i_BorderWidth;
-
-layout (set = 0, binding = 0) uniform Globals {
- mat4 u_Transform;
- float u_Scale;
-};
-
-layout(location = 0) out vec4 o_Color;
-layout(location = 1) out vec4 o_BorderColor;
-layout(location = 2) out vec2 o_Pos;
-layout(location = 3) out vec2 o_Scale;
-layout(location = 4) out float o_BorderRadius;
-layout(location = 5) out float o_BorderWidth;
-
-void main() {
- vec2 p_Pos = i_Pos * u_Scale;
- vec2 p_Scale = i_Scale * u_Scale;
-
- float i_BorderRadius = min(
- i_BorderRadius,
- min(i_Scale.x, i_Scale.y) / 2.0
- );
-
- mat4 i_Transform = mat4(
- vec4(p_Scale.x + 1.0, 0.0, 0.0, 0.0),
- vec4(0.0, p_Scale.y + 1.0, 0.0, 0.0),
- vec4(0.0, 0.0, 1.0, 0.0),
- vec4(p_Pos - vec2(0.5, 0.5), 0.0, 1.0)
- );
-
- o_Color = i_Color;
- o_BorderColor = i_BorderColor;
- o_Pos = p_Pos;
- o_Scale = p_Scale;
- o_BorderRadius = i_BorderRadius * u_Scale;
- o_BorderWidth = i_BorderWidth * u_Scale;
-
- gl_Position = u_Transform * i_Transform * vec4(v_Pos, 0.0, 1.0);
-}
diff --git a/wgpu/src/shader/quad.vert.spv b/wgpu/src/shader/quad.vert.spv
deleted file mode 100644
index fa71ba1e..00000000
--- a/wgpu/src/shader/quad.vert.spv
+++ /dev/null
Binary files differ
diff --git a/wgpu/src/shader/quad.wgsl b/wgpu/src/shader/quad.wgsl
new file mode 100644
index 00000000..80d733ab
--- /dev/null
+++ b/wgpu/src/shader/quad.wgsl
@@ -0,0 +1,122 @@
+[[block]]
+struct Globals {
+ transform: mat4x4<f32>;
+ scale: f32;
+};
+
+[[group(0), binding(0)]] var<uniform> globals: Globals;
+
+struct VertexInput {
+ [[location(0)]] v_pos: vec2<f32>;
+ [[location(1)]] pos: vec2<f32>;
+ [[location(2)]] scale: vec2<f32>;
+ [[location(3)]] color: vec4<f32>;
+ [[location(4)]] border_color: vec4<f32>;
+ [[location(5)]] border_radius: f32;
+ [[location(6)]] border_width: f32;
+};
+
+struct VertexOutput {
+ [[builtin(position)]] position: vec4<f32>;
+ [[location(0)]] color: vec4<f32>;
+ [[location(1)]] border_color: vec4<f32>;
+ [[location(2)]] pos: vec2<f32>;
+ [[location(3)]] scale: vec2<f32>;
+ [[location(4)]] border_radius: f32;
+ [[location(5)]] border_width: f32;
+};
+
+[[stage(vertex)]]
+fn vs_main(input: VertexInput) -> VertexOutput {
+ var out: VertexOutput;
+
+ var pos: vec2<f32> = input.pos * globals.scale;
+ var scale: vec2<f32> = input.scale * globals.scale;
+
+ var border_radius: f32 = min(
+ input.border_radius,
+ min(input.scale.x, input.scale.y) / 2.0
+ );
+
+ var transform: mat4x4<f32> = mat4x4<f32>(
+ vec4<f32>(scale.x + 1.0, 0.0, 0.0, 0.0),
+ vec4<f32>(0.0, scale.y + 1.0, 0.0, 0.0),
+ vec4<f32>(0.0, 0.0, 1.0, 0.0),
+ vec4<f32>(pos - vec2<f32>(0.5, 0.5), 0.0, 1.0)
+ );
+
+ out.color = input.color;
+ out.border_color = input.border_color;
+ out.pos = pos;
+ out.scale = scale;
+ out.border_radius = border_radius * globals.scale;
+ out.border_width = input.border_width * globals.scale;
+ out.position = globals.transform * transform * vec4<f32>(input.v_pos, 0.0, 1.0);
+
+ return out;
+}
+
+fn distance_alg(
+ frag_coord: vec2<f32>,
+ position: vec2<f32>,
+ size: vec2<f32>,
+ radius: f32
+) -> f32 {
+ var inner_size: vec2<f32> = size - vec2<f32>(radius, radius) * 2.0;
+ var top_left: vec2<f32> = position + vec2<f32>(radius, radius);
+ var bottom_right: vec2<f32> = top_left + inner_size;
+
+ var top_left_distance: vec2<f32> = top_left - frag_coord;
+ var bottom_right_distance: vec2<f32> = frag_coord - bottom_right;
+
+ var dist: vec2<f32> = vec2<f32>(
+ max(max(top_left_distance.x, bottom_right_distance.x), 0.0),
+ max(max(top_left_distance.y, bottom_right_distance.y), 0.0)
+ );
+
+ return sqrt(dist.x * dist.x + dist.y * dist.y);
+}
+
+
+[[stage(fragment)]]
+fn fs_main(
+ input: VertexOutput
+) -> [[location(0)]] vec4<f32> {
+ var mixed_color: vec4<f32> = input.color;
+
+ if (input.border_width > 0.0) {
+ var internal_border: f32 = max(
+ input.border_radius - input.border_width,
+ 0.0
+ );
+
+ var internal_distance: f32 = distance_alg(
+ vec2<f32>(input.position.x, input.position.y),
+ input.pos + vec2<f32>(input.border_width, input.border_width),
+ input.scale - vec2<f32>(input.border_width * 2.0, input.border_width * 2.0),
+ internal_border
+ );
+
+ var border_mix: f32 = smoothStep(
+ max(internal_border - 0.5, 0.0),
+ internal_border + 0.5,
+ internal_distance
+ );
+
+ mixed_color = mix(input.color, input.border_color, vec4<f32>(border_mix, border_mix, border_mix, border_mix));
+ }
+
+ var dist: f32 = distance_alg(
+ vec2<f32>(input.position.x, input.position.y),
+ input.pos,
+ input.scale,
+ input.border_radius
+ );
+
+ var radius_alpha: f32 = 1.0 - smoothStep(
+ max(input.border_radius - 0.5, 0.0),
+ input.border_radius + 0.5,
+ dist);
+
+ return vec4<f32>(mixed_color.x, mixed_color.y, mixed_color.z, mixed_color.w * radius_alpha);
+}
diff --git a/wgpu/src/shader/triangle.frag b/wgpu/src/shader/triangle.frag
deleted file mode 100644
index e39c45e7..00000000
--- a/wgpu/src/shader/triangle.frag
+++ /dev/null
@@ -1,8 +0,0 @@
-#version 450
-
-layout(location = 0) in vec4 i_Color;
-layout(location = 0) out vec4 o_Color;
-
-void main() {
- o_Color = i_Color;
-}
diff --git a/wgpu/src/shader/triangle.frag.spv b/wgpu/src/shader/triangle.frag.spv
deleted file mode 100644
index 11201872..00000000
--- a/wgpu/src/shader/triangle.frag.spv
+++ /dev/null
Binary files differ
diff --git a/wgpu/src/shader/triangle.vert b/wgpu/src/shader/triangle.vert
deleted file mode 100644
index 1f2c009b..00000000
--- a/wgpu/src/shader/triangle.vert
+++ /dev/null
@@ -1,15 +0,0 @@
-#version 450
-
-layout(location = 0) in vec2 i_Position;
-layout(location = 1) in vec4 i_Color;
-
-layout(location = 0) out vec4 o_Color;
-
-layout (set = 0, binding = 0) uniform Globals {
- mat4 u_Transform;
-};
-
-void main() {
- gl_Position = u_Transform * vec4(i_Position, 0.0, 1.0);
- o_Color = i_Color;
-}
diff --git a/wgpu/src/shader/triangle.vert.spv b/wgpu/src/shader/triangle.vert.spv
deleted file mode 100644
index 871f4f55..00000000
--- a/wgpu/src/shader/triangle.vert.spv
+++ /dev/null
Binary files differ
diff --git a/wgpu/src/shader/triangle.wgsl b/wgpu/src/shader/triangle.wgsl
new file mode 100644
index 00000000..96eaabcc
--- /dev/null
+++ b/wgpu/src/shader/triangle.wgsl
@@ -0,0 +1,31 @@
+[[block]]
+struct Globals {
+ transform: mat4x4<f32>;
+};
+
+[[group(0), binding(0)]] var<uniform> globals: Globals;
+
+struct VertexInput {
+ [[location(0)]] position: vec2<f32>;
+ [[location(1)]] color: vec4<f32>;
+};
+
+struct VertexOutput {
+ [[builtin(position)]] position: vec4<f32>;
+ [[location(0)]] color: vec4<f32>;
+};
+
+[[stage(vertex)]]
+fn vs_main(input: VertexInput) -> VertexOutput {
+ var out: VertexOutput;
+
+ out.color = input.color;
+ out.position = globals.transform * vec4<f32>(input.position, 0.0, 1.0);
+
+ return out;
+}
+
+[[stage(fragment)]]
+fn fs_main(input: VertexOutput) -> [[location(0)]] vec4<f32> {
+ return input.color;
+}
diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs
index 4d92d9e9..ee49ee4b 100644
--- a/wgpu/src/text.rs
+++ b/wgpu/src/text.rs
@@ -1,8 +1,12 @@
use crate::Transformation;
+
use iced_graphics::font;
+
use std::{cell::RefCell, collections::HashMap};
use wgpu_glyph::ab_glyph;
+pub use iced_native::text::Hit;
+
#[derive(Debug)]
pub struct Pipeline {
draw_brush: RefCell<wgpu_glyph::GlyphBrush<()>>,
@@ -15,6 +19,7 @@ impl Pipeline {
device: &wgpu::Device,
format: wgpu::TextureFormat,
default_font: Option<&[u8]>,
+ multithreading: bool,
) -> Self {
let default_font = default_font.map(|slice| slice.to_vec());
@@ -46,7 +51,7 @@ impl Pipeline {
let draw_brush =
wgpu_glyph::GlyphBrushBuilder::using_font(font.clone())
.initial_cache_size((2048, 2048))
- .draw_cache_multithread(false) // TODO: Expose as a configuration flag
+ .draw_cache_multithread(multithreading)
.build(device, format);
let measure_brush =
@@ -116,6 +121,94 @@ impl Pipeline {
}
}
+ pub fn hit_test(
+ &self,
+ content: &str,
+ size: f32,
+ font: iced_native::Font,
+ bounds: iced_native::Size,
+ point: iced_native::Point,
+ nearest_only: bool,
+ ) -> Hit {
+ use wgpu_glyph::GlyphCruncher;
+
+ let wgpu_glyph::FontId(font_id) = self.find_font(font);
+
+ let section = wgpu_glyph::Section {
+ bounds: (bounds.width, bounds.height),
+ text: vec![wgpu_glyph::Text {
+ text: content,
+ scale: size.into(),
+ font_id: wgpu_glyph::FontId(font_id),
+ extra: wgpu_glyph::Extra::default(),
+ }],
+ ..Default::default()
+ };
+
+ let mut mb = self.measure_brush.borrow_mut();
+
+ // The underlying type is FontArc, so clones are cheap.
+ use wgpu_glyph::ab_glyph::{Font, ScaleFont};
+ let font = mb.fonts()[font_id].clone().into_scaled(size);
+
+ // Implements an iterator over the glyph bounding boxes.
+ let bounds = mb.glyphs(section).map(
+ |wgpu_glyph::SectionGlyph {
+ byte_index, glyph, ..
+ }| {
+ (
+ *byte_index,
+ iced_native::Rectangle::new(
+ iced_native::Point::new(
+ glyph.position.x - font.h_side_bearing(glyph.id),
+ glyph.position.y - font.ascent(),
+ ),
+ iced_native::Size::new(
+ font.h_advance(glyph.id),
+ font.ascent() - font.descent(),
+ ),
+ ),
+ )
+ },
+ );
+
+ // Implements computation of the character index based on the byte index
+ // within the input string.
+ let char_index = |byte_index| {
+ let mut b_count = 0;
+ for (i, utf8_len) in
+ content.chars().map(|c| c.len_utf8()).enumerate()
+ {
+ if byte_index < (b_count + utf8_len) {
+ return i;
+ }
+ b_count += utf8_len;
+ }
+ return byte_index;
+ };
+
+ if !nearest_only {
+ for (idx, bounds) in bounds.clone() {
+ if bounds.contains(point) {
+ return Hit::CharOffset(char_index(idx));
+ }
+ }
+ }
+
+ let (idx, nearest) = bounds.fold(
+ (0usize, iced_native::Point::ORIGIN),
+ |acc: (usize, iced_native::Point), (idx, bounds)| {
+ if bounds.center().distance(point) < acc.1.distance(point) {
+ (idx, bounds.center())
+ } else {
+ acc
+ }
+ },
+ );
+
+ Hit::NearestCharOffset(char_index(idx), (point - nearest).into())
+ }
+
pub fn trim_measurement_cache(&mut self) {
// TODO: We should probably use a `GlyphCalculator` for this. However,
// it uses a lifetimed `GlyphCalculatorGuard` with side-effects on drop.
diff --git a/wgpu/src/triangle.rs b/wgpu/src/triangle.rs
index 2f255940..2aaebe58 100644
--- a/wgpu/src/triangle.rs
+++ b/wgpu/src/triangle.rs
@@ -29,7 +29,7 @@ struct Buffer<T> {
label: &'static str,
raw: wgpu::Buffer,
size: usize,
- usage: wgpu::BufferUsage,
+ usage: wgpu::BufferUsages,
_type: std::marker::PhantomData<T>,
}
@@ -38,7 +38,7 @@ impl<T> Buffer<T> {
label: &'static str,
device: &wgpu::Device,
size: usize,
- usage: wgpu::BufferUsage,
+ usage: wgpu::BufferUsages,
) -> Self {
let raw = device.create_buffer(&wgpu::BufferDescriptor {
label: Some(label),
@@ -85,7 +85,7 @@ impl Pipeline {
label: Some("iced_wgpu::triangle uniforms layout"),
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
- visibility: wgpu::ShaderStage::VERTEX,
+ visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: true,
@@ -101,7 +101,7 @@ impl Pipeline {
"iced_wgpu::triangle uniforms buffer",
device,
UNIFORM_BUFFER_SIZE,
- wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
+ wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
);
let constant_bind_group =
@@ -110,13 +110,17 @@ impl Pipeline {
layout: &constants_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
- resource: wgpu::BindingResource::Buffer {
- buffer: &constants_buffer.raw,
- offset: 0,
- size: wgpu::BufferSize::new(
- std::mem::size_of::<Uniforms>() as u64,
- ),
- },
+ resource: wgpu::BindingResource::Buffer(
+ wgpu::BufferBinding {
+ buffer: &constants_buffer.raw,
+ offset: 0,
+ size: wgpu::BufferSize::new(std::mem::size_of::<
+ Uniforms,
+ >(
+ )
+ as u64),
+ },
+ ),
}],
});
@@ -127,62 +131,55 @@ impl Pipeline {
bind_group_layouts: &[&constants_layout],
});
- let vs_module = device.create_shader_module(&wgpu::include_spirv!(
- "shader/triangle.vert.spv"
- ));
-
- let fs_module = device.create_shader_module(&wgpu::include_spirv!(
- "shader/triangle.frag.spv"
- ));
+ let shader =
+ device.create_shader_module(&wgpu::ShaderModuleDescriptor {
+ label: Some("iced_wgpu::triangle::shader"),
+ source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(
+ include_str!("shader/triangle.wgsl"),
+ )),
+ });
let pipeline =
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("iced_wgpu::triangle pipeline"),
layout: Some(&layout),
vertex: wgpu::VertexState {
- module: &vs_module,
- entry_point: "main",
+ module: &shader,
+ entry_point: "vs_main",
buffers: &[wgpu::VertexBufferLayout {
array_stride: mem::size_of::<Vertex2D>() as u64,
- step_mode: wgpu::InputStepMode::Vertex,
- attributes: &[
+ step_mode: wgpu::VertexStepMode::Vertex,
+ attributes: &wgpu::vertex_attr_array!(
// Position
- wgpu::VertexAttribute {
- shader_location: 0,
- format: wgpu::VertexFormat::Float2,
- offset: 0,
- },
+ 0 => Float32x2,
// Color
- wgpu::VertexAttribute {
- shader_location: 1,
- format: wgpu::VertexFormat::Float4,
- offset: 4 * 2,
- },
- ],
+ 1 => Float32x4,
+ ),
}],
},
fragment: Some(wgpu::FragmentState {
- module: &fs_module,
- entry_point: "main",
+ module: &shader,
+ entry_point: "fs_main",
targets: &[wgpu::ColorTargetState {
format,
- color_blend: wgpu::BlendState {
- src_factor: wgpu::BlendFactor::SrcAlpha,
- dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
- operation: wgpu::BlendOperation::Add,
- },
- alpha_blend: wgpu::BlendState {
- src_factor: wgpu::BlendFactor::One,
- dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
- operation: wgpu::BlendOperation::Add,
- },
- write_mask: wgpu::ColorWrite::ALL,
+ blend: Some(wgpu::BlendState {
+ color: wgpu::BlendComponent {
+ src_factor: wgpu::BlendFactor::SrcAlpha,
+ dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
+ operation: wgpu::BlendOperation::Add,
+ },
+ alpha: wgpu::BlendComponent {
+ src_factor: wgpu::BlendFactor::One,
+ dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
+ operation: wgpu::BlendOperation::Add,
+ },
+ }),
+ write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
front_face: wgpu::FrontFace::Cw,
- cull_mode: wgpu::CullMode::None,
..Default::default()
},
depth_stencil: None,
@@ -205,13 +202,13 @@ impl Pipeline {
"iced_wgpu::triangle vertex buffer",
device,
VERTEX_BUFFER_SIZE,
- wgpu::BufferUsage::VERTEX | wgpu::BufferUsage::COPY_DST,
+ wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
),
index_buffer: Buffer::new(
"iced_wgpu::triangle index buffer",
device,
INDEX_BUFFER_SIZE,
- wgpu::BufferUsage::INDEX | wgpu::BufferUsage::COPY_DST,
+ wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST,
),
}
}
@@ -254,15 +251,15 @@ impl Pipeline {
layout: &self.constants_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
- resource: wgpu::BindingResource::Buffer {
- buffer: &self.uniforms_buffer.raw,
- offset: 0,
- size: wgpu::BufferSize::new(std::mem::size_of::<
- Uniforms,
- >(
- )
- as u64),
- },
+ resource: wgpu::BindingResource::Buffer(
+ wgpu::BufferBinding {
+ buffer: &self.uniforms_buffer.raw,
+ offset: 0,
+ size: wgpu::BufferSize::new(
+ std::mem::size_of::<Uniforms>() as u64,
+ ),
+ },
+ ),
}],
});
}
@@ -363,13 +360,11 @@ impl Pipeline {
let mut render_pass =
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("iced_wgpu::triangle render pass"),
- color_attachments: &[
- wgpu::RenderPassColorAttachmentDescriptor {
- attachment,
- resolve_target,
- ops: wgpu::Operations { load, store: true },
- },
- ],
+ color_attachments: &[wgpu::RenderPassColorAttachment {
+ view: attachment,
+ resolve_target,
+ ops: wgpu::Operations { load, store: true },
+ }],
depth_stencil_attachment: None,
});
diff --git a/wgpu/src/triangle/msaa.rs b/wgpu/src/triangle/msaa.rs
index d964f815..070d2d93 100644
--- a/wgpu/src/triangle/msaa.rs
+++ b/wgpu/src/triangle/msaa.rs
@@ -20,9 +20,9 @@ impl Blit {
address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge,
address_mode_w: wgpu::AddressMode::ClampToEdge,
- mag_filter: wgpu::FilterMode::Linear,
- min_filter: wgpu::FilterMode::Linear,
- mipmap_filter: wgpu::FilterMode::Linear,
+ mag_filter: wgpu::FilterMode::Nearest,
+ min_filter: wgpu::FilterMode::Nearest,
+ mipmap_filter: wgpu::FilterMode::Nearest,
..Default::default()
});
@@ -31,7 +31,7 @@ impl Blit {
label: Some("iced_wgpu::triangle:msaa uniforms layout"),
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
- visibility: wgpu::ShaderStage::FRAGMENT,
+ visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler {
comparison: false,
filtering: false,
@@ -55,7 +55,7 @@ impl Blit {
label: Some("iced_wgpu::triangle::msaa texture layout"),
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
- visibility: wgpu::ShaderStage::FRAGMENT,
+ visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
sample_type: wgpu::TextureSampleType::Float {
filterable: false,
@@ -74,45 +74,46 @@ impl Blit {
bind_group_layouts: &[&constant_layout, &texture_layout],
});
- let vs_module = device.create_shader_module(&wgpu::include_spirv!(
- "../shader/blit.vert.spv"
- ));
-
- let fs_module = device.create_shader_module(&wgpu::include_spirv!(
- "../shader/blit.frag.spv"
- ));
+ let shader =
+ device.create_shader_module(&wgpu::ShaderModuleDescriptor {
+ label: Some("iced_wgpu::triangle::blit_shader"),
+ source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(
+ include_str!("../shader/blit.wgsl"),
+ )),
+ });
let pipeline =
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("iced_wgpu::triangle::msaa pipeline"),
layout: Some(&layout),
vertex: wgpu::VertexState {
- module: &vs_module,
- entry_point: "main",
+ module: &shader,
+ entry_point: "vs_main",
buffers: &[],
},
fragment: Some(wgpu::FragmentState {
- module: &fs_module,
- entry_point: "main",
+ module: &shader,
+ entry_point: "fs_main",
targets: &[wgpu::ColorTargetState {
format,
- color_blend: wgpu::BlendState {
- src_factor: wgpu::BlendFactor::SrcAlpha,
- dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
- operation: wgpu::BlendOperation::Add,
- },
- alpha_blend: wgpu::BlendState {
- src_factor: wgpu::BlendFactor::One,
- dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
- operation: wgpu::BlendOperation::Add,
- },
- write_mask: wgpu::ColorWrite::ALL,
+ blend: Some(wgpu::BlendState {
+ color: wgpu::BlendComponent {
+ src_factor: wgpu::BlendFactor::SrcAlpha,
+ dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
+ operation: wgpu::BlendOperation::Add,
+ },
+ alpha: wgpu::BlendComponent {
+ src_factor: wgpu::BlendFactor::One,
+ dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
+ operation: wgpu::BlendOperation::Add,
+ },
+ }),
+ write_mask: wgpu::ColorWrites::ALL,
}],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
front_face: wgpu::FrontFace::Cw,
- cull_mode: wgpu::CullMode::None,
..Default::default()
},
depth_stencil: None,
@@ -177,16 +178,14 @@ impl Blit {
let mut render_pass =
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("iced_wgpu::triangle::msaa render pass"),
- color_attachments: &[
- wgpu::RenderPassColorAttachmentDescriptor {
- attachment: target,
- resolve_target: None,
- ops: wgpu::Operations {
- load: wgpu::LoadOp::Load,
- store: true,
- },
+ color_attachments: &[wgpu::RenderPassColorAttachment {
+ view: target,
+ resolve_target: None,
+ ops: wgpu::Operations {
+ load: wgpu::LoadOp::Load,
+ store: true,
},
- ],
+ }],
depth_stencil_attachment: None,
});
@@ -222,7 +221,7 @@ impl Targets {
let extent = wgpu::Extent3d {
width,
height,
- depth: 1,
+ depth_or_array_layers: 1,
};
let attachment = device.create_texture(&wgpu::TextureDescriptor {
@@ -232,7 +231,7 @@ impl Targets {
sample_count,
dimension: wgpu::TextureDimension::D2,
format,
- usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
+ usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
});
let resolve = device.create_texture(&wgpu::TextureDescriptor {
@@ -242,8 +241,8 @@ impl Targets {
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format,
- usage: wgpu::TextureUsage::RENDER_ATTACHMENT
- | wgpu::TextureUsage::SAMPLED,
+ usage: wgpu::TextureUsages::RENDER_ATTACHMENT
+ | wgpu::TextureUsages::TEXTURE_BINDING,
});
let attachment =
diff --git a/wgpu/src/widget.rs b/wgpu/src/widget.rs
index 304bb726..a575d036 100644
--- a/wgpu/src/widget.rs
+++ b/wgpu/src/widget.rs
@@ -20,6 +20,7 @@ pub mod rule;
pub mod scrollable;
pub mod slider;
pub mod text_input;
+pub mod toggler;
pub mod tooltip;
#[doc(no_inline)]
@@ -45,6 +46,8 @@ pub use slider::Slider;
#[doc(no_inline)]
pub use text_input::TextInput;
#[doc(no_inline)]
+pub use toggler::Toggler;
+#[doc(no_inline)]
pub use tooltip::Tooltip;
#[cfg(feature = "canvas")]
diff --git a/wgpu/src/widget/pane_grid.rs b/wgpu/src/widget/pane_grid.rs
index 44f9201c..fc36862c 100644
--- a/wgpu/src/widget/pane_grid.rs
+++ b/wgpu/src/widget/pane_grid.rs
@@ -6,7 +6,7 @@
//! The [`pane_grid` example] showcases how to use a [`PaneGrid`] with resizing,
//! drag and drop, and hotkey support.
//!
-//! [`pane_grid` example]: https://github.com/hecrj/iced/tree/0.2/examples/pane_grid
+//! [`pane_grid` example]: https://github.com/hecrj/iced/tree/0.3/examples/pane_grid
use crate::Renderer;
pub use iced_graphics::pane_grid::{
diff --git a/wgpu/src/widget/toggler.rs b/wgpu/src/widget/toggler.rs
new file mode 100644
index 00000000..dfcf759b
--- /dev/null
+++ b/wgpu/src/widget/toggler.rs
@@ -0,0 +1,9 @@
+//! Show toggle controls using togglers.
+use crate::Renderer;
+
+pub use iced_graphics::toggler::{Style, StyleSheet};
+
+/// A toggler that can be toggled
+///
+/// This is an alias of an `iced_native` toggler with an `iced_wgpu::Renderer`.
+pub type Toggler<Message> = iced_native::Toggler<Message, Renderer>;
diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs
index 36d6ab1a..eca54b6f 100644
--- a/wgpu/src/window/compositor.rs
+++ b/wgpu/src/window/compositor.rs
@@ -13,6 +13,7 @@ pub struct Compositor {
queue: wgpu::Queue,
staging_belt: wgpu::util::StagingBelt,
local_pool: futures::executor::LocalPool,
+ format: wgpu::TextureFormat,
}
impl Compositor {
@@ -21,8 +22,15 @@ impl Compositor {
/// Requests a new [`Compositor`] with the given [`Settings`].
///
/// Returns `None` if no compatible graphics adapter could be found.
- pub async fn request(settings: Settings) -> Option<Self> {
- let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
+ pub async fn request<W: HasRawWindowHandle>(
+ settings: Settings,
+ compatible_window: Option<&W>,
+ ) -> Option<Self> {
+ let instance = wgpu::Instance::new(settings.internal_backend);
+
+ #[allow(unsafe_code)]
+ let compatible_surface = compatible_window
+ .map(|window| unsafe { instance.create_surface(window) });
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
@@ -31,10 +39,14 @@ impl Compositor {
} else {
wgpu::PowerPreference::HighPerformance
},
- compatible_surface: None,
+ compatible_surface: compatible_surface.as_ref(),
})
.await?;
+ let format = compatible_surface
+ .as_ref()
+ .and_then(|surface| surface.get_preferred_format(&adapter))?;
+
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
@@ -62,12 +74,13 @@ impl Compositor {
queue,
staging_belt,
local_pool,
+ format,
})
}
/// Creates a new rendering [`Backend`] for this [`Compositor`].
pub fn create_backend(&self) -> Backend {
- Backend::new(&self.device, self.settings)
+ Backend::new(&self.device, self.settings, self.format)
}
}
@@ -75,11 +88,16 @@ impl iced_graphics::window::Compositor for Compositor {
type Settings = Settings;
type Renderer = Renderer;
type Surface = wgpu::Surface;
- type SwapChain = wgpu::SwapChain;
- fn new(settings: Self::Settings) -> Result<(Self, Renderer), Error> {
- let compositor = futures::executor::block_on(Self::request(settings))
- .ok_or(Error::AdapterNotFound)?;
+ fn new<W: HasRawWindowHandle>(
+ settings: Self::Settings,
+ compatible_window: Option<&W>,
+ ) -> Result<(Self, Renderer), Error> {
+ let compositor = futures::executor::block_on(Self::request(
+ settings,
+ compatible_window,
+ ))
+ .ok_or(Error::AdapterNotFound)?;
let backend = compositor.create_backend();
@@ -96,85 +114,110 @@ impl iced_graphics::window::Compositor for Compositor {
}
}
- fn create_swap_chain(
+ fn configure_surface(
&mut self,
- surface: &Self::Surface,
+ surface: &mut Self::Surface,
width: u32,
height: u32,
- ) -> Self::SwapChain {
- self.device.create_swap_chain(
- surface,
- &wgpu::SwapChainDescriptor {
- usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
- format: self.settings.format,
+ ) {
+ surface.configure(
+ &self.device,
+ &wgpu::SurfaceConfiguration {
+ usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
+ format: self.format,
present_mode: self.settings.present_mode,
width,
height,
},
- )
+ );
}
fn draw<T: AsRef<str>>(
&mut self,
renderer: &mut Self::Renderer,
- swap_chain: &mut Self::SwapChain,
+ surface: &mut Self::Surface,
viewport: &Viewport,
background_color: Color,
output: &<Self::Renderer as iced_native::Renderer>::Output,
overlay: &[T],
- ) -> mouse::Interaction {
- let frame = swap_chain.get_current_frame().expect("Next frame");
-
- let mut encoder = self.device.create_command_encoder(
- &wgpu::CommandEncoderDescriptor {
- label: Some("iced_wgpu encoder"),
+ ) -> Result<mouse::Interaction, iced_graphics::window::SurfaceError> {
+ match surface.get_current_frame() {
+ Ok(frame) => {
+ let mut encoder = self.device.create_command_encoder(
+ &wgpu::CommandEncoderDescriptor {
+ label: Some("iced_wgpu encoder"),
+ },
+ );
+
+ let view = &frame
+ .output
+ .texture
+ .create_view(&wgpu::TextureViewDescriptor::default());
+
+ let _ =
+ encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
+ label: Some(
+ "iced_wgpu::window::Compositor render pass",
+ ),
+ color_attachments: &[wgpu::RenderPassColorAttachment {
+ view,
+ resolve_target: None,
+ ops: wgpu::Operations {
+ load: wgpu::LoadOp::Clear({
+ let [r, g, b, a] =
+ background_color.into_linear();
+
+ wgpu::Color {
+ r: f64::from(r),
+ g: f64::from(g),
+ b: f64::from(b),
+ a: f64::from(a),
+ }
+ }),
+ store: true,
+ },
+ }],
+ depth_stencil_attachment: None,
+ });
+
+ let mouse_interaction = renderer.backend_mut().draw(
+ &mut self.device,
+ &mut self.staging_belt,
+ &mut encoder,
+ view,
+ viewport,
+ output,
+ overlay,
+ );
+
+ // Submit work
+ self.staging_belt.finish();
+ self.queue.submit(Some(encoder.finish()));
+
+ // Recall staging buffers
+ self.local_pool
+ .spawner()
+ .spawn(self.staging_belt.recall())
+ .expect("Recall staging belt");
+
+ self.local_pool.run_until_stalled();
+
+ Ok(mouse_interaction)
+ }
+ Err(error) => match error {
+ wgpu::SurfaceError::Timeout => {
+ Err(iced_graphics::window::SurfaceError::Timeout)
+ }
+ wgpu::SurfaceError::Outdated => {
+ Err(iced_graphics::window::SurfaceError::Outdated)
+ }
+ wgpu::SurfaceError::Lost => {
+ Err(iced_graphics::window::SurfaceError::Lost)
+ }
+ wgpu::SurfaceError::OutOfMemory => {
+ Err(iced_graphics::window::SurfaceError::OutOfMemory)
+ }
},
- );
-
- let _ = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
- label: Some("iced_wgpu::window::Compositor render pass"),
- color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
- attachment: &frame.output.view,
- resolve_target: None,
- ops: wgpu::Operations {
- load: wgpu::LoadOp::Clear({
- let [r, g, b, a] = background_color.into_linear();
-
- wgpu::Color {
- r: f64::from(r),
- g: f64::from(g),
- b: f64::from(b),
- a: f64::from(a),
- }
- }),
- store: true,
- },
- }],
- depth_stencil_attachment: None,
- });
-
- let mouse_interaction = renderer.backend_mut().draw(
- &mut self.device,
- &mut self.staging_belt,
- &mut encoder,
- &frame.output.view,
- viewport,
- output,
- overlay,
- );
-
- // Submit work
- self.staging_belt.finish();
- self.queue.submit(Some(encoder.finish()));
-
- // Recall staging buffers
- self.local_pool
- .spawner()
- .spawn(self.staging_belt.recall())
- .expect("Recall staging belt");
-
- self.local_pool.run_until_stalled();
-
- mouse_interaction
+ }
}
}