Bug 1321907 - Hook up the GPU process to the profiler. r?dvander
MozReview-Commit-ID: 8Xq3FPprAF8
--- 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