From 3f467d121229142177ef1b2f417fe87c7bf7fdf2 Mon Sep 17 00:00:00 2001
From: Jim Eckerlein <jim.eckerlein@icloud.com>
Date: Sun, 24 Sep 2023 15:10:19 +0200
Subject: Compute vertex position in shader

---
 wgpu/src/quad.rs                   | 61 ------------------------------------
 wgpu/src/quad/gradient.rs          | 64 +++++++++++++++++---------------------
 wgpu/src/quad/solid.rs             | 47 ++++++++++++----------------
 wgpu/src/shader/quad.wgsl          |  8 +++++
 wgpu/src/shader/quad/gradient.wgsl |  4 +--
 wgpu/src/shader/quad/solid.wgsl    |  4 +--
 6 files changed, 60 insertions(+), 128 deletions(-)

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;
@@ -311,43 +287,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 {
diff --git a/wgpu/src/quad/gradient.rs b/wgpu/src/quad/gradient.rs
index a8e83d01..312408b7 100644
--- a/wgpu/src/quad/gradient.rs
+++ b/wgpu/src/quad/gradient.rs
@@ -106,36 +106,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
+                            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
+                        ),
+                    }],
                 },
                 fragment: Some(wgpu::FragmentState {
                     module: &shader,
@@ -171,12 +167,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..bab7367d 100644
--- a/wgpu/src/quad/solid.rs
+++ b/wgpu/src/quad/solid.rs
@@ -87,27 +87,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
+                            1 => Float32x4,
+                            // Position
+                            2 => Float32x2,
+                            // Size
+                            3 => Float32x2,
+                            // Border color
+                            4 => Float32x4,
+                            // Border radius
+                            5 => Float32x4,
+                            // Border width
+                            6 => Float32,
+                        ),
+                    }],
                 },
                 fragment: Some(wgpu::FragmentState {
                     module: &shader,
@@ -143,12 +140,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/quad.wgsl b/wgpu/src/shader/quad.wgsl
index f919cfe2..555e81bb 100644
--- a/wgpu/src/shader/quad.wgsl
+++ b/wgpu/src/shader/quad.wgsl
@@ -37,3 +37,11 @@ fn select_border_radius(radi: vec4<f32>, position: vec2<f32>, center: vec2<f32>)
     rx = select(rx, ry, position.y > center.y);
     return rx;
 }
+
+// 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) % 6u < 3u);
+}
diff --git a/wgpu/src/shader/quad/gradient.wgsl b/wgpu/src/shader/quad/gradient.wgsl
index 0754e97f..36cae61c 100644
--- a/wgpu/src/shader/quad/gradient.wgsl
+++ b/wgpu/src/shader/quad/gradient.wgsl
@@ -1,5 +1,5 @@
 struct GradientVertexInput {
-    @location(0) v_pos: vec2<f32>,
+    @builtin(vertex_index) vertex_index: u32,
     @location(1) @interpolate(flat) colors_1: vec4<u32>,
     @location(2) @interpolate(flat) colors_2: vec4<u32>,
     @location(3) @interpolate(flat) colors_3: vec4<u32>,
@@ -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..5fc5b13a 100644
--- a/wgpu/src/shader/quad/solid.wgsl
+++ b/wgpu/src/shader/quad/solid.wgsl
@@ -1,5 +1,5 @@
 struct SolidVertexInput {
-    @location(0) v_pos: vec2<f32>,
+    @builtin(vertex_index) vertex_index: u32,
     @location(1) color: vec4<f32>,
     @location(2) pos: vec2<f32>,
     @location(3) scale: vec2<f32>,
@@ -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;
-- 
cgit