diff options
author | 2019-11-06 20:34:58 +0100 | |
---|---|---|
committer | 2019-11-06 20:34:58 +0100 | |
commit | efa8d267b8e1d667902b1e0d0e7c6e4d79e75f6e (patch) | |
tree | efb1b525ed865976bd14d8ee9e664323349aa25e /wgpu | |
parent | ae6156f779c24beaabf43ea6110d3ce38e34a998 (diff) | |
parent | 6216f197e927aef0993a36c1bb094c7f917d54dd (diff) | |
download | iced-efa8d267b8e1d667902b1e0d0e7c6e4d79e75f6e.tar.gz iced-efa8d267b8e1d667902b1e0d0e7c6e4d79e75f6e.tar.bz2 iced-efa8d267b8e1d667902b1e0d0e7c6e4d79e75f6e.zip |
Merge pull request #40 from hecrj/feature/hidpi-support
HiDPI support
Diffstat (limited to '')
-rw-r--r-- | wgpu/src/quad.rs | 58 | ||||
-rw-r--r-- | wgpu/src/renderer.rs | 56 | ||||
-rw-r--r-- | wgpu/src/renderer/target.rs | 16 | ||||
-rw-r--r-- | wgpu/src/renderer/widget/checkbox.rs | 2 | ||||
-rw-r--r-- | wgpu/src/renderer/widget/text.rs | 7 | ||||
-rw-r--r-- | wgpu/src/shader/quad.frag | 8 | ||||
-rw-r--r-- | wgpu/src/shader/quad.frag.spv | bin | 3212 -> 3044 bytes | |||
-rw-r--r-- | wgpu/src/shader/quad.vert | 20 | ||||
-rw-r--r-- | wgpu/src/shader/quad.vert.spv | bin | 2544 -> 3020 bytes | |||
-rw-r--r-- | wgpu/src/transformation.rs | 5 |
10 files changed, 123 insertions, 49 deletions
diff --git a/wgpu/src/quad.rs b/wgpu/src/quad.rs index bfbd7e2d..4356f8af 100644 --- a/wgpu/src/quad.rs +++ b/wgpu/src/quad.rs @@ -6,7 +6,7 @@ use std::mem; pub struct Pipeline { pipeline: wgpu::RenderPipeline, constants: wgpu::BindGroup, - transform: wgpu::Buffer, + constants_buffer: wgpu::Buffer, vertices: wgpu::Buffer, indices: wgpu::Buffer, instances: wgpu::Buffer, @@ -23,20 +23,20 @@ impl Pipeline { }], }); - let transform = device + let constants_buffer = device .create_buffer_mapped( - 16, + 1, wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, ) - .fill_from_slice(Transformation::identity().as_ref()); + .fill_from_slice(&[Uniforms::default()]); let constants = device.create_bind_group(&wgpu::BindGroupDescriptor { layout: &constant_layout, bindings: &[wgpu::Binding { binding: 0, resource: wgpu::BindingResource::Buffer { - buffer: &transform, - range: 0..64, + buffer: &constants_buffer, + range: 0..std::mem::size_of::<Uniforms>() as u64, }, }], }); @@ -124,7 +124,7 @@ impl Pipeline { }, wgpu::VertexAttributeDescriptor { shader_location: 4, - format: wgpu::VertexFormat::Uint, + format: wgpu::VertexFormat::Float, offset: 4 * (2 + 2 + 4), }, ], @@ -151,7 +151,7 @@ impl Pipeline { Pipeline { pipeline, constants, - transform, + constants_buffer, vertices, indices, instances, @@ -164,19 +164,22 @@ impl Pipeline { encoder: &mut wgpu::CommandEncoder, instances: &[Quad], transformation: Transformation, + scale: f32, bounds: Rectangle<u32>, target: &wgpu::TextureView, ) { - let transform_buffer = device - .create_buffer_mapped(16, wgpu::BufferUsage::COPY_SRC) - .fill_from_slice(transformation.as_ref()); + let uniforms = Uniforms::new(transformation, scale); + + let constants_buffer = device + .create_buffer_mapped(1, wgpu::BufferUsage::COPY_SRC) + .fill_from_slice(&[uniforms]); encoder.copy_buffer_to_buffer( - &transform_buffer, + &constants_buffer, 0, - &self.transform, + &self.constants_buffer, 0, - 16 * 4, + std::mem::size_of::<Uniforms>() as u64, ); let mut i = 0; @@ -271,9 +274,34 @@ pub struct Quad { pub position: [f32; 2], pub scale: [f32; 2], pub color: [f32; 4], - pub border_radius: u32, + pub border_radius: f32, } impl Quad { const MAX: usize = 100_000; } + +#[repr(C)] +#[derive(Debug, Clone, Copy)] +struct Uniforms { + transform: [f32; 16], + scale: f32, +} + +impl Uniforms { + fn new(transformation: Transformation, scale: f32) -> Uniforms { + Self { + transform: *transformation.as_ref(), + scale, + } + } +} + +impl Default for Uniforms { + fn default() -> Self { + Self { + transform: *Transformation::identity().as_ref(), + scale: 1.0, + } + } +} diff --git a/wgpu/src/renderer.rs b/wgpu/src/renderer.rs index 060f07a3..f46acb8c 100644 --- a/wgpu/src/renderer.rs +++ b/wgpu/src/renderer.rs @@ -98,6 +98,7 @@ impl Renderer { log::debug!("Drawing"); let (width, height) = target.dimensions(); + let dpi = target.dpi(); let transformation = target.transformation(); let frame = target.next_frame(); @@ -137,7 +138,7 @@ impl Renderer { self.draw_overlay(overlay, &mut layers); for layer in layers { - self.flush(transformation, &layer, &mut encoder, &frame.view); + self.flush(dpi, transformation, &layer, &mut encoder, &frame.view); } self.queue.submit(&[encoder.finish()]); @@ -190,7 +191,10 @@ impl Renderer { layer.text.push(Section { text: &content, - screen_position: (x, y), + screen_position: ( + x - layer.offset.x as f32, + y - layer.offset.y as f32, + ), bounds: (bounds.width, bounds.height), scale: wgpu_glyph::Scale { x: *size, y: *size }, color: color.into_linear(), @@ -225,6 +229,7 @@ impl Renderer { background, border_radius, } => { + // TODO: Move some of this computations to the GPU (?) layer.quads.push(Quad { position: [ bounds.x - layer.offset.x as f32, @@ -234,7 +239,7 @@ impl Renderer { color: match background { Background::Color(color) => color.into_linear(), }, - border_radius: u32::from(*border_radius), + border_radius: *border_radius as f32, }); } Primitive::Image { path, bounds } => { @@ -308,16 +313,13 @@ impl Renderer { fn flush( &mut self, + dpi: f32, transformation: Transformation, layer: &Layer, encoder: &mut wgpu::CommandEncoder, target: &wgpu::TextureView, ) { - let translated = transformation - * Transformation::translate( - -(layer.offset.x as f32), - -(layer.offset.y as f32), - ); + let bounds = layer.bounds * dpi; if layer.quads.len() > 0 { self.quad_pipeline.draw( @@ -325,18 +327,26 @@ impl Renderer { encoder, &layer.quads, transformation, - layer.bounds, + dpi, + bounds, target, ); } if layer.images.len() > 0 { + let translated_and_scaled = transformation + * Transformation::scale(dpi, dpi) + * Transformation::translate( + -(layer.offset.x as f32), + -(layer.offset.y as f32), + ); + self.image_pipeline.draw( &mut self.device, encoder, &layer.images, - translated, - layer.bounds, + translated_and_scaled, + bounds, target, ); } @@ -345,6 +355,20 @@ impl Renderer { let mut glyph_brush = self.glyph_brush.borrow_mut(); for text in layer.text.iter() { + // Target physical coordinates directly to avoid blurry text + let text = Section { + screen_position: ( + text.screen_position.0 * dpi, + text.screen_position.1 * dpi, + ), + bounds: (text.bounds.0 * dpi, text.bounds.1 * dpi), + scale: wgpu_glyph::Scale { + x: text.scale.x * dpi, + y: text.scale.y * dpi, + }, + ..*text + }; + glyph_brush.queue(text); } @@ -353,12 +377,12 @@ impl Renderer { &mut self.device, encoder, target, - translated.into(), + transformation.into(), wgpu_glyph::Region { - x: layer.bounds.x, - y: layer.bounds.y, - width: layer.bounds.width, - height: layer.bounds.height, + x: bounds.x, + y: bounds.y, + width: bounds.width, + height: bounds.height, }, ) .expect("Draw text"); diff --git a/wgpu/src/renderer/target.rs b/wgpu/src/renderer/target.rs index d9d05bf0..eeeb629a 100644 --- a/wgpu/src/renderer/target.rs +++ b/wgpu/src/renderer/target.rs @@ -6,6 +6,7 @@ pub struct Target { surface: wgpu::Surface, width: u16, height: u16, + dpi: f32, transformation: Transformation, swap_chain: wgpu::SwapChain, } @@ -15,6 +16,10 @@ impl Target { (self.width, self.height) } + pub fn dpi(&self) -> f32 { + self.dpi + } + pub fn transformation(&self) -> Transformation { self.transformation } @@ -31,6 +36,7 @@ impl iced_native::renderer::Target for Target { window: &W, width: u16, height: u16, + dpi: f32, renderer: &Renderer, ) -> Target { let surface = wgpu::Surface::create(window); @@ -41,14 +47,22 @@ impl iced_native::renderer::Target for Target { surface, width, height, + dpi, transformation: Transformation::orthographic(width, height), swap_chain, } } - fn resize(&mut self, width: u16, height: u16, renderer: &Renderer) { + fn resize( + &mut self, + width: u16, + height: u16, + dpi: f32, + renderer: &Renderer, + ) { self.width = width; self.height = height; + self.dpi = dpi; self.transformation = Transformation::orthographic(width, height); self.swap_chain = new_swap_chain(&self.surface, width, height, &renderer.device); diff --git a/wgpu/src/renderer/widget/checkbox.rs b/wgpu/src/renderer/widget/checkbox.rs index ea7a4c0b..5867a36f 100644 --- a/wgpu/src/renderer/widget/checkbox.rs +++ b/wgpu/src/renderer/widget/checkbox.rs @@ -76,7 +76,7 @@ impl checkbox::Renderer for Renderer { a: 1.0, } }), - border_radius: 6, + border_radius: 5, }, ); diff --git a/wgpu/src/renderer/widget/text.rs b/wgpu/src/renderer/widget/text.rs index 82f75f09..29e07ff7 100644 --- a/wgpu/src/renderer/widget/text.rs +++ b/wgpu/src/renderer/widget/text.rs @@ -6,6 +6,9 @@ use wgpu_glyph::{GlyphCruncher, Section}; use std::cell::RefCell; use std::f32; +// TODO: Obtain from renderer configuration +const DEFAULT_TEXT_SIZE: f32 = 20.0; + impl text::Renderer for Renderer { fn node(&self, text: &Text) -> Node { let glyph_brush = self.glyph_brush.clone(); @@ -18,7 +21,7 @@ impl text::Renderer for Renderer { // I noticed that the first measure is the one that matters in // practice. Here, we use a RefCell to store the cached measurement. let measure = RefCell::new(None); - let size = text.size.map(f32::from).unwrap_or(20.0); + let size = text.size.map(f32::from).unwrap_or(DEFAULT_TEXT_SIZE); let style = Style::default().width(text.width); @@ -71,7 +74,7 @@ impl text::Renderer for Renderer { ( Primitive::Text { content: text.content.clone(), - size: f32::from(text.size.unwrap_or(20)), + size: text.size.map(f32::from).unwrap_or(DEFAULT_TEXT_SIZE), bounds: layout.bounds(), color: text.color.unwrap_or(Color::BLACK), horizontal_alignment: text.horizontal_alignment, diff --git a/wgpu/src/shader/quad.frag b/wgpu/src/shader/quad.frag index 849f581e..2ee77e71 100644 --- a/wgpu/src/shader/quad.frag +++ b/wgpu/src/shader/quad.frag @@ -3,7 +3,7 @@ layout(location = 0) in vec4 v_Color; layout(location = 1) in vec2 v_Pos; layout(location = 2) in vec2 v_Scale; -layout(location = 3) in flat uint v_BorderRadius; +layout(location = 3) in float v_BorderRadius; layout(location = 0) out vec4 o_Color; @@ -27,11 +27,7 @@ float rounded(in vec2 frag_coord, in vec2 position, in vec2 size, float radius, } void main() { - float radius_alpha = 1.0; - - if(v_BorderRadius > 0.0) { - radius_alpha = rounded(gl_FragCoord.xy, v_Pos, v_Scale, v_BorderRadius, 0.5); - } + float radius_alpha = rounded(gl_FragCoord.xy, v_Pos, v_Scale, v_BorderRadius, 0.5); o_Color = vec4(v_Color.xyz, v_Color.w * radius_alpha); } diff --git a/wgpu/src/shader/quad.frag.spv b/wgpu/src/shader/quad.frag.spv Binary files differindex 71b91b44..17bd8f46 100644 --- a/wgpu/src/shader/quad.frag.spv +++ b/wgpu/src/shader/quad.frag.spv diff --git a/wgpu/src/shader/quad.vert b/wgpu/src/shader/quad.vert index b7c5cf3e..539755cb 100644 --- a/wgpu/src/shader/quad.vert +++ b/wgpu/src/shader/quad.vert @@ -4,29 +4,33 @@ layout(location = 0) in vec2 v_Pos; layout(location = 1) in vec2 i_Pos; layout(location = 2) in vec2 i_Scale; layout(location = 3) in vec4 i_Color; -layout(location = 4) in uint i_BorderRadius; +layout(location = 4) in float i_BorderRadius; layout (set = 0, binding = 0) uniform Globals { mat4 u_Transform; + float u_Scale; }; layout(location = 0) out vec4 o_Color; layout(location = 1) out vec2 o_Pos; layout(location = 2) out vec2 o_Scale; -layout(location = 3) out uint o_BorderRadius; +layout(location = 3) out float o_BorderRadius; void main() { + vec2 p_Pos = i_Pos * u_Scale; + vec2 p_Scale = i_Scale * u_Scale; + mat4 i_Transform = mat4( - vec4(i_Scale.x, 0.0, 0.0, 0.0), - vec4(0.0, i_Scale.y, 0.0, 0.0), + vec4(p_Scale.x + 1.0, 0.0, 0.0, 0.0), + vec4(0.0, p_Scale.y + 1.0, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), - vec4(i_Pos, 0.0, 1.0) + vec4(p_Pos - vec2(0.5, 0.5), 0.0, 1.0) ); o_Color = i_Color; - o_Pos = i_Pos; - o_Scale = i_Scale; - o_BorderRadius = i_BorderRadius; + o_Pos = p_Pos; + o_Scale = p_Scale; + o_BorderRadius = i_BorderRadius * u_Scale; gl_Position = u_Transform * i_Transform * vec4(v_Pos, 0.0, 1.0); } diff --git a/wgpu/src/shader/quad.vert.spv b/wgpu/src/shader/quad.vert.spv Binary files differindex f62a160c..9050adfb 100644 --- a/wgpu/src/shader/quad.vert.spv +++ b/wgpu/src/shader/quad.vert.spv diff --git a/wgpu/src/transformation.rs b/wgpu/src/transformation.rs index b0d14cc8..c8a7ee75 100644 --- a/wgpu/src/transformation.rs +++ b/wgpu/src/transformation.rs @@ -26,6 +26,11 @@ impl Transformation { pub fn translate(x: f32, y: f32) -> Transformation { Transformation(Mat4::from_translation(Vec3::new(x, y, 0.0))) } + + /// Creates a scale transformation. + pub fn scale(x: f32, y: f32) -> Transformation { + Transformation(Mat4::from_scale(Vec3::new(x, y, 1.0))) + } } impl Mul for Transformation { |