[dawn][wire] Use client reservation structs for server injection.

- Moving to use this abstraction allows us to make changes to the
  reservation and injection mechanisms without changing any APIs.
- Adds new set of APIs for server injection that will supersede the
  existing ones.

Change-Id: Ia3576c78f4897dcf3a3606243f7b60552fe9bb06
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/174440
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Loko Kung <lokokung@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/include/dawn/wire/Wire.h b/include/dawn/wire/Wire.h
index 0e32fcd1..537b62f 100644
--- a/include/dawn/wire/Wire.h
+++ b/include/dawn/wire/Wire.h
@@ -63,6 +63,31 @@
     virtual const volatile char* HandleCommands(const volatile char* commands, size_t size) = 0;
 };
 
+// Reservation structs used between the client and the server.
+struct TextureReservation {
+    uint32_t id;
+    uint32_t generation;
+    uint32_t deviceId;
+    uint32_t deviceGeneration;
+};
+
+struct SwapChainReservation {
+    uint32_t id;
+    uint32_t generation;
+    uint32_t deviceId;
+    uint32_t deviceGeneration;
+};
+
+struct DeviceReservation {
+    uint32_t id;
+    uint32_t generation;
+};
+
+struct InstanceReservation {
+    uint32_t id;
+    uint32_t generation;
+};
+
 }  // namespace dawn::wire
 
 #endif  // INCLUDE_DAWN_WIRE_WIRE_H_
diff --git a/include/dawn/wire/WireClient.h b/include/dawn/wire/WireClient.h
index 5b0a3fa..ca7ea72 100644
--- a/include/dawn/wire/WireClient.h
+++ b/include/dawn/wire/WireClient.h
@@ -45,6 +45,8 @@
 
 struct ReservedTexture {
     WGPUTexture texture;
+    TextureReservation reservation;
+    // TODO(dawn:2021) Remove this once Chromium has been updated.
     uint32_t id;
     uint32_t generation;
     uint32_t deviceId;
@@ -53,22 +55,17 @@
 
 struct ReservedSwapChain {
     WGPUSwapChain swapchain;
-    uint32_t id;
-    uint32_t generation;
-    uint32_t deviceId;
-    uint32_t deviceGeneration;
+    SwapChainReservation reservation;
 };
 
 struct ReservedDevice {
     WGPUDevice device;
-    uint32_t id;
-    uint32_t generation;
+    DeviceReservation reservation;
 };
 
 struct ReservedInstance {
     WGPUInstance instance;
-    uint32_t id;
-    uint32_t generation;
+    InstanceReservation reservation;
 };
 
 struct DAWN_WIRE_EXPORT WireClientDescriptor {
diff --git a/include/dawn/wire/WireServer.h b/include/dawn/wire/WireServer.h
index ef08023..e5625cf 100644
--- a/include/dawn/wire/WireServer.h
+++ b/include/dawn/wire/WireServer.h
@@ -64,11 +64,14 @@
                          uint32_t generation,
                          uint32_t deviceId,
                          uint32_t deviceGeneration);
-
     bool InjectDevice(WGPUDevice device, uint32_t id, uint32_t generation);
-
     bool InjectInstance(WGPUInstance instance, uint32_t id, uint32_t generation);
 
+    bool InjectTexture(WGPUTexture texture, const TextureReservation& reservation);
+    bool InjectSwapChain(WGPUSwapChain texture, const SwapChainReservation& reservation);
+    bool InjectDevice(WGPUDevice device, const DeviceReservation& reservation);
+    bool InjectInstance(WGPUInstance instance, const InstanceReservation& reservation);
+
     // Look up a device by (id, generation) pair. Returns nullptr if the generation
     // has expired or the id is not found.
     // The Wire does not have destroy hooks to allow an embedder to observe when an object
diff --git a/src/dawn/fuzzers/DawnWireServerFuzzer.cpp b/src/dawn/fuzzers/DawnWireServerFuzzer.cpp
index 9ed53c8..3797267 100644
--- a/src/dawn/fuzzers/DawnWireServerFuzzer.cpp
+++ b/src/dawn/fuzzers/DawnWireServerFuzzer.cpp
@@ -136,7 +136,7 @@
     serverDesc.serializer = &devNull;
 
     std::unique_ptr<dawn::wire::WireServer> wireServer(new dawn::wire::WireServer(serverDesc));
-    wireServer->InjectInstance(sInstance->Get(), 1, 0);
+    wireServer->InjectInstance(sInstance->Get(), {1, 0});
     wireServer->HandleCommands(reinterpret_cast<const char*>(data), size);
 
     // Flush remaining callbacks to avoid memory leaks.
diff --git a/src/dawn/samples/SampleUtils.cpp b/src/dawn/samples/SampleUtils.cpp
index f1aa2a9..4b89cef 100644
--- a/src/dawn/samples/SampleUtils.cpp
+++ b/src/dawn/samples/SampleUtils.cpp
@@ -236,20 +236,16 @@
             procs = dawn::wire::client::GetProcs();
             s2cBuf->SetHandler(wireClient);
 
-            auto instanceReservation = wireClient->ReserveInstance();
-            wireServer->InjectInstance(instance->Get(), instanceReservation.id,
-                                       instanceReservation.generation);
+            auto reservedInstance = wireClient->ReserveInstance();
+            wireServer->InjectInstance(instance->Get(), reservedInstance.reservation);
 
-            auto deviceReservation = wireClient->ReserveDevice(instanceReservation.instance);
-            wireServer->InjectDevice(backendDevice, deviceReservation.id,
-                                     deviceReservation.generation);
-            cDevice = deviceReservation.device;
+            auto reservedDevice = wireClient->ReserveDevice(reservedInstance.instance);
+            wireServer->InjectDevice(backendDevice, reservedDevice.reservation);
+            cDevice = reservedDevice.device;
 
-            auto swapChainReservation = wireClient->ReserveSwapChain(cDevice, &swapChainDesc);
-            wireServer->InjectSwapChain(backendSwapChain, swapChainReservation.id,
-                                        swapChainReservation.generation, deviceReservation.id,
-                                        deviceReservation.generation);
-            swapChain = wgpu::SwapChain::Acquire(swapChainReservation.swapchain);
+            auto reservedSwapChain = wireClient->ReserveSwapChain(cDevice, &swapChainDesc);
+            wireServer->InjectSwapChain(backendSwapChain, reservedSwapChain.reservation);
+            swapChain = wgpu::SwapChain::Acquire(reservedSwapChain.swapchain);
         } break;
     }
 
diff --git a/src/dawn/tests/unittests/wire/WireCreatePipelineAsyncTests.cpp b/src/dawn/tests/unittests/wire/WireCreatePipelineAsyncTests.cpp
index 4106d36..e1c0490 100644
--- a/src/dawn/tests/unittests/wire/WireCreatePipelineAsyncTests.cpp
+++ b/src/dawn/tests/unittests/wire/WireCreatePipelineAsyncTests.cpp
@@ -298,10 +298,10 @@
 
     dawnProcSetProcs(&dawn::wire::client::GetProcs());
 
-    auto reservation = wireClient->ReserveInstance();
-    WGPUInstance instance = reservation.instance;
-    wireServer->InjectInstance(dawn::native::GetProcs().createInstance(nullptr), reservation.id,
-                               reservation.generation);
+    auto reserved = wireClient->ReserveInstance();
+    WGPUInstance instance = reserved.instance;
+    wireServer->InjectInstance(dawn::native::GetProcs().createInstance(nullptr),
+                               reserved.reservation);
 
     WGPURequestAdapterOptions adapterOptions = {};
     adapterOptions.backendType = WGPUBackendType_Null;
diff --git a/src/dawn/tests/unittests/wire/WireInjectDeviceTests.cpp b/src/dawn/tests/unittests/wire/WireInjectDeviceTests.cpp
index 5b0a92f..73d0733 100644
--- a/src/dawn/tests/unittests/wire/WireInjectDeviceTests.cpp
+++ b/src/dawn/tests/unittests/wire/WireInjectDeviceTests.cpp
@@ -47,18 +47,17 @@
 // Test that reserving and injecting a device makes calls on the client object forward to the
 // server object correctly.
 TEST_F(WireInjectDeviceTests, CallAfterReserveInject) {
-    ReservedDevice reservation = GetWireClient()->ReserveDevice(instance);
+    auto reserved = GetWireClient()->ReserveDevice(instance);
 
     WGPUDevice serverDevice = api.GetNewDevice();
     EXPECT_CALL(api, DeviceReference(serverDevice));
     EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice, _, _));
     EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice, _, _));
     EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice, _, _));
-    ASSERT_TRUE(
-        GetWireServer()->InjectDevice(serverDevice, reservation.id, reservation.generation));
+    ASSERT_TRUE(GetWireServer()->InjectDevice(serverDevice, reserved.reservation));
 
     WGPUBufferDescriptor bufferDesc = {};
-    wgpuDeviceCreateBuffer(reservation.device, &bufferDesc);
+    wgpuDeviceCreateBuffer(reserved.device, &bufferDesc);
     WGPUBuffer serverBuffer = api.GetNewBuffer();
     EXPECT_CALL(api, DeviceCreateBuffer(serverDevice, _)).WillOnce(Return(serverBuffer));
     FlushClient();
@@ -73,28 +72,26 @@
 
 // Test that reserve correctly returns different IDs each time.
 TEST_F(WireInjectDeviceTests, ReserveDifferentIDs) {
-    ReservedDevice reservation1 = GetWireClient()->ReserveDevice(instance);
-    ReservedDevice reservation2 = GetWireClient()->ReserveDevice(instance);
+    auto reserved1 = GetWireClient()->ReserveDevice(instance);
+    auto reserved2 = GetWireClient()->ReserveDevice(instance);
 
-    ASSERT_NE(reservation1.id, reservation2.id);
-    ASSERT_NE(reservation1.device, reservation2.device);
+    ASSERT_NE(reserved1.reservation.id, reserved2.reservation.id);
+    ASSERT_NE(reserved1.device, reserved2.device);
 }
 
 // Test that injecting the same id without a destroy first fails.
 TEST_F(WireInjectDeviceTests, InjectExistingID) {
-    ReservedDevice reservation = GetWireClient()->ReserveDevice(instance);
+    auto reserved = GetWireClient()->ReserveDevice(instance);
 
     WGPUDevice serverDevice = api.GetNewDevice();
     EXPECT_CALL(api, DeviceReference(serverDevice));
     EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice, _, _));
     EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice, _, _));
     EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice, _, _));
-    ASSERT_TRUE(
-        GetWireServer()->InjectDevice(serverDevice, reservation.id, reservation.generation));
+    ASSERT_TRUE(GetWireServer()->InjectDevice(serverDevice, reserved.reservation));
 
     // ID already in use, call fails.
-    ASSERT_FALSE(
-        GetWireServer()->InjectDevice(serverDevice, reservation.id, reservation.generation));
+    ASSERT_FALSE(GetWireServer()->InjectDevice(serverDevice, reserved.reservation));
 
     // Called on shutdown.
     EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice, nullptr, nullptr))
@@ -106,7 +103,7 @@
 
 // Test that the server only borrows the device and does a single reference-release
 TEST_F(WireInjectDeviceTests, InjectedDeviceLifetime) {
-    ReservedDevice reservation = GetWireClient()->ReserveDevice(instance);
+    auto reserved = GetWireClient()->ReserveDevice(instance);
 
     // Injecting the device adds a reference
     WGPUDevice serverDevice = api.GetNewDevice();
@@ -114,11 +111,10 @@
     EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice, _, _));
     EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice, _, _));
     EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice, _, _));
-    ASSERT_TRUE(
-        GetWireServer()->InjectDevice(serverDevice, reservation.id, reservation.generation));
+    ASSERT_TRUE(GetWireServer()->InjectDevice(serverDevice, reserved.reservation));
 
     // Releasing the device removes a single reference and clears its error callbacks.
-    wgpuDeviceRelease(reservation.device);
+    wgpuDeviceRelease(reserved.device);
     EXPECT_CALL(api, DeviceRelease(serverDevice));
     EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice, nullptr, nullptr)).Times(1);
     EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice, nullptr, nullptr)).Times(1);
@@ -133,26 +129,25 @@
 // Test that it is an error to get the primary queue of a device before it has been
 // injected on the server.
 TEST_F(WireInjectDeviceTests, GetQueueBeforeInject) {
-    ReservedDevice reservation = GetWireClient()->ReserveDevice(instance);
+    auto reserved = GetWireClient()->ReserveDevice(instance);
 
-    wgpuDeviceGetQueue(reservation.device);
+    wgpuDeviceGetQueue(reserved.device);
     FlushClient(false);
 }
 
 // Test that it is valid to get the primary queue of a device after it has been
 // injected on the server.
 TEST_F(WireInjectDeviceTests, GetQueueAfterInject) {
-    ReservedDevice reservation = GetWireClient()->ReserveDevice(instance);
+    auto reserved = GetWireClient()->ReserveDevice(instance);
 
     WGPUDevice serverDevice = api.GetNewDevice();
     EXPECT_CALL(api, DeviceReference(serverDevice));
     EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice, _, _));
     EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice, _, _));
     EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice, _, _));
-    ASSERT_TRUE(
-        GetWireServer()->InjectDevice(serverDevice, reservation.id, reservation.generation));
+    ASSERT_TRUE(GetWireServer()->InjectDevice(serverDevice, reserved.reservation));
 
-    wgpuDeviceGetQueue(reservation.device);
+    wgpuDeviceGetQueue(reserved.device);
 
     WGPUQueue apiQueue = api.GetNewQueue();
     EXPECT_CALL(api, DeviceGetQueue(serverDevice)).WillOnce(Return(apiQueue));
@@ -169,8 +164,8 @@
 // Test that the list of live devices can be reflected using GetDevice.
 TEST_F(WireInjectDeviceTests, ReflectLiveDevices) {
     // Reserve two devices.
-    ReservedDevice reservation1 = GetWireClient()->ReserveDevice(instance);
-    ReservedDevice reservation2 = GetWireClient()->ReserveDevice(instance);
+    auto reserved1 = GetWireClient()->ReserveDevice(instance);
+    auto reserved2 = GetWireClient()->ReserveDevice(instance);
 
     // Inject both devices.
 
@@ -179,23 +174,23 @@
     EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice1, _, _));
     EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice1, _, _));
     EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice1, _, _));
-    ASSERT_TRUE(
-        GetWireServer()->InjectDevice(serverDevice1, reservation1.id, reservation1.generation));
+    ASSERT_TRUE(GetWireServer()->InjectDevice(serverDevice1, reserved1.reservation));
 
     WGPUDevice serverDevice2 = api.GetNewDevice();
     EXPECT_CALL(api, DeviceReference(serverDevice2));
     EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice2, _, _));
     EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice2, _, _));
     EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice2, _, _));
-    ASSERT_TRUE(
-        GetWireServer()->InjectDevice(serverDevice2, reservation2.id, reservation2.generation));
+    ASSERT_TRUE(GetWireServer()->InjectDevice(serverDevice2, reserved2.reservation));
 
     // Test that both devices can be reflected.
-    ASSERT_EQ(serverDevice1, GetWireServer()->GetDevice(reservation1.id, reservation1.generation));
-    ASSERT_EQ(serverDevice2, GetWireServer()->GetDevice(reservation2.id, reservation2.generation));
+    ASSERT_EQ(serverDevice1, GetWireServer()->GetDevice(reserved1.reservation.id,
+                                                        reserved1.reservation.generation));
+    ASSERT_EQ(serverDevice2, GetWireServer()->GetDevice(reserved2.reservation.id,
+                                                        reserved2.reservation.generation));
 
     // Release the first device
-    wgpuDeviceRelease(reservation1.device);
+    wgpuDeviceRelease(reserved1.device);
     EXPECT_CALL(api, DeviceRelease(serverDevice1));
     EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice1, nullptr, nullptr)).Times(1);
     EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice1, nullptr, nullptr)).Times(1);
@@ -203,8 +198,10 @@
     FlushClient();
 
     // The first device should no longer reflect, but the second should
-    ASSERT_EQ(nullptr, GetWireServer()->GetDevice(reservation1.id, reservation1.generation));
-    ASSERT_EQ(serverDevice2, GetWireServer()->GetDevice(reservation2.id, reservation2.generation));
+    ASSERT_EQ(nullptr, GetWireServer()->GetDevice(reserved1.reservation.id,
+                                                  reserved1.reservation.generation));
+    ASSERT_EQ(serverDevice2, GetWireServer()->GetDevice(reserved2.reservation.id,
+                                                        reserved2.reservation.generation));
 
     // Called on shutdown.
     EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice2, nullptr, nullptr)).Times(1);
@@ -217,18 +214,16 @@
 // objects instead.
 TEST_F(WireInjectDeviceTests, TrackChildObjectsWithTwoReservedDevices) {
     // Reserve one device, inject it, and get the primary queue.
-    ReservedDevice reservation1 = GetWireClient()->ReserveDevice(instance);
+    auto reserved1 = GetWireClient()->ReserveDevice(instance);
 
     WGPUDevice serverDevice1 = api.GetNewDevice();
     EXPECT_CALL(api, DeviceReference(serverDevice1));
     EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice1, _, _));
     EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice1, _, _));
     EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice1, _, _));
-    ASSERT_TRUE(
-        GetWireServer()->InjectDevice(serverDevice1, reservation1.id, reservation1.generation));
+    ASSERT_TRUE(GetWireServer()->InjectDevice(serverDevice1, reserved1.reservation));
 
-    WGPUCommandEncoder commandEncoder =
-        wgpuDeviceCreateCommandEncoder(reservation1.device, nullptr);
+    WGPUCommandEncoder commandEncoder = wgpuDeviceCreateCommandEncoder(reserved1.device, nullptr);
 
     WGPUCommandEncoder serverCommandEncoder = api.GetNewCommandEncoder();
     EXPECT_CALL(api, DeviceCreateCommandEncoder(serverDevice1, _))
@@ -236,15 +231,14 @@
     FlushClient();
 
     // Reserve a second device, and inject it.
-    ReservedDevice reservation2 = GetWireClient()->ReserveDevice(instance);
+    auto reserved2 = GetWireClient()->ReserveDevice(instance);
 
     WGPUDevice serverDevice2 = api.GetNewDevice();
     EXPECT_CALL(api, DeviceReference(serverDevice2));
     EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(serverDevice2, _, _));
     EXPECT_CALL(api, OnDeviceSetLoggingCallback(serverDevice2, _, _));
     EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(serverDevice2, _, _));
-    ASSERT_TRUE(
-        GetWireServer()->InjectDevice(serverDevice2, reservation2.id, reservation2.generation));
+    ASSERT_TRUE(GetWireServer()->InjectDevice(serverDevice2, reserved2.reservation));
 
     // Release the encoder. This should work without error because it stores a stable
     // pointer to its device's list of child objects. On destruction, it removes itself from the
@@ -267,21 +261,21 @@
 TEST_F(WireInjectDeviceTests, ReclaimDeviceReservation) {
     // Test that doing a reservation and full release is an error.
     {
-        ReservedDevice reservation = GetWireClient()->ReserveDevice(instance);
-        wgpuDeviceRelease(reservation.device);
+        auto reserved = GetWireClient()->ReserveDevice(instance);
+        wgpuDeviceRelease(reserved.device);
         FlushClient(false);
     }
 
     // Test that doing a reservation and then reclaiming it recycles the ID.
     {
-        ReservedDevice reservation1 = GetWireClient()->ReserveDevice(instance);
-        GetWireClient()->ReclaimDeviceReservation(reservation1);
+        auto reserved1 = GetWireClient()->ReserveDevice(instance);
+        GetWireClient()->ReclaimDeviceReservation(reserved1);
 
-        ReservedDevice reservation2 = GetWireClient()->ReserveDevice(instance);
+        auto reserved2 = GetWireClient()->ReserveDevice(instance);
 
         // The ID is the same, but the generation is still different.
-        ASSERT_EQ(reservation1.id, reservation2.id);
-        ASSERT_NE(reservation1.generation, reservation2.generation);
+        ASSERT_EQ(reserved1.reservation.id, reserved2.reservation.id);
+        ASSERT_NE(reserved1.reservation.generation, reserved2.reservation.generation);
 
         // No errors should occur.
         FlushClient();
diff --git a/src/dawn/tests/unittests/wire/WireInjectInstanceTests.cpp b/src/dawn/tests/unittests/wire/WireInjectInstanceTests.cpp
index 43005fe..fedb0c7 100644
--- a/src/dawn/tests/unittests/wire/WireInjectInstanceTests.cpp
+++ b/src/dawn/tests/unittests/wire/WireInjectInstanceTests.cpp
@@ -46,15 +46,14 @@
 // Test that reserving and injecting an instance makes calls on the client object forward to the
 // server object correctly.
 TEST_F(WireInjectInstanceTests, CallAfterReserveInject) {
-    ReservedInstance reservation = GetWireClient()->ReserveInstance();
+    auto reserved = GetWireClient()->ReserveInstance();
 
     WGPUInstance serverInstance = api.GetNewInstance();
     EXPECT_CALL(api, InstanceReference(serverInstance));
-    ASSERT_TRUE(
-        GetWireServer()->InjectInstance(serverInstance, reservation.id, reservation.generation));
+    ASSERT_TRUE(GetWireServer()->InjectInstance(serverInstance, reserved.reservation));
 
     WGPUSurfaceDescriptor surfaceDesc = {};
-    wgpuInstanceCreateSurface(reservation.instance, &surfaceDesc);
+    wgpuInstanceCreateSurface(reserved.instance, &surfaceDesc);
     WGPUSurface serverSurface = api.GetNewSurface();
     EXPECT_CALL(api, InstanceCreateSurface(serverInstance, NotNull()))
         .WillOnce(Return(serverSurface));
@@ -63,39 +62,36 @@
 
 // Test that reserve correctly returns different IDs each time.
 TEST_F(WireInjectInstanceTests, ReserveDifferentIDs) {
-    ReservedInstance reservation1 = GetWireClient()->ReserveInstance();
-    ReservedInstance reservation2 = GetWireClient()->ReserveInstance();
+    auto reserved1 = GetWireClient()->ReserveInstance();
+    auto reserved2 = GetWireClient()->ReserveInstance();
 
-    ASSERT_NE(reservation1.id, reservation2.id);
-    ASSERT_NE(reservation1.instance, reservation2.instance);
+    ASSERT_NE(reserved1.reservation.id, reserved2.reservation.id);
+    ASSERT_NE(reserved1.instance, reserved2.instance);
 }
 
 // Test that injecting the same id fails.
 TEST_F(WireInjectInstanceTests, InjectExistingID) {
-    ReservedInstance reservation = GetWireClient()->ReserveInstance();
+    auto reserved = GetWireClient()->ReserveInstance();
 
     WGPUInstance serverInstance = api.GetNewInstance();
     EXPECT_CALL(api, InstanceReference(serverInstance));
-    ASSERT_TRUE(
-        GetWireServer()->InjectInstance(serverInstance, reservation.id, reservation.generation));
+    ASSERT_TRUE(GetWireServer()->InjectInstance(serverInstance, reserved.reservation));
 
     // ID already in use, call fails.
-    ASSERT_FALSE(
-        GetWireServer()->InjectInstance(serverInstance, reservation.id, reservation.generation));
+    ASSERT_FALSE(GetWireServer()->InjectInstance(serverInstance, reserved.reservation));
 }
 
 // Test that the server only borrows the instance and does a single reference-release
 TEST_F(WireInjectInstanceTests, InjectedInstanceLifetime) {
-    ReservedInstance reservation = GetWireClient()->ReserveInstance();
+    auto reserved = GetWireClient()->ReserveInstance();
 
     // Injecting the instance adds a reference
     WGPUInstance serverInstance = api.GetNewInstance();
     EXPECT_CALL(api, InstanceReference(serverInstance));
-    ASSERT_TRUE(
-        GetWireServer()->InjectInstance(serverInstance, reservation.id, reservation.generation));
+    ASSERT_TRUE(GetWireServer()->InjectInstance(serverInstance, reserved.reservation));
 
     // Releasing the instance removes a single reference.
-    wgpuInstanceRelease(reservation.instance);
+    wgpuInstanceRelease(reserved.instance);
     EXPECT_CALL(api, InstanceRelease(serverInstance));
     FlushClient();
 
@@ -109,21 +105,21 @@
 TEST_F(WireInjectInstanceTests, ReclaimInstanceReservation) {
     // Test that doing a reservation and full release is an error.
     {
-        ReservedInstance reservation = GetWireClient()->ReserveInstance();
-        wgpuInstanceRelease(reservation.instance);
+        auto reserved = GetWireClient()->ReserveInstance();
+        wgpuInstanceRelease(reserved.instance);
         FlushClient(false);
     }
 
     // Test that doing a reservation and then reclaiming it recycles the ID.
     {
-        ReservedInstance reservation1 = GetWireClient()->ReserveInstance();
-        GetWireClient()->ReclaimInstanceReservation(reservation1);
+        auto reserved1 = GetWireClient()->ReserveInstance();
+        GetWireClient()->ReclaimInstanceReservation(reserved1);
 
-        ReservedInstance reservation2 = GetWireClient()->ReserveInstance();
+        auto reserved2 = GetWireClient()->ReserveInstance();
 
         // The ID is the same, but the generation is still different.
-        ASSERT_EQ(reservation1.id, reservation2.id);
-        ASSERT_NE(reservation1.generation, reservation2.generation);
+        ASSERT_EQ(reserved1.reservation.id, reserved2.reservation.id);
+        ASSERT_NE(reserved1.reservation.generation, reserved2.reservation.generation);
 
         // No errors should occur.
         FlushClient();
diff --git a/src/dawn/tests/unittests/wire/WireInjectSwapChainTests.cpp b/src/dawn/tests/unittests/wire/WireInjectSwapChainTests.cpp
index e8975fa..7855b9c 100644
--- a/src/dawn/tests/unittests/wire/WireInjectSwapChainTests.cpp
+++ b/src/dawn/tests/unittests/wire/WireInjectSwapChainTests.cpp
@@ -54,57 +54,49 @@
 // Test that reserving and injecting a swapchain makes calls on the client object forward to the
 // server object correctly.
 TEST_F(WireInjectSwapChainTests, CallAfterReserveInject) {
-    ReservedSwapChain reservation = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
+    auto reserved = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
 
     WGPUSwapChain apiSwapchain = api.GetNewSwapChain();
     EXPECT_CALL(api, SwapChainReference(apiSwapchain));
-    ASSERT_TRUE(GetWireServer()->InjectSwapChain(apiSwapchain, reservation.id,
-                                                 reservation.generation, reservation.deviceId,
-                                                 reservation.deviceGeneration));
+    ASSERT_TRUE(GetWireServer()->InjectSwapChain(apiSwapchain, reserved.reservation));
 
-    wgpuSwapChainPresent(reservation.swapchain);
+    wgpuSwapChainPresent(reserved.swapchain);
     EXPECT_CALL(api, SwapChainPresent(apiSwapchain));
     FlushClient();
 }
 
 // Test that reserve correctly returns different IDs each time.
 TEST_F(WireInjectSwapChainTests, ReserveDifferentIDs) {
-    ReservedSwapChain reservation1 = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
-    ReservedSwapChain reservation2 = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
+    auto reserved1 = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
+    auto reserved2 = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
 
-    ASSERT_NE(reservation1.id, reservation2.id);
-    ASSERT_NE(reservation1.swapchain, reservation2.swapchain);
+    ASSERT_NE(reserved1.reservation.id, reserved2.reservation.id);
+    ASSERT_NE(reserved1.swapchain, reserved2.swapchain);
 }
 
 // Test that injecting the same id without a destroy first fails.
 TEST_F(WireInjectSwapChainTests, InjectExistingID) {
-    ReservedSwapChain reservation = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
+    auto reserved = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
 
     WGPUSwapChain apiSwapchain = api.GetNewSwapChain();
     EXPECT_CALL(api, SwapChainReference(apiSwapchain));
-    ASSERT_TRUE(GetWireServer()->InjectSwapChain(apiSwapchain, reservation.id,
-                                                 reservation.generation, reservation.deviceId,
-                                                 reservation.deviceGeneration));
+    ASSERT_TRUE(GetWireServer()->InjectSwapChain(apiSwapchain, reserved.reservation));
 
     // ID already in use, call fails.
-    ASSERT_FALSE(GetWireServer()->InjectSwapChain(apiSwapchain, reservation.id,
-                                                  reservation.generation, reservation.deviceId,
-                                                  reservation.deviceGeneration));
+    ASSERT_FALSE(GetWireServer()->InjectSwapChain(apiSwapchain, reserved.reservation));
 }
 
 // Test that the server only borrows the swapchain and does a single reference-release
 TEST_F(WireInjectSwapChainTests, InjectedSwapChainLifetime) {
-    ReservedSwapChain reservation = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
+    auto reserved = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
 
     // Injecting the swapchain adds a reference
     WGPUSwapChain apiSwapchain = api.GetNewSwapChain();
     EXPECT_CALL(api, SwapChainReference(apiSwapchain));
-    ASSERT_TRUE(GetWireServer()->InjectSwapChain(apiSwapchain, reservation.id,
-                                                 reservation.generation, reservation.deviceId,
-                                                 reservation.deviceGeneration));
+    ASSERT_TRUE(GetWireServer()->InjectSwapChain(apiSwapchain, reserved.reservation));
 
     // Releasing the swapchain removes a single reference.
-    wgpuSwapChainRelease(reservation.swapchain);
+    wgpuSwapChainRelease(reserved.swapchain);
     EXPECT_CALL(api, SwapChainRelease(apiSwapchain));
     FlushClient();
 
@@ -118,21 +110,21 @@
 TEST_F(WireInjectSwapChainTests, ReclaimSwapChainReservation) {
     // Test that doing a reservation and full release is an error.
     {
-        ReservedSwapChain reservation = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
-        wgpuSwapChainRelease(reservation.swapchain);
+        auto reserved = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
+        wgpuSwapChainRelease(reserved.swapchain);
         FlushClient(false);
     }
 
     // Test that doing a reservation and then reclaiming it recycles the ID.
     {
-        ReservedSwapChain reservation1 = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
-        GetWireClient()->ReclaimSwapChainReservation(reservation1);
+        auto reserved1 = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
+        GetWireClient()->ReclaimSwapChainReservation(reserved1);
 
-        ReservedSwapChain reservation2 = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
+        auto reserved2 = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
 
         // The ID is the same, but the generation is still different.
-        ASSERT_EQ(reservation1.id, reservation2.id);
-        ASSERT_NE(reservation1.generation, reservation2.generation);
+        ASSERT_EQ(reserved1.reservation.id, reserved2.reservation.id);
+        ASSERT_NE(reserved1.reservation.generation, reserved2.reservation.generation);
 
         // No errors should occur.
         FlushClient();
@@ -141,15 +133,13 @@
 
 // Test that the texture's reflection is correct for injected swapchains in the wire.
 TEST_F(WireInjectSwapChainTests, SwapChainTextureReflection) {
-    ReservedSwapChain reservation = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
+    auto reserved = GetWireClient()->ReserveSwapChain(device, &swapChainDesc);
 
     WGPUSwapChain apiSwapchain = api.GetNewSwapChain();
     EXPECT_CALL(api, SwapChainReference(apiSwapchain));
-    ASSERT_TRUE(GetWireServer()->InjectSwapChain(apiSwapchain, reservation.id,
-                                                 reservation.generation, reservation.deviceId,
-                                                 reservation.deviceGeneration));
+    ASSERT_TRUE(GetWireServer()->InjectSwapChain(apiSwapchain, reserved.reservation));
 
-    WGPUTexture tex = wgpuSwapChainGetCurrentTexture(reservation.swapchain);
+    WGPUTexture tex = wgpuSwapChainGetCurrentTexture(reserved.swapchain);
     WGPUTexture apiTex = api.GetNewTexture();
     EXPECT_CALL(api, SwapChainGetCurrentTexture(apiSwapchain)).WillOnce(Return(apiTex));
     FlushClient();
diff --git a/src/dawn/tests/unittests/wire/WireInjectTextureTests.cpp b/src/dawn/tests/unittests/wire/WireInjectTextureTests.cpp
index 2fbcfad..e2d1dbe 100644
--- a/src/dawn/tests/unittests/wire/WireInjectTextureTests.cpp
+++ b/src/dawn/tests/unittests/wire/WireInjectTextureTests.cpp
@@ -49,14 +49,13 @@
 // Test that reserving and injecting a texture makes calls on the client object forward to the
 // server object correctly.
 TEST_F(WireInjectTextureTests, CallAfterReserveInject) {
-    ReservedTexture reservation = GetWireClient()->ReserveTexture(device, &placeholderDesc);
+    auto reserved = GetWireClient()->ReserveTexture(device, &placeholderDesc);
 
     WGPUTexture apiTexture = api.GetNewTexture();
     EXPECT_CALL(api, TextureReference(apiTexture));
-    ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reservation.id, reservation.generation,
-                                               reservation.deviceId, reservation.deviceGeneration));
+    ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reserved.reservation));
 
-    wgpuTextureCreateView(reservation.texture, nullptr);
+    wgpuTextureCreateView(reserved.texture, nullptr);
     WGPUTextureView apiPlaceholderView = api.GetNewTextureView();
     EXPECT_CALL(api, TextureCreateView(apiTexture, nullptr)).WillOnce(Return(apiPlaceholderView));
     FlushClient();
@@ -64,81 +63,71 @@
 
 // Test that reserve correctly returns different IDs each time.
 TEST_F(WireInjectTextureTests, ReserveDifferentIDs) {
-    ReservedTexture reservation1 = GetWireClient()->ReserveTexture(device, &placeholderDesc);
-    ReservedTexture reservation2 = GetWireClient()->ReserveTexture(device, &placeholderDesc);
+    auto reserved1 = GetWireClient()->ReserveTexture(device, &placeholderDesc);
+    auto reserved2 = GetWireClient()->ReserveTexture(device, &placeholderDesc);
 
-    ASSERT_NE(reservation1.id, reservation2.id);
-    ASSERT_NE(reservation1.texture, reservation2.texture);
+    ASSERT_NE(reserved1.reservation.id, reserved2.reservation.id);
+    ASSERT_NE(reserved1.texture, reserved2.texture);
 }
 
 // Test that injecting the same id without a destroy first fails.
 TEST_F(WireInjectTextureTests, InjectExistingID) {
-    ReservedTexture reservation = GetWireClient()->ReserveTexture(device, &placeholderDesc);
+    auto reserved = GetWireClient()->ReserveTexture(device, &placeholderDesc);
 
     WGPUTexture apiTexture = api.GetNewTexture();
     EXPECT_CALL(api, TextureReference(apiTexture));
-    ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reservation.id, reservation.generation,
-                                               reservation.deviceId, reservation.deviceGeneration));
+    ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reserved.reservation));
 
     // ID already in use, call fails.
-    ASSERT_FALSE(GetWireServer()->InjectTexture(apiTexture, reservation.id, reservation.generation,
-                                                reservation.deviceId,
-                                                reservation.deviceGeneration));
+    ASSERT_FALSE(GetWireServer()->InjectTexture(apiTexture, reserved.reservation));
 }
 
 // Test that injecting the same id without a destroy first fails.
 TEST_F(WireInjectTextureTests, ReuseIDAndGeneration) {
     // Do this loop multiple times since the first time, we can't test `generation - 1` since
     // generation == 0.
-    ReservedTexture reservation;
+    ReservedTexture reserved;
     WGPUTexture apiTexture = nullptr;
     for (int i = 0; i < 2; ++i) {
-        reservation = GetWireClient()->ReserveTexture(device, &placeholderDesc);
+        reserved = GetWireClient()->ReserveTexture(device, &placeholderDesc);
 
         apiTexture = api.GetNewTexture();
         EXPECT_CALL(api, TextureReference(apiTexture));
-        ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reservation.id,
-                                                   reservation.generation, reservation.deviceId,
-                                                   reservation.deviceGeneration));
+        ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reserved.reservation));
 
         // Release the texture. It should be possible to reuse the ID now, but not the generation
-        wgpuTextureRelease(reservation.texture);
+        wgpuTextureRelease(reserved.texture);
         EXPECT_CALL(api, TextureRelease(apiTexture));
         FlushClient();
 
         // Invalid to inject with the same ID and generation.
-        ASSERT_FALSE(GetWireServer()->InjectTexture(apiTexture, reservation.id,
-                                                    reservation.generation, reservation.deviceId,
-                                                    reservation.deviceGeneration));
+        ASSERT_FALSE(GetWireServer()->InjectTexture(apiTexture, reserved.reservation));
         if (i > 0) {
-            EXPECT_GE(reservation.generation, 1u);
+            EXPECT_GE(reserved.reservation.generation, 1u);
 
             // Invalid to inject with the same ID and lesser generation.
-            ASSERT_FALSE(GetWireServer()->InjectTexture(
-                apiTexture, reservation.id, reservation.generation - 1, reservation.deviceId,
-                reservation.deviceGeneration));
+            reserved.reservation.generation -= 1;
+            ASSERT_FALSE(GetWireServer()->InjectTexture(apiTexture, reserved.reservation));
         }
     }
 
     // Valid to inject with the same ID and greater generation.
     EXPECT_CALL(api, TextureReference(apiTexture));
-    ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reservation.id,
-                                               reservation.generation + 1, reservation.deviceId,
-                                               reservation.deviceGeneration));
+    reserved.reservation.generation += 2;
+    ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reserved.reservation));
 }
 
 // Test that the server only borrows the texture and does a single reference-release
 TEST_F(WireInjectTextureTests, InjectedTextureLifetime) {
-    ReservedTexture reservation = GetWireClient()->ReserveTexture(device, &placeholderDesc);
+    auto reserved = GetWireClient()->ReserveTexture(device, &placeholderDesc);
 
     // Injecting the texture adds a reference
     WGPUTexture apiTexture = api.GetNewTexture();
     EXPECT_CALL(api, TextureReference(apiTexture));
-    ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reservation.id, reservation.generation,
-                                               reservation.deviceId, reservation.deviceGeneration));
+    ASSERT_TRUE(GetWireServer()->InjectTexture(apiTexture, reserved.reservation));
 
     // Releasing the texture removes a single reference.
-    wgpuTextureRelease(reservation.texture);
+    wgpuTextureRelease(reserved.texture);
     EXPECT_CALL(api, TextureRelease(apiTexture));
     FlushClient();
 
@@ -152,21 +141,21 @@
 TEST_F(WireInjectTextureTests, ReclaimTextureReservation) {
     // Test that doing a reservation and full release is an error.
     {
-        ReservedTexture reservation = GetWireClient()->ReserveTexture(device, &placeholderDesc);
-        wgpuTextureRelease(reservation.texture);
+        auto reserved = GetWireClient()->ReserveTexture(device, &placeholderDesc);
+        wgpuTextureRelease(reserved.texture);
         FlushClient(false);
     }
 
     // Test that doing a reservation and then reclaiming it recycles the ID.
     {
-        ReservedTexture reservation1 = GetWireClient()->ReserveTexture(device, &placeholderDesc);
-        GetWireClient()->ReclaimTextureReservation(reservation1);
+        auto reserved1 = GetWireClient()->ReserveTexture(device, &placeholderDesc);
+        GetWireClient()->ReclaimTextureReservation(reserved1);
 
-        ReservedTexture reservation2 = GetWireClient()->ReserveTexture(device, &placeholderDesc);
+        auto reserved2 = GetWireClient()->ReserveTexture(device, &placeholderDesc);
 
         // The ID is the same, but the generation is still different.
-        ASSERT_EQ(reservation1.id, reservation2.id);
-        ASSERT_NE(reservation1.generation, reservation2.generation);
+        ASSERT_EQ(reserved1.reservation.id, reserved2.reservation.id);
+        ASSERT_NE(reserved1.reservation.generation, reserved2.reservation.generation);
 
         // No errors should occur.
         FlushClient();
@@ -183,8 +172,8 @@
     desc.sampleCount = 3;
     desc.usage = WGPUTextureUsage_RenderAttachment;
 
-    ReservedTexture reservation = GetWireClient()->ReserveTexture(device, &desc);
-    WGPUTexture texture = reservation.texture;
+    auto reserved = GetWireClient()->ReserveTexture(device, &desc);
+    WGPUTexture texture = reserved.texture;
 
     ASSERT_EQ(desc.size.width, wgpuTextureGetWidth(texture));
     ASSERT_EQ(desc.size.height, wgpuTextureGetHeight(texture));
diff --git a/src/dawn/tests/unittests/wire/WireInstanceTests.cpp b/src/dawn/tests/unittests/wire/WireInstanceTests.cpp
index eb962e1..f2ae50b 100644
--- a/src/dawn/tests/unittests/wire/WireInstanceTests.cpp
+++ b/src/dawn/tests/unittests/wire/WireInstanceTests.cpp
@@ -55,13 +55,12 @@
 
 // Test that an Instance can be reserved and injected into the wire.
 TEST_F(WireInstanceBasicTest, ReserveAndInject) {
-    auto reservation = GetWireClient()->ReserveInstance();
-    wgpu::Instance instance = wgpu::Instance::Acquire(reservation.instance);
+    auto reserved = GetWireClient()->ReserveInstance();
+    wgpu::Instance instance = wgpu::Instance::Acquire(reserved.instance);
 
     WGPUInstance apiInstance = api.GetNewInstance();
     EXPECT_CALL(api, InstanceReference(apiInstance));
-    EXPECT_TRUE(
-        GetWireServer()->InjectInstance(apiInstance, reservation.id, reservation.generation));
+    EXPECT_TRUE(GetWireServer()->InjectInstance(apiInstance, reserved.reservation));
 
     instance = nullptr;
 
diff --git a/src/dawn/tests/unittests/wire/WireTest.cpp b/src/dawn/tests/unittests/wire/WireTest.cpp
index 479ebcc..48143a8 100644
--- a/src/dawn/tests/unittests/wire/WireTest.cpp
+++ b/src/dawn/tests/unittests/wire/WireTest.cpp
@@ -80,18 +80,17 @@
 
     dawnProcSetProcs(&dawn::wire::client::GetProcs());
 
-    auto instanceReservation = GetWireClient()->ReserveInstance();
-    instance = instanceReservation.instance;
+    auto reservedInstance = GetWireClient()->ReserveInstance();
+    instance = reservedInstance.instance;
     apiInstance = api.GetNewInstance();
     EXPECT_CALL(api, InstanceReference(apiInstance));
-    EXPECT_TRUE(GetWireServer()->InjectInstance(apiInstance, instanceReservation.id,
-                                                instanceReservation.generation));
+    EXPECT_TRUE(GetWireServer()->InjectInstance(apiInstance, reservedInstance.reservation));
 
-    auto deviceReservation = mWireClient->ReserveDevice(instance);
-    device = deviceReservation.device;
+    auto reservedDevice = mWireClient->ReserveDevice(instance);
+    device = reservedDevice.device;
     apiDevice = api.GetNewDevice();
     EXPECT_CALL(api, DeviceReference(apiDevice));
-    mWireServer->InjectDevice(apiDevice, deviceReservation.id, deviceReservation.generation);
+    mWireServer->InjectDevice(apiDevice, reservedDevice.reservation);
 
     // The GetQueue is done on WireClient startup so we expect it now.
     queue = wgpuDeviceGetQueue(device);
diff --git a/src/dawn/utils/WireHelper.cpp b/src/dawn/utils/WireHelper.cpp
index 39608fc..0854c20 100644
--- a/src/dawn/utils/WireHelper.cpp
+++ b/src/dawn/utils/WireHelper.cpp
@@ -140,10 +140,10 @@
                                     const WGPUInstanceDescriptor* wireDesc) override {
         DAWN_ASSERT(backendInstance != nullptr);
 
-        auto reservation = mWireClient->ReserveInstance(wireDesc);
-        mWireServer->InjectInstance(backendInstance, reservation.id, reservation.generation);
+        auto reserved = mWireClient->ReserveInstance(wireDesc);
+        mWireServer->InjectInstance(backendInstance, reserved.reservation);
 
-        return wgpu::Instance::Acquire(reservation.instance);
+        return wgpu::Instance::Acquire(reserved.instance);
     }
 
     void BeginWireTrace(const char* name) override {
diff --git a/src/dawn/wire/WireServer.cpp b/src/dawn/wire/WireServer.cpp
index ffffded..3f02396 100644
--- a/src/dawn/wire/WireServer.cpp
+++ b/src/dawn/wire/WireServer.cpp
@@ -48,7 +48,7 @@
                                uint32_t generation,
                                uint32_t deviceId,
                                uint32_t deviceGeneration) {
-    return mImpl->InjectTexture(texture, id, generation, deviceId, deviceGeneration) ==
+    return mImpl->InjectTexture(texture, {id, generation, deviceId, deviceGeneration}) ==
            WireResult::Success;
 }
 
@@ -57,16 +57,32 @@
                                  uint32_t generation,
                                  uint32_t deviceId,
                                  uint32_t deviceGeneration) {
-    return mImpl->InjectSwapChain(swapchain, id, generation, deviceId, deviceGeneration) ==
+    return mImpl->InjectSwapChain(swapchain, {id, generation, deviceId, deviceGeneration}) ==
            WireResult::Success;
 }
 
 bool WireServer::InjectDevice(WGPUDevice device, uint32_t id, uint32_t generation) {
-    return mImpl->InjectDevice(device, id, generation) == WireResult::Success;
+    return mImpl->InjectDevice(device, {id, generation}) == WireResult::Success;
 }
 
 bool WireServer::InjectInstance(WGPUInstance instance, uint32_t id, uint32_t generation) {
-    return mImpl->InjectInstance(instance, id, generation) == WireResult::Success;
+    return mImpl->InjectInstance(instance, {id, generation}) == WireResult::Success;
+}
+
+bool WireServer::InjectTexture(WGPUTexture texture, const TextureReservation& reservation) {
+    return mImpl->InjectTexture(texture, reservation) == WireResult::Success;
+}
+
+bool WireServer::InjectSwapChain(WGPUSwapChain swapchain, const SwapChainReservation& reservation) {
+    return mImpl->InjectSwapChain(swapchain, reservation) == WireResult::Success;
+}
+
+bool WireServer::InjectDevice(WGPUDevice device, const DeviceReservation& reservation) {
+    return mImpl->InjectDevice(device, reservation) == WireResult::Success;
+}
+
+bool WireServer::InjectInstance(WGPUInstance instance, const InstanceReservation& reservation) {
+    return mImpl->InjectInstance(instance, reservation) == WireResult::Success;
 }
 
 WGPUDevice WireServer::GetDevice(uint32_t id, uint32_t generation) {
diff --git a/src/dawn/wire/client/Client.cpp b/src/dawn/wire/client/Client.cpp
index 24e098a..128e46c 100644
--- a/src/dawn/wire/client/Client.cpp
+++ b/src/dawn/wire/client/Client.cpp
@@ -99,6 +99,11 @@
 
     ReservedTexture result;
     result.texture = ToAPI(texture);
+    result.reservation.id = texture->GetWireId();
+    result.reservation.generation = texture->GetWireGeneration();
+    result.reservation.deviceId = FromAPI(device)->GetWireId();
+    result.reservation.deviceGeneration = FromAPI(device)->GetWireGeneration();
+    // TODO(dawn:2021) Remove setting of deprecated fields once Chromium is updated.
     result.id = texture->GetWireId();
     result.generation = texture->GetWireGeneration();
     result.deviceId = FromAPI(device)->GetWireId();
@@ -112,10 +117,10 @@
 
     ReservedSwapChain result;
     result.swapchain = ToAPI(swapChain);
-    result.id = swapChain->GetWireId();
-    result.generation = swapChain->GetWireGeneration();
-    result.deviceId = FromAPI(device)->GetWireId();
-    result.deviceGeneration = FromAPI(device)->GetWireGeneration();
+    result.reservation.id = swapChain->GetWireId();
+    result.reservation.generation = swapChain->GetWireGeneration();
+    result.reservation.deviceId = FromAPI(device)->GetWireId();
+    result.reservation.deviceGeneration = FromAPI(device)->GetWireGeneration();
     return result;
 }
 
@@ -124,8 +129,8 @@
 
     ReservedDevice result;
     result.device = ToAPI(device);
-    result.id = device->GetWireId();
-    result.generation = device->GetWireGeneration();
+    result.reservation.id = device->GetWireId();
+    result.reservation.generation = device->GetWireGeneration();
     return result;
 }
 
@@ -134,7 +139,7 @@
 
     if (instance->Initialize(descriptor) != WireResult::Success) {
         Free(instance);
-        return {nullptr, 0, 0};
+        return {nullptr, {0, 0}};
     }
 
     // Reserve an EventManager for the given instance and make the association in the map.
@@ -143,8 +148,8 @@
 
     ReservedInstance result;
     result.instance = ToAPI(instance);
-    result.id = instance->GetWireId();
-    result.generation = instance->GetWireGeneration();
+    result.reservation.id = instance->GetWireId();
+    result.reservation.generation = instance->GetWireGeneration();
     return result;
 }
 
diff --git a/src/dawn/wire/server/Server.cpp b/src/dawn/wire/server/Server.cpp
index 048fa75..101e16b 100644
--- a/src/dawn/wire/server/Server.cpp
+++ b/src/dawn/wire/server/Server.cpp
@@ -56,23 +56,20 @@
     DestroyAllObjects(mProcs);
 }
 
-WireResult Server::InjectTexture(WGPUTexture texture,
-                                 uint32_t id,
-                                 uint32_t generation,
-                                 uint32_t deviceId,
-                                 uint32_t deviceGeneration) {
+WireResult Server::InjectTexture(WGPUTexture texture, const TextureReservation& reservation) {
     DAWN_ASSERT(texture != nullptr);
     Known<WGPUDevice> device;
-    WIRE_TRY(DeviceObjects().Get(deviceId, &device));
-    if (device->generation != deviceGeneration) {
+    WIRE_TRY(DeviceObjects().Get(reservation.deviceId, &device));
+    if (device->generation != reservation.deviceGeneration) {
         return WireResult::FatalError;
     }
 
     Known<WGPUTexture> data;
-    WIRE_TRY(TextureObjects().Allocate(&data, ObjectHandle{id, generation}));
+    WIRE_TRY(
+        TextureObjects().Allocate(&data, ObjectHandle{reservation.id, reservation.generation}));
 
     data->handle = texture;
-    data->generation = generation;
+    data->generation = reservation.generation;
     data->state = AllocationState::Allocated;
 
     // The texture is externally owned so it shouldn't be destroyed when we receive a destroy
@@ -83,22 +80,20 @@
 }
 
 WireResult Server::InjectSwapChain(WGPUSwapChain swapchain,
-                                   uint32_t id,
-                                   uint32_t generation,
-                                   uint32_t deviceId,
-                                   uint32_t deviceGeneration) {
+                                   const SwapChainReservation& reservation) {
     DAWN_ASSERT(swapchain != nullptr);
     Known<WGPUDevice> device;
-    WIRE_TRY(DeviceObjects().Get(deviceId, &device));
-    if (device->generation != deviceGeneration) {
+    WIRE_TRY(DeviceObjects().Get(reservation.deviceId, &device));
+    if (device->generation != reservation.deviceGeneration) {
         return WireResult::FatalError;
     }
 
     Known<WGPUSwapChain> data;
-    WIRE_TRY(SwapChainObjects().Allocate(&data, ObjectHandle{id, generation}));
+    WIRE_TRY(
+        SwapChainObjects().Allocate(&data, ObjectHandle{reservation.id, reservation.generation}));
 
     data->handle = swapchain;
-    data->generation = generation;
+    data->generation = reservation.generation;
     data->state = AllocationState::Allocated;
 
     // The texture is externally owned so it shouldn't be destroyed when we receive a destroy
@@ -108,13 +103,13 @@
     return WireResult::Success;
 }
 
-WireResult Server::InjectDevice(WGPUDevice device, uint32_t id, uint32_t generation) {
+WireResult Server::InjectDevice(WGPUDevice device, const DeviceReservation& reservation) {
     DAWN_ASSERT(device != nullptr);
     Known<WGPUDevice> data;
-    WIRE_TRY(DeviceObjects().Allocate(&data, ObjectHandle{id, generation}));
+    WIRE_TRY(DeviceObjects().Allocate(&data, ObjectHandle{reservation.id, reservation.generation}));
 
     data->handle = device;
-    data->generation = generation;
+    data->generation = reservation.generation;
     data->state = AllocationState::Allocated;
     data->info->server = this;
     data->info->self = data.AsHandle();
@@ -128,13 +123,14 @@
     return WireResult::Success;
 }
 
-WireResult Server::InjectInstance(WGPUInstance instance, uint32_t id, uint32_t generation) {
+WireResult Server::InjectInstance(WGPUInstance instance, const InstanceReservation& reservation) {
     DAWN_ASSERT(instance != nullptr);
     Known<WGPUInstance> data;
-    WIRE_TRY(InstanceObjects().Allocate(&data, ObjectHandle{id, generation}));
+    WIRE_TRY(
+        InstanceObjects().Allocate(&data, ObjectHandle{reservation.id, reservation.generation}));
 
     data->handle = instance;
-    data->generation = generation;
+    data->generation = reservation.generation;
     data->state = AllocationState::Allocated;
 
     // The instance is externally owned so it shouldn't be destroyed when we receive a destroy
diff --git a/src/dawn/wire/server/Server.h b/src/dawn/wire/server/Server.h
index bdb09b7..e3ee61c 100644
--- a/src/dawn/wire/server/Server.h
+++ b/src/dawn/wire/server/Server.h
@@ -172,21 +172,10 @@
     // ChunkedCommandHandler implementation
     const volatile char* HandleCommandsImpl(const volatile char* commands, size_t size) override;
 
-    WireResult InjectTexture(WGPUTexture texture,
-                             uint32_t id,
-                             uint32_t generation,
-                             uint32_t deviceId,
-                             uint32_t deviceGeneration);
-
-    WireResult InjectSwapChain(WGPUSwapChain swapchain,
-                               uint32_t id,
-                               uint32_t generation,
-                               uint32_t deviceId,
-                               uint32_t deviceGeneration);
-
-    WireResult InjectDevice(WGPUDevice device, uint32_t id, uint32_t generation);
-
-    WireResult InjectInstance(WGPUInstance instance, uint32_t id, uint32_t generation);
+    WireResult InjectTexture(WGPUTexture texture, const TextureReservation& reservation);
+    WireResult InjectSwapChain(WGPUSwapChain swapchain, const SwapChainReservation& reservation);
+    WireResult InjectDevice(WGPUDevice device, const DeviceReservation& reservation);
+    WireResult InjectInstance(WGPUInstance instance, const InstanceReservation& reservation);
 
     WGPUDevice GetDevice(uint32_t id, uint32_t generation);
     bool IsDeviceKnown(WGPUDevice device) const;