Remove Acquire, Release, and Relaxed from allowed Mem Sem bits for WebGPU (#2526)

Fixes #2524
diff --git a/source/val/validate_memory_semantics.cpp b/source/val/validate_memory_semantics.cpp
index 5dece3f..31154f5 100644
--- a/source/val/validate_memory_semantics.cpp
+++ b/source/val/validate_memory_semantics.cpp
@@ -55,9 +55,7 @@
                           SpvMemorySemanticsMakeAvailableKHRMask |
                           SpvMemorySemanticsMakeVisibleKHRMask;
     if (!spvOpcodeIsAtomicOp(inst->opcode())) {
-      valid_bits |= SpvMemorySemanticsAcquireMask |
-                    SpvMemorySemanticsReleaseMask |
-                    SpvMemorySemanticsAcquireReleaseMask;
+      valid_bits |= SpvMemorySemanticsAcquireReleaseMask;
     }
 
     if (value & ~valid_bits) {
@@ -69,11 +67,18 @@
       } else {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "WebGPU spec disallows any bit masks in Memory Semantics "
-                  "that are not Acquire, Release, AcquireRelease, "
-                  "UniformMemory, WorkgroupMemory, ImageMemory, "
-                  "OutputMemoryKHR, MakeAvailableKHR, or MakeVisibleKHR";
+                  "that are not AcquireRelease, UniformMemory, "
+                  "WorkgroupMemory, ImageMemory, OutputMemoryKHR, "
+                  "MakeAvailableKHR, or MakeVisibleKHR";
       }
     }
+
+    if (!spvOpcodeIsAtomicOp(inst->opcode()) &&
+        !(value & SpvMemorySemanticsAcquireReleaseMask)) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << "WebGPU spec requires AcquireRelease to set in Memory "
+                "Semantics.";
+    }
   }
 
   const size_t num_memory_order_set_bits = spvtools::utils::CountSetBits(
diff --git a/test/val/val_barriers_test.cpp b/test/val/val_barriers_test.cpp
index 264d130..0b28c45 100644
--- a/test/val/val_barriers_test.cpp
+++ b/test/val/val_barriers_test.cpp
@@ -78,9 +78,13 @@
 %acquire_and_release = OpConstant %u32 6
 %sequentially_consistent = OpConstant %u32 16
 %acquire_release_uniform_workgroup = OpConstant %u32 328
+%acquire_uniform_workgroup = OpConstant %u32 322
+%release_uniform_workgroup = OpConstant %u32 324
 %acquire_and_release_uniform = OpConstant %u32 70
 %acquire_release_subgroup = OpConstant %u32 136
 %uniform = OpConstant %u32 64
+%uniform_workgroup = OpConstant %u32 320
+
 
 %main = OpFunction %void None %func
 %main_entry = OpLabel
@@ -245,9 +249,8 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
 }
 
-TEST_F(ValidateBarriers, OpControlBarrierWebGPUSuccess) {
+TEST_F(ValidateBarriers, OpControlBarrierWebGPUAcquireReleaseSuccess) {
   const std::string body = R"(
-OpControlBarrier %workgroup %queuefamily %none
 OpControlBarrier %workgroup %workgroup %acquire_release_uniform_workgroup
 )";
 
@@ -255,6 +258,41 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
 }
 
+TEST_F(ValidateBarriers, OpControlBarrierWebGPURelaxedFailure) {
+  const std::string body = R"(
+OpControlBarrier %workgroup %workgroup %uniform_workgroup
+)";
+
+  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("WebGPU spec requires AcquireRelease to set"));
+}
+
+TEST_F(ValidateBarriers, OpControlBarrierWebGPUAcquireFailure) {
+  const std::string body = R"(
+OpControlBarrier %workgroup %workgroup %acquire_uniform_workgroup
+)";
+
+  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("WebGPU spec disallows any bit masks in Memory Semantics"));
+}
+
+TEST_F(ValidateBarriers, OpControlBarrierWebGPUReleaseFailure) {
+  const std::string body = R"(
+OpControlBarrier %workgroup %workgroup %release_uniform_workgroup
+)";
+
+  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("WebGPU spec disallows any bit masks in Memory Semantics"));
+}
+
 TEST_F(ValidateBarriers, OpControlBarrierExecutionModelFragmentSpirv12) {
   const std::string body = R"(
 OpControlBarrier %device %device %none
@@ -630,6 +668,50 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
 }
 
+TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUAcquireReleaseSuccess) {
+  const std::string body = R"(
+OpMemoryBarrier %workgroup %acquire_release_uniform_workgroup
+)";
+
+  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
+}
+
+TEST_F(ValidateBarriers, OpMemoryBarrierWebGPURelaxedFailure) {
+  const std::string body = R"(
+OpMemoryBarrier %workgroup %uniform_workgroup
+)";
+
+  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("WebGPU spec requires AcquireRelease to set"));
+}
+
+TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUAcquireFailure) {
+  const std::string body = R"(
+OpMemoryBarrier %workgroup %acquire_uniform_workgroup
+)";
+
+  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("WebGPU spec disallows any bit masks in Memory Semantics"));
+}
+
+TEST_F(ValidateBarriers, OpMemoryBarrierWebGPUReleaseFailure) {
+  const std::string body = R"(
+OpMemoryBarrier %workgroup %release_uniform_workgroup
+)";
+
+  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
+  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("WebGPU spec disallows any bit masks in Memory Semantics"));
+}
+
 TEST_F(ValidateBarriers, OpMemoryBarrierFloatMemoryScope) {
   const std::string body = R"(
 OpMemoryBarrier %f32_1 %acquire_release_uniform_workgroup