dawn_wire: Factor the common command serialization pattern.

Bug: dawn:445

Change-Id: I15a99a126c0494fd06dd727ff5c9008cde675d76
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/23560
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/generator/templates/dawn_wire/WireCmd.cpp b/generator/templates/dawn_wire/WireCmd.cpp
index 46a3d31..a914de1 100644
--- a/generator/templates/dawn_wire/WireCmd.cpp
+++ b/generator/templates/dawn_wire/WireCmd.cpp
@@ -380,7 +380,7 @@
     }
 
     void {{Cmd}}::Serialize(char* buffer
-        {%- if command.may_have_dawn_object -%}
+        {%- if not is_return -%}
             , const ObjectIdProvider& objectIdProvider
         {%- endif -%}
     ) const {
diff --git a/generator/templates/dawn_wire/WireCmd.h b/generator/templates/dawn_wire/WireCmd.h
index cdc146a..3a87795 100644
--- a/generator/templates/dawn_wire/WireCmd.h
+++ b/generator/templates/dawn_wire/WireCmd.h
@@ -102,7 +102,7 @@
         //* Serialize the structure and everything it points to into serializeBuffer which must be
         //* big enough to contain all the data (as queried from GetRequiredSize).
         void Serialize(char* serializeBuffer
-            {%- if command.may_have_dawn_object -%}
+            {%- if not is_return_command -%}
                 , const ObjectIdProvider& objectIdProvider
             {%- endif -%}
         ) const;
diff --git a/generator/templates/dawn_wire/client/ApiProcs.cpp b/generator/templates/dawn_wire/client/ApiProcs.cpp
index f33e5ed..a604a7f 100644
--- a/generator/templates/dawn_wire/client/ApiProcs.cpp
+++ b/generator/templates/dawn_wire/client/ApiProcs.cpp
@@ -196,9 +196,7 @@
                     {% endfor %}
 
                     //* Allocate space to send the command and copy the value args over.
-                    size_t requiredSize = cmd.GetRequiredSize();
-                    char* allocatedBuffer = static_cast<char*>(device->GetClient()->GetCmdSpace(requiredSize));
-                    cmd.Serialize(allocatedBuffer, *device->GetClient());
+                    device->GetClient()->SerializeCommand(cmd);
 
                     {% if method.return_type.category == "object" %}
                         return reinterpret_cast<{{as_cType(method.return_type.name)}}>(allocation->object.get());
@@ -226,10 +224,7 @@
                 cmd.objectType = ObjectType::{{type.name.CamelCase()}};
                 cmd.objectId = obj->id;
 
-                size_t requiredSize = cmd.GetRequiredSize();
-                char* allocatedBuffer = static_cast<char*>(obj->device->GetClient()->GetCmdSpace(requiredSize));
-                cmd.Serialize(allocatedBuffer);
-
+                obj->device->GetClient()->SerializeCommand(cmd);
                 obj->device->GetClient()->{{type.name.CamelCase()}}Allocator().Free(obj);
             }
 
diff --git a/src/dawn_wire/client/ApiProcs.cpp b/src/dawn_wire/client/ApiProcs.cpp
index 64f6f56..358e717 100644
--- a/src/dawn_wire/client/ApiProcs.cpp
+++ b/src/dawn_wire/client/ApiProcs.cpp
@@ -36,13 +36,11 @@
             cmd.handleCreateInfoLength = handleCreateInfoLength;
             cmd.handleCreateInfo = nullptr;
 
-            size_t commandSize = cmd.GetRequiredSize();
-            size_t requiredSize = commandSize + handleCreateInfoLength;
-            char* allocatedBuffer =
-                static_cast<char*>(buffer->device->GetClient()->GetCmdSpace(requiredSize));
-            cmd.Serialize(allocatedBuffer);
+            char* writeHandleSpace =
+                buffer->device->GetClient()->SerializeCommand(cmd, handleCreateInfoLength);
+
             // Serialize the handle into the space after the command.
-            handle->SerializeCreate(allocatedBuffer + commandSize);
+            handle->SerializeCreate(writeHandleSpace);
         }
     }  // namespace
 
@@ -155,9 +153,7 @@
         cmd.descriptor = descriptor;
         cmd.result = ObjectHandle{buffer->id, bufferObjectAndSerial->generation};
 
-        size_t requiredSize = cmd.GetRequiredSize();
-        char* allocatedBuffer = static_cast<char*>(wireClient->GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer, *wireClient);
+        wireClient->SerializeCommand(cmd);
 
         return reinterpret_cast<WGPUBuffer>(buffer);
     }
@@ -223,12 +219,11 @@
         cmd.handleCreateInfoLength = handleCreateInfoLength;
         cmd.handleCreateInfo = nullptr;
 
-        size_t commandSize = cmd.GetRequiredSize();
-        size_t requiredSize = commandSize + handleCreateInfoLength;
-        char* allocatedBuffer = static_cast<char*>(wireClient->GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer, *wireClient);
+        char* writeHandleSpace =
+            buffer->device->GetClient()->SerializeCommand(cmd, handleCreateInfoLength);
+
         // Serialize the WriteHandle into the space after the command.
-        buffer->writeHandle->SerializeCreate(allocatedBuffer + commandSize);
+        buffer->writeHandle->SerializeCreate(writeHandleSpace);
 
         return result;
     }
@@ -286,10 +281,7 @@
         cmd.count = count;
         cmd.data = static_cast<const uint8_t*>(data);
 
-        Client* wireClient = buffer->device->GetClient();
-        size_t requiredSize = cmd.GetRequiredSize();
-        char* allocatedBuffer = static_cast<char*>(wireClient->GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer);
+        buffer->device->GetClient()->SerializeCommand(cmd);
     }
 
     void ClientHandwrittenBufferUnmap(WGPUBuffer cBuffer) {
@@ -316,14 +308,12 @@
             cmd.writeFlushInfoLength = writeFlushInfoLength;
             cmd.writeFlushInfo = nullptr;
 
-            size_t commandSize = cmd.GetRequiredSize();
-            size_t requiredSize = commandSize + writeFlushInfoLength;
-            char* allocatedBuffer =
-                static_cast<char*>(buffer->device->GetClient()->GetCmdSpace(requiredSize));
-            cmd.Serialize(allocatedBuffer);
+            char* writeHandleSpace =
+                buffer->device->GetClient()->SerializeCommand(cmd, writeFlushInfoLength);
+
             // Serialize flush metadata into the space after the command.
             // This closes the handle for writing.
-            buffer->writeHandle->SerializeFlush(allocatedBuffer + commandSize);
+            buffer->writeHandle->SerializeFlush(writeHandleSpace);
             buffer->writeHandle = nullptr;
 
         } else if (buffer->readHandle) {
@@ -333,10 +323,7 @@
 
         BufferUnmapCmd cmd;
         cmd.self = cBuffer;
-        size_t requiredSize = cmd.GetRequiredSize();
-        char* allocatedBuffer =
-            static_cast<char*>(buffer->device->GetClient()->GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer, *buffer->device->GetClient());
+        buffer->device->GetClient()->SerializeCommand(cmd);
     }
 
     void ClientHandwrittenBufferDestroy(WGPUBuffer cBuffer) {
@@ -349,10 +336,7 @@
 
         BufferDestroyCmd cmd;
         cmd.self = cBuffer;
-        size_t requiredSize = cmd.GetRequiredSize();
-        char* allocatedBuffer =
-            static_cast<char*>(buffer->device->GetClient()->GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer, *buffer->device->GetClient());
+        buffer->device->GetClient()->SerializeCommand(cmd);
     }
 
     WGPUFence ClientHandwrittenQueueCreateFence(WGPUQueue cSelf,
@@ -366,9 +350,7 @@
         cmd.result = ObjectHandle{allocation->object->id, allocation->generation};
         cmd.descriptor = descriptor;
 
-        size_t requiredSize = cmd.GetRequiredSize();
-        char* allocatedBuffer = static_cast<char*>(device->GetClient()->GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer, *device->GetClient());
+        device->GetClient()->SerializeCommand(cmd);
 
         WGPUFence cFence = reinterpret_cast<WGPUFence>(allocation->object.get());
 
@@ -403,10 +385,7 @@
         cmd.fence = cFence;
         cmd.signalValue = signalValue;
 
-        size_t requiredSize = cmd.GetRequiredSize();
-        char* allocatedBuffer =
-            static_cast<char*>(fence->device->GetClient()->GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer, *fence->device->GetClient());
+        queue->device->GetClient()->SerializeCommand(cmd);
     }
 
     void ClientHandwrittenQueueWriteBuffer(WGPUQueue cQueue,
@@ -424,10 +403,7 @@
         cmd.data = static_cast<const uint8_t*>(data);
         cmd.size = size;
 
-        Client* wireClient = buffer->device->GetClient();
-        size_t requiredSize = cmd.GetRequiredSize();
-        char* allocatedBuffer = static_cast<char*>(wireClient->GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer);
+        queue->device->GetClient()->SerializeCommand(cmd);
     }
 
     void ClientDeviceReference(WGPUDevice) {
diff --git a/src/dawn_wire/client/Client.cpp b/src/dawn_wire/client/Client.cpp
index 9790d48..1953347 100644
--- a/src/dawn_wire/client/Client.cpp
+++ b/src/dawn_wire/client/Client.cpp
@@ -54,14 +54,14 @@
         return result;
     }
 
-    void* Client::GetCmdSpace(size_t size) {
+    char* Client::GetCmdSpace(size_t size) {
         if (DAWN_UNLIKELY(mIsDisconnected)) {
             if (size > mDummyCmdSpace.size()) {
                 mDummyCmdSpace.resize(size);
             }
             return mDummyCmdSpace.data();
         }
-        return mSerializer->GetCmdSpace(size);
+        return static_cast<char*>(mSerializer->GetCmdSpace(size));
     }
 
     void Client::Disconnect() {
diff --git a/src/dawn_wire/client/Client.h b/src/dawn_wire/client/Client.h
index 7769e33..d8df86d 100644
--- a/src/dawn_wire/client/Client.h
+++ b/src/dawn_wire/client/Client.h
@@ -42,13 +42,22 @@
         const volatile char* HandleCommands(const volatile char* commands, size_t size);
         ReservedTexture ReserveTexture(WGPUDevice device);
 
-        void* GetCmdSpace(size_t size);
+        template <typename Cmd>
+        char* SerializeCommand(const Cmd& cmd, size_t extraSize = 0) {
+            size_t requiredSize = cmd.GetRequiredSize();
+            // TODO(cwallez@chromium.org): Check for overflows and allocation success?
+            char* allocatedBuffer = GetCmdSpace(requiredSize + extraSize);
+            cmd.Serialize(allocatedBuffer, *this);
+            return allocatedBuffer + requiredSize;
+        }
 
         void Disconnect();
 
       private:
 #include "dawn_wire/client/ClientPrototypes_autogen.inc"
 
+        char* GetCmdSpace(size_t size);
+
         Device* mDevice = nullptr;
         CommandSerializer* mSerializer = nullptr;
         WireDeserializeAllocator mAllocator;
diff --git a/src/dawn_wire/client/Device.cpp b/src/dawn_wire/client/Device.cpp
index c69983a..43361b3 100644
--- a/src/dawn_wire/client/Device.cpp
+++ b/src/dawn_wire/client/Device.cpp
@@ -34,9 +34,7 @@
         cmd.self = reinterpret_cast<WGPUDevice>(this);
         cmd.result = ObjectHandle{allocation->object->id, allocation->generation};
 
-        size_t requiredSize = cmd.GetRequiredSize();
-        char* allocatedBuffer = static_cast<char*>(mClient->GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer, *mClient);
+        mClient->SerializeCommand(cmd);
     }
 
     Device::~Device() {
@@ -51,9 +49,7 @@
         cmd.objectType = ObjectType::Queue;
         cmd.objectId = mDefaultQueue->id;
 
-        size_t requiredSize = cmd.GetRequiredSize();
-        char* allocatedBuffer = static_cast<char*>(mClient->GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer);
+        mClient->SerializeCommand(cmd);
 
         mClient->QueueAllocator().Free(mDefaultQueue);
     }
@@ -92,10 +88,7 @@
         cmd.self = reinterpret_cast<WGPUDevice>(this);
         cmd.filter = filter;
 
-        Client* wireClient = GetClient();
-        size_t requiredSize = cmd.GetRequiredSize();
-        char* allocatedBuffer = static_cast<char*>(wireClient->GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer, *wireClient);
+        mClient->SerializeCommand(cmd);
     }
 
     bool Device::RequestPopErrorScope(WGPUErrorCallback callback, void* userdata) {
@@ -113,10 +106,7 @@
         cmd.device = reinterpret_cast<WGPUDevice>(this);
         cmd.requestSerial = serial;
 
-        Client* wireClient = GetClient();
-        size_t requiredSize = cmd.GetRequiredSize();
-        char* allocatedBuffer = static_cast<char*>(wireClient->GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer, *wireClient);
+        mClient->SerializeCommand(cmd);
 
         return true;
     }
diff --git a/src/dawn_wire/server/Server.cpp b/src/dawn_wire/server/Server.cpp
index 31b52dc..0199aba 100644
--- a/src/dawn_wire/server/Server.cpp
+++ b/src/dawn_wire/server/Server.cpp
@@ -39,8 +39,8 @@
         DestroyAllObjects(mProcs);
     }
 
-    void* Server::GetCmdSpace(size_t size) {
-        return mSerializer->GetCmdSpace(size);
+    char* Server::GetCmdSpace(size_t size) {
+        return static_cast<char*>(mSerializer->GetCmdSpace(size));
     }
 
     bool Server::InjectTexture(WGPUTexture texture, uint32_t id, uint32_t generation) {
diff --git a/src/dawn_wire/server/Server.h b/src/dawn_wire/server/Server.h
index effe69e..7dd0303 100644
--- a/src/dawn_wire/server/Server.h
+++ b/src/dawn_wire/server/Server.h
@@ -58,7 +58,15 @@
         bool InjectTexture(WGPUTexture texture, uint32_t id, uint32_t generation);
 
       private:
-        void* GetCmdSpace(size_t size);
+        template <typename Cmd>
+        char* SerializeCommand(const Cmd& cmd, size_t extraSize = 0) {
+            size_t requiredSize = cmd.GetRequiredSize();
+            // TODO(cwallez@chromium.org): Check for overflows and allocation success?
+            char* allocatedBuffer = GetCmdSpace(requiredSize + extraSize);
+            cmd.Serialize(allocatedBuffer);
+            return allocatedBuffer + requiredSize;
+        }
+        char* GetCmdSpace(size_t size);
 
         // Forwarding callbacks
         static void ForwardUncapturedError(WGPUErrorType type, const char* message, void* userdata);
diff --git a/src/dawn_wire/server/ServerBuffer.cpp b/src/dawn_wire/server/ServerBuffer.cpp
index 8498512..1b516f9 100644
--- a/src/dawn_wire/server/ServerBuffer.cpp
+++ b/src/dawn_wire/server/ServerBuffer.cpp
@@ -252,14 +252,11 @@
         cmd.initialDataInfoLength = initialDataInfoLength;
         cmd.initialDataInfo = nullptr;
 
-        size_t commandSize = cmd.GetRequiredSize();
-        size_t requiredSize = commandSize + initialDataInfoLength;
-        char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer);
+        char* readHandleSpace = SerializeCommand(cmd, initialDataInfoLength);
 
         if (status == WGPUBufferMapAsyncStatus_Success) {
             // Serialize the initialization message into the space after the command.
-            data->readHandle->SerializeInitialData(ptr, dataLength, allocatedBuffer + commandSize);
+            data->readHandle->SerializeInitialData(ptr, dataLength, readHandleSpace);
 
             // The in-flight map request returned successfully.
             // Move the ReadHandle so it is owned by the buffer.
@@ -284,9 +281,7 @@
         cmd.requestSerial = data->requestSerial;
         cmd.status = status;
 
-        size_t requiredSize = cmd.GetRequiredSize();
-        char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer);
+        SerializeCommand(cmd);
 
         if (status == WGPUBufferMapAsyncStatus_Success) {
             // The in-flight map request returned successfully.
diff --git a/src/dawn_wire/server/ServerDevice.cpp b/src/dawn_wire/server/ServerDevice.cpp
index 66c0d70..64ad1bb 100644
--- a/src/dawn_wire/server/ServerDevice.cpp
+++ b/src/dawn_wire/server/ServerDevice.cpp
@@ -31,18 +31,14 @@
         cmd.type = type;
         cmd.message = message;
 
-        size_t requiredSize = cmd.GetRequiredSize();
-        char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer);
+        SerializeCommand(cmd);
     }
 
     void Server::OnDeviceLost(const char* message) {
         ReturnDeviceLostCallbackCmd cmd;
         cmd.message = message;
 
-        size_t requiredSize = cmd.GetRequiredSize();
-        char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer);
+        SerializeCommand(cmd);
     }
 
     bool Server::DoDevicePopErrorScope(WGPUDevice cDevice, uint64_t requestSerial) {
@@ -73,9 +69,7 @@
         cmd.type = type;
         cmd.message = message;
 
-        size_t requiredSize = cmd.GetRequiredSize();
-        char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer);
+        SerializeCommand(cmd);
     }
 
 }}  // namespace dawn_wire::server
diff --git a/src/dawn_wire/server/ServerFence.cpp b/src/dawn_wire/server/ServerFence.cpp
index de056a1..1a4105c 100644
--- a/src/dawn_wire/server/ServerFence.cpp
+++ b/src/dawn_wire/server/ServerFence.cpp
@@ -35,9 +35,7 @@
         cmd.fence = data->fence;
         cmd.value = data->value;
 
-        size_t requiredSize = cmd.GetRequiredSize();
-        char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize));
-        cmd.Serialize(allocatedBuffer);
+        SerializeCommand(cmd);
     }
 
 }}  // namespace dawn_wire::server