summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón <hector@hecrj.dev>2024-01-19 20:54:09 +0100
committerLibravatar GitHub <noreply@github.com>2024-01-19 20:54:09 +0100
commitb3e3f6e3c9fc6879e6681810f54d7eaa7c0f3d30 (patch)
treeef1a846a756fadce7df07732538192ee4f4ce6cf
parent7ae7fcb89855002519bab752fd3686106ce448db (diff)
parent0c7f6e4b34391c709aa4c333c4a9cc10e607f6c4 (diff)
downloadiced-b3e3f6e3c9fc6879e6681810f54d7eaa7c0f3d30.tar.gz
iced-b3e3f6e3c9fc6879e6681810f54d7eaa7c0f3d30.tar.bz2
iced-b3e3f6e3c9fc6879e6681810f54d7eaa7c0f3d30.zip
Merge pull request #2099 from jim-ec/master
Compute vertex positions in the shader
-rw-r--r--wgpu/src/image.rs100
-rw-r--r--wgpu/src/quad.rs61
-rw-r--r--wgpu/src/quad/gradient.rs68
-rw-r--r--wgpu/src/quad/solid.rs49
-rw-r--r--wgpu/src/shader/image.wgsl18
-rw-r--r--wgpu/src/shader/quad/gradient.wgsl24
-rw-r--r--wgpu/src/shader/quad/solid.wgsl16
-rw-r--r--wgpu/src/shader/vertex.wgsl7
8 files changed, 114 insertions, 229 deletions
diff --git a/wgpu/src/image.rs b/wgpu/src/image.rs
index b78802c7..1e5d3ee0 100644
--- a/wgpu/src/image.rs
+++ b/wgpu/src/image.rs
@@ -35,8 +35,6 @@ pub struct Pipeline {
vector_cache: RefCell<vector::Cache>,
pipeline: wgpu::RenderPipeline,
- vertices: wgpu::Buffer,
- indices: wgpu::Buffer,
nearest_sampler: wgpu::Sampler,
linear_sampler: wgpu::Sampler,
texture: wgpu::BindGroup,
@@ -172,20 +170,14 @@ impl Data {
fn render<'a>(&'a self, render_pass: &mut wgpu::RenderPass<'a>) {
render_pass.set_bind_group(0, &self.constants, &[]);
- render_pass.set_vertex_buffer(1, self.instances.slice(..));
+ render_pass.set_vertex_buffer(0, self.instances.slice(..));
- render_pass.draw_indexed(
- 0..QUAD_INDICES.len() as u32,
- 0,
- 0..self.instance_count as u32,
- );
+ render_pass.draw(0..6, 0..self.instance_count as u32);
}
}
impl Pipeline {
pub fn new(device: &wgpu::Device, format: wgpu::TextureFormat) -> Self {
- use wgpu::util::DeviceExt;
-
let nearest_sampler = device.create_sampler(&wgpu::SamplerDescriptor {
address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge,
@@ -261,7 +253,11 @@ impl Pipeline {
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"),
+ concat!(
+ include_str!("shader/vertex.wgsl"),
+ "\n",
+ include_str!("shader/image.wgsl"),
+ ),
)),
});
@@ -272,28 +268,22 @@ impl Pipeline {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
- buffers: &[
- wgpu::VertexBufferLayout {
- array_stride: mem::size_of::<Vertex>() as u64,
- step_mode: wgpu::VertexStepMode::Vertex,
- attributes: &[wgpu::VertexAttribute {
- shader_location: 0,
- format: wgpu::VertexFormat::Float32x2,
- offset: 0,
- }],
- },
- wgpu::VertexBufferLayout {
- array_stride: mem::size_of::<Instance>() as u64,
- step_mode: wgpu::VertexStepMode::Instance,
- attributes: &wgpu::vertex_attr_array!(
- 1 => Float32x2,
- 2 => Float32x2,
- 3 => Float32x2,
- 4 => Float32x2,
- 5 => Sint32,
- ),
- },
- ],
+ buffers: &[wgpu::VertexBufferLayout {
+ array_stride: mem::size_of::<Instance>() as u64,
+ step_mode: wgpu::VertexStepMode::Instance,
+ attributes: &wgpu::vertex_attr_array!(
+ // Position
+ 0 => Float32x2,
+ // Scale
+ 1 => Float32x2,
+ // Atlas position
+ 2 => Float32x2,
+ // Atlas scale
+ 3 => Float32x2,
+ // Layer
+ 4 => Sint32,
+ ),
+ }],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
@@ -329,20 +319,6 @@ impl Pipeline {
multiview: None,
});
- let vertices =
- device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
- label: Some("iced_wgpu::image vertex buffer"),
- contents: bytemuck::cast_slice(&QUAD_VERTICES),
- 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::BufferUsages::INDEX,
- });
-
let texture_atlas = Atlas::new(device);
let texture = device.create_bind_group(&wgpu::BindGroupDescriptor {
@@ -364,8 +340,6 @@ impl Pipeline {
vector_cache: RefCell::new(vector::Cache::default()),
pipeline,
- vertices,
- indices,
nearest_sampler,
linear_sampler,
texture,
@@ -542,11 +516,6 @@ impl Pipeline {
);
render_pass.set_bind_group(1, &self.texture, &[]);
- render_pass.set_index_buffer(
- self.indices.slice(..),
- wgpu::IndexFormat::Uint16,
- );
- render_pass.set_vertex_buffer(0, self.vertices.slice(..));
layer.render(render_pass);
}
@@ -564,29 +533,6 @@ impl Pipeline {
}
#[repr(C)]
-#[derive(Clone, Copy, Zeroable, Pod)]
-pub struct Vertex {
- _position: [f32; 2],
-}
-
-const QUAD_INDICES: [u16; 6] = [0, 1, 2, 0, 2, 3];
-
-const QUAD_VERTICES: [Vertex; 4] = [
- Vertex {
- _position: [0.0, 0.0],
- },
- Vertex {
- _position: [1.0, 0.0],
- },
- Vertex {
- _position: [1.0, 1.0],
- },
- Vertex {
- _position: [0.0, 1.0],
- },
-];
-
-#[repr(C)]
#[derive(Debug, Clone, Copy, Zeroable, Pod)]
struct Instance {
_position: [f32; 2],
diff --git a/wgpu/src/quad.rs b/wgpu/src/quad.rs
index 37d0c623..4bcf9a66 100644
--- a/wgpu/src/quad.rs
+++ b/wgpu/src/quad.rs
@@ -9,7 +9,6 @@ use crate::graphics::color;
use crate::graphics::{self, Transformation};
use bytemuck::{Pod, Zeroable};
-use wgpu::util::DeviceExt;
use std::mem;
@@ -23,8 +22,6 @@ pub struct Pipeline {
solid: solid::Pipeline,
gradient: gradient::Pipeline,
constant_layout: wgpu::BindGroupLayout,
- vertices: wgpu::Buffer,
- indices: wgpu::Buffer,
layers: Vec<Layer>,
prepare_layer: usize,
}
@@ -48,23 +45,7 @@ impl Pipeline {
}],
});
- let vertices =
- device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
- label: Some("iced_wgpu::quad vertex buffer"),
- contents: bytemuck::cast_slice(&VERTICES),
- usage: wgpu::BufferUsages::VERTEX,
- });
-
- let indices =
- device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
- label: Some("iced_wgpu::quad index buffer"),
- contents: bytemuck::cast_slice(&INDICES),
- usage: wgpu::BufferUsages::INDEX,
- });
-
Self {
- vertices,
- indices,
solid: solid::Pipeline::new(device, format, &constant_layout),
gradient: gradient::Pipeline::new(device, format, &constant_layout),
layers: Vec::new(),
@@ -105,11 +86,6 @@ impl Pipeline {
bounds.width,
bounds.height,
);
- render_pass.set_index_buffer(
- self.indices.slice(..),
- wgpu::IndexFormat::Uint16,
- );
- render_pass.set_vertex_buffer(0, self.vertices.slice(..));
let mut solid_offset = 0;
let mut gradient_offset = 0;
@@ -312,43 +288,6 @@ fn color_target_state(
}
#[repr(C)]
-#[derive(Clone, Copy, bytemuck::Zeroable, bytemuck::Pod)]
-pub struct Vertex {
- _position: [f32; 2],
-}
-
-impl Vertex {
- fn buffer_layout<'a>() -> wgpu::VertexBufferLayout<'a> {
- wgpu::VertexBufferLayout {
- array_stride: mem::size_of::<Self>() as u64,
- step_mode: wgpu::VertexStepMode::Vertex,
- attributes: &[wgpu::VertexAttribute {
- shader_location: 0,
- format: wgpu::VertexFormat::Float32x2,
- offset: 0,
- }],
- }
- }
-}
-
-const INDICES: [u16; 6] = [0, 1, 2, 0, 2, 3];
-
-const VERTICES: [Vertex; 4] = [
- Vertex {
- _position: [0.0, 0.0],
- },
- Vertex {
- _position: [1.0, 0.0],
- },
- Vertex {
- _position: [1.0, 1.0],
- },
- Vertex {
- _position: [0.0, 1.0],
- },
-];
-
-#[repr(C)]
#[derive(Debug, Clone, Copy, bytemuck::Zeroable, bytemuck::Pod)]
struct Uniforms {
transform: [f32; 16],
diff --git a/wgpu/src/quad/gradient.rs b/wgpu/src/quad/gradient.rs
index a8e83d01..60b170cc 100644
--- a/wgpu/src/quad/gradient.rs
+++ b/wgpu/src/quad/gradient.rs
@@ -83,6 +83,8 @@ impl Pipeline {
concat!(
include_str!("../shader/quad.wgsl"),
"\n",
+ include_str!("../shader/vertex.wgsl"),
+ "\n",
include_str!("../shader/quad/gradient.wgsl"),
"\n",
include_str!("../shader/color/oklab.wgsl")
@@ -91,6 +93,8 @@ impl Pipeline {
concat!(
include_str!("../shader/quad.wgsl"),
"\n",
+ include_str!("../shader/vertex.wgsl"),
+ "\n",
include_str!("../shader/quad/gradient.wgsl"),
"\n",
include_str!("../shader/color/linear_rgb.wgsl")
@@ -106,36 +110,32 @@ impl Pipeline {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "gradient_vs_main",
- buffers: &[
- quad::Vertex::buffer_layout(),
- wgpu::VertexBufferLayout {
- array_stride: std::mem::size_of::<Gradient>()
- as u64,
- step_mode: wgpu::VertexStepMode::Instance,
- attributes: &wgpu::vertex_attr_array!(
- // Colors 1-2
- 1 => Uint32x4,
- // Colors 3-4
- 2 => Uint32x4,
- // Colors 5-6
- 3 => Uint32x4,
- // Colors 7-8
- 4 => Uint32x4,
- // Offsets 1-8
- 5 => Uint32x4,
- // Direction
- 6 => Float32x4,
- // Position & Scale
- 7 => Float32x4,
- // Border color
- 8 => Float32x4,
- // Border radius
- 9 => Float32x4,
- // Border width
- 10 => Float32
- ),
- },
- ],
+ buffers: &[wgpu::VertexBufferLayout {
+ array_stride: std::mem::size_of::<Gradient>() as u64,
+ step_mode: wgpu::VertexStepMode::Instance,
+ attributes: &wgpu::vertex_attr_array!(
+ // Colors 1-2
+ 0 => Uint32x4,
+ // Colors 3-4
+ 1 => Uint32x4,
+ // Colors 5-6
+ 2 => Uint32x4,
+ // Colors 7-8
+ 3 => Uint32x4,
+ // Offsets 1-8
+ 4 => Uint32x4,
+ // Direction
+ 5 => Float32x4,
+ // Position & Scale
+ 6 => Float32x4,
+ // Border color
+ 7 => Float32x4,
+ // Border radius
+ 8 => Float32x4,
+ // Border width
+ 9 => Float32
+ ),
+ }],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
@@ -171,12 +171,8 @@ impl Pipeline {
render_pass.set_pipeline(&self.pipeline);
render_pass.set_bind_group(0, constants, &[]);
- render_pass.set_vertex_buffer(1, layer.instances.slice(..));
+ render_pass.set_vertex_buffer(0, layer.instances.slice(..));
- render_pass.draw_indexed(
- 0..quad::INDICES.len() as u32,
- 0,
- range.start as u32..range.end as u32,
- );
+ render_pass.draw(0..6, range.start as u32..range.end as u32);
}
}
diff --git a/wgpu/src/quad/solid.rs b/wgpu/src/quad/solid.rs
index 9bc6b466..90e7f98e 100644
--- a/wgpu/src/quad/solid.rs
+++ b/wgpu/src/quad/solid.rs
@@ -75,6 +75,8 @@ impl Pipeline {
concat!(
include_str!("../shader/quad.wgsl"),
"\n",
+ include_str!("../shader/vertex.wgsl"),
+ "\n",
include_str!("../shader/quad/solid.wgsl"),
),
)),
@@ -87,27 +89,24 @@ impl Pipeline {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "solid_vs_main",
- buffers: &[
- quad::Vertex::buffer_layout(),
- wgpu::VertexBufferLayout {
- array_stride: std::mem::size_of::<Solid>() as u64,
- step_mode: wgpu::VertexStepMode::Instance,
- attributes: &wgpu::vertex_attr_array!(
- // Color
- 1 => Float32x4,
- // Position
- 2 => Float32x2,
- // Size
- 3 => Float32x2,
- // Border color
- 4 => Float32x4,
- // Border radius
- 5 => Float32x4,
- // Border width
- 6 => Float32,
- ),
- },
- ],
+ buffers: &[wgpu::VertexBufferLayout {
+ array_stride: std::mem::size_of::<Solid>() as u64,
+ step_mode: wgpu::VertexStepMode::Instance,
+ attributes: &wgpu::vertex_attr_array!(
+ // Color
+ 0 => Float32x4,
+ // Position
+ 1 => Float32x2,
+ // Size
+ 2 => Float32x2,
+ // Border color
+ 3 => Float32x4,
+ // Border radius
+ 4 => Float32x4,
+ // Border width
+ 5 => Float32,
+ ),
+ }],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
@@ -143,12 +142,8 @@ impl Pipeline {
render_pass.set_pipeline(&self.pipeline);
render_pass.set_bind_group(0, constants, &[]);
- render_pass.set_vertex_buffer(1, layer.instances.slice(..));
+ render_pass.set_vertex_buffer(0, layer.instances.slice(..));
- render_pass.draw_indexed(
- 0..quad::INDICES.len() as u32,
- 0,
- range.start as u32..range.end as u32,
- );
+ render_pass.draw(0..6, range.start as u32..range.end as u32);
}
}
diff --git a/wgpu/src/shader/image.wgsl b/wgpu/src/shader/image.wgsl
index 5e22cdf4..7b2e5238 100644
--- a/wgpu/src/shader/image.wgsl
+++ b/wgpu/src/shader/image.wgsl
@@ -7,12 +7,12 @@ struct Globals {
@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,
+ @builtin(vertex_index) vertex_index: u32,
+ @location(0) pos: vec2<f32>,
+ @location(1) scale: vec2<f32>,
+ @location(2) atlas_pos: vec2<f32>,
+ @location(3) atlas_scale: vec2<f32>,
+ @location(4) layer: i32,
}
struct VertexOutput {
@@ -25,7 +25,9 @@ struct VertexOutput {
fn vs_main(input: VertexInput) -> VertexOutput {
var out: VertexOutput;
- out.uv = vec2<f32>(input.v_pos * input.atlas_scale + input.atlas_pos);
+ let v_pos = vertex_position(input.vertex_index);
+
+ out.uv = vec2<f32>(v_pos * input.atlas_scale + input.atlas_pos);
out.layer = f32(input.layer);
var transform: mat4x4<f32> = mat4x4<f32>(
@@ -35,7 +37,7 @@ fn vs_main(input: VertexInput) -> VertexOutput {
vec4<f32>(input.pos, 0.0, 1.0)
);
- out.position = globals.transform * transform * vec4<f32>(input.v_pos, 0.0, 1.0);
+ out.position = globals.transform * transform * vec4<f32>(v_pos, 0.0, 1.0);
return out;
}
diff --git a/wgpu/src/shader/quad/gradient.wgsl b/wgpu/src/shader/quad/gradient.wgsl
index 0754e97f..4ad2fea8 100644
--- a/wgpu/src/shader/quad/gradient.wgsl
+++ b/wgpu/src/shader/quad/gradient.wgsl
@@ -1,15 +1,15 @@
struct GradientVertexInput {
- @location(0) v_pos: vec2<f32>,
- @location(1) @interpolate(flat) colors_1: vec4<u32>,
- @location(2) @interpolate(flat) colors_2: vec4<u32>,
- @location(3) @interpolate(flat) colors_3: vec4<u32>,
- @location(4) @interpolate(flat) colors_4: vec4<u32>,
- @location(5) @interpolate(flat) offsets: vec4<u32>,
- @location(6) direction: vec4<f32>,
- @location(7) position_and_scale: vec4<f32>,
- @location(8) border_color: vec4<f32>,
- @location(9) border_radius: vec4<f32>,
- @location(10) border_width: f32,
+ @builtin(vertex_index) vertex_index: u32,
+ @location(0) @interpolate(flat) colors_1: vec4<u32>,
+ @location(1) @interpolate(flat) colors_2: vec4<u32>,
+ @location(2) @interpolate(flat) colors_3: vec4<u32>,
+ @location(3) @interpolate(flat) colors_4: vec4<u32>,
+ @location(4) @interpolate(flat) offsets: vec4<u32>,
+ @location(5) direction: vec4<f32>,
+ @location(6) position_and_scale: vec4<f32>,
+ @location(7) border_color: vec4<f32>,
+ @location(8) border_radius: vec4<f32>,
+ @location(9) border_width: f32,
}
struct GradientVertexOutput {
@@ -48,7 +48,7 @@ fn gradient_vs_main(input: GradientVertexInput) -> GradientVertexOutput {
vec4<f32>(pos - vec2<f32>(0.5, 0.5), 0.0, 1.0)
);
- out.position = globals.transform * transform * vec4<f32>(input.v_pos, 0.0, 1.0);
+ out.position = globals.transform * transform * vec4<f32>(vertex_position(input.vertex_index), 0.0, 1.0);
out.colors_1 = input.colors_1;
out.colors_2 = input.colors_2;
out.colors_3 = input.colors_3;
diff --git a/wgpu/src/shader/quad/solid.wgsl b/wgpu/src/shader/quad/solid.wgsl
index ebd6d877..f84dd7ab 100644
--- a/wgpu/src/shader/quad/solid.wgsl
+++ b/wgpu/src/shader/quad/solid.wgsl
@@ -1,11 +1,11 @@
struct SolidVertexInput {
- @location(0) v_pos: vec2<f32>,
- @location(1) color: vec4<f32>,
- @location(2) pos: vec2<f32>,
- @location(3) scale: vec2<f32>,
- @location(4) border_color: vec4<f32>,
- @location(5) border_radius: vec4<f32>,
- @location(6) border_width: f32,
+ @builtin(vertex_index) vertex_index: u32,
+ @location(0) color: vec4<f32>,
+ @location(1) pos: vec2<f32>,
+ @location(2) scale: vec2<f32>,
+ @location(3) border_color: vec4<f32>,
+ @location(4) border_radius: vec4<f32>,
+ @location(5) border_width: f32,
}
struct SolidVertexOutput {
@@ -40,7 +40,7 @@ fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput {
vec4<f32>(pos - vec2<f32>(0.5, 0.5), 0.0, 1.0)
);
- out.position = globals.transform * transform * vec4<f32>(input.v_pos, 0.0, 1.0);
+ out.position = globals.transform * transform * vec4<f32>(vertex_position(input.vertex_index), 0.0, 1.0);
out.color = input.color;
out.border_color = input.border_color;
out.pos = pos;
diff --git a/wgpu/src/shader/vertex.wgsl b/wgpu/src/shader/vertex.wgsl
new file mode 100644
index 00000000..e6af6fc0
--- /dev/null
+++ b/wgpu/src/shader/vertex.wgsl
@@ -0,0 +1,7 @@
+// Compute the normalized quad coordinates based on the vertex index.
+fn vertex_position(vertex_index: u32) -> vec2<f32> {
+ // #: 0 1 2 3 4 5
+ // x: 1 1 0 0 0 1
+ // y: 1 0 0 0 1 1
+ return vec2<f32>((vec2(1u, 2u) + vertex_index) % vec2(6u) < vec2(3u));
+}