Bug 1681563 - Record WebRender device resets in telemetry and crash reports on non-Windows. r=jrmuizel

Differential Revision: https://phabricator.services.mozilla.com/D99346
This commit is contained in:
Andrew Osmond 2020-12-10 14:26:32 +00:00
parent 32309a1973
commit e73a5b9a7c
5 changed files with 56 additions and 17 deletions

View File

@ -7,6 +7,7 @@
#include "GPUProcessManager.h"
#include "gfxConfig.h"
#include "gfxPlatform.h"
#include "GPUProcessHost.h"
#include "GPUProcessListener.h"
#include "mozilla/MemoryReportingProcess.h"
@ -526,6 +527,16 @@ void GPUProcessManager::NotifyWebRenderError(wr::WebRenderError aError) {
DisableWebRender(aError, nsCString());
}
/* static */ void GPUProcessManager::RecordDeviceReset(
DeviceResetReason aReason) {
if (aReason != DeviceResetReason::FORCED_RESET) {
Telemetry::Accumulate(Telemetry::DEVICE_RESET_REASON, uint32_t(aReason));
}
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::DeviceResetReason, int(aReason));
}
bool GPUProcessManager::OnDeviceReset(bool aTrackThreshold) {
#ifdef XP_WIN
// Disable double buffering when device reset happens.

View File

@ -21,6 +21,7 @@
#include "nsIObserver.h"
#include "nsThreadUtils.h"
class nsBaseWidget;
enum class DeviceResetReason;
namespace mozilla {
class MemoryReportingProcess;
@ -148,6 +149,9 @@ class GPUProcessManager final : public GPUProcessHost::Listener {
// Destroy and recreate all of the compositors
void ResetCompositors();
// Record the device reset in telemetry / annotate the crash report.
static void RecordDeviceReset(DeviceResetReason aReason);
void OnProcessLaunchComplete(GPUProcessHost* aHost) override;
void OnProcessUnexpectedShutdown(GPUProcessHost* aHost) override;
void SimulateDeviceReset();

View File

@ -14,6 +14,7 @@
#include "mozilla/Telemetry.h"
#include "mozilla/WindowsVersion.h"
#include "mozilla/gfx/GPUParent.h"
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/gfx/GraphicsMessages.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/gfx/gfxVars.h"
@ -1044,13 +1045,7 @@ bool DeviceManagerDx::MaybeResetAndReacquireDevices() {
return false;
}
if (resetReason != DeviceResetReason::FORCED_RESET) {
Telemetry::Accumulate(Telemetry::DEVICE_RESET_REASON,
uint32_t(resetReason));
}
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::DeviceResetReason, int(resetReason));
GPUProcessManager::RecordDeviceReset(resetReason);
bool createCompositorDevice = !!mCompositorDevice;
bool createContentDevice = !!mContentDevice;
@ -1115,7 +1110,7 @@ static DeviceResetReason HResultToResetReason(HRESULT hr) {
default:
MOZ_ASSERT(false);
}
return DeviceResetReason::UNKNOWN;
return DeviceResetReason::OTHER;
}
bool DeviceManagerDx::HasDeviceReset(DeviceResetReason* aOutReason) {

View File

@ -146,16 +146,18 @@ inline const char* GetBackendName(mozilla::gfx::BackendType aBackend) {
}
enum class DeviceResetReason {
OK = 0,
HUNG,
REMOVED,
RESET,
DRIVER_ERROR,
INVALID_CALL,
OK = 0, // No reset.
HUNG, // Windows specific, guilty device reset.
REMOVED, // Windows specific, device removed or driver upgraded.
RESET, // Guilty device reset.
DRIVER_ERROR, // Innocent device reset.
INVALID_CALL, // Windows specific, guilty device reset.
OUT_OF_MEMORY,
FORCED_RESET,
UNKNOWN,
D3D9_RESET
FORCED_RESET, // Simulated device reset.
OTHER, // Unrecognized reason for device reset.
D3D9_RESET, // Windows specific, not used.
NVIDIA_VIDEO, // Linux specific, NVIDIA video memory was reset.
UNKNOWN, // GL specific, unknown if guilty or innocent.
};
enum class ForcedDeviceResetReason {

View File

@ -6,6 +6,7 @@
#include "base/task.h"
#include "GeckoProfiler.h"
#include "gfxPlatform.h"
#include "GLContext.h"
#include "RenderThread.h"
#include "nsThreadUtils.h"
@ -791,6 +792,27 @@ void RenderThread::InitDeviceTask() {
SharedGL();
}
#ifndef XP_WIN
static DeviceResetReason GLenumToResetReason(GLenum aReason) {
switch (aReason) {
case LOCAL_GL_NO_ERROR:
return DeviceResetReason::FORCED_RESET;
case LOCAL_GL_INNOCENT_CONTEXT_RESET_ARB:
return DeviceResetReason::DRIVER_ERROR;
case LOCAL_GL_PURGED_CONTEXT_RESET_NV:
return DeviceResetReason::NVIDIA_VIDEO;
case LOCAL_GL_GUILTY_CONTEXT_RESET_ARB:
return DeviceResetReason::RESET;
case LOCAL_GL_UNKNOWN_CONTEXT_RESET_ARB:
return DeviceResetReason::UNKNOWN;
case LOCAL_GL_OUT_OF_MEMORY:
return DeviceResetReason::OUT_OF_MEMORY;
default:
return DeviceResetReason::OTHER;
}
}
#endif
void RenderThread::HandleDeviceReset(const char* aWhere,
layers::CompositorBridgeParent* aBridge,
GLenum aReason) {
@ -800,6 +822,11 @@ void RenderThread::HandleDeviceReset(const char* aWhere,
return;
}
#ifndef XP_WIN
// On Windows, see DeviceManagerDx::MaybeResetAndReacquireDevices.
gfx::GPUProcessManager::RecordDeviceReset(GLenumToResetReason(aReason));
#endif
// On some platforms (i.e. Linux), we may get a device reset just for purging
// video memory with NVIDIA devices, because the driver has edge cases it
// needs to clear all of it.