Change validation of memory semantics for OpAtomics* in WebGPU (#2519)

Recent change to the spec restricted the valid values for Memory
Semantics in OpAtomics* in the WebGPU env. Implementing enforcing
these changes.

Fixes #2499
diff --git a/source/val/validate_memory_semantics.cpp b/source/val/validate_memory_semantics.cpp
index f90b5e4..5dece3f 100644
--- a/source/val/validate_memory_semantics.cpp
+++ b/source/val/validate_memory_semantics.cpp
@@ -48,21 +48,31 @@
   }
 
   if (spvIsWebGPUEnv(_.context()->target_env)) {
-    uint32_t valid_bits = SpvMemorySemanticsAcquireMask |
-                          SpvMemorySemanticsReleaseMask |
-                          SpvMemorySemanticsAcquireReleaseMask |
-                          SpvMemorySemanticsUniformMemoryMask |
+    uint32_t valid_bits = SpvMemorySemanticsUniformMemoryMask |
                           SpvMemorySemanticsWorkgroupMemoryMask |
                           SpvMemorySemanticsImageMemoryMask |
                           SpvMemorySemanticsOutputMemoryKHRMask |
                           SpvMemorySemanticsMakeAvailableKHRMask |
                           SpvMemorySemanticsMakeVisibleKHRMask;
+    if (!spvOpcodeIsAtomicOp(inst->opcode())) {
+      valid_bits |= SpvMemorySemanticsAcquireMask |
+                    SpvMemorySemanticsReleaseMask |
+                    SpvMemorySemanticsAcquireReleaseMask;
+    }
+
     if (value & ~valid_bits) {
-      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";
+      if (spvOpcodeIsAtomicOp(inst->opcode())) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "WebGPU spec disallows, for OpAtomic*, any bit masks in "
+                  "Memory Semantics that are not UniformMemory, "
+                  "WorkgroupMemory, ImageMemory, or OutputMemoryKHR";
+      } 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";
+      }
     }
   }
 
diff --git a/test/val/val_atomics_test.cpp b/test/val/val_atomics_test.cpp
index 2090c13..1be19c5 100644
--- a/test/val/val_atomics_test.cpp
+++ b/test/val/val_atomics_test.cpp
@@ -373,30 +373,37 @@
           "AtomicLoad: 64-bit atomics require the Int64Atomics capability"));
 }
 
-TEST_F(ValidateAtomics, AtomicLoadWebGPUShaderSuccess) {
+TEST_F(ValidateAtomics, AtomicLoadWebGPUSuccess) {
   const std::string body = R"(
 %val1 = OpAtomicLoad %u32 %u32_var %queuefamily %relaxed
-%val2 = OpAtomicLoad %u32 %u32_var %workgroup %acquire
+%val2 = OpAtomicLoad %u32 %u32_var %workgroup %relaxed
 )";
 
   CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
 }
 
-TEST_F(ValidateAtomics, AtomicLoadWebGPUShaderSequentiallyConsistentFailure) {
+TEST_F(ValidateAtomics, AtomicLoadWebGPUNonRelaxedFailure) {
+  const std::string body = R"(
+%val1 = OpAtomicLoad %u32 %u32_var %queuefamily %acquire
+%val2 = OpAtomicLoad %u32 %u32_var %workgroup %release
+)";
+
+  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("WebGPU spec disallows, for OpAtomic*, any bit masks"));
+}
+
+TEST_F(ValidateAtomics, AtomicLoadWebGPUSequentiallyConsistentFailure) {
   const std::string body = R"(
 %val3 = OpAtomicLoad %u32 %u32_var %subgroup %sequentially_consistent
 )";
 
   CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr(
-          "WebGPU spec disallows any bit masks in Memory Semantics that are "
-          "not Acquire, Release, AcquireRelease, UniformMemory, "
-          "WorkgroupMemory, ImageMemory, OutputMemoryKHR, MakeAvailableKHR, or "
-          "MakeVisibleKHR\n  %34 = OpAtomicLoad %uint %29 %uint_3 %uint_16\n"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("WebGPU spec disallows, for OpAtomic*, any bit masks"));
 }
 
 TEST_F(ValidateAtomics, VK_KHR_shader_atomic_int64Success) {
@@ -579,13 +586,24 @@
 
 TEST_F(ValidateAtomics, AtomicStoreWebGPUSuccess) {
   const std::string body = R"(
-OpAtomicStore %u32_var %queuefamily %release %u32_1
+OpAtomicStore %u32_var %queuefamily %relaxed %u32_1
 )";
 
   CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
 }
 
+TEST_F(ValidateAtomics, AtomicStoreWebGPUNonRelaxedFailure) {
+  const std::string body = R"(
+OpAtomicStore %u32_var %queuefamily %release %u32_1
+)";
+
+  CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("WebGPU spec disallows, for OpAtomic*, any bit masks"));
+}
+
 TEST_F(ValidateAtomics, AtomicStoreWebGPUSequentiallyConsistent) {
   const std::string body = R"(
 OpAtomicStore %u32_var %queuefamily %sequentially_consistent %u32_1
@@ -593,14 +611,8 @@
 
   CompileSuccessfully(GenerateWebGPUShaderCode(body), SPV_ENV_WEBGPU_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_WEBGPU_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr(
-          "WebGPU spec disallows any bit masks in Memory Semantics that are "
-          "not Acquire, Release, AcquireRelease, UniformMemory, "
-          "WorkgroupMemory, ImageMemory, OutputMemoryKHR, MakeAvailableKHR, or "
-          "MakeVisibleKHR\n"
-          "  OpAtomicStore %29 %uint_5 %uint_16 %uint_1\n"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("WebGPU spec disallows, for OpAtomic*, any bit masks"));
 }
 
 TEST_F(ValidateAtomics, AtomicStoreWrongPointerType) {