Reenable the tile and fill counts in the debug display

This commit is contained in:
Patrick Walton 2019-04-18 15:09:37 -07:00
parent cb9fe3edf2
commit 62a3fefca4
7 changed files with 106 additions and 113 deletions

View File

@ -26,10 +26,10 @@ use pathfinder_gpu::resources::ResourceLoader;
use pathfinder_gpu::{DepthFunc, DepthState, Device, Primitive, RenderState, StencilFunc}; use pathfinder_gpu::{DepthFunc, DepthState, Device, Primitive, RenderState, StencilFunc};
use pathfinder_gpu::{StencilState, UniformData}; use pathfinder_gpu::{StencilState, UniformData};
use pathfinder_renderer::builder::{RenderOptions, RenderTransform, SceneBuilder}; use pathfinder_renderer::builder::{RenderOptions, RenderTransform, SceneBuilder};
use pathfinder_renderer::gpu::renderer::{RenderMode, Renderer}; use pathfinder_renderer::gpu::renderer::{RenderMode, RenderStats, Renderer};
use pathfinder_renderer::gpu_data::{BuiltScene, RenderCommand, Stats}; use pathfinder_renderer::gpu_data::RenderCommand;
use pathfinder_renderer::post::{DEFRINGING_KERNEL_CORE_GRAPHICS, STEM_DARKENING_FACTORS}; use pathfinder_renderer::post::{DEFRINGING_KERNEL_CORE_GRAPHICS, STEM_DARKENING_FACTORS};
use pathfinder_renderer::scene::Scene; use pathfinder_renderer::scene::{Scene, SceneDescriptor};
use pathfinder_svg::BuiltSVG; use pathfinder_svg::BuiltSVG;
use pathfinder_ui::{MousePosition, UIEvent}; use pathfinder_ui::{MousePosition, UIEvent};
use rayon::ThreadPoolBuilder; use rayon::ThreadPoolBuilder;
@ -413,7 +413,7 @@ impl<W> DemoApp<W> where W: Window {
} }
if !frame.scene_stats.is_empty() || !frame.scene_rendering_times.is_empty() { if !frame.scene_stats.is_empty() || !frame.scene_rendering_times.is_empty() {
let zero = Stats::default(); let zero = RenderStats::default();
let aggregate_stats = frame.scene_stats.iter().fold(zero, |sum, item| sum + *item); let aggregate_stats = frame.scene_stats.iter().fold(zero, |sum, item| sum + *item);
let total_rendering_time = if frame.scene_rendering_times.is_empty() { let total_rendering_time = if frame.scene_rendering_times.is_empty() {
None None
@ -557,8 +557,6 @@ impl<W> DemoApp<W> where W: Window {
_ => panic!("Expected `BeginRenderScene`!"), _ => panic!("Expected `BeginRenderScene`!"),
}; };
self.current_frame.as_mut().unwrap().scene_stats.push(built_scene.stats());
match self.monochrome_scene_color { match self.monochrome_scene_color {
None => self.renderer.set_render_mode(RenderMode::Multicolor), None => self.renderer.set_render_mode(RenderMode::Multicolor),
Some(fg_color) => { Some(fg_color) => {
@ -592,6 +590,7 @@ impl<W> DemoApp<W> where W: Window {
} }
} }
self.current_frame.as_mut().unwrap().scene_stats.push(self.renderer.stats);
self.renderer.end_scene(); self.renderer.end_scene();
} }
@ -742,7 +741,7 @@ struct BuildOptions {
enum SceneToMainMsg { enum SceneToMainMsg {
BeginFrame { transforms: Vec<RenderTransform> }, BeginFrame { transforms: Vec<RenderTransform> },
EndFrame { tile_time: Duration }, EndFrame { tile_time: Duration },
BeginRenderScene(BuiltScene), BeginRenderScene(SceneDescriptor),
Execute(RenderCommand), Execute(RenderCommand),
EndRenderScene, EndRenderScene,
} }
@ -779,11 +778,7 @@ fn build_scene(scene: &Scene,
}; };
let built_options = render_options.prepare(scene.bounds); let built_options = render_options.prepare(scene.bounds);
let quad = built_options.quad(); sink.send(SceneToMainMsg::BeginRenderScene(scene.build_descriptor(&built_options))).unwrap();
let mut built_scene = BuiltScene::new(scene.view_box, &quad, scene.objects.len() as u32);
built_scene.shaders = scene.build_shaders();
sink.send(SceneToMainMsg::BeginRenderScene(built_scene)).unwrap();
let inner_sink = AssertUnwindSafe(sink.clone()); let inner_sink = AssertUnwindSafe(sink.clone());
let result = panic::catch_unwind(move || { let result = panic::catch_unwind(move || {
@ -1086,7 +1081,7 @@ struct Frame {
transforms: Vec<RenderTransform>, transforms: Vec<RenderTransform>,
ui_events: Vec<UIEvent>, ui_events: Vec<UIEvent>,
scene_rendering_times: Vec<Duration>, scene_rendering_times: Vec<Duration>,
scene_stats: Vec<Stats>, scene_stats: Vec<RenderStats>,
} }
impl Frame { impl Frame {

View File

@ -10,8 +10,7 @@
//! An OpenGL implementation of the device abstraction. //! An OpenGL implementation of the device abstraction.
use gl::types::{GLboolean, GLchar, GLenum, GLfloat, GLint, GLintptr, GLsizei, GLsizeiptr}; use gl::types::{GLboolean, GLchar, GLenum, GLfloat, GLint, GLsizei, GLsizeiptr, GLuint, GLvoid};
use gl::types::{GLuint, GLvoid};
use pathfinder_geometry::basic::point::Point2DI32; use pathfinder_geometry::basic::point::Point2DI32;
use pathfinder_geometry::basic::rect::RectI32; use pathfinder_geometry::basic::rect::RectI32;
use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, DepthFunc, Device}; use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, DepthFunc, Device};

View File

@ -66,7 +66,7 @@ impl<'a> SceneBuilder<'a> {
&self.scene) &self.scene)
}).collect(); }).collect();
self.finish_building(alpha_tiles); self.finish_building(alpha_tiles)
} }
pub fn build_in_parallel(&mut self) { pub fn build_in_parallel(&mut self) {
@ -79,7 +79,7 @@ impl<'a> SceneBuilder<'a> {
&self.scene) &self.scene)
}).collect(); }).collect();
self.finish_building(alpha_tiles); self.finish_building(alpha_tiles)
} }
fn build_object(&self, fn build_object(&self,
@ -219,7 +219,7 @@ pub struct PreparedRenderOptions {
impl PreparedRenderOptions { impl PreparedRenderOptions {
#[inline] #[inline]
pub fn quad(&self) -> [Point3DF32; 4] { pub fn bounding_quad(&self) -> [Point3DF32; 4] {
match self.transform { match self.transform {
PreparedRenderTransform::Perspective { quad, .. } => quad, PreparedRenderTransform::Perspective { quad, .. } => quad,
_ => [Point3DF32::default(); 4], _ => [Point3DF32::default(); 4],
@ -247,3 +247,9 @@ impl<F> RenderCommandListener for F where F: Fn(RenderCommand) + Send + Sync {
#[inline] #[inline]
fn send(&self, command: RenderCommand) { (*self)(command) } fn send(&self, command: RenderCommand) { (*self)(command) }
} }
#[derive(Clone, Copy, Debug, Default)]
pub struct TileStats {
pub solid_tile_count: u32,
pub alpha_tile_count: u32,
}

View File

@ -15,7 +15,7 @@
//! //!
//! The debug font atlas was generated using: https://evanw.github.io/font-texture-generator/ //! The debug font atlas was generated using: https://evanw.github.io/font-texture-generator/
use crate::gpu_data::Stats; use crate::gpu::renderer::RenderStats;
use pathfinder_geometry::basic::point::Point2DI32; use pathfinder_geometry::basic::point::Point2DI32;
use pathfinder_geometry::basic::rect::RectI32; use pathfinder_geometry::basic::rect::RectI32;
use pathfinder_gpu::Device; use pathfinder_gpu::Device;
@ -45,7 +45,7 @@ impl<D> DebugUI<D> where D: Device {
} }
pub fn add_sample(&mut self, pub fn add_sample(&mut self,
stats: Stats, stats: RenderStats,
tile_time: Duration, tile_time: Duration,
rendering_time: Option<Duration>) { rendering_time: Option<Duration>) {
self.cpu_samples.push(CPUSample { stats, elapsed: tile_time }); self.cpu_samples.push(CPUSample { stats, elapsed: tile_time });
@ -96,11 +96,11 @@ impl<D> DebugUI<D> where D: Device {
} }
} }
struct SampleBuffer<S> where S: Add<S, Output=S> + Div<u32, Output=S> + Clone + Default { struct SampleBuffer<S> where S: Add<S, Output=S> + Div<usize, Output=S> + Clone + Default {
samples: VecDeque<S>, samples: VecDeque<S>,
} }
impl<S> SampleBuffer<S> where S: Add<S, Output=S> + Div<u32, Output=S> + Clone + Default { impl<S> SampleBuffer<S> where S: Add<S, Output=S> + Div<usize, Output=S> + Clone + Default {
fn new() -> SampleBuffer<S> { fn new() -> SampleBuffer<S> {
SampleBuffer { samples: VecDeque::with_capacity(SAMPLE_BUFFER_SIZE) } SampleBuffer { samples: VecDeque::with_capacity(SAMPLE_BUFFER_SIZE) }
} }
@ -122,43 +122,27 @@ impl<S> SampleBuffer<S> where S: Add<S, Output=S> + Div<u32, Output=S> + Clone +
mean = mean + (*time).clone(); mean = mean + (*time).clone();
} }
mean / self.samples.len() as u32 mean / self.samples.len()
} }
} }
#[derive(Clone, Default)] #[derive(Clone, Default)]
struct CPUSample { struct CPUSample {
elapsed: Duration, elapsed: Duration,
stats: Stats, stats: RenderStats,
} }
impl Add<CPUSample> for CPUSample { impl Add<CPUSample> for CPUSample {
type Output = CPUSample; type Output = CPUSample;
fn add(self, other: CPUSample) -> CPUSample { fn add(self, other: CPUSample) -> CPUSample {
CPUSample { CPUSample { elapsed: self.elapsed + other.elapsed, stats: self.stats + other.stats }
elapsed: self.elapsed + other.elapsed,
stats: Stats {
object_count: self.stats.object_count + other.stats.object_count,
solid_tile_count: self.stats.solid_tile_count + other.stats.solid_tile_count,
alpha_tile_count: self.stats.alpha_tile_count + other.stats.alpha_tile_count,
fill_count: self.stats.fill_count + other.stats.fill_count,
},
}
} }
} }
impl Div<u32> for CPUSample { impl Div<usize> for CPUSample {
type Output = CPUSample; type Output = CPUSample;
fn div(self, divisor: u32) -> CPUSample { fn div(self, divisor: usize) -> CPUSample {
CPUSample { CPUSample { elapsed: self.elapsed / (divisor as u32), stats: self.stats / divisor }
elapsed: self.elapsed / divisor,
stats: Stats {
object_count: self.stats.object_count / divisor,
solid_tile_count: self.stats.solid_tile_count / divisor,
alpha_tile_count: self.stats.alpha_tile_count / divisor,
fill_count: self.stats.fill_count / divisor,
},
}
} }
} }
@ -174,10 +158,10 @@ impl Add<GPUSample> for GPUSample {
} }
} }
impl Div<u32> for GPUSample { impl Div<usize> for GPUSample {
type Output = GPUSample; type Output = GPUSample;
fn div(self, divisor: u32) -> GPUSample { fn div(self, divisor: usize) -> GPUSample {
GPUSample { elapsed: self.elapsed / divisor } GPUSample { elapsed: self.elapsed / (divisor as u32) }
} }
} }

View File

@ -9,10 +9,10 @@
// except according to those terms. // except according to those terms.
use crate::gpu::debug::DebugUI; use crate::gpu::debug::DebugUI;
use crate::gpu_data::{AlphaTileBatchPrimitive, BuiltScene, FillBatchPrimitive}; use crate::gpu_data::{AlphaTileBatchPrimitive, FillBatchPrimitive};
use crate::gpu_data::{RenderCommand, SolidTileBatchPrimitive}; use crate::gpu_data::{RenderCommand, SolidTileBatchPrimitive};
use crate::post::DefringingKernel; use crate::post::DefringingKernel;
use crate::scene::ObjectShader; use crate::scene::{ObjectShader, SceneDescriptor};
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH}; use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
use pathfinder_geometry::basic::point::{Point2DI32, Point3DF32}; use pathfinder_geometry::basic::point::{Point2DI32, Point3DF32};
use pathfinder_geometry::basic::rect::RectI32; use pathfinder_geometry::basic::rect::RectI32;
@ -24,6 +24,7 @@ use pathfinder_gpu::{TextureFormat, UniformData, VertexAttrType};
use pathfinder_simd::default::{F32x4, I32x4}; use pathfinder_simd::default::{F32x4, I32x4};
use std::cmp; use std::cmp;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::ops::{Add, Div};
use std::time::Duration; use std::time::Duration;
use std::u32; use std::u32;
@ -73,7 +74,12 @@ pub struct Renderer<D> where D: Device {
stencil_program: StencilProgram<D>, stencil_program: StencilProgram<D>,
stencil_vertex_array: StencilVertexArray<D>, stencil_vertex_array: StencilVertexArray<D>,
// Rendering state
mask_framebuffer_cleared: bool,
buffered_fills: Vec<FillBatchPrimitive>,
// Debug // Debug
pub stats: RenderStats,
current_timer_query: Option<D::TimerQuery>, current_timer_query: Option<D::TimerQuery>,
pending_timer_queries: VecDeque<D::TimerQuery>, pending_timer_queries: VecDeque<D::TimerQuery>,
free_timer_queries: Vec<D::TimerQuery>, free_timer_queries: Vec<D::TimerQuery>,
@ -83,10 +89,6 @@ pub struct Renderer<D> where D: Device {
viewport: RectI32, viewport: RectI32,
render_mode: RenderMode, render_mode: RenderMode,
use_depth: bool, use_depth: bool,
// Rendering state
mask_framebuffer_cleared: bool,
buffered_fills: Vec<FillBatchPrimitive>,
} }
impl<D> Renderer<D> where D: Device { impl<D> Renderer<D> where D: Device {
@ -175,22 +177,22 @@ impl<D> Renderer<D> where D: Device {
stencil_program, stencil_program,
stencil_vertex_array, stencil_vertex_array,
stats: RenderStats::default(),
current_timer_query: None, current_timer_query: None,
pending_timer_queries: VecDeque::new(), pending_timer_queries: VecDeque::new(),
free_timer_queries: vec![], free_timer_queries: vec![],
debug_ui, debug_ui,
mask_framebuffer_cleared: false,
buffered_fills: vec![],
viewport, viewport,
render_mode: RenderMode::default(), render_mode: RenderMode::default(),
use_depth: false, use_depth: false,
mask_framebuffer_cleared: false,
buffered_fills: vec![],
} }
} }
pub fn begin_scene(&mut self, built_scene: &BuiltScene) { pub fn begin_scene(&mut self, scene: &SceneDescriptor) {
self.init_postprocessing_framebuffer(); self.init_postprocessing_framebuffer();
let timer_query = self.free_timer_queries let timer_query = self.free_timer_queries
@ -199,13 +201,15 @@ impl<D> Renderer<D> where D: Device {
self.device.begin_timer_query(&timer_query); self.device.begin_timer_query(&timer_query);
self.current_timer_query = Some(timer_query); self.current_timer_query = Some(timer_query);
self.upload_shaders(&built_scene.shaders); self.upload_shaders(&scene.shaders);
if self.use_depth { if self.use_depth {
self.draw_stencil(&built_scene.quad); self.draw_stencil(&scene.bounding_quad);
} }
self.mask_framebuffer_cleared = false; self.mask_framebuffer_cleared = false;
self.stats = RenderStats { object_count: scene.object_count, ..RenderStats::default() };
} }
pub fn render_command(&mut self, command: &RenderCommand) { pub fn render_command(&mut self, command: &RenderCommand) {
@ -213,14 +217,16 @@ impl<D> Renderer<D> where D: Device {
RenderCommand::AddFills(ref fills) => self.add_fills(fills), RenderCommand::AddFills(ref fills) => self.add_fills(fills),
RenderCommand::FlushFills => self.draw_buffered_fills(), RenderCommand::FlushFills => self.draw_buffered_fills(),
RenderCommand::SolidTile(ref solid_tiles) => { RenderCommand::SolidTile(ref solid_tiles) => {
let count = solid_tiles.len() as u32; let count = solid_tiles.len();
self.stats.solid_tile_count += count;
self.upload_solid_tiles(solid_tiles); self.upload_solid_tiles(solid_tiles);
self.draw_solid_tiles(count); self.draw_solid_tiles(count as u32);
} }
RenderCommand::AlphaTile(ref alpha_tiles) => { RenderCommand::AlphaTile(ref alpha_tiles) => {
let count = alpha_tiles.len() as u32; let count = alpha_tiles.len();
self.stats.alpha_tile_count += count;
self.upload_alpha_tiles(alpha_tiles); self.upload_alpha_tiles(alpha_tiles);
self.draw_alpha_tiles(count); self.draw_alpha_tiles(count as u32);
} }
} }
} }
@ -319,6 +325,8 @@ impl<D> Renderer<D> where D: Device {
return; return;
} }
self.stats.fill_count += fills.len();
while !fills.is_empty() { while !fills.is_empty() {
let count = cmp::min(fills.len(), MAX_FILLS_PER_BATCH - self.buffered_fills.len()); let count = cmp::min(fills.len(), MAX_FILLS_PER_BATCH - self.buffered_fills.len());
self.buffered_fills.extend_from_slice(&fills[0..count]); self.buffered_fills.extend_from_slice(&fills[0..count]);
@ -1088,3 +1096,35 @@ impl Default for RenderMode {
RenderMode::Multicolor RenderMode::Multicolor
} }
} }
#[derive(Clone, Copy, Debug, Default)]
pub struct RenderStats {
pub object_count: usize,
pub fill_count: usize,
pub alpha_tile_count: usize,
pub solid_tile_count: usize,
}
impl Add<RenderStats> for RenderStats {
type Output = RenderStats;
fn add(self, other: RenderStats) -> RenderStats {
RenderStats {
object_count: self.object_count + other.object_count,
solid_tile_count: self.solid_tile_count + other.solid_tile_count,
alpha_tile_count: self.alpha_tile_count + other.alpha_tile_count,
fill_count: self.fill_count + other.fill_count,
}
}
}
impl Div<usize> for RenderStats {
type Output = RenderStats;
fn div(self, divisor: usize) -> RenderStats {
RenderStats {
object_count: self.object_count / divisor,
solid_tile_count: self.solid_tile_count / divisor,
alpha_tile_count: self.alpha_tile_count / divisor,
fill_count: self.fill_count / divisor,
}
}
}

View File

@ -11,16 +11,14 @@
//! Packed data ready to be sent to the GPU. //! Packed data ready to be sent to the GPU.
use crate::builder::SceneBuilder; use crate::builder::SceneBuilder;
use crate::scene::ObjectShader;
use crate::tile_map::DenseTileMap; use crate::tile_map::DenseTileMap;
use crate::tiles::{self, TILE_HEIGHT, TILE_WIDTH}; use crate::tiles::{self, TILE_HEIGHT, TILE_WIDTH};
use pathfinder_geometry::basic::line_segment::{LineSegmentF32, LineSegmentU4, LineSegmentU8}; use pathfinder_geometry::basic::line_segment::{LineSegmentF32, LineSegmentU4, LineSegmentU8};
use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32, Point3DF32}; use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32};
use pathfinder_geometry::basic::rect::{RectF32, RectI32}; use pathfinder_geometry::basic::rect::{RectF32, RectI32};
use pathfinder_geometry::util; use pathfinder_geometry::util;
use pathfinder_simd::default::{F32x4, I32x4}; use pathfinder_simd::default::{F32x4, I32x4};
use std::fmt::{Debug, Formatter, Result as DebugResult}; use std::fmt::{Debug, Formatter, Result as DebugResult};
use std::ops::Add;
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
#[derive(Debug)] #[derive(Debug)]
@ -31,14 +29,6 @@ pub(crate) struct BuiltObject {
pub tiles: DenseTileMap<TileObjectPrimitive>, pub tiles: DenseTileMap<TileObjectPrimitive>,
} }
#[derive(Debug)]
pub struct BuiltScene {
pub view_box: RectF32,
pub quad: [Point3DF32; 4],
pub object_count: u32,
pub shaders: Vec<ObjectShader>,
}
pub enum RenderCommand { pub enum RenderCommand {
AddFills(Vec<FillBatchPrimitive>), AddFills(Vec<FillBatchPrimitive>),
FlushFills, FlushFills,
@ -90,14 +80,6 @@ pub struct AlphaTileBatchPrimitive {
pub tile_index: u16, pub tile_index: u16,
} }
#[derive(Clone, Copy, Debug, Default)]
pub struct Stats {
pub object_count: u32,
pub solid_tile_count: u32,
pub alpha_tile_count: u32,
pub fill_count: u32,
}
// Utilities for built objects // Utilities for built objects
impl BuiltObject { impl BuiltObject {
@ -258,22 +240,6 @@ impl BuiltObject {
} }
} }
impl BuiltScene {
#[inline]
pub fn new(view_box: RectF32, quad: &[Point3DF32; 4], object_count: u32) -> BuiltScene {
BuiltScene { view_box, quad: *quad, object_count, shaders: vec![] }
}
pub fn stats(&self) -> Stats {
Stats {
object_count: self.object_count,
solid_tile_count: 0,
alpha_tile_count: 0,
fill_count: 0,
}
}
}
impl Default for TileObjectPrimitive { impl Default for TileObjectPrimitive {
#[inline] #[inline]
fn default() -> TileObjectPrimitive { fn default() -> TileObjectPrimitive {
@ -323,15 +289,3 @@ impl Debug for RenderCommand {
} }
} }
} }
impl Add<Stats> for Stats {
type Output = Stats;
fn add(self, other: Stats) -> Stats {
Stats {
object_count: other.object_count,
solid_tile_count: other.solid_tile_count,
alpha_tile_count: other.alpha_tile_count,
fill_count: other.fill_count,
}
}
}

View File

@ -12,7 +12,7 @@
use crate::builder::{PreparedRenderOptions, PreparedRenderTransform}; use crate::builder::{PreparedRenderOptions, PreparedRenderTransform};
use hashbrown::HashMap; use hashbrown::HashMap;
use pathfinder_geometry::basic::point::Point2DF32; use pathfinder_geometry::basic::point::{Point2DF32, Point3DF32};
use pathfinder_geometry::basic::rect::RectF32; use pathfinder_geometry::basic::rect::RectF32;
use pathfinder_geometry::basic::transform2d::Transform2DF32; use pathfinder_geometry::basic::transform2d::Transform2DF32;
use pathfinder_geometry::color::ColorU; use pathfinder_geometry::color::ColorU;
@ -52,7 +52,15 @@ impl Scene {
paint_id paint_id
} }
pub fn build_shaders(&self) -> Vec<ObjectShader> { pub fn build_descriptor(&self, built_options: &PreparedRenderOptions) -> SceneDescriptor {
SceneDescriptor {
shaders: self.build_shaders(),
bounding_quad: built_options.bounding_quad(),
object_count: self.objects.len(),
}
}
fn build_shaders(&self) -> Vec<ObjectShader> {
self.objects.iter().map(|object| { self.objects.iter().map(|object| {
let paint = &self.paints[object.paint.0 as usize]; let paint = &self.paints[object.paint.0 as usize];
ObjectShader { fill_color: paint.color } ObjectShader { fill_color: paint.color }
@ -154,6 +162,13 @@ impl Debug for Scene {
} }
} }
#[derive(Clone, Debug)]
pub struct SceneDescriptor {
pub shaders: Vec<ObjectShader>,
pub bounding_quad: [Point3DF32; 4],
pub object_count: usize,
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct PathObject { pub struct PathObject {
outline: Outline, outline: Outline,