Enable more context for command encoder errors

Addresses an issue pointed out by Brendan Duncan where some command
encoder errors were not providing appropriate context, such as the
command that was attempting to encode when the error was raised.

Change-Id: I703cbe2d471a352c32c6e526d44042dd33cddac7
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/192245
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Brandon Jones <bajones@chromium.org>
diff --git a/src/dawn/native/CommandEncoder.cpp b/src/dawn/native/CommandEncoder.cpp
index 92556e4..f9eb82f 100644
--- a/src/dawn/native/CommandEncoder.cpp
+++ b/src/dawn/native/CommandEncoder.cpp
@@ -139,7 +139,7 @@
         Extent3D renderSize = attachment->GetSingleSubresourceVirtualSize();
         Extent3D attachmentValidationSize = renderSize;
         if (attachment->GetTexture()->GetFormat().IsMultiPlanar()) {
-            // For multi-planar texture, D3D requires depth stencil buffer size mush be equal to the
+            // For multi-planar texture, D3D requires depth stencil buffer size must be equal to the
             // size of the plane 0 for the color attachment texture (`attachmentValidationSize`).
             // Vulkan, Metal and GL requires buffer size equal or bigger than render size. To make
             // all dawn backends work, dawn requires depth attachment's size equal to the
@@ -2065,7 +2065,8 @@
 }
 
 void CommandEncoder::APIInjectValidationError(const char* message) {
-    if (mEncodingContext.CheckCurrentEncoder(this)) {
+    if (!mEncodingContext.ConsumedError(mEncodingContext.CheckCurrentEncoder(this),
+                                        "injecting validation error: %s.", message)) {
         mEncodingContext.HandleError(DAWN_MAKE_ERROR(InternalErrorType::Validation, message));
     }
 }
diff --git a/src/dawn/native/EncodingContext.h b/src/dawn/native/EncodingContext.h
index b6ebc4d..601c5fe 100644
--- a/src/dawn/native/EncodingContext.h
+++ b/src/dawn/native/EncodingContext.h
@@ -93,38 +93,32 @@
         return false;
     }
 
-    inline bool CheckCurrentEncoder(const ApiObjectBase* encoder) {
-        if (mDestroyed) {
-            HandleError(DAWN_VALIDATION_ERROR("Recording in a destroyed %s.", mCurrentEncoder));
-            return false;
-        }
+    inline MaybeError CheckCurrentEncoder(const ApiObjectBase* encoder) {
+        DAWN_INVALID_IF(mDestroyed, "Recording in a destroyed %s.", mCurrentEncoder);
+
         if (DAWN_UNLIKELY(encoder != mCurrentEncoder)) {
-            if (mCurrentEncoder != mTopLevelEncoder) {
-                // The top level encoder was used when a pass encoder was current.
-                HandleError(DAWN_VALIDATION_ERROR(
-                    "Command cannot be recorded while %s is locked and %s is currently open.",
-                    mTopLevelEncoder, mCurrentEncoder));
-            } else if (mTopLevelEncoder == nullptr) {
-                // Note: mTopLevelEncoder == nullptr is used as a flag for if Finish() has been
-                // called.
-                if (encoder->GetType() == ObjectType::CommandEncoder ||
-                    encoder->GetType() == ObjectType::RenderBundleEncoder) {
-                    HandleError(DAWN_VALIDATION_ERROR("%s is already finished.", encoder));
-                } else {
-                    HandleError(DAWN_VALIDATION_ERROR("Parent encoder of %s is already finished.",
-                                                      encoder));
-                }
-            } else {
-                HandleError(DAWN_VALIDATION_ERROR("Recording in an error %s.", encoder));
+            // The top level encoder was used when a pass encoder was current.
+            DAWN_INVALID_IF(
+                mCurrentEncoder != mTopLevelEncoder,
+                "Command cannot be recorded while %s is locked and %s is currently open.",
+                mTopLevelEncoder, mCurrentEncoder);
+
+            // Note: mTopLevelEncoder == nullptr is used as a flag for if Finish() has been called.
+            if (mTopLevelEncoder == nullptr) {
+                DAWN_INVALID_IF(encoder->GetType() == ObjectType::CommandEncoder ||
+                                    encoder->GetType() == ObjectType::RenderBundleEncoder,
+                                "%s is already finished.", encoder);
+
+                return DAWN_VALIDATION_ERROR("Parent encoder of %s is already finished.", encoder);
             }
-            return false;
+            return DAWN_VALIDATION_ERROR("Recording in an error %s.", encoder);
         }
-        return true;
+        return {};
     }
 
     template <typename EncodeFunction>
     inline bool TryEncode(const ApiObjectBase* encoder, EncodeFunction&& encodeFunction) {
-        if (!CheckCurrentEncoder(encoder)) {
+        if (ConsumedError(CheckCurrentEncoder(encoder))) {
             return false;
         }
         DAWN_ASSERT(!mWasMovedToIterator);
@@ -136,7 +130,7 @@
                           EncodeFunction&& encodeFunction,
                           const char* formatStr,
                           const Args&... args) {
-        if (!CheckCurrentEncoder(encoder)) {
+        if (ConsumedError(CheckCurrentEncoder(encoder), formatStr, args...)) {
             return false;
         }
         DAWN_ASSERT(!mWasMovedToIterator);