summaryrefslogtreecommitdiffstats
path: root/glow
diff options
context:
space:
mode:
authorLibravatar shan <shankern@protonmail.com>2022-10-05 16:07:43 -0700
committerLibravatar shan <shankern@protonmail.com>2022-10-05 16:07:43 -0700
commit1eb8d972ba60592da7bfc27fe7ec80138e64dd7b (patch)
tree1951255bcb8d2b87767da406eb87b80ab5a709cc /glow
parentf7ce7244d017ec16545a3e52b6e7cf634bbffd4a (diff)
downloadiced-1eb8d972ba60592da7bfc27fe7ec80138e64dd7b.tar.gz
iced-1eb8d972ba60592da7bfc27fe7ec80138e64dd7b.tar.bz2
iced-1eb8d972ba60592da7bfc27fe7ec80138e64dd7b.zip
Reduced memory transfer of OpenGL gradient uniform upload. Rearranged gradient uniforms on OpenGL side to be more performant.
Diffstat (limited to 'glow')
-rw-r--r--glow/src/quad/compatibility.rs6
-rw-r--r--glow/src/quad/core.rs6
-rw-r--r--glow/src/shader/common/gradient.frag43
-rw-r--r--glow/src/triangle/gradient.rs143
4 files changed, 77 insertions, 121 deletions
diff --git a/glow/src/quad/compatibility.rs b/glow/src/quad/compatibility.rs
index eb3fb7e0..28a5ea7c 100644
--- a/glow/src/quad/compatibility.rs
+++ b/glow/src/quad/compatibility.rs
@@ -70,11 +70,10 @@ impl Pipeline {
unsafe {
gl.use_program(Some(program));
- let matrix: [f32; 16] = Transformation::identity().into();
gl.uniform_matrix_4_f32_slice(
Some(&transform_location),
false,
- &matrix,
+ Transformation::identity().as_ref(),
);
gl.uniform_1_f32(Some(&scale_location), 1.0);
@@ -139,11 +138,10 @@ impl Pipeline {
if transformation != self.current_transform {
unsafe {
- let matrix: [f32; 16] = transformation.into();
gl.uniform_matrix_4_f32_slice(
Some(&self.transform_location),
false,
- &matrix,
+ transformation.as_ref(),
);
self.current_transform = transformation;
diff --git a/glow/src/quad/core.rs b/glow/src/quad/core.rs
index 3e51b1ca..16bec385 100644
--- a/glow/src/quad/core.rs
+++ b/glow/src/quad/core.rs
@@ -65,11 +65,10 @@ impl Pipeline {
unsafe {
gl.use_program(Some(program));
- let matrix: [f32; 16] = Transformation::identity().into();
gl.uniform_matrix_4_f32_slice(
Some(&transform_location),
false,
- &matrix,
+ Transformation::identity().as_ref(),
);
gl.uniform_1_f32(Some(&scale_location), 1.0);
@@ -119,11 +118,10 @@ impl Pipeline {
if transformation != self.current_transform {
unsafe {
- let matrix: [f32; 16] = transformation.into();
gl.uniform_matrix_4_f32_slice(
Some(&self.transform_location),
false,
- &matrix,
+ transformation.as_ref(),
);
self.current_transform = transformation;
diff --git a/glow/src/shader/common/gradient.frag b/glow/src/shader/common/gradient.frag
index 1afb557d..89d2d398 100644
--- a/glow/src/shader/common/gradient.frag
+++ b/glow/src/shader/common/gradient.frag
@@ -1,6 +1,3 @@
-// GLSL does not support dynamically sized arrays without SSBOs
-#define MAX_STOPS 64
-
#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
@@ -16,34 +13,38 @@ layout (location = 0) out vec4 fragColor;
in vec2 raw_position;
-uniform vec2 gradient_start;
-uniform vec2 gradient_end;
-
+uniform vec4 gradient_direction;
uniform uint color_stops_size;
-uniform float color_stop_offsets[MAX_STOPS];
-uniform vec4 color_stop_colors[MAX_STOPS];
+// GLSL does not support dynamically sized arrays without SSBOs so this is capped to 16 stops
+//stored as color(vec4) -> offset(vec4) sequentially;
+uniform vec4 color_stops[32];
//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);
+ vec2 start = gradient_direction.xy;
+ vec2 end = gradient_direction.zw;
+ vec2 gradient_vec = vec2(end - start);
+ vec2 current_vec = vec2(raw_position.xy - start);
vec2 unit = normalize(gradient_vec);
float coord_offset = dot(unit, current_vec) / length(gradient_vec);
- for (uint i = 0; i < color_stops_size - 1; i++) {
- float stop_offset = color_stop_offsets[i];
- float next_stop_offset = color_stop_offsets[i + 1];
+ for (uint i = 0; i < color_stops_size - 2; i += 2) {
+ vec4 color = color_stops[i];
+ float offset = color_stops[i+1].x;
+
+ vec4 next_color = color_stops[i+2];
+ float next_offset = color_stops[i+3].x;
- if (stop_offset <= coord_offset && coord_offset <= next_stop_offset) {
- fragColor = mix(color_stop_colors[i], color_stop_colors[i+1], smoothstep(
- stop_offset,
- next_stop_offset,
+ if (offset <= coord_offset && coord_offset <= next_offset) {
+ fragColor = mix(color, next_color, smoothstep(
+ offset,
+ next_offset,
coord_offset
));
- } else if (coord_offset < color_stop_offsets[0]) {
- fragColor = color_stop_colors[0];
- } else if (coord_offset > color_stop_offsets[color_stops_size - 1]) {
- fragColor = color_stop_colors[color_stops_size - 1];
+ } else if (coord_offset < color_stops[1].x) {
+ fragColor = color_stops[0];
+ } else if (coord_offset > color_stops[color_stops_size - 1].x) {
+ fragColor = color_stops[color_stops_size - 2];
}
}
} \ No newline at end of file
diff --git a/glow/src/triangle/gradient.rs b/glow/src/triangle/gradient.rs
index 547871e2..4b157890 100644
--- a/glow/src/triangle/gradient.rs
+++ b/glow/src/triangle/gradient.rs
@@ -1,8 +1,8 @@
use crate::program::Version;
-use crate::triangle::{simple_triangle_program, set_transform};
+use crate::triangle::{set_transform, simple_triangle_program};
use glow::{Context, HasContext, NativeProgram};
-use iced_graphics::gradient::Linear;
use iced_graphics::gradient::Gradient;
+use iced_graphics::gradient::Linear;
use iced_graphics::Transformation;
#[derive(Debug)]
@@ -20,21 +20,14 @@ pub struct GradientUniformData {
#[derive(Debug)]
struct GradientUniformLocations {
- gradient_start_location: <Context as HasContext>::UniformLocation,
- gradient_end_location: <Context as HasContext>::UniformLocation,
+ gradient_direction_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],
+ color_stops_location: <Context as HasContext>::UniformLocation,
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 fn new(gl: &Context, shader_version: &Version) -> Self {
let program = simple_triangle_program(
@@ -56,76 +49,60 @@ impl GradientProgram {
transform: &Transformation,
) {
if transform != &self.uniform_data.transform {
- set_transform(gl, self.uniform_data.uniform_locations.transform_location, *transform);
+ set_transform(
+ gl,
+ self.uniform_data.uniform_locations.transform_location,
+ *transform,
+ );
}
if &self.uniform_data.gradient != gradient {
match gradient {
Gradient::Linear(linear) => {
- let gradient_start: [f32; 2] = (linear.start).into();
- let gradient_end: [f32; 2] = (linear.end).into();
-
unsafe {
- gl.uniform_2_f32(
+ gl.uniform_4_f32(
Some(
- &self
- .uniform_data
- .uniform_locations
- .gradient_start_location,
+ &self.uniform_data.uniform_locations.gradient_direction_location
),
- gradient_start[0],
- gradient_start[1],
+ linear.start.x,
+ linear.start.y,
+ linear.end.x,
+ linear.end.y
);
- gl.uniform_2_f32(
+ gl.uniform_1_u32(
Some(
&self
.uniform_data
.uniform_locations
- .gradient_end_location,
+ .color_stops_size_location,
),
- gradient_end[0],
- gradient_end[1],
+ (linear.color_stops.len() * 2) as u32,
);
- gl.uniform_1_u32(
+ let mut stops = [0.0; 128];
+
+ for (index, stop) in linear.color_stops.iter().enumerate() {
+ if index == 16 { break; }
+ stops[index*8] = stop.color.r;
+ stops[(index*8)+1] = stop.color.g;
+ stops[(index*8)+2] = stop.color.b;
+ stops[(index*8)+3] = stop.color.a;
+ stops[(index*8)+4] = stop.offset;
+ stops[(index*8)+5] = 0.;
+ stops[(index*8)+6] = 0.;
+ stops[(index*8)+7] = 0.;
+ }
+
+ gl.uniform_4_f32_slice(
Some(
&self
.uniform_data
.uniform_locations
- .color_stops_size_location,
+ .color_stops_location,
),
- linear.color_stops.len() as u32,
+ &stops,
);
-
- for (index, stop) in
- linear.color_stops.iter().enumerate()
- {
- gl.uniform_1_f32(
- Some(
- &self
- .uniform_data
- .uniform_locations
- .color_stops_locations[index]
- .offset,
- ),
- stop.offset,
- );
-
- gl.uniform_4_f32(
- Some(
- &self
- .uniform_data
- .uniform_locations
- .color_stops_locations[index]
- .color,
- ),
- stop.color.r,
- stop.color.g,
- stop.color.b,
- stop.color.a,
- );
- }
}
}
}
@@ -134,10 +111,13 @@ impl GradientProgram {
}
}
- pub fn use_program(&mut self, gl: &glow::Context, gradient: &Gradient, transform: &Transformation) {
- unsafe {
- gl.use_program(Some(self.program))
- }
+ pub fn use_program(
+ &mut self,
+ gl: &Context,
+ gradient: &Gradient,
+ transform: &Transformation,
+ ) {
+ unsafe { gl.use_program(Some(self.program)) }
self.write_uniforms(gl, gradient, transform);
}
@@ -145,38 +125,18 @@ impl GradientProgram {
impl GradientUniformData {
fn new(gl: &Context, program: NativeProgram) -> Self {
- let gradient_start_location =
- unsafe { gl.get_uniform_location(program, "gradient_start") }
- .expect("Gradient - Get gradient_start.");
-
- let gradient_end_location =
- unsafe { gl.get_uniform_location(program, "gradient_end") }
- .expect("Gradient - Get gradient_end.");
+ let gradient_direction_location =
+ unsafe { gl.get_uniform_location(program, "gradient_direction") }
+ .expect("Gradient - Get gradient_direction.");
let color_stops_size_location =
unsafe { gl.get_uniform_location(program, "color_stops_size") }
.expect("Gradient - Get color_stops_size.");
- let color_stops_locations: [ColorStopLocation; 64] =
- core::array::from_fn(|index| {
- let offset = unsafe {
- gl.get_uniform_location(
- program,
- &format!("color_stop_offsets[{}]", index),
- )
- }
- .expect("Gradient - Color stop offset location.");
-
- let color = unsafe {
- gl.get_uniform_location(
- program,
- &format!("color_stop_colors[{}]", index),
- )
- }
- .expect("Gradient - Color stop color location.");
-
- ColorStopLocation { color, offset }
- });
+ let color_stops_location = unsafe {
+ gl.get_uniform_location(program, "color_stops")
+ .expect("Gradient - Get color_stops.")
+ };
let transform_location =
unsafe { gl.get_uniform_location(program, "u_Transform") }
@@ -190,10 +150,9 @@ impl GradientUniformData {
}),
transform: Transformation::identity(),
uniform_locations: GradientUniformLocations {
- gradient_start_location,
- gradient_end_location,
+ gradient_direction_location,
color_stops_size_location,
- color_stops_locations,
+ color_stops_location,
transform_location,
},
}