diff options
author | 2022-10-05 16:07:43 -0700 | |
---|---|---|
committer | 2022-10-05 16:07:43 -0700 | |
commit | 1eb8d972ba60592da7bfc27fe7ec80138e64dd7b (patch) | |
tree | 1951255bcb8d2b87767da406eb87b80ab5a709cc /glow | |
parent | f7ce7244d017ec16545a3e52b6e7cf634bbffd4a (diff) | |
download | iced-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.rs | 6 | ||||
-rw-r--r-- | glow/src/quad/core.rs | 6 | ||||
-rw-r--r-- | glow/src/shader/common/gradient.frag | 43 | ||||
-rw-r--r-- | glow/src/triangle/gradient.rs | 143 |
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, }, } |