Make CompilationInfo extensible.

This adds overloads for WireCmd [De]serialization that don't take the
object id provider/resolvers and produce a fatal error as soon as an
object is encountered.

Bug: dawn:1186

Change-Id: I13e796a5d8f59c26279b9079d4496390506c739a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/68941
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Loko Kung <lokokung@google.com>
diff --git a/dawn.json b/dawn.json
index ada8ff6..25e3b4d 100644
--- a/dawn.json
+++ b/dawn.json
@@ -594,8 +594,7 @@
     },
     "compilation info": {
         "category": "structure",
-        "extensible": false,
-        "_TODO": "should be extensible, but need to make that work in wire: https://github.com/webgpu-native/webgpu-headers/issues/82",
+        "extensible": "in",
         "members": [
             {"name": "message count", "type": "uint32_t"},
             {"name": "messages", "type": "compilation message", "annotation": "const*", "length": "message count"}
@@ -603,7 +602,6 @@
     },
     "compilation info callback": {
         "category": "callback",
-        "tags": ["dawn"],
         "args": [
             {"name": "status", "type": "compilation info request status"},
             {"name": "compilation info", "type": "compilation info", "annotation": "const*"},
@@ -612,7 +610,6 @@
     },
     "compilation info request status": {
         "category": "enum",
-        "tags": ["dawn"],
         "values": [
             {"value": 0, "name": "success"},
             {"value": 1, "name": "error"},
@@ -622,8 +619,7 @@
     },
     "compilation message": {
         "category": "structure",
-        "extensible": false,
-        "_TODO": "should be extensible, but need to make that work in wire: https://github.com/webgpu-native/webgpu-headers/issues/82",
+        "extensible": "in",
         "members": [
             {"name": "message", "type": "char", "annotation": "const*", "length": "strlen", "optional": true},
             {"name": "type", "type": "compilation message type"},
@@ -1942,7 +1938,6 @@
         "methods": [
             {
                 "name": "get compilation info",
-                "tags": ["dawn"],
                 "args": [
                     {"name": "callback", "type": "compilation info callback"},
                     {"name": "userdata", "type": "void", "annotation": "*"}
diff --git a/generator/templates/dawn_wire/WireCmd.cpp b/generator/templates/dawn_wire/WireCmd.cpp
index e554a32..7df87c9 100644
--- a/generator/templates/dawn_wire/WireCmd.cpp
+++ b/generator/templates/dawn_wire/WireCmd.cpp
@@ -416,37 +416,63 @@
         return size;
     }
 
-    WireResult {{Cmd}}::Serialize(size_t commandSize, SerializeBuffer* buffer
-        {%- if command.may_have_dawn_object -%}
-            , const ObjectIdProvider& provider
-        {%- endif -%}
-    ) const {
-        {{Name}}Transfer* transfer;
-        WIRE_TRY(buffer->Next(&transfer));
-        transfer->commandSize = commandSize;
+    {% if command.may_have_dawn_object %}
+        WireResult {{Cmd}}::Serialize(
+            size_t commandSize,
+            SerializeBuffer* buffer,
+            const ObjectIdProvider& provider
+        ) const {
+            {{Name}}Transfer* transfer;
+            WIRE_TRY(buffer->Next(&transfer));
+            transfer->commandSize = commandSize;
+            return ({{Name}}Serialize(*this, transfer, buffer, provider));
+        }
+        WireResult {{Cmd}}::Serialize(size_t commandSize, SerializeBuffer* buffer) const {
+            ErrorObjectIdProvider provider;
+            return Serialize(commandSize, buffer, provider);
+        }
 
-        WIRE_TRY({{Name}}Serialize(*this, transfer, buffer
-            {%- if command.may_have_dawn_object -%}
-                , provider
-            {%- endif -%}
-        ));
-        return WireResult::Success;
-    }
+        WireResult {{Cmd}}::Deserialize(
+            DeserializeBuffer* deserializeBuffer,
+            DeserializeAllocator* allocator,
+            const ObjectIdResolver& resolver
+        ) {
+            const volatile {{Name}}Transfer* transfer;
+            WIRE_TRY(deserializeBuffer->Read(&transfer));
+            return {{Name}}Deserialize(this, transfer, deserializeBuffer, allocator, resolver);
+        }
+        WireResult {{Cmd}}::Deserialize(DeserializeBuffer* deserializeBuffer, DeserializeAllocator* allocator) {
+            ErrorObjectIdResolver resolver;
+            return Deserialize(deserializeBuffer, allocator, resolver);
+        }
+    {% else %}
+        WireResult {{Cmd}}::Serialize(size_t commandSize, SerializeBuffer* buffer) const {
+            {{Name}}Transfer* transfer;
+            WIRE_TRY(buffer->Next(&transfer));
+            transfer->commandSize = commandSize;
+            return ({{Name}}Serialize(*this, transfer, buffer));
+        }
+        WireResult {{Cmd}}::Serialize(
+            size_t commandSize,
+            SerializeBuffer* buffer,
+            const ObjectIdProvider&
+        ) const {
+            return Serialize(commandSize, buffer);
+        }
 
-    WireResult {{Cmd}}::Deserialize(DeserializeBuffer* deserializeBuffer, DeserializeAllocator* allocator
-        {%- if command.may_have_dawn_object -%}
-            , const ObjectIdResolver& resolver
-        {%- endif -%}
-    ) {
-        const volatile {{Name}}Transfer* transfer;
-        WIRE_TRY(deserializeBuffer->Read(&transfer));
-
-        return {{Name}}Deserialize(this, transfer, deserializeBuffer, allocator
-            {%- if command.may_have_dawn_object -%}
-                , resolver
-            {%- endif -%}
-        );
-    }
+        WireResult {{Cmd}}::Deserialize(DeserializeBuffer* deserializeBuffer, DeserializeAllocator* allocator) {
+            const volatile {{Name}}Transfer* transfer;
+            WIRE_TRY(deserializeBuffer->Read(&transfer));
+            return {{Name}}Deserialize(this, transfer, deserializeBuffer, allocator);
+        }
+        WireResult {{Cmd}}::Deserialize(
+            DeserializeBuffer* deserializeBuffer,
+            DeserializeAllocator* allocator,
+            const ObjectIdResolver&
+        ) {
+            return Deserialize(deserializeBuffer, allocator);
+        }
+    {% endif %}
 {% endmacro %}
 
 {% macro make_chained_struct_serialization_helpers(out=None) %}
diff --git a/generator/templates/dawn_wire/WireCmd.h b/generator/templates/dawn_wire/WireCmd.h
index c9b6c85..077dbf4 100644
--- a/generator/templates/dawn_wire/WireCmd.h
+++ b/generator/templates/dawn_wire/WireCmd.h
@@ -98,17 +98,9 @@
 
         //* Serialize the structure and everything it points to into serializeBuffer which must be
         //* big enough to contain all the data (as queried from GetRequiredSize).
-        {% if command.may_have_dawn_object %}
-            WireResult Serialize(size_t commandSize, SerializeBuffer* serializeBuffer, const ObjectIdProvider& objectIdProvider) const;
-        {% else %}
-            WireResult Serialize(size_t commandSize, SerializeBuffer* serializeBuffer) const;
-            // Override which drops the provider if it's not needed.
-            WireResult Serialize(size_t commandSize,
-                                 SerializeBuffer* serializeBuffer,
-                                 const ObjectIdProvider&) const {
-                return Serialize(commandSize, serializeBuffer);
-            }
-        {% endif %}
+        WireResult Serialize(size_t commandSize, SerializeBuffer* serializeBuffer, const ObjectIdProvider& objectIdProvider) const;
+        // Override which produces a FatalError if any object is used.
+        WireResult Serialize(size_t commandSize, SerializeBuffer* serializeBuffer) const;
 
         //* Deserializes the structure from a buffer, consuming a maximum of *size bytes. When this
         //* function returns, buffer and size will be updated by the number of bytes consumed to
@@ -117,11 +109,9 @@
         //* Deserialize returns:
         //*  - Success if everything went well (yay!)
         //*  - FatalError is something bad happened (buffer too small for example)
-        WireResult Deserialize(DeserializeBuffer* deserializeBuffer, DeserializeAllocator* allocator
-            {%- if command.may_have_dawn_object -%}
-                , const ObjectIdResolver& resolver
-            {%- endif -%}
-        );
+        WireResult Deserialize(DeserializeBuffer* deserializeBuffer, DeserializeAllocator* allocator, const ObjectIdResolver& resolver);
+        // Override which produces a FatalError if any object is used.
+        WireResult Deserialize(DeserializeBuffer* deserializeBuffer, DeserializeAllocator* allocator);
 
         {% if command.derived_method %}
             //* Command handlers want to know the object ID in addition to the backing object.
diff --git a/src/dawn_native/CompilationMessages.cpp b/src/dawn_native/CompilationMessages.cpp
index 326cb9b..70aae54 100644
--- a/src/dawn_native/CompilationMessages.cpp
+++ b/src/dawn_native/CompilationMessages.cpp
@@ -37,6 +37,7 @@
     }  // anonymous namespace
 
     OwnedCompilationMessages::OwnedCompilationMessages() {
+        mCompilationInfo.nextInChain = 0;
         mCompilationInfo.messageCount = 0;
         mCompilationInfo.messages = nullptr;
     }
@@ -51,8 +52,8 @@
         ASSERT(mCompilationInfo.messages == nullptr);
 
         mMessageStrings.push_back(message);
-        mMessages.push_back({nullptr, static_cast<WGPUCompilationMessageType>(type), lineNum,
-                             linePos, offset, length});
+        mMessages.push_back({nullptr, nullptr, static_cast<WGPUCompilationMessageType>(type),
+                             lineNum, linePos, offset, length});
     }
 
     void OwnedCompilationMessages::AddMessage(const tint::diag::Diagnostic& diagnostic) {
@@ -100,8 +101,8 @@
             mMessageStrings.push_back(diagnostic.message);
         }
 
-        mMessages.push_back({nullptr, tintSeverityToMessageType(diagnostic.severity), lineNum,
-                             linePos, offset, length});
+        mMessages.push_back({nullptr, nullptr, tintSeverityToMessageType(diagnostic.severity),
+                             lineNum, linePos, offset, length});
     }
 
     void OwnedCompilationMessages::AddMessages(const tint::diag::List& diagnostics) {
diff --git a/src/tests/unittests/wire/WireShaderModuleTests.cpp b/src/tests/unittests/wire/WireShaderModuleTests.cpp
index a999dff..d7d58d8 100644
--- a/src/tests/unittests/wire/WireShaderModuleTests.cpp
+++ b/src/tests/unittests/wire/WireShaderModuleTests.cpp
@@ -87,8 +87,10 @@
 TEST_F(WireShaderModuleTests, GetCompilationInfo) {
     wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockGetCompilationInfoCallback, nullptr);
 
-    WGPUCompilationMessage message = {"Test Message", WGPUCompilationMessageType_Info, 2, 4, 6, 8};
+    WGPUCompilationMessage message = {
+        nullptr, "Test Message", WGPUCompilationMessageType_Info, 2, 4, 6, 8};
     WGPUCompilationInfo compilationInfo;
+    compilationInfo.nextInChain = nullptr;
     compilationInfo.messageCount = 1;
     compilationInfo.messages = &message;
 
@@ -108,6 +110,7 @@
                          }
                          const WGPUCompilationMessage* infoMessage = &info->messages[0];
                          return strcmp(infoMessage->message, message.message) == 0 &&
+                                infoMessage->nextInChain == message.nextInChain &&
                                 infoMessage->type == message.type &&
                                 infoMessage->lineNum == message.lineNum &&
                                 infoMessage->linePos == message.linePos &&
@@ -124,8 +127,10 @@
 TEST_F(WireShaderModuleTests, GetCompilationInfoBeforeDisconnect) {
     wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockGetCompilationInfoCallback, nullptr);
 
-    WGPUCompilationMessage message = {"Test Message", WGPUCompilationMessageType_Info, 2, 4, 6, 8};
+    WGPUCompilationMessage message = {
+        nullptr, "Test Message", WGPUCompilationMessageType_Info, 2, 4, 6, 8};
     WGPUCompilationInfo compilationInfo;
+    compilationInfo.nextInChain = nullptr;
     compilationInfo.messageCount = 1;
     compilationInfo.messages = &message;
 
@@ -182,8 +187,10 @@
     wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockBufferMapCallbackWithNewRequests,
                                        &testData);
 
-    WGPUCompilationMessage message = {"Test Message", WGPUCompilationMessageType_Info, 2, 4, 6, 8};
+    WGPUCompilationMessage message = {
+        nullptr, "Test Message", WGPUCompilationMessageType_Info, 2, 4, 6, 8};
     WGPUCompilationInfo compilationInfo;
+    compilationInfo.nextInChain = nullptr;
     compilationInfo.messageCount = 1;
     compilationInfo.messages = &message;
 
@@ -207,8 +214,10 @@
     wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockBufferMapCallbackWithNewRequests,
                                        &testData);
 
-    WGPUCompilationMessage message = {"Test Message", WGPUCompilationMessageType_Info, 2, 4, 6, 8};
+    WGPUCompilationMessage message = {
+        nullptr, "Test Message", WGPUCompilationMessageType_Info, 2, 4, 6, 8};
     WGPUCompilationInfo compilationInfo;
+    compilationInfo.nextInChain = nullptr;
     compilationInfo.messageCount = 1;
     compilationInfo.messages = &message;
 
@@ -223,4 +232,4 @@
                 Call(WGPUCompilationInfoRequestStatus_Unknown, nullptr, _))
         .Times(1 + testData.numRequests);
     wgpuShaderModuleRelease(shaderModule);
-}
\ No newline at end of file
+}