Convert a few remaining DAWN_VALIDATION_ERROR.

There are still DAWN_VALIDATION_ERROR occurences left but they don't use
any format string so it is fine to merge DAWN_FORMAT_VALIDATION_ERROR
into DAWN_VALIDATION_ERROR in follow-up CLs.

Bug: dawn:563
Change-Id: Ic1ba1de44216b36ef6a972712b957685e0ee193e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/100467
Reviewed-by: Austin Eng <enga@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/generator/templates/dawn/native/ChainUtils.cpp b/generator/templates/dawn/native/ChainUtils.cpp
index 2973788..71f932e 100644
--- a/generator/templates/dawn/native/ChainUtils.cpp
+++ b/generator/templates/dawn/native/ChainUtils.cpp
@@ -40,26 +40,25 @@
                           std::vector<std::vector<{{namespace}}::SType>> oneOfConstraints) {
     std::unordered_set<{{namespace}}::SType> allSTypes;
     for (; chain; chain = chain->nextInChain) {
-        if (allSTypes.find(chain->sType) != allSTypes.end()) {
-            return DAWN_VALIDATION_ERROR("Chain cannot have duplicate sTypes");
-        }
+        DAWN_INVALID_IF(allSTypes.find(chain->sType) != allSTypes.end(),
+            "Extension chain has duplicate sType %s.", chain->sType);
         allSTypes.insert(chain->sType);
     }
+
     for (const auto& oneOfConstraint : oneOfConstraints) {
         bool satisfied = false;
         for ({{namespace}}::SType oneOfSType : oneOfConstraint) {
             if (allSTypes.find(oneOfSType) != allSTypes.end()) {
-                if (satisfied) {
-                    return DAWN_VALIDATION_ERROR("Unsupported sType combination");
-                }
+                DAWN_INVALID_IF(satisfied,
+                    "sType %s is part of a group of exclusive sTypes that is already present.",
+                    oneOfSType);
                 satisfied = true;
                 allSTypes.erase(oneOfSType);
             }
         }
     }
-    if (!allSTypes.empty()) {
-        return DAWN_VALIDATION_ERROR("Unsupported sType");
-    }
+
+    DAWN_INVALID_IF(!allSTypes.empty(), "Unsupported sType %s.", *allSTypes.begin());
     return {};
 }
 
diff --git a/generator/templates/dawn/native/ValidationUtils.cpp b/generator/templates/dawn/native/ValidationUtils.cpp
index 1cb78c6..a5efb01 100644
--- a/generator/templates/dawn/native/ValidationUtils.cpp
+++ b/generator/templates/dawn/native/ValidationUtils.cpp
@@ -29,7 +29,7 @@
                         return {};
                 {% endfor %}
                 default:
-                    return DAWN_VALIDATION_ERROR("Invalid value for {{as_cType(type.name)}}");
+                    return DAWN_FORMAT_VALIDATION_ERROR("Value %i is invalid for {{as_cType(type.name)}}.", static_cast<uint32_t>(value));
             }
         }
 
@@ -40,7 +40,7 @@
             if ((value & static_cast<{{namespace}}::{{as_cppType(type.name)}}>(~{{type.full_mask}})) == 0) {
                 return {};
             }
-            return DAWN_VALIDATION_ERROR("Invalid value for {{as_cType(type.name)}}");
+            return DAWN_FORMAT_VALIDATION_ERROR("Value %i is invalid for {{as_cType(type.name)}}.", static_cast<uint32_t>(value));
         }
 
     {% endfor %}
diff --git a/src/dawn/native/PipelineLayout.cpp b/src/dawn/native/PipelineLayout.cpp
index 8365f6d..c740a71 100644
--- a/src/dawn/native/PipelineLayout.cpp
+++ b/src/dawn/native/PipelineLayout.cpp
@@ -32,23 +32,20 @@
 MaybeError ValidatePipelineLayoutDescriptor(DeviceBase* device,
                                             const PipelineLayoutDescriptor* descriptor,
                                             PipelineCompatibilityToken pipelineCompatibilityToken) {
-    if (descriptor->nextInChain != nullptr) {
-        return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
-    }
-
-    if (descriptor->bindGroupLayoutCount > kMaxBindGroups) {
-        return DAWN_VALIDATION_ERROR("too many bind group layouts");
-    }
+    DAWN_INVALID_IF(descriptor->nextInChain != nullptr, "nextInChain is not nullptr.");
+    DAWN_INVALID_IF(descriptor->bindGroupLayoutCount > kMaxBindGroups,
+                    "bindGroupLayoutCount (%i) is larger than the maximum allowed (%i).",
+                    descriptor->bindGroupLayoutCount, kMaxBindGroups);
 
     BindingCounts bindingCounts = {};
     for (uint32_t i = 0; i < descriptor->bindGroupLayoutCount; ++i) {
         DAWN_TRY(device->ValidateObject(descriptor->bindGroupLayouts[i]));
-        if (descriptor->bindGroupLayouts[i]->GetPipelineCompatibilityToken() !=
-            pipelineCompatibilityToken) {
-            return DAWN_VALIDATION_ERROR(
-                "cannot create a pipeline layout using a bind group layout that was created as "
-                "part of a pipeline's default layout");
-        }
+        DAWN_INVALID_IF(descriptor->bindGroupLayouts[i]->GetPipelineCompatibilityToken() !=
+                            pipelineCompatibilityToken,
+                        "bindGroupLayouts[%i] (%s) is used to create a pipeline layout but it was "
+                        "created as part of a pipeline's default layout.",
+                        i, descriptor->bindGroupLayouts[i]);
+
         AccumulateBindingCounts(&bindingCounts,
                                 descriptor->bindGroupLayouts[i]->GetBindingCountInfo());
     }
@@ -151,6 +148,8 @@
 
         // Check if any properties are incompatible with existing entry
         // If compatible, we will merge some properties
+        // TODO(dawn:563): Improve the error message by doing early-outs when bindings aren't
+        // compatible instead of a single check at the end.
         if (!compatible) {
             return DAWN_VALIDATION_ERROR(
                 "Duplicate binding in default pipeline layout initialization "
@@ -281,7 +280,9 @@
                 const auto& [existingEntry, inserted] =
                     entryData[group].insert({bindingNumber, entry});
                 if (!inserted) {
-                    DAWN_TRY(MergeEntries(&existingEntry->second, entry));
+                    DAWN_TRY_CONTEXT(MergeEntries(&existingEntry->second, entry),
+                                     "merging implicit bindings for @group(%u) @binding(%u).",
+                                     uint32_t(group), uint32_t(bindingNumber));
                 }
             }
         }
diff --git a/src/dawn/native/RenderPipeline.cpp b/src/dawn/native/RenderPipeline.cpp
index ed7f479..8a3d82a 100644
--- a/src/dawn/native/RenderPipeline.cpp
+++ b/src/dawn/native/RenderPipeline.cpp
@@ -177,9 +177,7 @@
 
 MaybeError ValidateDepthStencilState(const DeviceBase* device,
                                      const DepthStencilState* descriptor) {
-    if (descriptor->nextInChain != nullptr) {
-        return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
-    }
+    DAWN_INVALID_IF(descriptor->nextInChain != nullptr, "nextInChain is not nullptr.");
 
     DAWN_TRY(ValidateCompareFunction(descriptor->depthCompare));
     DAWN_TRY(ValidateCompareFunction(descriptor->stencilFront.compare));
diff --git a/src/dawn/native/metal/ShaderModuleMTL.mm b/src/dawn/native/metal/ShaderModuleMTL.mm
index e56eb22..5a72f30 100644
--- a/src/dawn/native/metal/ShaderModuleMTL.mm
+++ b/src/dawn/native/metal/ShaderModuleMTL.mm
@@ -335,8 +335,8 @@
                                                                       error:&error]);
                 if (error != nullptr) {
                     if (error.code != MTLLibraryErrorCompileWarning) {
-                        return DAWN_VALIDATION_ERROR(std::string("Function compile error: ") +
-                                                     [error.localizedDescription UTF8String]);
+                        return DAWN_FORMAT_VALIDATION_ERROR(
+                            "Function compile error: %s", [error.localizedDescription UTF8String]);
                     }
                 }
                 ASSERT(out->function != nil);
diff --git a/src/dawn/native/null/DeviceNull.cpp b/src/dawn/native/null/DeviceNull.cpp
index 0406921..a00515d 100644
--- a/src/dawn/native/null/DeviceNull.cpp
+++ b/src/dawn/native/null/DeviceNull.cpp
@@ -398,9 +398,8 @@
         // TODO(crbug.com/dawn/269): figure out what should happen when surfaces are used by
         // multiple backends one after the other. It probably needs to block until the backend
         // and GPU are completely finished with the previous swapchain.
-        if (previousSwapChain->GetBackendType() != wgpu::BackendType::Null) {
-            return DAWN_VALIDATION_ERROR("null::SwapChain cannot switch between APIs");
-        }
+        DAWN_INVALID_IF(previousSwapChain->GetBackendType() != wgpu::BackendType::Null,
+                        "null::SwapChain cannot switch between APIs");
     }
 
     return {};
diff --git a/src/dawn/tests/unittests/validation/TextureViewValidationTests.cpp b/src/dawn/tests/unittests/validation/TextureViewValidationTests.cpp
index 244e615..81aeb3b 100644
--- a/src/dawn/tests/unittests/validation/TextureViewValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/TextureViewValidationTests.cpp
@@ -604,7 +604,7 @@
 
     // Validation should catch the invalid aspect.
     ASSERT_DEVICE_ERROR(texture.CreateView(&viewDesc),
-                        testing::HasSubstr("Invalid value for WGPUTextureAspect"));
+                        testing::HasSubstr("is invalid for WGPUTextureAspect"));
 }
 
 // Test creating cube map texture view