Add toggle enable_immediate_error_handling

Change-Id: Ia746382fb674f6f8a9b454e546b1e293d4df8678
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/167540
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/dawn/native/Device.cpp b/src/dawn/native/Device.cpp
index f19e176..676f1b4 100644
--- a/src/dawn/native/Device.cpp
+++ b/src/dawn/native/Device.cpp
@@ -243,6 +243,8 @@
         mLabel = descriptor->label;
     }
 
+    mIsImmediateErrorHandlingEnabled = IsToggleEnabled(Toggle::EnableImmediateErrorHandling);
+
     // Record the cache key from the properties. Note that currently, if a new extension
     // descriptor is added (and probably handled here), the cache key recording needs to be
     // updated.
@@ -632,6 +634,9 @@
                 callback(static_cast<WGPUErrorType>(ToWGPUErrorType(type)), messageStr.c_str(),
                          userdata);
             });
+            if (IsImmediateErrorHandlingEnabled()) {
+                mCallbackTaskManager->Flush();
+            }
         }
     }
 }
@@ -1516,6 +1521,10 @@
     return mAdapter != nullptr && mAdapter->GetFeatureLevel() == FeatureLevel::Compatibility;
 }
 
+bool DeviceBase::IsImmediateErrorHandlingEnabled() const {
+    return mIsImmediateErrorHandlingEnabled;
+}
+
 size_t DeviceBase::GetLazyClearCountForTesting() {
     return mLazyClearCountForTesting;
 }
diff --git a/src/dawn/native/Device.h b/src/dawn/native/Device.h
index ac1aebd..4cf59ba 100644
--- a/src/dawn/native/Device.h
+++ b/src/dawn/native/Device.h
@@ -378,6 +378,7 @@
     bool IsValidationEnabled() const;
     bool IsRobustnessEnabled() const;
     bool IsCompatibilityMode() const;
+    bool IsImmediateErrorHandlingEnabled() const;
 
     size_t GetLazyClearCountForTesting();
     void IncrementLazyClearCountForTesting();
@@ -620,6 +621,9 @@
     std::string mLabel;
     CacheKey mDeviceCacheKey;
 
+    // We cache this toggle so that we can check it without locking the device.
+    bool mIsImmediateErrorHandlingEnabled = false;
+
     // This pointer is non-null if Feature::ImplicitDeviceSynchronization is turned on.
     Ref<Mutex> mMutex = nullptr;
 };
diff --git a/src/dawn/native/EncodingContext.cpp b/src/dawn/native/EncodingContext.cpp
index 20dd98b..b1e1287 100644
--- a/src/dawn/native/EncodingContext.cpp
+++ b/src/dawn/native/EncodingContext.cpp
@@ -91,7 +91,7 @@
         error->AppendDebugGroup(*iter);
     }
 
-    if (!IsFinished()) {
+    if (!IsFinished() && !mDevice->IsImmediateErrorHandlingEnabled()) {
         // Encoding should only generate validation errors.
         DAWN_ASSERT(error->GetType() == InternalErrorType::Validation);
         // If the encoding context is not finished, errors are deferred until
diff --git a/src/dawn/native/Toggles.cpp b/src/dawn/native/Toggles.cpp
index b144c20..85fbc5e 100644
--- a/src/dawn/native/Toggles.cpp
+++ b/src/dawn/native/Toggles.cpp
@@ -515,6 +515,12 @@
      {"disable_polyfills_on_integer_div_and_mod",
       "Disable the Tint polyfills on integer division and modulo.", "https://crbug.com/tint/2128",
       ToggleStage::Device}},
+    {Toggle::EnableImmediateErrorHandling,
+     {"enable_immediate_error_handling",
+      "Have the uncaptured error callback invoked immediately when an error occurs, rather than "
+      "waiting for the next Tick. This enables using the stack trace in which the uncaptured error "
+      "occured when breaking into the uncaptured error callback.",
+      "https://crbug.com/dawn/1789", ToggleStage::Device}},
     {Toggle::NoWorkaroundSampleMaskBecomesZeroForAllButLastColorTarget,
      {"no_workaround_sample_mask_becomes_zero_for_all_but_last_color_target",
       "MacOS 12.0+ Intel has a bug where the sample mask is only applied for the last color "
diff --git a/src/dawn/native/Toggles.h b/src/dawn/native/Toggles.h
index 4643bfb..efcc5cf 100644
--- a/src/dawn/native/Toggles.h
+++ b/src/dawn/native/Toggles.h
@@ -128,6 +128,7 @@
     ExposeWGSLTestingFeatures,
     ExposeWGSLExperimentalFeatures,
     DisablePolyfillsOnIntegerDivisonAndModulo,
+    EnableImmediateErrorHandling,
 
     // Unresolved issues.
     NoWorkaroundSampleMaskBecomesZeroForAllButLastColorTarget,