diff --git a/Cargo.lock b/Cargo.lock index 5eb9a668..2740953f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -169,6 +169,9 @@ dependencies = [ "pathfinder_svg 0.1.0", "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "sdl2 0.32.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "usvg 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -321,6 +324,11 @@ dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "itoa" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "jemalloc-sys" version = "0.1.8" @@ -798,6 +806,11 @@ dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ryu" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "safe-transmute" version = "0.10.1" @@ -867,6 +880,16 @@ dependencies = [ "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde_json" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "simplecss" version = "0.1.0" @@ -1130,6 +1153,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebdff791af04e30089bde8ad2a632b86af433b40c04db8d70ad4b21487db7a6a" "checksum image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "52fb0666a1273dac46f9725aa4859bcd5595fc3554cf3495051b4de8db745e7d" "checksum inflate 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "84c683bde2d8413b8f1be3e459c30e4817672b6e7a31d9212b0323154e76eba7" +"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc62c8e50e381768ce8ee0428ee53741929f7ebd73e4d83f669bcf7693e00ae" "checksum jemallocator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9f0cd42ac65f758063fea55126b0148b1ce0a6354ff78e07a4d6806bc65c4ab3" "checksum jpeg-decoder 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c8b7d43206b34b3f94ea9445174bda196e772049b9bddbc620c9d29b2d20110d" @@ -1181,6 +1205,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" "checksum roxmltree 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "02660467d0c2da1b6276042501aee6e15ec5b8ff59423243f185b294cd53acf3" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum safe-transmute 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9604873ffe1980bc1f179103704a65c8aca141c248d9e52b7af95ff10578166e" "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" @@ -1191,6 +1216,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "0e732ed5a5592c17d961555e3b552985baf98d50ce418b7b655f31f6ba7eb1b7" "checksum serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d6115a3ca25c224e409185325afc16a0d5aaaabc15c42b09587d6f1ba39a5b" +"checksum serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "4b90a9fbe1211e57d3e1c15670f1cb00802988fb23a1a4aad7a2b63544f1920e" "checksum simplecss 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "135685097a85a64067df36e28a243e94a94f76d829087ce0be34eeb014260c0e" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" diff --git a/demo3/src/debug_text.rs b/demo3/src/debug_text.rs index 7f642bb6..25a4b4a0 100644 --- a/demo3/src/debug_text.rs +++ b/demo3/src/debug_text.rs @@ -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 * 2 + PADDING + 3; +const WINDOW_HEIGHT: i16 = LINE_HEIGHT * 3 + PADDING + 3; const PADDING: i16 = 12; const FONT_ASCENT: i16 = 28; const LINE_HEIGHT: i16 = 42; @@ -112,7 +112,10 @@ impl DebugRenderer { self.framebuffer_size = *window_size; } - pub fn draw(&self, prepare_time: Duration, tile_time: Duration) { + pub fn draw(&self, + prepare_time: Duration, + tile_time: Duration, + rendering_time: Option) { 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), @@ -124,6 +127,12 @@ impl DebugRenderer { 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)); + 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)); + } } fn draw_solid_rect(&self, rect: &Rect, color: ColorU) { diff --git a/demo3/src/device.rs b/demo3/src/device.rs index c0aeb2b5..bafed0b5 100644 --- a/demo3/src/device.rs +++ b/demo3/src/device.rs @@ -373,3 +373,59 @@ impl Texture { } } } + +pub struct TimerQuery { + gl_query: GLuint, +} + +impl Drop for TimerQuery { + #[inline] + fn drop(&mut self) { + unsafe { + gl::DeleteQueries(1, &mut self.gl_query); + } + } +} + +impl TimerQuery { + #[inline] + pub fn new() -> TimerQuery { + let mut query = TimerQuery { gl_query: 0 }; + unsafe { + gl::GenQueries(1, &mut query.gl_query); + } + query + } + + #[inline] + pub fn begin(&self) { + unsafe { + gl::BeginQuery(gl::TIME_ELAPSED, self.gl_query); + } + } + + #[inline] + pub fn end(&self) { + unsafe { + gl::EndQuery(gl::TIME_ELAPSED); + } + } + + #[inline] + pub fn is_available(&self) -> bool { + unsafe { + let mut result = 0; + gl::GetQueryObjectiv(self.gl_query, gl::QUERY_RESULT_AVAILABLE, &mut result); + result != gl::FALSE as GLint + } + } + + #[inline] + pub fn get(&self) -> u64 { + unsafe { + let mut result = 0; + gl::GetQueryObjectui64v(self.gl_query, gl::QUERY_RESULT, &mut result); + result + } + } +} diff --git a/demo3/src/main.rs b/demo3/src/main.rs index 4f552fdc..0c31811e 100644 --- a/demo3/src/main.rs +++ b/demo3/src/main.rs @@ -13,7 +13,7 @@ extern crate serde_derive; use crate::debug_text::DebugRenderer; use crate::device::{Buffer, BufferTarget, BufferUploadMode, Framebuffer, Program, Texture}; -use crate::device::{Uniform, VertexAttr}; +use crate::device::{TimerQuery, Uniform, VertexAttr}; use clap::{App, Arg}; use euclid::{Point2D, Rect, Size2D}; use gl::types::{GLfloat, GLint, GLuint}; @@ -31,8 +31,9 @@ use rayon::ThreadPoolBuilder; use sdl2::event::Event; use sdl2::keyboard::Keycode; use sdl2::video::GLProfile; +use std::collections::VecDeque; use std::f32::consts::FRAC_PI_4; -use std::time::Instant; +use std::time::{Duration, Instant}; use std::path::PathBuf; use usvg::{Options as UsvgOptions, Tree}; @@ -152,7 +153,8 @@ fn main() { gl::Clear(gl::COLOR_BUFFER_BIT); renderer.render_scene(&built_scene); - renderer.debug_renderer.draw(elapsed_prepare_time, elapsed_tile_time); + let rendering_time = renderer.shift_timer_query(); + renderer.debug_renderer.draw(elapsed_prepare_time, elapsed_tile_time, rendering_time); } window.gl_swap_window(); @@ -311,6 +313,9 @@ struct Renderer { mask_framebuffer: Framebuffer, fill_colors_texture: Texture, + pending_timer_queries: VecDeque, + free_timer_queries: Vec, + debug_renderer: DebugRenderer, main_framebuffer_size: Size2D, @@ -355,6 +360,9 @@ impl Renderer { mask_framebuffer, fill_colors_texture, + pending_timer_queries: VecDeque::new(), + free_timer_queries: vec![], + debug_renderer, main_framebuffer_size: *main_framebuffer_size, @@ -362,6 +370,9 @@ impl Renderer { } fn render_scene(&mut self, built_scene: &BuiltScene) { + let timer_query = self.free_timer_queries.pop().unwrap_or_else(|| TimerQuery::new()); + timer_query.begin(); + self.upload_shaders(&built_scene.shaders); self.upload_solid_tiles(&built_scene.solid_tiles); @@ -372,6 +383,20 @@ impl Renderer { self.draw_batch_fills(batch); self.draw_batch_mask_tiles(batch); } + + timer_query.end(); + self.pending_timer_queries.push_back(timer_query); + } + + fn shift_timer_query(&mut self) -> Option { + let query = self.pending_timer_queries.front()?; + if !query.is_available() { + return None + } + let query = self.pending_timer_queries.pop_front().unwrap(); + let result = Duration::from_nanos(query.get()); + self.free_timer_queries.push(query); + Some(result) } fn upload_shaders(&mut self, shaders: &[ObjectShader]) {