| ☠☠ backed out by 93e37c529818 ☠ ☠ | |
| author | Glenn Watson <github@intuitionlibrary.com> |
| Wed, 13 Feb 2019 04:02:02 +0000 | |
| changeset 458846 | bc69bea83b66eae8e56ea097898bd066f4c00820 |
| parent 458845 | 547cbfca4507c5add94dddd0dba868691b3ca15c |
| child 458847 | b7f9a1180f2356de24e63fe6f40949f914cc1b88 |
| push id | 35548 |
| push user | opoprus@mozilla.com |
| push date | Wed, 13 Feb 2019 09:48:26 +0000 |
| treeherder | mozilla-central@93e37c529818 [default view] [failures only] |
| perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
| reviewers | kvark, emilio |
| bugs | 1527522 |
| milestone | 67.0a1 |
| first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
| last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/Cargo.lock +++ b/Cargo.lock @@ -1,10 +1,8 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. [[package]] name = "Inflector" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3084,16 +3082,17 @@ dependencies = [ "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", "core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "dwrote 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "gleam 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
--- a/gfx/webrender_bindings/src/bindings.rs +++ b/gfx/webrender_bindings/src/bindings.rs @@ -19,17 +19,17 @@ use std::os::raw::{c_int}; use gleam::gl; use webrender::api::*; use webrender::{ReadPixelsFormat, Renderer, RendererOptions, RendererStats, ThreadListener}; use webrender::{ExternalImage, ExternalImageHandler, ExternalImageSource}; use webrender::DebugFlags; use webrender::{ApiRecordingReceiver, BinaryRecorder}; use webrender::{AsyncPropertySampler, PipelineInfo, SceneBuilderHooks}; -use webrender::{UploadMethod, VertexUsageHint}; +use webrender::{UploadMethod, VertexUsageHint, ProfilerHooks, set_profiler_hooks}; use webrender::{Device, Shaders, WrShaders, ShaderPrecacheFlags}; use thread_profiler::register_thread_with_profiler; use moz2d_renderer::Moz2dBlobImageHandler; use program_cache::{WrProgramCache, remove_disk_cache}; use app_units::Au; use rayon; use euclid::SideOffsets2D; use nsstring::nsAString; @@ -774,16 +774,36 @@ pub unsafe extern "C" fn wr_pipeline_inf // the underlying vec memory } extern "C" { pub fn gecko_profiler_start_marker(name: *const c_char); pub fn gecko_profiler_end_marker(name: *const c_char); } +/// Simple implementation of the WR ProfilerHooks trait to allow profile +/// markers to be seen in the Gecko profiler. +struct GeckoProfilerHooks; + +impl ProfilerHooks for GeckoProfilerHooks { + fn begin_marker(&self, label: &CStr) { + unsafe { + gecko_profiler_start_marker(label.as_ptr()); + } + } + + fn end_marker(&self, label: &CStr) { + unsafe { + gecko_profiler_end_marker(label.as_ptr()); + } + } +} + +const PROFILER_HOOKS: GeckoProfilerHooks = GeckoProfilerHooks {}; + #[allow(improper_ctypes)] // this is needed so that rustc doesn't complain about passing the &mut Transaction to an extern function extern "C" { // These callbacks are invoked from the scene builder thread (aka the APZ // updater thread) fn apz_register_updater(window_id: WrWindowId); fn apz_pre_scene_swap(window_id: WrWindowId); // This function takes ownership of the pipeline_info and is responsible for // freeing it via wr_pipeline_info_delete. @@ -1115,16 +1135,19 @@ pub extern "C" fn wr_window_new(window_i max_texture_size: Some(8192), // Moz2D doesn't like textures bigger than this clear_color: Some(ColorF::new(0.0, 0.0, 0.0, 0.0)), precache_flags, namespace_alloc_by_client: true, enable_picture_caching, ..Default::default() }; + // Ensure the WR profiler callbacks are hooked up to the Gecko profiler. + set_profiler_hooks(Some(&PROFILER_HOOKS)); + let notifier = Box::new(CppNotifier { window_id: window_id, }); let (renderer, sender) = match Renderer::new(gl, notifier, opts, shaders) { Ok((renderer, sender)) => (renderer, sender), Err(e) => { warn!(" Failed to create a Renderer: {:?}", e); let msg = CString::new(format!("wr_window_new: {:?}", e)).unwrap();
--- a/gfx/wr/webrender/Cargo.toml +++ b/gfx/wr/webrender/Cargo.toml @@ -23,16 +23,17 @@ webrender_build = { version = "0.0.1", p [dependencies] app_units = "0.7" base64 = { optional = true, version = "0.10" } bincode = "1.0" bitflags = "1.0" byteorder = "1.0" cfg-if = "0.1.2" +cstr = "0.1.2" fxhash = "0.2.1" gleam = "0.6.8" image = { optional = true, version = "0.21" } lazy_static = "1" log = "0.4" malloc_size_of_derive = "0.1" num-traits = "0.2" plane-split = "0.13.3"
--- a/gfx/wr/webrender/src/frame_builder.rs +++ b/gfx/wr/webrender/src/frame_builder.rs @@ -369,16 +369,18 @@ impl FrameBuilder { &mut self.prim_store.pictures, &frame_context, gpu_cache, &self.clip_store, &data_stores.clip, ); { + profile_marker!("UpdateVisibility"); + let visibility_context = FrameVisibilityContext { device_pixel_scale, clip_scroll_tree, screen_world_rect, surfaces, debug_flags, scene_properties, config: &self.config, @@ -434,25 +436,29 @@ impl FrameBuilder { root_spatial_node_index, ROOT_SURFACE_INDEX, true, &mut frame_state, &frame_context, ) .unwrap(); - self.prim_store.prepare_primitives( - &mut prim_list, - &pic_context, - &mut pic_state, - &frame_context, - &mut frame_state, - data_stores, - scratch, - ); + { + profile_marker!("PreparePrims"); + + self.prim_store.prepare_primitives( + &mut prim_list, + &pic_context, + &mut pic_state, + &frame_context, + &mut frame_state, + data_stores, + scratch, + ); + } let pic = &mut self.prim_store.pictures[self.root_pic_index.0]; pic.restore_context( prim_list, pic_context, pic_state, &mut frame_state, ); @@ -495,16 +501,17 @@ impl FrameBuilder { texture_cache_profile: &mut TextureCacheProfileCounters, gpu_cache_profile: &mut GpuCacheProfileCounters, scene_properties: &SceneProperties, data_stores: &mut DataStores, scratch: &mut PrimitiveScratchBuffer, debug_flags: DebugFlags, ) -> Frame { profile_scope!("build"); + profile_marker!("BuildFrame"); debug_assert!( DeviceIntRect::new(DeviceIntPoint::zero(), self.window_size) .contains_rect(&self.screen_rect) ); let mut profile_counters = FrameProfileCounters::new(); profile_counters .total_primitives @@ -541,89 +548,96 @@ impl FrameBuilder { scene_properties, &mut transform_palette, data_stores, &mut surfaces, scratch, debug_flags, ); - resource_cache.block_until_all_resources_added(gpu_cache, - &mut render_tasks, - texture_cache_profile); + { + profile_marker!("BlockOnResources"); + + resource_cache.block_until_all_resources_added(gpu_cache, + &mut render_tasks, + texture_cache_profile); + } let mut passes = vec![]; - - // Add passes as required for our cached render tasks. - if !render_tasks.cacheable_render_tasks.is_empty() { - passes.push(RenderPass::new_off_screen(screen_size)); - for cacheable_render_task in &render_tasks.cacheable_render_tasks { - render_tasks.assign_to_passes( - *cacheable_render_task, - 0, - screen_size, - &mut passes, - ); - } - passes.reverse(); - } - - if let Some(main_render_task_id) = main_render_task_id { - let passes_start = passes.len(); - passes.push(RenderPass::new_main_framebuffer(screen_size)); - render_tasks.assign_to_passes( - main_render_task_id, - passes_start, - screen_size, - &mut passes, - ); - passes[passes_start..].reverse(); - } - - let mut deferred_resolves = vec![]; let mut has_texture_cache_tasks = false; let mut prim_headers = PrimitiveHeaders::new(); - // Used to generated a unique z-buffer value per primitive. - let mut z_generator = ZBufferIdGenerator::new(); - let use_dual_source_blending = self.config.dual_source_blending_is_enabled && - self.config.dual_source_blending_is_supported; + + { + profile_marker!("Batching"); - for pass in &mut passes { - let mut ctx = RenderTargetContext { - device_pixel_scale, - prim_store: &self.prim_store, - resource_cache, - use_dual_source_blending, - clip_scroll_tree, - data_stores, - surfaces: &surfaces, - scratch, - screen_world_rect, - globals: &self.globals, - }; + // Add passes as required for our cached render tasks. + if !render_tasks.cacheable_render_tasks.is_empty() { + passes.push(RenderPass::new_off_screen(screen_size)); + for cacheable_render_task in &render_tasks.cacheable_render_tasks { + render_tasks.assign_to_passes( + *cacheable_render_task, + 0, + screen_size, + &mut passes, + ); + } + passes.reverse(); + } + + if let Some(main_render_task_id) = main_render_task_id { + let passes_start = passes.len(); + passes.push(RenderPass::new_main_framebuffer(screen_size)); + render_tasks.assign_to_passes( + main_render_task_id, + passes_start, + screen_size, + &mut passes, + ); + passes[passes_start..].reverse(); + } - pass.build( - &mut ctx, - gpu_cache, - &mut render_tasks, - &mut deferred_resolves, - &self.clip_store, - &mut transform_palette, - &mut prim_headers, - &mut z_generator, - ); + // Used to generated a unique z-buffer value per primitive. + let mut z_generator = ZBufferIdGenerator::new(); + let use_dual_source_blending = self.config.dual_source_blending_is_enabled && + self.config.dual_source_blending_is_supported; + + for pass in &mut passes { + let mut ctx = RenderTargetContext { + device_pixel_scale, + prim_store: &self.prim_store, + resource_cache, + use_dual_source_blending, + clip_scroll_tree, + data_stores, + surfaces: &surfaces, + scratch, + screen_world_rect, + globals: &self.globals, + }; - match pass.kind { - RenderPassKind::MainFramebuffer(ref color) => { - has_texture_cache_tasks |= color.must_be_drawn(); - } - RenderPassKind::OffScreen { ref texture_cache, ref color, .. } => { - has_texture_cache_tasks |= !texture_cache.is_empty(); - has_texture_cache_tasks |= color.must_be_drawn(); + pass.build( + &mut ctx, + gpu_cache, + &mut render_tasks, + &mut deferred_resolves, + &self.clip_store, + &mut transform_palette, + &mut prim_headers, + &mut z_generator, + ); + + match pass.kind { + RenderPassKind::MainFramebuffer(ref color) => { + has_texture_cache_tasks |= color.must_be_drawn(); + } + RenderPassKind::OffScreen { ref texture_cache, ref color, .. } => { + has_texture_cache_tasks |= !texture_cache.is_empty(); + has_texture_cache_tasks |= color.must_be_drawn(); + } } } } let gpu_cache_frame_id = gpu_cache.end_frame(gpu_cache_profile).frame_id(); render_tasks.write_task_data(device_pixel_scale);
--- a/gfx/wr/webrender/src/lib.rs +++ b/gfx/wr/webrender/src/lib.rs @@ -51,30 +51,35 @@ macro_rules! matches { } } #[macro_use] extern crate bitflags; #[macro_use] extern crate cfg_if; #[macro_use] +extern crate cstr; +#[macro_use] extern crate lazy_static; #[macro_use] extern crate log; #[macro_use] extern crate malloc_size_of_derive; #[cfg(any(feature = "serde"))] #[macro_use] extern crate serde; #[macro_use] extern crate thread_profiler; extern crate wr_malloc_size_of; use wr_malloc_size_of as malloc_size_of; +#[macro_use] +mod profiler; + mod batch; mod border; mod box_shadow; #[cfg(any(feature = "capture", feature = "replay"))] mod capture; mod clip; mod clip_scroll_tree; mod debug_colors; @@ -98,17 +103,16 @@ mod gpu_types; mod hit_test; mod image; mod intern; mod intern_types; mod internal_types; mod picture; mod prim_store; mod print_tree; -mod profiler; mod record; mod render_backend; mod render_task; mod renderer; mod resource_cache; mod scene; mod scene_builder; mod segment; @@ -202,16 +206,17 @@ pub extern crate webrender_api; extern crate webrender_build; #[doc(hidden)] pub use device::{build_shader_strings, ReadPixelsFormat, UploadMethod, VertexUsageHint}; pub use device::{ProgramBinary, ProgramCache, ProgramCacheObserver}; pub use device::Device; pub use frame_builder::ChasePrimitive; pub use picture::FRAMES_BEFORE_PICTURE_CACHING; +pub use profiler::{ProfilerHooks, set_profiler_hooks}; pub use renderer::{AsyncPropertySampler, CpuProfile, DebugFlags, OutputImageHandler, RendererKind}; pub use renderer::{ExternalImage, ExternalImageHandler, ExternalImageSource, GpuProfile}; pub use renderer::{GraphicsApi, GraphicsApiInfo, PipelineInfo, Renderer, RendererOptions}; pub use renderer::{RenderResults, RendererStats, SceneBuilderHooks, ThreadListener, ShaderPrecacheFlags}; pub use renderer::MAX_VERTEX_TEXTURE_WIDTH; pub use shade::{Shaders, WrShaders}; pub use webrender_api as api; pub use webrender_api::euclid;
--- a/gfx/wr/webrender/src/picture.rs +++ b/gfx/wr/webrender/src/picture.rs @@ -1641,16 +1641,18 @@ impl<'a> PictureUpdateState<'a> { surfaces: &'a mut Vec<SurfaceInfo>, pic_index: PictureIndex, picture_primitives: &mut [PicturePrimitive], frame_context: &FrameBuildingContext, gpu_cache: &mut GpuCache, clip_store: &ClipStore, clip_data_store: &ClipDataStore, ) { + profile_marker!("UpdatePictures"); + let mut state = PictureUpdateState { surfaces, surface_stack: vec![SurfaceIndex(0)], picture_stack: Vec::new(), are_raster_roots_assigned: true, }; state.update(
--- a/gfx/wr/webrender/src/profiler.rs +++ b/gfx/wr/webrender/src/profiler.rs @@ -2,29 +2,92 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use api::{ColorF, ColorU}; use debug_render::DebugRenderer; use device::query::{GpuSampler, GpuTimer, NamedTag}; use euclid::{Point2D, Rect, Size2D, vec2}; use internal_types::FastHashMap; -use renderer::MAX_VERTEX_TEXTURE_WIDTH; +use renderer::{MAX_VERTEX_TEXTURE_WIDTH, wr_has_been_initialized}; use std::collections::vec_deque::VecDeque; use std::{f32, mem}; +use std::ffi::CStr; use time::precise_time_ns; const GRAPH_WIDTH: f32 = 1024.0; const GRAPH_HEIGHT: f32 = 320.0; const GRAPH_PADDING: f32 = 8.0; const GRAPH_FRAME_HEIGHT: f32 = 16.0; const PROFILE_PADDING: f32 = 10.0; const ONE_SECOND_NS: u64 = 1000000000; +/// Defines the interface for hooking up an external profiler to WR. +pub trait ProfilerHooks : Send + Sync { + /// Called at the beginning of a profile scope. The label must + /// be a C string (null terminated). + fn begin_marker(&self, label: &CStr); + + /// Called at the end of a profile scope. The label must + /// be a C string (null terminated). + fn end_marker(&self, label: &CStr); +} + +/// The current global profiler callbacks, if set by embedder. +static mut PROFILER_HOOKS: Option<&'static ProfilerHooks> = None; + +/// Set the profiler callbacks, or None to disable the profiler. +/// This function must only ever be called before any WR instances +/// have been created, or the hooks will not be set. +pub fn set_profiler_hooks(hooks: Option<&'static ProfilerHooks>) { + if !wr_has_been_initialized() { + unsafe { + PROFILER_HOOKS = hooks; + } + } +} + +/// A simple RAII style struct to manage a profile scope. +pub struct ProfileScope { + name: &'static CStr, +} + +impl ProfileScope { + /// Begin a new profile scope + pub fn new(name: &'static CStr) -> Self { + unsafe { + if let Some(ref hooks) = PROFILER_HOOKS { + hooks.begin_marker(name); + } + } + + ProfileScope { + name, + } + } +} + +impl Drop for ProfileScope { + fn drop(&mut self) { + unsafe { + if let Some(ref hooks) = PROFILER_HOOKS { + hooks.end_marker(self.name); + } + } + } +} + +/// A helper macro to define profile scopes. +macro_rules! profile_marker { + ($string:expr) => { + let _scope = $crate::profiler::ProfileScope::new(cstr!($string)); + }; +} + #[derive(Debug, Clone)] pub struct GpuProfileTag { pub label: &'static str, pub color: ColorF, } impl NamedTag for GpuProfileTag { fn get_label(&self) -> &str {
--- a/gfx/wr/webrender/src/renderer.rs +++ b/gfx/wr/webrender/src/renderer.rs @@ -79,16 +79,17 @@ use std::cmp; use std::collections::VecDeque; use std::collections::hash_map::Entry; use std::f32; use std::mem; use std::os::raw::c_void; use std::path::PathBuf; use std::rc::Rc; use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::{channel, Receiver}; use std::thread; use std::cell::RefCell; use texture_cache::TextureCache; use thread_profiler::{register_thread_with_profiler, write_profile}; use tiling::{AlphaRenderTarget, ColorRenderTarget}; use tiling::{BlitJob, BlitJobSource, RenderPass, RenderPassKind, RenderTargetList}; use tiling::{Frame, RenderTarget, RenderTargetKind, TextureCacheRenderTarget}; @@ -101,16 +102,24 @@ cfg_if! { use serde_json; use debug_server::{self, DebugServer}; } else { use api::ApiMsg; use api::channel::MsgSender; } } +/// Is only false if no WR instances have ever been created. +static HAS_BEEN_INITIALIZED: AtomicBool = AtomicBool::new(false); + +/// Returns true if a WR instance has ever been initialized in this process. +pub fn wr_has_been_initialized() -> bool { + HAS_BEEN_INITIALIZED.load(Ordering::SeqCst) +} + pub const MAX_VERTEX_TEXTURE_WIDTH: usize = 1024; /// Enabling this toggle would force the GPU cache scattered texture to /// be resized every frame, which enables GPU debuggers to see if this /// is performed correctly. const GPU_CACHE_RESIZE_TEST: bool = false; /// Number of GPU blocks per UV rectangle provided for an image. pub const BLOCKS_PER_UV_RECT: usize = 2; @@ -1624,16 +1633,18 @@ impl Renderer { /// ``` /// [rendereroptions]: struct.RendererOptions.html pub fn new( gl: Rc<gl::Gl>, notifier: Box<RenderNotifier>, mut options: RendererOptions, shaders: Option<&mut WrShaders> ) -> Result<(Self, RenderApiSender), RendererError> { + HAS_BEEN_INITIALIZED.store(true, Ordering::SeqCst); + let (api_tx, api_rx) = channel::msg_channel()?; let (payload_tx, payload_rx) = channel::payload_channel()?; let (result_tx, result_rx) = channel(); let gl_type = gl.get_type(); let debug_server = DebugServer::new(api_tx.clone()); let mut device = Device::new(