[WebGPU backend] Implement native::webgpu::Texture

Just fill the bits needed immediately in CommandBufferWGPU.
CopyFromStagingToTextureImpl and writeTextureImpl unimplemented.

Enable CopyTests_B2T tests as well.

Bug: 413053623
Change-Id: I0123faf62cd1d79a8f50699909b034cc82f1607b
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/258499
Auto-Submit: Shrek Shao <shrekshao@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Gregg Tavares <gman@chromium.org>
Reviewed-by: Gregg Tavares <gman@chromium.org>
diff --git a/src/dawn/native/BUILD.gn b/src/dawn/native/BUILD.gn
index c7b0670..ab6ad62 100644
--- a/src/dawn/native/BUILD.gn
+++ b/src/dawn/native/BUILD.gn
@@ -728,6 +728,8 @@
       "webgpu/PhysicalDeviceWGPU.h",
       "webgpu/QueueWGPU.cpp",
       "webgpu/QueueWGPU.h",
+      "webgpu/TextureWGPU.cpp",
+      "webgpu/TextureWGPU.h",
       "webgpu/WebGPUError.h",
     ]
   }
diff --git a/src/dawn/native/CMakeLists.txt b/src/dawn/native/CMakeLists.txt
index 35deada..62eb7f4 100644
--- a/src/dawn/native/CMakeLists.txt
+++ b/src/dawn/native/CMakeLists.txt
@@ -590,6 +590,7 @@
         "webgpu/ObjectWGPU.h"
         "webgpu/PhysicalDeviceWGPU.h"
         "webgpu/QueueWGPU.h"
+        "webgpu/TextureWGPU.h"
         "webgpu/WebGPUError.h"
     )
     list(APPEND sources
@@ -599,6 +600,7 @@
         "webgpu/DeviceWGPU.cpp"
         "webgpu/PhysicalDeviceWGPU.cpp"
         "webgpu/QueueWGPU.cpp"
+        "webgpu/TextureWGPU.cpp"
     )
 endif()
 
diff --git a/src/dawn/native/webgpu/BufferWGPU.cpp b/src/dawn/native/webgpu/BufferWGPU.cpp
index 792eefc..fb7467e 100644
--- a/src/dawn/native/webgpu/BufferWGPU.cpp
+++ b/src/dawn/native/webgpu/BufferWGPU.cpp
@@ -130,4 +130,10 @@
     mMappedData = nullptr;
 }
 
+void Buffer::DestroyImpl() {
+    BufferBase::DestroyImpl();
+    auto& wgpu = ToBackend(GetDevice())->wgpu;
+    wgpu.bufferDestroy(mInnerHandle);
+}
+
 }  // namespace dawn::native::webgpu
diff --git a/src/dawn/native/webgpu/BufferWGPU.h b/src/dawn/native/webgpu/BufferWGPU.h
index a5970a0..4b20ce5 100644
--- a/src/dawn/native/webgpu/BufferWGPU.h
+++ b/src/dawn/native/webgpu/BufferWGPU.h
@@ -50,6 +50,7 @@
     bool IsCPUWritableAtCreation() const override;
     MaybeError MapAtCreationImpl() override;
     void* GetMappedPointerImpl() override;
+    void DestroyImpl() override;
 
     raw_ptr<void> mMappedData = nullptr;
 };
diff --git a/src/dawn/native/webgpu/CommandBufferWGPU.cpp b/src/dawn/native/webgpu/CommandBufferWGPU.cpp
index 994b760..0dc7a6c 100644
--- a/src/dawn/native/webgpu/CommandBufferWGPU.cpp
+++ b/src/dawn/native/webgpu/CommandBufferWGPU.cpp
@@ -29,6 +29,7 @@
 
 #include "dawn/native/webgpu/BufferWGPU.h"
 #include "dawn/native/webgpu/DeviceWGPU.h"
+#include "dawn/native/webgpu/TextureWGPU.h"
 
 namespace dawn::native::webgpu {
 
@@ -90,8 +91,7 @@
 
 WGPUTexelCopyTextureInfo ToWGPU(const TextureCopy& copy) {
     return {
-        // TODO(crbug.com/440123094): Do this when GetInnerHandle is implemented for TextureWGPU
-        .texture = nullptr,  // ToBackend(copy.texture)->GetInnerHandle(),
+        .texture = ToBackend(copy.texture)->GetInnerHandle(),
         .mipLevel = copy.mipLevel,
         .origin = ToWGPU(copy.origin),
         .aspect = ToWGPU(copy.aspect),
diff --git a/src/dawn/native/webgpu/DeviceWGPU.cpp b/src/dawn/native/webgpu/DeviceWGPU.cpp
index 19fb185..8cd3524 100644
--- a/src/dawn/native/webgpu/DeviceWGPU.cpp
+++ b/src/dawn/native/webgpu/DeviceWGPU.cpp
@@ -55,6 +55,7 @@
 #include "dawn/native/webgpu/CommandBufferWGPU.h"
 #include "dawn/native/webgpu/PhysicalDeviceWGPU.h"
 #include "dawn/native/webgpu/QueueWGPU.h"
+#include "dawn/native/webgpu/TextureWGPU.h"
 
 #include "tint/tint.h"
 
@@ -181,7 +182,7 @@
 }
 ResultOrError<Ref<TextureBase>> Device::CreateTextureImpl(
     const UnpackedPtr<TextureDescriptor>& descriptor) {
-    return Ref<TextureBase>{nullptr};
+    return Texture::Create(this, descriptor);
 }
 ResultOrError<Ref<TextureViewBase>> Device::CreateTextureViewImpl(
     TextureBase* texture,
diff --git a/src/dawn/native/webgpu/TextureWGPU.cpp b/src/dawn/native/webgpu/TextureWGPU.cpp
new file mode 100644
index 0000000..04eaa54
--- /dev/null
+++ b/src/dawn/native/webgpu/TextureWGPU.cpp
@@ -0,0 +1,59 @@
+// Copyright 2025 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "dawn/native/webgpu/TextureWGPU.h"
+
+#include <utility>
+
+#include "dawn/native/webgpu/DeviceWGPU.h"
+
+namespace dawn::native::webgpu {
+
+// static
+ResultOrError<Ref<Texture>> Texture::Create(Device* device,
+                                            const UnpackedPtr<TextureDescriptor>& descriptor) {
+    auto desc = ToAPI(*descriptor);
+    WGPUTexture innerTexture = device->wgpu.deviceCreateTexture(device->GetInnerHandle(), desc);
+    DAWN_ASSERT(innerTexture);
+    Ref<Texture> texture = AcquireRef(new Texture(device, descriptor, innerTexture));
+    return std::move(texture);
+}
+
+Texture::Texture(Device* device,
+                 const UnpackedPtr<TextureDescriptor>& descriptor,
+                 WGPUTexture innerTexture)
+    : TextureBase(device, descriptor), ObjectWGPU(device->wgpu.textureRelease) {
+    mInnerHandle = innerTexture;
+}
+
+void Texture::DestroyImpl() {
+    TextureBase::DestroyImpl();
+    auto& wgpu = ToBackend(GetDevice())->wgpu;
+    wgpu.textureDestroy(mInnerHandle);
+}
+
+}  // namespace dawn::native::webgpu
diff --git a/src/dawn/native/webgpu/TextureWGPU.h b/src/dawn/native/webgpu/TextureWGPU.h
new file mode 100644
index 0000000..c968594
--- /dev/null
+++ b/src/dawn/native/webgpu/TextureWGPU.h
@@ -0,0 +1,55 @@
+// Copyright 2025 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SRC_DAWN_NATIVE_WEBGPU_TEXTUREWGPU_H_
+#define SRC_DAWN_NATIVE_WEBGPU_TEXTUREWGPU_H_
+
+#include "dawn/native/Error.h"
+#include "dawn/native/Forward.h"
+#include "dawn/native/Texture.h"
+#include "dawn/native/webgpu/ObjectWGPU.h"
+#include "dawn/webgpu.h"
+
+namespace dawn::native::webgpu {
+
+class Device;
+
+class Texture final : public TextureBase, public ObjectWGPU<WGPUTexture> {
+  public:
+    static ResultOrError<Ref<Texture>> Create(Device* device,
+                                              const UnpackedPtr<TextureDescriptor>& descriptor);
+
+  private:
+    Texture(Device* device,
+            const UnpackedPtr<TextureDescriptor>& descriptor,
+            WGPUTexture innerTexture);
+    void DestroyImpl() override;
+};
+
+}  // namespace dawn::native::webgpu
+
+#endif  // SRC_DAWN_NATIVE_WEBGPU_TEXTUREWGPU_H_
diff --git a/src/dawn/tests/end2end/CopyTests.cpp b/src/dawn/tests/end2end/CopyTests.cpp
index 182b0c4..bf2056b 100644
--- a/src/dawn/tests/end2end/CopyTests.cpp
+++ b/src/dawn/tests/end2end/CopyTests.cpp
@@ -2821,7 +2821,7 @@
 DAWN_INSTANTIATE_TEST_P(CopyTests_B2T,
                         {D3D11Backend(), D3D11Backend({"d3d11_disable_cpu_buffers"}),
                          D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(),
-                         VulkanBackend()},
+                         VulkanBackend(), WebGPUBackend()},
                         {
                             wgpu::TextureFormat::R8Unorm,
                             wgpu::TextureFormat::RG8Unorm,
@@ -3417,7 +3417,8 @@
                       MetalBackend(),
                       OpenGLBackend(),
                       OpenGLESBackend(),
-                      VulkanBackend());
+                      VulkanBackend(),
+                      WebGPUBackend());
 
 // Test clearing full buffers
 TEST_P(ClearBufferTests, FullClear) {