Speed up `lorem-ipsum`, especially in debug builds

This commit is contained in:
Patrick Walton 2017-02-28 21:47:17 -08:00
parent 45ade674be
commit 7862bec2bb
1 changed files with 66 additions and 94 deletions

View File

@ -35,6 +35,7 @@ use std::mem;
use std::os::raw::c_void; use std::os::raw::c_void;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::mpsc::Receiver; use std::sync::mpsc::Receiver;
use std::time::Instant;
const ATLAS_SIZE: u32 = 2048; const ATLAS_SIZE: u32 = 2048;
const WIDTH: u32 = 640; const WIDTH: u32 = 640;
@ -197,9 +198,8 @@ impl DemoApp {
println!("wrote screenshot to: {}", ATLAS_DUMP_FILENAME); println!("wrote screenshot to: {}", ATLAS_DUMP_FILENAME);
false false
} }
WindowEvent::Scroll(x, y) => { WindowEvent::Scroll(_, y) if self.window.get_key(Key::LeftAlt) == Action::Press ||
if self.window.get_key(Key::LeftAlt) == Action::Press || self.window.get_key(Key::RightAlt) == Action::Press => {
self.window.get_key(Key::RightAlt) == Action::Press {
let old_point_size = self.point_size; let old_point_size = self.point_size;
self.point_size = old_point_size + y as f32; self.point_size = old_point_size + y as f32;
@ -209,25 +209,19 @@ impl DemoApp {
self.point_size = MAX_POINT_SIZE self.point_size = MAX_POINT_SIZE
} }
let mut center = let offset = Point2D::new(self.device_pixel_size.width as f32,
Point2D::new(self.translation.x as f32 - self.device_pixel_size.height as f32);
self.device_pixel_size.width as f32 *
0.5,
self.translation.y as f32 -
self.device_pixel_size.height as f32 *
0.5);
center.x = center.x * self.point_size / old_point_size;
center.y = center.y * self.point_size / old_point_size;
self.translation.x = let center = self.translation.cast().unwrap() - offset * 0.5;
(center.x + self.device_pixel_size.width as f32 * 0.5).round() as i32;
self.translation.y = self.translation = (center * self.point_size / old_point_size +
(center.y + self.device_pixel_size.height as f32 * 0.5).round() as i32; offset * 0.5).round().cast().unwrap();
} else {
self.translation.x += (x * SCROLL_SPEED).round() as i32; true
self.translation.y += (y * SCROLL_SPEED).round() as i32;
} }
WindowEvent::Scroll(x, y) => {
let vector = Point2D::new(x, y) * SCROLL_SPEED.round();
self.translation = self.translation + vector.cast().unwrap();
true true
} }
WindowEvent::Size(_, _) | WindowEvent::FramebufferSize(_, _) => { WindowEvent::Size(_, _) | WindowEvent::FramebufferSize(_, _) => {
@ -604,30 +598,38 @@ impl Renderer {
scale, scale,
SUBPIXEL_GRANULARITY); SUBPIXEL_GRANULARITY);
let mut glyphs: Vec<_> = positioned_glyphs.iter().map(|positioned_glyph| { let mut glyphs = vec![];
(positioned_glyph.glyph_index, for positioned_glyph in &positioned_glyphs {
(positioned_glyph.subpixel_x / SUBPIXEL_GRANULARITY).round() as u8) if positioned_glyph.glyph_index as usize >= glyphs.len() {
}).collect(); glyphs.resize(positioned_glyph.glyph_index as usize + 1, 0)
}
glyphs.sort(); let subpixel = (positioned_glyph.subpixel_x / SUBPIXEL_GRANULARITY).round() as u8;
glyphs.dedup(); glyphs[positioned_glyph.glyph_index as usize] |= 1 << subpixel
}
let mut cached_glyphs = vec![];
for (glyph_index, &subpixels) in glyphs.iter().enumerate() {
for subpixel in 0..SUBPIXEL_GRANULARITY_COUNT {
if (subpixels & (1 << subpixel)) == 0 {
cached_glyphs.push(CachedGlyph(Point2D::zero()));
continue
}
let cached_glyphs = glyphs.iter().map(|&(glyph_index, subpixel)| {
let subpixel_offset = (subpixel as f32) / (SUBPIXEL_GRANULARITY as f32); let subpixel_offset = (subpixel as f32) / (SUBPIXEL_GRANULARITY as f32);
let origin = atlas_builder.pack_glyph(&glyph_store.outlines, let options = GlyphRasterizationOptions {
glyph_index,
&GlyphRasterizationOptions {
point_size: point_size, point_size: point_size,
horizontal_offset: subpixel_offset, horizontal_offset: subpixel_offset,
..GlyphRasterizationOptions::default() ..GlyphRasterizationOptions::default()
}).unwrap(); };
CachedGlyph {
x: origin.x, let origin = atlas_builder.pack_glyph(&glyph_store.outlines,
y: origin.y, glyph_index as u16,
glyph_index: glyph_index, &options).unwrap();
subpixel: subpixel,
cached_glyphs.push(CachedGlyph(origin));
}
} }
}).collect();
(positioned_glyphs, cached_glyphs) (positioned_glyphs, cached_glyphs)
} }
@ -710,13 +712,11 @@ impl Renderer {
let glyph_rect_i = glyph_rect.round_out(); let glyph_rect_i = glyph_rect.round_out();
let glyph_size_i = glyph_rect_i.size(); let glyph_size_i = glyph_rect_i.size();
let cached_glyph_index = cached_glyphs.binary_search_by(|cached_glyph| { let cached_glyph_index = glyph_index as usize * SUBPIXEL_GRANULARITY_COUNT as usize +
(cached_glyph.glyph_index, cached_glyph.subpixel).cmp(&(glyph_index, subpixel)) subpixel as usize;
}).expect("Didn't cache the glyph properly!");
let cached_glyph = cached_glyphs[cached_glyph_index]; let cached_glyph = cached_glyphs[cached_glyph_index];
let uv_tl: Point2D<u32> = Point2D::new(cached_glyph.x, let uv_tl: Point2D<u32> = cached_glyph.0.floor().cast().unwrap();
cached_glyph.y).floor().cast().unwrap();
let uv_br = uv_tl + glyph_size_i.cast().unwrap(); let uv_br = uv_tl + glyph_size_i.cast().unwrap();
let left_pos = positioned_glyph.bounds.origin.x; let left_pos = positioned_glyph.bounds.origin.x;
@ -808,27 +808,14 @@ impl Renderer {
let mut fps_atlas_builder = AtlasBuilder::new(&atlas_options); let mut fps_atlas_builder = AtlasBuilder::new(&atlas_options);
let mut fps_glyphs = vec![]; let (fps_positioned_glyphs, fps_cached_glyphs) =
for &fps_glyph_index in &fps_glyph_store.all_glyph_indices { self.determine_visible_glyphs(&mut fps_atlas_builder,
for subpixel in 0..SUBPIXEL_GRANULARITY_COUNT { font,
let subpixel_increment = SUBPIXEL_GRANULARITY * subpixel as f32; fps_glyph_store,
let options = GlyphRasterizationOptions { &fps_typesetter,
point_size: FPS_DISPLAY_POINT_SIZE, device_pixel_size,
horizontal_offset: subpixel_increment, &Point2D::zero(),
..GlyphRasterizationOptions::default() FPS_DISPLAY_POINT_SIZE);
};
let origin = fps_atlas_builder.pack_glyph(&fps_glyph_store.outlines,
fps_glyph_index,
&options).unwrap();
fps_glyphs.push(CachedGlyph {
x: origin.x,
y: origin.y,
glyph_index: fps_glyph_index,
subpixel: subpixel,
})
}
}
let fps_atlas = fps_atlas_builder.create_atlas().unwrap(); let fps_atlas = fps_atlas_builder.create_atlas().unwrap();
let rect = Rect::new(Point2D::new(0, 0), self.atlas_size); let rect = Rect::new(Point2D::new(0, 0), self.atlas_size);
@ -846,20 +833,10 @@ impl Renderer {
let fps_left = FPS_PADDING; let fps_left = FPS_PADDING;
let fps_top = device_pixel_size.height as i32 - FPS_PADDING - fps_line_spacing; let fps_top = device_pixel_size.height as i32 - FPS_PADDING - fps_line_spacing;
let fps_viewport = Rect::new(Point2D::zero(), device_pixel_size.cast().unwrap());
let fps_scale = FPS_DISPLAY_POINT_SIZE / font.units_per_em() as f32;
let fps_positioned_glyphs =
fps_typesetter.positioned_glyphs_in_rect(&fps_viewport,
fps_glyph_store,
font.units_per_em() as f32,
fps_scale,
SUBPIXEL_GRANULARITY);
self.draw_glyphs(&fps_glyph_store, self.draw_glyphs(&fps_glyph_store,
&self.fps_composite_vertex_array, &self.fps_composite_vertex_array,
&fps_positioned_glyphs, &fps_positioned_glyphs,
&fps_glyphs, &fps_cached_glyphs,
device_pixel_size, device_pixel_size,
&Point2D::new(fps_left, fps_top), &Point2D::new(fps_left, fps_top),
self.fps_gl_texture, self.fps_gl_texture,
@ -920,12 +897,7 @@ impl Vertex {
} }
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
struct CachedGlyph { struct CachedGlyph(Point2D<f32>);
x: f32,
y: f32,
glyph_index: u16,
subpixel: u8,
}
#[derive(Debug)] #[derive(Debug)]
struct CompositeVertexArray { struct CompositeVertexArray {