EncodingContext: Forward the backtrace of stored errors.

This makes error messages from command buffers more useful because they
keep the whole stack trace instead of just showing that the error was
created in the CommandBuffer::Finish call.

Bug: dawn:632
Change-Id: I23e66045c3caa1ad086003a04eed78c40aefc562
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/49885
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn_native/CommandEncoder.cpp b/src/dawn_native/CommandEncoder.cpp
index 21060e4..1bd2efd 100644
--- a/src/dawn_native/CommandEncoder.cpp
+++ b/src/dawn_native/CommandEncoder.cpp
@@ -815,7 +815,7 @@
 
     void CommandEncoder::APIInjectValidationError(const char* message) {
         if (mEncodingContext.CheckCurrentEncoder(this)) {
-            mEncodingContext.HandleError(InternalErrorType::Validation, message);
+            mEncodingContext.HandleError(DAWN_VALIDATION_ERROR(message));
         }
     }
 
diff --git a/src/dawn_native/EncodingContext.cpp b/src/dawn_native/EncodingContext.cpp
index acdecd7..1752f6c 100644
--- a/src/dawn_native/EncodingContext.cpp
+++ b/src/dawn_native/EncodingContext.cpp
@@ -53,18 +53,17 @@
         }
     }
 
-    void EncodingContext::HandleError(InternalErrorType type, const char* message) {
+    void EncodingContext::HandleError(std::unique_ptr<ErrorData> error) {
         if (!IsFinished()) {
             // Encoding should only generate validation errors.
-            ASSERT(type == InternalErrorType::Validation);
+            ASSERT(error->GetType() == InternalErrorType::Validation);
             // If the encoding context is not finished, errors are deferred until
             // Finish() is called.
-            if (!mGotError) {
-                mGotError = true;
-                mErrorMessage = message;
+            if (mError == nullptr) {
+                mError = std::move(error);
             }
         } else {
-            mDevice->HandleError(type, message);
+            mDevice->HandleError(error->GetType(), error->GetMessage().c_str());
         }
     }
 
@@ -129,8 +128,8 @@
         mCurrentEncoder = nullptr;
         mTopLevelEncoder = nullptr;
 
-        if (mGotError) {
-            return DAWN_VALIDATION_ERROR(mErrorMessage);
+        if (mError != nullptr) {
+            return std::move(mError);
         }
         if (currentEncoder != topLevelEncoder) {
             return DAWN_VALIDATION_ERROR("Command buffer recording ended mid-pass");
diff --git a/src/dawn_native/EncodingContext.h b/src/dawn_native/EncodingContext.h
index f181e57..7d0f88d 100644
--- a/src/dawn_native/EncodingContext.h
+++ b/src/dawn_native/EncodingContext.h
@@ -39,15 +39,11 @@
         CommandIterator* GetIterator();
 
         // Functions to handle encoder errors
-        void HandleError(InternalErrorType type, const char* message);
-
-        inline void ConsumeError(std::unique_ptr<ErrorData> error) {
-            HandleError(error->GetType(), error->GetMessage().c_str());
-        }
+        void HandleError(std::unique_ptr<ErrorData> error);
 
         inline bool ConsumedError(MaybeError maybeError) {
             if (DAWN_UNLIKELY(maybeError.IsError())) {
-                ConsumeError(maybeError.AcquireError());
+                HandleError(maybeError.AcquireError());
                 return true;
             }
             return false;
@@ -57,11 +53,10 @@
             if (DAWN_UNLIKELY(encoder != mCurrentEncoder)) {
                 if (mCurrentEncoder != mTopLevelEncoder) {
                     // The top level encoder was used when a pass encoder was current.
-                    HandleError(InternalErrorType::Validation,
-                                "Command cannot be recorded inside a pass");
+                    HandleError(DAWN_VALIDATION_ERROR("Command cannot be recorded inside a pass"));
                 } else {
-                    HandleError(InternalErrorType::Validation,
-                                "Recording in an error or already ended pass encoder");
+                    HandleError(DAWN_VALIDATION_ERROR(
+                        "Recording in an error or already ended pass encoder"));
                 }
                 return false;
             }
@@ -113,8 +108,7 @@
         bool mWasMovedToIterator = false;
         bool mWereCommandsAcquired = false;
 
-        bool mGotError = false;
-        std::string mErrorMessage;
+        std::unique_ptr<ErrorData> mError;
     };
 
 }  // namespace dawn_native