Adds device-side cache key generation.

- Note that the device-side cache key will be prepended to object cache keys to prevent incompatible adapter/device cache clashes.
- Adds a new template file to auto=generate these cache serializers based on arguments.

Bug: dawn:549
Change-Id: I24b9d11eb38c579acfcc173a5dced9e1b649cf2c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/86081
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Loko Kung <lokokung@google.com>
diff --git a/generator/dawn_json_generator.py b/generator/dawn_json_generator.py
index 29c1be9..d02213d 100644
--- a/generator/dawn_json_generator.py
+++ b/generator/dawn_json_generator.py
@@ -955,6 +955,10 @@
                 FileRender('dawn/native/ObjectType.cpp',
                            'src/' + native_dir + '/ObjectType_autogen.cpp',
                            frontend_params))
+            renders.append(
+                FileRender('dawn/native/CacheKey.cpp',
+                           'src/' + native_dir + '/CacheKey_autogen.cpp',
+                           frontend_params))
 
         if 'wire' in targets:
             params_dawn_wire = parse_json(loaded_json,
diff --git a/generator/templates/dawn/native/CacheKey.cpp b/generator/templates/dawn/native/CacheKey.cpp
new file mode 100644
index 0000000..cf31449
--- /dev/null
+++ b/generator/templates/dawn/native/CacheKey.cpp
@@ -0,0 +1,68 @@
+//* Copyright 2022 The Dawn Authors
+//*
+//* Licensed under the Apache License, Version 2.0 (the "License");
+//* you may not use this file except in compliance with the License.
+//* You may obtain a copy of the License at
+//*
+//*     http://www.apache.org/licenses/LICENSE-2.0
+//*
+//* Unless required by applicable law or agreed to in writing, software
+//* distributed under the License is distributed on an "AS IS" BASIS,
+//* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//* See the License for the specific language governing permissions and
+//* limitations under the License.
+
+{% set impl_dir = metadata.impl_dir + "/" if metadata.impl_dir else "" %}
+{% set namespace_name = Name(metadata.native_namespace) %}
+{% set native_namespace = namespace_name.namespace_case() %}
+{% set native_dir = impl_dir + namespace_name.Dirs() %}
+{% set prefix = metadata.proc_table_prefix.lower() %}
+#include "{{native_dir}}/CacheKey.h"
+#include "{{native_dir}}/{{prefix}}_platform.h"
+
+#include <cstring>
+
+namespace {{native_namespace}} {
+
+//
+// Cache key serializers for wgpu structures used in caching.
+//
+{% macro render_serializer(member) %}
+    {%- set name = member.name.camelCase() -%}
+    {% if member.length == None %}
+        key->Record(t.{{name}});
+    {% elif member.length == "strlen" %}
+        key->RecordIterable(t.{{name}}, strlen(t.{{name}}));
+    {% else %}
+        key->RecordIterable(t.{{name}}, t.{{member.length.name.camelCase()}});
+    {% endif %}
+{% endmacro %}
+
+{# Helper macro to render serializers. Should be used in a call block to provide additional custom
+   handling when necessary. The optional `omit` field can be used to omit fields that are either
+   handled in the custom code, or unnecessary in the serialized output.
+   Example:
+       {% call render_cache_key_serializer("struct name", omits=["omit field"]) %}
+           // Custom C++ code to handle special types/members that are hard to generate code for
+       {% endcall %}
+#}
+{% macro render_cache_key_serializer(json_type, omits=[]) %}
+    {%- set cpp_type = types[json_type].name.CamelCase() -%}
+    template <>
+    void CacheKeySerializer<{{cpp_type}}>::Serialize(CacheKey* key, const {{cpp_type}}& t) {
+    {{ caller() }}
+    {% for member in types[json_type].members %}
+        {%- if not member.name.get() in omits %}
+                {{render_serializer(member)}}
+        {%- endif %}
+    {% endfor %}
+    }
+{% endmacro %}
+
+{% call render_cache_key_serializer("adapter properties") %}
+{% endcall %}
+
+{% call render_cache_key_serializer("dawn cache device descriptor") %}
+{% endcall %}
+
+} // namespace {{native_namespace}}