Descriptorize Buffer

We still keep a dummy BufferBuilder object around so that it can be used
for the builder error callback tests of the wire.

Change-Id: If0c502bb8b62ee3ed61815e34e9b6ee6c03a65ef
diff --git a/dawn.json b/dawn.json
index 4628a17..7f038ed 100644
--- a/dawn.json
+++ b/dawn.json
@@ -212,6 +212,7 @@
         ]
     },
     "buffer builder": {
+        "_comment": "This builder is kept for testing only",
         "category": "object",
         "methods": [
             {
@@ -219,12 +220,6 @@
                 "returns": "buffer"
             },
             {
-                "name": "set allowed usage",
-                "args": [
-                    {"name": "usage", "type": "buffer usage bit"}
-                ]
-            },
-            {
                 "name": "set size",
                 "args": [
                     {"name": "size", "type": "uint32_t"}
@@ -232,6 +227,14 @@
             }
         ]
     },
+    "buffer descriptor": {
+        "category": "structure",
+        "extensible": true,
+        "members": [
+            {"name": "usage", "type": "buffer usage bit"},
+            {"name": "size", "type": "uint32_t"}
+        ]
+    },
     "buffer map read callback": {
         "category": "natively defined"
     },
@@ -537,7 +540,14 @@
                 "returns": "blend state builder"
             },
             {
-                "name": "create buffer builder",
+                "name": "create buffer",
+                "returns": "buffer",
+                "args": [
+                    {"name": "descriptor", "type": "buffer descriptor", "annotation": "const*"}
+                ]
+            },
+            {
+                "name": "create buffer builder for testing",
                 "returns": "buffer builder"
             },
             {
diff --git a/examples/ComputeBoids.cpp b/examples/ComputeBoids.cpp
index c001635..99e351e 100644
--- a/examples/ComputeBoids.cpp
+++ b/examples/ComputeBoids.cpp
@@ -80,10 +80,10 @@
     }
 
     for (size_t i = 0; i < 2; i++) {
-        particleBuffers[i] = device.CreateBufferBuilder()
-            .SetAllowedUsage(dawn::BufferUsageBit::TransferDst | dawn::BufferUsageBit::Vertex | dawn::BufferUsageBit::Storage)
-            .SetSize(sizeof(Particle) * kNumParticles)
-            .GetResult();
+        dawn::BufferDescriptor descriptor;
+        descriptor.size = sizeof(Particle) * kNumParticles;
+        descriptor.usage = dawn::BufferUsageBit::TransferDst | dawn::BufferUsageBit::Vertex | dawn::BufferUsageBit::Storage;
+        particleBuffers[i] = device.CreateBuffer(&descriptor);
 
         particleBuffers[i].SetSubData(0,
             sizeof(Particle) * kNumParticles,
diff --git a/examples/CubeReflection.cpp b/examples/CubeReflection.cpp
index 4e5f007..75ed5d7 100644
--- a/examples/CubeReflection.cpp
+++ b/examples/CubeReflection.cpp
@@ -169,10 +169,10 @@
 
     dawn::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl);
 
-    cameraBuffer = device.CreateBufferBuilder()
-        .SetAllowedUsage(dawn::BufferUsageBit::TransferDst | dawn::BufferUsageBit::Uniform)
-        .SetSize(sizeof(CameraData))
-        .GetResult();
+    dawn::BufferDescriptor cameraBufDesc;
+    cameraBufDesc.size = sizeof(CameraData);
+    cameraBufDesc.usage = dawn::BufferUsageBit::TransferDst | dawn::BufferUsageBit::Uniform;
+    cameraBuffer = device.CreateBuffer(&cameraBufDesc);
 
     glm::mat4 transform(1.0);
     transformBuffer[0] = utils::CreateBufferFromData(device, &transform, sizeof(glm::mat4), dawn::BufferUsageBit::Uniform);
diff --git a/examples/glTFViewer/glTFViewer.cpp b/examples/glTFViewer/glTFViewer.cpp
index 7074c48..85b3c43 100644
--- a/examples/glTFViewer/glTFViewer.cpp
+++ b/examples/glTFViewer/glTFViewer.cpp
@@ -123,10 +123,10 @@
 // Initialization
 namespace {
     void initBuffers() {
-        defaultBuffer = device.CreateBufferBuilder()
-            .SetAllowedUsage(dawn::BufferUsageBit::Vertex | dawn::BufferUsageBit::Index)
-            .SetSize(256)
-            .GetResult();
+        dawn::BufferDescriptor descriptor;
+        descriptor.size = 256;
+        descriptor.usage = dawn::BufferUsageBit::Vertex | dawn::BufferUsageBit::Index;
+        defaultBuffer = device.CreateBuffer(&descriptor);
 
         for (const auto& bv : scene.bufferViews) {
             const auto& iBufferViewID = bv.first;
diff --git a/generator/templates/mock_api.cpp b/generator/templates/mock_api.cpp
index 1ea25c3..3c39d71 100644
--- a/generator/templates/mock_api.cpp
+++ b/generator/templates/mock_api.cpp
@@ -108,3 +108,6 @@
         return reinterpret_cast<{{as_cType(type.name)}}>(mObjects.back().get());
     }
 {% endfor %}
+
+MockProcTable::MockProcTable() {
+}
diff --git a/generator/templates/mock_api.h b/generator/templates/mock_api.h
index b3e826d..b82a22a 100644
--- a/generator/templates/mock_api.h
+++ b/generator/templates/mock_api.h
@@ -90,6 +90,8 @@
 
 class MockProcTable : public ProcTableAsClass {
     public:
+        MockProcTable();
+
         {% for type in by_category["object"] %}
             {% for method in type.methods if len(method.arguments) < 10 %}
                 MOCK_METHOD{{len(method.arguments) + 1}}(
diff --git a/src/dawn_native/Buffer.cpp b/src/dawn_native/Buffer.cpp
index 7666592..d22b0e9 100644
--- a/src/dawn_native/Buffer.cpp
+++ b/src/dawn_native/Buffer.cpp
@@ -16,16 +16,38 @@
 
 #include "common/Assert.h"
 #include "dawn_native/Device.h"
+#include "dawn_native/ValidationUtils_autogen.h"
 
 #include <cstdio>
 #include <utility>
 
 namespace dawn_native {
 
+    MaybeError ValidateBufferDescriptor(DeviceBase*, const BufferDescriptor* descriptor) {
+        DAWN_TRY_ASSERT(descriptor->nextInChain == nullptr, "nextInChain must be nullptr");
+        DAWN_TRY(ValidateBufferUsageBit(descriptor->usage));
+
+        dawn::BufferUsageBit usage = descriptor->usage;
+
+        const dawn::BufferUsageBit kMapWriteAllowedUsages =
+            dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc;
+        if (usage & dawn::BufferUsageBit::MapWrite && (usage & kMapWriteAllowedUsages) != usage) {
+            DAWN_RETURN_ERROR("Only TransferSrc is allowed with MapWrite");
+        }
+
+        const dawn::BufferUsageBit kMapReadAllowedUsages =
+            dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::TransferDst;
+        if (usage & dawn::BufferUsageBit::MapRead && (usage & kMapReadAllowedUsages) != usage) {
+            DAWN_RETURN_ERROR("Only TransferDst is allowed with MapRead");
+        }
+
+        return {};
+    }
+
     // Buffer
 
-    BufferBase::BufferBase(BufferBuilder* builder)
-        : mDevice(builder->mDevice), mSize(builder->mSize), mUsage(builder->mAllowedUsage) {
+    BufferBase::BufferBase(DeviceBase* device, const BufferDescriptor* descriptor)
+        : mDevice(device), mSize(descriptor->size), mUsage(descriptor->usage) {
     }
 
     BufferBase::~BufferBase() {
@@ -181,62 +203,6 @@
         return {};
     }
 
-    // BufferBuilder
-
-    enum BufferSetProperties {
-        BUFFER_PROPERTY_ALLOWED_USAGE = 0x1,
-        BUFFER_PROPERTY_SIZE = 0x2,
-    };
-
-    BufferBuilder::BufferBuilder(DeviceBase* device) : Builder(device) {
-    }
-
-    BufferBase* BufferBuilder::GetResultImpl() {
-        constexpr int allProperties = BUFFER_PROPERTY_ALLOWED_USAGE | BUFFER_PROPERTY_SIZE;
-        if ((mPropertiesSet & allProperties) != allProperties) {
-            HandleError("Buffer missing properties");
-            return nullptr;
-        }
-
-        const dawn::BufferUsageBit kMapWriteAllowedUsages =
-            dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc;
-        if (mAllowedUsage & dawn::BufferUsageBit::MapWrite &&
-            (mAllowedUsage & kMapWriteAllowedUsages) != mAllowedUsage) {
-            HandleError("Only TransferSrc is allowed with MapWrite");
-            return nullptr;
-        }
-
-        const dawn::BufferUsageBit kMapReadAllowedUsages =
-            dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::TransferDst;
-        if (mAllowedUsage & dawn::BufferUsageBit::MapRead &&
-            (mAllowedUsage & kMapReadAllowedUsages) != mAllowedUsage) {
-            HandleError("Only TransferDst is allowed with MapRead");
-            return nullptr;
-        }
-
-        return mDevice->CreateBuffer(this);
-    }
-
-    void BufferBuilder::SetAllowedUsage(dawn::BufferUsageBit usage) {
-        if ((mPropertiesSet & BUFFER_PROPERTY_ALLOWED_USAGE) != 0) {
-            HandleError("Buffer allowedUsage property set multiple times");
-            return;
-        }
-
-        mAllowedUsage = usage;
-        mPropertiesSet |= BUFFER_PROPERTY_ALLOWED_USAGE;
-    }
-
-    void BufferBuilder::SetSize(uint32_t size) {
-        if ((mPropertiesSet & BUFFER_PROPERTY_SIZE) != 0) {
-            HandleError("Buffer size property set multiple times");
-            return;
-        }
-
-        mSize = size;
-        mPropertiesSet |= BUFFER_PROPERTY_SIZE;
-    }
-
     // BufferViewBase
 
     BufferViewBase::BufferViewBase(BufferViewBuilder* builder)
diff --git a/src/dawn_native/Buffer.h b/src/dawn_native/Buffer.h
index a5a41fc..851a31d 100644
--- a/src/dawn_native/Buffer.h
+++ b/src/dawn_native/Buffer.h
@@ -24,6 +24,8 @@
 
 namespace dawn_native {
 
+    MaybeError ValidateBufferDescriptor(DeviceBase* device, const BufferDescriptor* descriptor);
+
     static constexpr dawn::BufferUsageBit kReadOnlyBufferUsages =
         dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::TransferSrc |
         dawn::BufferUsageBit::Index | dawn::BufferUsageBit::Vertex | dawn::BufferUsageBit::Uniform;
@@ -34,7 +36,7 @@
 
     class BufferBase : public RefCounted {
       public:
-        BufferBase(BufferBuilder* builder);
+        BufferBase(DeviceBase* device, const BufferDescriptor* descriptor);
         ~BufferBase();
 
         uint32_t GetSize() const;
@@ -85,24 +87,6 @@
         bool mIsMapped = false;
     };
 
-    class BufferBuilder : public Builder<BufferBase> {
-      public:
-        BufferBuilder(DeviceBase* device);
-
-        // Dawn API
-        void SetAllowedUsage(dawn::BufferUsageBit usage);
-        void SetSize(uint32_t size);
-
-      private:
-        friend class BufferBase;
-
-        BufferBase* GetResultImpl() override;
-
-        uint32_t mSize;
-        dawn::BufferUsageBit mAllowedUsage = dawn::BufferUsageBit::None;
-        int mPropertiesSet = 0;
-    };
-
     class BufferViewBase : public RefCounted {
       public:
         BufferViewBase(BufferViewBuilder* builder);
@@ -135,6 +119,18 @@
         int mPropertiesSet = 0;
     };
 
+    // This builder class is kept around purely for testing but should not be used.
+    class BufferBuilder : public Builder<BufferViewBase> {
+      public:
+        BufferBuilder(DeviceBase* device) : Builder(device) {
+            UNREACHABLE();
+        }
+
+        void SetSize(uint32_t) {
+            UNREACHABLE();
+        }
+    };
+
 }  // namespace dawn_native
 
 #endif  // DAWNNATIVE_BUFFER_H_
diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp
index 4bd782d..85b7967 100644
--- a/src/dawn_native/Device.cpp
+++ b/src/dawn_native/Device.cpp
@@ -111,8 +111,14 @@
     BlendStateBuilder* DeviceBase::CreateBlendStateBuilder() {
         return new BlendStateBuilder(this);
     }
-    BufferBuilder* DeviceBase::CreateBufferBuilder() {
-        return new BufferBuilder(this);
+    BufferBase* DeviceBase::CreateBuffer(const BufferDescriptor* descriptor) {
+        BufferBase* result = nullptr;
+
+        if (ConsumedError(CreateBufferInternal(&result, descriptor))) {
+            return nullptr;
+        }
+
+        return result;
     }
     CommandBufferBuilder* DeviceBase::CreateCommandBufferBuilder() {
         return new CommandBufferBuilder(this);
@@ -205,6 +211,13 @@
         return {};
     }
 
+    MaybeError DeviceBase::CreateBufferInternal(BufferBase** result,
+                                                const BufferDescriptor* descriptor) {
+        DAWN_TRY(ValidateBufferDescriptor(this, descriptor));
+        DAWN_TRY_ASSIGN(*result, CreateBufferImpl(descriptor));
+        return {};
+    }
+
     MaybeError DeviceBase::CreatePipelineLayoutInternal(
         PipelineLayoutBase** result,
         const PipelineLayoutDescriptor* descriptor) {
diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h
index 9ff29ed..0c6d271 100644
--- a/src/dawn_native/Device.h
+++ b/src/dawn_native/Device.h
@@ -45,7 +45,6 @@
 
         virtual BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) = 0;
         virtual BlendStateBase* CreateBlendState(BlendStateBuilder* builder) = 0;
-        virtual BufferBase* CreateBuffer(BufferBuilder* builder) = 0;
         virtual BufferViewBase* CreateBufferView(BufferViewBuilder* builder) = 0;
         virtual CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) = 0;
         virtual ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) = 0;
@@ -83,7 +82,7 @@
         BindGroupBuilder* CreateBindGroupBuilder();
         BindGroupLayoutBase* CreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor);
         BlendStateBuilder* CreateBlendStateBuilder();
-        BufferBuilder* CreateBufferBuilder();
+        BufferBase* CreateBuffer(const BufferDescriptor* descriptor);
         CommandBufferBuilder* CreateCommandBufferBuilder();
         ComputePipelineBuilder* CreateComputePipelineBuilder();
         DepthStencilStateBuilder* CreateDepthStencilStateBuilder();
@@ -102,9 +101,14 @@
         void Reference();
         void Release();
 
+        BufferBuilder* CreateBufferBuilderForTesting() {
+            return nullptr;
+        }
+
       private:
         virtual ResultOrError<BindGroupLayoutBase*> CreateBindGroupLayoutImpl(
             const BindGroupLayoutDescriptor* descriptor) = 0;
+        virtual ResultOrError<BufferBase*> CreateBufferImpl(const BufferDescriptor* descriptor) = 0;
         virtual ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
             const PipelineLayoutDescriptor* descriptor) = 0;
         virtual ResultOrError<QueueBase*> CreateQueueImpl() = 0;
@@ -115,6 +119,7 @@
 
         MaybeError CreateBindGroupLayoutInternal(BindGroupLayoutBase** result,
                                                  const BindGroupLayoutDescriptor* descriptor);
+        MaybeError CreateBufferInternal(BufferBase** result, const BufferDescriptor* descriptor);
         MaybeError CreatePipelineLayoutInternal(PipelineLayoutBase** result,
                                                 const PipelineLayoutDescriptor* descriptor);
         MaybeError CreateQueueInternal(QueueBase** result);
diff --git a/src/dawn_native/ShaderModule.cpp b/src/dawn_native/ShaderModule.cpp
index 699aa30..457bafe 100644
--- a/src/dawn_native/ShaderModule.cpp
+++ b/src/dawn_native/ShaderModule.cpp
@@ -23,7 +23,8 @@
 
 namespace dawn_native {
 
-    MaybeError ValidateShaderModuleDescriptor(DeviceBase*, const ShaderModuleDescriptor* descriptor) {
+    MaybeError ValidateShaderModuleDescriptor(DeviceBase*,
+                                              const ShaderModuleDescriptor* descriptor) {
         DAWN_TRY_ASSERT(descriptor->nextInChain == nullptr, "nextInChain must be nullptr");
         // TODO(cwallez@chromium.org): Use spirv-val to check the module is well-formed
         return {};
diff --git a/src/dawn_native/d3d12/BufferD3D12.cpp b/src/dawn_native/d3d12/BufferD3D12.cpp
index 164b377..dd67467 100644
--- a/src/dawn_native/d3d12/BufferD3D12.cpp
+++ b/src/dawn_native/d3d12/BufferD3D12.cpp
@@ -67,7 +67,8 @@
         }
     }  // namespace
 
-    Buffer::Buffer(BufferBuilder* builder) : BufferBase(builder) {
+    Buffer::Buffer(Device* device, const BufferDescriptor* descriptor)
+        : BufferBase(device, descriptor) {
         D3D12_RESOURCE_DESC resourceDescriptor;
         resourceDescriptor.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
         resourceDescriptor.Alignment = 0;
@@ -100,9 +101,8 @@
             mLastUsage = dawn::BufferUsageBit::TransferSrc;
         }
 
-        mResource = ToBackend(GetDevice())
-                        ->GetResourceAllocator()
-                        ->Allocate(heapType, resourceDescriptor, bufferUsage);
+        mResource =
+            device->GetResourceAllocator()->Allocate(heapType, resourceDescriptor, bufferUsage);
     }
 
     Buffer::~Buffer() {
diff --git a/src/dawn_native/d3d12/BufferD3D12.h b/src/dawn_native/d3d12/BufferD3D12.h
index a00c7a5..4ff93ba 100644
--- a/src/dawn_native/d3d12/BufferD3D12.h
+++ b/src/dawn_native/d3d12/BufferD3D12.h
@@ -26,7 +26,7 @@
 
     class Buffer : public BufferBase {
       public:
-        Buffer(BufferBuilder* builder);
+        Buffer(Device* device, const BufferDescriptor* descriptor);
         ~Buffer();
 
         uint32_t GetD3D12Size() const;
diff --git a/src/dawn_native/d3d12/DeviceD3D12.cpp b/src/dawn_native/d3d12/DeviceD3D12.cpp
index dddbc26..f163791 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.cpp
+++ b/src/dawn_native/d3d12/DeviceD3D12.cpp
@@ -269,8 +269,8 @@
     BlendStateBase* Device::CreateBlendState(BlendStateBuilder* builder) {
         return new BlendState(builder);
     }
-    BufferBase* Device::CreateBuffer(BufferBuilder* builder) {
-        return new Buffer(builder);
+    ResultOrError<BufferBase*> Device::CreateBufferImpl(const BufferDescriptor* descriptor) {
+        return new Buffer(this, descriptor);
     }
     BufferViewBase* Device::CreateBufferView(BufferViewBuilder* builder) {
         return new BufferView(builder);
diff --git a/src/dawn_native/d3d12/DeviceD3D12.h b/src/dawn_native/d3d12/DeviceD3D12.h
index 5574153..3d19966 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.h
+++ b/src/dawn_native/d3d12/DeviceD3D12.h
@@ -40,7 +40,6 @@
 
         BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override;
         BlendStateBase* CreateBlendState(BlendStateBuilder* builder) override;
-        BufferBase* CreateBuffer(BufferBuilder* builder) override;
         BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override;
         CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override;
         ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override;
@@ -78,6 +77,7 @@
       private:
         ResultOrError<BindGroupLayoutBase*> CreateBindGroupLayoutImpl(
             const BindGroupLayoutDescriptor* descriptor) override;
+        ResultOrError<BufferBase*> CreateBufferImpl(const BufferDescriptor* descriptor) override;
         ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
             const PipelineLayoutDescriptor* descriptor) override;
         ResultOrError<QueueBase*> CreateQueueImpl() override;
diff --git a/src/dawn_native/metal/BufferMTL.h b/src/dawn_native/metal/BufferMTL.h
index 7d0b59b..fbf4d37 100644
--- a/src/dawn_native/metal/BufferMTL.h
+++ b/src/dawn_native/metal/BufferMTL.h
@@ -26,7 +26,7 @@
 
     class Buffer : public BufferBase {
       public:
-        Buffer(BufferBuilder* builder);
+        Buffer(Device* device, const BufferDescriptor* descriptor);
         ~Buffer();
 
         id<MTLBuffer> GetMTLBuffer();
diff --git a/src/dawn_native/metal/BufferMTL.mm b/src/dawn_native/metal/BufferMTL.mm
index de14f45..ebef40d 100644
--- a/src/dawn_native/metal/BufferMTL.mm
+++ b/src/dawn_native/metal/BufferMTL.mm
@@ -19,7 +19,8 @@
 
 namespace dawn_native { namespace metal {
 
-    Buffer::Buffer(BufferBuilder* builder) : BufferBase(builder) {
+    Buffer::Buffer(Device* device, const BufferDescriptor* descriptor)
+        : BufferBase(device, descriptor) {
         MTLResourceOptions storageMode;
         if (GetUsage() & (dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::MapWrite)) {
             storageMode = MTLResourceStorageModeShared;
@@ -27,8 +28,7 @@
             storageMode = MTLResourceStorageModePrivate;
         }
 
-        mMtlBuffer = [ToBackend(GetDevice())->GetMTLDevice() newBufferWithLength:GetSize()
-                                                                         options:storageMode];
+        mMtlBuffer = [device->GetMTLDevice() newBufferWithLength:GetSize() options:storageMode];
     }
 
     Buffer::~Buffer() {
diff --git a/src/dawn_native/metal/DeviceMTL.h b/src/dawn_native/metal/DeviceMTL.h
index 7a87caa..d838a03 100644
--- a/src/dawn_native/metal/DeviceMTL.h
+++ b/src/dawn_native/metal/DeviceMTL.h
@@ -37,7 +37,6 @@
 
         BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override;
         BlendStateBase* CreateBlendState(BlendStateBuilder* builder) override;
-        BufferBase* CreateBuffer(BufferBuilder* builder) override;
         BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override;
         CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override;
         ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override;
@@ -64,6 +63,7 @@
       private:
         ResultOrError<BindGroupLayoutBase*> CreateBindGroupLayoutImpl(
             const BindGroupLayoutDescriptor* descriptor) override;
+        ResultOrError<BufferBase*> CreateBufferImpl(const BufferDescriptor* descriptor) override;
         ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
             const PipelineLayoutDescriptor* descriptor) override;
         ResultOrError<QueueBase*> CreateQueueImpl() override;
diff --git a/src/dawn_native/metal/DeviceMTL.mm b/src/dawn_native/metal/DeviceMTL.mm
index 0f41704..4d5f064 100644
--- a/src/dawn_native/metal/DeviceMTL.mm
+++ b/src/dawn_native/metal/DeviceMTL.mm
@@ -88,8 +88,8 @@
     BlendStateBase* Device::CreateBlendState(BlendStateBuilder* builder) {
         return new BlendState(builder);
     }
-    BufferBase* Device::CreateBuffer(BufferBuilder* builder) {
-        return new Buffer(builder);
+    ResultOrError<BufferBase*> Device::CreateBufferImpl(const BufferDescriptor* descriptor) {
+        return new Buffer(this, descriptor);
     }
     BufferViewBase* Device::CreateBufferView(BufferViewBuilder* builder) {
         return new BufferView(builder);
diff --git a/src/dawn_native/null/NullBackend.cpp b/src/dawn_native/null/NullBackend.cpp
index c0a6650..cbfe8c5 100644
--- a/src/dawn_native/null/NullBackend.cpp
+++ b/src/dawn_native/null/NullBackend.cpp
@@ -43,8 +43,8 @@
     BlendStateBase* Device::CreateBlendState(BlendStateBuilder* builder) {
         return new BlendState(builder);
     }
-    BufferBase* Device::CreateBuffer(BufferBuilder* builder) {
-        return new Buffer(builder);
+    ResultOrError<BufferBase*> Device::CreateBufferImpl(const BufferDescriptor* descriptor) {
+        return new Buffer(this, descriptor);
     }
     BufferViewBase* Device::CreateBufferView(BufferViewBuilder* builder) {
         return new BufferView(builder);
@@ -120,7 +120,8 @@
         bool isWrite;
     };
 
-    Buffer::Buffer(BufferBuilder* builder) : BufferBase(builder) {
+    Buffer::Buffer(Device* device, const BufferDescriptor* descriptor)
+        : BufferBase(device, descriptor) {
         if (GetUsage() & (dawn::BufferUsageBit::TransferDst | dawn::BufferUsageBit::MapRead |
                           dawn::BufferUsageBit::MapWrite)) {
             mBackingData = std::unique_ptr<char[]>(new char[GetSize()]);
diff --git a/src/dawn_native/null/NullBackend.h b/src/dawn_native/null/NullBackend.h
index 6d06a65..d3a5b8e 100644
--- a/src/dawn_native/null/NullBackend.h
+++ b/src/dawn_native/null/NullBackend.h
@@ -97,7 +97,6 @@
 
         BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override;
         BlendStateBase* CreateBlendState(BlendStateBuilder* builder) override;
-        BufferBase* CreateBuffer(BufferBuilder* builder) override;
         BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override;
         CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override;
         ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override;
@@ -118,6 +117,7 @@
       private:
         ResultOrError<BindGroupLayoutBase*> CreateBindGroupLayoutImpl(
             const BindGroupLayoutDescriptor* descriptor) override;
+        ResultOrError<BufferBase*> CreateBufferImpl(const BufferDescriptor* descriptor) override;
         ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
             const PipelineLayoutDescriptor* descriptor) override;
         ResultOrError<QueueBase*> CreateQueueImpl() override;
@@ -130,7 +130,7 @@
 
     class Buffer : public BufferBase {
       public:
-        Buffer(BufferBuilder* builder);
+        Buffer(Device* device, const BufferDescriptor* descriptor);
         ~Buffer();
 
         void MapReadOperationCompleted(uint32_t serial, void* ptr, bool isWrite);
diff --git a/src/dawn_native/opengl/BufferGL.cpp b/src/dawn_native/opengl/BufferGL.cpp
index 4182b4a..6f2387b 100644
--- a/src/dawn_native/opengl/BufferGL.cpp
+++ b/src/dawn_native/opengl/BufferGL.cpp
@@ -14,11 +14,14 @@
 
 #include "dawn_native/opengl/BufferGL.h"
 
+#include "dawn_native/opengl/DeviceGL.h"
+
 namespace dawn_native { namespace opengl {
 
     // Buffer
 
-    Buffer::Buffer(BufferBuilder* builder) : BufferBase(builder) {
+    Buffer::Buffer(Device* device, const BufferDescriptor* descriptor)
+        : BufferBase(device, descriptor) {
         glGenBuffers(1, &mBuffer);
         glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
         glBufferData(GL_ARRAY_BUFFER, GetSize(), nullptr, GL_STATIC_DRAW);
diff --git a/src/dawn_native/opengl/BufferGL.h b/src/dawn_native/opengl/BufferGL.h
index c6c85f6..98c3d1e 100644
--- a/src/dawn_native/opengl/BufferGL.h
+++ b/src/dawn_native/opengl/BufferGL.h
@@ -25,7 +25,7 @@
 
     class Buffer : public BufferBase {
       public:
-        Buffer(BufferBuilder* builder);
+        Buffer(Device* device, const BufferDescriptor* descriptor);
 
         GLuint GetHandle() const;
 
diff --git a/src/dawn_native/opengl/DeviceGL.cpp b/src/dawn_native/opengl/DeviceGL.cpp
index 26bdf41..04358f8 100644
--- a/src/dawn_native/opengl/DeviceGL.cpp
+++ b/src/dawn_native/opengl/DeviceGL.cpp
@@ -56,8 +56,8 @@
     BlendStateBase* Device::CreateBlendState(BlendStateBuilder* builder) {
         return new BlendState(builder);
     }
-    BufferBase* Device::CreateBuffer(BufferBuilder* builder) {
-        return new Buffer(builder);
+    ResultOrError<BufferBase*> Device::CreateBufferImpl(const BufferDescriptor* descriptor) {
+        return new Buffer(this, descriptor);
     }
     BufferViewBase* Device::CreateBufferView(BufferViewBuilder* builder) {
         return new BufferView(builder);
diff --git a/src/dawn_native/opengl/DeviceGL.h b/src/dawn_native/opengl/DeviceGL.h
index b1fcdec..8449dd8 100644
--- a/src/dawn_native/opengl/DeviceGL.h
+++ b/src/dawn_native/opengl/DeviceGL.h
@@ -34,7 +34,6 @@
       public:
         BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override;
         BlendStateBase* CreateBlendState(BlendStateBuilder* builder) override;
-        BufferBase* CreateBuffer(BufferBuilder* builder) override;
         BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override;
         CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override;
         ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override;
@@ -52,6 +51,7 @@
       private:
         ResultOrError<BindGroupLayoutBase*> CreateBindGroupLayoutImpl(
             const BindGroupLayoutDescriptor* descriptor) override;
+        ResultOrError<BufferBase*> CreateBufferImpl(const BufferDescriptor* descriptor) override;
         ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
             const PipelineLayoutDescriptor* descriptor) override;
         ResultOrError<QueueBase*> CreateQueueImpl() override;
diff --git a/src/dawn_native/vulkan/BufferVk.cpp b/src/dawn_native/vulkan/BufferVk.cpp
index 9142abc..3c7d137 100644
--- a/src/dawn_native/vulkan/BufferVk.cpp
+++ b/src/dawn_native/vulkan/BufferVk.cpp
@@ -103,9 +103,8 @@
 
     }  // namespace
 
-    Buffer::Buffer(BufferBuilder* builder) : BufferBase(builder) {
-        Device* device = ToBackend(GetDevice());
-
+    Buffer::Buffer(Device* device, const BufferDescriptor* descriptor)
+        : BufferBase(device, descriptor) {
         VkBufferCreateInfo createInfo;
         createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
         createInfo.pNext = nullptr;
diff --git a/src/dawn_native/vulkan/BufferVk.h b/src/dawn_native/vulkan/BufferVk.h
index 0c466a7..d2ff4f6 100644
--- a/src/dawn_native/vulkan/BufferVk.h
+++ b/src/dawn_native/vulkan/BufferVk.h
@@ -27,7 +27,7 @@
 
     class Buffer : public BufferBase {
       public:
-        Buffer(BufferBuilder* builder);
+        Buffer(Device* device, const BufferDescriptor* descriptor);
         ~Buffer();
 
         void OnMapReadCommandSerialFinished(uint32_t mapSerial, const void* data);
diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp
index 1bf7769..3010083 100644
--- a/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/src/dawn_native/vulkan/DeviceVk.cpp
@@ -227,8 +227,8 @@
     BlendStateBase* Device::CreateBlendState(BlendStateBuilder* builder) {
         return new BlendState(builder);
     }
-    BufferBase* Device::CreateBuffer(BufferBuilder* builder) {
-        return new Buffer(builder);
+    ResultOrError<BufferBase*> Device::CreateBufferImpl(const BufferDescriptor* descriptor) {
+        return new Buffer(this, descriptor);
     }
     BufferViewBase* Device::CreateBufferView(BufferViewBuilder* builder) {
         return new BufferView(builder);
diff --git a/src/dawn_native/vulkan/DeviceVk.h b/src/dawn_native/vulkan/DeviceVk.h
index 19e1d91..62daaa7 100644
--- a/src/dawn_native/vulkan/DeviceVk.h
+++ b/src/dawn_native/vulkan/DeviceVk.h
@@ -65,7 +65,6 @@
         // Dawn API
         BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override;
         BlendStateBase* CreateBlendState(BlendStateBuilder* builder) override;
-        BufferBase* CreateBuffer(BufferBuilder* builder) override;
         BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override;
         CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override;
         ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override;
@@ -83,6 +82,7 @@
       private:
         ResultOrError<BindGroupLayoutBase*> CreateBindGroupLayoutImpl(
             const BindGroupLayoutDescriptor* descriptor) override;
+        ResultOrError<BufferBase*> CreateBufferImpl(const BufferDescriptor* descriptor) override;
         ResultOrError<PipelineLayoutBase*> CreatePipelineLayoutImpl(
             const PipelineLayoutDescriptor* descriptor) override;
         ResultOrError<QueueBase*> CreateQueueImpl() override;
diff --git a/src/tests/DawnTest.cpp b/src/tests/DawnTest.cpp
index a523977..6000f0c 100644
--- a/src/tests/DawnTest.cpp
+++ b/src/tests/DawnTest.cpp
@@ -303,13 +303,13 @@
 DawnTest::ReadbackReservation DawnTest::ReserveReadback(uint32_t readbackSize) {
     // For now create a new MapRead buffer for each readback
     // TODO(cwallez@chromium.org): eventually make bigger buffers and allocate linearly?
+    dawn::BufferDescriptor descriptor;
+    descriptor.size = readbackSize;
+    descriptor.usage = dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::TransferDst;
+
     ReadbackSlot slot;
     slot.bufferSize = readbackSize;
-    slot.buffer =
-        device.CreateBufferBuilder()
-            .SetSize(readbackSize)
-            .SetAllowedUsage(dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::TransferDst)
-            .GetResult();
+    slot.buffer = device.CreateBuffer(&descriptor);
 
     ReadbackReservation reservation;
     reservation.buffer = slot.buffer.Clone();
diff --git a/src/tests/end2end/BasicTests.cpp b/src/tests/end2end/BasicTests.cpp
index 45998f5..e047474 100644
--- a/src/tests/end2end/BasicTests.cpp
+++ b/src/tests/end2end/BasicTests.cpp
@@ -22,10 +22,10 @@
 // Test Buffer::SetSubData changes the content of the buffer, but really this is the most
 // basic test possible, and tests the test harness
 TEST_P(BasicTests, BufferSetSubData) {
-    dawn::Buffer buffer = device.CreateBufferBuilder()
-        .SetSize(4)
-        .SetAllowedUsage(dawn::BufferUsageBit::TransferSrc | dawn::BufferUsageBit::TransferDst)
-        .GetResult();
+    dawn::BufferDescriptor descriptor;
+    descriptor.size = 4;
+    descriptor.usage = dawn::BufferUsageBit::TransferSrc | dawn::BufferUsageBit::TransferDst;
+    dawn::Buffer buffer = device.CreateBuffer(&descriptor);
 
     uint8_t value = 187;
     buffer.SetSubData(0, sizeof(value), &value);
diff --git a/src/tests/end2end/BufferTests.cpp b/src/tests/end2end/BufferTests.cpp
index 4b3bcd6..0d8a92c 100644
--- a/src/tests/end2end/BufferTests.cpp
+++ b/src/tests/end2end/BufferTests.cpp
@@ -43,10 +43,10 @@
 
 // Test that the simplest map read (one u8 at offset 0) works.
 TEST_P(BufferMapReadTests, SmallReadAtZero) {
-    dawn::Buffer buffer = device.CreateBufferBuilder()
-        .SetSize(1)
-        .SetAllowedUsage(dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::TransferDst)
-        .GetResult();
+    dawn::BufferDescriptor descriptor;
+    descriptor.size = 1;
+    descriptor.usage = dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::TransferDst;
+    dawn::Buffer buffer = device.CreateBuffer(&descriptor);
 
     uint8_t myData = 187;
     buffer.SetSubData(0, sizeof(myData), &myData);
@@ -59,10 +59,10 @@
 
 // Test mapping a buffer at an offset.
 TEST_P(BufferMapReadTests, SmallReadAtOffset) {
-    dawn::Buffer buffer = device.CreateBufferBuilder()
-        .SetSize(4000)
-        .SetAllowedUsage(dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::TransferDst)
-        .GetResult();
+    dawn::BufferDescriptor descriptor;
+    descriptor.size = 4000;
+    descriptor.usage = dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::TransferDst;
+    dawn::Buffer buffer = device.CreateBuffer(&descriptor);
 
     uint8_t myData = 234;
     buffer.SetSubData(2048, sizeof(myData), &myData);
@@ -75,10 +75,10 @@
 
 // Test mapping a buffer at an offset that's not uint32-aligned.
 TEST_P(BufferMapReadTests, SmallReadAtUnalignedOffset) {
-    dawn::Buffer buffer = device.CreateBufferBuilder()
-        .SetSize(4000)
-        .SetAllowedUsage(dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::TransferDst)
-        .GetResult();
+    dawn::BufferDescriptor descriptor;
+    descriptor.size = 4000;
+    descriptor.usage = dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::TransferDst;
+    dawn::Buffer buffer = device.CreateBuffer(&descriptor);
 
     uint8_t myData = 213;
     buffer.SetSubData(3, 1, &myData);
@@ -97,10 +97,10 @@
         myData.push_back(i);
     }
 
-    dawn::Buffer buffer = device.CreateBufferBuilder()
-        .SetSize(static_cast<uint32_t>(kDataSize * sizeof(uint32_t)))
-        .SetAllowedUsage(dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::TransferDst)
-        .GetResult();
+    dawn::BufferDescriptor descriptor;
+    descriptor.size = static_cast<uint32_t>(kDataSize * sizeof(uint32_t));
+    descriptor.usage = dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::TransferDst;
+    dawn::Buffer buffer = device.CreateBuffer(&descriptor);
 
     buffer.SetSubData(0, kDataSize * sizeof(uint32_t), reinterpret_cast<uint8_t*>(myData.data()));
 
@@ -139,10 +139,10 @@
 
 // Test that the simplest map write (one u32 at offset 0) works.
 TEST_P(BufferMapWriteTests, SmallWriteAtZero) {
-    dawn::Buffer buffer = device.CreateBufferBuilder()
-        .SetSize(4)
-        .SetAllowedUsage(dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc)
-        .GetResult();
+    dawn::BufferDescriptor descriptor;
+    descriptor.size = 4;
+    descriptor.usage = dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc;
+    dawn::Buffer buffer = device.CreateBuffer(&descriptor);
 
     uint32_t myData = 2934875;
     void* mappedData = MapWriteAsyncAndWait(buffer, 0, 4);
@@ -154,10 +154,10 @@
 
 // Test mapping a buffer at an offset.
 TEST_P(BufferMapWriteTests, SmallWriteAtOffset) {
-    dawn::Buffer buffer = device.CreateBufferBuilder()
-        .SetSize(4000)
-        .SetAllowedUsage(dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc)
-        .GetResult();
+    dawn::BufferDescriptor descriptor;
+    descriptor.size = 4000;
+    descriptor.usage = dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc;
+    dawn::Buffer buffer = device.CreateBuffer(&descriptor);
 
     uint32_t myData = 2934875;
     void* mappedData = MapWriteAsyncAndWait(buffer, 2048, 4);
@@ -175,10 +175,10 @@
         myData.push_back(i);
     }
 
-    dawn::Buffer buffer = device.CreateBufferBuilder()
-        .SetSize(static_cast<uint32_t>(kDataSize * sizeof(uint32_t)))
-        .SetAllowedUsage(dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc)
-        .GetResult();
+    dawn::BufferDescriptor descriptor;
+    descriptor.size = static_cast<uint32_t>(kDataSize * sizeof(uint32_t));
+    descriptor.usage = dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc;
+    dawn::Buffer buffer = device.CreateBuffer(&descriptor);
 
     void* mappedData = MapWriteAsyncAndWait(buffer, 0, kDataSize * sizeof(uint32_t));
     memcpy(mappedData, myData.data(), kDataSize * sizeof(uint32_t));
@@ -194,10 +194,10 @@
 
 // Test the simplest set sub data: setting one u8 at offset 0.
 TEST_P(BufferSetSubDataTests, SmallDataAtZero) {
-    dawn::Buffer buffer = device.CreateBufferBuilder()
-        .SetSize(1)
-        .SetAllowedUsage(dawn::BufferUsageBit::TransferSrc | dawn::BufferUsageBit::TransferDst)
-        .GetResult();
+    dawn::BufferDescriptor descriptor;
+    descriptor.size = 1;
+    descriptor.usage = dawn::BufferUsageBit::TransferSrc | dawn::BufferUsageBit::TransferDst;
+    dawn::Buffer buffer = device.CreateBuffer(&descriptor);
 
     uint8_t value = 171;
     buffer.SetSubData(0, sizeof(value), &value);
@@ -207,10 +207,10 @@
 
 // Test that SetSubData offset works.
 TEST_P(BufferSetSubDataTests, SmallDataAtOffset) {
-    dawn::Buffer buffer = device.CreateBufferBuilder()
-        .SetSize(4000)
-        .SetAllowedUsage(dawn::BufferUsageBit::TransferSrc | dawn::BufferUsageBit::TransferDst)
-        .GetResult();
+    dawn::BufferDescriptor descriptor;
+    descriptor.size = 4000;
+    descriptor.usage = dawn::BufferUsageBit::TransferSrc | dawn::BufferUsageBit::TransferDst;
+    dawn::Buffer buffer = device.CreateBuffer(&descriptor);
 
     constexpr uint32_t kOffset = 2000;
     uint8_t value = 231;
@@ -230,10 +230,10 @@
 
     constexpr uint32_t kSize = 4000 * 1000;
     constexpr uint32_t kElements = 1000 * 1000;
-    dawn::Buffer buffer = device.CreateBufferBuilder()
-        .SetSize(kSize)
-        .SetAllowedUsage(dawn::BufferUsageBit::TransferSrc | dawn::BufferUsageBit::TransferDst)
-        .GetResult();
+    dawn::BufferDescriptor descriptor;
+    descriptor.size = kSize;
+    descriptor.usage = dawn::BufferUsageBit::TransferSrc | dawn::BufferUsageBit::TransferDst;
+    dawn::Buffer buffer = device.CreateBuffer(&descriptor);
 
     std::vector<uint32_t> expectedData;
     for (uint32_t i = 0; i < kElements; ++i) {
@@ -248,10 +248,10 @@
 TEST_P(BufferSetSubDataTests, LargeSetSubData) {
     constexpr uint32_t kSize = 4000 * 1000;
     constexpr uint32_t kElements = 1000 * 1000;
-    dawn::Buffer buffer = device.CreateBufferBuilder()
-        .SetSize(kSize)
-        .SetAllowedUsage(dawn::BufferUsageBit::TransferSrc | dawn::BufferUsageBit::TransferDst)
-        .GetResult();
+    dawn::BufferDescriptor descriptor;
+    descriptor.size = kSize;
+    descriptor.usage = dawn::BufferUsageBit::TransferSrc | dawn::BufferUsageBit::TransferDst;
+    dawn::Buffer buffer = device.CreateBuffer(&descriptor);
 
     std::vector<uint32_t> expectedData;
     for (uint32_t i = 0; i < kElements; ++i) {
diff --git a/src/tests/end2end/ComputeCopyStorageBufferTests.cpp b/src/tests/end2end/ComputeCopyStorageBufferTests.cpp
index 84936b5..8bf51be 100644
--- a/src/tests/end2end/ComputeCopyStorageBufferTests.cpp
+++ b/src/tests/end2end/ComputeCopyStorageBufferTests.cpp
@@ -43,12 +43,12 @@
                         .GetResult();
 
     // Set up src storage buffer
-    auto src =
-        device.CreateBufferBuilder()
-            .SetSize(kNumUints * sizeof(uint32_t))
-            .SetAllowedUsage(dawn::BufferUsageBit::Storage | dawn::BufferUsageBit::TransferSrc |
-                             dawn::BufferUsageBit::TransferDst)
-            .GetResult();
+    dawn::BufferDescriptor srcDesc;
+    srcDesc.size = kNumUints * sizeof(uint32_t);
+    srcDesc.usage = dawn::BufferUsageBit::Storage | dawn::BufferUsageBit::TransferSrc |
+                    dawn::BufferUsageBit::TransferDst;
+    dawn::Buffer src = device.CreateBuffer(&srcDesc);
+
     std::array<uint32_t, kNumUints> expected;
     for (uint32_t i = 0; i < kNumUints; ++i) {
         expected[i] = (i + 1u) * 0x11111111u;
@@ -59,12 +59,12 @@
         src.CreateBufferViewBuilder().SetExtent(0, kNumUints * sizeof(uint32_t)).GetResult();
 
     // Set up dst storage buffer
-    auto dst =
-        device.CreateBufferBuilder()
-            .SetSize(kNumUints * sizeof(uint32_t))
-            .SetAllowedUsage(dawn::BufferUsageBit::Storage | dawn::BufferUsageBit::TransferSrc |
-                             dawn::BufferUsageBit::TransferDst)
-            .GetResult();
+    dawn::BufferDescriptor dstDesc;
+    dstDesc.size = kNumUints * sizeof(uint32_t);
+    dstDesc.usage = dawn::BufferUsageBit::Storage | dawn::BufferUsageBit::TransferSrc |
+                    dawn::BufferUsageBit::TransferDst;
+    dawn::Buffer dst = device.CreateBuffer(&dstDesc);
+
     std::array<uint32_t, kNumUints> zero{};
     dst.SetSubData(0, sizeof(zero), reinterpret_cast<const uint8_t*>(zero.data()));
     auto dstView =
diff --git a/src/tests/end2end/CopyTests.cpp b/src/tests/end2end/CopyTests.cpp
index 164f35a..3be0220 100644
--- a/src/tests/end2end/CopyTests.cpp
+++ b/src/tests/end2end/CopyTests.cpp
@@ -100,10 +100,11 @@
             // Create a buffer of size `size` and populate it with empty data (0,0,0,0)
             // Note: Prepopulating the buffer with empty data ensures that there is not random data in the expectation
             // and helps ensure that the padding due to the row pitch is not modified by the copy
-            dawn::Buffer buffer = device.CreateBufferBuilder()
-                .SetSize(bufferSpec.size)
-                .SetAllowedUsage(dawn::BufferUsageBit::TransferSrc | dawn::BufferUsageBit::TransferDst)
-                .GetResult();
+            dawn::BufferDescriptor bufDescriptor;
+            bufDescriptor.size = bufferSpec.size;
+            bufDescriptor.usage = dawn::BufferUsageBit::TransferSrc | dawn::BufferUsageBit::TransferDst;
+            dawn::Buffer buffer = device.CreateBuffer(&bufDescriptor);
+
             std::vector<RGBA8> emptyData(bufferSpec.size / kBytesPerTexel);
             buffer.SetSubData(0, static_cast<uint32_t>(emptyData.size() * sizeof(RGBA8)), reinterpret_cast<const uint8_t*>(emptyData.data()));
 
@@ -147,10 +148,11 @@
 
     void DoTest(const TextureSpec& textureSpec, const BufferSpec& bufferSpec) {
         // Create a buffer of size `size` and populate it with data
-        dawn::Buffer buffer = device.CreateBufferBuilder()
-            .SetSize(bufferSpec.size)
-            .SetAllowedUsage(dawn::BufferUsageBit::TransferSrc | dawn::BufferUsageBit::TransferDst)
-            .GetResult();
+        dawn::BufferDescriptor bufDescriptor;
+        bufDescriptor.size = bufferSpec.size;
+        bufDescriptor.usage = dawn::BufferUsageBit::TransferSrc | dawn::BufferUsageBit::TransferDst;
+        dawn::Buffer buffer = device.CreateBuffer(&bufDescriptor);
+
         std::vector<RGBA8> bufferData(bufferSpec.size / kBytesPerTexel);
         FillBufferData(bufferData.data(), bufferData.size());
         buffer.SetSubData(0, static_cast<uint32_t>(bufferData.size() * sizeof(RGBA8)), reinterpret_cast<const uint8_t*>(bufferData.data()));
diff --git a/src/tests/end2end/PushConstantTests.cpp b/src/tests/end2end/PushConstantTests.cpp
index f6343ad..baac0be 100644
--- a/src/tests/end2end/PushConstantTests.cpp
+++ b/src/tests/end2end/PushConstantTests.cpp
@@ -30,17 +30,14 @@
             dawn::Buffer resultBuffer;
         };
         TestBindings MakeTestBindings(bool extraBuffer) {
-            dawn::Buffer buf1 = device.CreateBufferBuilder()
-                .SetSize(4)
-                .SetAllowedUsage(dawn::BufferUsageBit::Storage | dawn::BufferUsageBit::TransferSrc | dawn::BufferUsageBit::TransferDst)
-                .GetResult();
             uint32_t one = 1;
-            buf1.SetSubData(0, sizeof(one), reinterpret_cast<uint8_t*>(&one));
-
-            dawn::Buffer buf2 = device.CreateBufferBuilder()
-                .SetSize(4)
-                .SetAllowedUsage(dawn::BufferUsageBit::Storage)
-                .GetResult();
+            dawn::Buffer buf1 = utils::CreateBufferFromData(device, &one, 4, dawn::BufferUsageBit::Storage |
+                                                                             dawn::BufferUsageBit::TransferSrc |
+                                                                             dawn::BufferUsageBit::TransferDst);
+            dawn::BufferDescriptor buf2Desc;
+            buf2Desc.size = 4;
+            buf2Desc.usage = dawn::BufferUsageBit::Storage;
+            dawn::Buffer buf2 = device.CreateBuffer(&buf2Desc);
 
             dawn::ShaderStageBit kAllStages = dawn::ShaderStageBit::Compute | dawn::ShaderStageBit::Fragment | dawn::ShaderStageBit::Vertex;
             constexpr dawn::ShaderStageBit kNoStages{};
diff --git a/src/tests/unittests/WireTests.cpp b/src/tests/unittests/WireTests.cpp
index d65292d..1361fb9 100644
--- a/src/tests/unittests/WireTests.cpp
+++ b/src/tests/unittests/WireTests.cpp
@@ -476,7 +476,7 @@
     dawnCommandBufferBuilder cmdBufBuilder = dawnDeviceCreateCommandBufferBuilder(device);
     dawnCommandBufferBuilderSetErrorCallback(cmdBufBuilder, ToMockBuilderErrorCallback, 1, 2);
 
-    dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilder(device);
+    dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilderForTesting(device);
     dawnBufferBuilderSetErrorCallback(bufferBuilder, ToMockBuilderErrorCallback, 3, 4);
     dawnBuffer buffer = dawnBufferBuilderGetResult(bufferBuilder); // Hey look an error!
 
@@ -490,7 +490,7 @@
         .WillOnce(Return(apiCmdBufBuilder));
 
     dawnBufferBuilder apiBufferBuilder = api.GetNewBufferBuilder();
-    EXPECT_CALL(api, DeviceCreateBufferBuilder(apiDevice))
+    EXPECT_CALL(api, DeviceCreateBufferBuilderForTesting(apiDevice))
         .WillOnce(Return(apiBufferBuilder));
 
     // Hey look an error!
@@ -514,12 +514,12 @@
 
 // Test that we get a success builder error status when no error happens
 TEST_F(WireTests, SuccessCallbackOnBuilderSuccess) {
-    dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilder(device);
+    dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilderForTesting(device);
     dawnBufferBuilderSetErrorCallback(bufferBuilder, ToMockBuilderErrorCallback, 1, 2);
     dawnBufferBuilderGetResult(bufferBuilder);
 
     dawnBufferBuilder apiBufferBuilder = api.GetNewBufferBuilder();
-    EXPECT_CALL(api, DeviceCreateBufferBuilder(apiDevice))
+    EXPECT_CALL(api, DeviceCreateBufferBuilderForTesting(apiDevice))
         .WillOnce(Return(apiBufferBuilder));
 
     dawnBuffer apiBuffer = api.GetNewBuffer();
@@ -541,7 +541,7 @@
 TEST_F(WireTests, UnknownBuilderErrorStatusCallback) {
     // The builder is destroyed before the object is built
     {
-        dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilder(device);
+        dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilderForTesting(device);
         dawnBufferBuilderSetErrorCallback(bufferBuilder, ToMockBuilderErrorCallback, 1, 2);
 
         EXPECT_CALL(*mockBuilderErrorCallback, Call(DAWN_BUILDER_ERROR_STATUS_UNKNOWN, _ , 1 ,2)).Times(1);
@@ -551,7 +551,7 @@
 
     // If the builder has been consumed, it doesn't fire the callback with unknown
     {
-        dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilder(device);
+        dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilderForTesting(device);
         dawnBufferBuilderSetErrorCallback(bufferBuilder, ToMockBuilderErrorCallback, 3, 4);
         dawnBufferBuilderGetResult(bufferBuilder);
 
@@ -563,7 +563,7 @@
     // If the builder has been consumed, and the object is destroyed before the result comes from the server,
     // then the callback is fired with unknown
     {
-        dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilder(device);
+        dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilderForTesting(device);
         dawnBufferBuilderSetErrorCallback(bufferBuilder, ToMockBuilderErrorCallback, 5, 6);
         dawnBuffer buffer = dawnBufferBuilderGetResult(bufferBuilder);
 
@@ -577,11 +577,11 @@
 TEST_F(WireTests, SuccessCallbackNotForwardedToDevice) {
     dawnDeviceSetErrorCallback(device, ToMockDeviceErrorCallback, 0);
 
-    dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilder(device);
+    dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilderForTesting(device);
     dawnBufferBuilderGetResult(bufferBuilder);
 
     dawnBufferBuilder apiBufferBuilder = api.GetNewBufferBuilder();
-    EXPECT_CALL(api, DeviceCreateBufferBuilder(apiDevice))
+    EXPECT_CALL(api, DeviceCreateBufferBuilderForTesting(apiDevice))
         .WillOnce(Return(apiBufferBuilder));
 
     dawnBuffer apiBuffer = api.GetNewBuffer();
@@ -600,11 +600,11 @@
     uint64_t userdata = 30495;
     dawnDeviceSetErrorCallback(device, ToMockDeviceErrorCallback, userdata);
 
-    dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilder(device);
+    dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilderForTesting(device);
     dawnBufferBuilderGetResult(bufferBuilder);
 
     dawnBufferBuilder apiBufferBuilder = api.GetNewBufferBuilder();
-    EXPECT_CALL(api, DeviceCreateBufferBuilder(apiDevice))
+    EXPECT_CALL(api, DeviceCreateBufferBuilderForTesting(apiDevice))
         .WillOnce(Return(apiBufferBuilder));
 
     EXPECT_CALL(api, BufferBuilderGetResult(apiBufferBuilder))
@@ -649,10 +649,10 @@
     uint64_t userdata2 = 982734239028;
 
     // Create the buffer builder, the callback is set immediately on the server side
-    dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilder(device);
+    dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilderForTesting(device);
 
     dawnBufferBuilder apiBufferBuilder = api.GetNewBufferBuilder();
-    EXPECT_CALL(api, DeviceCreateBufferBuilder(apiDevice))
+    EXPECT_CALL(api, DeviceCreateBufferBuilderForTesting(apiDevice))
         .WillOnce(Return(apiBufferBuilder));
 
     EXPECT_CALL(api, OnBuilderSetErrorCallback(apiBufferBuilder, _, _, _))
@@ -692,28 +692,24 @@
             WireTestsBase::SetUp();
 
             {
-                dawnBufferBuilder apiBufferBuilder = api.GetNewBufferBuilder();
-                dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilder(device);
-                EXPECT_CALL(api, DeviceCreateBufferBuilder(apiDevice))
-                    .WillOnce(Return(apiBufferBuilder))
-                    .RetiresOnSaturation();
+                dawnBufferDescriptor descriptor;
+                descriptor.nextInChain = nullptr;
 
                 apiBuffer = api.GetNewBuffer();
-                buffer = dawnBufferBuilderGetResult(bufferBuilder);
-                EXPECT_CALL(api, BufferBuilderGetResult(apiBufferBuilder))
+                buffer = dawnDeviceCreateBuffer(device, &descriptor);
+
+                EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _))
                     .WillOnce(Return(apiBuffer))
                     .RetiresOnSaturation();
                 FlushClient();
             }
             {
-                dawnBufferBuilder apiBufferBuilder = api.GetNewBufferBuilder();
-                dawnBufferBuilder bufferBuilder = dawnDeviceCreateBufferBuilder(device);
-                EXPECT_CALL(api, DeviceCreateBufferBuilder(apiDevice))
-                    .WillOnce(Return(apiBufferBuilder))
-                    .RetiresOnSaturation();
+                dawnBufferDescriptor descriptor;
+                descriptor.nextInChain = nullptr;
 
-                errorBuffer = dawnBufferBuilderGetResult(bufferBuilder);
-                EXPECT_CALL(api, BufferBuilderGetResult(apiBufferBuilder))
+                errorBuffer = dawnDeviceCreateBuffer(device, &descriptor);
+
+                EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _))
                     .WillOnce(Return(nullptr))
                     .RetiresOnSaturation();
                 FlushClient();
diff --git a/src/tests/unittests/validation/BindGroupValidationTests.cpp b/src/tests/unittests/validation/BindGroupValidationTests.cpp
index cec08dc..931b64d 100644
--- a/src/tests/unittests/validation/BindGroupValidationTests.cpp
+++ b/src/tests/unittests/validation/BindGroupValidationTests.cpp
@@ -24,10 +24,13 @@
                     {0, dawn::ShaderStageBit::Vertex, dawn::BindingType::UniformBuffer},
                 });
 
-    auto buffer = device.CreateBufferBuilder()
-        .SetAllowedUsage(dawn::BufferUsageBit::Uniform)
-        .SetSize(512)
-        .GetResult();
+    dawn::Buffer buffer;
+    {
+        dawn::BufferDescriptor descriptor;
+        descriptor.size = 512;
+        descriptor.usage = dawn::BufferUsageBit::Uniform;
+        buffer = device.CreateBuffer(&descriptor);
+    }
 
     // Check that offset 0 is valid
     {
diff --git a/src/tests/unittests/validation/BufferValidationTests.cpp b/src/tests/unittests/validation/BufferValidationTests.cpp
index 0bb7579..91c1951 100644
--- a/src/tests/unittests/validation/BufferValidationTests.cpp
+++ b/src/tests/unittests/validation/BufferValidationTests.cpp
@@ -43,22 +43,25 @@
 class BufferValidationTest : public ValidationTest {
     protected:
         dawn::Buffer CreateMapReadBuffer(uint32_t size) {
-            return device.CreateBufferBuilder()
-                .SetSize(size)
-                .SetAllowedUsage(dawn::BufferUsageBit::MapRead)
-                .GetResult();
+            dawn::BufferDescriptor descriptor;
+            descriptor.size = size;
+            descriptor.usage = dawn::BufferUsageBit::MapRead;
+
+            return device.CreateBuffer(&descriptor);
         }
         dawn::Buffer CreateMapWriteBuffer(uint32_t size) {
-            return device.CreateBufferBuilder()
-                .SetSize(size)
-                .SetAllowedUsage(dawn::BufferUsageBit::MapWrite)
-                .GetResult();
+            dawn::BufferDescriptor descriptor;
+            descriptor.size = size;
+            descriptor.usage = dawn::BufferUsageBit::MapWrite;
+
+            return device.CreateBuffer(&descriptor);
         }
         dawn::Buffer CreateSetSubDataBuffer(uint32_t size) {
-            return device.CreateBufferBuilder()
-                .SetSize(size)
-                .SetAllowedUsage(dawn::BufferUsageBit::TransferDst)
-                .GetResult();
+            dawn::BufferDescriptor descriptor;
+            descriptor.size = size;
+            descriptor.usage = dawn::BufferUsageBit::TransferDst;
+
+            return device.CreateBuffer(&descriptor);
         }
 
         dawn::Queue queue;
@@ -84,48 +87,11 @@
 TEST_F(BufferValidationTest, CreationSuccess) {
     // Success
     {
-        dawn::Buffer buf = AssertWillBeSuccess(device.CreateBufferBuilder())
-            .SetSize(4)
-            .SetAllowedUsage(dawn::BufferUsageBit::Uniform)
-            .GetResult();
-    }
-}
+        dawn::BufferDescriptor descriptor;
+        descriptor.size = 4;
+        descriptor.usage = dawn::BufferUsageBit::Uniform;
 
-// Test failure when specifying properties multiple times
-TEST_F(BufferValidationTest, CreationDuplicates) {
-    // When size is specified multiple times
-    {
-        dawn::Buffer buf = AssertWillBeError(device.CreateBufferBuilder())
-            .SetSize(4)
-            .SetSize(3)
-            .SetAllowedUsage(dawn::BufferUsageBit::Uniform)
-            .GetResult();
-    }
-
-    // When allowed usage is specified multiple times
-    {
-        dawn::Buffer buf = AssertWillBeError(device.CreateBufferBuilder())
-            .SetSize(4)
-            .SetAllowedUsage(dawn::BufferUsageBit::Vertex)
-            .SetAllowedUsage(dawn::BufferUsageBit::Uniform)
-            .GetResult();
-    }
-}
-
-// Test failure when required properties are missing
-TEST_F(BufferValidationTest, CreationMissingProperties) {
-    // When allowed usage is missing
-    {
-        dawn::Buffer buf = AssertWillBeError(device.CreateBufferBuilder())
-            .SetSize(4)
-            .GetResult();
-    }
-
-    // When size is missing
-    {
-        dawn::Buffer buf = AssertWillBeError(device.CreateBufferBuilder())
-            .SetAllowedUsage(dawn::BufferUsageBit::Vertex)
-            .GetResult();
+        device.CreateBuffer(&descriptor);
     }
 }
 
@@ -133,34 +99,38 @@
 TEST_F(BufferValidationTest, CreationMapUsageRestrictions) {
     // MapRead with TransferDst is ok
     {
-        dawn::Buffer buf = AssertWillBeSuccess(device.CreateBufferBuilder(), "1")
-            .SetAllowedUsage(dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::TransferDst)
-            .SetSize(4)
-            .GetResult();
+        dawn::BufferDescriptor descriptor;
+        descriptor.size = 4;
+        descriptor.usage = dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::TransferDst;
+
+        device.CreateBuffer(&descriptor);
     }
 
     // MapRead with something else is an error
     {
-        dawn::Buffer buf = AssertWillBeError(device.CreateBufferBuilder(), "2")
-            .SetAllowedUsage(dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::Uniform)
-            .SetSize(4)
-            .GetResult();
+        dawn::BufferDescriptor descriptor;
+        descriptor.size = 4;
+        descriptor.usage = dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::Uniform;
+
+        ASSERT_DEVICE_ERROR(device.CreateBuffer(&descriptor));
     }
 
     // MapWrite with TransferSrc is ok
     {
-        dawn::Buffer buf = AssertWillBeSuccess(device.CreateBufferBuilder(), "3")
-            .SetAllowedUsage(dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc)
-            .SetSize(4)
-            .GetResult();
+        dawn::BufferDescriptor descriptor;
+        descriptor.size = 4;
+        descriptor.usage = dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferSrc;
+
+        device.CreateBuffer(&descriptor);
     }
 
     // MapWrite with something else is an error
     {
-        dawn::Buffer buf = AssertWillBeError(device.CreateBufferBuilder(), "4")
-            .SetAllowedUsage(dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::Uniform)
-            .SetSize(4)
-            .GetResult();
+        dawn::BufferDescriptor descriptor;
+        descriptor.size = 4;
+        descriptor.usage = dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::Uniform;
+
+        ASSERT_DEVICE_ERROR(device.CreateBuffer(&descriptor));
     }
 }
 
@@ -216,10 +186,11 @@
 
 // Test map reading a buffer with wrong current usage
 TEST_F(BufferValidationTest, MapReadWrongUsage) {
-    dawn::Buffer buf = device.CreateBufferBuilder()
-        .SetSize(4)
-        .SetAllowedUsage(dawn::BufferUsageBit::TransferDst)
-        .GetResult();
+    dawn::BufferDescriptor descriptor;
+    descriptor.size = 4;
+    descriptor.usage = dawn::BufferUsageBit::TransferDst;
+
+    dawn::Buffer buf = device.CreateBuffer(&descriptor);
 
     dawn::CallbackUserdata userdata = 40600;
     EXPECT_CALL(*mockBufferMapReadCallback, Call(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, userdata))
@@ -230,10 +201,11 @@
 
 // Test map writing a buffer with wrong current usage
 TEST_F(BufferValidationTest, MapWriteWrongUsage) {
-    dawn::Buffer buf = device.CreateBufferBuilder()
-        .SetSize(4)
-        .SetAllowedUsage(dawn::BufferUsageBit::TransferSrc)
-        .GetResult();
+    dawn::BufferDescriptor descriptor;
+    descriptor.size = 4;
+    descriptor.usage = dawn::BufferUsageBit::TransferSrc;
+
+    dawn::Buffer buf = device.CreateBuffer(&descriptor);
 
     dawn::CallbackUserdata userdata = 40600;
     EXPECT_CALL(*mockBufferMapWriteCallback, Call(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, userdata))
@@ -468,10 +440,11 @@
 
 // Test error case for SetSubData with the wrong usage
 TEST_F(BufferValidationTest, SetSubDataWrongUsage) {
-    dawn::Buffer buf = device.CreateBufferBuilder()
-        .SetSize(1)
-        .SetAllowedUsage(dawn::BufferUsageBit::Vertex)
-        .GetResult();
+    dawn::BufferDescriptor descriptor;
+    descriptor.size = 4;
+    descriptor.usage = dawn::BufferUsageBit::Vertex;
+
+    dawn::Buffer buf = device.CreateBuffer(&descriptor);
 
     uint8_t foo = 0;
     ASSERT_DEVICE_ERROR(buf.SetSubData(0, sizeof(foo), &foo));
diff --git a/src/tests/unittests/validation/CopyCommandsValidationTests.cpp b/src/tests/unittests/validation/CopyCommandsValidationTests.cpp
index 8ae1d46..c351f9d 100644
--- a/src/tests/unittests/validation/CopyCommandsValidationTests.cpp
+++ b/src/tests/unittests/validation/CopyCommandsValidationTests.cpp
@@ -18,12 +18,12 @@
 
 class CopyCommandTest : public ValidationTest {
     protected:
-        dawn::Buffer CreateFrozenBuffer(uint32_t size, dawn::BufferUsageBit usage) {
-            dawn::Buffer buf = AssertWillBeSuccess(device.CreateBufferBuilder())
-                .SetSize(size)
-                .SetAllowedUsage(usage)
-                .GetResult();
-            return buf;
+        dawn::Buffer CreateBuffer(uint32_t size, dawn::BufferUsageBit usage) {
+            dawn::BufferDescriptor descriptor;
+            descriptor.size = size;
+            descriptor.usage = usage;
+
+            return device.CreateBuffer(&descriptor);
         }
 
         dawn::Texture Create2DTexture(uint32_t width, uint32_t height, uint32_t levels,
@@ -51,8 +51,8 @@
 
 // Test a successfull B2B copy
 TEST_F(CopyCommandTest_B2B, Success) {
-    dawn::Buffer source = CreateFrozenBuffer(16, dawn::BufferUsageBit::TransferSrc);
-    dawn::Buffer destination = CreateFrozenBuffer(16, dawn::BufferUsageBit::TransferDst);
+    dawn::Buffer source = CreateBuffer(16, dawn::BufferUsageBit::TransferSrc);
+    dawn::Buffer destination = CreateBuffer(16, dawn::BufferUsageBit::TransferDst);
 
     // Copy different copies, including some that touch the OOB condition
     {
@@ -75,8 +75,8 @@
 
 // Test B2B copies with OOB
 TEST_F(CopyCommandTest_B2B, OutOfBounds) {
-    dawn::Buffer source = CreateFrozenBuffer(16, dawn::BufferUsageBit::TransferSrc);
-    dawn::Buffer destination = CreateFrozenBuffer(16, dawn::BufferUsageBit::TransferDst);
+    dawn::Buffer source = CreateBuffer(16, dawn::BufferUsageBit::TransferSrc);
+    dawn::Buffer destination = CreateBuffer(16, dawn::BufferUsageBit::TransferDst);
 
     // OOB on the source
     {
@@ -95,9 +95,9 @@
 
 // Test B2B copies with incorrect buffer usage
 TEST_F(CopyCommandTest_B2B, BadUsage) {
-    dawn::Buffer source = CreateFrozenBuffer(16, dawn::BufferUsageBit::TransferSrc);
-    dawn::Buffer destination = CreateFrozenBuffer(16, dawn::BufferUsageBit::TransferDst);
-    dawn::Buffer vertex = CreateFrozenBuffer(16, dawn::BufferUsageBit::Vertex);
+    dawn::Buffer source = CreateBuffer(16, dawn::BufferUsageBit::TransferSrc);
+    dawn::Buffer destination = CreateBuffer(16, dawn::BufferUsageBit::TransferDst);
+    dawn::Buffer vertex = CreateBuffer(16, dawn::BufferUsageBit::Vertex);
 
     // Source with incorrect usage
     {
@@ -120,7 +120,7 @@
 // Test a successfull B2T copy
 TEST_F(CopyCommandTest_B2T, Success) {
     uint32_t bufferSize = BufferSizeForTextureCopy(4, 4, 1);
-    dawn::Buffer source = CreateFrozenBuffer(bufferSize, dawn::BufferUsageBit::TransferSrc);
+    dawn::Buffer source = CreateBuffer(bufferSize, dawn::BufferUsageBit::TransferSrc);
     dawn::Texture destination = Create2DTexture(16, 16, 5, dawn::TextureFormat::R8G8B8A8Unorm,
                                                      dawn::TextureUsageBit::TransferDst);
 
@@ -166,7 +166,7 @@
 // Test OOB conditions on the buffer
 TEST_F(CopyCommandTest_B2T, OutOfBoundsOnBuffer) {
     uint32_t bufferSize = BufferSizeForTextureCopy(4, 4, 1);
-    dawn::Buffer source = CreateFrozenBuffer(bufferSize, dawn::BufferUsageBit::TransferSrc);
+    dawn::Buffer source = CreateBuffer(bufferSize, dawn::BufferUsageBit::TransferSrc);
     dawn::Texture destination = Create2DTexture(16, 16, 5, dawn::TextureFormat::R8G8B8A8Unorm,
                                                      dawn::TextureUsageBit::TransferDst);
 
@@ -196,7 +196,7 @@
     {
         uint32_t sourceBufferSize = BufferSizeForTextureCopy(7, 3, 1);
         ASSERT_TRUE(256 * 3 > sourceBufferSize) << "row pitch * height should overflow buffer";
-        dawn::Buffer sourceBuffer = CreateFrozenBuffer(sourceBufferSize, dawn::BufferUsageBit::TransferSrc);
+        dawn::Buffer sourceBuffer = CreateBuffer(sourceBufferSize, dawn::BufferUsageBit::TransferSrc);
         dawn::CommandBuffer commands = AssertWillBeSuccess(device.CreateCommandBufferBuilder())
             .CopyBufferToTexture(sourceBuffer, 0, 256, destination, 0, 0, 0, 7, 3, 1, 0)
             .GetResult();
@@ -206,7 +206,7 @@
 // Test OOB conditions on the texture
 TEST_F(CopyCommandTest_B2T, OutOfBoundsOnTexture) {
     uint32_t bufferSize = BufferSizeForTextureCopy(4, 4, 1);
-    dawn::Buffer source = CreateFrozenBuffer(bufferSize, dawn::BufferUsageBit::TransferSrc);
+    dawn::Buffer source = CreateBuffer(bufferSize, dawn::BufferUsageBit::TransferSrc);
     dawn::Texture destination = Create2DTexture(16, 16, 5, dawn::TextureFormat::R8G8B8A8Unorm,
                                                      dawn::TextureUsageBit::TransferDst);
 
@@ -241,7 +241,7 @@
 
 // Test that we force Z=0 and Depth=1 on copies to 2D textures
 TEST_F(CopyCommandTest_B2T, ZDepthConstraintFor2DTextures) {
-    dawn::Buffer source = CreateFrozenBuffer(16 * 4, dawn::BufferUsageBit::TransferSrc);
+    dawn::Buffer source = CreateBuffer(16 * 4, dawn::BufferUsageBit::TransferSrc);
     dawn::Texture destination = Create2DTexture(16, 16, 5, dawn::TextureFormat::R8G8B8A8Unorm,
                                                      dawn::TextureUsageBit::TransferDst);
 
@@ -262,8 +262,8 @@
 
 // Test B2T copies with incorrect buffer usage
 TEST_F(CopyCommandTest_B2T, IncorrectUsage) {
-    dawn::Buffer source = CreateFrozenBuffer(16 * 4, dawn::BufferUsageBit::TransferSrc);
-    dawn::Buffer vertex = CreateFrozenBuffer(16 * 4, dawn::BufferUsageBit::Vertex);
+    dawn::Buffer source = CreateBuffer(16 * 4, dawn::BufferUsageBit::TransferSrc);
+    dawn::Buffer vertex = CreateBuffer(16 * 4, dawn::BufferUsageBit::Vertex);
     dawn::Texture destination = Create2DTexture(16, 16, 5, dawn::TextureFormat::R8G8B8A8Unorm,
                                                      dawn::TextureUsageBit::TransferDst);
     dawn::Texture sampled = Create2DTexture(16, 16, 5, dawn::TextureFormat::R8G8B8A8Unorm,
@@ -286,7 +286,7 @@
 
 TEST_F(CopyCommandTest_B2T, IncorrectRowPitch) {
     uint32_t bufferSize = BufferSizeForTextureCopy(128, 16, 1);
-    dawn::Buffer source = CreateFrozenBuffer(bufferSize, dawn::BufferUsageBit::TransferSrc);
+    dawn::Buffer source = CreateBuffer(bufferSize, dawn::BufferUsageBit::TransferSrc);
     dawn::Texture destination = Create2DTexture(128, 16, 5, dawn::TextureFormat::R8G8B8A8Unorm,
         dawn::TextureUsageBit::TransferDst);
 
@@ -315,7 +315,7 @@
 // Test B2T copies with incorrect buffer offset usage
 TEST_F(CopyCommandTest_B2T, IncorrectBufferOffset) {
     uint32_t bufferSize = BufferSizeForTextureCopy(4, 4, 1);
-    dawn::Buffer source = CreateFrozenBuffer(bufferSize, dawn::BufferUsageBit::TransferSrc);
+    dawn::Buffer source = CreateBuffer(bufferSize, dawn::BufferUsageBit::TransferSrc);
     dawn::Texture destination = Create2DTexture(16, 16, 5, dawn::TextureFormat::R8G8B8A8Unorm,
                                                      dawn::TextureUsageBit::TransferDst);
 
@@ -351,7 +351,7 @@
     uint32_t bufferSize = BufferSizeForTextureCopy(4, 4, 1);
     dawn::Texture source = Create2DTexture(16, 16, 5, dawn::TextureFormat::R8G8B8A8Unorm,
                                                 dawn::TextureUsageBit::TransferSrc);
-    dawn::Buffer destination = CreateFrozenBuffer(bufferSize, dawn::BufferUsageBit::TransferDst);
+    dawn::Buffer destination = CreateBuffer(bufferSize, dawn::BufferUsageBit::TransferDst);
 
     // Different copies, including some that touch the OOB condition
     {
@@ -397,7 +397,7 @@
     uint32_t bufferSize = BufferSizeForTextureCopy(4, 4, 1);
     dawn::Texture source = Create2DTexture(16, 16, 5, dawn::TextureFormat::R8G8B8A8Unorm,
                                                 dawn::TextureUsageBit::TransferSrc);
-    dawn::Buffer destination = CreateFrozenBuffer(bufferSize, dawn::BufferUsageBit::TransferDst);
+    dawn::Buffer destination = CreateBuffer(bufferSize, dawn::BufferUsageBit::TransferDst);
 
     // OOB on the texture because x + width overflows
     {
@@ -433,7 +433,7 @@
     uint32_t bufferSize = BufferSizeForTextureCopy(4, 4, 1);
     dawn::Texture source = Create2DTexture(16, 16, 5, dawn::TextureFormat::R8G8B8A8Unorm,
                                                 dawn::TextureUsageBit::TransferSrc);
-    dawn::Buffer destination = CreateFrozenBuffer(bufferSize, dawn::BufferUsageBit::TransferDst);
+    dawn::Buffer destination = CreateBuffer(bufferSize, dawn::BufferUsageBit::TransferDst);
 
     // OOB on the buffer because we copy too many pixels
     {
@@ -461,7 +461,7 @@
     {
         uint32_t destinationBufferSize = BufferSizeForTextureCopy(7, 3, 1);
         ASSERT_TRUE(256 * 3 > destinationBufferSize) << "row pitch * height should overflow buffer";
-        dawn::Buffer destinationBuffer = CreateFrozenBuffer(destinationBufferSize, dawn::BufferUsageBit::TransferDst);
+        dawn::Buffer destinationBuffer = CreateBuffer(destinationBufferSize, dawn::BufferUsageBit::TransferDst);
         dawn::CommandBuffer commands = AssertWillBeSuccess(device.CreateCommandBufferBuilder())
             .CopyTextureToBuffer(source, 0, 0, 0, 7, 3, 1, 0, destinationBuffer, 0, 256)
             .GetResult();
@@ -473,7 +473,7 @@
     uint32_t bufferSize = BufferSizeForTextureCopy(4, 4, 1);
     dawn::Texture source = Create2DTexture(16, 16, 5, dawn::TextureFormat::R8G8B8A8Unorm,
                                                 dawn::TextureUsageBit::TransferSrc);
-    dawn::Buffer destination = CreateFrozenBuffer(bufferSize, dawn::BufferUsageBit::TransferDst);
+    dawn::Buffer destination = CreateBuffer(bufferSize, dawn::BufferUsageBit::TransferDst);
 
     // Z=1 on an empty copy still errors
     {
@@ -497,8 +497,8 @@
                                                 dawn::TextureUsageBit::TransferSrc);
     dawn::Texture sampled = Create2DTexture(16, 16, 5, dawn::TextureFormat::R8G8B8A8Unorm,
                                                  dawn::TextureUsageBit::Sampled);
-    dawn::Buffer destination = CreateFrozenBuffer(bufferSize, dawn::BufferUsageBit::TransferDst);
-    dawn::Buffer vertex = CreateFrozenBuffer(bufferSize, dawn::BufferUsageBit::Vertex);
+    dawn::Buffer destination = CreateBuffer(bufferSize, dawn::BufferUsageBit::TransferDst);
+    dawn::Buffer vertex = CreateBuffer(bufferSize, dawn::BufferUsageBit::Vertex);
 
     // Incorrect source usage
     {
@@ -519,7 +519,7 @@
     uint32_t bufferSize = BufferSizeForTextureCopy(128, 16, 1);
     dawn::Texture source = Create2DTexture(128, 16, 5, dawn::TextureFormat::R8G8B8A8Unorm,
         dawn::TextureUsageBit::TransferDst);
-    dawn::Buffer destination = CreateFrozenBuffer(bufferSize, dawn::BufferUsageBit::TransferSrc);
+    dawn::Buffer destination = CreateBuffer(bufferSize, dawn::BufferUsageBit::TransferSrc);
 
     // Default row pitch is not 256-byte aligned
     {
@@ -548,7 +548,7 @@
     uint32_t bufferSize = BufferSizeForTextureCopy(128, 16, 1);
     dawn::Texture source = Create2DTexture(128, 16, 5, dawn::TextureFormat::R8G8B8A8Unorm,
         dawn::TextureUsageBit::TransferSrc);
-    dawn::Buffer destination = CreateFrozenBuffer(bufferSize, dawn::BufferUsageBit::TransferDst);
+    dawn::Buffer destination = CreateBuffer(bufferSize, dawn::BufferUsageBit::TransferDst);
 
     // Correct usage
     {
diff --git a/src/tests/unittests/validation/VertexBufferValidationTests.cpp b/src/tests/unittests/validation/VertexBufferValidationTests.cpp
index 733f893..b3d97c6 100644
--- a/src/tests/unittests/validation/VertexBufferValidationTests.cpp
+++ b/src/tests/unittests/validation/VertexBufferValidationTests.cpp
@@ -37,10 +37,11 @@
         std::array<dawn::Buffer, N> MakeVertexBuffers() {
             std::array<dawn::Buffer, N> buffers;
             for (auto& buffer : buffers) {
-                buffer = device.CreateBufferBuilder()
-                    .SetSize(256)
-                    .SetAllowedUsage(dawn::BufferUsageBit::Vertex)
-                    .GetResult();
+                dawn::BufferDescriptor descriptor;
+                descriptor.size = 256;
+                descriptor.usage = dawn::BufferUsageBit::Vertex;
+
+                buffer = device.CreateBuffer(&descriptor);
             }
             return buffers;
         }
diff --git a/src/utils/DawnHelpers.cpp b/src/utils/DawnHelpers.cpp
index 65adb97..f2d89f0 100644
--- a/src/utils/DawnHelpers.cpp
+++ b/src/utils/DawnHelpers.cpp
@@ -98,10 +98,11 @@
                                       const void* data,
                                       uint32_t size,
                                       dawn::BufferUsageBit usage) {
-        dawn::Buffer buffer = device.CreateBufferBuilder()
-                                  .SetAllowedUsage(dawn::BufferUsageBit::TransferDst | usage)
-                                  .SetSize(size)
-                                  .GetResult();
+        dawn::BufferDescriptor descriptor;
+        descriptor.size = size;
+        descriptor.usage = usage | dawn::BufferUsageBit::TransferDst;
+
+        dawn::Buffer buffer = device.CreateBuffer(&descriptor);
         buffer.SetSubData(0, size, reinterpret_cast<const uint8_t*>(data));
         return buffer;
     }