Bug 1392476 - Add dropframe telemetry for WebVR; r=francois,kip
authorDaosheng Mu <daoshengmu@gmail.com>
Mon, 28 Aug 2017 18:43:25 +0800
changeset 428760 d206c52ee4f73ff2e6bf1c3f4cc6d86ee1f58b31
parent 428759 d2315652e64f1274dab652021e1f710b4f0fbd10
child 428761 ab26002b1029ce3340d2c43c3c0507043a37aa8e
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfrancois, kip
bugs1392476
milestone57.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 1392476 - Add dropframe telemetry for WebVR; r=francois,kip MozReview-Commit-ID: IPVnPBkY8CN
gfx/vr/gfxVR.h
gfx/vr/gfxVROculus.cpp
gfx/vr/gfxVROculus.h
gfx/vr/gfxVROpenVR.cpp
gfx/vr/gfxVROpenVR.h
toolkit/components/telemetry/Histograms.json
--- a/gfx/vr/gfxVR.h
+++ b/gfx/vr/gfxVR.h
@@ -306,16 +306,35 @@ struct VRControllerInfo
            mNumHaptics == other.mNumHaptics;
   }
 
   bool operator!=(const VRControllerInfo& other) const {
     return !(*this == other);
   }
 };
 
+struct VRTelemetry
+{
+  VRTelemetry()
+   : mLastDroppedFrameCount(-1)
+  {}
+
+  void Clear() {
+    mPresentationStart = TimeStamp();
+    mLastDroppedFrameCount = -1;
+  }
+
+  bool IsLastDroppedFrameValid() {
+    return (mLastDroppedFrameCount != -1);
+  }
+
+  TimeStamp mPresentationStart;
+  int32_t mLastDroppedFrameCount;
+};
+
 class VRSystemManager {
 public:
   static uint32_t AllocateDisplayID();
   static uint32_t AllocateControllerID();
 
 protected:
   static Atomic<uint32_t> sDisplayBase;
   static Atomic<uint32_t> sControllerBase;
--- a/gfx/vr/gfxVROculus.cpp
+++ b/gfx/vr/gfxVROculus.cpp
@@ -228,29 +228,50 @@ VROculusSession::StopTracking()
 
 void
 VROculusSession::StartPresentation(const IntSize& aSize)
 {
   if (!mPresenting) {
     mPresenting = true;
     mPresentationSize = aSize;
     Refresh();
-    mPresentationStart = TimeStamp::Now();
+    mTelemetry.Clear();
+    mTelemetry.mPresentationStart = TimeStamp::Now();
+
+    ovrPerfStats perfStats;
+    if (ovr_GetPerfStats(mSession, &perfStats) == ovrSuccess) {
+      if (perfStats.FrameStatsCount) {
+        mTelemetry.mLastDroppedFrameCount = perfStats.FrameStats[0].AppDroppedFrameCount;
+      }
+    }
   }
 }
 
 void
 VROculusSession::StopPresentation()
 {
   if (mPresenting) {
     mLastPresentationEnd = TimeStamp::Now();
     mPresenting = false;
+
+    const TimeDuration duration = mLastPresentationEnd - mTelemetry.mPresentationStart;
     Telemetry::Accumulate(Telemetry::WEBVR_USERS_VIEW_IN, 1);
-    Telemetry::AccumulateTimeDelta(Telemetry::WEBVR_TIME_SPENT_VIEWING_IN_OCULUS,
-                                   mPresentationStart);
+    Telemetry::Accumulate(Telemetry::WEBVR_TIME_SPENT_VIEWING_IN_OCULUS,
+                          duration.ToMilliseconds());
+
+    if (mTelemetry.IsLastDroppedFrameValid() && duration.ToSeconds()) {
+      ovrPerfStats perfStats;
+      if (ovr_GetPerfStats(mSession, &perfStats) == ovrSuccess) {
+        if (perfStats.FrameStatsCount) {
+          const uint32_t droppedFramesPerSec = (perfStats.FrameStats[0].AppDroppedFrameCount -
+                                                mTelemetry.mLastDroppedFrameCount) / duration.ToSeconds();
+          Telemetry::Accumulate(Telemetry::WEBVR_DROPPED_FRAMES_IN_OCULUS, droppedFramesPerSec);
+        }
+      }
+    }
     Refresh();
   }
 }
 
 VROculusSession::~VROculusSession()
 {
   Uninitialize(true);
 }
--- a/gfx/vr/gfxVROculus.h
+++ b/gfx/vr/gfxVROculus.h
@@ -32,16 +32,17 @@ enum class OculusControllerAxisType : ui
   ThumbstickXAxis,
   ThumbstickYAxis,
   NumVRControllerAxisType
 };
 
 class VROculusSession
 {
   NS_INLINE_DECL_REFCOUNTING(VROculusSession);
+  friend class VRDisplayOculus;
 public:
   VROculusSession();
   void Refresh();
   bool IsTrackingReady() const;
   bool IsRenderReady() const;
   ovrSession Get();
   void StartPresentation(const IntSize& aSize);
   void StopPresentation();
@@ -51,24 +52,24 @@ public:
   ovrTextureSwapChain GetSwapChain();
 
 private:
   PRLibrary* mOvrLib;
   ovrSession mSession;
   ovrInitFlags mInitFlags;
   ovrTextureSwapChain mTextureSet;
   nsTArray<RefPtr<layers::CompositingRenderTargetD3D11>> mRenderTargets;
-  bool mPresenting;
   IntSize mPresentationSize;
   RefPtr<ID3D11Device> mDevice;
   // The timestamp of the last time Oculus set ShouldQuit to true.
   TimeStamp mLastShouldQuit;
   // The timestamp of the last ending presentation
   TimeStamp mLastPresentationEnd;
-  TimeStamp mPresentationStart;
+  VRTelemetry mTelemetry;
+  bool mPresenting;
 
   ~VROculusSession();
   void Uninitialize(bool aUnloadLib);
   bool Initialize(ovrInitFlags aFlags);
   bool LoadOvrLib();
   void UnloadOvrLib();
   bool StartSession();
   void StopSession();
--- a/gfx/vr/gfxVROpenVR.cpp
+++ b/gfx/vr/gfxVROpenVR.cpp
@@ -263,32 +263,44 @@ VRDisplayOpenVR::GetSensorState()
 
 void
 VRDisplayOpenVR::StartPresentation()
 {
   if (mIsPresenting) {
     return;
   }
   mIsPresenting = true;
-  mPresentationStart = TimeStamp::Now();
+  mTelemetry.Clear();
+  mTelemetry.mPresentationStart = TimeStamp::Now();
+
+  ::vr::Compositor_CumulativeStats stats;
+  mVRCompositor->GetCumulativeStats(&stats, sizeof(::vr::Compositor_CumulativeStats));
+  mTelemetry.mLastDroppedFrameCount = stats.m_nNumReprojectedFrames;
 }
 
 void
 VRDisplayOpenVR::StopPresentation()
 {
   if (!mIsPresenting) {
     return;
   }
 
   mVRCompositor->ClearLastSubmittedFrame();
 
   mIsPresenting = false;
+  const TimeDuration duration = TimeStamp::Now() - mTelemetry.mPresentationStart;
   Telemetry::Accumulate(Telemetry::WEBVR_USERS_VIEW_IN, 2);
-  Telemetry::AccumulateTimeDelta(Telemetry::WEBVR_TIME_SPENT_VIEWING_IN_OPENVR,
-                                 mPresentationStart);
+  Telemetry::Accumulate(Telemetry::WEBVR_TIME_SPENT_VIEWING_IN_OPENVR,
+                        duration.ToMilliseconds());
+
+  ::vr::Compositor_CumulativeStats stats;
+  mVRCompositor->GetCumulativeStats(&stats, sizeof(::vr::Compositor_CumulativeStats));
+  const uint32_t droppedFramesPerSec = (stats.m_nNumReprojectedFrames -
+                                        mTelemetry.mLastDroppedFrameCount) / duration.ToSeconds();
+  Telemetry::Accumulate(Telemetry::WEBVR_DROPPED_FRAMES_IN_OPENVR, droppedFramesPerSec);
 }
 
 bool
 VRDisplayOpenVR::SubmitFrame(void* aTextureHandle,
                              ::vr::ETextureType aTextureType,
                              const IntSize& aSize,
                              const gfx::Rect& aLeftEyeRect,
                              const gfx::Rect& aRightEyeRect)
--- a/gfx/vr/gfxVROpenVR.h
+++ b/gfx/vr/gfxVROpenVR.h
@@ -57,17 +57,17 @@ protected:
   virtual ~VRDisplayOpenVR();
   void Destroy();
 
   // not owned by us; global from OpenVR
   ::vr::IVRSystem *mVRSystem;
   ::vr::IVRChaperone *mVRChaperone;
   ::vr::IVRCompositor *mVRCompositor;
 
-  TimeStamp mPresentationStart;
+  VRTelemetry mTelemetry;
   bool mIsPresenting;
 
   void UpdateStageParameters();
   void PollEvents();
   bool SubmitFrame(void* aTextureHandle,
                    ::vr::ETextureType aTextureType,
                    const IntSize& aSize,
                    const gfx::Rect& aLeftEyeRect,
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -13569,16 +13569,38 @@
     "bug_numbers": [1306156],
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 1200000,
     "n_buckets": 100,
     "releaseChannelCollection": "opt-out",
     "description": "The amount of time spent(ms) of a session for viewing content in OpenVR."
   },
+  "WEBVR_DROPPED_FRAMES_IN_OCULUS": {
+    "record_in_processes": ["main", "gpu"],
+    "alert_emails": ["dmu@mozilla.com"],
+    "bug_numbers": [1392476],
+    "expires_in_version": "never",
+    "kind": "linear",
+    "high": 200,
+    "n_buckets": 100,
+    "releaseChannelCollection": "opt-out",
+    "description": "The average number of dropped frames per sec in Oculus, sent when user exits WebVR content."
+  },
+  "WEBVR_DROPPED_FRAMES_IN_OPENVR": {
+    "record_in_processes": ["main", "gpu"],
+    "alert_emails": ["dmu@mozilla.com"],
+    "bug_numbers": [1392476],
+    "expires_in_version": "never",
+    "kind": "linear",
+    "high": 200,
+    "n_buckets": 100,
+    "releaseChannelCollection": "opt-out",
+    "description": "The average number of dropped frames per sec in OpenVR, sent when user exits WebVR content."
+  },
   "URLCLASSIFIER_UI_EVENTS": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["seceng-telemetry@mozilla.com", "francois@mozilla.com"],
     "bug_numbers": [1375277],
     "expires_in_version": "never",
     "kind": "enumerated",
     "n_values": 64,
     "description": "URL CLassifier-related (aka Safe Browsing) UI events. See nsIUrlClassifierUITelemetry.idl for the specific values."