Do scene building just-in-time on a per-outline basis as part of tiling

This commit is contained in:
Patrick Walton 2019-02-02 11:36:42 -08:00
parent f19757e4cf
commit b0e91369e5
3 changed files with 49 additions and 98 deletions

View File

@ -16,7 +16,7 @@ use pathfinder_geometry::transform3d::{Perspective, Transform3DF32};
use pathfinder_gl::renderer::Renderer;
use pathfinder_renderer::builder::SceneBuilder;
use pathfinder_renderer::gpu_data::BuiltScene;
use pathfinder_renderer::scene::Scene;
use pathfinder_renderer::scene::{BuildTransform, Scene};
use pathfinder_renderer::z_buffer::ZBuffer;
use pathfinder_svg::SceneExt;
use rayon::ThreadPoolBuilder;
@ -111,7 +111,6 @@ fn main() {
if !first_frame {
if let Ok(SceneToMainMsg::Render {
built_scene,
prepare_time,
tile_time
}) = scene_thread_proxy.receiver.recv() {
unsafe {
@ -120,7 +119,7 @@ fn main() {
renderer.render_scene(&built_scene);
let rendering_time = renderer.shift_timer_query();
renderer.debug_renderer.draw(prepare_time, tile_time, rendering_time);
renderer.debug_renderer.draw(tile_time, rendering_time);
}
}
}
@ -214,29 +213,10 @@ impl SceneThread {
match msg {
MainToSceneMsg::Exit => return,
MainToSceneMsg::Build(perspective) => {
// FIXME(pcwalton): Stop cloning scenes?
let mut start_time = Instant::now();
let mut scene = self.scene.clone();
match perspective {
Some(perspective) => {
match self.options.jobs {
Some(1) => scene.apply_perspective_sequentially(&perspective),
_ => scene.apply_perspective(&perspective),
}
}
None => scene.prepare(),
}
let prepare_time = Instant::now() - start_time;
start_time = Instant::now();
let built_scene = build_scene(&scene, &self.options);
let start_time = Instant::now();
let built_scene = build_scene(&self.scene, perspective, &self.options);
let tile_time = Instant::now() - start_time;
self.sender.send(SceneToMainMsg::Render {
built_scene,
prepare_time,
tile_time,
}).unwrap();
self.sender.send(SceneToMainMsg::Render { built_scene, tile_time }).unwrap();
}
}
}
@ -251,7 +231,6 @@ enum MainToSceneMsg {
enum SceneToMainMsg {
Render {
built_scene: BuiltScene,
prepare_time: Duration,
tile_time: Duration,
}
}
@ -324,13 +303,18 @@ fn load_scene(options: &Options, window_size: &Size2D<u32>) -> Scene {
scene
}
fn build_scene(scene: &Scene, options: &Options) -> BuiltScene {
fn build_scene(scene: &Scene, perspective: Option<Perspective>, options: &Options) -> BuiltScene {
let z_buffer = ZBuffer::new(&scene.view_box);
let build_transform = match perspective {
None => BuildTransform::None,
Some(perspective) => BuildTransform::Perspective(perspective),
};
let built_objects = panic::catch_unwind(|| {
match options.jobs {
Some(1) => scene.build_objects_sequentially(&z_buffer),
_ => scene.build_objects(&z_buffer),
Some(1) => scene.build_objects_sequentially(&build_transform, &z_buffer),
_ => scene.build_objects(&build_transform, &z_buffer),
}
});

View File

@ -31,7 +31,7 @@ const DEBUG_FONT_VERTEX_SIZE: GLint = 8;
const DEBUG_SOLID_VERTEX_SIZE: GLint = 4;
const WINDOW_WIDTH: i16 = 400;
const WINDOW_HEIGHT: i16 = LINE_HEIGHT * 3 + PADDING + 3;
const WINDOW_HEIGHT: i16 = LINE_HEIGHT * 2 + PADDING + 2;
const PADDING: i16 = 12;
const FONT_ASCENT: i16 = 28;
const LINE_HEIGHT: i16 = 42;
@ -112,26 +112,20 @@ impl DebugRenderer {
self.framebuffer_size = *window_size;
}
pub fn draw(&self,
prepare_time: Duration,
tile_time: Duration,
rendering_time: Option<Duration>) {
pub fn draw(&self, tile_time: Duration, rendering_time: Option<Duration>) {
let window_rect =
Rect::new(Point2D::new(self.framebuffer_size.width as i16 - PADDING - WINDOW_WIDTH,
self.framebuffer_size.height as i16 - PADDING - WINDOW_HEIGHT),
Size2D::new(WINDOW_WIDTH, WINDOW_HEIGHT));
self.draw_solid_rect(&window_rect, WINDOW_COLOR);
self.draw_text(&format!("Preparation: {:.3} ms", duration_ms(prepare_time)),
&Point2D::new(window_rect.origin.x + PADDING,
window_rect.origin.y + PADDING + FONT_ASCENT));
self.draw_text(&format!("Tiling: {:.3} ms", duration_ms(tile_time)),
&Point2D::new(window_rect.origin.x + PADDING,
window_rect.origin.y + PADDING + FONT_ASCENT + LINE_HEIGHT));
window_rect.origin.y + PADDING + FONT_ASCENT));
if let Some(rendering_time) = rendering_time {
self.draw_text(&format!("Rendering: {:.3} ms", duration_ms(rendering_time)),
&Point2D::new(
window_rect.origin.x + PADDING,
window_rect.origin.y + PADDING + FONT_ASCENT + LINE_HEIGHT * 2));
window_rect.origin.y + PADDING + FONT_ASCENT + LINE_HEIGHT));
}
}

View File

@ -21,8 +21,7 @@ use pathfinder_geometry::outline::Outline;
use pathfinder_geometry::point::{Point2DF32, Point3DF32};
use pathfinder_geometry::transform3d::Perspective;
use pathfinder_geometry::transform::Transform2DF32;
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator};
use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator};
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
use std::fmt::{self, Debug, Formatter};
#[derive(Clone)]
@ -67,13 +66,15 @@ impl Scene {
.collect()
}
pub fn build_objects_sequentially(&self, z_buffer: &ZBuffer) -> Vec<BuiltObject> {
pub fn build_objects_sequentially(&self, build_transform: &BuildTransform, z_buffer: &ZBuffer)
-> Vec<BuiltObject> {
self.objects
.iter()
.enumerate()
.map(|(object_index, object)| {
let outline = self.apply_build_transform(&object.outline, build_transform);
let mut tiler = Tiler::new(
&object.outline,
&outline,
&self.view_box,
object_index as u16,
ShaderId(object.paint.0),
@ -85,13 +86,15 @@ impl Scene {
.collect()
}
pub fn build_objects(&self, z_buffer: &ZBuffer) -> Vec<BuiltObject> {
pub fn build_objects(&self, build_transform: &BuildTransform, z_buffer: &ZBuffer)
-> Vec<BuiltObject> {
self.objects
.par_iter()
.enumerate()
.map(|(object_index, object)| {
let outline = self.apply_build_transform(&object.outline, build_transform);
let mut tiler = Tiler::new(
&object.outline,
&outline,
&self.view_box,
object_index as u16,
ShaderId(object.paint.0),
@ -103,34 +106,25 @@ impl Scene {
.collect()
}
fn update_bounds(&mut self) {
let mut bounds = Rect::zero();
for (object_index, object) in self.objects.iter_mut().enumerate() {
if object_index == 0 {
bounds = *object.outline.bounds();
} else {
bounds = bounds.union(object.outline.bounds());
fn apply_build_transform(&self, outline: &Outline, build_transform: &BuildTransform)
-> Outline {
// FIXME(pcwalton): Don't clone?
let mut outline = (*outline).clone();
match *build_transform {
BuildTransform::Perspective(ref perspective) => {
// FIXME(pcwalton): Do this only once!
let quad = self.apply_perspective_to_quad(perspective);
outline.clip_against_polygon(&quad);
outline.apply_perspective(perspective);
}
BuildTransform::Transform2D(ref transform) => {
outline.transform(transform);
}
self.bounds = bounds;
BuildTransform::None => {}
}
pub fn prepare(&mut self) {
for object in &mut self.objects {
object.outline.clip_against_rect(&self.view_box);
object.outline.make_monotonic();
}
}
pub fn transform(&mut self, transform: &Transform2DF32) {
for object in &mut self.objects {
object.outline.transform(transform);
object.outline.clip_against_rect(&self.view_box);
object.outline.make_monotonic();
}
self.update_bounds();
outline.clip_against_rect(&self.view_box);
outline.make_monotonic();
outline
}
fn apply_perspective_to_quad(&self, perspective: &Perspective) -> Vec<Point2DF32> {
@ -141,33 +135,6 @@ impl Scene {
.collect()
}
pub fn apply_perspective_sequentially(&mut self, perspective: &Perspective) {
let quad = self.apply_perspective_to_quad(perspective);
for object in &mut self.objects {
object.outline.clip_against_polygon(&quad);
object.outline.apply_perspective(perspective);
object.outline.clip_against_rect(&self.view_box);
object.outline.make_monotonic();
}
self.update_bounds();
}
pub fn apply_perspective(&mut self, perspective: &Perspective) {
let quad = self.apply_perspective_to_quad(perspective);
let view_box = &self.view_box;
self.objects.par_iter_mut().for_each(|object| {
object.outline.clip_against_polygon(&quad);
object.outline.apply_perspective(perspective);
object.outline.clip_against_rect(&view_box);
object.outline.make_monotonic();
});
self.update_bounds();
}
fn clip_bounding_quad_with_perspective(&self, perspective: &Perspective) -> Vec<Point3DF32> {
let mut points = vec![
Point3DF32::from_euclid_2d(&self.bounds.origin),
@ -245,3 +212,9 @@ pub fn scene_tile_index(tile_x: i16, tile_y: i16, tile_rect: Rect<i16>) -> u32 {
(tile_y - tile_rect.origin.y) as u32 * tile_rect.size.width as u32
+ (tile_x - tile_rect.origin.x) as u32
}
pub enum BuildTransform {
None,
Transform2D(Transform2DF32),
Perspective(Perspective),
}