Report when constant buffer offsetting doesn't work. (bug 1379413 part 2, r=bas)
authorDavid Anderson <danderson@mozilla.com>
Tue, 11 Jul 2017 00:13:26 -0700
changeset 368155 0b438dce0908ba9dfd2f25e8486151603f22aa52
parent 368154 3cbaaeb4f8c235b75721e2137d5687780edfecce
child 368156 4cc39579c80c10bd469219b3718d54cc164af12a
push id92421
push userdanderson@mozilla.com
push dateTue, 11 Jul 2017 07:15:40 +0000
treeherdermozilla-inbound@0b438dce0908 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbas
bugs1379413
milestone56.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
Report when constant buffer offsetting doesn't work. (bug 1379413 part 2, r=bas)
gfx/config/gfxConfig.cpp
gfx/config/gfxConfig.h
gfx/config/gfxFallback.h
gfx/ipc/GPUChild.cpp
gfx/ipc/GPUChild.h
gfx/ipc/GfxMessageUtils.h
gfx/ipc/PGPU.ipdl
gfx/layers/d3d11/MLGDeviceD3D11.cpp
gfx/layers/mlgpu/MLGDevice.cpp
widget/GfxInfoBase.cpp
--- a/gfx/config/gfxConfig.cpp
+++ b/gfx/config/gfxConfig.cpp
@@ -1,15 +1,17 @@
 /* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* vim: set sts=2 ts=8 sw=2 tw=99 et: */
 /* 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 "gfxConfig.h"
 #include "mozilla/UniquePtr.h"
+#include "mozilla/Unused.h"
+#include "mozilla/gfx/GPUParent.h"
 #include "mozilla/gfx/GraphicsMessages.h"
 #include "plstr.h"
 
 namespace mozilla {
 namespace gfx {
 
 static UniquePtr<gfxConfig> sConfig;
 
@@ -180,17 +182,33 @@ gfxConfig::Inherit(Feature aFeature, Fea
 gfxConfig::UseFallback(Fallback aFallback)
 {
   return sConfig->UseFallbackImpl(aFallback);
 }
 
 /* static */ void
 gfxConfig::EnableFallback(Fallback aFallback, const char* aMessage)
 {
-  // Ignore aMessage for now.
+  if (!NS_IsMainThread()) {
+    nsCString message(aMessage);
+    NS_DispatchToMainThread(
+      NS_NewRunnableFunction("gfxConfig::EnableFallback",
+                             [=]() -> void {
+
+        gfxConfig::EnableFallback(aFallback, message.get());
+      }));
+    return;
+  }
+
+  if (XRE_IsGPUProcess()) {
+    nsCString message(aMessage);
+    Unused << GPUParent::GetSingleton()->SendUsedFallback(aFallback, message);
+    return;
+  }
+
   sConfig->EnableFallbackImpl(aFallback, aMessage);
 }
 
 bool
 gfxConfig::UseFallbackImpl(Fallback aFallback) const
 {
   return !!(mFallbackBits & (uint64_t(1) << uint64_t(aFallback)));
 }
--- a/gfx/config/gfxConfig.h
+++ b/gfx/config/gfxConfig.h
@@ -162,17 +162,18 @@ public:
   // of a parameter.
   static void UserEnable(Feature aFeature, const char* aMessage);
   static void UserForceEnable(Feature aFeature, const char* aMessage);
   static void UserDisable(Feature aFeature, const char* aMessage, const nsACString& aFailureId = EmptyCString());
 
   // Query whether a fallback has been toggled.
   static bool UseFallback(Fallback aFallback);
 
-  // Enable a fallback.
+  // Add a log entry denoting that a given fallback had to be used. This can
+  // be called from any thread in the UI or GPU process.
   static void EnableFallback(Fallback aFallback, const char* aMessage);
 
   // Run a callback for each initialized FeatureState.
   typedef std::function<void(const char* aName,
                              const char* aDescription,
                              FeatureState& aFeature)> FeatureIterCallback;
   static void ForEachFeature(const FeatureIterCallback& aCallback);
 
--- a/gfx/config/gfxFallback.h
+++ b/gfx/config/gfxFallback.h
@@ -9,17 +9,17 @@
 #include <stdint.h>
 #include "gfxTelemetry.h"
 
 namespace mozilla {
 namespace gfx {
 
 #define GFX_FALLBACK_MAP(_)                                                       \
   /* Name */                                                                      \
-  _(PLACEHOLDER_DO_NOT_USE)                                                       \
+  _(NO_CONSTANT_BUFFER_OFFSETTING)                                                \
   /* Add new entries above this comment */
 
 enum class Fallback : uint32_t {
 #define MAKE_ENUM(name) name,
   GFX_FALLBACK_MAP(MAKE_ENUM)
 #undef MAKE_ENUM
   NumValues
 };
--- a/gfx/ipc/GPUChild.cpp
+++ b/gfx/ipc/GPUChild.cpp
@@ -275,16 +275,23 @@ GPUChild::ActorDestroy(ActorDestroyReaso
 
 mozilla::ipc::IPCResult
 GPUChild::RecvUpdateFeature(const Feature& aFeature, const FeatureFailure& aChange)
 {
   gfxConfig::SetFailed(aFeature, aChange.status(), aChange.message().get(), aChange.failureId());
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult
+GPUChild::RecvUsedFallback(const Fallback& aFallback, const nsCString& aMessage)
+{
+  gfxConfig::EnableFallback(aFallback, aMessage.get());
+  return IPC_OK();
+}
+
 class DeferredDeleteGPUChild : public Runnable
 {
 public:
   explicit DeferredDeleteGPUChild(UniquePtr<GPUChild>&& aChild)
     : Runnable("gfx::DeferredDeleteGPUChild")
     , mChild(Move(aChild))
   {
   }
--- a/gfx/ipc/GPUChild.h
+++ b/gfx/ipc/GPUChild.h
@@ -54,16 +54,17 @@ public:
 
   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(const GPUDeviceData& aData) override;
   mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport) override;
   mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration) override;
   mozilla::ipc::IPCResult RecvUpdateFeature(const Feature& aFeature, const FeatureFailure& aChange) override;
+  mozilla::ipc::IPCResult RecvUsedFallback(const Fallback& aFallback, const nsCString& aMessage) override;
 
   bool SendRequestMemoryReport(const uint32_t& aGeneration,
                                const bool& aAnonymize,
                                const bool& aMinimizeMemoryUsage,
                                const MaybeFileDesc& aDMDFile);
 
   static void Destroy(UniquePtr<GPUChild>&& aChild);
 
--- a/gfx/ipc/GfxMessageUtils.h
+++ b/gfx/ipc/GfxMessageUtils.h
@@ -9,16 +9,17 @@
 
 #include "FilterSupport.h"
 #include "FrameMetrics.h"
 #include "ImageTypes.h"
 #include "RegionBuilder.h"
 #include "base/process_util.h"
 #include "chrome/common/ipc_message_utils.h"
 #include "gfxFeature.h"
+#include "gfxFallback.h"
 #include "gfxPoint.h"
 #include "gfxRect.h"
 #include "gfxTelemetry.h"
 #include "gfxTypes.h"
 #include "ipc/IPCMessageUtils.h"
 #include "mozilla/gfx/Matrix.h"
 #include "nsRect.h"
 #include "nsRegion.h"
@@ -224,16 +225,24 @@ template <>
 struct ParamTraits<mozilla::gfx::Feature>
   : public ContiguousEnumSerializer<
              mozilla::gfx::Feature,
              mozilla::gfx::Feature::HW_COMPOSITING,
              mozilla::gfx::Feature::NumValues>
 {};
 
 template <>
+struct ParamTraits<mozilla::gfx::Fallback>
+  : public ContiguousEnumSerializer<
+             mozilla::gfx::Fallback,
+             mozilla::gfx::Fallback::NO_CONSTANT_BUFFER_OFFSETTING,
+             mozilla::gfx::Fallback::NumValues>
+{};
+
+template <>
 struct ParamTraits<mozilla::gfx::FeatureStatus>
   : public ContiguousEnumSerializer<
              mozilla::gfx::FeatureStatus,
              mozilla::gfx::FeatureStatus::Unused,
              mozilla::gfx::FeatureStatus::LAST>
 {};
 
 template <>
--- a/gfx/ipc/PGPU.ipdl
+++ b/gfx/ipc/PGPU.ipdl
@@ -17,16 +17,17 @@ using base::ProcessId from "base/process
 using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
 using mozilla::Telemetry::Accumulation from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::KeyedAccumulation from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::ScalarAction from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::KeyedScalarAction from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::ChildEventData from "mozilla/TelemetryComms.h";
 using mozilla::Telemetry::DiscardedData from "mozilla/TelemetryComms.h";
 using mozilla::gfx::Feature from "gfxFeature.h";
+using mozilla::gfx::Fallback from "gfxFallback.h";
 
 namespace mozilla {
 namespace gfx {
 
 union GfxPrefValue {
   bool;
   int32_t;
   uint32_t;
@@ -115,12 +116,15 @@ child:
   async NotifyDeviceReset(GPUDeviceData status);
 
   async AddMemoryReport(MemoryReport aReport);
   async FinishMemoryReport(uint32_t aGeneration);
 
   // Update the UI process after a feature's status has changed. This is used
   // outside of the normal startup flow.
   async UpdateFeature(Feature aFeature, FeatureFailure aChange);
+
+  // Notify about:support/Telemetry that a fallback occurred.
+  async UsedFallback(Fallback aFallback, nsCString message);
 };
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/layers/d3d11/MLGDeviceD3D11.cpp
+++ b/gfx/layers/d3d11/MLGDeviceD3D11.cpp
@@ -12,16 +12,17 @@
 #include "mozilla/layers/DiagnosticsD3D11.h"
 #include "mozilla/layers/LayerMLGPU.h"
 #include "mozilla/layers/MemoryReportingMLGPU.h"
 #include "mozilla/layers/ShaderDefinitionsMLGPU.h"
 #include "mozilla/widget/CompositorWidget.h"
 #include "mozilla/widget/WinCompositorWidget.h"
 #include "MLGShaders.h"
 #include "TextureD3D11.h"
+#include "gfxConfig.h"
 #include "gfxPrefs.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 using namespace mozilla::widget;
 using namespace mozilla::layers::mlg;
@@ -786,18 +787,23 @@ MLGDeviceD3D11::Initialize()
     D3D11_FEATURE_DATA_D3D11_OPTIONS options;
     HRESULT hr = mDevice->CheckFeatureSupport(
       D3D11_FEATURE_D3D11_OPTIONS,
       &options,
       sizeof(options));
     if (SUCCEEDED(hr)) {
       if (IsWin8OrLater()) {
         mCanUseConstantBufferOffsetBinding = (options.ConstantBufferOffsetting != FALSE);
+      } else {
+        gfxConfig::EnableFallback(Fallback::NO_CONSTANT_BUFFER_OFFSETTING,
+                                  "Unsupported by driver");
       }
       mCanUseClearView = (options.ClearView != FALSE);
+    } else {
+      gfxCriticalNote << "Failed to query D3D11.1 feature support: " << hexa(hr);
     }
   }
 
   // Get capabilities.
   switch (mDevice->GetFeatureLevel()) {
   case D3D_FEATURE_LEVEL_11_1:
   case D3D_FEATURE_LEVEL_11_0:
     mMaxConstantBufferBindSize = D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16;
--- a/gfx/layers/mlgpu/MLGDevice.cpp
+++ b/gfx/layers/mlgpu/MLGDevice.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 20; 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 "MLGDevice.h"
 #include "mozilla/layers/TextureHost.h"
 #include "BufferCache.h"
+#include "gfxConfig.h"
 #include "gfxPrefs.h"
 #include "gfxUtils.h"
 #include "ShaderDefinitionsMLGPU.h"
 #include "SharedBufferMLGPU.h"
 
 namespace mozilla {
 namespace layers {
 
@@ -84,20 +85,24 @@ MLGDevice::Initialize()
     // StagingBuffer depends on this value being accurate, so for now we just
     // double-check it here.
     return Fail("FEATURE_FAILURE_MIN_MAX_CB_BIND_SIZE", "Minimum constant buffer bind size not met");
   }
 
   // We allow this to be pref'd off for testing. Switching it off enables
   // Direct3D 11.0/Windows 7/OpenGL-style buffer code paths.
   if (!gfxPrefs::AdvancedLayersEnableBufferSharing()) {
+    gfxConfig::EnableFallback(Fallback::NO_CONSTANT_BUFFER_OFFSETTING,
+                              "Disabled by pref");
     mCanUseConstantBufferOffsetBinding = false;
   }
-  if (mCanUseConstantBufferOffsetBinding) {
-    mCanUseConstantBufferOffsetBinding = VerifyConstantBufferOffsetting();
+  if (mCanUseConstantBufferOffsetBinding && !VerifyConstantBufferOffsetting()) {
+    gfxConfig::EnableFallback(Fallback::NO_CONSTANT_BUFFER_OFFSETTING,
+                              "Constant buffer offset binding does not work");
+    mCanUseConstantBufferOffsetBinding = false;
   }
 
   // We allow this to be pref'd off for testing. Disabling it turns on
   // ID3D11DeviceContext1::ClearView support, which is present on
   // newer Windows 8+ drivers.
   if (!gfxPrefs::AdvancedLayersEnableClearView()) {
     mCanUseClearView = false;
   }
--- a/widget/GfxInfoBase.cpp
+++ b/widget/GfxInfoBase.cpp
@@ -1376,16 +1376,21 @@ GfxInfoBase::DescribeFeatures(JSContext*
   gfx::FeatureStatus gpuProcess = gfxConfig::GetValue(Feature::GPU_PROCESS);
   InitFeatureObject(aCx, aObj, "gpuProcess", FEATURE_GPU_PROCESS, Some(gpuProcess), &obj);
 
   // Only include AL if the platform attempted to use it.
   gfx::FeatureStatus advancedLayers = gfxConfig::GetValue(Feature::ADVANCED_LAYERS);
   if (advancedLayers != FeatureStatus::Unused) {
     InitFeatureObject(aCx, aObj, "advancedLayers", FEATURE_ADVANCED_LAYERS,
                       Some(advancedLayers), &obj);
+
+    if (gfxConfig::UseFallback(Fallback::NO_CONSTANT_BUFFER_OFFSETTING)) {
+      JS::Rooted<JS::Value> trueVal(aCx, JS::BooleanValue(true));
+      JS_SetProperty(aCx, obj, "noConstantBufferOffsetting", trueVal);
+    }
   }
 }
 
 bool
 GfxInfoBase::InitFeatureObject(JSContext* aCx,
                                JS::Handle<JSObject*> aContainer,
                                const char* aName,
                                int32_t aFeature,