dawn: Add Device::CreateErrorTexture(desc)

This will be used by Blink to create error textures with correct
reflection information exposed to JavaScript.

Bug: chromium:1345736
Change-Id: I0bc3a72d602c1bb57dc76e90f4883951f86ef428
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/96681
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Shrek Shao <shrekshao@google.com>
Commit-Queue: Shrek Shao <shrekshao@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Auto-Submit: Corentin Wallez <cwallez@chromium.org>
diff --git a/dawn.json b/dawn.json
index 29632dd..0bb86f5 100644
--- a/dawn.json
+++ b/dawn.json
@@ -1110,6 +1110,14 @@
                 ]
             },
             {
+                "name": "create error texture",
+                "returns": "texture",
+                "tags": ["dawn"],
+                "args": [
+                    {"name": "descriptor", "type": "texture descriptor", "annotation": "const*"}
+                ]
+            },
+            {
                 "name": "destroy"
             },
             {
diff --git a/dawn_wire.json b/dawn_wire.json
index 5da5cc4..55098d0 100644
--- a/dawn_wire.json
+++ b/dawn_wire.json
@@ -223,6 +223,7 @@
             "DeviceCreateErrorBuffer",
             "DeviceCreateQuerySet",
             "DeviceCreateTexture",
+            "DeviceCreateErrorTexture",
             "DeviceGetQueue",
             "DeviceInjectError"
         ],
diff --git a/src/dawn/native/Device.cpp b/src/dawn/native/Device.cpp
index e15bee0..060826b 100644
--- a/src/dawn/native/Device.cpp
+++ b/src/dawn/native/Device.cpp
@@ -1231,6 +1231,10 @@
     return ExternalTextureBase::MakeError(this);
 }
 
+TextureBase* DeviceBase::APICreateErrorTexture(const TextureDescriptor* desc) {
+    return TextureBase::MakeError(this, desc);
+}
+
 // Other Device API methods
 
 // Returns true if future ticking is needed.
diff --git a/src/dawn/native/Device.h b/src/dawn/native/Device.h
index 10f9087..a74be9c 100644
--- a/src/dawn/native/Device.h
+++ b/src/dawn/native/Device.h
@@ -266,8 +266,8 @@
 
     // For Dawn Wire
     BufferBase* APICreateErrorBuffer();
-
     ExternalTextureBase* APICreateErrorExternalTexture();
+    TextureBase* APICreateErrorTexture(const TextureDescriptor* desc);
 
     QueueBase* APIGetQueue();
 
diff --git a/src/dawn/tests/unittests/validation/TextureValidationTests.cpp b/src/dawn/tests/unittests/validation/TextureValidationTests.cpp
index 543d7e0..d40fce4 100644
--- a/src/dawn/tests/unittests/validation/TextureValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/TextureValidationTests.cpp
@@ -945,4 +945,33 @@
     CheckTextureMatchesDescriptor(tex, desc);
 }
 
+// Test that CreateErrorTexture creates an invalid texture but doesn't produce an error.
+TEST_F(TextureValidationTest, CreateErrorTexture) {
+    wgpu::TextureDescriptor desc;
+    desc.format = wgpu::TextureFormat::RGBA8Unorm;
+    desc.size = {1, 1, 1};
+    desc.usage = wgpu::TextureUsage::RenderAttachment;
+
+    // Check that the descriptor is valid.
+    device.CreateTexture(&desc);
+
+    // Creating the error texture doesn't produce a validation error.
+    wgpu::Texture tex = device.CreateErrorTexture(&desc);
+
+    // Using the texture, for example to create a view, is an error.
+    ASSERT_DEVICE_ERROR(tex.CreateView());
+}
+
+// Test that the texture creation parameters are correctly reflected for textures created via
+// CreateErrorTexture
+TEST_F(TextureValidationTest, CreationParameterReflectionForCreateErrorTexture) {
+    wgpu::TextureDescriptor desc;
+    desc.format = wgpu::TextureFormat::RGBA8Unorm;
+    desc.size = {1, 1, 1};
+    desc.usage = wgpu::TextureUsage::RenderAttachment;
+
+    wgpu::Texture tex = device.CreateErrorTexture(&desc);
+    CheckTextureMatchesDescriptor(tex, desc);
+}
+
 }  // namespace
diff --git a/src/dawn/wire/client/Device.cpp b/src/dawn/wire/client/Device.cpp
index d945694..ace00a1 100644
--- a/src/dawn/wire/client/Device.cpp
+++ b/src/dawn/wire/client/Device.cpp
@@ -212,6 +212,10 @@
     return Texture::Create(this, descriptor);
 }
 
+WGPUTexture Device::CreateErrorTexture(const WGPUTextureDescriptor* descriptor) {
+    return Texture::CreateError(this, descriptor);
+}
+
 WGPUQueue Device::GetQueue() {
     // The queue is lazily created because if a Device is created by
     // Reserve/Inject, we cannot send the GetQueue message until
diff --git a/src/dawn/wire/client/Device.h b/src/dawn/wire/client/Device.h
index 185cbd0..d1af343 100644
--- a/src/dawn/wire/client/Device.h
+++ b/src/dawn/wire/client/Device.h
@@ -52,6 +52,7 @@
                                    void* userdata);
     WGPUQuerySet CreateQuerySet(const WGPUQuerySetDescriptor* descriptor);
     WGPUTexture CreateTexture(const WGPUTextureDescriptor* descriptor);
+    WGPUTexture CreateErrorTexture(const WGPUTextureDescriptor* descriptor);
 
     void HandleError(WGPUErrorType errorType, const char* message);
     void HandleLogging(WGPULoggingType loggingType, const char* message);
diff --git a/src/dawn/wire/client/Texture.cpp b/src/dawn/wire/client/Texture.cpp
index 40a9873..69f773e 100644
--- a/src/dawn/wire/client/Texture.cpp
+++ b/src/dawn/wire/client/Texture.cpp
@@ -35,6 +35,22 @@
     return ToAPI(texture);
 }
 
+// static
+WGPUTexture Texture::CreateError(Device* device, const WGPUTextureDescriptor* descriptor) {
+    Client* wireClient = device->GetClient();
+    Texture* texture = wireClient->Make<Texture>(descriptor);
+
+    // Send the Device::CreateErrorTexture command without modifications.
+    DeviceCreateErrorTextureCmd cmd;
+    cmd.self = ToAPI(device);
+    cmd.selfId = device->GetWireId();
+    cmd.descriptor = descriptor;
+    cmd.result = texture->GetWireHandle();
+    wireClient->SerializeCommand(cmd);
+
+    return ToAPI(texture);
+}
+
 Texture::Texture(const ObjectBaseParams& params, const WGPUTextureDescriptor* descriptor)
     : ObjectBase(params),
       mSize(descriptor->size),
diff --git a/src/dawn/wire/client/Texture.h b/src/dawn/wire/client/Texture.h
index 4cbd230..9798f91 100644
--- a/src/dawn/wire/client/Texture.h
+++ b/src/dawn/wire/client/Texture.h
@@ -26,6 +26,7 @@
 class Texture final : public ObjectBase {
   public:
     static WGPUTexture Create(Device* device, const WGPUTextureDescriptor* descriptor);
+    static WGPUTexture CreateError(Device* device, const WGPUTextureDescriptor* descriptor);
 
     Texture(const ObjectBaseParams& params, const WGPUTextureDescriptor* descriptor);
     ~Texture() override;