Descriptorize Texture

This patch introduces texture descriptor for texture creation instead
of texture builders.

This patch also adds "arrayLayer" to texture descriptor and removes
mDevice in TextureD3D12.
diff --git a/dawn.json b/dawn.json
index 7f038ed..0300bc6 100644
--- a/dawn.json
+++ b/dawn.json
@@ -604,8 +604,11 @@
                 "returns": "swap chain builder"
             },
             {
-                "name": "create texture builder",
-                "returns": "texture builder"
+                "name": "create texture",
+                "returns": "texture",
+                "args": [
+                    {"name": "descriptor", "type": "texture descriptor", "annotation": "const*"}
+                ]
             },
             {
                 "name": "tick"
@@ -996,45 +999,18 @@
             }
         ]
     },
-    "texture builder": {
-        "category": "object",
-        "methods": [
-            {
-                "name": "get result",
-                "returns": "texture"
-            },
-            {
-                "name": "set dimension",
-                "args": [
-                    {"name": "dimension", "type": "texture dimension"}
-                ]
-            },
-            {
-                "name": "set extent",
-                "args": [
-                    {"name": "width", "type": "uint32_t"},
-                    {"name": "height", "type": "uint32_t"},
-                    {"name": "depth", "type": "uint32_t"}
-                ]
-            },
-            {
-                "name": "set format",
-                "args": [
-                    {"name": "format", "type": "texture format"}
-                ]
-            },
-            {
-                "name": "set mip levels",
-                "args": [
-                    {"name": "num mip levels", "type": "uint32_t"}
-                ]
-            },
-            {
-                "name": "set allowed usage",
-                "args": [
-                    {"name": "usage", "type": "texture usage bit"}
-                ]
-            }
+    "texture descriptor": {
+        "category": "structure",
+        "extensible": true,
+        "members": [
+            {"name": "usage", "type": "texture usage bit"},
+            {"name": "dimension", "type": "texture dimension"},
+            {"name": "width", "type": "uint32_t"},
+            {"name": "height", "type": "uint32_t"},
+            {"name": "depth", "type": "uint32_t"},
+            {"name": "arrayLayer", "type": "uint32_t"},
+            {"name": "format", "type": "texture format"},
+            {"name": "mipLevel", "type": "uint32_t"}
         ]
     },
     "texture dimension": {
diff --git a/examples/CppHelloTriangle.cpp b/examples/CppHelloTriangle.cpp
index ea3578b..bf331df 100644
--- a/examples/CppHelloTriangle.cpp
+++ b/examples/CppHelloTriangle.cpp
@@ -48,13 +48,16 @@
 }
 
 void initTextures() {
-    texture = device.CreateTextureBuilder()
-        .SetDimension(dawn::TextureDimension::e2D)
-        .SetExtent(1024, 1024, 1)
-        .SetFormat(dawn::TextureFormat::R8G8B8A8Unorm)
-        .SetMipLevels(1)
-        .SetAllowedUsage(dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::Sampled)
-        .GetResult();
+    dawn::TextureDescriptor descriptor;
+    descriptor.dimension = dawn::TextureDimension::e2D;
+    descriptor.width = 1024;
+    descriptor.height = 1024;
+    descriptor.depth = 1;
+    descriptor.arrayLayer = 1;
+    descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm;
+    descriptor.mipLevel = 1;
+    descriptor.usage = dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::Sampled;
+    texture = device.CreateTexture(&descriptor);
 
     dawn::SamplerDescriptor samplerDesc = utils::GetDefaultSamplerDescriptor();
     sampler = device.CreateSampler(&samplerDesc);
diff --git a/examples/SampleUtils.cpp b/examples/SampleUtils.cpp
index 9055476..8d459db 100644
--- a/examples/SampleUtils.cpp
+++ b/examples/SampleUtils.cpp
@@ -136,13 +136,16 @@
 }
 
 dawn::TextureView CreateDefaultDepthStencilView(const dawn::Device& device) {
-    auto depthStencilTexture = device.CreateTextureBuilder()
-        .SetDimension(dawn::TextureDimension::e2D)
-        .SetExtent(640, 480, 1)
-        .SetFormat(dawn::TextureFormat::D32FloatS8Uint)
-        .SetMipLevels(1)
-        .SetAllowedUsage(dawn::TextureUsageBit::OutputAttachment)
-        .GetResult();
+    dawn::TextureDescriptor descriptor;
+    descriptor.dimension = dawn::TextureDimension::e2D;
+    descriptor.width = 640;
+    descriptor.height = 480;
+    descriptor.depth = 1;
+    descriptor.arrayLayer = 1;
+    descriptor.format = dawn::TextureFormat::D32FloatS8Uint;
+    descriptor.mipLevel = 1;
+    descriptor.usage = dawn::TextureUsageBit::OutputAttachment;
+    auto depthStencilTexture = device.CreateTexture(&descriptor);
     return depthStencilTexture.CreateTextureViewBuilder()
         .GetResult();
 }
diff --git a/examples/glTFViewer/glTFViewer.cpp b/examples/glTFViewer/glTFViewer.cpp
index 85b3c43..e80aab3 100644
--- a/examples/glTFViewer/glTFViewer.cpp
+++ b/examples/glTFViewer/glTFViewer.cpp
@@ -382,13 +382,16 @@
                     continue;
             }
 
-            auto oTexture = device.CreateTextureBuilder()
-                .SetDimension(dawn::TextureDimension::e2D)
-                .SetExtent(iImage.width, iImage.height, 1)
-                .SetFormat(format)
-                .SetMipLevels(1)
-                .SetAllowedUsage(dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::Sampled)
-                .GetResult();
+            dawn::TextureDescriptor descriptor;
+            descriptor.dimension = dawn::TextureDimension::e2D;
+            descriptor.width = iImage.width;
+            descriptor.height = iImage.height;
+            descriptor.depth = 1;
+            descriptor.arrayLayer = 1;
+            descriptor.format = format;
+            descriptor.mipLevel = 1;
+            descriptor.usage = dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::Sampled;
+            auto oTexture = device.CreateTexture(&descriptor);
                 // TODO: release this texture
 
             const uint8_t* origData = iImage.image.data();
diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp
index 85b7967..217cf43 100644
--- a/src/dawn_native/Device.cpp
+++ b/src/dawn_native/Device.cpp
@@ -178,8 +178,13 @@
     SwapChainBuilder* DeviceBase::CreateSwapChainBuilder() {
         return new SwapChainBuilder(this);
     }
-    TextureBuilder* DeviceBase::CreateTextureBuilder() {
-        return new TextureBuilder(this);
+    TextureBase* DeviceBase::CreateTexture(const TextureDescriptor* descriptor) {
+        TextureBase* result = nullptr;
+
+        if (ConsumedError(CreateTextureInternal(&result, descriptor))) {
+            return nullptr;
+        }
+        return result;
     }
 
     // Other Device API methods
@@ -245,6 +250,13 @@
         return {};
     }
 
+    MaybeError DeviceBase::CreateTextureInternal(TextureBase** result,
+                                                 const TextureDescriptor* descriptor) {
+        DAWN_TRY(ValidateTextureDescriptor(this, descriptor));
+        DAWN_TRY_ASSIGN(*result, CreateTextureImpl(descriptor));
+        return {};
+    }
+
     // Other implementation details
 
     void DeviceBase::ConsumeError(ErrorData* error) {
diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h
index 0c6d271..cb76645 100644
--- a/src/dawn_native/Device.h
+++ b/src/dawn_native/Device.h
@@ -55,7 +55,6 @@
             RenderPassDescriptorBuilder* builder) = 0;
         virtual RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) = 0;
         virtual SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) = 0;
-        virtual TextureBase* CreateTexture(TextureBuilder* builder) = 0;
         virtual TextureViewBase* CreateTextureView(TextureViewBuilder* builder) = 0;
 
         virtual void TickImpl() = 0;
@@ -94,7 +93,7 @@
         SamplerBase* CreateSampler(const SamplerDescriptor* descriptor);
         ShaderModuleBase* CreateShaderModule(const ShaderModuleDescriptor* descriptor);
         SwapChainBuilder* CreateSwapChainBuilder();
-        TextureBuilder* CreateTextureBuilder();
+        TextureBase* CreateTexture(const TextureDescriptor* descriptor);
 
         void Tick();
         void SetErrorCallback(dawn::DeviceErrorCallback callback, dawn::CallbackUserdata userdata);
@@ -116,6 +115,8 @@
             const SamplerDescriptor* descriptor) = 0;
         virtual ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl(
             const ShaderModuleDescriptor* descriptor) = 0;
+        virtual ResultOrError<TextureBase*> CreateTextureImpl(
+            const TextureDescriptor* descriptor) = 0;
 
         MaybeError CreateBindGroupLayoutInternal(BindGroupLayoutBase** result,
                                                  const BindGroupLayoutDescriptor* descriptor);
@@ -126,6 +127,7 @@
         MaybeError CreateSamplerInternal(SamplerBase** result, const SamplerDescriptor* descriptor);
         MaybeError CreateShaderModuleInternal(ShaderModuleBase** result,
                                               const ShaderModuleDescriptor* descriptor);
+        MaybeError CreateTextureInternal(TextureBase** result, const TextureDescriptor* descriptor);
 
         void ConsumeError(ErrorData* error);
 
diff --git a/src/dawn_native/Forward.h b/src/dawn_native/Forward.h
index 9a30a1a..a67b89a 100644
--- a/src/dawn_native/Forward.h
+++ b/src/dawn_native/Forward.h
@@ -50,7 +50,6 @@
     class SwapChainBase;
     class SwapChainBuilder;
     class TextureBase;
-    class TextureBuilder;
     class TextureViewBase;
     class TextureViewBuilder;
 
diff --git a/src/dawn_native/SwapChain.cpp b/src/dawn_native/SwapChain.cpp
index 8dc96e8..ebb2a9d 100644
--- a/src/dawn_native/SwapChain.cpp
+++ b/src/dawn_native/SwapChain.cpp
@@ -59,16 +59,18 @@
             return nullptr;
         }
 
-        auto* builder = mDevice->CreateTextureBuilder();
-        builder->SetDimension(dawn::TextureDimension::e2D);
-        builder->SetExtent(mWidth, mHeight, 1);
-        builder->SetFormat(mFormat);
-        builder->SetMipLevels(1);
-        builder->SetAllowedUsage(mAllowedUsage);
+        TextureDescriptor descriptor;
+        descriptor.dimension = dawn::TextureDimension::e2D;
+        descriptor.width = mWidth;
+        descriptor.height = mHeight;
+        descriptor.depth = 1;
+        descriptor.arrayLayer = 1;
+        descriptor.format = mFormat;
+        descriptor.mipLevel = 1;
+        descriptor.usage = mAllowedUsage;
 
-        auto* texture = GetNextTextureImpl(builder);
+        auto* texture = GetNextTextureImpl(&descriptor);
         mLastNextTexture = texture;
-        builder->Release();
         return texture;
     }
 
diff --git a/src/dawn_native/SwapChain.h b/src/dawn_native/SwapChain.h
index 021dc9e..02110bf 100644
--- a/src/dawn_native/SwapChain.h
+++ b/src/dawn_native/SwapChain.h
@@ -41,7 +41,7 @@
 
       protected:
         const dawnSwapChainImplementation& GetImplementation();
-        virtual TextureBase* GetNextTextureImpl(TextureBuilder* builder) = 0;
+        virtual TextureBase* GetNextTextureImpl(const TextureDescriptor*) = 0;
         virtual void OnBeforePresent(TextureBase* texture) = 0;
 
       private:
diff --git a/src/dawn_native/Texture.cpp b/src/dawn_native/Texture.cpp
index aef8792..e0ffa79 100644
--- a/src/dawn_native/Texture.cpp
+++ b/src/dawn_native/Texture.cpp
@@ -16,8 +16,23 @@
 
 #include "common/Assert.h"
 #include "dawn_native/Device.h"
+#include "dawn_native/ValidationUtils_autogen.h"
 
 namespace dawn_native {
+    MaybeError ValidateTextureDescriptor(DeviceBase*, const TextureDescriptor* descriptor) {
+        DAWN_TRY_ASSERT(descriptor->nextInChain == nullptr, "nextInChain must be nullptr");
+        DAWN_TRY(ValidateTextureUsageBit(descriptor->usage));
+        DAWN_TRY(ValidateTextureDimension(descriptor->dimension));
+        DAWN_TRY(ValidateTextureFormat(descriptor->format));
+
+        // TODO(jiawei.shao@intel.com): check stuff based on the dimension
+        if (descriptor->width == 0 || descriptor->height == 0 || descriptor->depth == 0 ||
+            descriptor->arrayLayer == 0 || descriptor->mipLevel == 0) {
+            DAWN_RETURN_ERROR("Cannot create an empty texture");
+        }
+
+        return {};
+    }
 
     uint32_t TextureFormatPixelSize(dawn::TextureFormat format) {
         switch (format) {
@@ -67,15 +82,16 @@
 
     // TextureBase
 
-    TextureBase::TextureBase(TextureBuilder* builder)
-        : mDevice(builder->mDevice),
-          mDimension(builder->mDimension),
-          mFormat(builder->mFormat),
-          mWidth(builder->mWidth),
-          mHeight(builder->mHeight),
-          mDepth(builder->mDepth),
-          mNumMipLevels(builder->mNumMipLevels),
-          mUsage(builder->mAllowedUsage) {
+    TextureBase::TextureBase(DeviceBase* device, const TextureDescriptor* descriptor)
+        : mDevice(device),
+          mDimension(descriptor->dimension),
+          mFormat(descriptor->format),
+          mWidth(descriptor->width),
+          mHeight(descriptor->height),
+          mDepth(descriptor->depth),
+          mArrayLayers(descriptor->arrayLayer),
+          mNumMipLevels(descriptor->mipLevel),
+          mUsage(descriptor->usage) {
     }
 
     DeviceBase* TextureBase::GetDevice() const {
@@ -97,6 +113,9 @@
     uint32_t TextureBase::GetDepth() const {
         return mDepth;
     }
+    uint32_t TextureBase::GetArrayLayers() const {
+        return mArrayLayers;
+    }
     uint32_t TextureBase::GetNumMipLevels() const {
         return mNumMipLevels;
     }
@@ -108,90 +127,6 @@
         return new TextureViewBuilder(mDevice, this);
     }
 
-    // TextureBuilder
-
-    enum TextureSetProperties {
-        TEXTURE_PROPERTY_DIMENSION = 0x1,
-        TEXTURE_PROPERTY_EXTENT = 0x2,
-        TEXTURE_PROPERTY_FORMAT = 0x4,
-        TEXTURE_PROPERTY_MIP_LEVELS = 0x8,
-        TEXTURE_PROPERTY_ALLOWED_USAGE = 0x10,
-    };
-
-    TextureBuilder::TextureBuilder(DeviceBase* device) : Builder(device) {
-    }
-
-    TextureBase* TextureBuilder::GetResultImpl() {
-        constexpr int allProperties = TEXTURE_PROPERTY_DIMENSION | TEXTURE_PROPERTY_EXTENT |
-                                      TEXTURE_PROPERTY_FORMAT | TEXTURE_PROPERTY_MIP_LEVELS |
-                                      TEXTURE_PROPERTY_ALLOWED_USAGE;
-        if ((mPropertiesSet & allProperties) != allProperties) {
-            HandleError("Texture missing properties");
-            return nullptr;
-        }
-
-        // TODO(cwallez@chromium.org): check stuff based on the dimension
-
-        return mDevice->CreateTexture(this);
-    }
-
-    void TextureBuilder::SetDimension(dawn::TextureDimension dimension) {
-        if ((mPropertiesSet & TEXTURE_PROPERTY_DIMENSION) != 0) {
-            HandleError("Texture dimension property set multiple times");
-            return;
-        }
-
-        mPropertiesSet |= TEXTURE_PROPERTY_DIMENSION;
-        mDimension = dimension;
-    }
-
-    void TextureBuilder::SetExtent(uint32_t width, uint32_t height, uint32_t depth) {
-        if ((mPropertiesSet & TEXTURE_PROPERTY_EXTENT) != 0) {
-            HandleError("Texture extent property set multiple times");
-            return;
-        }
-
-        if (width == 0 || height == 0 || depth == 0) {
-            HandleError("Cannot create an empty texture");
-            return;
-        }
-
-        mPropertiesSet |= TEXTURE_PROPERTY_EXTENT;
-        mWidth = width;
-        mHeight = height;
-        mDepth = depth;
-    }
-
-    void TextureBuilder::SetFormat(dawn::TextureFormat format) {
-        if ((mPropertiesSet & TEXTURE_PROPERTY_FORMAT) != 0) {
-            HandleError("Texture format property set multiple times");
-            return;
-        }
-
-        mPropertiesSet |= TEXTURE_PROPERTY_FORMAT;
-        mFormat = format;
-    }
-
-    void TextureBuilder::SetMipLevels(uint32_t numMipLevels) {
-        if ((mPropertiesSet & TEXTURE_PROPERTY_MIP_LEVELS) != 0) {
-            HandleError("Texture mip levels property set multiple times");
-            return;
-        }
-
-        mPropertiesSet |= TEXTURE_PROPERTY_MIP_LEVELS;
-        mNumMipLevels = numMipLevels;
-    }
-
-    void TextureBuilder::SetAllowedUsage(dawn::TextureUsageBit usage) {
-        if ((mPropertiesSet & TEXTURE_PROPERTY_ALLOWED_USAGE) != 0) {
-            HandleError("Texture allowed usage property set multiple times");
-            return;
-        }
-
-        mPropertiesSet |= TEXTURE_PROPERTY_ALLOWED_USAGE;
-        mAllowedUsage = usage;
-    }
-
     // TextureViewBase
 
     TextureViewBase::TextureViewBase(TextureViewBuilder* builder) : mTexture(builder->mTexture) {
diff --git a/src/dawn_native/Texture.h b/src/dawn_native/Texture.h
index aa0a5f3..d9ba9f9 100644
--- a/src/dawn_native/Texture.h
+++ b/src/dawn_native/Texture.h
@@ -16,12 +16,14 @@
 #define DAWNNATIVE_TEXTURE_H_
 
 #include "dawn_native/Builder.h"
+#include "dawn_native/Error.h"
 #include "dawn_native/Forward.h"
 #include "dawn_native/RefCounted.h"
 
 #include "dawn_native/dawn_platform.h"
 
 namespace dawn_native {
+    MaybeError ValidateTextureDescriptor(DeviceBase* device, const TextureDescriptor* descriptor);
 
     uint32_t TextureFormatPixelSize(dawn::TextureFormat format);
     bool TextureFormatHasDepth(dawn::TextureFormat format);
@@ -38,13 +40,14 @@
 
     class TextureBase : public RefCounted {
       public:
-        TextureBase(TextureBuilder* builder);
+        TextureBase(DeviceBase* device, const TextureDescriptor* descriptor);
 
         dawn::TextureDimension GetDimension() const;
         dawn::TextureFormat GetFormat() const;
         uint32_t GetWidth() const;
         uint32_t GetHeight() const;
         uint32_t GetDepth() const;
+        uint32_t GetArrayLayers() const;
         uint32_t GetNumMipLevels() const;
         dawn::TextureUsageBit GetUsage() const;
         DeviceBase* GetDevice() const;
@@ -58,36 +61,11 @@
         dawn::TextureDimension mDimension;
         dawn::TextureFormat mFormat;
         uint32_t mWidth, mHeight, mDepth;
+        uint32_t mArrayLayers;
         uint32_t mNumMipLevels;
         dawn::TextureUsageBit mUsage = dawn::TextureUsageBit::None;
     };
 
-    class TextureBuilder : public Builder<TextureBase> {
-      public:
-        TextureBuilder(DeviceBase* device);
-
-        // Dawn API
-        void SetDimension(dawn::TextureDimension dimension);
-        void SetExtent(uint32_t width, uint32_t height, uint32_t depth);
-        void SetFormat(dawn::TextureFormat format);
-        void SetMipLevels(uint32_t numMipLevels);
-        void SetAllowedUsage(dawn::TextureUsageBit usage);
-        void SetInitialUsage(dawn::TextureUsageBit usage);
-
-      private:
-        friend class TextureBase;
-
-        TextureBase* GetResultImpl() override;
-
-        int mPropertiesSet = 0;
-
-        dawn::TextureDimension mDimension;
-        uint32_t mWidth, mHeight, mDepth;
-        dawn::TextureFormat mFormat;
-        uint32_t mNumMipLevels;
-        dawn::TextureUsageBit mAllowedUsage = dawn::TextureUsageBit::None;
-    };
-
     class TextureViewBase : public RefCounted {
       public:
         TextureViewBase(TextureViewBuilder* builder);
diff --git a/src/dawn_native/d3d12/DeviceD3D12.cpp b/src/dawn_native/d3d12/DeviceD3D12.cpp
index f163791..f43936c 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.cpp
+++ b/src/dawn_native/d3d12/DeviceD3D12.cpp
@@ -311,8 +311,8 @@
     SwapChainBase* Device::CreateSwapChain(SwapChainBuilder* builder) {
         return new SwapChain(builder);
     }
-    TextureBase* Device::CreateTexture(TextureBuilder* builder) {
-        return new Texture(builder);
+    ResultOrError<TextureBase*> Device::CreateTextureImpl(const TextureDescriptor* descriptor) {
+        return new Texture(this, descriptor);
     }
     TextureViewBase* Device::CreateTextureView(TextureViewBuilder* builder) {
         return new TextureView(builder);
diff --git a/src/dawn_native/d3d12/DeviceD3D12.h b/src/dawn_native/d3d12/DeviceD3D12.h
index 3d19966..da9af0a 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.h
+++ b/src/dawn_native/d3d12/DeviceD3D12.h
@@ -49,7 +49,6 @@
             RenderPassDescriptorBuilder* builder) override;
         RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
         SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
-        TextureBase* CreateTexture(TextureBuilder* builder) override;
         TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override;
 
         void TickImpl() override;
@@ -84,6 +83,7 @@
         ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override;
         ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl(
             const ShaderModuleDescriptor* descriptor) override;
+        ResultOrError<TextureBase*> CreateTextureImpl(const TextureDescriptor* descriptor) override;
 
         uint64_t mSerial = 0;
         ComPtr<ID3D12Fence> mFence;
diff --git a/src/dawn_native/d3d12/SwapChainD3D12.cpp b/src/dawn_native/d3d12/SwapChainD3D12.cpp
index 3e1cb2f..2b3b6c4 100644
--- a/src/dawn_native/d3d12/SwapChainD3D12.cpp
+++ b/src/dawn_native/d3d12/SwapChainD3D12.cpp
@@ -34,7 +34,7 @@
     SwapChain::~SwapChain() {
     }
 
-    TextureBase* SwapChain::GetNextTextureImpl(TextureBuilder* builder) {
+    TextureBase* SwapChain::GetNextTextureImpl(const TextureDescriptor* descriptor) {
         const auto& im = GetImplementation();
         dawnSwapChainNextTexture next = {};
         dawnSwapChainError error = im.GetNextTexture(im.userData, &next);
@@ -44,7 +44,7 @@
         }
 
         ID3D12Resource* nativeTexture = reinterpret_cast<ID3D12Resource*>(next.texture.ptr);
-        return new Texture(builder, nativeTexture);
+        return new Texture(ToBackend(GetDevice()), descriptor, nativeTexture);
     }
 
     void SwapChain::OnBeforePresent(TextureBase* texture) {
diff --git a/src/dawn_native/d3d12/SwapChainD3D12.h b/src/dawn_native/d3d12/SwapChainD3D12.h
index 12c1a85..8a82aa9 100644
--- a/src/dawn_native/d3d12/SwapChainD3D12.h
+++ b/src/dawn_native/d3d12/SwapChainD3D12.h
@@ -25,7 +25,7 @@
         ~SwapChain();
 
       protected:
-        TextureBase* GetNextTextureImpl(TextureBuilder* builder) override;
+        TextureBase* GetNextTextureImpl(const TextureDescriptor* descriptor) override;
         void OnBeforePresent(TextureBase* texture) override;
 
         dawn::TextureUsageBit mTextureUsage;
diff --git a/src/dawn_native/d3d12/TextureD3D12.cpp b/src/dawn_native/d3d12/TextureD3D12.cpp
index ccf75bb..81e04ae 100644
--- a/src/dawn_native/d3d12/TextureD3D12.cpp
+++ b/src/dawn_native/d3d12/TextureD3D12.cpp
@@ -107,8 +107,8 @@
         }
     }
 
-    Texture::Texture(TextureBuilder* builder)
-        : TextureBase(builder), mDevice(ToBackend(builder->GetDevice())) {
+    Texture::Texture(Device* device, const TextureDescriptor* descriptor)
+        : TextureBase(device, descriptor) {
         D3D12_RESOURCE_DESC resourceDescriptor;
         resourceDescriptor.Dimension = D3D12TextureDimension(GetDimension());
         resourceDescriptor.Alignment = 0;
@@ -122,22 +122,24 @@
         resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
         resourceDescriptor.Flags = D3D12ResourceFlags(GetUsage(), GetFormat());
 
-        mResource = mDevice->GetResourceAllocator()->Allocate(
-            D3D12_HEAP_TYPE_DEFAULT, resourceDescriptor, D3D12_RESOURCE_STATE_COMMON);
+        mResource = ToBackend(GetDevice())
+                        ->GetResourceAllocator()
+                        ->Allocate(D3D12_HEAP_TYPE_DEFAULT, resourceDescriptor,
+                                   D3D12_RESOURCE_STATE_COMMON);
         mResourcePtr = mResource.Get();
     }
 
     // With this constructor, the lifetime of the ID3D12Resource is externally managed.
-    Texture::Texture(TextureBuilder* builder, ID3D12Resource* nativeTexture)
-        : TextureBase(builder),
-          mDevice(ToBackend(builder->GetDevice())),
-          mResourcePtr(nativeTexture) {
+    Texture::Texture(Device* device,
+                     const TextureDescriptor* descriptor,
+                     ID3D12Resource* nativeTexture)
+        : TextureBase(device, descriptor), mResourcePtr(nativeTexture) {
     }
 
     Texture::~Texture() {
         if (mResource) {
             // If we own the resource, release it.
-            mDevice->GetResourceAllocator()->Release(mResource);
+            ToBackend(GetDevice())->GetResourceAllocator()->Release(mResource);
         }
     }
 
diff --git a/src/dawn_native/d3d12/TextureD3D12.h b/src/dawn_native/d3d12/TextureD3D12.h
index 2c1a791..571681b 100644
--- a/src/dawn_native/d3d12/TextureD3D12.h
+++ b/src/dawn_native/d3d12/TextureD3D12.h
@@ -27,8 +27,8 @@
 
     class Texture : public TextureBase {
       public:
-        Texture(TextureBuilder* builder);
-        Texture(TextureBuilder* builder, ID3D12Resource* nativeTexture);
+        Texture(Device* device, const TextureDescriptor* descriptor);
+        Texture(Device* device, const TextureDescriptor* descriptor, ID3D12Resource* nativeTexture);
         ~Texture();
 
         DXGI_FORMAT GetD3D12Format() const;
@@ -38,7 +38,6 @@
                                 dawn::TextureUsageBit usage);
 
       private:
-        Device* mDevice;
         ComPtr<ID3D12Resource> mResource = {};
         ID3D12Resource* mResourcePtr = nullptr;
         dawn::TextureUsageBit mLastUsage = dawn::TextureUsageBit::None;
diff --git a/src/dawn_native/metal/DeviceMTL.h b/src/dawn_native/metal/DeviceMTL.h
index d838a03..dbcb941 100644
--- a/src/dawn_native/metal/DeviceMTL.h
+++ b/src/dawn_native/metal/DeviceMTL.h
@@ -46,7 +46,6 @@
             RenderPassDescriptorBuilder* builder) override;
         RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
         SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
-        TextureBase* CreateTexture(TextureBuilder* builder) override;
         TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override;
 
         void TickImpl() override;
@@ -70,6 +69,7 @@
         ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override;
         ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl(
             const ShaderModuleDescriptor* descriptor) override;
+        ResultOrError<TextureBase*> CreateTextureImpl(const TextureDescriptor* descriptor) override;
 
         void OnCompletedHandler();
 
diff --git a/src/dawn_native/metal/DeviceMTL.mm b/src/dawn_native/metal/DeviceMTL.mm
index 4d5f064..6ecd6b1 100644
--- a/src/dawn_native/metal/DeviceMTL.mm
+++ b/src/dawn_native/metal/DeviceMTL.mm
@@ -130,8 +130,8 @@
     SwapChainBase* Device::CreateSwapChain(SwapChainBuilder* builder) {
         return new SwapChain(builder);
     }
-    TextureBase* Device::CreateTexture(TextureBuilder* builder) {
-        return new Texture(builder);
+    ResultOrError<TextureBase*> Device::CreateTextureImpl(const TextureDescriptor* descriptor) {
+        return new Texture(this, descriptor);
     }
     TextureViewBase* Device::CreateTextureView(TextureViewBuilder* builder) {
         return new TextureView(builder);
diff --git a/src/dawn_native/metal/SwapChainMTL.h b/src/dawn_native/metal/SwapChainMTL.h
index 02f4dca..ac88ce1 100644
--- a/src/dawn_native/metal/SwapChainMTL.h
+++ b/src/dawn_native/metal/SwapChainMTL.h
@@ -27,7 +27,7 @@
         ~SwapChain();
 
       protected:
-        TextureBase* GetNextTextureImpl(TextureBuilder* builder) override;
+        TextureBase* GetNextTextureImpl(const TextureDescriptor* descriptor) override;
         void OnBeforePresent(TextureBase* texture) override;
     };
 
diff --git a/src/dawn_native/metal/SwapChainMTL.mm b/src/dawn_native/metal/SwapChainMTL.mm
index c53299e..f7d1a52 100644
--- a/src/dawn_native/metal/SwapChainMTL.mm
+++ b/src/dawn_native/metal/SwapChainMTL.mm
@@ -31,7 +31,7 @@
     SwapChain::~SwapChain() {
     }
 
-    TextureBase* SwapChain::GetNextTextureImpl(TextureBuilder* builder) {
+    TextureBase* SwapChain::GetNextTextureImpl(const TextureDescriptor* descriptor) {
         const auto& im = GetImplementation();
         dawnSwapChainNextTexture next = {};
         dawnSwapChainError error = im.GetNextTexture(im.userData, &next);
@@ -41,7 +41,7 @@
         }
 
         id<MTLTexture> nativeTexture = reinterpret_cast<id<MTLTexture>>(next.texture.ptr);
-        return new Texture(builder, nativeTexture);
+        return new Texture(ToBackend(GetDevice()), descriptor, nativeTexture);
     }
 
     void SwapChain::OnBeforePresent(TextureBase*) {
diff --git a/src/dawn_native/metal/TextureMTL.h b/src/dawn_native/metal/TextureMTL.h
index 9bb3de6..3057c36 100644
--- a/src/dawn_native/metal/TextureMTL.h
+++ b/src/dawn_native/metal/TextureMTL.h
@@ -21,12 +21,14 @@
 
 namespace dawn_native { namespace metal {
 
+    class Device;
+
     MTLPixelFormat MetalPixelFormat(dawn::TextureFormat format);
 
     class Texture : public TextureBase {
       public:
-        Texture(TextureBuilder* builder);
-        Texture(TextureBuilder* builder, id<MTLTexture> mtlTexture);
+        Texture(Device* device, const TextureDescriptor* descriptor);
+        Texture(Device* device, const TextureDescriptor* descriptor, id<MTLTexture> mtlTexture);
         ~Texture();
 
         id<MTLTexture> GetMTLTexture();
diff --git a/src/dawn_native/metal/TextureMTL.mm b/src/dawn_native/metal/TextureMTL.mm
index 3ce2e86..3c3a1c2 100644
--- a/src/dawn_native/metal/TextureMTL.mm
+++ b/src/dawn_native/metal/TextureMTL.mm
@@ -66,7 +66,8 @@
         }
     }
 
-    Texture::Texture(TextureBuilder* builder) : TextureBase(builder) {
+    Texture::Texture(Device* device, const TextureDescriptor* descriptor)
+        : TextureBase(device, descriptor) {
         auto desc = [MTLTextureDescriptor new];
         [desc autorelease];
         desc.textureType = MetalTextureType(GetDimension());
@@ -79,12 +80,12 @@
         desc.arrayLength = 1;
         desc.storageMode = MTLStorageModePrivate;
 
-        auto mtlDevice = ToBackend(builder->GetDevice())->GetMTLDevice();
+        auto mtlDevice = device->GetMTLDevice();
         mMtlTexture = [mtlDevice newTextureWithDescriptor:desc];
     }
 
-    Texture::Texture(TextureBuilder* builder, id<MTLTexture> mtlTexture)
-        : TextureBase(builder), mMtlTexture(mtlTexture) {
+    Texture::Texture(Device* device, const TextureDescriptor* descriptor, id<MTLTexture> mtlTexture)
+        : TextureBase(device, descriptor), mMtlTexture(mtlTexture) {
         [mMtlTexture retain];
     }
 
diff --git a/src/dawn_native/null/NullBackend.cpp b/src/dawn_native/null/NullBackend.cpp
index cbfe8c5..8331614 100644
--- a/src/dawn_native/null/NullBackend.cpp
+++ b/src/dawn_native/null/NullBackend.cpp
@@ -90,8 +90,8 @@
     SwapChainBase* Device::CreateSwapChain(SwapChainBuilder* builder) {
         return new SwapChain(builder);
     }
-    TextureBase* Device::CreateTexture(TextureBuilder* builder) {
-        return new Texture(builder);
+    ResultOrError<TextureBase*> Device::CreateTextureImpl(const TextureDescriptor* descriptor) {
+        return new Texture(this, descriptor);
     }
     TextureViewBase* Device::CreateTextureView(TextureViewBuilder* builder) {
         return new TextureView(builder);
@@ -207,8 +207,8 @@
     SwapChain::~SwapChain() {
     }
 
-    TextureBase* SwapChain::GetNextTextureImpl(TextureBuilder* builder) {
-        return GetDevice()->CreateTexture(builder);
+    TextureBase* SwapChain::GetNextTextureImpl(const TextureDescriptor* descriptor) {
+        return GetDevice()->CreateTexture(descriptor);
     }
 
     void SwapChain::OnBeforePresent(TextureBase*) {
diff --git a/src/dawn_native/null/NullBackend.h b/src/dawn_native/null/NullBackend.h
index d3a5b8e..3b206a3 100644
--- a/src/dawn_native/null/NullBackend.h
+++ b/src/dawn_native/null/NullBackend.h
@@ -106,7 +106,6 @@
             RenderPassDescriptorBuilder* builder) override;
         RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
         SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
-        TextureBase* CreateTexture(TextureBuilder* builder) override;
         TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override;
 
         void TickImpl() override;
@@ -124,6 +123,7 @@
         ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override;
         ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl(
             const ShaderModuleDescriptor* descriptor) override;
+        ResultOrError<TextureBase*> CreateTextureImpl(const TextureDescriptor* descriptor) override;
 
         std::vector<std::unique_ptr<PendingOperation>> mPendingOperations;
     };
@@ -170,7 +170,7 @@
         ~SwapChain();
 
       protected:
-        TextureBase* GetNextTextureImpl(TextureBuilder* builder) override;
+        TextureBase* GetNextTextureImpl(const TextureDescriptor* descriptor) override;
         void OnBeforePresent(TextureBase*) override;
     };
 
diff --git a/src/dawn_native/opengl/DeviceGL.cpp b/src/dawn_native/opengl/DeviceGL.cpp
index 04358f8..a9dcd55 100644
--- a/src/dawn_native/opengl/DeviceGL.cpp
+++ b/src/dawn_native/opengl/DeviceGL.cpp
@@ -98,8 +98,8 @@
     SwapChainBase* Device::CreateSwapChain(SwapChainBuilder* builder) {
         return new SwapChain(builder);
     }
-    TextureBase* Device::CreateTexture(TextureBuilder* builder) {
-        return new Texture(builder);
+    ResultOrError<TextureBase*> Device::CreateTextureImpl(const TextureDescriptor* descriptor) {
+        return new Texture(this, descriptor);
     }
     TextureViewBase* Device::CreateTextureView(TextureViewBuilder* builder) {
         return new TextureView(builder);
diff --git a/src/dawn_native/opengl/DeviceGL.h b/src/dawn_native/opengl/DeviceGL.h
index 8449dd8..dfe2644 100644
--- a/src/dawn_native/opengl/DeviceGL.h
+++ b/src/dawn_native/opengl/DeviceGL.h
@@ -43,7 +43,6 @@
             RenderPassDescriptorBuilder* builder) override;
         RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
         SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
-        TextureBase* CreateTexture(TextureBuilder* builder) override;
         TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override;
 
         void TickImpl() override;
@@ -58,6 +57,7 @@
         ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override;
         ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl(
             const ShaderModuleDescriptor* descriptor) override;
+        ResultOrError<TextureBase*> CreateTextureImpl(const TextureDescriptor* descriptor) override;
     };
 
 }}  // namespace dawn_native::opengl
diff --git a/src/dawn_native/opengl/SwapChainGL.cpp b/src/dawn_native/opengl/SwapChainGL.cpp
index 2cbeee0..5e46808 100644
--- a/src/dawn_native/opengl/SwapChainGL.cpp
+++ b/src/dawn_native/opengl/SwapChainGL.cpp
@@ -15,6 +15,7 @@
 #include "dawn_native/opengl/SwapChainGL.h"
 
 #include "dawn_native/Device.h"
+#include "dawn_native/opengl/Forward.h"
 #include "dawn_native/opengl/TextureGL.h"
 
 #include <dawn/dawn_wsi.h>
@@ -29,7 +30,7 @@
     SwapChain::~SwapChain() {
     }
 
-    TextureBase* SwapChain::GetNextTextureImpl(TextureBuilder* builder) {
+    TextureBase* SwapChain::GetNextTextureImpl(const TextureDescriptor* descriptor) {
         const auto& im = GetImplementation();
         dawnSwapChainNextTexture next = {};
         dawnSwapChainError error = im.GetNextTexture(im.userData, &next);
@@ -38,7 +39,7 @@
             return nullptr;
         }
         GLuint nativeTexture = next.texture.u32;
-        return new Texture(builder, nativeTexture);
+        return new Texture(ToBackend(GetDevice()), descriptor, nativeTexture);
     }
 
     void SwapChain::OnBeforePresent(TextureBase*) {
diff --git a/src/dawn_native/opengl/SwapChainGL.h b/src/dawn_native/opengl/SwapChainGL.h
index 23b8188..d1df750 100644
--- a/src/dawn_native/opengl/SwapChainGL.h
+++ b/src/dawn_native/opengl/SwapChainGL.h
@@ -29,7 +29,7 @@
         ~SwapChain();
 
       protected:
-        TextureBase* GetNextTextureImpl(TextureBuilder* builder) override;
+        TextureBase* GetNextTextureImpl(const TextureDescriptor* descriptor) override;
         void OnBeforePresent(TextureBase* texture) override;
     };
 
diff --git a/src/dawn_native/opengl/TextureGL.cpp b/src/dawn_native/opengl/TextureGL.cpp
index fe52874..12cadc8 100644
--- a/src/dawn_native/opengl/TextureGL.cpp
+++ b/src/dawn_native/opengl/TextureGL.cpp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include "dawn_native/opengl/TextureGL.h"
+#include "dawn_native/opengl/DeviceGL.h"
 
 #include "common/Assert.h"
 
@@ -67,11 +68,12 @@
 
     // Texture
 
-    Texture::Texture(TextureBuilder* builder) : Texture(builder, GenTexture()) {
+    Texture::Texture(Device* device, const TextureDescriptor* descriptor)
+        : Texture(device, descriptor, GenTexture()) {
     }
 
-    Texture::Texture(TextureBuilder* builder, GLuint handle)
-        : TextureBase(builder), mHandle(handle) {
+    Texture::Texture(Device* device, const TextureDescriptor* descriptor, GLuint handle)
+        : TextureBase(device, descriptor), mHandle(handle) {
         mTarget = TargetForDimension(GetDimension());
 
         uint32_t width = GetWidth();
diff --git a/src/dawn_native/opengl/TextureGL.h b/src/dawn_native/opengl/TextureGL.h
index 3c29a5b..7e40b1a 100644
--- a/src/dawn_native/opengl/TextureGL.h
+++ b/src/dawn_native/opengl/TextureGL.h
@@ -21,6 +21,8 @@
 
 namespace dawn_native { namespace opengl {
 
+    class Device;
+
     struct TextureFormatInfo {
         GLenum internalFormat;
         GLenum format;
@@ -29,8 +31,8 @@
 
     class Texture : public TextureBase {
       public:
-        Texture(TextureBuilder* builder);
-        Texture(TextureBuilder* builder, GLuint handle);
+        Texture(Device* device, const TextureDescriptor* descriptor);
+        Texture(Device* device, const TextureDescriptor* descriptor, GLuint handle);
         ~Texture();
 
         GLuint GetHandle() const;
diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp
index 3010083..25984cb 100644
--- a/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/src/dawn_native/vulkan/DeviceVk.cpp
@@ -269,8 +269,8 @@
     SwapChainBase* Device::CreateSwapChain(SwapChainBuilder* builder) {
         return new SwapChain(builder);
     }
-    TextureBase* Device::CreateTexture(TextureBuilder* builder) {
-        return new Texture(builder);
+    ResultOrError<TextureBase*> Device::CreateTextureImpl(const TextureDescriptor* descriptor) {
+        return new Texture(this, descriptor);
     }
     TextureViewBase* Device::CreateTextureView(TextureViewBuilder* builder) {
         return new TextureView(builder);
diff --git a/src/dawn_native/vulkan/DeviceVk.h b/src/dawn_native/vulkan/DeviceVk.h
index 62daaa7..764b125 100644
--- a/src/dawn_native/vulkan/DeviceVk.h
+++ b/src/dawn_native/vulkan/DeviceVk.h
@@ -74,7 +74,6 @@
             RenderPassDescriptorBuilder* builder) override;
         RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
         SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
-        TextureBase* CreateTexture(TextureBuilder* builder) override;
         TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override;
 
         void TickImpl() override;
@@ -89,6 +88,7 @@
         ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override;
         ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl(
             const ShaderModuleDescriptor* descriptor) override;
+        ResultOrError<TextureBase*> CreateTextureImpl(const TextureDescriptor* descriptor) override;
 
         bool CreateInstance(VulkanGlobalKnobs* usedKnobs,
                             const std::vector<const char*>& requiredExtensions);
diff --git a/src/dawn_native/vulkan/SwapChainVk.cpp b/src/dawn_native/vulkan/SwapChainVk.cpp
index 658479c..dd84569 100644
--- a/src/dawn_native/vulkan/SwapChainVk.cpp
+++ b/src/dawn_native/vulkan/SwapChainVk.cpp
@@ -31,7 +31,7 @@
     SwapChain::~SwapChain() {
     }
 
-    TextureBase* SwapChain::GetNextTextureImpl(TextureBuilder* builder) {
+    TextureBase* SwapChain::GetNextTextureImpl(const TextureDescriptor* descriptor) {
         const auto& im = GetImplementation();
         dawnSwapChainNextTexture next = {};
         dawnSwapChainError error = im.GetNextTexture(im.userData, &next);
@@ -42,7 +42,7 @@
         }
 
         VkImage nativeTexture = VkImage::CreateFromU64(next.texture.u64);
-        return new Texture(builder, nativeTexture);
+        return new Texture(ToBackend(GetDevice()), descriptor, nativeTexture);
     }
 
     void SwapChain::OnBeforePresent(TextureBase* texture) {
diff --git a/src/dawn_native/vulkan/SwapChainVk.h b/src/dawn_native/vulkan/SwapChainVk.h
index 00715e5..87f6ee5 100644
--- a/src/dawn_native/vulkan/SwapChainVk.h
+++ b/src/dawn_native/vulkan/SwapChainVk.h
@@ -27,7 +27,7 @@
         ~SwapChain();
 
       protected:
-        TextureBase* GetNextTextureImpl(TextureBuilder* builder) override;
+        TextureBase* GetNextTextureImpl(const TextureDescriptor* descriptor) override;
         void OnBeforePresent(TextureBase* texture) override;
 
       private:
diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp
index 6d9add9..ae66277 100644
--- a/src/dawn_native/vulkan/TextureVk.cpp
+++ b/src/dawn_native/vulkan/TextureVk.cpp
@@ -235,9 +235,8 @@
         return flags;
     }
 
-    Texture::Texture(TextureBuilder* builder) : TextureBase(builder) {
-        Device* device = ToBackend(GetDevice());
-
+    Texture::Texture(Device* device, const TextureDescriptor* descriptor)
+        : TextureBase(device, descriptor) {
         // Create the Vulkan image "container". We don't need to check that the format supports the
         // combination of sample, usage etc. because validation should have been done in the Dawn
         // frontend already based on the minimum supported formats in the Vulkan spec
@@ -278,8 +277,8 @@
         }
     }
 
-    Texture::Texture(TextureBuilder* builder, VkImage nativeImage)
-        : TextureBase(builder), mHandle(nativeImage) {
+    Texture::Texture(Device* device, const TextureDescriptor* descriptor, VkImage nativeImage)
+        : TextureBase(device, descriptor), mHandle(nativeImage) {
     }
 
     Texture::~Texture() {
diff --git a/src/dawn_native/vulkan/TextureVk.h b/src/dawn_native/vulkan/TextureVk.h
index e5bbe3c..d87e0a3 100644
--- a/src/dawn_native/vulkan/TextureVk.h
+++ b/src/dawn_native/vulkan/TextureVk.h
@@ -27,8 +27,8 @@
 
     class Texture : public TextureBase {
       public:
-        Texture(TextureBuilder* builder);
-        Texture(TextureBuilder* builder, VkImage nativeImage);
+        Texture(Device* device, const TextureDescriptor* descriptor);
+        Texture(Device* device, const TextureDescriptor* descriptor, VkImage nativeImage);
         ~Texture();
 
         VkImage GetHandle() const;
diff --git a/src/tests/end2end/BlendStateTests.cpp b/src/tests/end2end/BlendStateTests.cpp
index 7d7441a..5a02280 100644
--- a/src/tests/end2end/BlendStateTests.cpp
+++ b/src/tests/end2end/BlendStateTests.cpp
@@ -690,14 +690,18 @@
     std::array<dawn::Texture, 4> renderTargets;
     std::array<dawn::TextureView, 4> renderTargetViews;
 
+    dawn::TextureDescriptor descriptor;
+    descriptor.dimension = dawn::TextureDimension::e2D;
+    descriptor.width = kRTSize;
+    descriptor.height = kRTSize;
+    descriptor.depth = 1;
+    descriptor.arrayLayer = 1;
+    descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm;
+    descriptor.mipLevel = 1;
+    descriptor.usage = dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc;
+
     for (uint32_t i = 0; i < 4; ++i) {
-        renderTargets[i] = device.CreateTextureBuilder()
-            .SetDimension(dawn::TextureDimension::e2D)
-            .SetExtent(kRTSize, kRTSize, 1)
-            .SetFormat(dawn::TextureFormat::R8G8B8A8Unorm)
-            .SetMipLevels(1)
-            .SetAllowedUsage(dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc)
-            .GetResult();
+        renderTargets[i] = device.CreateTexture(&descriptor);
         renderTargetViews[i] = renderTargets[i].CreateTextureViewBuilder().GetResult();
     }
 
diff --git a/src/tests/end2end/CopyTests.cpp b/src/tests/end2end/CopyTests.cpp
index 3be0220..2968c81 100644
--- a/src/tests/end2end/CopyTests.cpp
+++ b/src/tests/end2end/CopyTests.cpp
@@ -72,13 +72,16 @@
 
         void DoTest(const TextureSpec& textureSpec, const BufferSpec& bufferSpec) {
             // Create a texture that is `width` x `height` with (`level` + 1) mip levels.
-            dawn::Texture texture = device.CreateTextureBuilder()
-                .SetDimension(dawn::TextureDimension::e2D)
-                .SetExtent(textureSpec.width, textureSpec.height, 1)
-                .SetFormat(dawn::TextureFormat::R8G8B8A8Unorm)
-                .SetMipLevels(textureSpec.level + 1)
-                .SetAllowedUsage(dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::TransferSrc)
-                .GetResult();
+            dawn::TextureDescriptor descriptor;
+            descriptor.dimension = dawn::TextureDimension::e2D;
+            descriptor.width = textureSpec.width;
+            descriptor.height = textureSpec.height;
+            descriptor.depth = 1;
+            descriptor.arrayLayer = 1;
+            descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm;
+            descriptor.mipLevel = textureSpec.level + 1;
+            descriptor.usage = dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::TransferSrc;
+            dawn::Texture texture = device.CreateTexture(&descriptor);
 
             uint32_t width = textureSpec.width >> textureSpec.level;
             uint32_t height = textureSpec.height >> textureSpec.level;
@@ -158,13 +161,16 @@
         buffer.SetSubData(0, static_cast<uint32_t>(bufferData.size() * sizeof(RGBA8)), reinterpret_cast<const uint8_t*>(bufferData.data()));
 
         // Create a texture that is `width` x `height` with (`level` + 1) mip levels.
-        dawn::Texture texture = device.CreateTextureBuilder()
-            .SetDimension(dawn::TextureDimension::e2D)
-            .SetExtent(textureSpec.width, textureSpec.height, 1)
-            .SetFormat(dawn::TextureFormat::R8G8B8A8Unorm)
-            .SetMipLevels(textureSpec.level + 1)
-            .SetAllowedUsage(dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::TransferSrc)
-            .GetResult();
+        dawn::TextureDescriptor descriptor;
+        descriptor.dimension = dawn::TextureDimension::e2D;
+        descriptor.width = textureSpec.width;
+        descriptor.height = textureSpec.height;
+        descriptor.depth = 1;
+        descriptor.arrayLayer = 1;
+        descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm;
+        descriptor.mipLevel = textureSpec.level + 1;
+        descriptor.usage = dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::TransferSrc;
+        dawn::Texture texture = device.CreateTexture(&descriptor);
 
         dawn::CommandBuffer commands[2];
 
diff --git a/src/tests/end2end/DepthStencilStateTests.cpp b/src/tests/end2end/DepthStencilStateTests.cpp
index f70806e..64e4bc4 100644
--- a/src/tests/end2end/DepthStencilStateTests.cpp
+++ b/src/tests/end2end/DepthStencilStateTests.cpp
@@ -24,23 +24,29 @@
         void SetUp() override {
             DawnTest::SetUp();
 
-            renderTarget = device.CreateTextureBuilder()
-                .SetDimension(dawn::TextureDimension::e2D)
-                .SetExtent(kRTSize, kRTSize, 1)
-                .SetFormat(dawn::TextureFormat::R8G8B8A8Unorm)
-                .SetMipLevels(1)
-                .SetAllowedUsage(dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc)
-                .GetResult();
+            dawn::TextureDescriptor renderTargetDescriptor;
+            renderTargetDescriptor.dimension = dawn::TextureDimension::e2D;
+            renderTargetDescriptor.width = kRTSize;
+            renderTargetDescriptor.height = kRTSize;
+            renderTargetDescriptor.depth = 1;
+            renderTargetDescriptor.arrayLayer = 1;
+            renderTargetDescriptor.format = dawn::TextureFormat::R8G8B8A8Unorm;
+            renderTargetDescriptor.mipLevel = 1;
+            renderTargetDescriptor.usage = dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc;
+            renderTarget = device.CreateTexture(&renderTargetDescriptor);
 
             renderTargetView = renderTarget.CreateTextureViewBuilder().GetResult();
 
-            depthTexture = device.CreateTextureBuilder()
-                .SetDimension(dawn::TextureDimension::e2D)
-                .SetExtent(kRTSize, kRTSize, 1)
-                .SetFormat(dawn::TextureFormat::D32FloatS8Uint)
-                .SetMipLevels(1)
-                .SetAllowedUsage(dawn::TextureUsageBit::OutputAttachment)
-                .GetResult();
+            dawn::TextureDescriptor depthDescriptor;
+            depthDescriptor.dimension = dawn::TextureDimension::e2D;
+            depthDescriptor.width = kRTSize;
+            depthDescriptor.height = kRTSize;
+            depthDescriptor.depth = 1;
+            depthDescriptor.arrayLayer = 1;
+            depthDescriptor.format = dawn::TextureFormat::D32FloatS8Uint;
+            depthDescriptor.mipLevel = 1;
+            depthDescriptor.usage = dawn::TextureUsageBit::OutputAttachment;
+            depthTexture = device.CreateTexture(&depthDescriptor);
 
             depthTextureView = depthTexture.CreateTextureViewBuilder().GetResult();
 
diff --git a/src/tests/end2end/RenderPassLoadOpTests.cpp b/src/tests/end2end/RenderPassLoadOpTests.cpp
index 4b3143b..dbafeb4 100644
--- a/src/tests/end2end/RenderPassLoadOpTests.cpp
+++ b/src/tests/end2end/RenderPassLoadOpTests.cpp
@@ -55,13 +55,16 @@
         void SetUp() override {
             DawnTest::SetUp();
 
-            renderTarget = device.CreateTextureBuilder()
-                .SetDimension(dawn::TextureDimension::e2D)
-                .SetExtent(kRTSize, kRTSize, 1)
-                .SetFormat(dawn::TextureFormat::R8G8B8A8Unorm)
-                .SetMipLevels(1)
-                .SetAllowedUsage(dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc)
-                .GetResult();
+            dawn::TextureDescriptor descriptor;
+            descriptor.dimension = dawn::TextureDimension::e2D;
+            descriptor.width = kRTSize;
+            descriptor.height = kRTSize;
+            descriptor.depth = 1;
+            descriptor.arrayLayer = 1;
+            descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm;
+            descriptor.mipLevel = 1;
+            descriptor.usage = dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc;
+            renderTarget = device.CreateTexture(&descriptor);
 
             renderTargetView = renderTarget.CreateTextureViewBuilder().GetResult();
 
diff --git a/src/tests/end2end/SamplerTests.cpp b/src/tests/end2end/SamplerTests.cpp
index b0aea72..72adfb4 100644
--- a/src/tests/end2end/SamplerTests.cpp
+++ b/src/tests/end2end/SamplerTests.cpp
@@ -80,13 +80,16 @@
             .SetStage(dawn::ShaderStage::Fragment, fsModule, "main")
             .GetResult();
 
-        auto texture = device.CreateTextureBuilder()
-            .SetDimension(dawn::TextureDimension::e2D)
-            .SetExtent(2, 2, 1)
-            .SetFormat(dawn::TextureFormat::R8G8B8A8Unorm)
-            .SetMipLevels(1)
-            .SetAllowedUsage(dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::Sampled)
-            .GetResult();
+        dawn::TextureDescriptor descriptor;
+        descriptor.dimension = dawn::TextureDimension::e2D;
+        descriptor.width = 2;
+        descriptor.height = 2;
+        descriptor.depth = 1;
+        descriptor.arrayLayer = 1;
+        descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm;
+        descriptor.mipLevel = 1;
+        descriptor.usage = dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::Sampled;
+        dawn::Texture texture = device.CreateTexture(&descriptor);
 
         // Create a 2x2 checkerboard texture, with black in the top left and bottom right corners.
         const uint32_t rowPixels = kTextureRowPitchAlignment / sizeof(RGBA8);
diff --git a/src/tests/unittests/validation/CopyCommandsValidationTests.cpp b/src/tests/unittests/validation/CopyCommandsValidationTests.cpp
index c351f9d..5410d44 100644
--- a/src/tests/unittests/validation/CopyCommandsValidationTests.cpp
+++ b/src/tests/unittests/validation/CopyCommandsValidationTests.cpp
@@ -28,13 +28,16 @@
 
         dawn::Texture Create2DTexture(uint32_t width, uint32_t height, uint32_t levels,
                                          dawn::TextureFormat format, dawn::TextureUsageBit usage) {
-            dawn::Texture tex = AssertWillBeSuccess(device.CreateTextureBuilder())
-                .SetDimension(dawn::TextureDimension::e2D)
-                .SetExtent(width, height, 1)
-                .SetFormat(format)
-                .SetMipLevels(levels)
-                .SetAllowedUsage(usage)
-                .GetResult();
+            dawn::TextureDescriptor descriptor;
+            descriptor.dimension = dawn::TextureDimension::e2D;
+            descriptor.width = width;
+            descriptor.height = height;
+            descriptor.depth = 1;
+            descriptor.arrayLayer = 1;
+            descriptor.format = format;
+            descriptor.mipLevel = levels;
+            descriptor.usage = usage;
+            dawn::Texture tex = device.CreateTexture(&descriptor);
             return tex;
         }
 
diff --git a/src/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp b/src/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp
index 5a3efc9..117d234 100644
--- a/src/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp
+++ b/src/tests/unittests/validation/RenderPassDescriptorValidationTests.cpp
@@ -22,13 +22,16 @@
 };
 
 dawn::TextureView Create2DAttachment(dawn::Device& device, uint32_t width, uint32_t height, dawn::TextureFormat format) {
-    dawn::Texture attachment = device.CreateTextureBuilder()
-        .SetDimension(dawn::TextureDimension::e2D)
-        .SetExtent(width, height, 1)
-        .SetFormat(format)
-        .SetMipLevels(1)
-        .SetAllowedUsage(dawn::TextureUsageBit::OutputAttachment)
-        .GetResult();
+    dawn::TextureDescriptor descriptor;
+    descriptor.dimension = dawn::TextureDimension::e2D;
+    descriptor.width = width;
+    descriptor.height = height;
+    descriptor.depth = 1;
+    descriptor.arrayLayer = 1;
+    descriptor.format = format;
+    descriptor.mipLevel = 1;
+    descriptor.usage = dawn::TextureUsageBit::OutputAttachment;
+    dawn::Texture attachment = device.CreateTexture(&descriptor);
 
     return attachment.CreateTextureViewBuilder()
         .GetResult();
diff --git a/src/tests/unittests/validation/ValidationTest.cpp b/src/tests/unittests/validation/ValidationTest.cpp
index 5eeb832..f511b5f 100644
--- a/src/tests/unittests/validation/ValidationTest.cpp
+++ b/src/tests/unittests/validation/ValidationTest.cpp
@@ -71,13 +71,17 @@
 }
 
 dawn::RenderPassDescriptor ValidationTest::CreateSimpleRenderPass() {
-        auto colorBuffer = device.CreateTextureBuilder()
-            .SetDimension(dawn::TextureDimension::e2D)
-            .SetExtent(640, 480, 1)
-            .SetFormat(dawn::TextureFormat::R8G8B8A8Unorm)
-            .SetMipLevels(1)
-            .SetAllowedUsage(dawn::TextureUsageBit::OutputAttachment)
-            .GetResult();
+        dawn::TextureDescriptor descriptor;
+        descriptor.dimension = dawn::TextureDimension::e2D;
+        descriptor.width = 640;
+        descriptor.height = 480;
+        descriptor.depth = 1;
+        descriptor.arrayLayer = 1;
+        descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm;
+        descriptor.mipLevel = 1;
+        descriptor.usage = dawn::TextureUsageBit::OutputAttachment;
+
+        auto colorBuffer = device.CreateTexture(&descriptor);
         auto colorView = colorBuffer.CreateTextureViewBuilder()
             .GetResult();
 
@@ -119,13 +123,16 @@
     dummy.height = 400;
     dummy.attachmentFormat = dawn::TextureFormat::R8G8B8A8Unorm;
 
-    dummy.attachment = AssertWillBeSuccess(device.CreateTextureBuilder())
-        .SetDimension(dawn::TextureDimension::e2D)
-        .SetExtent(dummy.width, dummy.height, 1)
-        .SetFormat(dummy.attachmentFormat)
-        .SetMipLevels(1)
-        .SetAllowedUsage(dawn::TextureUsageBit::OutputAttachment)
-        .GetResult();
+    dawn::TextureDescriptor descriptor;
+    descriptor.dimension = dawn::TextureDimension::e2D;
+    descriptor.width = dummy.width;
+    descriptor.height = dummy.height;
+    descriptor.depth = 1;
+    descriptor.arrayLayer = 1;
+    descriptor.format = dummy.attachmentFormat;
+    descriptor.mipLevel = 1;
+    descriptor.usage = dawn::TextureUsageBit::OutputAttachment;
+    dummy.attachment = device.CreateTexture(&descriptor);
 
     dawn::TextureView view = AssertWillBeSuccess(dummy.attachment.CreateTextureViewBuilder()).GetResult();
 
diff --git a/src/utils/DawnHelpers.cpp b/src/utils/DawnHelpers.cpp
index f2d89f0..01daa9b 100644
--- a/src/utils/DawnHelpers.cpp
+++ b/src/utils/DawnHelpers.cpp
@@ -115,14 +115,17 @@
         result.height = height;
 
         result.colorFormat = dawn::TextureFormat::R8G8B8A8Unorm;
-        result.color = device.CreateTextureBuilder()
-                           .SetDimension(dawn::TextureDimension::e2D)
-                           .SetExtent(width, height, 1)
-                           .SetFormat(result.colorFormat)
-                           .SetMipLevels(1)
-                           .SetAllowedUsage(dawn::TextureUsageBit::OutputAttachment |
-                                            dawn::TextureUsageBit::TransferSrc)
-                           .GetResult();
+        dawn::TextureDescriptor descriptor;
+        descriptor.dimension = dawn::TextureDimension::e2D;
+        descriptor.width = width;
+        descriptor.height = height;
+        descriptor.depth = 1;
+        descriptor.arrayLayer = 1;
+        descriptor.format = result.colorFormat;
+        descriptor.mipLevel = 1;
+        descriptor.usage =
+            dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc;
+        result.color = device.CreateTexture(&descriptor);
 
         dawn::TextureView colorView = result.color.CreateTextureViewBuilder().GetResult();
         result.renderPassInfo = device.CreateRenderPassDescriptorBuilder()