Bug 1321907 - Hook up the GPU process to the profiler. r?dvander draft
authorMarkus Stange <mstange@themasta.com>
Tue, 21 Mar 2017 19:39:13 -0400
changeset 503321 44a45d5b18e1c919a0b063f1ddaa009b15944487
parent 503320 c9f7da493a20fbef2536dd3269cfe9b6772f5c49
child 503322 7896bb768cd012673d2abd1cf72828617cdedc02
push id50537
push userbmo:mstange@themasta.com
push dateThu, 23 Mar 2017 02:37:11 +0000
reviewersdvander
bugs1321907
milestone55.0a1
Bug 1321907 - Hook up the GPU process to the profiler. r?dvander MozReview-Commit-ID: 8Xq3FPprAF8
gfx/ipc/GPUChild.cpp
gfx/ipc/GPUChild.h
gfx/ipc/GPUParent.cpp
gfx/ipc/GPUParent.h
gfx/ipc/PGPU.ipdl
--- a/gfx/ipc/GPUChild.cpp
+++ b/gfx/ipc/GPUChild.cpp
@@ -13,16 +13,20 @@
 #include "mozilla/TelemetryIPC.h"
 #include "mozilla/dom/CheckerboardReportService.h"
 #include "mozilla/dom/MemoryReportRequest.h"
 #include "mozilla/gfx/gfxVars.h"
 #if defined(XP_WIN)
 # include "mozilla/gfx/DeviceManagerDx.h"
 #endif
 #include "mozilla/ipc/CrashReporterHost.h"
+#include "mozilla/Unused.h"
+#ifdef MOZ_GECKO_PROFILER
+#include "CrossProcessProfilerController.h"
+#endif
 
 namespace mozilla {
 namespace gfx {
 
 GPUChild::GPUChild(GPUProcessHost* aHost)
  : mHost(aHost),
    mGPUReady(false)
 {
@@ -59,16 +63,20 @@ GPUChild::Init()
   devicePrefs.hwCompositing() = gfxConfig::GetValue(Feature::HW_COMPOSITING);
   devicePrefs.d3d11Compositing() = gfxConfig::GetValue(Feature::D3D11_COMPOSITING);
   devicePrefs.oglCompositing() = gfxConfig::GetValue(Feature::OPENGL_COMPOSITING);
   devicePrefs.useD2D1() = gfxConfig::GetValue(Feature::DIRECT2D);
 
   SendInit(prefs, updates, devicePrefs);
 
   gfxVars::AddReceiver(this);
+
+#ifdef MOZ_ENABLE_PROFILER_SPS
+  mProfilerController = CrossProcessProfilerController::ForProtocol(this);
+#endif
 }
 
 void
 GPUChild::OnVarChanged(const GfxVarUpdate& aVar)
 {
   SendUpdateVar(aVar);
 }
 
@@ -180,16 +188,27 @@ GPUChild::RecvRecordChildEvents(nsTArray
 
 mozilla::ipc::IPCResult
 GPUChild::RecvNotifyDeviceReset()
 {
   mHost->mListener->OnProcessDeviceReset(mHost);
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult
+GPUChild::RecvProfile(const nsCString& aProfile)
+{
+#ifdef MOZ_GECKO_PROFILER
+  if (mProfilerController) {
+    mProfilerController->RecvProfile(aProfile);
+  }
+#endif
+  return IPC_OK();
+}
+
 bool
 GPUChild::SendRequestMemoryReport(const uint32_t& aGeneration,
                                   const bool& aAnonymize,
                                   const bool& aMinimizeMemoryUsage,
                                   const MaybeFileDesc& aDMDFile)
 {
   mMemoryReportRequest = MakeUnique<MemoryReportRequestHost>(aGeneration);
   Unused << PGPUChild::SendRequestMemoryReport(
@@ -215,16 +234,40 @@ GPUChild::RecvFinishMemoryReport(const u
   if (mMemoryReportRequest) {
     mMemoryReportRequest->Finish(aGeneration);
     mMemoryReportRequest = nullptr;
   }
   return IPC_OK();
 }
 
 void
+GPUChild::SendStartProfiler(const ProfilerInitParams& aParams)
+{
+  Unused << PGPUChild::SendStartProfiler(aParams);
+}
+
+void
+GPUChild::SendStopProfiler()
+{
+  Unused << PGPUChild::SendStopProfiler();
+}
+
+void
+GPUChild::SendPauseProfiler(const bool& aPause)
+{
+  Unused << PGPUChild::SendPauseProfiler(aPause);
+}
+
+void
+GPUChild::SendGatherProfile()
+{
+  Unused << PGPUChild::SendGatherProfile();
+}
+
+void
 GPUChild::ActorDestroy(ActorDestroyReason aWhy)
 {
   if (aWhy == AbnormalShutdown) {
 #ifdef MOZ_CRASHREPORTER
     if (mCrashReporter) {
       mCrashReporter->GenerateCrashReport(OtherPid());
       mCrashReporter = nullptr;
     }
@@ -235,16 +278,20 @@ GPUChild::ActorDestroy(ActorDestroyReaso
 
     // Notify the Telemetry environment so that we can refresh and do a subsession split
     if (nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService()) {
       obsvc->NotifyObservers(nullptr, "compositor:process-aborted", nullptr);
     }
 
   }
 
+#ifdef MOZ_ENABLE_PROFILER_SPS
+  mProfilerController = nullptr;
+#endif
+
   gfxVars::RemoveReceiver(this);
   mHost->OnChannelClosed();
 }
 
 class DeferredDeleteGPUChild : public Runnable
 {
 public:
   explicit DeferredDeleteGPUChild(UniquePtr<GPUChild>&& aChild)
--- a/gfx/ipc/GPUChild.h
+++ b/gfx/ipc/GPUChild.h
@@ -5,31 +5,38 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef _include_mozilla_gfx_ipc_GPUChild_h_
 #define _include_mozilla_gfx_ipc_GPUChild_h_
 
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/gfx/PGPUChild.h"
 #include "mozilla/gfx/gfxVarReceiver.h"
+#include "ProfilerControllingProcess.h"
 
 namespace mozilla {
+
+#ifdef MOZ_GECKO_PROFILER
+class CrossProcessProfilerController;
+#endif
+
 namespace ipc {
 class CrashReporterHost;
 } // namespace ipc
 namespace dom {
 class MemoryReportRequestHost;
 } // namespace dom
 namespace gfx {
 
 class GPUProcessHost;
 
 class GPUChild final
-  : public PGPUChild,
-    public gfxVarReceiver
+  : public PGPUChild
+  , public gfxVarReceiver
+  , public ProfilerControllingProcess
 {
   typedef mozilla::dom::MemoryReportRequestHost MemoryReportRequestHost;
 
 public:
   explicit GPUChild(GPUProcessHost* aHost);
   ~GPUChild();
 
   void Init();
@@ -49,29 +56,38 @@ public:
   mozilla::ipc::IPCResult RecvUpdateChildScalars(InfallibleTArray<ScalarAction>&& aScalarActions) override;
   mozilla::ipc::IPCResult RecvUpdateChildKeyedScalars(InfallibleTArray<KeyedScalarAction>&& aScalarActions) override;
   mozilla::ipc::IPCResult RecvRecordChildEvents(nsTArray<ChildEventData>&& events) override;
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
   mozilla::ipc::IPCResult RecvGraphicsError(const nsCString& aError) override;
   mozilla::ipc::IPCResult RecvNotifyUiObservers(const nsCString& aTopic) override;
   mozilla::ipc::IPCResult RecvNotifyDeviceReset() override;
+  mozilla::ipc::IPCResult RecvProfile(const nsCString& aProfile) override;
   mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport) override;
   mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration) override;
 
+  void SendStartProfiler(const ProfilerInitParams& aParams) override;
+  void SendStopProfiler() override;
+  void SendPauseProfiler(const bool& aPause) override;
+  void SendGatherProfile() override;
+
   bool SendRequestMemoryReport(const uint32_t& aGeneration,
                                const bool& aAnonymize,
                                const bool& aMinimizeMemoryUsage,
                                const MaybeFileDesc& aDMDFile);
 
   static void Destroy(UniquePtr<GPUChild>&& aChild);
 
 private:
   GPUProcessHost* mHost;
   UniquePtr<ipc::CrashReporterHost> mCrashReporter;
   UniquePtr<MemoryReportRequestHost> mMemoryReportRequest;
   bool mGPUReady;
+#ifdef MOZ_GECKO_PROFILER
+  UniquePtr<CrossProcessProfilerController> mProfilerController;
+#endif
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif // _include_mozilla_gfx_ipc_GPUChild_h_
--- a/gfx/ipc/GPUParent.cpp
+++ b/gfx/ipc/GPUParent.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=99: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 #ifdef XP_WIN
 #include "WMF.h"
 #endif
 #include "GPUParent.h"
+#include "GeckoProfiler.h"
 #include "gfxConfig.h"
 #include "gfxPlatform.h"
 #include "gfxPrefs.h"
 #include "GPUProcessHost.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/dom/MemoryReportRequest.h"
@@ -372,16 +373,68 @@ GPUParent::RecvNotifyGpuObservers(const 
   MOZ_ASSERT(obsSvc);
   if (obsSvc) {
     obsSvc->NotifyObservers(nullptr, aTopic.get(), nullptr);
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
+GPUParent::RecvStartProfiler(const ProfilerInitParams& params)
+{
+  nsTArray<const char*> featureArray;
+  for (size_t i = 0; i < params.features().Length(); ++i) {
+    featureArray.AppendElement(params.features()[i].get());
+  }
+
+  nsTArray<const char*> threadNameFilterArray;
+  for (size_t i = 0; i < params.threadFilters().Length(); ++i) {
+    threadNameFilterArray.AppendElement(params.threadFilters()[i].get());
+  }
+  profiler_start(params.entries(), params.interval(),
+                 featureArray.Elements(), featureArray.Length(),
+                 threadNameFilterArray.Elements(),
+                 threadNameFilterArray.Length());
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+GPUParent::RecvStopProfiler()
+{
+  profiler_stop();
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+GPUParent::RecvPauseProfiler(const bool& aPause)
+{
+  if (aPause) {
+    profiler_pause();
+  } else {
+    profiler_resume();
+  }
+
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+GPUParent::RecvGatherProfile()
+{
+  nsCString profileCString;
+  UniquePtr<char[]> profile = profiler_get_profile();
+  if (profile) {
+    profileCString = nsDependentCString(profile.get());
+  }
+
+  Unused << SendProfile(profileCString);
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
 GPUParent::RecvRequestMemoryReport(const uint32_t& aGeneration,
                                    const bool& aAnonymize,
                                    const bool& aMinimizeMemoryUsage,
                                    const MaybeFileDesc& aDMDFile)
 {
   nsPrintfCString processName("GPU (pid %u)", (unsigned)getpid());
 
   mozilla::dom::MemoryReportRequestClient::Start(
--- a/gfx/ipc/GPUParent.h
+++ b/gfx/ipc/GPUParent.h
@@ -49,16 +49,20 @@ public:
   mozilla::ipc::IPCResult RecvNewContentCompositorBridge(Endpoint<PCompositorBridgeParent>&& aEndpoint) override;
   mozilla::ipc::IPCResult RecvNewContentImageBridge(Endpoint<PImageBridgeParent>&& aEndpoint) override;
   mozilla::ipc::IPCResult RecvNewContentVRManager(Endpoint<PVRManagerParent>&& aEndpoint) override;
   mozilla::ipc::IPCResult RecvNewContentVideoDecoderManager(Endpoint<PVideoDecoderManagerParent>&& aEndpoint) override;
   mozilla::ipc::IPCResult RecvGetDeviceStatus(GPUDeviceData* aOutStatus) override;
   mozilla::ipc::IPCResult RecvAddLayerTreeIdMapping(nsTArray<LayerTreeIdMapping>&& aMappings) override;
   mozilla::ipc::IPCResult RecvRemoveLayerTreeIdMapping(const LayerTreeIdMapping& aMapping) override;
   mozilla::ipc::IPCResult RecvNotifyGpuObservers(const nsCString& aTopic) override;
+  mozilla::ipc::IPCResult RecvStartProfiler(const ProfilerInitParams& params) override;
+  mozilla::ipc::IPCResult RecvPauseProfiler(const bool& aPause) override;
+  mozilla::ipc::IPCResult RecvStopProfiler() override;
+  mozilla::ipc::IPCResult RecvGatherProfile() override;
   mozilla::ipc::IPCResult RecvRequestMemoryReport(
     const uint32_t& generation,
     const bool& anonymize,
     const bool& minimizeMemoryUsage,
     const MaybeFileDesc& DMDFile) override;
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
--- a/gfx/ipc/PGPU.ipdl
+++ b/gfx/ipc/PGPU.ipdl
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 include GraphicsMessages;
+include ProfilerTypes;
 include MemoryReportTypes;
 include protocol PCompositorBridge;
 include protocol PImageBridge;
 include protocol PVRManager;
 include protocol PVsyncBridge;
 include protocol PUiCompositorController;
 include protocol PVideoDecoderManager;
 
@@ -83,16 +84,22 @@ parent:
   // Request the current DeviceStatus from the GPU process. This blocks until
   // one is available (i.e., Init has completed).
   sync GetDeviceStatus() returns (GPUDeviceData status);
 
   // Have a message be broadcasted to the GPU process by the GPU process
   // observer service.
   async NotifyGpuObservers(nsCString aTopic);
 
+  // Control the Gecko Profiler in the GPU process.
+  async StartProfiler(ProfilerInitParams params);
+  async StopProfiler();
+  async PauseProfiler(bool aPause);
+  async GatherProfile();
+
   async RequestMemoryReport(uint32_t generation,
                             bool anonymize,
                             bool minimizeMemoryUsage,
                             MaybeFileDesc DMDFile);
 
 child:
   // Sent when the GPU process has initialized devices. This occurs once, after
   // Init().
@@ -114,14 +121,16 @@ child:
   async AccumulateChildHistograms(Accumulation[] accumulations);
   async AccumulateChildKeyedHistograms(KeyedAccumulation[] accumulations);
   async UpdateChildScalars(ScalarAction[] actions);
   async UpdateChildKeyedScalars(KeyedScalarAction[] actions);
   async RecordChildEvents(ChildEventData[] events);
 
   async NotifyDeviceReset();
 
+  // Called in response to GatherProfile.
+  async Profile(nsCString aProfile);
   async AddMemoryReport(MemoryReport aReport);
   async FinishMemoryReport(uint32_t aGeneration);
 };
 
 } // namespace gfx
 } // namespace mozilla