From f7ce7244d017ec16545a3e52b6e7cf634bbffd4a Mon Sep 17 00:00:00 2001
From: shan <shankern@protonmail.com>
Date: Wed, 5 Oct 2022 11:32:59 -0700
Subject: Adjusted gradient uniforms to be more tightly packed.

---
 wgpu/src/shader/triangle_gradient.wgsl | 29 ++++++++++++++-----------
 wgpu/src/triangle/gradient.rs          | 39 +++++++++++++++++-----------------
 2 files changed, 37 insertions(+), 31 deletions(-)

(limited to 'wgpu')

diff --git a/wgpu/src/shader/triangle_gradient.wgsl b/wgpu/src/shader/triangle_gradient.wgsl
index cb35b61c..df7158af 100644
--- a/wgpu/src/shader/triangle_gradient.wgsl
+++ b/wgpu/src/shader/triangle_gradient.wgsl
@@ -1,10 +1,10 @@
 // uniforms
 struct GradientUniforms {
     transform: mat4x4<f32>,
-    @size(16) start: vec2<f32>,
-    @size(16) end: vec2<f32>,
-    @size(16) start_stop: i32,
-    @size(16) end_stop: i32,
+    //xy = start, wz = end
+    position: vec4<f32>,
+    //x = start, y = end, zw = padding
+    stop_range: vec4<i32>,
 }
 
 struct Stop {
@@ -13,7 +13,7 @@ struct Stop {
 };
 
 @group(0) @binding(0)
-var<uniform> gradient_uniforms: GradientUniforms;
+var<uniform> uniforms: GradientUniforms;
 
 @group(0) @binding(1)
 var<storage, read> color_stops: array<Stop>;
@@ -26,7 +26,7 @@ struct VertexOutput {
 @vertex
 fn vs_main(@location(0) input: vec2<f32>) -> VertexOutput {
     var output: VertexOutput;
-    output.position = gradient_uniforms.transform * vec4<f32>(input.xy, 0.0, 1.0);
+    output.position = uniforms.transform * vec4<f32>(input.xy, 0.0, 1.0);
     output.raw_position = input;
 
     return output;
@@ -34,13 +34,18 @@ fn vs_main(@location(0) input: vec2<f32>) -> VertexOutput {
 
 @fragment
 fn fs_gradient(input: VertexOutput) -> @location(0) vec4<f32> {
-    let v1 = gradient_uniforms.end - gradient_uniforms.start;
-    let v2 = input.raw_position.xy - gradient_uniforms.start;
+    let start = uniforms.position.xy;
+    let end = uniforms.position.zw;
+    let start_stop = uniforms.stop_range.x;
+    let end_stop = uniforms.stop_range.y;
+
+    let v1 = end - start;
+    let v2 = input.raw_position.xy - start;
     let unit = normalize(v1);
     let offset = dot(unit, v2) / length(v1);
 
-    let min_stop = color_stops[gradient_uniforms.start_stop];
-    let max_stop = color_stops[gradient_uniforms.end_stop];
+    let min_stop = color_stops[start_stop];
+    let max_stop = color_stops[end_stop];
 
     var color: vec4<f32>;
 
@@ -51,8 +56,8 @@ fn fs_gradient(input: VertexOutput) -> @location(0) vec4<f32> {
     } else {
         var min = min_stop;
         var max = max_stop;
-        var min_index = gradient_uniforms.start_stop;
-        var max_index = gradient_uniforms.end_stop;
+        var min_index = start_stop;
+        var max_index = end_stop;
 
         loop {
             if (min_index >= max_index - 1) {
diff --git a/wgpu/src/triangle/gradient.rs b/wgpu/src/triangle/gradient.rs
index e8c6d7db..c647e6af 100644
--- a/wgpu/src/triangle/gradient.rs
+++ b/wgpu/src/triangle/gradient.rs
@@ -5,7 +5,7 @@ use crate::triangle::{
     default_triangle_primitive_state, vertex_buffer_layout,
 };
 use encase::ShaderType;
-use glam::{Vec2, Vec4};
+use glam::{IVec4, Vec4};
 use iced_graphics::gradient::Gradient;
 use iced_graphics::Transformation;
 
@@ -21,17 +21,13 @@ pub(super) struct GradientPipeline {
     bind_group: wgpu::BindGroup,
 }
 
-//TODO I can tightly pack this by rearranging/consolidating some fields
 #[derive(Debug, ShaderType)]
 pub(super) struct GradientUniforms {
     transform: glam::Mat4,
-    start: Vec2,
-    #[align(16)]
-    end: Vec2,
-    #[align(16)]
-    start_stop: i32,
-    #[align(16)]
-    end_stop: i32,
+    //xy = start, zw = end
+    direction: Vec4,
+    //x = start, y = end, zw = padding
+    stop_range: IVec4,
 }
 
 #[derive(Debug, ShaderType)]
@@ -58,7 +54,7 @@ impl GradientPipeline {
             "iced_wgpu::triangle [GRADIENT] uniforms",
         );
 
-        //TODO: With a WASM target storage buffers are not supported. Will need to use UBOs & static 
+        //TODO: With a WASM target storage buffers are not supported. Will need to use UBOs & static
         // sized array (64 on OpenGL side right now) to make gradients work
         let storage_buffer = DynamicBuffer::storage(
             device,
@@ -143,7 +139,9 @@ impl GradientPipeline {
             uniform_buffer,
             storage_buffer,
             color_stop_offset: 0,
-            color_stops_pending_write: GradientStorage { color_stops: vec![] },
+            color_stops_pending_write: GradientStorage {
+                color_stops: vec![],
+            },
             bind_group_layout,
             bind_group,
         }
@@ -159,10 +157,13 @@ impl GradientPipeline {
 
                 self.uniform_buffer.push(&GradientUniforms {
                     transform: transform.into(),
-                    start: Vec2::new(linear.start.x, linear.start.y),
-                    end: Vec2::new(linear.end.x, linear.end.y),
-                    start_stop: start_offset,
-                    end_stop: end_offset,
+                    direction: Vec4::new(
+                        linear.start.x,
+                        linear.start.y,
+                        linear.end.x,
+                        linear.end.y,
+                    ),
+                    stop_range: IVec4::new(start_offset, end_offset, 0, 0),
                 });
 
                 self.color_stop_offset = end_offset + 1;
@@ -202,13 +203,13 @@ impl GradientPipeline {
                         wgpu::BufferBinding {
                             buffer: uniform_buffer,
                             offset: 0,
-                            size: Some(GradientUniforms::min_size())
-                        }
-                    )
+                            size: Some(GradientUniforms::min_size()),
+                        },
+                    ),
                 },
                 wgpu::BindGroupEntry {
                     binding: 1,
-                    resource: storage_buffer.as_entire_binding()
+                    resource: storage_buffer.as_entire_binding(),
                 },
             ],
         })
-- 
cgit