Make the C++ api header-only

The goal is to make it much easier to use alternative C++ wrappers
(in different namespaces) that may wrap dawn::native or dawn::wire
directly.

Across Chrome, in  //gpu, Skia, and Dawn, this change has a zero-sized
net impact on Android binary size.

This change caught some BUILD.gn issues where the samples depended on
dawn:proc_shared when their deps also depended on dawn:proc(static),
leading to duplicate symbol collisions.

Bug: chromium:40195122
Change-Id: I873776464c5017b7a439acf03a8a6274cd91badf
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/175947
Auto-Submit: Austin Eng <enga@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/docs/dawn/codegen.md b/docs/dawn/codegen.md
index 4293887..47702db 100644
--- a/docs/dawn/codegen.md
+++ b/docs/dawn/codegen.md
@@ -11,7 +11,7 @@
 At this time it is used to generate:
 
  - the Dawn, Emscripten, and upstream webgpu-native `webgpu.h` C header
- - the Dawn and Emscripten `webgpu_cpp.cpp/h` C++ wrapper over the C header
+ - the Dawn and Emscripten `webgpu_cpp.h` C++ wrapper over the C header
  - libraries that implements `webgpu.h` by calling in a static or `thread_local` proc table
  - other parts of the [Emscripten](https://emscripten.org/) WebGPU implementation
  - a GMock version of the API with its proc table for testing
diff --git a/generator/dawn_json_generator.py b/generator/dawn_json_generator.py
index d6e2091..bb27818 100644
--- a/generator/dawn_json_generator.py
+++ b/generator/dawn_json_generator.py
@@ -1079,11 +1079,6 @@
                            'src/dawn/native/webgpu_dawn_native_proc.cpp',
                            [RENDER_PARAMS_BASE, params_dawn]))
 
-        if 'cpp' in targets:
-            renders.append(
-                FileRender('api_cpp.cpp', 'src/dawn/' + api + '_cpp.cpp',
-                           [RENDER_PARAMS_BASE, params_dawn]))
-
         if 'webgpu_headers' in targets:
             params_upstream = parse_json(loaded_json,
                                          enabled_tags=['upstream', 'native'],
@@ -1111,11 +1106,6 @@
                     'api_cpp_chained_struct.h',
                     'emscripten-bits/system/include/webgpu/webgpu_cpp_chained_struct.h',
                     [RENDER_PARAMS_BASE, params_emscripten]))
-            # system/lib/webgpu
-            renders.append(
-                FileRender('api_cpp.cpp',
-                           'emscripten-bits/system/lib/webgpu/webgpu_cpp.cpp',
-                           [RENDER_PARAMS_BASE, params_emscripten]))
             # Snippets to paste into existing Emscripten files
             renders.append(
                 FileRender('api_struct_info.json',
diff --git a/generator/templates/api_cpp.cpp b/generator/templates/api_cpp.cpp
index d534984..e69de29 100644
--- a/generator/templates/api_cpp.cpp
+++ b/generator/templates/api_cpp.cpp
@@ -1,251 +0,0 @@
-//* Copyright 2017 The Dawn & Tint Authors
-//*
-//* Redistribution and use in source and binary forms, with or without
-//* modification, are permitted provided that the following conditions are met:
-//*
-//* 1. Redistributions of source code must retain the above copyright notice, this
-//*    list of conditions and the following disclaimer.
-//*
-//* 2. Redistributions in binary form must reproduce the above copyright notice,
-//*    this list of conditions and the following disclaimer in the documentation
-//*    and/or other materials provided with the distribution.
-//*
-//* 3. Neither the name of the copyright holder nor the names of its
-//*    contributors may be used to endorse or promote products derived from
-//*    this software without specific prior written permission.
-//*
-//* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-//* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-//* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-//* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-//* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-//* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-//* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-//* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-//* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-//* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include <utility>
-
-{% set api = metadata.api.lower() %}
-{% if 'dawn' in enabled_tags %}
-    #include "dawn/{{api}}_cpp.h"
-{% else %}
-    #include "{{api}}/{{api}}_cpp.h"
-{% endif %}
-
-#if defined(__GNUC__) || defined(__clang__)
-// error: 'offsetof' within non-standard-layout type '{{metadata.namespace}}::XXX' is conditionally-supported
-#pragma GCC diagnostic ignored "-Winvalid-offsetof"
-#endif
-
-namespace {{metadata.namespace}} {
-    {% for type in by_category["enum"] %}
-        {% set CppType = as_cppType(type.name) %}
-        {% set CType = as_cType(type.name) %}
-
-        // {{CppType}}
-
-        static_assert(sizeof({{CppType}}) == sizeof({{CType}}), "sizeof mismatch for {{CppType}}");
-        static_assert(alignof({{CppType}}) == alignof({{CType}}), "alignof mismatch for {{CppType}}");
-
-        {% for value in type.values %}
-            static_assert(static_cast<uint32_t>({{CppType}}::{{as_cppEnum(value.name)}}) == {{as_cEnum(type.name, value.name)}}, "value mismatch for {{CppType}}::{{as_cppEnum(value.name)}}");
-        {% endfor %}
-    {% endfor -%}
-
-    {% for type in by_category["bitmask"] %}
-        {% set CppType = as_cppType(type.name) %}
-        {% set CType = as_cType(type.name) + "Flags" %}
-
-        // {{CppType}}
-
-        static_assert(sizeof({{CppType}}) == sizeof({{CType}}), "sizeof mismatch for {{CppType}}");
-        static_assert(alignof({{CppType}}) == alignof({{CType}}), "alignof mismatch for {{CppType}}");
-
-        {% for value in type.values %}
-            static_assert(static_cast<uint32_t>({{CppType}}::{{as_cppEnum(value.name)}}) == {{as_cEnum(type.name, value.name)}}, "value mismatch for {{CppType}}::{{as_cppEnum(value.name)}}");
-        {% endfor %}
-    {% endfor %}
-
-    // ChainedStruct
-
-    {% set c_prefix = metadata.c_prefix %}
-    static_assert(sizeof(ChainedStruct) == sizeof({{c_prefix}}ChainedStruct),
-            "sizeof mismatch for ChainedStruct");
-    static_assert(alignof(ChainedStruct) == alignof({{c_prefix}}ChainedStruct),
-            "alignof mismatch for ChainedStruct");
-    static_assert(offsetof(ChainedStruct, nextInChain) == offsetof({{c_prefix}}ChainedStruct, next),
-            "offsetof mismatch for ChainedStruct::nextInChain");
-    static_assert(offsetof(ChainedStruct, sType) == offsetof({{c_prefix}}ChainedStruct, sType),
-            "offsetof mismatch for ChainedStruct::sType");
-    {% for type in by_category["structure"] %}
-        {% set CppType = as_cppType(type.name) %}
-        {% set CType = as_cType(type.name) %}
-
-        // {{CppType}}
-
-        static_assert(sizeof({{CppType}}) == sizeof({{CType}}), "sizeof mismatch for {{CppType}}");
-        static_assert(alignof({{CppType}}) == alignof({{CType}}), "alignof mismatch for {{CppType}}");
-
-        {% if type.extensible %}
-            static_assert(offsetof({{CppType}}, nextInChain) == offsetof({{CType}}, nextInChain),
-                    "offsetof mismatch for {{CppType}}::nextInChain");
-        {% endif %}
-        {% for member in type.members %}
-            {% set memberName = member.name.camelCase() %}
-            static_assert(offsetof({{CppType}}, {{memberName}}) == offsetof({{CType}}, {{memberName}}),
-                    "offsetof mismatch for {{CppType}}::{{memberName}}");
-        {% endfor %}
-    {% endfor -%}
-
-    {%- macro render_c_actual_arg(arg) -%}
-        {%- if arg.annotation == "value" -%}
-            {%- if arg.type.category == "object" -%}
-                {{as_varName(arg.name)}}.Get()
-            {%- elif arg.type.category == "enum" or arg.type.category == "bitmask" -%}
-                static_cast<{{as_cType(arg.type.name)}}>({{as_varName(arg.name)}})
-            {%- elif arg.type.category == "structure" -%}
-                *reinterpret_cast<{{as_cType(arg.type.name)}} const*>(&{{as_varName(arg.name)}})
-            {%- elif arg.type.category in ["function pointer", "native"] -%}
-                {{as_varName(arg.name)}}
-            {%- else -%}
-                UNHANDLED
-            {%- endif -%}
-        {%- else -%}
-            reinterpret_cast<{{decorate("", as_cType(arg.type.name), arg)}}>({{as_varName(arg.name)}})
-        {%- endif -%}
-    {%- endmacro -%}
-
-    template <typename T>
-    static T& AsNonConstReference(const T& value) {
-        return const_cast<T&>(value);
-    }
-
-    {% for type in by_category["structure"] if type.has_free_members_function %}
-        // {{as_cppType(type.name)}}
-        {{as_cppType(type.name)}}::~{{as_cppType(type.name)}}() {
-            if (
-                {%- for member in type.members if member.annotation != 'value' %}
-                    {% if not loop.first %} || {% endif -%}
-                    this->{{member.name.camelCase()}} != nullptr
-                {%- endfor -%}
-            ) {
-                {{as_cMethod(type.name, Name("free members"))}}(
-                    *reinterpret_cast<{{as_cType(type.name)}}*>(this));
-            }
-        }
-
-        static void Reset({{as_cppType(type.name)}}& value) {
-            {{as_cppType(type.name)}} defaultValue{};
-            {% for member in type.members %}
-                AsNonConstReference(value.{{member.name.camelCase()}}) = defaultValue.{{member.name.camelCase()}};
-            {% endfor %}
-        }
-
-        {{as_cppType(type.name)}}::{{as_cppType(type.name)}}({{as_cppType(type.name)}}&& rhs)
-        : {% for member in type.members %}
-            {%- set memberName = member.name.camelCase() -%}
-            {{memberName}}(rhs.{{memberName}}){% if not loop.last %},{{"\n      "}}{% endif %}
-        {% endfor -%}
-        {
-            Reset(rhs);
-        }
-
-        {{as_cppType(type.name)}}& {{as_cppType(type.name)}}::operator=({{as_cppType(type.name)}}&& rhs) {
-            if (&rhs == this) {
-                return *this;
-            }
-            this->~{{as_cppType(type.name)}}();
-            {% for member in type.members %}
-                AsNonConstReference(this->{{member.name.camelCase()}}) = std::move(rhs.{{member.name.camelCase()}});
-            {% endfor %}
-            Reset(rhs);
-            return *this;
-        }
-
-    {% endfor %}
-
-    {% for type in by_category["object"] %}
-        {% set CppType = as_cppType(type.name) %}
-        {% set CType = as_cType(type.name) %}
-
-        // {{CppType}}
-
-        static_assert(sizeof({{CppType}}) == sizeof({{CType}}), "sizeof mismatch for {{CppType}}");
-        static_assert(alignof({{CppType}}) == alignof({{CType}}), "alignof mismatch for {{CppType}}");
-
-        {% macro render_cpp_method_declaration(type, method) -%}
-            {% set CppType = as_cppType(type.name) %}
-            {% set OriginalMethodName = method.name.CamelCase() %}
-            {% set MethodName = OriginalMethodName[:-1] if method.name.chunks[-1] == "f" else OriginalMethodName %}
-            {{as_cppType(method.return_type.name)}} {{CppType}}::{{MethodName}}(
-                {%- for arg in method.arguments -%}
-                    {%- if not loop.first %}, {% endif -%}
-                    {%- if arg.type.category == "object" and arg.annotation == "value" -%}
-                        {{as_cppType(arg.type.name)}} const& {{as_varName(arg.name)}}
-                    {%- else -%}
-                        {{as_annotated_cppType(arg)}}
-                    {%- endif -%}
-                {%- endfor -%}
-            ) const
-        {%- endmacro -%}
-
-        {%- macro render_cpp_to_c_method_call(type, method) -%}
-            {{as_cMethod(type.name, method.name)}}(Get()
-                {%- for arg in method.arguments -%},{{" "}}{{render_c_actual_arg(arg)}}
-                {%- endfor -%}
-            )
-        {%- endmacro -%}
-
-        {% for method in type.methods -%}
-            {{render_cpp_method_declaration(type, method)}} {
-                {% for arg in method.arguments if arg.type.has_free_members_function and arg.annotation == '*' %}
-                    *{{as_varName(arg.name)}} = {{as_cppType(arg.type.name)}}();
-                {% endfor %}
-                {% if method.return_type.name.concatcase() == "void" %}
-                    {{render_cpp_to_c_method_call(type, method)}};
-                {% else %}
-                    auto result = {{render_cpp_to_c_method_call(type, method)}};
-                    return {{convert_cType_to_cppType(method.return_type, 'value', 'result') | indent(8)}};
-                {% endif %}
-            }
-        {% endfor %}
-        void {{CppType}}::{{c_prefix}}Reference({{CType}} handle) {
-            if (handle != nullptr) {
-                {{as_cMethod(type.name, Name("reference"))}}(handle);
-            }
-        }
-        void {{CppType}}::{{c_prefix}}Release({{CType}} handle) {
-            if (handle != nullptr) {
-                {{as_cMethod(type.name, Name("release"))}}(handle);
-            }
-        }
-    {% endfor %}
-
-    // Function
-
-    {% for function in by_category["function"] if not function.no_cpp %}
-        {%- macro render_function_call(function) -%}
-            {{as_cMethod(None, function.name)}}(
-                {%- for arg in function.arguments -%}
-                    {% if not loop.first %}, {% endif %}{{render_c_actual_arg(arg)}}
-                {%- endfor -%}
-            )
-        {%- endmacro -%}
-
-        {{as_cppType(function.return_type.name) | indent(4, true) }} {{as_cppType(function.name) }}(
-            {%- for arg in function.arguments -%}
-                {% if not loop.first %}, {% endif %}{{as_annotated_cppType(arg)}}
-            {%- endfor -%}
-        ) {
-            {% if function.return_type.name.concatcase() == "void" %}
-                {{render_function_call(function)}};
-            {% else %}
-                auto result = {{render_function_call(function)}};
-                return {{convert_cType_to_cppType(function.return_type, 'value', 'result')}};
-            {% endif %}
-        }
-    {% endfor %}
-
-}
diff --git a/generator/templates/api_cpp.h b/generator/templates/api_cpp.h
index d129f54..ca281fa 100644
--- a/generator/templates/api_cpp.h
+++ b/generator/templates/api_cpp.h
@@ -48,6 +48,11 @@
         constexpr size_t ConstexprMax(size_t a, size_t b) {
             return a > b ? a : b;
         }
+
+        template <typename T>
+        static T& AsNonConstReference(const T& value) {
+            return const_cast<T&>(value);
+        }
     }  // namespace detail
 
     {% set c_prefix = metadata.c_prefix %}
@@ -57,21 +62,54 @@
         static constexpr {{type}} k{{as_cppType(constant.name)}} = {{ value }};
     {% endfor %}
 
+    {%- macro render_c_actual_arg(arg) -%}
+        {%- if arg.annotation == "value" -%}
+            {%- if arg.type.category == "object" -%}
+                {{as_varName(arg.name)}}.Get()
+            {%- elif arg.type.category == "enum" or arg.type.category == "bitmask" -%}
+                static_cast<{{as_cType(arg.type.name)}}>({{as_varName(arg.name)}})
+            {%- elif arg.type.category == "structure" -%}
+                *reinterpret_cast<{{as_cType(arg.type.name)}} const*>(&{{as_varName(arg.name)}})
+            {%- elif arg.type.category in ["function pointer", "native"] -%}
+                {{as_varName(arg.name)}}
+            {%- else -%}
+                UNHANDLED
+            {%- endif -%}
+        {%- else -%}
+            reinterpret_cast<{{decorate("", as_cType(arg.type.name), arg)}}>({{as_varName(arg.name)}})
+        {%- endif -%}
+    {%- endmacro -%}
+
+    {%- macro render_cpp_to_c_method_call(type, method) -%}
+        {{as_cMethod(type.name, method.name)}}(Get()
+            {%- for arg in method.arguments -%},{{" "}}{{render_c_actual_arg(arg)}}
+            {%- endfor -%}
+        )
+    {%- endmacro -%}
+
     {% for type in by_category["enum"] %}
-        enum class {{as_cppType(type.name)}} : uint32_t {
+        {% set CppType = as_cppType(type.name) %}
+        {% set CType = as_cType(type.name) %}
+        enum class {{CppType}} : uint32_t {
             {% for value in type.values %}
-                {{as_cppEnum(value.name)}} = 0x{{format(value.value, "08X")}},
+                {{as_cppEnum(value.name)}} = {{as_cEnum(type.name, value.name)}},
             {% endfor %}
         };
+        static_assert(sizeof({{CppType}}) == sizeof({{CType}}), "sizeof mismatch for {{CppType}}");
+        static_assert(alignof({{CppType}}) == alignof({{CType}}), "alignof mismatch for {{CppType}}");
 
     {% endfor %}
 
     {% for type in by_category["bitmask"] %}
-        enum class {{as_cppType(type.name)}} : uint32_t {
+        {% set CppType = as_cppType(type.name) %}
+        {% set CType = as_cType(type.name) + "Flags" %}
+        enum class {{CppType}} : uint32_t {
             {% for value in type.values %}
-                {{as_cppEnum(value.name)}} = 0x{{format(value.value, "08X")}},
+                {{as_cppEnum(value.name)}} = {{as_cEnum(type.name, value.name)}},
             {% endfor %}
         };
+        static_assert(sizeof({{CppType}}) == sizeof({{CType}}), "sizeof mismatch for {{CppType}}");
+        static_assert(alignof({{CppType}}) == alignof({{CType}}), "alignof mismatch for {{CppType}}");
 
     {% endfor %}
 
@@ -208,10 +246,11 @@
     {%- endif -%}
 {%- endmacro %}
 
-{% macro render_cpp_method_declaration(type, method) %}
+{% macro render_cpp_method_declaration(type, method, dfn=False) %}
     {% set CppType = as_cppType(type.name) %}
     {% set OriginalMethodName = method.name.CamelCase() %}
     {% set MethodName = OriginalMethodName[:-1] if method.name.chunks[-1] == "f" else OriginalMethodName %}
+    {% set MethodName = CppType + "::" + MethodName if dfn else MethodName %}
     {{as_cppType(method.return_type.name)}} {{MethodName}}(
         {%- for arg in method.arguments -%}
             {%- if not loop.first %}, {% endif -%}
@@ -220,7 +259,7 @@
             {%- else -%}
                 {{as_annotated_cppType(arg)}}
             {%- endif -%}
-            {{render_cpp_default_value(arg, False)}}
+            {% if not dfn %}{{render_cpp_default_value(arg, False)}}{% endif %}
         {%- endfor -%}
     ) const
 {%- endmacro %}
@@ -234,26 +273,54 @@
             using ObjectBase::operator=;
 
             {% for method in type.methods %}
-                {{render_cpp_method_declaration(type, method)}};
+                inline {{render_cpp_method_declaration(type, method)}};
             {% endfor %}
 
           private:
             friend ObjectBase<{{CppType}}, {{CType}}>;
-            static void {{c_prefix}}Reference({{CType}} handle);
-            static void {{c_prefix}}Release({{CType}} handle);
+            static inline void {{c_prefix}}Reference({{CType}} handle);
+            static inline void {{c_prefix}}Release({{CType}} handle);
         };
 
     {% endfor %}
 
+    {%- macro render_function_call(function) -%}
+        {{as_cMethod(None, function.name)}}(
+            {%- for arg in function.arguments -%}
+                {% if not loop.first %}, {% endif %}{{render_c_actual_arg(arg)}}
+            {%- endfor -%}
+        )
+    {%- endmacro -%}
+
+    // Free Functions
+
     {% for function in by_category["function"] if not function.no_cpp %}
-        {{as_cppType(function.return_type.name)}} {{as_cppType(function.name)}}(
+        inline {{as_cppType(function.return_type.name)}} {{as_cppType(function.name)}}(
             {%- for arg in function.arguments -%}
                 {%- if not loop.first %}, {% endif -%}
                 {{as_annotated_cppType(arg)}}{{render_cpp_default_value(arg, False)}}
             {%- endfor -%}
-        );
+        ) {
+            {% if function.return_type.name.concatcase() == "void" %}
+                {{render_function_call(function)}};
+            {% else %}
+                auto result = {{render_function_call(function)}};
+                return {{convert_cType_to_cppType(function.return_type, 'value', 'result')}};
+            {% endif %}
+        }
     {% endfor %}
 
+     // ChainedStruct
+    {% set c_prefix = metadata.c_prefix %}
+    static_assert(sizeof(ChainedStruct) == sizeof({{c_prefix}}ChainedStruct),
+            "sizeof mismatch for ChainedStruct");
+    static_assert(alignof(ChainedStruct) == alignof({{c_prefix}}ChainedStruct),
+            "alignof mismatch for ChainedStruct");
+    static_assert(offsetof(ChainedStruct, nextInChain) == offsetof({{c_prefix}}ChainedStruct, next),
+            "offsetof mismatch for ChainedStruct::nextInChain");
+    static_assert(offsetof(ChainedStruct, sType) == offsetof({{c_prefix}}ChainedStruct, sType),
+            "offsetof mismatch for ChainedStruct::sType");
+
     {% for type in by_category["structure"] %}
         {% set Out = "Out" if type.output else "" %}
         {% set const = "const" if not type.output else "" %}
@@ -272,11 +339,11 @@
                 {% endif %}
         {% endif %}
             {% if type.has_free_members_function %}
-                ~{{as_cppType(type.name)}}();
+                inline ~{{as_cppType(type.name)}}();
                 {{as_cppType(type.name)}}(const {{as_cppType(type.name)}}&) = delete;
                 {{as_cppType(type.name)}}& operator=(const {{as_cppType(type.name)}}&) = delete;
-                {{as_cppType(type.name)}}({{as_cppType(type.name)}}&&);
-                {{as_cppType(type.name)}}& operator=({{as_cppType(type.name)}}&&);
+                inline {{as_cppType(type.name)}}({{as_cppType(type.name)}}&&);
+                inline {{as_cppType(type.name)}}& operator=({{as_cppType(type.name)}}&&);
             {% endif %}
             {% if type.extensible %}
                 ChainedStruct{{Out}} {{const}} * nextInChain = nullptr;
@@ -292,6 +359,11 @@
                     {{member_declaration}};
                 {% endif %}
             {% endfor %}
+            {% if type.has_free_members_function %}
+
+              private:
+                static inline void Reset({{as_cppType(type.name)}}& value);
+            {% endif %}
         };
 
     {% endfor %}
@@ -301,6 +373,109 @@
         // and need to be imported into this namespace for Argument Dependent Lookup.
         WGPU_IMPORT_BITMASK_OPERATORS
     {% endif %}
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+// error: 'offsetof' within non-standard-layout type '{{metadata.namespace}}::XXX' is conditionally-supported
+#pragma GCC diagnostic ignored "-Winvalid-offsetof"
+#endif
+    {% for type in by_category["structure"] %}
+        {% set CppType = as_cppType(type.name) %}
+        {% set CType = as_cType(type.name) %}
+        // {{CppType}} implementation
+        {% if type.has_free_members_function %}
+            {{CppType}}::~{{CppType}}() {
+                if (
+                    {%- for member in type.members if member.annotation != 'value' %}
+                        {% if not loop.first %} || {% endif -%}
+                        this->{{member.name.camelCase()}} != nullptr
+                    {%- endfor -%}
+                ) {
+                    {{as_cMethod(type.name, Name("free members"))}}(
+                        *reinterpret_cast<{{as_cType(type.name)}}*>(this));
+                }
+            }
+
+            {{CppType}}::{{CppType}}({{CppType}}&& rhs)
+                : {% for member in type.members %}
+                {%- set memberName = member.name.camelCase() -%}
+                {{memberName}}(rhs.{{memberName}}){% if not loop.last %},{{"\n            "}}{% endif %}
+            {% endfor -%}
+            {
+                Reset(rhs);
+            }
+
+            {{CppType}}& {{CppType}}::operator=({{CppType}}&& rhs) {
+                if (&rhs == this) {
+                    return *this;
+                }
+                this->~{{CppType}}();
+                {% for member in type.members %}
+                    detail::AsNonConstReference(this->{{member.name.camelCase()}}) = std::move(rhs.{{member.name.camelCase()}});
+                {% endfor %}
+                Reset(rhs);
+                return *this;
+            }
+
+             // static
+            void {{CppType}}::Reset({{CppType}}& value) {
+                {{CppType}} defaultValue{};
+                {% for member in type.members %}
+                    detail::AsNonConstReference(value.{{member.name.camelCase()}}) = defaultValue.{{member.name.camelCase()}};
+                {% endfor %}
+            }
+        {% endif %}
+
+        static_assert(sizeof({{CppType}}) == sizeof({{CType}}), "sizeof mismatch for {{CppType}}");
+        static_assert(alignof({{CppType}}) == alignof({{CType}}), "alignof mismatch for {{CppType}}");
+        {% if type.extensible %}
+            static_assert(offsetof({{CppType}}, nextInChain) == offsetof({{CType}}, nextInChain),
+                    "offsetof mismatch for {{CppType}}::nextInChain");
+        {% endif %}
+        {% for member in type.members %}
+            {% set memberName = member.name.camelCase() %}
+            static_assert(offsetof({{CppType}}, {{memberName}}) == offsetof({{CType}}, {{memberName}}),
+                    "offsetof mismatch for {{CppType}}::{{memberName}}");
+        {% endfor %}
+
+    {% endfor %}
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+    {% for type in by_category["object"] %}
+        {% set CppType = as_cppType(type.name) %}
+        {% set CType = as_cType(type.name) %}
+        // {{CppType}} implementation
+
+        {% for method in type.methods %}
+            {{render_cpp_method_declaration(type, method, dfn=True)}} {
+                {% for arg in method.arguments if arg.type.has_free_members_function and arg.annotation == '*' %}
+                    *{{as_varName(arg.name)}} = {{as_cppType(arg.type.name)}}();
+                {% endfor %}
+                {% if method.return_type.name.concatcase() == "void" %}
+                    {{render_cpp_to_c_method_call(type, method)}};
+                {% else %}
+                    auto result = {{render_cpp_to_c_method_call(type, method)}};
+                    return {{convert_cType_to_cppType(method.return_type, 'value', 'result') | indent(8)}};
+                {% endif %}
+            }
+        {% endfor %}
+        void {{CppType}}::{{c_prefix}}Reference({{CType}} handle) {
+            if (handle != nullptr) {
+                {{as_cMethod(type.name, Name("reference"))}}(handle);
+            }
+        }
+        void {{CppType}}::{{c_prefix}}Release({{CType}} handle) {
+            if (handle != nullptr) {
+                {{as_cMethod(type.name, Name("release"))}}(handle);
+            }
+        }
+        static_assert(sizeof({{CppType}}) == sizeof({{CType}}), "sizeof mismatch for {{CppType}}");
+        static_assert(alignof({{CppType}}) == alignof({{CType}}), "alignof mismatch for {{CppType}}");
+
+    {% endfor %}
+
 }  // namespace {{metadata.namespace}}
 
 namespace wgpu {
diff --git a/src/dawn/BUILD.gn b/src/dawn/BUILD.gn
index 2e243b5..ee5355b 100644
--- a/src/dawn/BUILD.gn
+++ b/src/dawn/BUILD.gn
@@ -34,15 +34,8 @@
 # Dawn C++ wrapper
 ###############################################################################
 
-dawn_json_generator("cpp_gen") {
-  target = "cpp"
-  outputs = [ "src/dawn/webgpu_cpp.cpp" ]
-}
-
 source_set("cpp") {
   public_deps = [ "${dawn_root}/include/dawn:cpp_headers" ]
-  deps = [ ":cpp_gen" ]
-  sources = get_target_outputs(":cpp_gen")
 }
 
 ###############################################################################
@@ -87,7 +80,6 @@
     "emscripten-bits/system/include/webgpu/webgpu.h",
     "emscripten-bits/system/include/webgpu/webgpu_cpp.h",
     "emscripten-bits/system/include/webgpu/webgpu_cpp_chained_struct.h",
-    "emscripten-bits/system/lib/webgpu/webgpu_cpp.cpp",
     "emscripten-bits/webgpu_struct_info.json",
     "emscripten-bits/library_webgpu_enum_tables.js",
   ]
diff --git a/src/dawn/CMakeLists.txt b/src/dawn/CMakeLists.txt
index 4bb4986..6e0932e 100644
--- a/src/dawn/CMakeLists.txt
+++ b/src/dawn/CMakeLists.txt
@@ -86,23 +86,8 @@
 target_link_libraries(dawncpp_headers INTERFACE dawn_headers)
 install_if_enabled(dawncpp_headers)
 
-###############################################################################
-# Dawn C++ wrapper
-###############################################################################
-
-DawnJSONGenerator(
-    TARGET "cpp"
-    PRINT_NAME "Dawn C++ wrapper"
-    RESULT_VARIABLE "DAWNCPP_GEN_SOURCES"
-)
-
-add_library(dawncpp)
-common_compile_options(dawncpp)
-target_sources(dawncpp PRIVATE ${DAWNCPP_GEN_SOURCES})
-target_link_libraries(dawncpp PUBLIC dawncpp_headers)
-install_if_enabled(dawncpp)
-
-add_library(webgpu_cpp ALIAS dawncpp)
+add_library(dawncpp ALIAS dawncpp_headers)
+add_library(webgpu_cpp ALIAS dawncpp_headers)
 
 ###############################################################################
 # libdawn_proc
diff --git a/src/dawn/samples/BUILD.gn b/src/dawn/samples/BUILD.gn
index ed3f26b..9e7eab2 100644
--- a/src/dawn/samples/BUILD.gn
+++ b/src/dawn/samples/BUILD.gn
@@ -48,7 +48,6 @@
   # Export all of these as public deps so that `gn check` allows includes
   public_deps = [
     "${dawn_root}/src/dawn:cpp",
-    "${dawn_root}/src/dawn:proc_shared",
     "${dawn_root}/src/dawn/common",
     "${dawn_root}/src/dawn/glfw",
     "${dawn_root}/src/dawn/native",