[dawn] Fix nullability of WGPUPipelineLayoutDescriptor.bindGroupLayouts

The 'optional': true on this member was setting it WGPU_NULLABLE, which
is technically true, but we don't do this for any of the other array
members. The 'optional' here actually meant something very different,
that the *inner* object was nullable, not that the array was nullable.
So renamed that to 'array_element_optional'.

Bug: 427657664
Change-Id: I92bfb4f7694d472ddd1a1d7ebe31aada360d003e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/249396
Reviewed-by: Loko Kung <lokokung@google.com>
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/generator/dawn_json_generator.py b/generator/dawn_json_generator.py
index ce1d16b..062d268 100644
--- a/generator/dawn_json_generator.py
+++ b/generator/dawn_json_generator.py
@@ -237,12 +237,14 @@
 # Methods and structures are both "records", so record members correspond to
 # method arguments or structure members.
 class RecordMember(AnnotatedTypedMember):
+
     def __init__(self,
                  name,
                  typ,
                  annotation,
                  json_data,
                  optional=False,
+                 array_element_optional=False,
                  is_return_value=False,
                  default_value=None,
                  skip_serialize=False):
@@ -250,6 +252,9 @@
         self.name = name
         self.length = None
         self.optional = optional
+        self.array_element_optional = array_element_optional
+        if array_element_optional:
+            assert annotation == 'const*', 'array_element_optional can only be used on array types'
         self.is_return_value = is_return_value
         self.handle_type = None
         self.id_type = None
@@ -440,6 +445,8 @@
                               m.get('annotation', 'value'),
                               m,
                               optional=m.get('optional', False),
+                              array_element_optional=m.get(
+                                  'array_element_optional', False),
                               is_return_value=m.get('is_return_value', False),
                               default_value=m.get('default', None),
                               skip_serialize=m.get('skip_serialize', False))
diff --git a/generator/templates/dawn/wire/WireCmd.cpp b/generator/templates/dawn/wire/WireCmd.cpp
index 16b5d90..f12db7f 100644
--- a/generator/templates/dawn/wire/WireCmd.cpp
+++ b/generator/templates/dawn/wire/WireCmd.cpp
@@ -54,35 +54,35 @@
 {%- endmacro -%}
 
 //* Outputs the type that will be used on the wire for the member
-{%- macro member_transfer_type(member) -%}
-    {%- if member.type.category == "object" -%}
+{%- macro member_transfer_type(type) -%}
+    {%- if type.category == "object" -%}
         ObjectId
-    {%- elif member.type.category == "structure" -%}
-        {{as_cType(member.type.name)}}Transfer
-    {%- elif as_cType(member.type.name) == "size_t" -%}
+    {%- elif type.category == "structure" -%}
+        {{as_cType(type.name)}}Transfer
+    {%- elif as_cType(type.name) == "size_t" -%}
         {{as_cType(types["uint64_t"].name)}}
     {%- else -%}
-        {%- do assert(member.type.is_wire_transparent, 'wire transparent') -%}
-        {{as_cType(member.type.name)}}
+        {%- do assert(type.is_wire_transparent, 'wire transparent') -%}
+        {{as_cType(type.name)}}
     {%- endif -%}
 {%- endmacro -%}
 
 //* Outputs the size of one element of the type that will be used on the wire for the member
-{%- macro member_transfer_sizeof(member) -%}
-    sizeof({{member_transfer_type(member)}})
+{%- macro member_transfer_sizeof(type) -%}
+    sizeof({{member_transfer_type(type)}})
 {%- endmacro -%}
 
 //* Outputs the serialization code to put `in` in `out`
-{%- macro serialize_member(member, in, out) -%}
-    {%- if member.type.category == "object" -%}
-        {%- set Optional = "Optional" if member.optional else "" -%}
+{%- macro serialize_member(type, optional, in, out) -%}
+    {%- if type.category == "object" -%}
+        {%- set Optional = "Optional" if optional else "" -%}
         WIRE_TRY(provider.Get{{Optional}}Id({{in}}, &{{out}}));
-    {%- elif member.type.category == "structure" -%}
+    {%- elif type.category == "structure" -%}
         //* Do not memcpy or we may serialize padding bytes which can leak information across a
         //* trusted boundary.
-        {%- set Provider = ", provider" if member.type.may_have_dawn_object else "" -%}
-        WIRE_TRY({{as_cType(member.type.name)}}Serialize({{in}}, &{{out}}, buffer{{Provider}}));
-    {%- elif not is_wire_serializable(member.type) -%}
+        {%- set Provider = ", provider" if type.may_have_dawn_object else "" -%}
+        WIRE_TRY({{as_cType(type.name)}}Serialize({{in}}, &{{out}}, buffer{{Provider}}));
+    {%- elif not is_wire_serializable(type) -%}
         if ({{in}} != nullptr) return WireResult::FatalError;
     {%- else -%}
         {{out}} = {{in}};
@@ -90,26 +90,26 @@
 {%- endmacro -%}
 
 //* Outputs the deserialization code to put `in` in `out`
-{%- macro deserialize_member(member, in, out) -%}
-    {%- if member.type.category == "object" -%}
-        {%- set Optional = "Optional" if member.optional else "" -%}
+{%- macro deserialize_member(type, optional, in, out) -%}
+    {%- if type.category == "object" -%}
+        {%- set Optional = "Optional" if optional else "" -%}
         WIRE_TRY(resolver.Get{{Optional}}FromId({{in}}, &{{out}}));
-    {%- elif member.type.category == "structure" %}
-        {% if member.type.is_wire_transparent %}
+    {%- elif type.category == "structure" %}
+        {% if type.is_wire_transparent %}
             static_assert(sizeof({{out}}) == sizeof({{in}}), "Deserialize memcpy size must match.");
-                memcpy(&{{out}}, const_cast<const {{member_transfer_type(member)}}*>(&{{in}}), {{member_transfer_sizeof(member)}});
+                memcpy(&{{out}}, const_cast<const {{member_transfer_type(type)}}*>(&{{in}}), {{member_transfer_sizeof(type)}});
         {%- else %}
-            WIRE_TRY({{as_cType(member.type.name)}}Deserialize(&{{out}}, &{{in}}, deserializeBuffer, allocator
-                {%- if member.type.may_have_dawn_object -%}
+            WIRE_TRY({{as_cType(type.name)}}Deserialize(&{{out}}, &{{in}}, deserializeBuffer, allocator
+                {%- if type.may_have_dawn_object -%}
                     , resolver
                 {%- endif -%}
             ));
         {%- endif -%}
-    {%- elif member.type.category == 'callback info' %}
-        {{out}} = WGPU_{{member.type.name.SNAKE_CASE()}}_INIT;
-    {%- elif not is_wire_serializable(member.type) %}
+    {%- elif type.category == 'callback info' %}
+        {{out}} = WGPU_{{type.name.SNAKE_CASE()}}_INIT;
+    {%- elif not is_wire_serializable(type) %}
         {{out}} = nullptr;
-    {%- elif member.type.name.get() == "size_t" -%}
+    {%- elif type.name.get() == "size_t" -%}
         //* Deserializing into size_t requires check that the uint64_t used on the wire won't narrow.
         if ({{in}} > std::numeric_limits<size_t>::max()) return WireResult::FatalError;
             {{out}} = checked_cast<size_t>({{in}});
@@ -149,7 +149,7 @@
             {% endif %}
             //* Value types are directly in the command, objects being replaced with their IDs.
             {% if member.annotation == "value" %}
-                {{member_transfer_type(member)}} {{as_varName(member.name)}};
+                {{member_transfer_type(member.type)}} {{as_varName(member.name)}};
                 {% continue %}
             {% endif %}
             //* Optional members additionally come with a boolean to indicate whether they were set.
@@ -209,7 +209,7 @@
                 {
                     {% do assert(member.annotation != "const*const*", "const*const* not valid here") %}
                     auto memberLength = {{member_length(member, "record.")}};
-                    auto size = WireAlignSizeofN<{{member_transfer_type(member)}}>(memberLength);
+                    auto size = WireAlignSizeofN<{{member_transfer_type(member.type)}}>(memberLength);
                     DAWN_ASSERT(size);
                     result += *size;
                     //* Structures might contain more pointers so we need to add their extra size as well.
@@ -295,7 +295,7 @@
             {% endif %}
             //* Value types are directly in the transfer record, objects being replaced with their IDs.
             {% if member.annotation == "value" %}
-                {{serialize_member(member, "record." + memberName, "transfer->" + memberName)}}
+                {{serialize_member(member.type, member.optional, "record." + memberName, "transfer->" + memberName)}}
                 {% continue %}
             {% endif %}
             //* Allocate space and write the non-value arguments in it.
@@ -309,7 +309,7 @@
             {% endif %}
                 auto memberLength = {{member_length(member, "record.")}};
 
-                {{member_transfer_type(member)}}* memberBuffer;
+                {{member_transfer_type(member.type)}}* memberBuffer;
                 WIRE_TRY(buffer->NextN(memberLength, &memberBuffer));
 
                 {% if member.type.is_wire_transparent %}
@@ -319,14 +319,14 @@
                     if (memberLength != 0) {
                         memcpy(
                             memberBuffer, record.{{memberName}},
-                            {{member_transfer_sizeof(member)}} * memberLength);
+                            {{member_transfer_sizeof(member.type)}} * memberLength);
                     }
                 {% else %}
                     //* This loop cannot overflow because it iterates up to |memberLength|. Even if
                     //* memberLength were the maximum integer value, |i| would become equal to it
                     //* just before exiting the loop, but not increment past or wrap around.
                     for (decltype(memberLength) i = 0; i < memberLength; ++i) {
-                        {{serialize_member(member, "record." + memberName + "[i]", "memberBuffer[i]" )}}
+                        {{serialize_member(member.type, member.array_element_optional, "record." + memberName + "[i]", "memberBuffer[i]" )}}
                     }
                 {% endif %}
             }
@@ -408,7 +408,7 @@
             {% set memberName = as_varName(member.name) %}
             //* Value types are directly in the transfer record, objects being replaced with their IDs.
             {% if member.annotation == "value" %}
-                {{deserialize_member(member, "transfer->" + memberName, "record->" + memberName)}}
+                {{deserialize_member(member.type, member.optional, "transfer->" + memberName, "record->" + memberName)}}
                 {% continue %}
             {% endif %}
             //* Get extra buffer data, and copy pointed to values in extra allocated space. Note that
@@ -428,7 +428,7 @@
                 {
             {% endif %}
                 auto memberLength = {{member_length(member, "record->")}};
-                const volatile {{member_transfer_type(member)}}* memberBuffer;
+                const volatile {{member_transfer_type(member.type)}}* memberBuffer;
                 WIRE_TRY(deserializeBuffer->ReadN(memberLength, &memberBuffer));
 
                 //* For data-only members (e.g. "data" in WriteBuffer and WriteTexture), they are
@@ -438,7 +438,7 @@
                 //* dawn_native must be a copy of what's in the wire.
                 {% if member.json_data["wire_is_data_only"] %}
                     record->{{memberName}} =
-                        const_cast<const {{member_transfer_type(member)}}*>(memberBuffer);
+                        const_cast<const {{member_transfer_type(member.type)}}*>(memberBuffer);
 
                 {% else %}
                     {{as_cType(member.type.name)}}* copiedMembers;
@@ -457,8 +457,8 @@
                             //* unexpected downstream effects.
                             memcpy(
                                 copiedMembers,
-                                const_cast<const {{member_transfer_type(member)}}*>(memberBuffer),
-                              {{member_transfer_sizeof(member)}} * memberLength);
+                                const_cast<const {{member_transfer_type(member.type)}}*>(memberBuffer),
+                              {{member_transfer_sizeof(member.type)}} * memberLength);
                         }
                     {% else %}
                         //* This loop cannot overflow because it iterates up to |memberLength|. Even
@@ -466,7 +466,7 @@
                         //* to it just before exiting the loop, but not increment past or wrap
                         //* around.
                         for (decltype(memberLength) i = 0; i < memberLength; ++i) {
-                            {{deserialize_member(member, "memberBuffer[i]", "copiedMembers[i]")}}
+                            {{deserialize_member(member.type, member.array_element_optional, "memberBuffer[i]", "copiedMembers[i]")}}
                         }
                     {% endif %}
                 {% endif %}
diff --git a/src/dawn/dawn.json b/src/dawn/dawn.json
index 173305c..836a33a 100644
--- a/src/dawn/dawn.json
+++ b/src/dawn/dawn.json
@@ -2661,7 +2661,7 @@
         "members": [
             {"name": "label", "type": "string view", "optional": true},
             {"name": "bind group layout count", "type": "size_t"},
-            {"name": "bind group layouts", "type": "bind group layout", "annotation": "const*", "length": "bind group layout count", "optional": true},
+            {"name": "bind group layouts", "type": "bind group layout", "annotation": "const*", "length": "bind group layout count", "array_element_optional": true},
             {"name": "immediate size", "type": "uint32_t", "default": 0}
         ]
     },
diff --git a/third_party/webgpu-headers/webgpu.h.diff b/third_party/webgpu-headers/webgpu.h.diff
index 76c6760..265d6ca 100644
--- a/third_party/webgpu-headers/webgpu.h.diff
+++ b/third_party/webgpu-headers/webgpu.h.diff
@@ -1,15 +1,6 @@
 --- webgpu_header
 +++ dawn_header
 @@
-     WGPUChainedStruct * nextInChain;
-     WGPUStringView label;
-     size_t bindGroupLayoutCount;
--    WGPUBindGroupLayout const * bindGroupLayouts;
-+    WGPU_NULLABLE WGPUBindGroupLayout const * bindGroupLayouts;
-     uint32_t immediateSize;
- } WGPUPipelineLayoutDescriptor WGPU_STRUCTURE_ATTRIBUTE;
- 
-@@
  typedef WGPUInstance (*WGPUProcCreateInstance)(WGPU_NULLABLE WGPUInstanceDescriptor const * descriptor) WGPU_FUNCTION_ATTRIBUTE;
  typedef void (*WGPUProcGetInstanceFeatures)(WGPUSupportedInstanceFeatures * features) WGPU_FUNCTION_ATTRIBUTE;
  typedef WGPUStatus (*WGPUProcGetInstanceLimits)(WGPUInstanceLimits * limits) WGPU_FUNCTION_ATTRIBUTE;