Bug 1506748 - Record profiler markers for scene building and blob rasterization. r=mstange
authorMatt Woodrow <mwoodrow@mozilla.com>
Wed, 14 Nov 2018 23:21:23 +0000
changeset 446447 bec62e8ca661fffe9942cb40d232c632106d2e6c
parent 446446 d364b0b15fa522aa681eb1648d0b866e29be3783
child 446448 0210ae2d20cc9637f496df75e0515843e3587700
push id35041
push useraiakab@mozilla.com
push dateThu, 15 Nov 2018 09:52:43 +0000
treeherdermozilla-central@48720735b142 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1506748
milestone65.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
Bug 1506748 - Record profiler markers for scene building and blob rasterization. r=mstange MozReview-Commit-ID: IA2ooFX5jtA Differential Revision: https://phabricator.services.mozilla.com/D11723
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/webrender_bindings/Moz2DImageRenderer.cpp
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/src/moz2d_renderer.rs
gfx/webrender_bindings/webrender_ffi.h
gfx/webrender_bindings/webrender_ffi_generated.h
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -49,16 +49,30 @@ bool is_in_compositor_thread()
   return mozilla::layers::CompositorThreadHolder::IsInCompositorThread();
 }
 
 bool is_in_render_thread()
 {
   return mozilla::wr::RenderThread::IsInRenderThread();
 }
 
+void gecko_profiler_start_marker(const char* name)
+{
+#ifdef MOZ_GECKO_PROFILER
+  profiler_tracing("WebRender", name, TRACING_INTERVAL_START);
+#endif
+}
+
+void gecko_profiler_end_marker(const char* name)
+{
+#ifdef MOZ_GECKO_PROFILER
+  profiler_tracing("WebRender", name, TRACING_INTERVAL_END);
+#endif
+}
+
 bool is_glcontext_egl(void* glcontext_ptr)
 {
   MOZ_ASSERT(glcontext_ptr);
 
   mozilla::gl::GLContext* glcontext = reinterpret_cast<mozilla::gl::GLContext*>(glcontext_ptr);
   if (!glcontext) {
     return false;
   }
--- a/gfx/webrender_bindings/Moz2DImageRenderer.cpp
+++ b/gfx/webrender_bindings/Moz2DImageRenderer.cpp
@@ -10,16 +10,17 @@
 #include "mozilla/Range.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/RectAbsolute.h"
 #include "mozilla/gfx/Logging.h"
 #include "mozilla/gfx/RecordedEvent.h"
 #include "mozilla/layers/WebRenderDrawEventRecorder.h"
 #include "WebRenderTypes.h"
 #include "webrender_ffi.h"
+#include "GeckoProfiler.h"
 
 #include <unordered_map>
 
 #ifdef XP_MACOSX
 #include "mozilla/gfx/UnscaledFontMac.h"
 #elif defined(XP_WIN)
 #include "mozilla/gfx/UnscaledFontDWrite.h"
 #else
@@ -320,16 +321,17 @@ GetScaledFont(Translator* aTranslator, W
 static bool Moz2DRenderCallback(const Range<const uint8_t> aBlob,
                                 gfx::IntSize aSize,
                                 gfx::SurfaceFormat aFormat,
                                 const uint16_t *aTileSize,
                                 const mozilla::wr::TileOffset *aTileOffset,
                                 const mozilla::wr::DeviceUintRect *aDirtyRect,
                                 Range<uint8_t> aOutput)
 {
+  AUTO_PROFILER_TRACING("WebRender", "RasterizeSingleBlob");
   MOZ_ASSERT(aSize.width > 0 && aSize.height > 0);
   if (aSize.width <= 0 || aSize.height <= 0) {
     return false;
   }
 
   auto stride = aSize.width * gfx::BytesPerPixel(aFormat);
 
   if (aOutput.length() < static_cast<size_t>(aSize.height * stride)) {
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -744,16 +744,21 @@ pub unsafe extern "C" fn wr_renderer_flu
 
 /// cbindgen:postfix=WR_DESTRUCTOR_SAFE_FUNC
 #[no_mangle]
 pub unsafe extern "C" fn wr_pipeline_info_delete(_info: WrPipelineInfo) {
     // _info will be dropped here, and the drop impl on FfiVec will free
     // 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);
+}
+
 #[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.
@@ -781,16 +786,17 @@ impl APZCallbacks {
 }
 
 impl SceneBuilderHooks for APZCallbacks {
     fn register(&self) {
         unsafe { apz_register_updater(self.window_id) }
     }
 
     fn pre_scene_build(&self) {
+        unsafe { gecko_profiler_start_marker(b"SceneBuilding\0".as_ptr() as *const c_char); }
     }
 
     fn pre_scene_swap(&self, scenebuild_time: u64) {
         unsafe {
             record_telemetry_time(TelemetryProbe::SceneBuildTime, scenebuild_time);
             apz_pre_scene_swap(self.window_id);
         }
     }
@@ -801,23 +807,26 @@ impl SceneBuilderHooks for APZCallbacks 
             record_telemetry_time(TelemetryProbe::SceneSwapTime, sceneswap_time);
             apz_post_scene_swap(self.window_id, info);
         }
 
         // After a scene swap we should schedule a render for the next vsync,
         // otherwise there's no guarantee that the new scene will get rendered
         // anytime soon
         unsafe { wr_schedule_render(self.window_id) }
+        unsafe { gecko_profiler_end_marker(b"SceneBuilding\0".as_ptr() as *const c_char); }
     }
 
     fn post_resource_update(&self) {
         unsafe { wr_schedule_render(self.window_id) }
+        unsafe { gecko_profiler_end_marker(b"SceneBuilding\0".as_ptr() as *const c_char); }
     }
 
     fn post_empty_scene_build(&self) {
+        unsafe { gecko_profiler_end_marker(b"SceneBuilding\0".as_ptr() as *const c_char); }
     }
 
     fn poke(&self) {
         unsafe { apz_run_updater(self.window_id) }
     }
 
     fn deregister(&self) {
         unsafe { apz_deregister_updater(self.window_id) }
--- a/gfx/webrender_bindings/src/moz2d_renderer.rs
+++ b/gfx/webrender_bindings/src/moz2d_renderer.rs
@@ -2,26 +2,26 @@
 
 //! Provides the webrender-side implementation of gecko blob images.
 //!
 //! Pretty much this is just a shim that calls back into Moz2DImageRenderer, but
 //! it also handles merging "partial" blob images (see `merge_blob_images`) and
 //! registering fonts found in the blob (see `prepare_request`).
 
 use webrender::api::*;
-use bindings::{ByteSlice, MutByteSlice, wr_moz2d_render_cb, ArcVecU8};
+use bindings::{ByteSlice, MutByteSlice, wr_moz2d_render_cb, ArcVecU8, gecko_profiler_start_marker, gecko_profiler_end_marker};
 use rayon::ThreadPool;
 use rayon::prelude::*;
 
 use std::collections::hash_map::HashMap;
 use std::collections::hash_map;
 use std::collections::btree_map::BTreeMap;
 use std::collections::Bound::Included;
 use std::mem;
-use std::os::raw::c_void;
+use std::os::raw::{c_void, c_char};
 use std::ptr;
 use std::sync::Arc;
 use std;
 
 #[cfg(target_os = "windows")]
 use dwrote;
 
 #[cfg(target_os = "macos")]
@@ -448,20 +448,38 @@ struct BlobCommand {
 /// Rasterizes gecko blob images.
 struct Moz2dBlobRasterizer {
     /// Pool of rasterizers.
     workers: Arc<ThreadPool>,
     /// Blobs to rasterize.
     blob_commands: HashMap<ImageKey, BlobCommand>,
 }
 
+struct GeckoProfilerMarker {
+    name: &'static [u8],
+}
+
+impl GeckoProfilerMarker {
+    pub fn new(name: &'static [u8]) -> GeckoProfilerMarker {
+        unsafe { gecko_profiler_start_marker(name.as_ptr() as *const c_char); }
+        GeckoProfilerMarker { name }
+    }
+}
+
+impl Drop for GeckoProfilerMarker {
+    fn drop(&mut self) {
+        unsafe { gecko_profiler_end_marker(self.name.as_ptr() as *const c_char); }
+    }
+}
+
 impl AsyncBlobImageRasterizer for Moz2dBlobRasterizer {
    
     fn rasterize(&mut self, requests: &[BlobImageParams], low_priority: bool) -> Vec<(BlobImageRequest, BlobImageResult)> {
         // All we do here is spin up our workers to callback into gecko to replay the drawing commands.
+        let _marker = GeckoProfilerMarker::new(b"BlobRasterization\0");
 
         let requests: Vec<Job> = requests.into_iter().map(|params| {
             let command = &self.blob_commands[&params.request.key];
             let blob = Arc::clone(&command.data);
             Job {
                 request: params.request,
                 descriptor: params.descriptor,
                 commands: blob,
@@ -599,16 +617,17 @@ extern "C" {
         size: f32,
         options: Option<&FontInstanceOptions>,
         platform_options: Option<&FontInstancePlatformOptions>,
         variations: *const FontVariation,
         num_variations: usize,
     );
     fn DeleteBlobFont(key: WrFontInstanceKey);
     fn ClearBlobImageResources(namespace: WrIdNamespace);
+
 }
 
 impl Moz2dBlobImageHandler {
     /// Create a new BlobImageHandler with the given thread pool.
     pub fn new(workers: Arc<ThreadPool>) -> Self {
         Moz2dBlobImageHandler {
             blob_commands: HashMap::new(),
             workers: workers,
--- a/gfx/webrender_bindings/webrender_ffi.h
+++ b/gfx/webrender_bindings/webrender_ffi.h
@@ -25,16 +25,19 @@ bool gfx_use_wrench();
 const char* gfx_wr_resource_path_override();
 void gfx_critical_note(const char* msg);
 void gfx_critical_error(const char* msg);
 void gecko_printf_stderr_output(const char* msg);
 void* get_proc_address_from_glcontext(void* glcontext_ptr, const char* procname);
 void gecko_profiler_register_thread(const char* threadname);
 void gecko_profiler_unregister_thread();
 
+void gecko_profiler_start_marker(const char* name);
+void gecko_profiler_end_marker(const char* name);
+
 // Prelude of types necessary before including webrender_ffi_generated.h
 namespace mozilla {
 namespace wr {
 
 struct FontInstanceFlags {
   uint32_t bits;
 
   bool operator==(const FontInstanceFlags& aOther) const {
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -1151,16 +1151,19 @@ extern bool is_glcontext_angle(void *aGl
 extern bool is_glcontext_egl(void *aGlcontextPtr);
 
 extern bool is_in_compositor_thread();
 
 extern bool is_in_main_thread();
 
 extern bool is_in_render_thread();
 
+extern void gecko_profiler_start_marker(const char* name);
+extern void gecko_profiler_end_marker(const char* name);
+
 extern void record_telemetry_time(TelemetryProbe aProbe,
                                   uint64_t aTimeNs);
 
 WR_INLINE
 bool remove_program_binary_disk_cache(const nsAString *aProfPath)
 WR_FUNC;
 
 WR_INLINE