This is an automated email from the ASF dual-hosted git repository.

guan404ming pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git


The following commit(s) were added to refs/heads/main by this push:
     new 189cef1249 [Fix][WebGPU] Preserve read-only buffer access modes 
(#20113)
189cef1249 is described below

commit 189cef12497f780acd065a1b10d8423830b02614
Author: Akaash Parthasarathy <[email protected]>
AuthorDate: Tue Aug 11 07:45:12 2026 -0700

    [Fix][WebGPU] Preserve read-only buffer access modes (#20113)
    
    Preserve read-only WebGPU storage-buffer access modes after typed TIR
    buffer lowering. Resolve `DeclBuffer` aliases to their underlying
    pointer parameters and only emit `read_write` when the buffer is
    actually written. This prevents read-only metadata buffers from being
    misclassified and triggering WGSL uniform-control-flow validation errors
    around `workgroupBarrier`.
---
 src/backend/webgpu/codegen/codegen_webgpu.cc       | 29 ++++++++++++++-
 tests/python/codegen/test_target_codegen_webgpu.py | 42 ++++++++++++++++++++++
 2 files changed, 70 insertions(+), 1 deletion(-)

diff --git a/src/backend/webgpu/codegen/codegen_webgpu.cc 
b/src/backend/webgpu/codegen/codegen_webgpu.cc
index 933a81f826..fe67febc45 100644
--- a/src/backend/webgpu/codegen/codegen_webgpu.cc
+++ b/src/backend/webgpu/codegen/codegen_webgpu.cc
@@ -31,7 +31,9 @@
 #include <tvm/tirx/transform.h>
 
 #include <algorithm>
+#include <optional>
 #include <string>
+#include <unordered_map>
 #include <unordered_set>
 #include <utility>
 #include <vector>
@@ -67,6 +69,22 @@ class WebGPUWorkgroupInfoCollector : public StmtExprVisitor {
  private:
   using StmtExprVisitor::VisitExpr_;
 
+  static ffi::Optional<Var> GetBufferDataVar(const Expr& data) {
+    if (auto var = data.as<Var>()) {
+      return var;
+    }
+    if (const auto* call = data.as<CallNode>();
+        call && call->op.same_as(tirx::builtin::buffer_data()) && 
call->args.size() == 1) {
+      return call->args[0].as<Var>();
+    }
+    return std::nullopt;
+  }
+
+  Var ResolveBuffer(Var buffer_var) const {
+    auto it = buffer_aliases_.find(buffer_var.get());
+    return it == buffer_aliases_.end() ? buffer_var : it->second;
+  }
+
   void VisitExpr_(const VarNode* op) final {
     StmtExprVisitor::VisitExpr_(op);
     Var buffer_var = ffi::GetRef<Var>(op);
@@ -77,7 +95,15 @@ class WebGPUWorkgroupInfoCollector : public StmtExprVisitor {
 
   void VisitStmt_(const BufferStoreNode* op) final {
     StmtExprVisitor::VisitStmt_(op);
-    info_.write_access_set.insert(op->buffer.var());
+    info_.write_access_set.insert(ResolveBuffer(op->buffer.var()));
+  }
+
+  void VisitStmt_(const DeclBufferNode* op) final {
+    if (auto source = GetBufferDataVar(op->data)) {
+      buffer_aliases_.insert_or_assign(op->buffer.get(), 
ResolveBuffer(source.value()));
+      return;
+    }
+    StmtExprVisitor::VisitStmt_(op);
   }
 
   void VisitStmt_(const AttrStmtNode* op) final {
@@ -104,6 +130,7 @@ class WebGPUWorkgroupInfoCollector : public StmtExprVisitor 
{
     StmtExprVisitor::VisitStmt_(op);
   }
   WebGPUWorkGroupInfo info_;
+  std::unordered_map<const VarNode*, Var> buffer_aliases_;
 };
 
 std::string CodeGenWebGPU::Finish() {
diff --git a/tests/python/codegen/test_target_codegen_webgpu.py 
b/tests/python/codegen/test_target_codegen_webgpu.py
new file mode 100644
index 0000000000..96bfc6b90d
--- /dev/null
+++ b/tests/python/codegen/test_target_codegen_webgpu.py
@@ -0,0 +1,42 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import tvm
+import tvm.testing
+from tvm.script import ir as I
+from tvm.script import tirx as T
+
+
+def test_codegen_buffer_access_modes():
+    """Read-only typed buffer parameters should remain read-only in WGSL."""
+
+    @I.ir_module(s_tir=True)
+    class Module:
+        @T.prim_func(s_tir=True)
+        def main(A: T.Buffer((8,), "float32"), B: T.Buffer((8,), "float32")):
+            for tx in T.thread_binding(8, thread="threadIdx.x"):
+                B[tx] = A[tx]
+
+    executable = tvm.compile(Module, target="webgpu")
+    source = executable.mod.imports[0].inspect_source("wgsl")
+
+    assert "var<storage, read> A_ptr" in source
+    assert "var<storage, read_write> B_ptr" in source
+
+
+if __name__ == "__main__":
+    tvm.testing.main()

Reply via email to