From 195374c716cfb9796aa379b3642ffbffc74b5c58 Mon Sep 17 00:00:00 2001 From: grovesNL Date: Mon, 9 May 2022 11:52:38 -0230 Subject: [PATCH] Pack attributes slightly --- examples/hello-world.rs | 10 ++++--- src/lib.rs | 61 +++++++++++++++++++++-------------------- src/shader.wgsl | 41 ++++++++++++++++----------- 3 files changed, 62 insertions(+), 50 deletions(-) diff --git a/examples/hello-world.rs b/examples/hello-world.rs index 00ca933..b31eac3 100644 --- a/examples/hello-world.rs +++ b/examples/hello-world.rs @@ -1,12 +1,14 @@ -use fontdue::{ - layout::{CoordinateSystem, Layout, LayoutSettings, TextStyle}, - Font, FontSettings, +use glyphon::{ + fontdue::{ + layout::{CoordinateSystem, Layout, LayoutSettings, TextStyle}, + Font, FontSettings, + }, + Resolution, TextRenderer, }; use wgpu::{ Color, CommandEncoderDescriptor, LoadOp, Operations, RenderPassColorAttachment, RenderPassDescriptor, TextureViewDescriptor, }; -use glyphon::{Resolution, TextRenderer}; use winit::{ event::{Event, WindowEvent}, event_loop::{ControlFlow, EventLoop}, diff --git a/src/lib.rs b/src/lib.rs index ad6fce0..31ace64 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,8 @@ use std::{ collections::{HashMap, HashSet}, error::Error, fmt::{self, Display, Formatter}, - iter, mem, + iter, + mem::size_of, num::{NonZeroU32, NonZeroU64}, slice, }; @@ -25,6 +26,8 @@ use wgpu::{ TextureViewDimension, VertexFormat, VertexState, }; +pub use fontdue; + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum PrepareError { AtlasFull, @@ -53,8 +56,8 @@ enum GpuCache { } struct GlyphDetails { - width: u32, - height: u32, + width: u16, + height: u16, gpu_cache: GpuCache, atlas_id: Option, } @@ -62,12 +65,9 @@ struct GlyphDetails { #[repr(C)] #[derive(Clone, Copy, Debug)] struct GlyphToRender { - x: f32, - y: f32, - width: f32, - height: f32, - atlas_x: f32, - atlas_y: f32, + pos: [u32; 2], + dim: [u16; 2], + uv: [u16; 2], color: [u8; 4], } @@ -186,24 +186,29 @@ impl TextRenderer { }); let vertex_buffers = [wgpu::VertexBufferLayout { - array_stride: mem::size_of::() as wgpu::BufferAddress, + array_stride: size_of::() as wgpu::BufferAddress, step_mode: wgpu::VertexStepMode::Vertex, attributes: &[ wgpu::VertexAttribute { - format: VertexFormat::Float32x4, + format: VertexFormat::Uint32x2, offset: 0, shader_location: 0, }, wgpu::VertexAttribute { - format: VertexFormat::Float32x2, - offset: mem::size_of::() as u64 * 4, + format: VertexFormat::Uint32, + offset: size_of::() as u64 * 2, shader_location: 1, }, wgpu::VertexAttribute { format: VertexFormat::Uint32, - offset: mem::size_of::() as u64 * 6, + offset: size_of::() as u64 * 3, shader_location: 2, }, + wgpu::VertexAttribute { + format: VertexFormat::Uint32, + offset: size_of::() as u64 * 4, + shader_location: 3, + }, ], }]; @@ -215,7 +220,7 @@ impl TextRenderer { ty: BindingType::Buffer { ty: BufferBindingType::Uniform, has_dynamic_offset: false, - min_binding_size: NonZeroU64::new(mem::size_of::() as u64), + min_binding_size: NonZeroU64::new(size_of::() as u64), }, count: None, }, @@ -242,10 +247,7 @@ impl TextRenderer { let params = Params { screen_resolution }; let params_raw = unsafe { - slice::from_raw_parts( - ¶ms as *const Params as *const u8, - mem::size_of::(), - ) + slice::from_raw_parts(¶ms as *const Params as *const u8, size_of::()) }; let params_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { @@ -354,7 +356,7 @@ impl TextRenderer { queue.write_buffer(&self.params_buffer, 0, unsafe { slice::from_raw_parts( &self.params as *const Params as *const u8, - mem::size_of::(), + size_of::(), ) }); } @@ -432,8 +434,8 @@ impl TextRenderer { self.glyph_cache.insert( glyph.key, GlyphDetails { - width: metrics.width as u32, - height: metrics.height as u32, + width: metrics.width as u16, + height: metrics.height as u16, gpu_cache, atlas_id, }, @@ -481,12 +483,11 @@ impl TextRenderer { glyph_vertices.extend( iter::repeat(GlyphToRender { - x: glyph.x, - y: glyph.y, - width: details.width as f32, - height: details.height as f32, - atlas_x: atlas_x as f32, - atlas_y: atlas_y as f32, + // Note: subpixel positioning is not currently handled, so we always use + // the nearest pixel. + pos: [glyph.x.round() as u32, glyph.y.round() as u32], + dim: [details.width, details.height], + uv: [atlas_x, atlas_y], color: [255, 255, 0, 255], }) .take(4), @@ -511,7 +512,7 @@ impl TextRenderer { let vertices_raw = unsafe { slice::from_raw_parts( vertices as *const _ as *const u8, - mem::size_of::() * vertices.len(), + size_of::() * vertices.len(), ) }; @@ -531,7 +532,7 @@ impl TextRenderer { let indices_raw = unsafe { slice::from_raw_parts( indices as *const _ as *const u8, - mem::size_of::() * indices.len(), + size_of::() * indices.len(), ) }; diff --git a/src/shader.wgsl b/src/shader.wgsl index b1b21b4..7446f03 100644 --- a/src/shader.wgsl +++ b/src/shader.wgsl @@ -1,7 +1,15 @@ +struct VertexInput { + @builtin(vertex_index) vertex_idx: u32, + @location(0) pos: vec2, + @location(1) dim: u32, + @location(2) uv: u32, + @location(3) color: u32, +} + struct VertexOutput { @builtin(position) position: vec4, @location(0) color: vec4, - @location(1) tex_coords: vec2, + @location(1) uv: vec2, }; struct Params { @@ -18,17 +26,15 @@ var atlas_texture: texture_2d; var atlas_sampler: sampler; @vertex -fn vs_main(@builtin(vertex_index) vertex_idx: u32, @location(0) in_vert: vec4, @location(1) tex_coords: vec2, @location(2) color: u32) -> VertexOutput { - let width = in_vert.z; - let height = in_vert.w; - - let v = vertex_idx % 4u; - var pos = in_vert.xy; - var uv = tex_coords; +fn vs_main(in_vert: VertexInput) -> VertexOutput { + var pos = in_vert.pos; + let width = in_vert.dim & 0xffffu; + let height = (in_vert.dim & 0xffff0000u) >> 16u; + let color = in_vert.color; + var uv = vec2(in_vert.uv & 0xffffu, (in_vert.uv & 0xffff0000u) >> 16u); + let v = in_vert.vertex_idx % 4u; switch v { - case 0u: { - } case 1u: { pos.x += width; uv.x += width; @@ -46,12 +52,15 @@ fn vs_main(@builtin(vertex_index) vertex_idx: u32, @location(0) in_vert: vec4(params.screen_resolution) - 1.0; - pos.y *= -1.0; - var vert_output: VertexOutput; - vert_output.position = vec4(pos.xy, 0.0, 1.0); + vert_output.position = vec4( + 2.0 * vec2(pos) / vec2(params.screen_resolution) - 1.0, + 0.0, + 1.0, + ); + + vert_output.position.y *= -1.0; vert_output.color = vec4( f32((color & 0xffu)), @@ -60,12 +69,12 @@ fn vs_main(@builtin(vertex_index) vertex_idx: u32, @location(0) in_vert: vec4> 24u), ) / 255.0; - vert_output.tex_coords = uv / vec2(textureDimensions(atlas_texture).xy); + vert_output.uv = vec2(uv) / vec2(textureDimensions(atlas_texture).xy); return vert_output; } @fragment fn fs_main(in_frag: VertexOutput) -> @location(0) vec4 { - return in_frag.color * textureSample(atlas_texture, atlas_sampler, in_frag.tex_coords).x; + return in_frag.color * textureSample(atlas_texture, atlas_sampler, in_frag.uv).x; }