[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