Support read-only and read-write storage textures as unsafe apis

This patch makes read-only and read-write storage textures a part of
WebGPU core feature behind toggle "allow-unsafe-apis" and makes the
original experimental extension a no-op one for compatibility.

Bug: dawn:1972
Change-Id: Ic7c0d27db4681f621793d10cced560f6d3ea7d64
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/157521
Reviewed-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/dawn/native/BindGroupLayoutInternal.cpp b/src/dawn/native/BindGroupLayoutInternal.cpp
index c263589..53940d9 100644
--- a/src/dawn/native/BindGroupLayoutInternal.cpp
+++ b/src/dawn/native/BindGroupLayoutInternal.cpp
@@ -83,13 +83,10 @@
     switch (storageTextureBindingLayout.access) {
         case wgpu::StorageTextureAccess::ReadOnly:
         case wgpu::StorageTextureAccess::ReadWrite:
-            if (!device->APIHasFeature(
-                    wgpu::FeatureName::ChromiumExperimentalReadWriteStorageTexture)) {
+            if (!device->IsToggleEnabled(Toggle::AllowUnsafeAPIs)) {
                 return DAWN_VALIDATION_ERROR(
-                    "storage texture access %s cannot be used without feature "
-                    "%s",
-                    storageTextureBindingLayout.access,
-                    wgpu::FeatureName::ChromiumExperimentalReadWriteStorageTexture);
+                    "storage texture access %s is guarded by toggle allow_unsafe_apis",
+                    storageTextureBindingLayout.access);
             }
             break;
 
diff --git a/src/dawn/native/Format.cpp b/src/dawn/native/Format.cpp
index a81327a..6da03b5 100644
--- a/src/dawn/native/Format.cpp
+++ b/src/dawn/native/Format.cpp
@@ -437,7 +437,7 @@
 
     // 4 bytes color formats
     SampleTypeBit sampleTypeFor32BitFloatFormats = device->HasFeature(Feature::Float32Filterable) ? kAnyFloat : SampleTypeBit::UnfilterableFloat;
-    auto supportsReadWriteStorageUsage = device->HasFeature(Feature::ChromiumExperimentalReadWriteStorageTexture) ? Cap::StorageRW : Cap::None;
+    auto supportsReadWriteStorageUsage = device->IsToggleEnabled(Toggle::AllowUnsafeAPIs) ? Cap::StorageRW : Cap::None;
     auto supportsPLS = device->HasFeature(Feature::PixelLocalStorageCoherent) || device->HasFeature(Feature::PixelLocalStorageNonCoherent) ? Cap::PLS : Cap::None;
 
     AddColorFormat(wgpu::TextureFormat::R32Uint, Cap::Renderable | Cap::StorageW | supportsReadWriteStorageUsage | supportsPLS, ByteSize(4), SampleTypeBit::Uint, ComponentCount(1), RenderTargetPixelByteCost(4), RenderTargetComponentAlignment(4));
diff --git a/src/dawn/tests/end2end/StorageTextureTests.cpp b/src/dawn/tests/end2end/StorageTextureTests.cpp
index 7da7872..9de0161 100644
--- a/src/dawn/tests/end2end/StorageTextureTests.cpp
+++ b/src/dawn/tests/end2end/StorageTextureTests.cpp
@@ -1031,28 +1031,10 @@
                       MetalBackend({"nonzero_clear_resources_on_creation_for_testing"}),
                       VulkanBackend({"nonzero_clear_resources_on_creation_for_testing"}));
 
-class ReadWriteStorageTextureTests : public StorageTextureTests {
-  public:
-    std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
-        if (SupportsFeatures({wgpu::FeatureName::ChromiumExperimentalReadWriteStorageTexture})) {
-            mIsReadWriteStorageTextureSupported = true;
-            return {wgpu::FeatureName::ChromiumExperimentalReadWriteStorageTexture};
-        } else {
-            mIsReadWriteStorageTextureSupported = false;
-            return {};
-        }
-    }
-
-    bool IsReadWriteStorageTextureSupported() { return mIsReadWriteStorageTextureSupported; }
-
-  private:
-    bool mIsReadWriteStorageTextureSupported = false;
-};
+class ReadWriteStorageTextureTests : public StorageTextureTests {};
 
 // Verify read-write storage texture can work correctly in compute shaders.
 TEST_P(ReadWriteStorageTextureTests, ReadWriteStorageTextureInComputeShader) {
-    DAWN_TEST_UNSUPPORTED_IF(!IsReadWriteStorageTextureSupported());
-
     std::array<uint32_t, kWidth * kHeight> inputData;
     std::array<uint32_t, kWidth * kHeight> expectedData;
     for (size_t i = 0; i < inputData.size(); ++i) {
@@ -1066,7 +1048,6 @@
 
     std::ostringstream sstream;
     sstream << R"(
-enable chromium_experimental_read_write_storage_texture;
 @group(0) @binding(0) var rwImage : texture_storage_2d<r32uint, read_write>;
 
 @compute @workgroup_size()"
@@ -1098,8 +1079,6 @@
 
 // Verify read-write storage texture can work correctly in fragment shaders.
 TEST_P(ReadWriteStorageTextureTests, ReadWriteStorageTextureInFragmentShader) {
-    DAWN_TEST_UNSUPPORTED_IF(!IsReadWriteStorageTextureSupported());
-
     std::array<uint32_t, kWidth * kHeight> inputData;
     std::array<uint32_t, kWidth * kHeight> expectedData;
     for (size_t i = 0; i < inputData.size(); ++i) {
@@ -1130,7 +1109,6 @@
 })");
 
     wgpu::ShaderModule fsModule = utils::CreateShaderModule(device, R"(
-enable chromium_experimental_read_write_storage_texture;
 @group(0) @binding(0) var rwImage : texture_storage_2d<r32uint, read_write>;
 @fragment fn main(@builtin(position) fragcoord: vec4f) -> @location(0) vec4f {
     var data1 = textureLoad(rwImage, vec2i(fragcoord.xy));
@@ -1167,8 +1145,6 @@
 
 // Verify read-only storage texture can work correctly in compute shaders.
 TEST_P(ReadWriteStorageTextureTests, ReadOnlyStorageTextureInComputeShader) {
-    DAWN_TEST_UNSUPPORTED_IF(!IsReadWriteStorageTextureSupported());
-
     constexpr wgpu::TextureFormat kStorageTextureFormat = wgpu::TextureFormat::R32Uint;
     const std::vector<uint8_t> kInitialTextureData = GetExpectedData(kStorageTextureFormat);
     wgpu::Texture readonlyStorageTexture = CreateTextureWithTestData(
@@ -1176,7 +1152,6 @@
 
     std::ostringstream sstream;
     sstream << R"(
-enable chromium_experimental_read_write_storage_texture;
 @group(0) @binding(0) var srcImage : texture_storage_2d<r32uint, read>;
 @group(0) @binding(1) var<storage, read_write> output : u32;
 
@@ -1222,8 +1197,6 @@
 
 // Verify read-only storage texture can work correctly in vertex shaders.
 TEST_P(ReadWriteStorageTextureTests, ReadOnlyStorageTextureInVertexShader) {
-    DAWN_TEST_UNSUPPORTED_IF(!IsReadWriteStorageTextureSupported());
-
     // TODO(dawn:1972): Implement read-only storage texture as sampled texture in vertex shader.
     DAWN_SUPPRESS_TEST_IF(IsOpenGLES());
 
@@ -1234,7 +1207,6 @@
 
     std::ostringstream vsstream;
     vsstream << R"(
-enable chromium_experimental_read_write_storage_texture;
 @group(0) @binding(0) var srcImage : texture_storage_2d<r32uint, read>;
 
 struct VertexOutput {
@@ -1274,8 +1246,6 @@
 
 // Verify read-only storage texture can work correctly in fragment shaders.
 TEST_P(ReadWriteStorageTextureTests, ReadOnlyStorageTextureInFragmentShader) {
-    DAWN_TEST_UNSUPPORTED_IF(!IsReadWriteStorageTextureSupported());
-
     constexpr wgpu::TextureFormat kStorageTextureFormat = wgpu::TextureFormat::R32Uint;
     const std::vector<uint8_t> kInitialTextureData = GetExpectedData(kStorageTextureFormat);
     wgpu::Texture readonlyStorageTexture = CreateTextureWithTestData(
@@ -1283,7 +1253,6 @@
 
     std::ostringstream fsstream;
     fsstream << R"(
-enable chromium_experimental_read_write_storage_texture;
 @group(0) @binding(0) var srcImage : texture_storage_2d<r32uint, read>;
 
 @fragment fn main() -> @location(0) vec4f {
@@ -1307,8 +1276,6 @@
 // Verify using read-write storage texture access in pipeline layout is compatible with write-only
 // storage texture access in shader.
 TEST_P(ReadWriteStorageTextureTests, ReadWriteInPipelineLayoutAndWriteOnlyInShader) {
-    DAWN_TEST_UNSUPPORTED_IF(!IsReadWriteStorageTextureSupported());
-
     constexpr wgpu::TextureFormat kStorageTextureFormat = wgpu::TextureFormat::R32Uint;
     std::array<uint32_t, kWidth * kHeight> expectedData;
     for (size_t i = 0; i < expectedData.size(); ++i) {
@@ -1321,7 +1288,6 @@
 
     std::ostringstream sstream;
     sstream << R"(
-enable chromium_experimental_read_write_storage_texture;
 @group(0) @binding(0) var rwImage : texture_storage_2d<r32uint, write>;
 
 @compute @workgroup_size()"
diff --git a/src/dawn/tests/unittests/validation/StorageTextureValidationTests.cpp b/src/dawn/tests/unittests/validation/StorageTextureValidationTests.cpp
index 8771973..8e50d37 100644
--- a/src/dawn/tests/unittests/validation/StorageTextureValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/StorageTextureValidationTests.cpp
@@ -86,25 +86,17 @@
         wgpu::StorageTextureAccess storageTextureBindingType,
         wgpu::TextureFormat textureFormat,
         const char* imageTypeDeclaration = "texture_storage_2d",
-        bool disableReadWriteStorageTextureExtension = false,
         wgpu::ShaderStage shaderStage = wgpu::ShaderStage::Compute) {
         const char* access = "";
-        const char* extension = "";
         switch (storageTextureBindingType) {
             case wgpu::StorageTextureAccess::WriteOnly:
                 access = "write";
                 break;
             case wgpu::StorageTextureAccess::ReadOnly:
                 access = "read";
-                if (!disableReadWriteStorageTextureExtension) {
-                    extension = "enable chromium_experimental_read_write_storage_texture;\n";
-                }
                 break;
             case wgpu::StorageTextureAccess::ReadWrite:
                 access = "read_write";
-                if (!disableReadWriteStorageTextureExtension) {
-                    extension = "enable chromium_experimental_read_write_storage_texture;\n";
-                }
                 break;
             default:
                 DAWN_UNREACHABLE();
@@ -125,12 +117,19 @@
         }
 
         std::ostringstream ostream;
-        ostream << extension << "@group(0) @binding(0) var image0 : " << imageTypeDeclaration << "<"
+        ostream << "@group(0) @binding(0) var image0 : " << imageTypeDeclaration << "<"
                 << utils::GetWGSLImageFormatQualifier(textureFormat) << ", " << access << ">;\n"
-                << shaderStageDeclaration
-                << " fn main() {\n"
-                   "    _ = textureDimensions(image0);\n"
-                   "}\n";
+                << shaderStageDeclaration << " fn main()";
+        if (shaderStage == wgpu::ShaderStage::Vertex) {
+            ostream << " -> @builtin(position) vec4f ";
+        }
+
+        ostream << "{\n"
+                   "    _ = textureDimensions(image0);\n";
+        if (shaderStage == wgpu::ShaderStage::Vertex) {
+            ostream << "    return vec4f(0.0);";
+        }
+        ostream << "}\n";
 
         return ostream.str();
     }
@@ -218,15 +217,15 @@
     }
 }
 
-// Validate both read-only and write-only storage textures can be declared in
-// compute shaders.
+// Validate both read-only and write-only storage textures can be declared in compute shaders.
 TEST_F(StorageTextureValidationTests, ComputePipeline) {
     // Write-only storage textures can be declared in a compute shader.
     {
         wgpu::ShaderModule csModule = utils::CreateShaderModule(device, R"(
             @group(0) @binding(0) var image0 : texture_storage_2d<rgba8unorm, write>;
 
-            @compute @workgroup_size(1) fn main(@builtin(local_invocation_id) LocalInvocationID : vec3u) {
+            @compute @workgroup_size(1)
+            fn main(@builtin(local_invocation_id) LocalInvocationID : vec3u) {
                 textureStore(image0, vec2i(LocalInvocationID.xy), vec4f(0.0, 0.0, 0.0, 0.0));
             })");
 
@@ -239,44 +238,22 @@
     }
 }
 
-// Validate read-only and read-write storage textures are not currently supported without enabling
-// chromium_experimental_read_write_storage_texture.
+// Validate read-only, write-only and read-write storage textures are supported in shader modules.
 TEST_F(StorageTextureValidationTests, ReadWriteStorageTexture) {
     constexpr std::array<wgpu::StorageTextureAccess, 2> kStorageTextureAccesses = {
         {wgpu::StorageTextureAccess::ReadOnly, wgpu::StorageTextureAccess::ReadWrite}};
     constexpr std::array<wgpu::ShaderStage, 3> kShaderStages = {
         {wgpu::ShaderStage::Vertex, wgpu::ShaderStage::Fragment, wgpu::ShaderStage::Compute}};
-    constexpr std::array<bool, 2> kDisableExtension = {{true, false}};
 
     for (wgpu::StorageTextureAccess access : kStorageTextureAccesses) {
         for (wgpu::ShaderStage shaderStage : kShaderStages) {
-            for (bool disableExtension : kDisableExtension) {
-                std::string shader = CreateShaderWithStorageTexture(
-                    access, wgpu::TextureFormat::R32Float, "texture_storage_2d", disableExtension,
-                    shaderStage);
-                ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, shader.c_str()));
-            }
+            std::string shader = CreateShaderWithStorageTexture(
+                access, wgpu::TextureFormat::R32Float, "texture_storage_2d", shaderStage);
+            utils::CreateShaderModule(device, shader.c_str());
         }
     }
 }
 
-// Test that using write-only storage texture in BindGroupLayout is always valid, while using
-// read-only or read-write storage texture in BindGroupLayout is invalid without the optional
-// feature "chromium-experimental-read-write-storage-texture".
-TEST_F(StorageTextureValidationTests, BindGroupLayoutWithStorageTextureBindingType) {
-    const std::vector<BindGroupLayoutTestSpec> kTestSpecs = {
-        {{wgpu::ShaderStage::Vertex, wgpu::StorageTextureAccess::WriteOnly, false},
-         {wgpu::ShaderStage::Vertex, wgpu::StorageTextureAccess::ReadOnly, false},
-         {wgpu::ShaderStage::Vertex, wgpu::StorageTextureAccess::ReadWrite, false},
-         {wgpu::ShaderStage::Fragment, wgpu::StorageTextureAccess::WriteOnly, true},
-         {wgpu::ShaderStage::Fragment, wgpu::StorageTextureAccess::ReadOnly, false},
-         {wgpu::ShaderStage::Fragment, wgpu::StorageTextureAccess::ReadWrite, false},
-         {wgpu::ShaderStage::Compute, wgpu::StorageTextureAccess::WriteOnly, true},
-         {wgpu::ShaderStage::Compute, wgpu::StorageTextureAccess::ReadOnly, false},
-         {wgpu::ShaderStage::Compute, wgpu::StorageTextureAccess::ReadWrite, false}}};
-    DoBindGroupLayoutTest(kTestSpecs);
-}
-
 // Validate it is an error to declare a read-only or write-only storage texture in shaders with any
 // format that doesn't support TextureUsage::StorageBinding texture usages.
 TEST_F(StorageTextureValidationTests, StorageTextureFormatInShaders) {
@@ -908,27 +885,20 @@
     }
 }
 
-class ReadWriteStorageTextureValidationTests : public StorageTextureValidationTests {
-  protected:
-    WGPUDevice CreateTestDevice(native::Adapter dawnAdapter,
-                                wgpu::DeviceDescriptor descriptor) override {
-        wgpu::FeatureName requiredFeatures[1] = {
-            wgpu::FeatureName::ChromiumExperimentalReadWriteStorageTexture};
-        descriptor.requiredFeatures = requiredFeatures;
-        descriptor.requiredFeatureCount = 1;
+class ReadWriteStorageTextureValidationTests : public StorageTextureValidationTests {};
 
-        return dawnAdapter.CreateDevice(&descriptor);
-    }
-};
-
-// Test that using read-only or read-write storage texture in BindGroupLayout is valid with the
-// optional feature "chromium-experimental-read-write-storage-texture".
-TEST_F(ReadWriteStorageTextureValidationTests, BindGroupLayoutWithStorageTextureBindingType) {
+// Test that using read-only storage texture is valid for all shader stages in BindGroupLayout,
+// while write-only and read-write storage textures are only valid for fragment and compute shader
+// stages.
+TEST_F(StorageTextureValidationTests, BindGroupLayoutWithStorageTextureBindingType) {
     const std::vector<BindGroupLayoutTestSpec> kTestSpecs = {
-        {{wgpu::ShaderStage::Vertex, wgpu::StorageTextureAccess::ReadOnly, true},
+        {{wgpu::ShaderStage::Vertex, wgpu::StorageTextureAccess::WriteOnly, false},
+         {wgpu::ShaderStage::Vertex, wgpu::StorageTextureAccess::ReadOnly, true},
          {wgpu::ShaderStage::Vertex, wgpu::StorageTextureAccess::ReadWrite, false},
+         {wgpu::ShaderStage::Fragment, wgpu::StorageTextureAccess::WriteOnly, true},
          {wgpu::ShaderStage::Fragment, wgpu::StorageTextureAccess::ReadOnly, true},
          {wgpu::ShaderStage::Fragment, wgpu::StorageTextureAccess::ReadWrite, true},
+         {wgpu::ShaderStage::Compute, wgpu::StorageTextureAccess::WriteOnly, true},
          {wgpu::ShaderStage::Compute, wgpu::StorageTextureAccess::ReadOnly, true},
          {wgpu::ShaderStage::Compute, wgpu::StorageTextureAccess::ReadWrite, true}}};
     DoBindGroupLayoutTest(kTestSpecs);
@@ -988,20 +958,6 @@
     }
 }
 
-// Test that using ReadOnly or ReadWrite storage texture access without declaring the optional
-// feature "chromium-experimental-read-write-storage-texture" is invalid.
-TEST_F(ReadWriteStorageTextureValidationTests, ReadWriteStorageTextureAccessWithoutExtension) {
-    constexpr std::array<wgpu::StorageTextureAccess, 2> kStorageTextureAccesses = {
-        {wgpu::StorageTextureAccess::ReadOnly, wgpu::StorageTextureAccess::ReadWrite}};
-    constexpr bool kDisableExtension = true;
-    constexpr wgpu::TextureFormat kFormat = wgpu::TextureFormat::R32Uint;
-    for (wgpu::StorageTextureAccess access : kStorageTextureAccesses) {
-        std::string computeShader = CreateShaderWithStorageTexture(
-            access, kFormat, "texture_storage_2d", kDisableExtension);
-        ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, computeShader.c_str()));
-    }
-}
-
 // Test that storage texture access in shader must be compatible with the one in pipeline layout
 // when we create a pipeline with storage texture. Note that read-write storage texture access in
 // pipeline layout is compatible with write-only storage texture access in shader.
@@ -1196,5 +1152,81 @@
     }
 }
 
+class ReadWriteStorageTextureDisallowUnsafeAPITests
+    : public ReadWriteStorageTextureValidationTests {
+  protected:
+    // Create the device with the AllowUnsafeAPIs toggle explicitly disabled, which overrides the
+    // inheritance.
+    WGPUDevice CreateTestDevice(native::Adapter dawnAdapter,
+                                wgpu::DeviceDescriptor descriptor) override {
+        wgpu::DawnTogglesDescriptor deviceTogglesDesc;
+        descriptor.nextInChain = &deviceTogglesDesc;
+        const char* toggle = "allow_unsafe_apis";
+        deviceTogglesDesc.disabledToggles = &toggle;
+        deviceTogglesDesc.disabledToggleCount = 1;
+        return dawnAdapter.CreateDevice(&descriptor);
+    }
+};
+
+// Check that both read-only and read-write storage texture accesses are validated as unsafe.
+TEST_F(ReadWriteStorageTextureDisallowUnsafeAPITests, StorageAccessInBindGroupLayout) {
+    const std::vector<BindGroupLayoutTestSpec> kTestSpecs = {
+        {{wgpu::ShaderStage::Vertex, wgpu::StorageTextureAccess::ReadOnly, false},
+         {wgpu::ShaderStage::Vertex, wgpu::StorageTextureAccess::ReadWrite, false},
+         {wgpu::ShaderStage::Fragment, wgpu::StorageTextureAccess::ReadOnly, false},
+         {wgpu::ShaderStage::Fragment, wgpu::StorageTextureAccess::ReadWrite, false},
+         {wgpu::ShaderStage::Compute, wgpu::StorageTextureAccess::ReadOnly, false},
+         {wgpu::ShaderStage::Compute, wgpu::StorageTextureAccess::ReadWrite, false}}};
+    DoBindGroupLayoutTest(kTestSpecs);
+}
+
+// Check that both read-only and read-write storage textures are validated as unsafe in render and
+// compute pipelines.
+TEST_F(ReadWriteStorageTextureDisallowUnsafeAPITests, ReadWriteStorageTextureInPipeline) {
+    constexpr std::array<wgpu::StorageTextureAccess, 2> kStorageTextureAccesses = {
+        {wgpu::StorageTextureAccess::ReadOnly, wgpu::StorageTextureAccess::ReadWrite}};
+    constexpr std::array<wgpu::ShaderStage, 3> kShaderStages = {
+        {wgpu::ShaderStage::Vertex, wgpu::ShaderStage::Fragment, wgpu::ShaderStage::Compute}};
+
+    for (wgpu::StorageTextureAccess access : kStorageTextureAccesses) {
+        for (wgpu::ShaderStage shaderStage : kShaderStages) {
+            std::string shader = CreateShaderWithStorageTexture(
+                access, wgpu::TextureFormat::R32Float, "texture_storage_2d", shaderStage);
+            wgpu::ShaderModule shaderModule = utils::CreateShaderModule(device, shader.c_str());
+
+            switch (shaderStage) {
+                case wgpu::ShaderStage::Vertex: {
+                    utils::ComboRenderPipelineDescriptor renderDescriptor;
+                    renderDescriptor.vertex.module = shaderModule;
+                    renderDescriptor.cFragment.module = mDefaultFSModule;
+                    renderDescriptor.layout = nullptr;
+                    ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&renderDescriptor));
+                    break;
+                }
+                case wgpu::ShaderStage::Fragment: {
+                    utils::ComboRenderPipelineDescriptor renderDescriptor;
+                    renderDescriptor.vertex.module = mDefaultVSModule;
+                    renderDescriptor.cFragment.module = shaderModule;
+                    renderDescriptor.cTargets[0].writeMask = wgpu::ColorWriteMask::None;
+                    renderDescriptor.layout = nullptr;
+                    ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&renderDescriptor));
+                    break;
+                }
+                case wgpu::ShaderStage::Compute: {
+                    wgpu::ComputePipelineDescriptor computeDescriptor;
+                    computeDescriptor.compute.module = shaderModule;
+                    computeDescriptor.compute.entryPoint = "main";
+                    ASSERT_DEVICE_ERROR(device.CreateComputePipeline(&computeDescriptor));
+                    break;
+                }
+                case wgpu::ShaderStage::None:
+                default: {
+                    DAWN_UNREACHABLE();
+                }
+            }
+        }
+    }
+}
+
 }  // anonymous namespace
 }  // namespace dawn
diff --git a/src/tint/lang/spirv/reader/ast_parser/ast_parser.cc b/src/tint/lang/spirv/reader/ast_parser/ast_parser.cc
index 2c7d268..0bf7f61 100644
--- a/src/tint/lang/spirv/reader/ast_parser/ast_parser.cc
+++ b/src/tint/lang/spirv/reader/ast_parser/ast_parser.cc
@@ -2583,9 +2583,6 @@
         } else {
             const auto access =
                 usage.IsStorageReadWriteTexture() ? core::Access::kReadWrite : core::Access::kWrite;
-            if (access == core::Access::kReadWrite) {
-                Enable(wgsl::Extension::kChromiumExperimentalReadWriteStorageTexture);
-            }
             const auto format = enum_converter_.ToTexelFormat(image_type->format());
             if (format == core::TexelFormat::kUndefined) {
                 return nullptr;
diff --git a/src/tint/lang/spirv/reader/ast_parser/function.cc b/src/tint/lang/spirv/reader/ast_parser/function.cc
index 99e728a..198f58f 100644
--- a/src/tint/lang/spirv/reader/ast_parser/function.cc
+++ b/src/tint/lang/spirv/reader/ast_parser/function.cc
@@ -5325,7 +5325,6 @@
         if (memory != uint32_t(spv::Scope::Workgroup)) {
             return Fail() << "textureBarrier requires workgroup memory scope";
         }
-        parser_impl_.Enable(wgsl::Extension::kChromiumExperimentalReadWriteStorageTexture);
         AddStatement(builder_.CallStmt(builder_.Call("textureBarrier")));
         semantics &= ~static_cast<uint32_t>(spv::MemorySemanticsMask::ImageMemory);
     }
diff --git a/src/tint/lang/spirv/reader/ast_parser/handle_test.cc b/src/tint/lang/spirv/reader/ast_parser/handle_test.cc
index 4d8caf4..154ccc2 100644
--- a/src/tint/lang/spirv/reader/ast_parser/handle_test.cc
+++ b/src/tint/lang/spirv/reader/ast_parser/handle_test.cc
@@ -4233,9 +4233,8 @@
 
     EXPECT_TRUE(p->error().empty()) << p->error();
     const auto got = test::ToString(p->program());
-    auto* expect = R"(enable chromium_experimental_read_write_storage_texture;
-
-@group(0) @binding(0) var RWTexture2D : texture_storage_2d<rgba32float, read_write>;
+    auto* expect =
+        R"(@group(0) @binding(0) var RWTexture2D : texture_storage_2d<rgba32float, read_write>;
 
 const x_9 = vec2u(1u);
 
diff --git a/src/tint/lang/spirv/reader/ast_parser/parse.cc b/src/tint/lang/spirv/reader/ast_parser/parse.cc
index af503d2..94c4355 100644
--- a/src/tint/lang/spirv/reader/ast_parser/parse.cc
+++ b/src/tint/lang/spirv/reader/ast_parser/parse.cc
@@ -71,7 +71,6 @@
                     case wgsl::Extension::kChromiumExperimentalFullPtrParameters:
                     case wgsl::Extension::kChromiumExperimentalPixelLocal:
                     case wgsl::Extension::kChromiumExperimentalPushConstant:
-                    case wgsl::Extension::kChromiumExperimentalReadWriteStorageTexture:
                     case wgsl::Extension::kChromiumExperimentalSubgroups:
                     case wgsl::Extension::kChromiumInternalDualSourceBlending:
                     case wgsl::Extension::kChromiumInternalRelaxedUniformLayout: {
@@ -82,6 +81,7 @@
                         return Program(std::move(builder));
                     }
                     case wgsl::Extension::kF16:
+                    case wgsl::Extension::kChromiumExperimentalReadWriteStorageTexture:
                         break;
                 }
             }
diff --git a/src/tint/lang/spirv/reader/ast_parser/parser_test.cc b/src/tint/lang/spirv/reader/ast_parser/parser_test.cc
index f7b2ded..7375186 100644
--- a/src/tint/lang/spirv/reader/ast_parser/parser_test.cc
+++ b/src/tint/lang/spirv/reader/ast_parser/parser_test.cc
@@ -91,63 +91,6 @@
     EXPECT_EQ(program.Diagnostics().count(), 0u) << errs;
 }
 
-constexpr auto kShaderWithReadWriteStorageTexture = R"(
-               OpCapability Shader
-               OpCapability StorageImageExtendedFormats
-               OpMemoryModel Logical GLSL450
-               OpEntryPoint GLCompute %100 "main"
-               OpExecutionMode %100 LocalSize 8 8 1
-               OpSource HLSL 600
-               OpName %type_2d_image "type.2d.image"
-               OpName %RWTexture2D "RWTexture2D"
-               OpName %100 "main"
-               OpDecorate %RWTexture2D DescriptorSet 0
-               OpDecorate %RWTexture2D Binding 0
-      %float = OpTypeFloat 32
-    %float_0 = OpConstant %float 0
-    %v4float = OpTypeVector %float 4
-       %uint = OpTypeInt 32 0
-     %uint_1 = OpConstant %uint 1
-     %v2uint = OpTypeVector %uint 2
-      %coord = OpConstantComposite %v2uint %uint_1 %uint_1
-%type_2d_image = OpTypeImage %float 2D 2 0 0 2 Rgba32f
-%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
-       %void = OpTypeVoid
-         %20 = OpTypeFunction %void
-%RWTexture2D = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
-        %100 = OpFunction %void None %20
-         %22 = OpLabel
-         %30 = OpLoad %type_2d_image %RWTexture2D
-         %31 = OpImageRead %v4float %30 %coord None
-         %32 = OpFAdd %v4float %31 %31
-               OpImageWrite %30 %coord %32 None
-               OpReturn
-               OpFunctionEnd
-  )";
-
-TEST_F(ParserTest, AllowChromiumExtensions_False) {
-    auto spv = test::Assemble(kShaderWithReadWriteStorageTexture);
-    Options options;
-    options.allow_chromium_extensions = false;
-    auto program = Parse(spv, options);
-    auto errs = program.Diagnostics().str();
-    EXPECT_FALSE(program.IsValid()) << errs;
-    EXPECT_THAT(errs,
-                ::testing::HasSubstr(
-                    "error: module requires chromium_experimental_read_write_storage_texture, but "
-                    "'allow-chromium-extensions' was not passed"));
-}
-
-TEST_F(ParserTest, AllowChromiumExtensions_True) {
-    auto spv = test::Assemble(kShaderWithReadWriteStorageTexture);
-    Options options;
-    options.allow_chromium_extensions = true;
-    auto program = Parse(spv, options);
-    auto errs = program.Diagnostics().str();
-    EXPECT_TRUE(program.IsValid()) << errs;
-    EXPECT_EQ(program.Diagnostics().count(), 0u) << errs;
-}
-
 // TODO(dneto): uint32 vec, valid SPIR-V
 // TODO(dneto): uint32 vec, invalid SPIR-V
 
diff --git a/src/tint/lang/wgsl/inspector/inspector_test.cc b/src/tint/lang/wgsl/inspector/inspector_test.cc
index 80435da..052c464 100644
--- a/src/tint/lang/wgsl/inspector/inspector_test.cc
+++ b/src/tint/lang/wgsl/inspector/inspector_test.cc
@@ -3126,11 +3126,9 @@
             expectedResourceType = ResourceBinding::ResourceType::kWriteOnlyStorageTexture;
             break;
         case core::Access::kRead:
-            Enable(wgsl::Extension::kChromiumExperimentalReadWriteStorageTexture);
             expectedResourceType = ResourceBinding::ResourceType::kReadOnlyStorageTexture;
             break;
         case core::Access::kReadWrite:
-            Enable(wgsl::Extension::kChromiumExperimentalReadWriteStorageTexture);
             expectedResourceType = ResourceBinding::ResourceType::kReadWriteStorageTexture;
             break;
         case core::Access::kUndefined:
diff --git a/src/tint/lang/wgsl/resolver/builtin_validation_test.cc b/src/tint/lang/wgsl/resolver/builtin_validation_test.cc
index 4e4fe92..c317db4 100644
--- a/src/tint/lang/wgsl/resolver/builtin_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/builtin_validation_test.cc
@@ -809,29 +809,13 @@
         R"(12:34 error: the sourceLaneIndex argument of subgroupBroadcast must be a const-expression)");
 }
 
-TEST_F(ResolverBuiltinValidationTest, TextureBarrierWithoutExtension) {
+TEST_F(ResolverBuiltinValidationTest, TextureBarrier) {
     // fn func { textureBarrier(); }
     Func("func", tint::Empty, ty.void_(),
          Vector{
              CallStmt(Call(Source{Source::Location{12, 34}}, "textureBarrier")),
          });
 
-    EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(
-        r()->error(),
-        R"(12:34 error: cannot call built-in function 'textureBarrier' without extension chromium_experimental_read_write_storage_texture)");
-}
-
-TEST_F(ResolverBuiltinValidationTest, TextureBarrierWithExtension) {
-    // enable chromium_experimental_read_write_storage_texture;
-    // fn func { textureBarrier(); }
-    Enable(wgsl::Extension::kChromiumExperimentalReadWriteStorageTexture);
-
-    Func("func", tint::Empty, ty.void_(),
-         Vector{
-             CallStmt(Call(Source{Source::Location{12, 34}}, "textureBarrier")),
-         });
-
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 }
 
diff --git a/src/tint/lang/wgsl/resolver/type_validation_test.cc b/src/tint/lang/wgsl/resolver/type_validation_test.cc
index 710fdf4..bf9d840 100644
--- a/src/tint/lang/wgsl/resolver/type_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/type_validation_test.cc
@@ -1196,7 +1196,7 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 }
 
-TEST_F(StorageTextureAccessTest, ReadOnlyAccess_WithoutExtension_Fail) {
+TEST_F(StorageTextureAccessTest, ReadOnlyAccess_Pass) {
     // @group(0) @binding(0)
     // var a : texture_storage_1d<r32uint, read>;
 
@@ -1205,27 +1205,10 @@
 
     GlobalVar("a", st, Group(0_a), Binding(0_a));
 
-    EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(),
-              "12:34 error: read-only storage textures require the "
-              "chromium_experimental_read_write_storage_texture extension to be enabled");
-}
-
-TEST_F(StorageTextureAccessTest, ReadOnlyAccess_WithExtension_Pass) {
-    // enable chromium_experimental_read_write_storage_texture;
-    // @group(0) @binding(0)
-    // var a : texture_storage_1d<r32uint, read>;
-
-    Enable(wgsl::Extension::kChromiumExperimentalReadWriteStorageTexture);
-    auto st = ty.storage_texture(Source{{12, 34}}, core::type::TextureDimension::k1d,
-                                 core::TexelFormat::kR32Uint, core::Access::kRead);
-
-    GlobalVar("a", st, Group(0_a), Binding(0_a));
-
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 }
 
-TEST_F(StorageTextureAccessTest, RWAccess_WithoutExtension_Fail) {
+TEST_F(StorageTextureAccessTest, RWAccess_Pass) {
     // @group(0) @binding(0)
     // var a : texture_storage_1d<r32uint, read_write>;
 
@@ -1234,23 +1217,6 @@
 
     GlobalVar("a", st, Group(0_a), Binding(0_a));
 
-    EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(),
-              "12:34 error: read-write storage textures require the "
-              "chromium_experimental_read_write_storage_texture extension to be enabled");
-}
-
-TEST_F(StorageTextureAccessTest, RWAccess_WithExtension_Pass) {
-    // enable chromium_experimental_read_write_storage_texture;
-    // @group(0) @binding(0)
-    // var a : texture_storage_1d<r32uint, read_write>;
-
-    Enable(wgsl::Extension::kChromiumExperimentalReadWriteStorageTexture);
-    auto st = ty.storage_texture(Source{{12, 34}}, core::type::TextureDimension::k1d,
-                                 core::TexelFormat::kR32Uint, core::Access::kReadWrite);
-
-    GlobalVar("a", st, Group(0_a), Binding(0_a));
-
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 }
 
diff --git a/src/tint/lang/wgsl/resolver/validator.cc b/src/tint/lang/wgsl/resolver/validator.cc
index d3c0205..da7536d 100644
--- a/src/tint/lang/wgsl/resolver/validator.cc
+++ b/src/tint/lang/wgsl/resolver/validator.cc
@@ -333,25 +333,7 @@
 bool Validator::StorageTexture(const core::type::StorageTexture* t, const Source& source) const {
     switch (t->access()) {
         case core::Access::kRead:
-            if (!enabled_extensions_.Contains(
-                    wgsl::Extension::kChromiumExperimentalReadWriteStorageTexture)) {
-                AddError(
-                    "read-only storage textures require the "
-                    "chromium_experimental_read_write_storage_texture extension to be enabled",
-                    source);
-                return false;
-            }
-            break;
         case core::Access::kReadWrite:
-            if (!enabled_extensions_.Contains(
-                    wgsl::Extension::kChromiumExperimentalReadWriteStorageTexture)) {
-                AddError(
-                    "read-write storage textures require the "
-                    "chromium_experimental_read_write_storage_texture extension to be enabled",
-                    source);
-                return false;
-            }
-            break;
         case core::Access::kWrite:
             break;
         case core::Access::kUndefined:
diff --git a/src/tint/lang/wgsl/sem/builtin_fn.cc b/src/tint/lang/wgsl/sem/builtin_fn.cc
index 968320f..ea49f47 100644
--- a/src/tint/lang/wgsl/sem/builtin_fn.cc
+++ b/src/tint/lang/wgsl/sem/builtin_fn.cc
@@ -112,9 +112,6 @@
     if (IsSubgroup()) {
         return wgsl::Extension::kChromiumExperimentalSubgroups;
     }
-    if (fn_ == wgsl::BuiltinFn::kTextureBarrier) {
-        return wgsl::Extension::kChromiumExperimentalReadWriteStorageTexture;
-    }
     return wgsl::Extension::kUndefined;
 }
 
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
index 4a87f27..e3650e6 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
@@ -605,9 +605,6 @@
                 }
 
                 switch (c->Func()) {
-                    case wgsl::BuiltinFn::kTextureBarrier:
-                        Enable(wgsl::Extension::kChromiumExperimentalReadWriteStorageTexture);
-                        break;
                     case wgsl::BuiltinFn::kSubgroupBallot:
                     case wgsl::BuiltinFn::kSubgroupBroadcast:
                         Enable(wgsl::Extension::kChromiumExperimentalSubgroups);
@@ -942,9 +939,6 @@
                 return b.ty.sampled_texture(t->dim(), el);
             },
             [&](const core::type::StorageTexture* t) {
-                if (t->access() == core::Access::kRead || t->access() == core::Access::kReadWrite) {
-                    Enable(wgsl::Extension::kChromiumExperimentalReadWriteStorageTexture);
-                }
                 return b.ty.storage_texture(t->dim(), t->texel_format(), t->access());
             },
             [&](const core::type::Sampler* s) { return b.ty.sampler(s->kind()); },
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
index 86dbbca..53af431 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
@@ -3212,55 +3212,6 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// chromium_experimental_read_write_storage_texture
-////////////////////////////////////////////////////////////////////////////////
-TEST_F(IRToProgramTest, Enable_ChromiumExperimentalReadWriteStorageTexture_TextureBarrier) {
-    auto* fn = b.Function("f", ty.void_());
-    b.Append(fn->Block(), [&] {
-        b.Append(mod.instructions.Create<wgsl::ir::BuiltinCall>(
-            b.InstructionResult(ty.void_()), wgsl::BuiltinFn::kTextureBarrier, Empty));
-        b.Return(fn);
-    });
-
-    EXPECT_WGSL(R"(
-enable chromium_experimental_read_write_storage_texture;
-
-fn f() {
-  textureBarrier();
-}
-)");
-}
-
-TEST_F(IRToProgramTest, Enable_ChromiumExperimentalReadWriteStorageTexture_ReadOnlyStorageTexture) {
-    auto* T = b.Var("T", ty.ptr<handle>(ty.Get<core::type::StorageTexture>(
-                             core::type::TextureDimension::k2d, core::TexelFormat::kR32Float,
-                             core::Access::kRead, ty.f32())));
-    T->SetBindingPoint(0, 0);
-    b.ir.root_block->Append(T);
-
-    EXPECT_WGSL(R"(
-enable chromium_experimental_read_write_storage_texture;
-
-@group(0) @binding(0) var T : texture_storage_2d<r32float, read>;
-)");
-}
-
-TEST_F(IRToProgramTest,
-       Enable_ChromiumExperimentalReadWriteStorageTexture_ReadWriteOnlyStorageTexture) {
-    auto* T = b.Var("T", ty.ptr<handle>(ty.Get<core::type::StorageTexture>(
-                             core::type::TextureDimension::k2d, core::TexelFormat::kR32Float,
-                             core::Access::kReadWrite, ty.f32())));
-    T->SetBindingPoint(0, 0);
-    b.ir.root_block->Append(T);
-
-    EXPECT_WGSL(R"(
-enable chromium_experimental_read_write_storage_texture;
-
-@group(0) @binding(0) var T : texture_storage_2d<r32float, read_write>;
-)");
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // chromium_experimental_subgroups
 ////////////////////////////////////////////////////////////////////////////////
 TEST_F(IRToProgramTest, Enable_ChromiumExperimentalSubgroups_SubgroupBallot) {