summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar shan <shankern@protonmail.com>2022-10-04 18:24:46 -0700
committerLibravatar shan <shankern@protonmail.com>2022-10-04 18:24:46 -0700
commit6e7b3ced0b1daf368e44e181ecdb4ae529877eb6 (patch)
treee530025c737d509b640172d595cff0a0809f5a40
parent5d0fffc626928177239336757507b986b081b878 (diff)
downloadiced-6e7b3ced0b1daf368e44e181ecdb4ae529877eb6.tar.gz
iced-6e7b3ced0b1daf368e44e181ecdb4ae529877eb6.tar.bz2
iced-6e7b3ced0b1daf368e44e181ecdb4ae529877eb6.zip
Reworked wgpu buffers, updated glow side to have proper transform location storage, attempting to fix visibility modifiers, implemented some of the feedback received in initial PR.
-rw-r--r--examples/arc/src/main.rs4
-rw-r--r--examples/clock/src/main.rs6
-rw-r--r--examples/modern_art/src/main.rs7
-rw-r--r--examples/solar_system/src/main.rs4
-rw-r--r--glow/src/backend.rs2
-rw-r--r--glow/src/shader/common/gradient.frag1
-rw-r--r--glow/src/triangle.rs126
-rw-r--r--glow/src/triangle/gradient.rs92
-rw-r--r--glow/src/triangle/solid.rs62
-rw-r--r--graphics/src/gradient.rs2
-rw-r--r--graphics/src/layer.rs32
-rw-r--r--graphics/src/widget/canvas.rs4
-rw-r--r--graphics/src/widget/canvas/fill.rs14
-rw-r--r--graphics/src/widget/canvas/stroke.rs14
-rw-r--r--wgpu/src/backend.rs2
-rw-r--r--wgpu/src/buffers/buffer.rs141
-rw-r--r--wgpu/src/buffers/dynamic_buffers.rs3
-rw-r--r--wgpu/src/triangle.rs303
-rw-r--r--wgpu/src/triangle/gradient.rs6
-rw-r--r--wgpu/src/triangle/solid.rs15
20 files changed, 417 insertions, 423 deletions
diff --git a/examples/arc/src/main.rs b/examples/arc/src/main.rs
index 6029a69c..bc7e49c6 100644
--- a/examples/arc/src/main.rs
+++ b/examples/arc/src/main.rs
@@ -2,7 +2,7 @@ use std::{f32::consts::PI, time::Instant};
use iced::executor;
use iced::widget::canvas::{
- self, Cache, Canvas, Cursor, Geometry, Path, Stroke, StrokeStyle,
+ self, Cache, Canvas, Cursor, Geometry, Path, Stroke, Style,
};
use iced::{
Application, Command, Element, Length, Point, Rectangle, Settings,
@@ -114,7 +114,7 @@ impl<Message> canvas::Program<Message> for Arc {
frame.stroke(
&path,
Stroke {
- style: StrokeStyle::Solid(palette.text),
+ style: Style::Solid(palette.text),
width: 10.0,
..Stroke::default()
},
diff --git a/examples/clock/src/main.rs b/examples/clock/src/main.rs
index 51f25a3f..06ed44f0 100644
--- a/examples/clock/src/main.rs
+++ b/examples/clock/src/main.rs
@@ -1,6 +1,6 @@
use iced::executor;
use iced::widget::canvas::{
- Cache, Cursor, Geometry, LineCap, Path, Stroke, StrokeStyle,
+ Cache, Cursor, Geometry, LineCap, Path, Stroke, Style,
};
use iced::widget::{canvas, container};
use iced::{
@@ -111,7 +111,7 @@ impl<Message> canvas::Program<Message> for Clock {
let thin_stroke = || -> Stroke {
Stroke {
width,
- style: StrokeStyle::Solid(Color::WHITE),
+ style: Style::Solid(Color::WHITE),
line_cap: LineCap::Round,
..Stroke::default()
}
@@ -120,7 +120,7 @@ impl<Message> canvas::Program<Message> for Clock {
let wide_stroke = || -> Stroke {
Stroke {
width: width * 3.0,
- style: StrokeStyle::Solid(Color::WHITE),
+ style: Style::Solid(Color::WHITE),
line_cap: LineCap::Round,
..Stroke::default()
}
diff --git a/examples/modern_art/src/main.rs b/examples/modern_art/src/main.rs
index c7945012..238c9a0f 100644
--- a/examples/modern_art/src/main.rs
+++ b/examples/modern_art/src/main.rs
@@ -1,5 +1,5 @@
use rand::{Rng, thread_rng};
-use crate::canvas::{Cursor, FillStyle, Geometry};
+use crate::canvas::{Cursor, Geometry};
use iced::widget::canvas::{Cache, Fill, Frame};
use iced::widget::{canvas, Canvas};
use iced::Settings;
@@ -8,6 +8,7 @@ use iced::{
Renderer, Size, Theme,
};
use iced_graphics::gradient::Gradient;
+use iced_graphics::widget::canvas::Style;
fn main() -> iced::Result {
ModernArt::run(Settings {
@@ -120,7 +121,7 @@ fn generate_box(frame: &mut Frame, bounds: Size) -> bool {
top_left,
size,
Fill {
- style: FillStyle::Solid(random_color()),
+ style: Style::Solid(random_color()),
.. Default::default()
}
);
@@ -129,7 +130,7 @@ fn generate_box(frame: &mut Frame, bounds: Size) -> bool {
top_left,
size,
Fill {
- style: FillStyle::Gradient(&gradient(
+ style: Style::Gradient(&gradient(
top_left,
Point::new(top_left.x + size.width, top_left.y + size.height)
)),
diff --git a/examples/solar_system/src/main.rs b/examples/solar_system/src/main.rs
index fcd20561..8d713ce0 100644
--- a/examples/solar_system/src/main.rs
+++ b/examples/solar_system/src/main.rs
@@ -19,7 +19,7 @@ use iced::{
};
use std::time::Instant;
-use crate::canvas::StrokeStyle;
+use crate::canvas::Style;
pub fn main() -> iced::Result {
SolarSystem::run(Settings {
@@ -179,7 +179,7 @@ impl<Message> canvas::Program<Message> for State {
frame.stroke(
&orbit,
Stroke {
- style: StrokeStyle::Solid(Color::from_rgba8(0, 153, 255, 0.1)),
+ style: Style::Solid(Color::from_rgba8(0, 153, 255, 0.1)),
width: 1.0,
line_dash: canvas::LineDash {
offset: 0,
diff --git a/glow/src/backend.rs b/glow/src/backend.rs
index 6fc4fb38..7333d513 100644
--- a/glow/src/backend.rs
+++ b/glow/src/backend.rs
@@ -99,7 +99,7 @@ impl Backend {
);
}
- if !layer.meshes.0.is_empty() {
+ if !layer.meshes.is_empty() {
let scaled = transformation
* Transformation::scale(scale_factor, scale_factor);
diff --git a/glow/src/shader/common/gradient.frag b/glow/src/shader/common/gradient.frag
index 588f63e0..1afb557d 100644
--- a/glow/src/shader/common/gradient.frag
+++ b/glow/src/shader/common/gradient.frag
@@ -23,6 +23,7 @@ uniform uint color_stops_size;
uniform float color_stop_offsets[MAX_STOPS];
uniform vec4 color_stop_colors[MAX_STOPS];
+//TODO: rewrite without branching to make ALUs happy
void main() {
vec2 gradient_vec = vec2(gradient_end - gradient_start);
vec2 current_vec = vec2(raw_position.xy - gradient_start);
diff --git a/glow/src/triangle.rs b/glow/src/triangle.rs
index 85d873fe..f16f8af4 100644
--- a/glow/src/triangle.rs
+++ b/glow/src/triangle.rs
@@ -2,23 +2,22 @@
mod gradient;
mod solid;
-use crate::program::{self, Shader};
-use crate::Transformation;
+use crate::{program, Transformation};
use glow::HasContext;
-use iced_graphics::layer::{Mesh, Meshes};
+use iced_graphics::layer::{attribute_count_of, Mesh};
use iced_graphics::shader;
use std::marker::PhantomData;
use crate::triangle::gradient::GradientProgram;
use crate::triangle::solid::SolidProgram;
pub use iced_graphics::triangle::{Mesh2D, Vertex2D};
+use shader::Shader;
#[derive(Debug)]
pub(crate) struct Pipeline {
vertex_array: <glow::Context as HasContext>::VertexArray,
vertices: Buffer<Vertex2D>,
indices: Buffer<u32>,
- current_transform: Transformation,
programs: TrianglePrograms,
}
@@ -68,7 +67,6 @@ impl Pipeline {
vertex_array,
vertices,
indices,
- current_transform: Transformation::identity(),
programs: TrianglePrograms {
solid: SolidProgram::new(gl, shader_version),
gradient: GradientProgram::new(gl, shader_version),
@@ -78,7 +76,7 @@ impl Pipeline {
pub fn draw(
&mut self,
- meshes: &Meshes<'_>,
+ meshes: &[Mesh<'_>],
gl: &glow::Context,
target_height: u32,
transformation: Transformation,
@@ -90,8 +88,8 @@ impl Pipeline {
gl.bind_vertex_array(Some(self.vertex_array))
}
- //count the total number of vertices & indices we need to handle for all meshes
- let (total_vertices, total_indices) = meshes.attribute_count();
+ //count the total amount of vertices & indices we need to handle
+ let (total_vertices, total_indices) = attribute_count_of(meshes);
// Then we ensure the current attribute buffers are big enough, resizing if necessary
unsafe {
@@ -100,25 +98,25 @@ impl Pipeline {
}
// We upload all the vertices and indices upfront
- let mut last_vertex = 0;
- let mut last_index = 0;
+ let mut vertex_offset = 0;
+ let mut index_offset = 0;
- for Mesh { buffers, .. } in meshes.0.iter() {
+ for mesh in meshes {
unsafe {
gl.buffer_sub_data_u8_slice(
glow::ARRAY_BUFFER,
- (last_vertex * std::mem::size_of::<Vertex2D>()) as i32,
- bytemuck::cast_slice(&buffers.vertices),
+ (vertex_offset * std::mem::size_of::<Vertex2D>()) as i32,
+ bytemuck::cast_slice(&mesh.buffers.vertices),
);
gl.buffer_sub_data_u8_slice(
glow::ELEMENT_ARRAY_BUFFER,
- (last_index * std::mem::size_of::<u32>()) as i32,
- bytemuck::cast_slice(&buffers.indices),
+ (index_offset * std::mem::size_of::<u32>()) as i32,
+ bytemuck::cast_slice(&mesh.buffers.indices),
);
- last_vertex += buffers.vertices.len();
- last_index += buffers.indices.len();
+ vertex_offset += mesh.buffers.vertices.len();
+ index_offset += mesh.buffers.indices.len();
}
}
@@ -126,22 +124,11 @@ impl Pipeline {
let mut last_vertex = 0;
let mut last_index = 0;
- for (index, Mesh {
- buffers,
- origin,
- clip_bounds,
- shader,
- }) in meshes.0.iter().enumerate()
- {
- let transform =
- transformation * Transformation::translate(origin.x, origin.y);
-
- if index == 0 {
- //set initial transform uniform for both programs
- self.programs.set_transforms(gl, transform);
- }
+ for mesh in meshes {
+ let transform = transformation
+ * Transformation::translate(mesh.origin.x, mesh.origin.y);
- let clip_bounds = (*clip_bounds * scale_factor).snap();
+ let clip_bounds = (mesh.clip_bounds * scale_factor).snap();
unsafe {
gl.scissor(
@@ -152,25 +139,25 @@ impl Pipeline {
clip_bounds.height as i32,
);
- let t = if self.current_transform != transform {
- self.current_transform = transform;
- Some(transform)
- } else {
- None
- };
-
- self.use_with_shader(gl, shader, t);
+ match mesh.shader {
+ Shader::Solid(color) => {
+ self.programs.solid.use_program(gl, &color, &transform);
+ }
+ Shader::Gradient(gradient) => {
+ self.programs.gradient.use_program(gl, &gradient, &transform);
+ }
+ }
gl.draw_elements_base_vertex(
glow::TRIANGLES,
- buffers.indices.len() as i32,
+ mesh.buffers.indices.len() as i32,
glow::UNSIGNED_INT,
(last_index * std::mem::size_of::<u32>()) as i32,
last_vertex as i32,
);
- last_vertex += buffers.vertices.len();
- last_index += buffers.indices.len();
+ last_vertex += mesh.buffers.vertices.len();
+ last_index += mesh.buffers.indices.len();
}
}
@@ -180,31 +167,6 @@ impl Pipeline {
gl.disable(glow::MULTISAMPLE);
}
}
-
- fn use_with_shader(
- &mut self,
- gl: &glow::Context,
- shader: &shader::Shader,
- transform: Option<Transformation>,
- ) {
- match shader {
- shader::Shader::Solid(color) => {
- unsafe { gl.use_program(Some(self.programs.solid.program)) }
- self.programs.solid.set_uniforms(gl, color, transform);
- }
- shader::Shader::Gradient(gradient) => {
- unsafe { gl.use_program(Some(self.programs.gradient.program)) }
- self.programs.gradient.set_uniforms(gl, gradient, transform);
- }
- }
- }
-}
-
-impl TrianglePrograms {
- pub fn set_transforms(&self, gl: &glow::Context, transform: Transformation) {
- update_transform(gl, self.solid.program, Some(transform));
- update_transform(gl, self.gradient.program, Some(transform));
- }
}
/// A simple shader program. Uses [`triangle.vert`] for its vertex shader and only binds position
@@ -215,14 +177,14 @@ pub(super) fn simple_triangle_program(
fragment_shader: &'static str,
) -> <glow::Context as HasContext>::Program {
unsafe {
- let vertex_shader = Shader::vertex(
+ let vertex_shader = program::Shader::vertex(
gl,
shader_version,
include_str!("shader/common/triangle.vert"),
);
let fragment_shader =
- Shader::fragment(gl, shader_version, fragment_shader);
+ program::Shader::fragment(gl, shader_version, fragment_shader);
program::create(
gl,
@@ -232,23 +194,17 @@ pub(super) fn simple_triangle_program(
}
}
-pub(super) fn update_transform(
+pub fn set_transform(
gl: &glow::Context,
- program: <glow::Context as HasContext>::Program,
- transform: Option<Transformation>
+ location: <glow::Context as HasContext>::UniformLocation,
+ transform: Transformation,
) {
- if let Some(t) = transform {
- let transform_location =
- unsafe { gl.get_uniform_location(program, "u_Transform") }
- .expect("Get transform location.");
-
- unsafe {
- gl.uniform_matrix_4_f32_slice(
- Some(&transform_location),
- false,
- t.as_ref(),
- );
- }
+ unsafe {
+ gl.uniform_matrix_4_f32_slice(
+ Some(&location),
+ false,
+ transform.as_ref()
+ );
}
}
diff --git a/glow/src/triangle/gradient.rs b/glow/src/triangle/gradient.rs
index d1b10d77..547871e2 100644
--- a/glow/src/triangle/gradient.rs
+++ b/glow/src/triangle/gradient.rs
@@ -1,18 +1,42 @@
use crate::program::Version;
-use crate::triangle::{simple_triangle_program, update_transform};
+use crate::triangle::{simple_triangle_program, set_transform};
use glow::{Context, HasContext, NativeProgram};
+use iced_graphics::gradient::Linear;
use iced_graphics::gradient::Gradient;
-use iced_graphics::widget::canvas::gradient::Linear;
use iced_graphics::Transformation;
#[derive(Debug)]
-pub(super) struct GradientProgram {
- pub(super) program: <Context as HasContext>::Program,
- pub(super) uniform_data: GradientUniformData,
+pub struct GradientProgram {
+ pub program: <Context as HasContext>::Program,
+ pub uniform_data: GradientUniformData,
+}
+
+#[derive(Debug)]
+pub struct GradientUniformData {
+ gradient: Gradient,
+ transform: Transformation,
+ uniform_locations: GradientUniformLocations,
+}
+
+#[derive(Debug)]
+struct GradientUniformLocations {
+ gradient_start_location: <Context as HasContext>::UniformLocation,
+ gradient_end_location: <Context as HasContext>::UniformLocation,
+ color_stops_size_location: <Context as HasContext>::UniformLocation,
+ //currently the maximum number of stops is 64 due to needing to allocate the
+ //memory for the array of stops with a const value in GLSL
+ color_stops_locations: [ColorStopLocation; 64],
+ transform_location: <Context as HasContext>::UniformLocation,
+}
+
+#[derive(Copy, Debug, Clone)]
+struct ColorStopLocation {
+ color: <Context as HasContext>::UniformLocation,
+ offset: <Context as HasContext>::UniformLocation,
}
impl GradientProgram {
- pub(super) fn new(gl: &Context, shader_version: &Version) -> Self {
+ pub fn new(gl: &Context, shader_version: &Version) -> Self {
let program = simple_triangle_program(
gl,
shader_version,
@@ -25,15 +49,17 @@ impl GradientProgram {
}
}
- pub(super) fn set_uniforms<'a>(
+ pub fn write_uniforms(
&mut self,
gl: &Context,
gradient: &Gradient,
- transform: Option<Transformation>,
+ transform: &Transformation,
) {
- update_transform(gl, self.program, transform);
+ if transform != &self.uniform_data.transform {
+ set_transform(gl, self.uniform_data.uniform_locations.transform_location, *transform);
+ }
- if &self.uniform_data.current_gradient != gradient {
+ if &self.uniform_data.gradient != gradient {
match gradient {
Gradient::Linear(linear) => {
let gradient_start: [f32; 2] = (linear.start).into();
@@ -104,31 +130,17 @@ impl GradientProgram {
}
}
- self.uniform_data.current_gradient = gradient.clone();
+ self.uniform_data.gradient = gradient.clone();
}
}
-}
-
-#[derive(Debug)]
-pub(super) struct GradientUniformData {
- current_gradient: Gradient,
- uniform_locations: GradientUniformLocations,
-}
-#[derive(Debug)]
-struct GradientUniformLocations {
- gradient_start_location: <Context as HasContext>::UniformLocation,
- gradient_end_location: <Context as HasContext>::UniformLocation,
- color_stops_size_location: <Context as HasContext>::UniformLocation,
- //currently the maximum number of stops is 64 due to needing to allocate the
- //memory for the array of stops with a const value in GLSL
- color_stops_locations: [ColorStopLocation; 64],
-}
+ pub fn use_program(&mut self, gl: &glow::Context, gradient: &Gradient, transform: &Transformation) {
+ unsafe {
+ gl.use_program(Some(self.program))
+ }
-#[derive(Copy, Debug, Clone)]
-struct ColorStopLocation {
- color: <Context as HasContext>::UniformLocation,
- offset: <Context as HasContext>::UniformLocation,
+ self.write_uniforms(gl, gradient, transform);
+ }
}
impl GradientUniformData {
@@ -153,10 +165,7 @@ impl GradientUniformData {
&format!("color_stop_offsets[{}]", index),
)
}
- .expect(&format!(
- "Gradient - Color stop offset with index {}",
- index
- ));
+ .expect("Gradient - Color stop offset location.");
let color = unsafe {
gl.get_uniform_location(
@@ -164,25 +173,28 @@ impl GradientUniformData {
&format!("color_stop_colors[{}]", index),
)
}
- .expect(&format!(
- "Gradient - Color stop colors with index {}",
- index
- ));
+ .expect("Gradient - Color stop color location.");
ColorStopLocation { color, offset }
});
+ let transform_location =
+ unsafe { gl.get_uniform_location(program, "u_Transform") }
+ .expect("Get transform location.");
+
GradientUniformData {
- current_gradient: Gradient::Linear(Linear {
+ gradient: Gradient::Linear(Linear {
start: Default::default(),
end: Default::default(),
color_stops: vec![],
}),
+ transform: Transformation::identity(),
uniform_locations: GradientUniformLocations {
gradient_start_location,
gradient_end_location,
color_stops_size_location,
color_stops_locations,
+ transform_location,
},
}
}
diff --git a/glow/src/triangle/solid.rs b/glow/src/triangle/solid.rs
index 3a33cea8..d5b73eb9 100644
--- a/glow/src/triangle/solid.rs
+++ b/glow/src/triangle/solid.rs
@@ -1,13 +1,38 @@
use crate::program::Version;
-use crate::triangle::{simple_triangle_program, update_transform};
+use crate::triangle::{set_transform, simple_triangle_program};
use crate::Color;
use glow::{Context, HasContext, NativeProgram};
use iced_graphics::Transformation;
#[derive(Debug)]
pub struct SolidProgram {
- pub(crate) program: <Context as HasContext>::Program,
- pub(crate) uniform_data: SolidUniformData,
+ program: <Context as HasContext>::Program,
+ uniform_data: SolidUniformData,
+}
+
+#[derive(Debug)]
+pub(crate) struct SolidUniformData {
+ pub color: Color,
+ pub color_location: <Context as HasContext>::UniformLocation,
+ pub transform: Transformation,
+ pub transform_location: <Context as HasContext>::UniformLocation,
+}
+
+impl SolidUniformData {
+ fn new(gl: &Context, program: NativeProgram) -> Self {
+ Self {
+ color: Color::TRANSPARENT,
+ color_location: unsafe {
+ gl.get_uniform_location(program, "color")
+ }
+ .expect("Solid - Color uniform location."),
+ transform: Transformation::identity(),
+ transform_location: unsafe {
+ gl.get_uniform_location(program, "u_Transform")
+ }
+ .expect("Get transform location."),
+ }
+ }
}
impl SolidProgram {
@@ -24,15 +49,17 @@ impl SolidProgram {
}
}
- pub fn set_uniforms<'a>(
+ pub fn write_uniforms(
&mut self,
gl: &Context,
color: &Color,
- transform: Option<Transformation>,
+ transform: &Transformation,
) {
- update_transform(gl, self.program, transform);
+ if transform != &self.uniform_data.transform {
+ set_transform(gl, self.uniform_data.transform_location, *transform)
+ }
- if &self.uniform_data.color != color {
+ if color != &self.uniform_data.color {
unsafe {
gl.uniform_4_f32(
Some(&self.uniform_data.color_location),
@@ -46,22 +73,11 @@ impl SolidProgram {
self.uniform_data.color = *color;
}
}
-}
-
-#[derive(Debug)]
-pub(crate) struct SolidUniformData {
- pub color: Color,
- pub color_location: <Context as HasContext>::UniformLocation,
-}
-impl SolidUniformData {
- fn new(gl: &Context, program: NativeProgram) -> Self {
- Self {
- color: Color::TRANSPARENT,
- color_location: unsafe {
- gl.get_uniform_location(program, "color")
- }
- .expect("Solid - Color uniform location."),
+ pub fn use_program(&mut self, gl: &glow::Context, color: &Color, transform: &Transformation) {
+ unsafe {
+ gl.use_program(Some(self.program))
}
+ self.write_uniforms(gl, color, transform)
}
-}
+} \ No newline at end of file
diff --git a/graphics/src/gradient.rs b/graphics/src/gradient.rs
index fa57842b..0c394e8b 100644
--- a/graphics/src/gradient.rs
+++ b/graphics/src/gradient.rs
@@ -1,6 +1,6 @@
//! For creating a Gradient.
use iced_native::Color;
-use crate::gradient::linear::Linear;
+pub use crate::gradient::linear::Linear;
use crate::Point;
#[derive(Debug, Clone, PartialEq)]
diff --git a/graphics/src/layer.rs b/graphics/src/layer.rs
index b7731922..096c50dc 100644
--- a/graphics/src/layer.rs
+++ b/graphics/src/layer.rs
@@ -19,7 +19,7 @@ pub struct Layer<'a> {
pub quads: Vec<Quad>,
/// The triangle meshes of the [`Layer`].
- pub meshes: Meshes<'a>,
+ pub meshes: Vec<Mesh<'a>>,
/// The text of the [`Layer`].
pub text: Vec<Text<'a>>,
@@ -34,7 +34,7 @@ impl<'a> Layer<'a> {
Self {
bounds,
quads: Vec::new(),
- meshes: Meshes(Vec::new()),
+ meshes: Vec::new(),
text: Vec::new(),
images: Vec::new(),
}
@@ -174,7 +174,7 @@ impl<'a> Layer<'a> {
// Only draw visible content
if let Some(clip_bounds) = layer.bounds.intersection(&bounds) {
- layer.meshes.0.push(
+ layer.meshes.push(
Mesh {
origin: Point::new(translation.x, translation.y),
buffers,
@@ -335,20 +335,14 @@ unsafe impl bytemuck::Zeroable for Quad {}
#[allow(unsafe_code)]
unsafe impl bytemuck::Pod for Quad {}
-#[derive(Debug)]
-/// A collection of meshes.
-pub struct Meshes<'a>(pub Vec<Mesh<'a>>);
-
-impl<'a> Meshes<'a> {
- /// Returns the number of total vertices & total indices of all [`Mesh`]es.
- pub fn attribute_count(&self) -> (usize, usize) {
- self.0
- .iter()
- .map(|Mesh { buffers, .. }| {
- (buffers.vertices.len(), buffers.indices.len())
- })
- .fold((0, 0), |(total_v, total_i), (v, i)| {
- (total_v + v, total_i + i)
- })
- }
+/// Returns the number of total vertices & total indices of all [`Mesh`]es.
+pub fn attribute_count_of<'a>(meshes: &'a [Mesh<'a>]) -> (usize, usize) {
+ meshes
+ .iter()
+ .map(|Mesh { buffers, .. }| {
+ (buffers.vertices.len(), buffers.indices.len())
+ })
+ .fold((0, 0), |(total_v, total_i), (v, i)| {
+ (total_v + v, total_i + i)
+ })
} \ No newline at end of file
diff --git a/graphics/src/widget/canvas.rs b/graphics/src/widget/canvas.rs
index 95c962af..f6929e97 100644
--- a/graphics/src/widget/canvas.rs
+++ b/graphics/src/widget/canvas.rs
@@ -19,12 +19,12 @@ mod text;
pub use cache::Cache;
pub use cursor::Cursor;
pub use event::Event;
-pub use fill::{Fill, FillRule, FillStyle};
+pub use fill::{Fill, FillRule, Style};
pub use frame::Frame;
pub use geometry::Geometry;
pub use path::Path;
pub use program::Program;
-pub use stroke::{LineCap, LineDash, LineJoin, Stroke, StrokeStyle};
+pub use stroke::{LineCap, LineDash, LineJoin, Stroke};
pub use text::Text;
use crate::{Backend, Primitive, Renderer};
diff --git a/graphics/src/widget/canvas/fill.rs b/graphics/src/widget/canvas/fill.rs
index 60029e03..6f10505c 100644
--- a/graphics/src/widget/canvas/fill.rs
+++ b/graphics/src/widget/canvas/fill.rs
@@ -8,7 +8,7 @@ pub struct Fill<'a> {
/// The color or gradient of the fill.
///
/// By default, it is set to [`FillStyle::Solid`] `BLACK`.
- pub style: FillStyle<'a>,
+ pub style: Style<'a>,
/// The fill rule defines how to determine what is inside and what is
/// outside of a shape.
@@ -24,7 +24,7 @@ pub struct Fill<'a> {
impl <'a> Default for Fill<'a> {
fn default() -> Fill<'a> {
Fill {
- style: FillStyle::Solid(Color::BLACK),
+ style: Style::Solid(Color::BLACK),
rule: FillRule::NonZero,
}
}
@@ -33,7 +33,7 @@ impl <'a> Default for Fill<'a> {
impl<'a> From<Color> for Fill<'a> {
fn from(color: Color) -> Fill<'a> {
Fill {
- style: FillStyle::Solid(color),
+ style: Style::Solid(color),
..Fill::default()
}
}
@@ -41,18 +41,18 @@ impl<'a> From<Color> for Fill<'a> {
/// The color or gradient of a [`Fill`].
#[derive(Debug, Clone)]
-pub enum FillStyle<'a> {
+pub enum Style<'a> {
/// A solid color
Solid(Color),
/// A color gradient
Gradient(&'a Gradient),
}
-impl <'a> Into<Shader> for FillStyle<'a> {
+impl <'a> Into<Shader> for Style<'a> {
fn into(self) -> Shader {
match self {
- FillStyle::Solid(color) => Shader::Solid(color),
- FillStyle::Gradient(gradient) => gradient.clone().into()
+ Style::Solid(color) => Shader::Solid(color),
+ Style::Gradient(gradient) => gradient.clone().into()
}
}
}
diff --git a/graphics/src/widget/canvas/stroke.rs b/graphics/src/widget/canvas/stroke.rs
index ed82f189..7ce5ff1d 100644
--- a/graphics/src/widget/canvas/stroke.rs
+++ b/graphics/src/widget/canvas/stroke.rs
@@ -8,7 +8,7 @@ pub struct Stroke<'a> {
/// The color or gradient of the stroke.
///
/// By default, it is set to [`StrokeStyle::Solid`] `BLACK`.
- pub style: StrokeStyle<'a>,
+ pub style: Style<'a>,
/// The distance between the two edges of the stroke.
pub width: f32,
/// The shape to be used at the end of open subpaths when they are stroked.
@@ -24,7 +24,7 @@ impl<'a> Stroke<'a> {
/// Sets the color of the [`Stroke`].
pub fn with_color(self, color: Color) -> Self {
Stroke {
- style: StrokeStyle::Solid(color),
+ style: Style::Solid(color),
..self
}
}
@@ -48,7 +48,7 @@ impl<'a> Stroke<'a> {
impl<'a> Default for Stroke<'a> {
fn default() -> Self {
Stroke {
- style: StrokeStyle::Solid(Color::BLACK),
+ style: Style::Solid(Color::BLACK),
width: 1.0,
line_cap: LineCap::default(),
line_join: LineJoin::default(),
@@ -59,18 +59,18 @@ impl<'a> Default for Stroke<'a> {
/// The color or gradient of a [`Stroke`].
#[derive(Debug, Clone, Copy)]
-pub enum StrokeStyle<'a> {
+pub enum Style<'a> {
/// A solid color
Solid(Color),
/// A color gradient
Gradient(&'a Gradient),
}
-impl <'a> Into<Shader> for StrokeStyle<'a> {
+impl <'a> Into<Shader> for Style<'a> {
fn into(self) -> Shader {
match self {
- StrokeStyle::Solid(color) => Shader::Solid(color),
- StrokeStyle::Gradient(gradient) => gradient.clone().into()
+ Style::Solid(color) => Shader::Solid(color),
+ Style::Gradient(gradient) => gradient.clone().into()
}
}
}
diff --git a/wgpu/src/backend.rs b/wgpu/src/backend.rs
index fd688004..9295a491 100644
--- a/wgpu/src/backend.rs
+++ b/wgpu/src/backend.rs
@@ -132,7 +132,7 @@ impl Backend {
);
}
- if !layer.meshes.0.is_empty() {
+ if !layer.meshes.is_empty() {
let scaled = transformation
* Transformation::scale(scale_factor, scale_factor);
diff --git a/wgpu/src/buffers/buffer.rs b/wgpu/src/buffers/buffer.rs
index dae3b038..a44120d3 100644
--- a/wgpu/src/buffers/buffer.rs
+++ b/wgpu/src/buffers/buffer.rs
@@ -1,91 +1,124 @@
//! Utilities for static buffer operations.
+use bytemuck::{Pod, Zeroable};
+use std::marker::PhantomData;
+use std::mem;
+
+//128 triangles/indices
+const DEFAULT_STATIC_BUFFER_COUNT: wgpu::BufferAddress = 128;
/// A generic buffer struct useful for items which have no alignment requirements
/// (e.g. Vertex, Index buffers) and are set once and never changed until destroyed.
-///
-/// This buffer is mapped to the GPU on creation, so must be initialized with the correct capacity.
#[derive(Debug)]
-pub(crate) struct StaticBuffer {
- //stored sequentially per mesh iteration
+pub(crate) struct StaticBuffer<T> {
+ //stored sequentially per mesh iteration; refers to the offset index in the GPU buffer
offsets: Vec<wgpu::BufferAddress>,
+ label: &'static str,
+ usages: wgpu::BufferUsages,
gpu: wgpu::Buffer,
//the static size of the buffer
size: wgpu::BufferAddress,
+ _data: PhantomData<T>,
}
-impl StaticBuffer {
+impl<T: Pod + Zeroable> StaticBuffer<T> {
+ /// Initialize a new static buffer.
pub fn new(
device: &wgpu::Device,
label: &'static str,
- size: u64,
- usage: wgpu::BufferUsages,
- total_offsets: usize,
+ usages: wgpu::BufferUsages,
) -> Self {
+ let size = (mem::size_of::<T>() as u64) * DEFAULT_STATIC_BUFFER_COUNT;
+
Self {
- offsets: Vec::with_capacity(total_offsets),
- gpu: device.create_buffer(&wgpu::BufferDescriptor {
- label: Some(label),
- size,
- usage,
- mapped_at_creation: true,
- }),
+ offsets: Vec::new(),
+ label,
+ usages,
+ gpu: Self::gpu_buffer(device, label, size, usages),
size,
+ _data: Default::default(),
}
}
- /// Resolves pending write operations & unmaps buffer from host memory.
- pub fn flush(&self) {
- (&self.gpu).unmap();
+ fn gpu_buffer(
+ device: &wgpu::Device,
+ label: &'static str,
+ size: wgpu::BufferAddress,
+ usage: wgpu::BufferUsages,
+ ) -> wgpu::Buffer {
+ device.create_buffer(&wgpu::BufferDescriptor {
+ label: Some(label),
+ size,
+ usage,
+ mapped_at_creation: false,
+ })
}
- /// Returns whether or not the buffer needs to be recreated. This can happen whenever the mesh
- /// data is re-submitted.
- pub fn needs_recreate(&self, new_size: usize) -> bool {
- self.size != new_size as u64
- }
+ /// Returns whether or not the buffer needs to be recreated. This can happen whenever mesh data
+ /// changes & a redraw is requested.
+ pub fn recreate_if_needed(
+ &mut self,
+ device: &wgpu::Device,
+ new_count: usize,
+ ) -> bool {
+ let size =
+ wgpu::BufferAddress::from((mem::size_of::<T>() * new_count) as u64);
- /// Writes the current vertex data to the gpu buffer with a memcpy & stores its offset.
- pub fn write(&mut self, offset: u64, content: &[u8]) {
- //offset has to be divisible by 8 for alignment reasons
- let actual_offset = if offset % 8 != 0 {
- offset + 4
+ if self.size <= size {
+ self.offsets.clear();
+ self.size = size;
+ self.gpu = Self::gpu_buffer(device, self.label, size, self.usages);
+ true
} else {
- offset
- };
+ false
+ }
+ }
- let mut buffer = self
- .gpu
- .slice(actual_offset..(actual_offset + content.len() as u64))
- .get_mapped_range_mut();
- buffer.copy_from_slice(content);
- self.offsets.push(actual_offset);
+ /// Writes the current vertex data to the gpu buffer if it is currently writable with a memcpy &
+ /// stores its offset.
+ ///
+ /// This will return either the offset of the written bytes, or `None` if the GPU buffer is not
+ /// currently writable.
+ pub fn write(
+ &mut self,
+ device: &wgpu::Device,
+ staging_belt: &mut wgpu::util::StagingBelt,
+ encoder: &mut wgpu::CommandEncoder,
+ 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 as u64) {
+ //offset has to be divisible by 8 for alignment reasons
+ let actual_offset = if offset % 8 != 0 { offset + 4 } else { offset };
+
+ let mut buffer = staging_belt.write_buffer(
+ encoder,
+ &self.gpu,
+ actual_offset,
+ buffer_size,
+ device,
+ );
+
+ buffer.copy_from_slice(bytes);
+
+ self.offsets.push(actual_offset);
+ }
+
+ bytes_size
}
fn offset_at(&self, index: usize) -> &wgpu::BufferAddress {
self.offsets
.get(index)
- .expect(&format!("Offset index {} is not in range.", index))
+ .expect("Offset at index does not exist.")
}
/// Returns the slice calculated from the offset stored at the given index.
- /// e.g. to calculate the slice for the 2nd mesh in the layer, this would be the offset at index
+ /// e.g. to calculate the slice for the 2nd mesh in the layer, this would be the offset at index
/// 1 that we stored earlier when writing.
- pub fn slice_from_index<T>(
- &self,
- index: usize,
- ) -> wgpu::BufferSlice<'_> {
+ pub fn slice_from_index(&self, index: usize) -> wgpu::BufferSlice<'_> {
self.gpu.slice(self.offset_at(index)..)
}
}
-
-/// Returns true if the current buffer doesn't exist & needs to be created, or if it's too small
-/// for the new content.
-pub(crate) fn needs_recreate(
- buffer: &Option<StaticBuffer>,
- new_size: usize,
-) -> bool {
- match buffer {
- None => true,
- Some(buf) => buf.needs_recreate(new_size),
- }
-}
diff --git a/wgpu/src/buffers/dynamic_buffers.rs b/wgpu/src/buffers/dynamic_buffers.rs
index d81529ce..75cc202c 100644
--- a/wgpu/src/buffers/dynamic_buffers.rs
+++ b/wgpu/src/buffers/dynamic_buffers.rs
@@ -50,7 +50,6 @@ impl DynamicBufferType {
}
}
-//TODO think about making cpu & gpu buffers optional
pub(crate) struct DynamicBuffer<T: ShaderType> {
offsets: Vec<wgpu::DynamicOffset>,
cpu: DynamicBufferType,
@@ -183,7 +182,7 @@ impl<T: ShaderType + WriteInto> DynamicBuffer<T> {
let offset = self
.offsets
.get(index)
- .expect(&format!("Index {} not found in offsets.", index))
+ .expect("Index not found in offsets.")
.clone();
offset
diff --git a/wgpu/src/triangle.rs b/wgpu/src/triangle.rs
index f1770e9a..df5e3132 100644
--- a/wgpu/src/triangle.rs
+++ b/wgpu/src/triangle.rs
@@ -3,11 +3,11 @@ use crate::{settings, Transformation};
use core::fmt;
use std::fmt::Formatter;
-use iced_graphics::layer::Meshes;
+use iced_graphics::layer::{attribute_count_of, Mesh};
use iced_graphics::shader::Shader;
use iced_graphics::Size;
-use crate::buffers::buffer::{needs_recreate, StaticBuffer};
+use crate::buffers::buffer::StaticBuffer;
use crate::triangle::gradient::GradientPipeline;
use crate::triangle::solid::SolidPipeline;
pub use iced_graphics::triangle::{Mesh2D, Vertex2D};
@@ -20,10 +20,9 @@ mod solid;
#[derive(Debug)]
pub(crate) struct Pipeline {
blit: Option<msaa::Blit>,
- // these are optional so we don't allocate any memory to the GPU if
- // application has no triangle meshes.
- vertex_buffer: Option<StaticBuffer>,
- index_buffer: Option<StaticBuffer>,
+ vertex_buffer: StaticBuffer<Vertex2D>,
+ index_buffer: StaticBuffer<u32>,
+ index_strides: Vec<u32>,
pipelines: TrianglePipelines,
}
@@ -69,8 +68,17 @@ impl Pipeline {
) -> Pipeline {
Pipeline {
blit: antialiasing.map(|a| msaa::Blit::new(device, format, a)),
- vertex_buffer: None,
- index_buffer: None,
+ vertex_buffer: StaticBuffer::new(
+ device,
+ "iced_wgpu::triangle vertex buffer",
+ wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
+ ),
+ index_buffer: StaticBuffer::new(
+ device,
+ "iced_wgpu::triangle vertex buffer",
+ wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST,
+ ),
+ index_strides: Vec::new(),
pipelines: TrianglePipelines {
solid: SolidPipeline::new(device, format, antialiasing),
gradient: GradientPipeline::new(device, format, antialiasing),
@@ -88,177 +96,152 @@ impl Pipeline {
target_size: Size<u32>,
transformation: Transformation,
scale_factor: f32,
- meshes: &Meshes<'_>,
+ meshes: &[Mesh<'_>],
) {
- //count the total number of vertices & indices we need to handle
- let (total_vertices, total_indices) = meshes.attribute_count();
+ //count the total amount of vertices & indices we need to handle
+ let (total_vertices, total_indices) = attribute_count_of(meshes);
+
+ // Then we ensure the current attribute buffers are big enough, resizing if necessary
+ // with wgpu this means recreating the buffer.
+
+ //We are not currently using the return value of these functions as we have no system in
+ //place to calculate mesh diff, or to know whether or not that would be more performant for
+ //the majority of use cases. Therefore we will write GPU data every frame (for now).
+ let _ = self.vertex_buffer.recreate_if_needed(device, total_vertices);
+ let _ = self.index_buffer.recreate_if_needed(device, total_indices);
+
+ //prepare dynamic buffers & data store for writing
+ self.index_strides.clear();
+ self.pipelines.clear();
+
+ let mut vertex_offset = 0;
+ let mut index_offset = 0;
- //Only create buffers if they need to be re-sized or don't exist
- if needs_recreate(&self.vertex_buffer, total_vertices) {
- //mapped to GPU at creation with total vertices
- self.vertex_buffer = Some(StaticBuffer::new(
+ for mesh in meshes {
+ let transform = transformation
+ * Transformation::translate(mesh.origin.x, mesh.origin.y);
+
+ //write to both buffers
+ let new_vertex_offset = self.vertex_buffer.write(
device,
- "iced_wgpu::triangle vertex buffer",
- //TODO: a more reasonable default to prevent frequent resizing calls
- // before this was 10_000
- (std::mem::size_of::<Vertex2D>() * total_vertices) as u64,
- wgpu::BufferUsages::VERTEX,
- meshes.0.len(),
- ))
- }
+ staging_belt,
+ encoder,
+ vertex_offset,
+ &mesh.buffers.vertices,
+ );
- if needs_recreate(&self.index_buffer, total_indices) {
- //mapped to GPU at creation with total indices
- self.index_buffer = Some(StaticBuffer::new(
+ let new_index_offset = self.index_buffer.write(
device,
- "iced_wgpu::triangle index buffer",
- //TODO: a more reasonable default to prevent frequent resizing calls
- // before this was 10_000
- (std::mem::size_of::<Vertex2D>() * total_indices) as u64,
- wgpu::BufferUsages::INDEX,
- meshes.0.len(),
- ));
- }
+ staging_belt,
+ encoder,
+ index_offset,
+ &mesh.buffers.indices,
+ );
- if let Some(vertex_buffer) = &mut self.vertex_buffer {
- if let Some(index_buffer) = &mut self.index_buffer {
- let mut offset_v = 0;
- let mut offset_i = 0;
- //TODO: store this more efficiently
- let mut indices_lengths = Vec::with_capacity(meshes.0.len());
-
- //iterate through meshes to write all attribute data
- for mesh in meshes.0.iter() {
- let transform = transformation
- * Transformation::translate(
- mesh.origin.x,
- mesh.origin.y,
- );
+ vertex_offset = vertex_offset + new_vertex_offset;
+ index_offset = index_offset + new_index_offset;
- let vertices = bytemuck::cast_slice(&mesh.buffers.vertices);
- let indices = bytemuck::cast_slice(&mesh.buffers.indices);
-
- //TODO: it's (probably) more efficient to reduce this write command and
- // iterate first and then upload
- vertex_buffer.write(offset_v, vertices);
- index_buffer.write(offset_i, indices);
-
- offset_v += vertices.len() as u64;
- offset_i += indices.len() as u64;
- indices_lengths.push(mesh.buffers.indices.len());
-
- match mesh.shader {
- Shader::Solid(color) => {
- self.pipelines.solid.push(transform, color);
- }
- Shader::Gradient(gradient) => {
- self.pipelines.gradient.push(transform, gradient);
- }
- }
+ self.index_strides.push(mesh.buffers.indices.len() as u32);
+
+ //push uniform data to CPU buffers
+ match mesh.shader {
+ Shader::Solid(color) => {
+ self.pipelines.solid.push(transform, color);
}
+ Shader::Gradient(gradient) => {
+ self.pipelines.gradient.push(transform, gradient);
+ }
+ }
+ }
- //done writing to gpu buffer, unmap from host memory since we don't need it
- //anymore
- vertex_buffer.flush();
- index_buffer.flush();
-
- //resize & memcpy uniforms from CPU buffers to GPU buffers for all pipelines
- self.pipelines.write(device, staging_belt, encoder);
-
- //configure the render pass now that the data is uploaded to the GPU
- {
- //configure antialiasing pass
- let (attachment, resolve_target, load) =
- if let Some(blit) = &mut self.blit {
- let (attachment, resolve_target) = blit.targets(
- device,
- target_size.width,
- target_size.height,
- );
-
- (
- attachment,
- Some(resolve_target),
- wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
- )
- } else {
- (target, None, wgpu::LoadOp::Load)
- };
-
- let mut render_pass = encoder.begin_render_pass(
- &wgpu::RenderPassDescriptor {
- label: Some("iced_wgpu::triangle render pass"),
- color_attachments: &[Some(
- wgpu::RenderPassColorAttachment {
- view: attachment,
- resolve_target,
- ops: wgpu::Operations { load, store: true },
- },
- )],
- depth_stencil_attachment: None,
+ //write uniform data to GPU
+ self.pipelines.write(device, staging_belt, encoder);
+
+ //configure the render pass now that the data is uploaded to the GPU
+ {
+ //configure antialiasing pass
+ let (attachment, resolve_target, load) = if let Some(blit) =
+ &mut self.blit
+ {
+ let (attachment, resolve_target) =
+ blit.targets(device, target_size.width, target_size.height);
+
+ (
+ attachment,
+ Some(resolve_target),
+ wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
+ )
+ } else {
+ (target, None, wgpu::LoadOp::Load)
+ };
+
+ let mut render_pass =
+ encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
+ label: Some("iced_wgpu::triangle render pass"),
+ color_attachments: &[Some(
+ wgpu::RenderPassColorAttachment {
+ view: attachment,
+ resolve_target,
+ ops: wgpu::Operations { load, store: true },
},
- );
-
- //TODO: do this a better way; store it in the respective pipelines perhaps
- // to be more readable
- let mut num_solids = 0;
- let mut num_gradients = 0;
-
- //TODO: try to avoid this extra iteration if possible
- for index in 0..meshes.0.len() {
- let clip_bounds =
- (meshes.0[index].clip_bounds * scale_factor).snap();
-
- render_pass.set_scissor_rect(
- clip_bounds.x,
- clip_bounds.y,
- clip_bounds.width,
- clip_bounds.height,
- );
-
- match meshes.0[index].shader {
- Shader::Solid(_) => {
- self.pipelines.solid.configure_render_pass(
- &mut render_pass,
- num_solids,
- );
- num_solids += 1;
- }
- Shader::Gradient(_) => {
- self.pipelines.gradient.configure_render_pass(
- &mut render_pass,
- num_gradients,
- );
- num_gradients += 1;
- }
- }
-
- render_pass.set_index_buffer(
- index_buffer.slice_from_index::<u32>(index),
- wgpu::IndexFormat::Uint32,
+ )],
+ depth_stencil_attachment: None,
+ });
+
+ //TODO I can't figure out a clean way to encapsulate these into their appropriate
+ // structs without displeasing the borrow checker due to the lifetime requirements of
+ // render_pass & using a mutable reference to each pipeline in a loop...
+ let mut num_solids = 0;
+ let mut num_gradients = 0;
+
+ 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.shader {
+ Shader::Solid(_) => {
+ self.pipelines.solid.configure_render_pass(
+ &mut render_pass,
+ num_solids,
);
-
- render_pass.set_vertex_buffer(
- 0,
- vertex_buffer.slice_from_index::<Vertex2D>(index),
- );
-
- render_pass.draw_indexed(
- 0..(indices_lengths[index] as u32),
- 0,
- 0..1,
+ num_solids += 1;
+ }
+ Shader::Gradient(_) => {
+ self.pipelines.gradient.configure_render_pass(
+ &mut render_pass,
+ num_gradients,
);
+ num_gradients += 1;
}
- }
+ };
+
+ render_pass.set_vertex_buffer(
+ 0,
+ self.vertex_buffer.slice_from_index(index),
+ );
+
+ render_pass.set_index_buffer(
+ self.index_buffer.slice_from_index(index),
+ wgpu::IndexFormat::Uint32,
+ );
+
+ render_pass.draw_indexed(
+ 0..(self.index_strides[index] as u32),
+ 0,
+ 0..1,
+ );
}
}
if let Some(blit) = &mut self.blit {
blit.draw(encoder, target);
}
-
- //cleanup
- self.pipelines.clear();
}
}
diff --git a/wgpu/src/triangle/gradient.rs b/wgpu/src/triangle/gradient.rs
index 471b204c..15b6b7e0 100644
--- a/wgpu/src/triangle/gradient.rs
+++ b/wgpu/src/triangle/gradient.rs
@@ -253,13 +253,13 @@ impl GradientPipeline {
pub fn configure_render_pass<'a>(
&'a self,
render_pass: &mut wgpu::RenderPass<'a>,
- index: usize,
+ count: usize,
) {
render_pass.set_pipeline(&self.pipeline);
render_pass.set_bind_group(
0,
&self.bind_group,
- &[self.uniform_buffer.offset_at_index(index)],
- );
+ &[self.uniform_buffer.offset_at_index(count)],
+ )
}
}
diff --git a/wgpu/src/triangle/solid.rs b/wgpu/src/triangle/solid.rs
index a3cbd72b..e7e9098a 100644
--- a/wgpu/src/triangle/solid.rs
+++ b/wgpu/src/triangle/solid.rs
@@ -8,15 +8,15 @@ use encase::ShaderType;
use glam::Vec4;
use iced_graphics::Transformation;
-pub(super) struct SolidPipeline {
+pub struct SolidPipeline {
pipeline: wgpu::RenderPipeline,
- pub(super) buffer: DynamicBuffer<SolidUniforms>,
+ pub(crate) buffer: DynamicBuffer<SolidUniforms>,
bind_group_layout: wgpu::BindGroupLayout,
bind_group: wgpu::BindGroup,
}
#[derive(Debug, Clone, Copy, ShaderType)]
-pub(super) struct SolidUniforms {
+pub struct SolidUniforms {
transform: glam::Mat4,
color: Vec4,
}
@@ -156,14 +156,13 @@ impl SolidPipeline {
pub fn configure_render_pass<'a>(
&'a self,
render_pass: &mut wgpu::RenderPass<'a>,
- index: usize,
+ count: usize,
) {
render_pass.set_pipeline(&self.pipeline);
-
render_pass.set_bind_group(
0,
&self.bind_group,
- &[self.buffer.offset_at_index(index)],
- );
+ &[self.buffer.offset_at_index(count)],
+ )
}
-} \ No newline at end of file
+}