Make Toggles overriden automatically and device creation

Bug: dawn:373
Change-Id: I9aac64d1b800caad123161f4b48e70d39c1e0085
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/18761
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp
index 3834d1d..674f5f5 100644
--- a/src/dawn_native/Device.cpp
+++ b/src/dawn_native/Device.cpp
@@ -14,6 +14,7 @@
 
 #include "dawn_native/Device.h"
 
+#include "common/Log.h"
 #include "dawn_native/Adapter.h"
 #include "dawn_native/AttachmentState.h"
 #include "dawn_native/BindGroup.h"
@@ -72,13 +73,14 @@
         mErrorScopeTracker = std::make_unique<ErrorScopeTracker>(this);
         mFenceSignalTracker = std::make_unique<FenceSignalTracker>(this);
         mDynamicUploader = std::make_unique<DynamicUploader>(this);
-        SetDefaultToggles();
 
         if (descriptor != nullptr) {
+            ApplyToggleOverrides(descriptor);
             ApplyExtensions(descriptor);
         }
-
         mFormatTable = BuildFormatTable(this);
+
+        SetDefaultToggles();
     }
 
     DeviceBase::~DeviceBase() {
@@ -655,23 +657,6 @@
         }
     }
 
-    void DeviceBase::ApplyToggleOverrides(const DeviceDescriptor* deviceDescriptor) {
-        ASSERT(deviceDescriptor);
-
-        for (const char* toggleName : deviceDescriptor->forceEnabledToggles) {
-            Toggle toggle = GetAdapter()->GetInstance()->ToggleNameToEnum(toggleName);
-            if (toggle != Toggle::InvalidEnum) {
-                mEnabledToggles.Set(toggle, true);
-            }
-        }
-        for (const char* toggleName : deviceDescriptor->forceDisabledToggles) {
-            Toggle toggle = GetAdapter()->GetInstance()->ToggleNameToEnum(toggleName);
-            if (toggle != Toggle::InvalidEnum) {
-                mEnabledToggles.Set(toggle, false);
-            }
-        }
-    }
-
     void DeviceBase::ApplyExtensions(const DeviceDescriptor* deviceDescriptor) {
         ASSERT(deviceDescriptor);
         ASSERT(GetAdapter()->SupportsAllRequestedExtensions(deviceDescriptor->requiredExtensions));
@@ -684,18 +669,10 @@
         return mEnabledExtensions.GetEnabledExtensionNames();
     }
 
-    std::vector<const char*> DeviceBase::GetTogglesUsed() const {
-        return mEnabledToggles.GetContainedToggleNames();
-    }
-
     bool DeviceBase::IsExtensionEnabled(Extension extension) const {
         return mEnabledExtensions.IsEnabled(extension);
     }
 
-    bool DeviceBase::IsToggleEnabled(Toggle toggle) const {
-        return mEnabledToggles.Has(toggle);
-    }
-
     bool DeviceBase::IsValidationEnabled() const {
         return !IsToggleEnabled(Toggle::SkipValidation);
     }
@@ -708,12 +685,6 @@
         ++mLazyClearCountForTesting;
     }
 
-    void DeviceBase::SetDefaultToggles() {
-        // Sets the default-enabled toggles
-        mEnabledToggles.Set(Toggle::LazyClearResourceOnFirstUse, true);
-        mEnabledToggles.Set(Toggle::UseSpvc, false);
-    }
-
     // Implementation details of object creation
 
     MaybeError DeviceBase::CreateBindGroupInternal(BindGroupBase** result,
@@ -912,8 +883,52 @@
         return mDynamicUploader.get();
     }
 
+    // The Toggle device facility
+
+    std::vector<const char*> DeviceBase::GetTogglesUsed() const {
+        return mEnabledToggles.GetContainedToggleNames();
+    }
+
+    bool DeviceBase::IsToggleEnabled(Toggle toggle) const {
+        return mEnabledToggles.Has(toggle);
+    }
+
     void DeviceBase::SetToggle(Toggle toggle, bool isEnabled) {
+        if (!mOverridenToggles.Has(toggle)) {
+            mEnabledToggles.Set(toggle, isEnabled);
+        }
+    }
+
+    void DeviceBase::ForceSetToggle(Toggle toggle, bool isEnabled) {
+        if (!mOverridenToggles.Has(toggle) && mEnabledToggles.Has(toggle) != isEnabled) {
+            dawn::WarningLog() << "Forcing toggle \"" << ToggleEnumToName(toggle) << "\" to "
+                               << isEnabled << "when it was overriden to be " << !isEnabled;
+        }
         mEnabledToggles.Set(toggle, isEnabled);
     }
 
+    void DeviceBase::SetDefaultToggles() {
+        SetToggle(Toggle::LazyClearResourceOnFirstUse, true);
+        SetToggle(Toggle::UseSpvc, false);
+    }
+
+    void DeviceBase::ApplyToggleOverrides(const DeviceDescriptor* deviceDescriptor) {
+        ASSERT(deviceDescriptor);
+
+        for (const char* toggleName : deviceDescriptor->forceEnabledToggles) {
+            Toggle toggle = GetAdapter()->GetInstance()->ToggleNameToEnum(toggleName);
+            if (toggle != Toggle::InvalidEnum) {
+                mEnabledToggles.Set(toggle, true);
+                mOverridenToggles.Set(toggle, true);
+            }
+        }
+        for (const char* toggleName : deviceDescriptor->forceDisabledToggles) {
+            Toggle toggle = GetAdapter()->GetInstance()->ToggleNameToEnum(toggleName);
+            if (toggle != Toggle::InvalidEnum) {
+                mEnabledToggles.Set(toggle, false);
+                mOverridenToggles.Set(toggle, true);
+            }
+        }
+    }
+
 }  // namespace dawn_native