From d4743183d40c6044ce6fa39e2a52919a32912cda Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 19 May 2020 14:23:28 +0200 Subject: Draft first working version of `iced_glow` :tada: --- glow/src/quad.rs | 254 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 glow/src/quad.rs (limited to 'glow/src/quad.rs') diff --git a/glow/src/quad.rs b/glow/src/quad.rs new file mode 100644 index 00000000..744597d2 --- /dev/null +++ b/glow/src/quad.rs @@ -0,0 +1,254 @@ +use crate::{Transformation, Viewport}; +use glow::HasContext; +use iced_native::Rectangle; + +#[derive(Debug)] +pub struct Pipeline { + program: ::Program, + vertex_array: ::VertexArray, + instances: ::Buffer, + current_transform: Transformation, + current_scale: f32, +} + +impl Pipeline { + pub fn new(gl: &glow::Context) -> Pipeline { + let program = unsafe { + create_program( + gl, + &[ + (glow::VERTEX_SHADER, include_str!("shader/quad.vert")), + (glow::FRAGMENT_SHADER, include_str!("shader/quad.frag")), + ], + ) + }; + + unsafe { + gl.use_program(Some(program)); + + gl.uniform_matrix_4_f32_slice( + Some(0), + false, + &Transformation::identity().into(), + ); + gl.uniform_1_f32(Some(1), 1.0); + + gl.use_program(None); + } + + let (vertex_array, instances) = + unsafe { create_instance_buffer(gl, Quad::MAX) }; + + Pipeline { + program, + vertex_array, + instances, + current_transform: Transformation::identity(), + current_scale: 1.0, + } + } + + pub fn draw( + &mut self, + gl: &glow::Context, + viewport: &Viewport, + instances: &[Quad], + transformation: Transformation, + scale: f32, + bounds: Rectangle, + ) { + unsafe { + gl.enable(glow::SCISSOR_TEST); + gl.scissor( + bounds.x as i32, + (viewport.height() + - (bounds.y + bounds.height).min(viewport.height())) + as i32, + bounds.width as i32, + bounds.height as i32, + ); + + gl.use_program(Some(self.program)); + gl.bind_vertex_array(Some(self.vertex_array)); + gl.bind_buffer(glow::ARRAY_BUFFER, Some(self.instances)); + } + + if transformation != self.current_transform { + unsafe { + gl.uniform_matrix_4_f32_slice( + Some(0), + false, + &transformation.into(), + ); + + self.current_transform = transformation; + } + } + + if scale != self.current_scale { + unsafe { + gl.uniform_1_f32(Some(1), scale); + } + + self.current_scale = scale; + } + + let mut i = 0; + let total = instances.len(); + + while i < total { + let end = (i + Quad::MAX).min(total); + let amount = end - i; + + unsafe { + gl.buffer_sub_data_u8_slice( + glow::ARRAY_BUFFER, + 0, + bytemuck::cast_slice(&instances[i..end]), + ); + + gl.draw_arrays_instanced( + glow::TRIANGLE_STRIP, + 0, + 4, + amount as i32, + ); + } + + i += Quad::MAX; + } + + unsafe { + gl.bind_vertex_array(None); + gl.use_program(None); + gl.disable(glow::SCISSOR_TEST); + } + } +} + +#[derive(Debug, Clone, Copy)] +#[repr(C)] +pub struct Quad { + pub position: [f32; 2], + pub scale: [f32; 2], + pub color: [f32; 4], + pub border_color: [f32; 4], + pub border_radius: f32, + pub border_width: f32, +} + +unsafe impl bytemuck::Zeroable for Quad {} +unsafe impl bytemuck::Pod for Quad {} + +impl Quad { + const MAX: usize = 100_000; +} + +unsafe fn create_program( + gl: &glow::Context, + shader_sources: &[(u32, &str)], +) -> ::Program { + let program = gl.create_program().expect("Cannot create program"); + + let mut shaders = Vec::with_capacity(shader_sources.len()); + + for (shader_type, shader_source) in shader_sources.iter() { + let shader = gl + .create_shader(*shader_type) + .expect("Cannot create shader"); + + gl.shader_source(shader, shader_source); + gl.compile_shader(shader); + + if !gl.get_shader_compile_status(shader) { + panic!(gl.get_shader_info_log(shader)); + } + + gl.attach_shader(program, shader); + + shaders.push(shader); + } + + gl.link_program(program); + if !gl.get_program_link_status(program) { + panic!(gl.get_program_info_log(program)); + } + + for shader in shaders { + gl.detach_shader(program, shader); + gl.delete_shader(shader); + } + + program +} + +unsafe fn create_instance_buffer( + gl: &glow::Context, + size: usize, +) -> ( + ::VertexArray, + ::Buffer, +) { + let vertex_array = gl.create_vertex_array().expect("Create vertex array"); + let buffer = gl.create_buffer().expect("Create instance buffer"); + + gl.bind_vertex_array(Some(vertex_array)); + gl.bind_buffer(glow::ARRAY_BUFFER, Some(buffer)); + gl.buffer_data_size( + glow::ARRAY_BUFFER, + (size * std::mem::size_of::()) as i32, + glow::DYNAMIC_DRAW, + ); + + let stride = std::mem::size_of::() as i32; + + gl.enable_vertex_attrib_array(0); + gl.vertex_attrib_pointer_f32(0, 2, glow::FLOAT, false, stride, 0); + gl.vertex_attrib_divisor(0, 1); + + gl.enable_vertex_attrib_array(1); + gl.vertex_attrib_pointer_f32(1, 2, glow::FLOAT, false, stride, 4 * 2); + gl.vertex_attrib_divisor(1, 1); + + gl.enable_vertex_attrib_array(2); + gl.vertex_attrib_pointer_f32(2, 4, glow::FLOAT, false, stride, 4 * (2 + 2)); + gl.vertex_attrib_divisor(2, 1); + + gl.enable_vertex_attrib_array(3); + gl.vertex_attrib_pointer_f32( + 3, + 4, + glow::FLOAT, + false, + stride, + 4 * (2 + 2 + 4), + ); + gl.vertex_attrib_divisor(3, 1); + + gl.enable_vertex_attrib_array(4); + gl.vertex_attrib_pointer_f32( + 4, + 1, + glow::FLOAT, + false, + stride, + 4 * (2 + 2 + 4 + 4), + ); + gl.vertex_attrib_divisor(4, 1); + + gl.enable_vertex_attrib_array(5); + gl.vertex_attrib_pointer_f32( + 5, + 1, + glow::FLOAT, + false, + stride, + 4 * (2 + 2 + 4 + 4 + 1), + ); + gl.vertex_attrib_divisor(5, 1); + + gl.bind_vertex_array(None); + gl.bind_buffer(glow::ARRAY_BUFFER, None); + + (vertex_array, buffer) +} -- cgit From 720e7756f2afe30706b6b1a7fbde86b9f15e1d8c Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 19 May 2020 22:55:12 +0200 Subject: Move `Layer` to `iced_graphics` --- glow/src/quad.rs | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) (limited to 'glow/src/quad.rs') diff --git a/glow/src/quad.rs b/glow/src/quad.rs index 744597d2..26424b39 100644 --- a/glow/src/quad.rs +++ b/glow/src/quad.rs @@ -1,7 +1,10 @@ use crate::{Transformation, Viewport}; use glow::HasContext; +use iced_graphics::layer; use iced_native::Rectangle; +const MAX_INSTANCES: usize = 100_000; + #[derive(Debug)] pub struct Pipeline { program: ::Program, @@ -37,7 +40,7 @@ impl Pipeline { } let (vertex_array, instances) = - unsafe { create_instance_buffer(gl, Quad::MAX) }; + unsafe { create_instance_buffer(gl, MAX_INSTANCES) }; Pipeline { program, @@ -52,7 +55,7 @@ impl Pipeline { &mut self, gl: &glow::Context, viewport: &Viewport, - instances: &[Quad], + instances: &[layer::Quad], transformation: Transformation, scale: f32, bounds: Rectangle, @@ -97,7 +100,7 @@ impl Pipeline { let total = instances.len(); while i < total { - let end = (i + Quad::MAX).min(total); + let end = (i + MAX_INSTANCES).min(total); let amount = end - i; unsafe { @@ -115,7 +118,7 @@ impl Pipeline { ); } - i += Quad::MAX; + i += MAX_INSTANCES; } unsafe { @@ -126,24 +129,6 @@ impl Pipeline { } } -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Quad { - pub position: [f32; 2], - pub scale: [f32; 2], - pub color: [f32; 4], - pub border_color: [f32; 4], - pub border_radius: f32, - pub border_width: f32, -} - -unsafe impl bytemuck::Zeroable for Quad {} -unsafe impl bytemuck::Pod for Quad {} - -impl Quad { - const MAX: usize = 100_000; -} - unsafe fn create_program( gl: &glow::Context, shader_sources: &[(u32, &str)], @@ -196,11 +181,11 @@ unsafe fn create_instance_buffer( gl.bind_buffer(glow::ARRAY_BUFFER, Some(buffer)); gl.buffer_data_size( glow::ARRAY_BUFFER, - (size * std::mem::size_of::()) as i32, + (size * std::mem::size_of::()) as i32, glow::DYNAMIC_DRAW, ); - let stride = std::mem::size_of::() as i32; + let stride = std::mem::size_of::() as i32; gl.enable_vertex_attrib_array(0); gl.vertex_attrib_pointer_f32(0, 2, glow::FLOAT, false, stride, 0); -- cgit From a1a5fcfd46622d5b18d1716aa2adb4659835ccf3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 20 May 2020 20:28:35 +0200 Subject: Refactor `Viewport` and `Compositor` --- glow/src/quad.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'glow/src/quad.rs') diff --git a/glow/src/quad.rs b/glow/src/quad.rs index 26424b39..fd71757f 100644 --- a/glow/src/quad.rs +++ b/glow/src/quad.rs @@ -1,4 +1,4 @@ -use crate::{Transformation, Viewport}; +use crate::Transformation; use glow::HasContext; use iced_graphics::layer; use iced_native::Rectangle; @@ -54,7 +54,7 @@ impl Pipeline { pub fn draw( &mut self, gl: &glow::Context, - viewport: &Viewport, + target_height: u32, instances: &[layer::Quad], transformation: Transformation, scale: f32, @@ -64,9 +64,7 @@ impl Pipeline { gl.enable(glow::SCISSOR_TEST); gl.scissor( bounds.x as i32, - (viewport.height() - - (bounds.y + bounds.height).min(viewport.height())) - as i32, + (target_height - (bounds.y + bounds.height)) as i32, bounds.width as i32, bounds.height as i32, ); -- cgit From d77492c0c37dec1207049b340a318e263cb96b82 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 21 May 2020 01:01:47 +0200 Subject: Avoid relying `origin_upper_left` It seems to cause considerable glitches when resizing. --- glow/src/quad.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'glow/src/quad.rs') diff --git a/glow/src/quad.rs b/glow/src/quad.rs index fd71757f..acac3219 100644 --- a/glow/src/quad.rs +++ b/glow/src/quad.rs @@ -12,6 +12,7 @@ pub struct Pipeline { instances: ::Buffer, current_transform: Transformation, current_scale: f32, + current_target_height: u32, } impl Pipeline { @@ -35,6 +36,7 @@ impl Pipeline { &Transformation::identity().into(), ); gl.uniform_1_f32(Some(1), 1.0); + gl.uniform_1_f32(Some(2), 0.0); gl.use_program(None); } @@ -48,6 +50,7 @@ impl Pipeline { instances, current_transform: Transformation::identity(), current_scale: 1.0, + current_target_height: 0, } } @@ -94,6 +97,14 @@ impl Pipeline { self.current_scale = scale; } + if target_height != self.current_target_height { + unsafe { + gl.uniform_1_f32(Some(2), target_height as f32); + } + + self.current_target_height = target_height; + } + let mut i = 0; let total = instances.len(); -- cgit From 60dcfc354e844757d2291bf44cb21c624bc270c2 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 21 May 2020 19:07:33 +0200 Subject: Draft `triangle` pipeline in `iced_glow` --- glow/src/quad.rs | 41 ++--------------------------------------- 1 file changed, 2 insertions(+), 39 deletions(-) (limited to 'glow/src/quad.rs') diff --git a/glow/src/quad.rs b/glow/src/quad.rs index acac3219..3a051268 100644 --- a/glow/src/quad.rs +++ b/glow/src/quad.rs @@ -1,3 +1,4 @@ +use crate::program; use crate::Transformation; use glow::HasContext; use iced_graphics::layer; @@ -18,7 +19,7 @@ pub struct Pipeline { impl Pipeline { pub fn new(gl: &glow::Context) -> Pipeline { let program = unsafe { - create_program( + program::create( gl, &[ (glow::VERTEX_SHADER, include_str!("shader/quad.vert")), @@ -138,44 +139,6 @@ impl Pipeline { } } -unsafe fn create_program( - gl: &glow::Context, - shader_sources: &[(u32, &str)], -) -> ::Program { - let program = gl.create_program().expect("Cannot create program"); - - let mut shaders = Vec::with_capacity(shader_sources.len()); - - for (shader_type, shader_source) in shader_sources.iter() { - let shader = gl - .create_shader(*shader_type) - .expect("Cannot create shader"); - - gl.shader_source(shader, shader_source); - gl.compile_shader(shader); - - if !gl.get_shader_compile_status(shader) { - panic!(gl.get_shader_info_log(shader)); - } - - gl.attach_shader(program, shader); - - shaders.push(shader); - } - - gl.link_program(program); - if !gl.get_program_link_status(program) { - panic!(gl.get_program_info_log(program)); - } - - for shader in shaders { - gl.detach_shader(program, shader); - gl.delete_shader(shader); - } - - program -} - unsafe fn create_instance_buffer( gl: &glow::Context, size: usize, -- cgit From bbfb1c040c92e36b3d23a2167ad3432c819b9668 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 21 May 2020 19:50:53 +0200 Subject: Update to latest `glow` --- glow/src/quad.rs | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) (limited to 'glow/src/quad.rs') diff --git a/glow/src/quad.rs b/glow/src/quad.rs index 3a051268..c2fd08a2 100644 --- a/glow/src/quad.rs +++ b/glow/src/quad.rs @@ -31,13 +31,11 @@ impl Pipeline { unsafe { gl.use_program(Some(program)); - gl.uniform_matrix_4_f32_slice( - Some(0), - false, - &Transformation::identity().into(), - ); - gl.uniform_1_f32(Some(1), 1.0); - gl.uniform_1_f32(Some(2), 0.0); + let matrix: [f32; 16] = Transformation::identity().into(); + gl.uniform_matrix_4_f32_slice(Some(&0), false, &matrix); + + gl.uniform_1_f32(Some(&1), 1.0); + gl.uniform_1_f32(Some(&2), 0.0); gl.use_program(None); } @@ -80,11 +78,8 @@ impl Pipeline { if transformation != self.current_transform { unsafe { - gl.uniform_matrix_4_f32_slice( - Some(0), - false, - &transformation.into(), - ); + let matrix: [f32; 16] = transformation.into(); + gl.uniform_matrix_4_f32_slice(Some(&0), false, &matrix); self.current_transform = transformation; } @@ -92,7 +87,7 @@ impl Pipeline { if scale != self.current_scale { unsafe { - gl.uniform_1_f32(Some(1), scale); + gl.uniform_1_f32(Some(&1), scale); } self.current_scale = scale; @@ -100,7 +95,7 @@ impl Pipeline { if target_height != self.current_target_height { unsafe { - gl.uniform_1_f32(Some(2), target_height as f32); + gl.uniform_1_f32(Some(&2), target_height as f32); } self.current_target_height = target_height; -- cgit From 6f71a8e3d5e47ab05653315b0d44b35af6a20338 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 22 May 2020 05:52:11 +0200 Subject: Use `get_uniform_location` for wider compatibility --- glow/src/quad.rs | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) (limited to 'glow/src/quad.rs') diff --git a/glow/src/quad.rs b/glow/src/quad.rs index c2fd08a2..a8fbb9e5 100644 --- a/glow/src/quad.rs +++ b/glow/src/quad.rs @@ -11,6 +11,9 @@ pub struct Pipeline { program: ::Program, vertex_array: ::VertexArray, instances: ::Buffer, + transform_location: ::UniformLocation, + scale_location: ::UniformLocation, + screen_height_location: ::UniformLocation, current_transform: Transformation, current_scale: f32, current_target_height: u32, @@ -28,14 +31,30 @@ impl Pipeline { ) }; + let transform_location = + unsafe { gl.get_uniform_location(program, "u_Transform") } + .expect("Get transform location"); + + let scale_location = + unsafe { gl.get_uniform_location(program, "u_Scale") } + .expect("Get scale location"); + + let screen_height_location = + unsafe { gl.get_uniform_location(program, "u_ScreenHeight") } + .expect("Get target height location"); + unsafe { gl.use_program(Some(program)); let matrix: [f32; 16] = Transformation::identity().into(); - gl.uniform_matrix_4_f32_slice(Some(&0), false, &matrix); + gl.uniform_matrix_4_f32_slice( + Some(&transform_location), + false, + &matrix, + ); - gl.uniform_1_f32(Some(&1), 1.0); - gl.uniform_1_f32(Some(&2), 0.0); + gl.uniform_1_f32(Some(&scale_location), 1.0); + gl.uniform_1_f32(Some(&screen_height_location), 0.0); gl.use_program(None); } @@ -47,6 +66,9 @@ impl Pipeline { program, vertex_array, instances, + transform_location, + scale_location, + screen_height_location, current_transform: Transformation::identity(), current_scale: 1.0, current_target_height: 0, @@ -79,7 +101,11 @@ impl Pipeline { if transformation != self.current_transform { unsafe { let matrix: [f32; 16] = transformation.into(); - gl.uniform_matrix_4_f32_slice(Some(&0), false, &matrix); + gl.uniform_matrix_4_f32_slice( + Some(&self.transform_location), + false, + &matrix, + ); self.current_transform = transformation; } @@ -87,7 +113,7 @@ impl Pipeline { if scale != self.current_scale { unsafe { - gl.uniform_1_f32(Some(&1), scale); + gl.uniform_1_f32(Some(&self.scale_location), scale); } self.current_scale = scale; @@ -95,7 +121,10 @@ impl Pipeline { if target_height != self.current_target_height { unsafe { - gl.uniform_1_f32(Some(&2), target_height as f32); + gl.uniform_1_f32( + Some(&self.screen_height_location), + target_height as f32, + ); } self.current_target_height = target_height; -- cgit From d6bf8955dbca03898e379aae376d91677bb4d223 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 22 May 2020 19:17:07 +0200 Subject: Use published `glow` and `glow_glyph` versions --- glow/src/quad.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'glow/src/quad.rs') diff --git a/glow/src/quad.rs b/glow/src/quad.rs index a8fbb9e5..3a65338a 100644 --- a/glow/src/quad.rs +++ b/glow/src/quad.rs @@ -48,13 +48,13 @@ impl Pipeline { let matrix: [f32; 16] = Transformation::identity().into(); gl.uniform_matrix_4_f32_slice( - Some(&transform_location), + Some(transform_location), false, &matrix, ); - gl.uniform_1_f32(Some(&scale_location), 1.0); - gl.uniform_1_f32(Some(&screen_height_location), 0.0); + gl.uniform_1_f32(Some(scale_location), 1.0); + gl.uniform_1_f32(Some(screen_height_location), 0.0); gl.use_program(None); } @@ -102,7 +102,7 @@ impl Pipeline { unsafe { let matrix: [f32; 16] = transformation.into(); gl.uniform_matrix_4_f32_slice( - Some(&self.transform_location), + Some(self.transform_location), false, &matrix, ); @@ -113,7 +113,7 @@ impl Pipeline { if scale != self.current_scale { unsafe { - gl.uniform_1_f32(Some(&self.scale_location), scale); + gl.uniform_1_f32(Some(self.scale_location), scale); } self.current_scale = scale; @@ -122,7 +122,7 @@ impl Pipeline { if target_height != self.current_target_height { unsafe { gl.uniform_1_f32( - Some(&self.screen_height_location), + Some(self.screen_height_location), target_height as f32, ); } -- cgit