Do scene building just-in-time on a per-outline basis as part of tiling
This commit is contained in:
parent
f19757e4cf
commit
b0e91369e5
|
@ -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),
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
BuildTransform::None => {}
|
||||
}
|
||||
|
||||
self.bounds = bounds;
|
||||
}
|
||||
|
||||
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),
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue