[dawn][native] Tighten MapMode validation to check for values.

- Currently, WebGPU doesn't actually use MapMode as a bitmask, so
  validate it as a value for now. If/when we relax this and allow
  for cases where we can have multiple map modes, then relax the
  validation.

Bug: 492403441
Change-Id: I5edc63917a57ec2dfe8b98ea128ea79f6c5e4b9a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/298435
Reviewed-by: Brandon Jones <bajones@chromium.org>
Auto-Submit: Loko Kung <lokokung@google.com>
Commit-Queue: Loko Kung <lokokung@google.com>
diff --git a/src/dawn/native/Buffer.cpp b/src/dawn/native/Buffer.cpp
index 1d763f6..617d5c3 100644
--- a/src/dawn/native/Buffer.cpp
+++ b/src/dawn/native/Buffer.cpp
@@ -951,22 +951,25 @@
                     "Mapping range (offset:%u, size: %u) doesn't fit in the size (%u) of %s.",
                     offset, size, mSize, this);
 
-    bool isReadMode = mode & wgpu::MapMode::Read;
-    bool isWriteMode = mode & wgpu::MapMode::Write;
-    DAWN_INVALID_IF(!(isReadMode ^ isWriteMode), "Map mode (%s) is not one of %s or %s.", mode,
-                    wgpu::MapMode::Write, wgpu::MapMode::Read);
-
-    if (mode & wgpu::MapMode::Read) {
-        DAWN_INVALID_IF(!(mInternalUsage & wgpu::BufferUsage::MapRead),
-                        "The buffer usages (%s) do not contain %s.", mInternalUsage,
-                        wgpu::BufferUsage::MapRead);
-    } else {
-        DAWN_ASSERT(mode & wgpu::MapMode::Write);
-        DAWN_INVALID_IF(!(mInternalUsage & wgpu::BufferUsage::MapWrite),
-                        "The buffer usages (%s) do not contain %s.", mInternalUsage,
-                        wgpu::BufferUsage::MapWrite);
+    // If/when we allow multiple map modes at the same time for a map call, relax the restrictions
+    // that using a switch/case implicitly implies for the bitmask.
+    switch (mode) {
+        case wgpu::MapMode::Read: {
+            DAWN_INVALID_IF(!(mInternalUsage & wgpu::BufferUsage::MapRead),
+                            "The buffer usages (%s) do not contain %s.", mInternalUsage,
+                            wgpu::BufferUsage::MapRead);
+            break;
+        }
+        case wgpu::MapMode::Write: {
+            DAWN_INVALID_IF(!(mInternalUsage & wgpu::BufferUsage::MapWrite),
+                            "The buffer usages (%s) do not contain %s.", mInternalUsage,
+                            wgpu::BufferUsage::MapWrite);
+            break;
+        }
+        default:
+            return DAWN_VALIDATION_ERROR("Map mode (%s) is not one of %s or %s.", mode,
+                                         wgpu::MapMode::Write, wgpu::MapMode::Read);
     }
-
     return {};
 }
 
diff --git a/src/dawn/tests/unittests/validation/BufferValidationTests.cpp b/src/dawn/tests/unittests/validation/BufferValidationTests.cpp
index 716f0bf..3f14378 100644
--- a/src/dawn/tests/unittests/validation/BufferValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/BufferValidationTests.cpp
@@ -248,6 +248,18 @@
     AssertMapAsyncError(buffer, GetParam(), 0, 4);
 }
 
+// Test map async with a mode that includes exactly one valid mode, but is an invalid value.
+TEST_P(BufferMappingValidationTest, MapAsync_UnsupportedMode) {
+    wgpu::Buffer buffer = CreateBuffer(4);
+
+    // Create an invalid map mode that includes the valid mode.
+    static constexpr wgpu::MapMode kInvalidMapModeBits =
+        ~(wgpu::MapMode::Read | wgpu::MapMode::Write);
+    wgpu::MapMode mode = kInvalidMapModeBits | GetParam();
+
+    AssertMapAsyncError(buffer, mode, 0, 4);
+}
+
 // Test map async with an invalid offset and size alignment.
 TEST_P(BufferMappingValidationTest, MapAsync_OffsetSizeAlignment) {
     // Control case, offset aligned to 8 and size to 4 is valid