WebGPU error handling 2: CommandEncoder for samples and end2end tests

CommandEncoder is the replacement for CommandBufferBuilder. This commit
adds the dawn.json definition for it and an initial implementation that
wraps CommandBufferBuilder. This is done so that the code can be ported
to CommandEncoder gradually, otherwise the commit would be too big and
would risk many merge conflicts.

This converts all samples and end2end tests to use CommandEncoder.

BUG=dawn:8

Change-Id: If4ce86e6fb39ba4e0c2af6328d40e63be17d18c1
Reviewed-on: https://dawn-review.googlesource.com/c/4741
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index 77cdae1..d36d2a5 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -443,6 +443,8 @@
     "src/dawn_native/CommandBuffer.h",
     "src/dawn_native/CommandBufferStateTracker.cpp",
     "src/dawn_native/CommandBufferStateTracker.h",
+    "src/dawn_native/CommandEncoder.cpp",
+    "src/dawn_native/CommandEncoder.h",
     "src/dawn_native/Commands.cpp",
     "src/dawn_native/Commands.h",
     "src/dawn_native/ComputePassEncoder.cpp",
diff --git a/dawn.json b/dawn.json
index 68b5ae2..7f48ac5 100644
--- a/dawn.json
+++ b/dawn.json
@@ -320,6 +320,55 @@
             }
         ]
     },
+    "command encoder": {
+        "category": "object",
+        "methods": [
+            {
+                "name": "finish",
+                "returns": "command buffer"
+            },
+            {
+                "name": "begin compute pass",
+                "returns": "compute pass encoder"
+            },
+            {
+                "name": "begin render pass",
+                "args": [
+                    {"name": "info", "type": "render pass descriptor"}
+                ],
+                "returns": "render pass encoder"
+            },
+            {
+                "name": "copy buffer to buffer",
+                "args": [
+                    {"name": "source", "type": "buffer"},
+                    {"name": "source offset", "type": "uint32_t"},
+                    {"name": "destination", "type": "buffer"},
+                    {"name": "destination offset", "type": "uint32_t"},
+                    {"name": "size", "type": "uint32_t"}
+                ],
+                "TODO": [
+                    "Restrictions on the alignment of the copy? Cf Metal on OSX"
+                ]
+            },
+            {
+                "name": "copy buffer to texture",
+                "args": [
+                    {"name": "source", "type": "buffer copy view", "annotation": "const*"},
+                    {"name": "destination", "type": "texture copy view", "annotation": "const*"},
+                    {"name": "copy size", "type": "extent 3D", "annotation": "const*"}
+                ]
+            },
+            {
+                "name": "copy texture to buffer",
+                "args": [
+                    {"name": "source", "type": "texture copy view", "annotation": "const*"},
+                    {"name": "destination", "type": "buffer copy view", "annotation": "const*"},
+                    {"name": "copy size", "type": "extent 3D", "annotation": "const*"}
+                ]
+            }
+        ]
+    },
     "compare function": {
         "category": "enum",
         "values": [
@@ -421,6 +470,10 @@
                 "returns": "command buffer builder"
             },
             {
+                "name": "create command encoder",
+                "returns": "command encoder"
+            },
+            {
                 "name": "create fence",
                 "returns": "fence",
                 "args": [
diff --git a/examples/Animometer.cpp b/examples/Animometer.cpp
index 187c663..5d2e281 100644
--- a/examples/Animometer.cpp
+++ b/examples/Animometer.cpp
@@ -140,9 +140,9 @@
 
     size_t i = 0;
 
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass);
         pass.SetPipeline(pipeline);
 
         for (int k = 0; k < 10000; k++) {
@@ -155,7 +155,7 @@
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
     swapchain.Present(backbuffer);
     DoFlush();
diff --git a/examples/CHelloTriangle.cpp b/examples/CHelloTriangle.cpp
index 8f2a2e6..5dd38b7 100644
--- a/examples/CHelloTriangle.cpp
+++ b/examples/CHelloTriangle.cpp
@@ -131,16 +131,16 @@
     }
     dawnCommandBuffer commands;
     {
-        dawnCommandBufferBuilder builder = dawnDeviceCreateCommandBufferBuilder(device);
+        dawnCommandEncoder encoder = dawnDeviceCreateCommandEncoder(device);
 
-        dawnRenderPassEncoder pass = dawnCommandBufferBuilderBeginRenderPass(builder, renderpassInfo);
+        dawnRenderPassEncoder pass = dawnCommandEncoderBeginRenderPass(encoder, renderpassInfo);
         dawnRenderPassEncoderSetPipeline(pass, pipeline);
         dawnRenderPassEncoderDraw(pass, 3, 1, 0, 0);
         dawnRenderPassEncoderEndPass(pass);
         dawnRenderPassEncoderRelease(pass);
 
-        commands = dawnCommandBufferBuilderGetResult(builder);
-        dawnCommandBufferBuilderRelease(builder);
+        commands = dawnCommandEncoderFinish(encoder);
+        dawnCommandEncoderRelease(encoder);
     }
 
     dawnQueueSubmit(queue, 1, &commands);
diff --git a/examples/ComputeBoids.cpp b/examples/ComputeBoids.cpp
index 9776402..8e2dd0c 100644
--- a/examples/ComputeBoids.cpp
+++ b/examples/ComputeBoids.cpp
@@ -280,10 +280,10 @@
 dawn::CommandBuffer createCommandBuffer(const dawn::RenderPassDescriptor& renderPass, size_t i) {
     static const uint32_t zeroOffsets[1] = {0};
     auto& bufferDst = particleBuffers[(i + 1) % 2];
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
 
     {
-        dawn::ComputePassEncoder pass = builder.BeginComputePass();
+        dawn::ComputePassEncoder pass = encoder.BeginComputePass();
         pass.SetPipeline(updatePipeline);
         pass.SetBindGroup(0, updateBGs[i]);
         pass.Dispatch(kNumParticles, 1, 1);
@@ -291,7 +291,7 @@
     }
 
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass);
         pass.SetPipeline(renderPipeline);
         pass.SetVertexBuffers(0, 1, &bufferDst, zeroOffsets);
         pass.SetVertexBuffers(1, 1, &modelBuffer, zeroOffsets);
@@ -299,7 +299,7 @@
         pass.EndPass();
     }
 
-    return builder.GetResult();
+    return encoder.Finish();
 }
 
 void init() {
diff --git a/examples/CppHelloTriangle.cpp b/examples/CppHelloTriangle.cpp
index c1bd437..8f837d1 100644
--- a/examples/CppHelloTriangle.cpp
+++ b/examples/CppHelloTriangle.cpp
@@ -74,11 +74,11 @@
     dawn::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(stagingBuffer, 0, 0, 0);
     dawn::TextureCopyView textureCopyView = utils::CreateTextureCopyView(texture, 0, 0, {0, 0, 0});
     dawn::Extent3D copySize = {1024, 1024, 1};
-    dawn::CommandBuffer copy =
-        device.CreateCommandBufferBuilder()
-            .CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copySize)
-            .GetResult();
 
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
+    encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copySize);
+
+    dawn::CommandBuffer copy = encoder.Finish();
     queue.Submit(1, &copy);
 }
 
@@ -165,9 +165,9 @@
     GetNextRenderPassDescriptor(device, swapchain, depthStencilView, &backbuffer, &renderPass);
 
     static const uint32_t vertexBufferOffsets[1] = {0};
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass);
         pass.SetPipeline(pipeline);
         pass.SetBindGroup(0, bindGroup);
         pass.SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets);
@@ -176,7 +176,7 @@
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
     swapchain.Present(backbuffer);
     DoFlush();
diff --git a/examples/CubeReflection.cpp b/examples/CubeReflection.cpp
index b35cd3c..833c40b 100644
--- a/examples/CubeReflection.cpp
+++ b/examples/CubeReflection.cpp
@@ -276,9 +276,9 @@
     dawn::RenderPassDescriptor renderPass;
     GetNextRenderPassDescriptor(device, swapchain, depthStencilView, &backbuffer, &renderPass);
 
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass);
         pass.SetPipeline(pipeline);
         pass.SetBindGroup(0, bindGroup[0]);
         pass.SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets);
@@ -299,7 +299,7 @@
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
     swapchain.Present(backbuffer);
     DoFlush();
diff --git a/examples/glTFViewer/glTFViewer.cpp b/examples/glTFViewer/glTFViewer.cpp
index 2203a32..d0ec863 100644
--- a/examples/glTFViewer/glTFViewer.cpp
+++ b/examples/glTFViewer/glTFViewer.cpp
@@ -471,9 +471,11 @@
             dawn::TextureCopyView textureCopyView =
                 utils::CreateTextureCopyView(oTexture, 0, 0, {0, 0, 0});
             dawn::Extent3D copySize = {iImage.width, iImage.height, 1};
-            auto cmdbuf = device.CreateCommandBufferBuilder()
-                              .CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copySize)
-                              .GetResult();
+
+            dawn::CommandEncoder encoder = device.CreateCommandEncoder();
+            encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copySize);
+
+            dawn::CommandBuffer cmdbuf = encoder.Finish();
             queue.Submit(1, &cmdbuf);
 
             textures[iTextureID] = oTexture.CreateDefaultTextureView();
@@ -603,9 +605,9 @@
         GetNextRenderPassDescriptor(device, swapchain, depthStencilView, &backbuffer, &renderPass);
 
         const auto& defaultSceneNodes = scene.scenes.at(scene.defaultScene);
-        dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
         {
-            dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass);
+            dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass);
             for (const auto& n : defaultSceneNodes) {
                 const auto& node = scene.nodes.at(n);
                 drawNode(pass, node);
@@ -613,7 +615,7 @@
             pass.EndPass();
         }
 
-        dawn::CommandBuffer commands = builder.GetResult();
+        dawn::CommandBuffer commands = encoder.Finish();
         queue.Submit(1, &commands);
 
         swapchain.Present(backbuffer);
diff --git a/src/dawn_native/CommandBuffer.cpp b/src/dawn_native/CommandBuffer.cpp
index db88ab3..4f72bcc 100644
--- a/src/dawn_native/CommandBuffer.cpp
+++ b/src/dawn_native/CommandBuffer.cpp
@@ -303,6 +303,15 @@
         : ObjectBase(builder->GetDevice()), mResourceUsages(builder->AcquireResourceUsages()) {
     }
 
+    CommandBufferBase::CommandBufferBase(DeviceBase* device, ObjectBase::ErrorTag tag)
+        : ObjectBase(device, tag) {
+    }
+
+    // static
+    CommandBufferBase* CommandBufferBase::MakeError(DeviceBase* device) {
+        return new CommandBufferBase(device, ObjectBase::kError);
+    }
+
     const CommandBufferResourceUsage& CommandBufferBase::GetResourceUsages() const {
         return mResourceUsages;
     }
diff --git a/src/dawn_native/CommandBuffer.h b/src/dawn_native/CommandBuffer.h
index 27f126a..f880324 100644
--- a/src/dawn_native/CommandBuffer.h
+++ b/src/dawn_native/CommandBuffer.h
@@ -43,9 +43,13 @@
       public:
         CommandBufferBase(CommandBufferBuilder* builder);
 
+        static CommandBufferBase* MakeError(DeviceBase* device);
+
         const CommandBufferResourceUsage& GetResourceUsages() const;
 
       private:
+        CommandBufferBase(DeviceBase* device, ObjectBase::ErrorTag tag);
+
         CommandBufferResourceUsage mResourceUsages;
     };
 
diff --git a/src/dawn_native/CommandEncoder.cpp b/src/dawn_native/CommandEncoder.cpp
new file mode 100644
index 0000000..1ccd725
--- /dev/null
+++ b/src/dawn_native/CommandEncoder.cpp
@@ -0,0 +1,103 @@
+// Copyright 2019 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dawn_native/CommandEncoder.h"
+
+#include "dawn_native/CommandBuffer.h"
+#include "dawn_native/Device.h"
+
+namespace dawn_native {
+
+    CommandEncoderBase::CommandEncoderBase(DeviceBase* device) : ObjectBase(device) {
+        // Create a builder with an external reference count of 1. We don't use Ref<> because we
+        // want to release the external reference when the encoder is destroyed.
+        mBuilder = GetDevice()->CreateCommandBufferBuilder();
+        mBuilder->SetErrorCallback(
+            HandleBuilderError,
+            static_cast<dawnCallbackUserdata>(reinterpret_cast<uintptr_t>(this)), 0);
+    }
+
+    CommandEncoderBase::~CommandEncoderBase() {
+        // Release the single external reference of the builder
+        mBuilder->Release();
+        mBuilder = nullptr;
+    }
+
+    ComputePassEncoderBase* CommandEncoderBase::BeginComputePass() {
+        return mBuilder->BeginComputePass();
+    }
+
+    RenderPassEncoderBase* CommandEncoderBase::BeginRenderPass(RenderPassDescriptorBase* info) {
+        return mBuilder->BeginRenderPass(info);
+    }
+
+    void CommandEncoderBase::CopyBufferToBuffer(BufferBase* source,
+                                                uint32_t sourceOffset,
+                                                BufferBase* destination,
+                                                uint32_t destinationOffset,
+                                                uint32_t size) {
+        return mBuilder->CopyBufferToBuffer(source, sourceOffset, destination, destinationOffset,
+                                            size);
+    }
+
+    void CommandEncoderBase::CopyBufferToTexture(const BufferCopyView* source,
+                                                 const TextureCopyView* destination,
+                                                 const Extent3D* copySize) {
+        return mBuilder->CopyBufferToTexture(source, destination, copySize);
+    }
+
+    void CommandEncoderBase::CopyTextureToBuffer(const TextureCopyView* source,
+                                                 const BufferCopyView* destination,
+                                                 const Extent3D* copySize) {
+        return mBuilder->CopyTextureToBuffer(source, destination, copySize);
+    }
+
+    CommandBufferBase* CommandEncoderBase::Finish() {
+        if (GetDevice()->ConsumedError(ValidateFinish())) {
+            return CommandBufferBase::MakeError(GetDevice());
+        }
+        ASSERT(!IsError());
+
+        CommandBufferBase* result = mBuilder->GetResult();
+        if (result == nullptr) {
+            ASSERT(mGotError);
+            GetDevice()->ConsumedError(DAWN_VALIDATION_ERROR(mErrorMessage));
+            return CommandBufferBase::MakeError(GetDevice());
+        }
+
+        ASSERT(result != nullptr);
+        return result;
+    }
+
+    MaybeError CommandEncoderBase::ValidateFinish() {
+        DAWN_TRY(GetDevice()->ValidateObject(this));
+        DAWN_TRY(mBuilder->ValidateGetResult());
+        return {};
+    }
+
+    // static
+    void CommandEncoderBase::HandleBuilderError(dawnBuilderErrorStatus status,
+                                                const char* message,
+                                                dawnCallbackUserdata userdata1,
+                                                dawnCallbackUserdata) {
+        CommandEncoderBase* self =
+            reinterpret_cast<CommandEncoderBase*>(static_cast<uintptr_t>(userdata1));
+
+        if (status != DAWN_BUILDER_ERROR_STATUS_SUCCESS && !self->mGotError) {
+            self->mGotError = true;
+            self->mErrorMessage = message;
+        }
+    }
+
+}  // namespace dawn_native
diff --git a/src/dawn_native/CommandEncoder.h b/src/dawn_native/CommandEncoder.h
new file mode 100644
index 0000000..c4c7e06
--- /dev/null
+++ b/src/dawn_native/CommandEncoder.h
@@ -0,0 +1,67 @@
+// Copyright 2019 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef DAWNNATIVE_COMMANDENCODER_H_
+#define DAWNNATIVE_COMMANDENCODER_H_
+
+#include "dawn_native/dawn_platform.h"
+
+#include "dawn_native/Error.h"
+#include "dawn_native/ObjectBase.h"
+
+#include <string>
+
+namespace dawn_native {
+
+    class CommandBufferBuilder;
+
+    // CommandEncoder is temporarily a wrapper around CommandBufferBuilder so the two can coexist
+    // while code is migrated to the new shiny CommandEncoder interface. It captures any command
+    // buffer builder error and defers to trigger a device error when "Finish" is called.
+    class CommandEncoderBase : public ObjectBase {
+      public:
+        CommandEncoderBase(DeviceBase* device);
+        ~CommandEncoderBase();
+
+        // Dawn API
+        ComputePassEncoderBase* BeginComputePass();
+        RenderPassEncoderBase* BeginRenderPass(RenderPassDescriptorBase* info);
+        void CopyBufferToBuffer(BufferBase* source,
+                                uint32_t sourceOffset,
+                                BufferBase* destination,
+                                uint32_t destinationOffset,
+                                uint32_t size);
+        void CopyBufferToTexture(const BufferCopyView* source,
+                                 const TextureCopyView* destination,
+                                 const Extent3D* copySize);
+        void CopyTextureToBuffer(const TextureCopyView* source,
+                                 const BufferCopyView* destination,
+                                 const Extent3D* copySize);
+        CommandBufferBase* Finish();
+
+      private:
+        MaybeError ValidateFinish();
+        static void HandleBuilderError(dawnBuilderErrorStatus status,
+                                       const char* message,
+                                       dawnCallbackUserdata userdata1,
+                                       dawnCallbackUserdata userdata2);
+
+        CommandBufferBuilder* mBuilder = nullptr;
+        bool mGotError = false;
+        std::string mErrorMessage;
+    };
+
+}  // namespace dawn_native
+
+#endif  // DAWNNATIVE_COMMANDENCODER_H_
diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp
index 8a45075..068c753 100644
--- a/src/dawn_native/Device.cpp
+++ b/src/dawn_native/Device.cpp
@@ -19,6 +19,7 @@
 #include "dawn_native/BindGroupLayout.h"
 #include "dawn_native/Buffer.h"
 #include "dawn_native/CommandBuffer.h"
+#include "dawn_native/CommandEncoder.h"
 #include "dawn_native/ComputePipeline.h"
 #include "dawn_native/ErrorData.h"
 #include "dawn_native/Fence.h"
@@ -145,6 +146,9 @@
     CommandBufferBuilder* DeviceBase::CreateCommandBufferBuilder() {
         return new CommandBufferBuilder(this);
     }
+    CommandEncoderBase* DeviceBase::CreateCommandEncoder() {
+        return new CommandEncoderBase(this);
+    }
     ComputePipelineBase* DeviceBase::CreateComputePipeline(
         const ComputePipelineDescriptor* descriptor) {
         ComputePipelineBase* result = nullptr;
diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h
index 3dc8b83..ac5b550 100644
--- a/src/dawn_native/Device.h
+++ b/src/dawn_native/Device.h
@@ -91,6 +91,7 @@
         BindGroupLayoutBase* CreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor);
         BufferBase* CreateBuffer(const BufferDescriptor* descriptor);
         CommandBufferBuilder* CreateCommandBufferBuilder();
+        CommandEncoderBase* CreateCommandEncoder();
         ComputePipelineBase* CreateComputePipeline(const ComputePipelineDescriptor* descriptor);
         FenceBase* CreateFence(const FenceDescriptor* descriptor);
         InputStateBuilder* CreateInputStateBuilder();
diff --git a/src/dawn_native/Forward.h b/src/dawn_native/Forward.h
index 73a2555..76c12a5 100644
--- a/src/dawn_native/Forward.h
+++ b/src/dawn_native/Forward.h
@@ -29,6 +29,7 @@
     class ComputePipelineBase;
     class CommandBufferBase;
     class CommandBufferBuilder;
+    class CommandEncoderBase;
     class ComputePassEncoderBase;
     class FenceBase;
     class InputStateBase;
diff --git a/src/tests/DawnTest.cpp b/src/tests/DawnTest.cpp
index 23c32e5..13b6950 100644
--- a/src/tests/DawnTest.cpp
+++ b/src/tests/DawnTest.cpp
@@ -267,11 +267,10 @@
 
     // We need to enqueue the copy immediately because by the time we resolve the expectation,
     // the buffer might have been modified.
-    dawn::CommandBuffer commands =
-        device.CreateCommandBufferBuilder()
-            .CopyBufferToBuffer(buffer, offset, readback.buffer, readback.offset, size)
-            .GetResult();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
+    encoder.CopyBufferToBuffer(buffer, offset, readback.buffer, readback.offset, size);
 
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     DeferredExpectation deferred;
@@ -312,11 +311,11 @@
     dawn::BufferCopyView bufferCopyView =
         utils::CreateBufferCopyView(readback.buffer, readback.offset, rowPitch, 0);
     dawn::Extent3D copySize = {width, height, 1};
-    dawn::CommandBuffer commands =
-        device.CreateCommandBufferBuilder()
-            .CopyTextureToBuffer(&textureCopyView, &bufferCopyView, &copySize)
-            .GetResult();
 
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
+    encoder.CopyTextureToBuffer(&textureCopyView, &bufferCopyView, &copySize);
+
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     DeferredExpectation deferred;
diff --git a/src/tests/end2end/BindGroupTests.cpp b/src/tests/end2end/BindGroupTests.cpp
index d757428..b0a60ad 100644
--- a/src/tests/end2end/BindGroupTests.cpp
+++ b/src/tests/end2end/BindGroupTests.cpp
@@ -24,13 +24,13 @@
 protected:
     dawn::CommandBuffer CreateSimpleComputeCommandBuffer(
             const dawn::ComputePipeline& pipeline, const dawn::BindGroup& bindGroup) {
-        dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
-        dawn::ComputePassEncoder pass = builder.BeginComputePass();
+        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
+        dawn::ComputePassEncoder pass = encoder.BeginComputePass();
         pass.SetPipeline(pipeline);
         pass.SetBindGroup(0, bindGroup);
         pass.Dispatch(1, 1, 1);
         pass.EndPass();
-        return builder.GetResult();
+        return encoder.Finish();
     }
 
     dawn::PipelineLayout MakeBasicPipelineLayout(
@@ -152,14 +152,14 @@
         {1, buffer, 256, sizeof(Data::color)}
     });
 
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
-    dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
+    dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
     pass.SetPipeline(pipeline);
     pass.SetBindGroup(0, bindGroup);
     pass.Draw(3, 1, 0, 0);
     pass.EndPass();
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     RGBA8 filled(0, 255, 0, 255);
@@ -267,19 +267,19 @@
         {2, textureView}
     });
 
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     dawn::BufferCopyView bufferCopyView =
         utils::CreateBufferCopyView(stagingBuffer, 0, widthInBytes, 0);
     dawn::TextureCopyView textureCopyView = utils::CreateTextureCopyView(texture, 0, 0, {0, 0, 0});
     dawn::Extent3D copySize = {width, height, 1};
-    builder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copySize);
-    dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+    encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copySize);
+    dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
     pass.SetPipeline(pipeline);
     pass.SetBindGroup(0, bindGroup);
     pass.Draw(3, 1, 0, 0);
     pass.EndPass();
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     RGBA8 filled(0, 255, 0, 255);
@@ -367,15 +367,15 @@
                                                    {1, buffers[i], 256, sizeof(Data::color)}}));
     }
 
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
-    dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
+    dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
     pass.SetPipeline(pipeline);
     pass.SetBindGroup(0, bindGroups[0]);
     pass.SetBindGroup(1, bindGroups[1]);
     pass.Draw(3, 1, 0, 0);
     pass.EndPass();
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     RGBA8 filled(255, 255, 0, 255);
@@ -434,8 +434,8 @@
     pipelineDescriptor.cColorStates[0].format = renderPass.colorFormat;
 
     dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDescriptor);
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
-    dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
+    dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
 
     pass.SetPipeline(pipeline);
 
@@ -455,7 +455,7 @@
     pass.Draw(3, 1, 0, 0);
     pass.EndPass();
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     RGBA8 filled(255, 0, 0, 255);
diff --git a/src/tests/end2end/BlendStateTests.cpp b/src/tests/end2end/BlendStateTests.cpp
index 7b17c50..6b9ddd8 100644
--- a/src/tests/end2end/BlendStateTests.cpp
+++ b/src/tests/end2end/BlendStateTests.cpp
@@ -106,9 +106,9 @@
         void DoSingleSourceTest(RGBA8 base, const TriangleSpec& triangle, const RGBA8& expected) {
             dawn::Color blendColor{triangle.blendFactor[0], triangle.blendFactor[1], triangle.blendFactor[2], triangle.blendFactor[3]};
 
-            dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+            dawn::CommandEncoder encoder = device.CreateCommandEncoder();
             {
-                dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+                dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
                 // First use the base pipeline to draw a triangle with no blending
                 pass.SetPipeline(basePipeline);
                 pass.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { base } })));
@@ -122,7 +122,7 @@
                 pass.EndPass();
             }
 
-            dawn::CommandBuffer commands = builder.GetResult();
+            dawn::CommandBuffer commands = encoder.Finish();
             queue.Submit(1, &commands);
 
             EXPECT_PIXEL_RGBA8_EQ(expected, renderPass.color, kRTSize / 2, kRTSize / 2);
@@ -689,16 +689,16 @@
         RGBA8 base(32, 64, 128, 192);
         RGBA8 expected(32, 0, 0, 0);
 
-        dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
         {
-            dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+            dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
             pass.SetPipeline(testPipeline);
             pass.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { base } })));
             pass.Draw(3, 1, 0, 0);
             pass.EndPass();
         }
 
-        dawn::CommandBuffer commands = builder.GetResult();
+        dawn::CommandBuffer commands = encoder.Finish();
         queue.Submit(1, &commands);
         EXPECT_PIXEL_RGBA8_EQ(expected, renderPass.color, kRTSize / 2, kRTSize / 2);
     }
@@ -815,9 +815,9 @@
         RGBA8 expected2 = color2;
         RGBA8 expected3 = min(color3, base);
 
-        dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
         {
-            dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderpass);
+            dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderpass);
             pass.SetPipeline(basePipeline);
             pass.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 4>({ { base, base, base, base } })));
             pass.Draw(3, 1, 0, 0);
@@ -828,7 +828,7 @@
             pass.EndPass();
         }
 
-        dawn::CommandBuffer commands = builder.GetResult();
+        dawn::CommandBuffer commands = encoder.Finish();
         queue.Submit(1, &commands);
 
         EXPECT_PIXEL_RGBA8_EQ(expected0, renderTargets[0], kRTSize / 2, kRTSize / 2) << "Attachment slot 0 should have been " << color0 << " + " << base << " = " << expected0;
@@ -879,9 +879,9 @@
 
     // Check that the initial blend color is (0,0,0,0)
     {
-        dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
         {
-            dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+            dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
             pass.SetPipeline(basePipeline);
             pass.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { RGBA8(0, 0, 0, 0) } })));
             pass.Draw(3, 1, 0, 0);
@@ -891,7 +891,7 @@
             pass.EndPass();
         }
 
-        dawn::CommandBuffer commands = builder.GetResult();
+        dawn::CommandBuffer commands = encoder.Finish();
         queue.Submit(1, &commands);
 
         EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, kRTSize / 2, kRTSize / 2);
@@ -899,9 +899,9 @@
 
     // Check that setting the blend color works
     {
-        dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
         {
-            dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+            dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
             pass.SetPipeline(basePipeline);
             pass.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { RGBA8(0, 0, 0, 0) } })));
             pass.Draw(3, 1, 0, 0);
@@ -912,7 +912,7 @@
             pass.EndPass();
         }
 
-        dawn::CommandBuffer commands = builder.GetResult();
+        dawn::CommandBuffer commands = encoder.Finish();
         queue.Submit(1, &commands);
 
         EXPECT_PIXEL_RGBA8_EQ(RGBA8(255, 255, 255, 255), renderPass.color, kRTSize / 2, kRTSize / 2);
@@ -920,9 +920,9 @@
 
     // Check that the blend color is not inherited between render passes
     {
-        dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
         {
-            dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+            dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
             pass.SetPipeline(basePipeline);
             pass.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { RGBA8(0, 0, 0, 0) } })));
             pass.Draw(3, 1, 0, 0);
@@ -933,7 +933,7 @@
             pass.EndPass();
         }
         {
-            dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+            dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
             pass.SetPipeline(basePipeline);
             pass.SetBindGroup(0, MakeBindGroupForColors(std::array<RGBA8, 1>({ { RGBA8(0, 0, 0, 0) } })));
             pass.Draw(3, 1, 0, 0);
@@ -943,7 +943,7 @@
             pass.EndPass();
         }
 
-        dawn::CommandBuffer commands = builder.GetResult();
+        dawn::CommandBuffer commands = encoder.Finish();
         queue.Submit(1, &commands);
 
         EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, kRTSize / 2, kRTSize / 2);
diff --git a/src/tests/end2end/ComputeCopyStorageBufferTests.cpp b/src/tests/end2end/ComputeCopyStorageBufferTests.cpp
index 14b0a14..a2af907 100644
--- a/src/tests/end2end/ComputeCopyStorageBufferTests.cpp
+++ b/src/tests/end2end/ComputeCopyStorageBufferTests.cpp
@@ -76,14 +76,14 @@
 
     dawn::CommandBuffer commands;
     {
-        dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
-        dawn::ComputePassEncoder pass = builder.BeginComputePass();
+        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
+        dawn::ComputePassEncoder pass = encoder.BeginComputePass();
         pass.SetPipeline(pipeline);
         pass.SetBindGroup(0, bindGroup);
         pass.Dispatch(kInstances, 1, 1);
         pass.EndPass();
 
-        commands = builder.GetResult();
+        commands = encoder.Finish();
     }
 
     queue.Submit(1, &commands);
diff --git a/src/tests/end2end/CopyTests.cpp b/src/tests/end2end/CopyTests.cpp
index 99bed81..1031f37 100644
--- a/src/tests/end2end/CopyTests.cpp
+++ b/src/tests/end2end/CopyTests.cpp
@@ -91,7 +91,7 @@
             uint32_t texelsPerRow = rowPitch / kBytesPerTexel;
             uint32_t texelCountPerLayer = texelsPerRow * (height - 1) + width;
 
-            dawn::CommandBufferBuilder cmdBuilder = device.CreateCommandBufferBuilder();
+            dawn::CommandEncoder encoder = device.CreateCommandEncoder();
 
             std::vector<std::vector<RGBA8>> textureArrayData(textureSpec.arraySize);
             for (uint32_t slice = 0; slice < textureSpec.arraySize; ++slice) {
@@ -106,7 +106,7 @@
                 dawn::TextureCopyView textureCopyView =
                     utils::CreateTextureCopyView(texture, textureSpec.level, slice, {0, 0, 0});
                 dawn::Extent3D copySize = {width, height, 1};
-                cmdBuilder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copySize);
+                encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copySize);
             }
 
             // Create a buffer of size `size * textureSpec.arrayLayer` and populate it with empty data (0,0,0,0)
@@ -127,11 +127,11 @@
                 dawn::BufferCopyView bufferCopyView =
                     utils::CreateBufferCopyView(buffer, bufferOffset, bufferSpec.rowPitch, 0);
                 dawn::Extent3D copySize = {textureSpec.copyWidth, textureSpec.copyHeight, 1};
-                cmdBuilder.CopyTextureToBuffer(&textureCopyView, &bufferCopyView, &copySize);
+                encoder.CopyTextureToBuffer(&textureCopyView, &bufferCopyView, &copySize);
                 bufferOffset += bufferSpec.size;
             }
 
-            dawn::CommandBuffer commands = cmdBuilder.GetResult();
+            dawn::CommandBuffer commands = encoder.Finish();
             queue.Submit(1, &commands);
 
             bufferOffset = bufferSpec.offset;
@@ -195,7 +195,7 @@
         descriptor.usage = dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::TransferSrc;
         dawn::Texture texture = device.CreateTexture(&descriptor);
 
-        dawn::CommandBufferBuilder cmdBuilder = device.CreateCommandBufferBuilder();
+        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
 
         // Create an upload buffer filled with empty data and use it to populate the `level` mip of the texture
         // Note: Prepopulating the texture with empty data ensures that there is not random data in the expectation
@@ -214,7 +214,7 @@
             dawn::TextureCopyView textureCopyView =
                 utils::CreateTextureCopyView(texture, textureSpec.level, 0, {0, 0, 0});
             dawn::Extent3D copySize = {width, height, 1};
-            cmdBuilder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copySize);
+            encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copySize);
         }
 
         // Copy to the region [(`x`, `y`), (`x + copyWidth, `y + copyWidth`)] at the `level` mip from the buffer at the specified `offset` and `rowPitch`
@@ -224,10 +224,10 @@
             dawn::TextureCopyView textureCopyView = utils::CreateTextureCopyView(
                 texture, textureSpec.level, 0, {textureSpec.x, textureSpec.y, 0});
             dawn::Extent3D copySize = {textureSpec.copyWidth, textureSpec.copyHeight, 1};
-            cmdBuilder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copySize);
+            encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copySize);
         }
 
-        dawn::CommandBuffer commands = cmdBuilder.GetResult();
+        dawn::CommandBuffer commands = encoder.Finish();
         queue.Submit(1, &commands);
 
         // Pack the data used to create the buffer in the specified copy region to have the same format as the expected texture data.
diff --git a/src/tests/end2end/DepthStencilStateTests.cpp b/src/tests/end2end/DepthStencilStateTests.cpp
index beb6b59..72d807b 100644
--- a/src/tests/end2end/DepthStencilStateTests.cpp
+++ b/src/tests/end2end/DepthStencilStateTests.cpp
@@ -266,14 +266,14 @@
         // Each test param represents a pair of triangles with a color, depth, stencil value, and depthStencil state, one frontfacing, one backfacing
         // Draw the triangles in order and check the expected colors for the frontfaces and backfaces
         void DoTest(const std::vector<TestSpec> &testParams, const RGBA8& expectedFront, const RGBA8& expectedBack) {
-            dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+            dawn::CommandEncoder encoder = device.CreateCommandEncoder();
 
             struct TriangleData {
                 float color[3];
                 float depth;
             };
 
-            dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderpass);
+            dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderpass);
 
             for (size_t i = 0; i < testParams.size(); ++i) {
                 const TestSpec& test = testParams[i];
@@ -307,7 +307,7 @@
             }
             pass.EndPass();
 
-            dawn::CommandBuffer commands = builder.GetResult();
+            dawn::CommandBuffer commands = encoder.Finish();
             queue.Submit(1, &commands);
 
             EXPECT_PIXEL_RGBA8_EQ(expectedFront, renderTarget, kRTSize / 4, kRTSize / 2) << "Front face check failed";
diff --git a/src/tests/end2end/DrawIndexedTests.cpp b/src/tests/end2end/DrawIndexedTests.cpp
index 5babbf5..3148516 100644
--- a/src/tests/end2end/DrawIndexedTests.cpp
+++ b/src/tests/end2end/DrawIndexedTests.cpp
@@ -95,9 +95,9 @@
                   uint32_t baseVertex, uint32_t firstInstance, RGBA8 bottomLeftExpected,
                   RGBA8 topRightExpected) {
             uint32_t zeroOffset = 0;
-            dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+            dawn::CommandEncoder encoder = device.CreateCommandEncoder();
             {
-                dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+                dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
                 pass.SetPipeline(pipeline);
                 pass.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset);
                 pass.SetIndexBuffer(indexBuffer, 0);
@@ -105,7 +105,7 @@
                 pass.EndPass();
             }
 
-            dawn::CommandBuffer commands = builder.GetResult();
+            dawn::CommandBuffer commands = encoder.Finish();
             queue.Submit(1, &commands);
 
             EXPECT_PIXEL_RGBA8_EQ(bottomLeftExpected, renderPass.color, 1, 3);
diff --git a/src/tests/end2end/DrawTests.cpp b/src/tests/end2end/DrawTests.cpp
index f599874..b7eed7a 100644
--- a/src/tests/end2end/DrawTests.cpp
+++ b/src/tests/end2end/DrawTests.cpp
@@ -86,16 +86,16 @@
               RGBA8 bottomLeftExpected,
               RGBA8 topRightExpected) {
         uint32_t zeroOffset = 0;
-        dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
         {
-            dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+            dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
             pass.SetPipeline(pipeline);
             pass.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset);
             pass.Draw(vertexCount, instanceCount, firstIndex, firstInstance);
             pass.EndPass();
         }
 
-        dawn::CommandBuffer commands = builder.GetResult();
+        dawn::CommandBuffer commands = encoder.Finish();
         queue.Submit(1, &commands);
 
         EXPECT_PIXEL_RGBA8_EQ(bottomLeftExpected, renderPass.color, 1, 3);
diff --git a/src/tests/end2end/IndexFormatTests.cpp b/src/tests/end2end/IndexFormatTests.cpp
index e48004a..b940179 100644
--- a/src/tests/end2end/IndexFormatTests.cpp
+++ b/src/tests/end2end/IndexFormatTests.cpp
@@ -91,9 +91,9 @@
     });
 
     uint32_t zeroOffset = 0;
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
         pass.SetPipeline(pipeline);
         pass.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset);
         pass.SetIndexBuffer(indexBuffer, 0);
@@ -101,7 +101,7 @@
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 100, 300);
@@ -122,9 +122,9 @@
     });
 
     uint32_t zeroOffset = 0;
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
         pass.SetPipeline(pipeline);
         pass.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset);
         pass.SetIndexBuffer(indexBuffer, 0);
@@ -132,7 +132,7 @@
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 100, 300);
@@ -166,9 +166,9 @@
     });
 
     uint32_t zeroOffset = 0;
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
         pass.SetPipeline(pipeline);
         pass.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset);
         pass.SetIndexBuffer(indexBuffer, 0);
@@ -176,7 +176,7 @@
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 190, 190);  // A
@@ -200,9 +200,9 @@
     });
 
     uint32_t zeroOffset = 0;
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
         pass.SetPipeline(pipeline);
         pass.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset);
         pass.SetIndexBuffer(indexBuffer, 0);
@@ -210,7 +210,7 @@
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 190, 190);  // A
@@ -239,9 +239,9 @@
     });
 
     uint32_t zeroOffset = 0;
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
         pass.SetPipeline(pipeline16);
         pass.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset);
         pass.SetIndexBuffer(indexBuffer, 0);
@@ -250,7 +250,7 @@
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 100, 300);
@@ -274,9 +274,9 @@
     });
 
     uint32_t zeroOffset = 0;
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
         pass.SetIndexBuffer(indexBuffer, 0);
         pass.SetPipeline(pipeline);
         pass.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset);
@@ -284,7 +284,7 @@
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 100, 300);
diff --git a/src/tests/end2end/InputStateTests.cpp b/src/tests/end2end/InputStateTests.cpp
index b0ca913..9e365c3 100644
--- a/src/tests/end2end/InputStateTests.cpp
+++ b/src/tests/end2end/InputStateTests.cpp
@@ -178,9 +178,9 @@
             EXPECT_LE(triangles, 4u);
             EXPECT_LE(instances, 4u);
 
-            dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+            dawn::CommandEncoder encoder = device.CreateCommandEncoder();
 
-            dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+            dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
             pass.SetPipeline(pipeline);
 
             uint32_t zeroOffset = 0;
@@ -191,7 +191,7 @@
             pass.Draw(triangles * 3, instances, 0, 0);
             pass.EndPass();
 
-            dawn::CommandBuffer commands = builder.GetResult();
+            dawn::CommandBuffer commands = encoder.Finish();
             queue.Submit(1, &commands);
 
             CheckResult(triangles, instances);
@@ -452,9 +452,9 @@
         3, 4, 5, 6,
     });
 
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
 
-    dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+    dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
 
     uint32_t zeroOffset = 0;
     pass.SetVertexBuffers(0, 1, &buffer, &zeroOffset);
@@ -465,7 +465,7 @@
 
     pass.EndPass();
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     CheckResult(1, 4);
@@ -497,9 +497,9 @@
         3, 4, 5, 6,
     });
 
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
 
-    dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+    dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
 
     uint32_t zeroOffset = 0;
     pass.SetVertexBuffers(0, 1, &buffer, &zeroOffset);
@@ -513,7 +513,7 @@
 
     pass.EndPass();
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     CheckResult(1, 4);
diff --git a/src/tests/end2end/PrimitiveTopologyTests.cpp b/src/tests/end2end/PrimitiveTopologyTests.cpp
index ce0ed32..791c8b3 100644
--- a/src/tests/end2end/PrimitiveTopologyTests.cpp
+++ b/src/tests/end2end/PrimitiveTopologyTests.cpp
@@ -208,16 +208,16 @@
             dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);
 
             static const uint32_t zeroOffset = 0;
-            dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+            dawn::CommandEncoder encoder = device.CreateCommandEncoder();
             {
-                dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+                dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
                 pass.SetPipeline(pipeline);
                 pass.SetVertexBuffers(0, 1, &vertexBuffer, &zeroOffset);
                 pass.Draw(6, 1, 0, 0);
                 pass.EndPass();
             }
 
-            dawn::CommandBuffer commands = builder.GetResult();
+            dawn::CommandBuffer commands = encoder.Finish();
             queue.Submit(1, &commands);
 
             for (auto& locationSpec : locationSpecs) {
diff --git a/src/tests/end2end/PushConstantTests.cpp b/src/tests/end2end/PushConstantTests.cpp
index c4ee54c..e8cf5eb 100644
--- a/src/tests/end2end/PushConstantTests.cpp
+++ b/src/tests/end2end/PushConstantTests.cpp
@@ -210,9 +210,9 @@
     dawn::ComputePipeline pipeline = MakeTestComputePipeline(binding.layout, MakeAllZeroSpec());
 
     uint32_t notZero = 42;
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::ComputePassEncoder pass = builder.BeginComputePass();
+        dawn::ComputePassEncoder pass = encoder.BeginComputePass();
 
         // Test compute push constants are set to zero by default.
         pass.SetPipeline(pipeline);
@@ -225,7 +225,7 @@
         pass.EndPass();
     }
     {
-        dawn::ComputePassEncoder pass = builder.BeginComputePass();
+        dawn::ComputePassEncoder pass = encoder.BeginComputePass();
 
         pass.SetPipeline(pipeline);
         pass.SetBindGroup(0, binding.bindGroup);
@@ -234,7 +234,7 @@
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_BUFFER_U32_EQ(1, binding.resultBuffer, 0);
@@ -249,16 +249,16 @@
     dawn::PipelineLayout layout = MakeEmptyLayout();
     dawn::RenderPipeline pipeline = MakeTestRenderPipeline(layout, MakeAllZeroSpec(), MakeAllZeroSpec());
 
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
         // Test render push constants are set to zero by default.
         pass.SetPipeline(pipeline);
         pass.Draw(1, 1, 0, 0);
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 1, 0, 0), renderPass.color, 0, 0);
@@ -279,9 +279,9 @@
     dawn::ComputePipeline pipeline = MakeTestComputePipeline(binding.layout, spec);
 
 
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::ComputePassEncoder pass = builder.BeginComputePass();
+        dawn::ComputePassEncoder pass = encoder.BeginComputePass();
 
         pass.SetPushConstants(dawn::ShaderStageBit::Compute, 0, 3, reinterpret_cast<uint32_t*>(&values));
         pass.SetPipeline(pipeline);
@@ -291,7 +291,7 @@
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_BUFFER_U32_EQ(1, binding.resultBuffer, 0);
@@ -309,9 +309,9 @@
 
     uint32_t one = 1;
     uint32_t two = 2;
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::ComputePassEncoder pass = builder.BeginComputePass();
+        dawn::ComputePassEncoder pass = encoder.BeginComputePass();
 
         // Set Push constant before there is a pipeline set
         pass.SetPushConstants(dawn::ShaderStageBit::Compute, 0, 1, &one);
@@ -327,7 +327,7 @@
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_BUFFER_U32_EQ(1, binding1.resultBuffer, 0);
@@ -346,9 +346,9 @@
     auto binding = MakeTestBindings(false);
     dawn::ComputePipeline pipeline = MakeTestComputePipeline(binding.layout, spec);
 
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::ComputePassEncoder pass = builder.BeginComputePass();
+        dawn::ComputePassEncoder pass = encoder.BeginComputePass();
 
         pass.SetPushConstants(dawn::ShaderStageBit::Compute, 0, kMaxPushConstants, &values[0]);
         pass.SetPipeline(pipeline);
@@ -358,7 +358,7 @@
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_BUFFER_U32_EQ(1, binding.resultBuffer, 0);
@@ -376,9 +376,9 @@
 
     uint32_t one = 1;
     uint32_t two = 2;
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
         pass.SetPushConstants(dawn::ShaderStageBit::Vertex, 0, 1, &one);
         pass.SetPushConstants(dawn::ShaderStageBit::Fragment, 0, 1, &two);
         pass.SetPipeline(pipeline);
@@ -386,7 +386,7 @@
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 1, 0, 0), renderPass.color, 0, 0);
@@ -402,16 +402,16 @@
     dawn::RenderPipeline pipeline = MakeTestRenderPipeline(layout, spec, spec);
 
     uint32_t two = 2;
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
         pass.SetPushConstants(dawn::ShaderStageBit::Vertex | dawn::ShaderStageBit::Fragment, 0, 1, &two);
         pass.SetPipeline(pipeline);
         pass.Draw(1, 1, 0, 0);
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 1, 0, 0), renderPass.color, 0, 0);
diff --git a/src/tests/end2end/RenderPassLoadOpTests.cpp b/src/tests/end2end/RenderPassLoadOpTests.cpp
index a759c12..3339404 100644
--- a/src/tests/end2end/RenderPassLoadOpTests.cpp
+++ b/src/tests/end2end/RenderPassLoadOpTests.cpp
@@ -124,10 +124,10 @@
         .SetColorAttachments(1, &colorAttachment)
         .GetResult();
 
-    auto commandsClearZeroBuilder = device.CreateCommandBufferBuilder();
-    auto clearZeroPass = commandsClearZeroBuilder.BeginRenderPass(renderPassClearZero);
+    auto commandsClearZeroEncoder = device.CreateCommandEncoder();
+    auto clearZeroPass = commandsClearZeroEncoder.BeginRenderPass(renderPassClearZero);
     clearZeroPass.EndPass();
-    auto commandsClearZero = commandsClearZeroBuilder.GetResult();
+    auto commandsClearZero = commandsClearZeroEncoder.Finish();
 
     dawn::RenderPassColorAttachmentDescriptor colorAttachmentGreen = colorAttachment;
     colorAttachmentGreen.clearColor = { 0.0f, 1.0f, 0.0f, 1.0f };
@@ -135,10 +135,10 @@
         .SetColorAttachments(1, &colorAttachmentGreen)
         .GetResult();
 
-    auto commandsClearGreenBuilder = device.CreateCommandBufferBuilder();
-    auto clearGreenPass = commandsClearGreenBuilder.BeginRenderPass(renderPassClearGreen);
+    auto commandsClearGreenEncoder = device.CreateCommandEncoder();
+    auto clearGreenPass = commandsClearGreenEncoder.BeginRenderPass(renderPassClearGreen);
     clearGreenPass.EndPass();
-    auto commandsClearGreen = commandsClearGreenBuilder.GetResult();
+    auto commandsClearGreen = commandsClearGreenEncoder.Finish();
 
     queue.Submit(1, &commandsClearZero);
     EXPECT_TEXTURE_RGBA8_EQ(expectZero.data(), renderTarget, 0, 0, kRTSize, kRTSize, 0, 0);
@@ -155,11 +155,11 @@
 
     dawn::CommandBuffer commandsLoad;
     {
-        auto builder = device.CreateCommandBufferBuilder();
-        auto pass = builder.BeginRenderPass(renderPassLoad);
+        auto encoder = device.CreateCommandEncoder();
+        auto pass = encoder.BeginRenderPass(renderPassLoad);
         blueQuad.Draw(&pass);
         pass.EndPass();
-        commandsLoad = builder.GetResult();
+        commandsLoad = encoder.Finish();
     }
 
     queue.Submit(1, &commandsLoad);
diff --git a/src/tests/end2end/RenderPassTests.cpp b/src/tests/end2end/RenderPassTests.cpp
index b5eccae..94c4abb 100644
--- a/src/tests/end2end/RenderPassTests.cpp
+++ b/src/tests/end2end/RenderPassTests.cpp
@@ -80,7 +80,7 @@
 
     dawn::Texture renderTarget1 = CreateDefault2DTexture();
     dawn::Texture renderTarget2 = CreateDefault2DTexture();
-    dawn::CommandBufferBuilder commandBufferBuilder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
 
     dawn::RenderPassColorAttachmentDescriptor colorAttachment;
     colorAttachment.loadOp = dawn::LoadOp::Clear;
@@ -97,7 +97,7 @@
             .SetColorAttachments(1, &colorAttachment)
             .GetResult();
 
-        dawn::RenderPassEncoder pass = commandBufferBuilder.BeginRenderPass(renderPass);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass);
         pass.SetPipeline(pipeline);
         pass.Draw(3, 1, 0, 0);
         pass.EndPass();
@@ -112,13 +112,13 @@
             .SetColorAttachments(1, &colorAttachment)
             .GetResult();
 
-        dawn::RenderPassEncoder pass = commandBufferBuilder.BeginRenderPass(renderPass);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass);
         pass.SetPipeline(pipeline);
         pass.Draw(3, 1, 0, 0);
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = commandBufferBuilder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_PIXEL_RGBA8_EQ(kBlue, renderTarget1, 1, kRTSize - 1);
diff --git a/src/tests/end2end/SamplerTests.cpp b/src/tests/end2end/SamplerTests.cpp
index afe2e8e..9f2f567 100644
--- a/src/tests/end2end/SamplerTests.cpp
+++ b/src/tests/end2end/SamplerTests.cpp
@@ -106,12 +106,13 @@
         dawn::TextureCopyView textureCopyView =
             utils::CreateTextureCopyView(texture, 0, 0, {0, 0, 0});
         dawn::Extent3D copySize = {2, 2, 1};
-        dawn::CommandBuffer copy =
-            device.CreateCommandBufferBuilder()
-                .CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copySize)
-                .GetResult();
 
+        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
+        encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copySize);
+
+        dawn::CommandBuffer copy = encoder.Finish();
         queue.Submit(1, &copy);
+
         mTextureView = texture.CreateDefaultTextureView();
     }
 
@@ -137,16 +138,16 @@
             {1, mTextureView}
         });
 
-        dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
         {
-            dawn::RenderPassEncoder pass = builder.BeginRenderPass(mRenderPass.renderPassInfo);
+            dawn::RenderPassEncoder pass = encoder.BeginRenderPass(mRenderPass.renderPassInfo);
             pass.SetPipeline(mPipeline);
             pass.SetBindGroup(0, bindGroup);
             pass.Draw(6, 1, 0, 0);
             pass.EndPass();
         }
 
-        dawn::CommandBuffer commands = builder.GetResult();
+        dawn::CommandBuffer commands = encoder.Finish();
         queue.Submit(1, &commands);
 
         RGBA8 expectedU2(u.mExpected2, u.mExpected2, u.mExpected2, 255);
diff --git a/src/tests/end2end/ScissorTests.cpp b/src/tests/end2end/ScissorTests.cpp
index 1cb3051..95c61ad 100644
--- a/src/tests/end2end/ScissorTests.cpp
+++ b/src/tests/end2end/ScissorTests.cpp
@@ -51,15 +51,15 @@
     utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 100, 100);
     dawn::RenderPipeline pipeline = CreateQuadPipeline(renderPass.colorFormat);
 
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
         pass.SetPipeline(pipeline);
         pass.Draw(6, 1, 0, 0);
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 0, 0);
@@ -73,16 +73,16 @@
     utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 100, 100);
     dawn::RenderPipeline pipeline = CreateQuadPipeline(renderPass.colorFormat);
 
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
         pass.SetPipeline(pipeline);
         pass.SetScissorRect(0, 0, 200, 200);
         pass.Draw(6, 1, 0, 0);
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 0, 0);
@@ -99,16 +99,16 @@
     utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 2, 2);
     dawn::RenderPipeline pipeline = CreateQuadPipeline(renderPass.colorFormat);
 
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
         pass.SetPipeline(pipeline);
         pass.SetScissorRect(0, 0, 0, 0);
         pass.Draw(6, 1, 0, 0);
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), renderPass.color, 0, 0);
@@ -127,16 +127,16 @@
     constexpr uint32_t kW = 5;
     constexpr uint32_t kH = 13;
 
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
         pass.SetPipeline(pipeline);
         pass.SetScissorRect(kX, kY, kW, kH);
         pass.Draw(6, 1, 0, 0);
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     // Test the two opposite corners of the scissor box. With one pixel inside and on outside
@@ -152,22 +152,22 @@
     utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 100, 100);
     dawn::RenderPipeline pipeline = CreateQuadPipeline(renderPass.colorFormat);
 
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     // RenderPass 1 set the scissor
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
         pass.SetScissorRect(0, 0, 0, 0);
         pass.EndPass();
     }
     // RenderPass 2 draw a full quad, it shouldn't be scissored
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
         pass.SetPipeline(pipeline);
         pass.Draw(6, 1, 0, 0);
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 0, 0);
diff --git a/src/tests/end2end/TextureViewTests.cpp b/src/tests/end2end/TextureViewTests.cpp
index 6b2ac46..5c00f11 100644
--- a/src/tests/end2end/TextureViewTests.cpp
+++ b/src/tests/end2end/TextureViewTests.cpp
@@ -134,7 +134,7 @@
         constexpr uint32_t kPixelsPerRowPitch = kTextureRowPitchAlignment / sizeof(RGBA8);
         ASSERT_LE(textureWidthLevel0, kPixelsPerRowPitch);
 
-        dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
         for (uint32_t layer = 0; layer < layerCount; ++layer) {
             for (uint32_t level = 0; level < levelCount; ++level) {
                 const uint32_t texWidth = textureWidthLevel0 >> level;
@@ -152,10 +152,10 @@
                 dawn::TextureCopyView textureCopyView =
                     utils::CreateTextureCopyView(mTexture, level, layer, {0, 0, 0});
                 dawn::Extent3D copySize = {texWidth, texHeight, 1};
-                builder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copySize);
+                encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, &copySize);
             }
         }
-        dawn::CommandBuffer copy = builder.GetResult();
+        dawn::CommandBuffer copy = encoder.Finish();
         queue.Submit(1, &copy);
     }
 
@@ -176,16 +176,16 @@
 
         dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&textureDescriptor);
 
-        dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
         {
-            dawn::RenderPassEncoder pass = builder.BeginRenderPass(mRenderPass.renderPassInfo);
+            dawn::RenderPassEncoder pass = encoder.BeginRenderPass(mRenderPass.renderPassInfo);
             pass.SetPipeline(pipeline);
             pass.SetBindGroup(0, bindGroup);
             pass.Draw(6, 1, 0, 0);
             pass.EndPass();
         }
 
-        dawn::CommandBuffer commands = builder.GetResult();
+        dawn::CommandBuffer commands = encoder.Finish();
         queue.Submit(1, &commands);
 
         RGBA8 expectedPixel(0, 0, 0, expected);
@@ -520,16 +520,16 @@
 
         dawn::RenderPipeline oneColorPipeline = device.CreateRenderPipeline(&pipelineDescriptor);
 
-        dawn::CommandBufferBuilder commandBufferBuilder = device.CreateCommandBufferBuilder();
+        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
         {
             dawn::RenderPassEncoder pass =
-                commandBufferBuilder.BeginRenderPass(renderPassInfo);
+                encoder.BeginRenderPass(renderPassInfo);
             pass.SetPipeline(oneColorPipeline);
             pass.Draw(6, 1, 0, 0);
             pass.EndPass();
         }
 
-        dawn::CommandBuffer commands = commandBufferBuilder.GetResult();
+        dawn::CommandBuffer commands = encoder.Finish();
         queue.Submit(1, &commands);
 
         // Check if the right pixels (Green) have been written into the right part of the texture.
diff --git a/src/tests/end2end/ViewportOrientationTests.cpp b/src/tests/end2end/ViewportOrientationTests.cpp
index 18ecc8a..074997eb 100644
--- a/src/tests/end2end/ViewportOrientationTests.cpp
+++ b/src/tests/end2end/ViewportOrientationTests.cpp
@@ -44,15 +44,15 @@
 
     dawn::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);
 
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
     {
-        dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass.renderPassInfo);
+        dawn::RenderPassEncoder pass = encoder.BeginRenderPass(renderPass.renderPassInfo);
         pass.SetPipeline(pipeline);
         pass.Draw(1, 1, 0, 0);
         pass.EndPass();
     }
 
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 
     EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 0, 0);
diff --git a/src/tests/unittests/validation/BufferValidationTests.cpp b/src/tests/unittests/validation/BufferValidationTests.cpp
index 2e2081e..2b05026 100644
--- a/src/tests/unittests/validation/BufferValidationTests.cpp
+++ b/src/tests/unittests/validation/BufferValidationTests.cpp
@@ -614,9 +614,9 @@
     dawn::Buffer bufA = device.CreateBuffer(&descriptorA);
     dawn::Buffer bufB = device.CreateBuffer(&descriptorB);
 
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
-    builder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
+    encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
+    dawn::CommandBuffer commands = encoder.Finish();
     queue.Submit(1, &commands);
 }
 
@@ -635,9 +635,9 @@
 
         bufA.MapWriteAsync(ToMockBufferMapWriteCallback, 40329);
 
-        dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
-        builder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
-        dawn::CommandBuffer commands = builder.GetResult();
+        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
+        encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
+        dawn::CommandBuffer commands = encoder.Finish();
         ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
         queue.Submit(0, nullptr);
     }
@@ -647,9 +647,9 @@
 
         bufB.MapReadAsync(ToMockBufferMapReadCallback, 11329);
 
-        dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
-        builder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
-        dawn::CommandBuffer commands = builder.GetResult();
+        dawn::CommandEncoder encoder = device.CreateCommandEncoder();
+        encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
+        dawn::CommandBuffer commands = encoder.Finish();
         ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
         queue.Submit(0, nullptr);
     }
@@ -669,9 +669,9 @@
     dawn::Buffer bufB = device.CreateBuffer(&descriptorB);
 
     bufA.Destroy();
-    dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder();
-    builder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
-    dawn::CommandBuffer commands = builder.GetResult();
+    dawn::CommandEncoder encoder = device.CreateCommandEncoder();
+    encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
+    dawn::CommandBuffer commands = encoder.Finish();
     ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
 }