Generate a single ProcTable instead of one per backend.

This required putting Queue::Submit on QueueBase which is something we
would want to do anyway, and removes the need for Queue::ValidateSubmit
being called in the ProcTable.

This removes the need for all the "GeneratedCodeIncludes" files and
leads to a bunch of simplifications in BindGroup as well as the
dawn_native CMakeLists.txt.

Finally this was done in order to simplify the writing of BUILD.gn
files.
diff --git a/generator/main.py b/generator/main.py
index 737ff10..b295bae 100644
--- a/generator/main.py
+++ b/generator/main.py
@@ -358,9 +358,16 @@
     assert(not type_name.native and not method_name.native)
     return 'dawn' + 'Proc' + type_name.CamelCase() + method_name.CamelCase()
 
-def as_backendType(typ):
+def as_frontendType(typ):
     if typ.category == 'object':
-        return typ.name.CamelCase() + '*'
+        if typ.is_builder:
+            return typ.name.CamelCase() + '*'
+        else:
+            return typ.name.CamelCase() + 'Base*'
+    elif typ.category in ['bitmask', 'enum']:
+        return 'dawn::' + typ.name.CamelCase()
+    elif typ.category == 'structure':
+        return as_cppType(typ.name)
     else:
         return as_cType(typ.name)
 
@@ -389,7 +396,7 @@
     print(text)
 
 def main():
-    targets = ['dawn_headers', 'libdawn', 'mock_dawn', 'opengl', 'metal', 'd3d12', 'null', 'dawn_wire', "dawn_native_utils"]
+    targets = ['dawn_headers', 'libdawn', 'mock_dawn', 'dawn_wire', "dawn_native_utils"]
 
     parser = argparse.ArgumentParser(
         description = 'Generates code for various target for Dawn.',
@@ -453,40 +460,36 @@
         renders.append(FileRender('mock_api.h', 'mock/mock_dawn.h', [base_params, api_params, c_params]))
         renders.append(FileRender('mock_api.cpp', 'mock/mock_dawn.cpp', [base_params, api_params, c_params]))
 
-    base_backend_params = [
-        base_params,
-        api_params,
-        c_params,
-        {
-            'as_backendType': lambda typ: as_backendType(typ), # TODO as_backendType and friends take a Type and not a Name :(
-            'as_annotated_backendType': lambda arg: annotated(as_backendType(arg.type), arg)
-        }
-    ]
-
-    for backend in ['d3d12', 'metal', 'null', 'opengl', 'vulkan']:
-        if not backend in targets:
-            continue
-
-        extension = 'cpp'
-        if backend == 'metal':
-            extension = 'mm'
-
-        backend_params = {
-            'namespace': backend,
-        }
-        renders.append(FileRender('dawn_native/ProcTable.cpp', 'dawn_native/' + backend + '/ProcTable.' + extension, base_backend_params + [backend_params]))
-
     if 'dawn_native_utils' in targets:
-        renders.append(FileRender('dawn_native/ValidationUtils.h', 'dawn_native/ValidationUtils_autogen.h', base_backend_params))
-        renders.append(FileRender('dawn_native/ValidationUtils.cpp', 'dawn_native/ValidationUtils_autogen.cpp', base_backend_params))
-        renders.append(FileRender('dawn_native/api_structs.h', 'dawn_native/dawn_structs_autogen.h', base_backend_params))
-        renders.append(FileRender('dawn_native/api_structs.cpp', 'dawn_native/dawn_structs_autogen.cpp', base_backend_params))
+        frontend_params = [
+            base_params,
+            api_params,
+            c_params,
+            {
+                'as_frontendType': lambda typ: as_frontendType(typ), # TODO as_frontendType and friends take a Type and not a Name :(
+                'as_annotated_frontendType': lambda arg: annotated(as_frontendType(arg.type), arg)
+            }
+        ]
+
+        renders.append(FileRender('dawn_native/ValidationUtils.h', 'dawn_native/ValidationUtils_autogen.h', frontend_params))
+        renders.append(FileRender('dawn_native/ValidationUtils.cpp', 'dawn_native/ValidationUtils_autogen.cpp', frontend_params))
+        renders.append(FileRender('dawn_native/api_structs.h', 'dawn_native/dawn_structs_autogen.h', frontend_params))
+        renders.append(FileRender('dawn_native/api_structs.cpp', 'dawn_native/dawn_structs_autogen.cpp', frontend_params))
+        renders.append(FileRender('dawn_native/ProcTable.cpp', 'dawn_native/ProcTable.cpp', frontend_params))
 
     if 'dawn_wire' in targets:
-        renders.append(FileRender('dawn_wire/WireCmd.h', 'dawn_wire/WireCmd_autogen.h', base_backend_params))
-        renders.append(FileRender('dawn_wire/WireCmd.cpp', 'dawn_wire/WireCmd_autogen.cpp', base_backend_params))
-        renders.append(FileRender('dawn_wire/WireClient.cpp', 'dawn_wire/WireClient.cpp', base_backend_params))
-        renders.append(FileRender('dawn_wire/WireServer.cpp', 'dawn_wire/WireServer.cpp', base_backend_params))
+        wire_params = [
+            base_params,
+            api_params,
+            c_params,
+            {
+                'as_wireType': lambda typ: typ.name.CamelCase() + '*' if typ.category == 'object' else as_cppType(typ.name)
+            }
+        ]
+        renders.append(FileRender('dawn_wire/WireCmd.h', 'dawn_wire/WireCmd_autogen.h', wire_params))
+        renders.append(FileRender('dawn_wire/WireCmd.cpp', 'dawn_wire/WireCmd_autogen.cpp', wire_params))
+        renders.append(FileRender('dawn_wire/WireClient.cpp', 'dawn_wire/WireClient.cpp', wire_params))
+        renders.append(FileRender('dawn_wire/WireServer.cpp', 'dawn_wire/WireServer.cpp', wire_params))
 
     output_separator = '\n' if args.gn else ';'
     if args.print_dependencies:
diff --git a/generator/templates/dawn_native/ProcTable.cpp b/generator/templates/dawn_native/ProcTable.cpp
index 8808f40..9ad84fc 100644
--- a/generator/templates/dawn_native/ProcTable.cpp
+++ b/generator/templates/dawn_native/ProcTable.cpp
@@ -17,57 +17,32 @@
 #include "dawn_native/dawn_platform.h"
 #include "dawn_native/ErrorData.h"
 #include "dawn_native/ValidationUtils_autogen.h"
-#include "dawn_native/{{namespace}}/GeneratedCodeIncludes.h"
+
+{% for type in by_category["object"] %}
+    {% if not type.is_builder and type.name.canonical_case() not in ["buffer view", "texture view"] %}
+        #include "dawn_native/{{type.name.CamelCase()}}.h"
+    {% endif %}
+{% endfor %}
 
 namespace dawn_native {
-namespace {{namespace}} {
 
     namespace {
 
         {% set methodsWithExtraValidation = (
             "CommandBufferBuilderGetResult",
-            "QueueSubmit",
         ) %}
 
         {% for type in by_category["object"] %}
             {% for method in native_methods(type) %}
                 {% set suffix = as_MethodSuffix(type.name, method.name) %}
 
-                //* Entry point without validation, forwards the arguments to the method directly
-                {{as_backendType(method.return_type)}} NonValidating{{suffix}}(
-                    {{-as_backendType(type)}} self
-                    {%- for arg in method.arguments -%}
-                        , {{as_annotated_backendType(arg)}}
-                    {%- endfor -%}
-                ) {
-                    {% if method.return_type.name.canonical_case() != "void" %}
-                        auto result =
-                    {%- endif %}
-                    self->{{method.name.CamelCase()}}(
-                        {%- for arg in method.arguments -%}
-                            {%- if not loop.first %}, {% endif -%}
-                            {%- if arg.type.category in ["enum", "bitmask"] -%}
-                                static_cast<dawn::{{as_cppType(arg.type.name)}}>({{as_varName(arg.name)}})
-                            {%- elif arg.type.category == "structure" and arg.annotation != "value" -%}
-                                reinterpret_cast<const {{as_cppType(arg.type.name)}}*>({{as_varName(arg.name)}})
-                            {%- else -%}
-                                {{as_varName(arg.name)}}
-                            {%- endif -%}
-                        {%- endfor -%}
-                    );
-                    {% if method.return_type.name.canonical_case() != "void" %}
-                        return reinterpret_cast<{{as_backendType(method.return_type)}}>(result);
-                    {% endif %}
-                }
-
                 //* Autogenerated part of the entry point validation
                 //*  - Check that enum and bitmaks are in the correct range
                 //*  - Check that builders have not been consumed already
-                //*  - Others TODO
                 bool ValidateBase{{suffix}}(
-                    {{-as_backendType(type)}} self
+                    {{-as_frontendType(type)}} self
                     {%- for arg in method.arguments -%}
-                        , {{as_annotated_backendType(arg)}}
+                        , {{as_annotated_frontendType(arg)}}
                     {%- endfor -%}
                 ) {
                     {% if type.is_builder and method.name.canonical_case() not in ("release", "reference") %}
@@ -104,10 +79,10 @@
                 }
 
                 //* Entry point with validation
-                {{as_backendType(method.return_type)}} Validating{{suffix}}(
-                    {{-as_backendType(type)}} self
+                {{as_frontendType(method.return_type)}} Validating{{suffix}}(
+                    {{-as_frontendType(type)}} self
                     {%- for arg in method.arguments -%}
-                        , {{as_annotated_backendType(arg)}}
+                        , {{as_annotated_frontendType(arg)}}
                     {%- endfor -%}
                 ) {
                     //* Do the autogenerated checks
@@ -147,7 +122,7 @@
                     //* error callback would always get called with an Unknown status
                     {% if type.is_builder and method.name.canonical_case() == "get result" %}
                         if (!valid) {
-                            {{as_backendType(method.return_type)}} fakeResult = nullptr;
+                            {{as_frontendType(method.return_type)}} fakeResult = nullptr;
                             bool shouldBeFalse = self->HandleResult(fakeResult);
                             ASSERT(shouldBeFalse == false);
                         }
@@ -174,24 +149,14 @@
                         {%- endfor -%}
                     );
                     {% if method.return_type.name.canonical_case() != "void" %}
-                        return reinterpret_cast<{{as_backendType(method.return_type)}}>(result);
+                        return reinterpret_cast<{{as_frontendType(method.return_type)}}>(result);
                     {% endif %}
                 }
             {% endfor %}
         {% endfor %}
     }
 
-    dawnProcTable GetNonValidatingProcs() {
-        dawnProcTable table;
-        {% for type in by_category["object"] %}
-            {% for method in native_methods(type) %}
-                table.{{as_varName(type.name, method.name)}} = reinterpret_cast<{{as_cProc(type.name, method.name)}}>(NonValidating{{as_MethodSuffix(type.name, method.name)}});
-            {% endfor %}
-        {% endfor %}
-        return table;
-    }
-
-    dawnProcTable GetValidatingProcs() {
+    dawnProcTable GetProcs() {
         dawnProcTable table;
         {% for type in by_category["object"] %}
             {% for method in native_methods(type) %}
@@ -201,4 +166,3 @@
         return table;
     }
 }
-}
diff --git a/generator/templates/dawn_native/api_structs.h b/generator/templates/dawn_native/api_structs.h
index e621331..6de4da6 100644
--- a/generator/templates/dawn_native/api_structs.h
+++ b/generator/templates/dawn_native/api_structs.h
@@ -26,15 +26,7 @@
                 const void* nextInChain = nullptr;
             {% endif %}
             {% for member in type.members %}
-                {% if member.type.category == "object" %}
-                    {{decorate(as_varName(member.name), as_cppType(member.type.name) + "Base*", member)}};
-                {% elif member.type.category == "structure" %}
-                    {{as_annotated_cppType(member)}};
-                {% elif member.type.category in ["enum", "bitmask"] %}
-                    {{decorate(as_varName(member.name), "dawn::" + as_cppType(member.type.name), member)}};
-                {% else %}
-                    {{as_annotated_cppType(member)}};
-                {% endif %}
+                {{as_annotated_frontendType(member)}};
             {% endfor %}
         };
 
diff --git a/generator/templates/dawn_wire/WireClient.cpp b/generator/templates/dawn_wire/WireClient.cpp
index aafed27..49b0f0d 100644
--- a/generator/templates/dawn_wire/WireClient.cpp
+++ b/generator/templates/dawn_wire/WireClient.cpp
@@ -215,7 +215,7 @@
                 // Implementation of the ObjectIdProvider interface
                 {% for type in by_category["object"] %}
                     ObjectId GetId({{as_cType(type.name)}} object) const override {
-                        return reinterpret_cast<{{as_backendType(type)}}>(object)->id;
+                        return reinterpret_cast<{{as_wireType(type)}}>(object)->id;
                     }
                 {% endfor %}
 
@@ -239,13 +239,13 @@
             {% for method in type.methods %}
                 {% set Suffix = as_MethodSuffix(type.name, method.name) %}
 
-                {{as_backendType(method.return_type)}} Client{{Suffix}}(
+                {{as_wireType(method.return_type)}} Client{{Suffix}}(
                     {{-as_cType(type.name)}} cSelf
                     {%- for arg in method.arguments -%}
                         , {{as_annotated_cType(arg)}}
                     {%- endfor -%}
                 ) {
-                    {{as_backendType(type)}} self = reinterpret_cast<{{as_backendType(type)}}>(cSelf);
+                    auto self = reinterpret_cast<{{as_wireType(type)}}>(cSelf);
                     Device* device = self->device;
                     {{Suffix}}Cmd cmd;
 
diff --git a/src/dawn_native/BindGroup.h b/src/dawn_native/BindGroup.h
index 3fbad9e3..9aea5a6 100644
--- a/src/dawn_native/BindGroup.h
+++ b/src/dawn_native/BindGroup.h
@@ -25,7 +25,6 @@
 
 #include <array>
 #include <bitset>
-#include <type_traits>
 
 namespace dawn_native {
 
@@ -55,25 +54,8 @@
         void SetLayout(BindGroupLayoutBase* layout);
         void SetUsage(dawn::BindGroupUsage usage);
 
-        template <typename T>
-        void SetBufferViews(uint32_t start, uint32_t count, T* const* bufferViews) {
-            static_assert(std::is_base_of<BufferViewBase, T>::value, "");
-            SetBufferViews(start, count, reinterpret_cast<BufferViewBase* const*>(bufferViews));
-        }
         void SetBufferViews(uint32_t start, uint32_t count, BufferViewBase* const* bufferViews);
-
-        template <typename T>
-        void SetSamplers(uint32_t start, uint32_t count, T* const* samplers) {
-            static_assert(std::is_base_of<SamplerBase, T>::value, "");
-            SetSamplers(start, count, reinterpret_cast<SamplerBase* const*>(samplers));
-        }
         void SetSamplers(uint32_t start, uint32_t count, SamplerBase* const* samplers);
-
-        template <typename T>
-        void SetTextureViews(uint32_t start, uint32_t count, T* const* textureViews) {
-            static_assert(std::is_base_of<TextureViewBase, T>::value, "");
-            SetTextureViews(start, count, reinterpret_cast<TextureViewBase* const*>(textureViews));
-        }
         void SetTextureViews(uint32_t start, uint32_t count, TextureViewBase* const* textureViews);
 
       private:
diff --git a/src/dawn_native/CMakeLists.txt b/src/dawn_native/CMakeLists.txt
index c191ae7..4828d17 100644
--- a/src/dawn_native/CMakeLists.txt
+++ b/src/dawn_native/CMakeLists.txt
@@ -30,21 +30,8 @@
         -T dawn_native_utils
 )
 
-function(GenerateProcTable backend)
-    Generate(
-        LIB_NAME ${backend}_autogen
-        LIB_TYPE STATIC
-        FOLDER "dawn_native"
-        PRINT_NAME "${backend} backend autogenerated files"
-        COMMAND_LINE_ARGS
-            ${GENERATOR_COMMON_ARGS}
-            -T ${backend}
-    )
-    target_link_libraries(${backend}_autogen dawn_native_utils_autogen)
-endfunction()
-
 set(DAWN_NATIVE_SOURCES)
-set(DAWN_NATIVE_DEPS dawn_common spirv_cross)
+set(DAWN_NATIVE_DEPS dawn_common spirv_cross dawn_native_utils_autogen)
 set(DAWN_NATIVE_INCLUDE_DIRS ${SPIRV_CROSS_INCLUDE_DIR})
 
 ################################################################################
@@ -52,10 +39,7 @@
 ################################################################################
 
 if (DAWN_ENABLE_OPENGL)
-    GenerateProcTable(opengl)
-    target_link_libraries(opengl_autogen glad)
-
-    list(APPEND DAWN_NATIVE_DEPS opengl_autogen glad)
+    list(APPEND DAWN_NATIVE_DEPS glad)
     list(APPEND DAWN_NATIVE_INCLUDE_DIRS ${GLAD_INCLUDE_DIR})
     list(APPEND DAWN_NATIVE_SOURCES
         ${OPENGL_DIR}/BlendStateGL.cpp
@@ -100,9 +84,6 @@
 ################################################################################
 
 if (DAWN_ENABLE_NULL)
-    GenerateProcTable(null)
-    list(APPEND DAWN_NATIVE_DEPS null_autogen)
-
     list(APPEND DAWN_NATIVE_SOURCES
         ${NULL_DIR}/NullBackend.cpp
         ${NULL_DIR}/NullBackend.h
@@ -115,8 +96,7 @@
 ################################################################################
 
 if (DAWN_ENABLE_METAL)
-    GenerateProcTable(metal)
-    list(APPEND DAWN_NATIVE_DEPS metal_autogen "-framework Metal" "-framework Cocoa")
+    list(APPEND DAWN_NATIVE_DEPS "-framework Metal" "-framework Cocoa")
 
     list(APPEND DAWN_NATIVE_SOURCES
         ${METAL_DIR}/BlendStateMTL.mm
@@ -159,8 +139,6 @@
 ################################################################################
 
 if (DAWN_ENABLE_D3D12)
-    GenerateProcTable(d3d12)
-
     # WIN10_SDK_PATH will be something like C:\Program Files (x86)\Windows Kits\10
     get_filename_component(WIN10_SDK_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows\\v10.0;InstallationFolder]" ABSOLUTE CACHE)
 
@@ -216,9 +194,8 @@
         list(APPEND D3D12_LIBRARIES ${DXGUID_LIBRARY})
     endif()
 
-    list(APPEND DAWN_NATIVE_DEPS d3d12_autogen ${D3D12_LIBRARIES})
-    target_include_directories(d3d12_autogen SYSTEM PUBLIC ${D3D12_INCLUDE_DIR} ${DXGI_INCLUDE_DIR})
-
+    list(APPEND DAWN_NATIVE_DEPS ${D3D12_LIBRARIES})
+    list(APPEND DAWN_NATIVE_INCLUDE_DIRS ${D3D12_INCLUDE_DIR} ${DXGI_INCLUDE_DIR})
     list(APPEND DAWN_NATIVE_SOURCES
         ${D3D12_DIR}/d3d12_platform.h
         ${D3D12_DIR}/BindGroupD3D12.cpp
@@ -277,10 +254,7 @@
 ################################################################################
 
 if (DAWN_ENABLE_VULKAN)
-    GenerateProcTable(vulkan)
-    list(APPEND DAWN_NATIVE_DEPS vulkan_autogen)
-    target_include_directories(vulkan_autogen PUBLIC ${VULKAN_HEADERS_INCLUDE_DIR})
-
+    list(APPEND DAWN_NATIVE_INCLUDE_DIRS ${VULKAN_HEADERS_INCLUDE_DIR})
     list(APPEND DAWN_NATIVE_SOURCES
         ${VULKAN_DIR}/BindGroupVk.cpp
         ${VULKAN_DIR}/BindGroupVk.h
diff --git a/src/dawn_native/Queue.cpp b/src/dawn_native/Queue.cpp
index 7733e1a..384b1fe 100644
--- a/src/dawn_native/Queue.cpp
+++ b/src/dawn_native/Queue.cpp
@@ -28,8 +28,15 @@
         return mDevice;
     }
 
-    MaybeError QueueBase::ValidateSubmitCommand(CommandBufferBase*) {
-        // TODO(cwallez@chromium.org): Validate resources referenced by command buffers can be used
+    void QueueBase::Submit(uint32_t numCommands, CommandBufferBase* const* commands) {
+        if (mDevice->ConsumedError(ValidateSubmit(numCommands, commands))) {
+            return;
+        }
+
+        SubmitImpl(numCommands, commands);
+    }
+
+    MaybeError QueueBase::ValidateSubmit(uint32_t, CommandBufferBase* const*) {
         return {};
     }
 
diff --git a/src/dawn_native/Queue.h b/src/dawn_native/Queue.h
index 07a3843..6a356de 100644
--- a/src/dawn_native/Queue.h
+++ b/src/dawn_native/Queue.h
@@ -30,19 +30,13 @@
 
         DeviceBase* GetDevice();
 
-        template <typename T>
-        MaybeError ValidateSubmit(uint32_t numCommands, T* const* commands) {
-            static_assert(std::is_base_of<CommandBufferBase, T>::value,
-                          "invalid command buffer type");
-
-            for (uint32_t i = 0; i < numCommands; ++i) {
-                DAWN_TRY(ValidateSubmitCommand(commands[i]));
-            }
-            return {};
-        }
+        // Dawn API
+        void Submit(uint32_t numCommands, CommandBufferBase* const* commands);
 
       private:
-        MaybeError ValidateSubmitCommand(CommandBufferBase* command);
+        virtual void SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) = 0;
+
+        MaybeError ValidateSubmit(uint32_t numCommands, CommandBufferBase* const* commands);
 
         DeviceBase* mDevice;
     };
diff --git a/src/dawn_native/d3d12/DeviceD3D12.cpp b/src/dawn_native/d3d12/DeviceD3D12.cpp
index e2f9f1f..0d4b833 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.cpp
+++ b/src/dawn_native/d3d12/DeviceD3D12.cpp
@@ -39,14 +39,15 @@
 #include "dawn_native/d3d12/SwapChainD3D12.h"
 #include "dawn_native/d3d12/TextureD3D12.h"
 
-namespace dawn_native { namespace d3d12 {
+namespace dawn_native {
+    dawnProcTable GetProcs();
+}  // namespace dawn_native
 
-    dawnProcTable GetNonValidatingProcs();
-    dawnProcTable GetValidatingProcs();
+namespace dawn_native { namespace d3d12 {
 
     void Init(dawnProcTable* procs, dawnDevice* device) {
         *device = nullptr;
-        *procs = GetValidatingProcs();
+        *procs = GetProcs();
         *device = reinterpret_cast<dawnDevice>(new Device());
     }
 
diff --git a/src/dawn_native/d3d12/GeneratedCodeIncludes.h b/src/dawn_native/d3d12/GeneratedCodeIncludes.h
deleted file mode 100644
index 8d5ac99..0000000
--- a/src/dawn_native/d3d12/GeneratedCodeIncludes.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2017 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.
-
-#include "dawn_native/d3d12/BindGroupD3D12.h"
-#include "dawn_native/d3d12/BindGroupLayoutD3D12.h"
-#include "dawn_native/d3d12/BlendStateD3D12.h"
-#include "dawn_native/d3d12/BufferD3D12.h"
-#include "dawn_native/d3d12/CommandBufferD3D12.h"
-#include "dawn_native/d3d12/ComputePipelineD3D12.h"
-#include "dawn_native/d3d12/DepthStencilStateD3D12.h"
-#include "dawn_native/d3d12/DeviceD3D12.h"
-#include "dawn_native/d3d12/InputStateD3D12.h"
-#include "dawn_native/d3d12/PipelineLayoutD3D12.h"
-#include "dawn_native/d3d12/QueueD3D12.h"
-#include "dawn_native/d3d12/RenderPassDescriptorD3D12.h"
-#include "dawn_native/d3d12/RenderPipelineD3D12.h"
-#include "dawn_native/d3d12/SamplerD3D12.h"
-#include "dawn_native/d3d12/ShaderModuleD3D12.h"
-#include "dawn_native/d3d12/SwapChainD3D12.h"
-#include "dawn_native/d3d12/TextureD3D12.h"
diff --git a/src/dawn_native/d3d12/QueueD3D12.cpp b/src/dawn_native/d3d12/QueueD3D12.cpp
index 7fdf8ba..344f060 100644
--- a/src/dawn_native/d3d12/QueueD3D12.cpp
+++ b/src/dawn_native/d3d12/QueueD3D12.cpp
@@ -22,14 +22,14 @@
     Queue::Queue(Device* device) : QueueBase(device) {
     }
 
-    void Queue::Submit(uint32_t numCommands, CommandBuffer* const* commands) {
+    void Queue::SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) {
         Device* device = ToBackend(GetDevice());
 
         device->Tick();
 
         device->OpenCommandList(&mCommandList);
         for (uint32_t i = 0; i < numCommands; ++i) {
-            commands[i]->RecordCommands(mCommandList);
+            ToBackend(commands[i])->RecordCommands(mCommandList);
         }
         ASSERT_SUCCESS(mCommandList->Close());
 
diff --git a/src/dawn_native/d3d12/QueueD3D12.h b/src/dawn_native/d3d12/QueueD3D12.h
index c0dd2cb..7420b1d 100644
--- a/src/dawn_native/d3d12/QueueD3D12.h
+++ b/src/dawn_native/d3d12/QueueD3D12.h
@@ -28,10 +28,9 @@
       public:
         Queue(Device* device);
 
-        // Dawn API
-        void Submit(uint32_t numCommands, CommandBuffer* const* commands);
-
       private:
+        void SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) override;
+
         ComPtr<ID3D12GraphicsCommandList> mCommandList;
     };
 
diff --git a/src/dawn_native/metal/DeviceMTL.mm b/src/dawn_native/metal/DeviceMTL.mm
index 0cd4b21..2f8b516 100644
--- a/src/dawn_native/metal/DeviceMTL.mm
+++ b/src/dawn_native/metal/DeviceMTL.mm
@@ -35,14 +35,16 @@
 
 #include <unistd.h>
 
+namespace dawn_native {
+    dawnProcTable GetProcs();
+}  // namespace dawn_native
+
 namespace dawn_native { namespace metal {
-    dawnProcTable GetNonValidatingProcs();
-    dawnProcTable GetValidatingProcs();
 
     void Init(id<MTLDevice> metalDevice, dawnProcTable* procs, dawnDevice* device) {
         *device = nullptr;
 
-        *procs = GetValidatingProcs();
+        *procs = GetProcs();
         *device = reinterpret_cast<dawnDevice>(new Device(metalDevice));
     }
 
diff --git a/src/dawn_native/metal/GeneratedCodeIncludes.h b/src/dawn_native/metal/GeneratedCodeIncludes.h
deleted file mode 100644
index 9f56c30..0000000
--- a/src/dawn_native/metal/GeneratedCodeIncludes.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2017 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.
-
-#include "dawn_native/BindGroup.h"
-#include "dawn_native/BindGroupLayout.h"
-#include "dawn_native/RenderPassDescriptor.h"
-#include "dawn_native/metal/BlendStateMTL.h"
-#include "dawn_native/metal/BufferMTL.h"
-#include "dawn_native/metal/CommandBufferMTL.h"
-#include "dawn_native/metal/ComputePipelineMTL.h"
-#include "dawn_native/metal/DepthStencilStateMTL.h"
-#include "dawn_native/metal/DeviceMTL.h"
-#include "dawn_native/metal/InputStateMTL.h"
-#include "dawn_native/metal/PipelineLayoutMTL.h"
-#include "dawn_native/metal/QueueMTL.h"
-#include "dawn_native/metal/RenderPipelineMTL.h"
-#include "dawn_native/metal/SamplerMTL.h"
-#include "dawn_native/metal/ShaderModuleMTL.h"
-#include "dawn_native/metal/SwapChainMTL.h"
-#include "dawn_native/metal/TextureMTL.h"
diff --git a/src/dawn_native/metal/QueueMTL.h b/src/dawn_native/metal/QueueMTL.h
index 0e4e5cb..e5c6de7 100644
--- a/src/dawn_native/metal/QueueMTL.h
+++ b/src/dawn_native/metal/QueueMTL.h
@@ -26,8 +26,8 @@
       public:
         Queue(Device* device);
 
-        // Dawn API
-        void Submit(uint32_t numCommands, CommandBuffer* const* commands);
+      private:
+        void SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) override;
     };
 
 }}  // namespace dawn_native::metal
diff --git a/src/dawn_native/metal/QueueMTL.mm b/src/dawn_native/metal/QueueMTL.mm
index 54a10bd..fdcf47b 100644
--- a/src/dawn_native/metal/QueueMTL.mm
+++ b/src/dawn_native/metal/QueueMTL.mm
@@ -22,13 +22,13 @@
     Queue::Queue(Device* device) : QueueBase(device) {
     }
 
-    void Queue::Submit(uint32_t numCommands, CommandBuffer* const* commands) {
+    void Queue::SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) {
         Device* device = ToBackend(GetDevice());
         device->Tick();
         id<MTLCommandBuffer> commandBuffer = device->GetPendingCommandBuffer();
 
         for (uint32_t i = 0; i < numCommands; ++i) {
-            commands[i]->FillCommands(commandBuffer);
+            ToBackend(commands[i])->FillCommands(commandBuffer);
         }
 
         device->SubmitPendingCommandBuffer();
diff --git a/src/dawn_native/null/GeneratedCodeIncludes.h b/src/dawn_native/null/GeneratedCodeIncludes.h
deleted file mode 100644
index f917f18..0000000
--- a/src/dawn_native/null/GeneratedCodeIncludes.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2017 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.
-
-#include "dawn_native/null/NullBackend.h"
diff --git a/src/dawn_native/null/NullBackend.cpp b/src/dawn_native/null/NullBackend.cpp
index cb4304d..244ecb0 100644
--- a/src/dawn_native/null/NullBackend.cpp
+++ b/src/dawn_native/null/NullBackend.cpp
@@ -19,13 +19,14 @@
 
 #include <spirv-cross/spirv_cross.hpp>
 
+namespace dawn_native {
+    dawnProcTable GetProcs();
+}  // namespace dawn_native
+
 namespace dawn_native { namespace null {
 
-    dawnProcTable GetNonValidatingProcs();
-    dawnProcTable GetValidatingProcs();
-
     void Init(dawnProcTable* procs, dawnDevice* device) {
-        *procs = GetValidatingProcs();
+        *procs = GetProcs();
         *device = reinterpret_cast<dawnDevice>(new Device);
     }
 
@@ -189,7 +190,7 @@
     Queue::~Queue() {
     }
 
-    void Queue::Submit(uint32_t, CommandBuffer* const*) {
+    void Queue::SubmitImpl(uint32_t, CommandBufferBase* const*) {
         auto operations = ToBackend(GetDevice())->AcquirePendingOperations();
 
         for (auto& operation : operations) {
diff --git a/src/dawn_native/null/NullBackend.h b/src/dawn_native/null/NullBackend.h
index 383163f..d780f6d 100644
--- a/src/dawn_native/null/NullBackend.h
+++ b/src/dawn_native/null/NullBackend.h
@@ -159,8 +159,8 @@
         Queue(Device* device);
         ~Queue();
 
-        // Dawn API
-        void Submit(uint32_t numCommands, CommandBuffer* const* commands);
+      private:
+        void SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) override;
     };
 
     class SwapChain : public SwapChainBase {
diff --git a/src/dawn_native/opengl/DeviceGL.cpp b/src/dawn_native/opengl/DeviceGL.cpp
index 62cbbe9..67d51e6 100644
--- a/src/dawn_native/opengl/DeviceGL.cpp
+++ b/src/dawn_native/opengl/DeviceGL.cpp
@@ -32,16 +32,18 @@
 #include "dawn_native/opengl/SwapChainGL.h"
 #include "dawn_native/opengl/TextureGL.h"
 
+namespace dawn_native {
+    dawnProcTable GetProcs();
+}  // namespace dawn_native
+
 namespace dawn_native { namespace opengl {
-    dawnProcTable GetNonValidatingProcs();
-    dawnProcTable GetValidatingProcs();
 
     void Init(void* (*getProc)(const char*), dawnProcTable* procs, dawnDevice* device) {
         *device = nullptr;
 
         gladLoadGLLoader(reinterpret_cast<GLADloadproc>(getProc));
 
-        *procs = GetValidatingProcs();
+        *procs = GetProcs();
         *device = reinterpret_cast<dawnDevice>(new Device);
 
         glEnable(GL_DEPTH_TEST);
diff --git a/src/dawn_native/opengl/GeneratedCodeIncludes.h b/src/dawn_native/opengl/GeneratedCodeIncludes.h
deleted file mode 100644
index 10b3c8d..0000000
--- a/src/dawn_native/opengl/GeneratedCodeIncludes.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2017 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.
-
-#include "dawn_native/BindGroup.h"
-#include "dawn_native/BindGroupLayout.h"
-#include "dawn_native/RenderPassDescriptor.h"
-#include "dawn_native/opengl/BlendStateGL.h"
-#include "dawn_native/opengl/BufferGL.h"
-#include "dawn_native/opengl/CommandBufferGL.h"
-#include "dawn_native/opengl/ComputePipelineGL.h"
-#include "dawn_native/opengl/DepthStencilStateGL.h"
-#include "dawn_native/opengl/DeviceGL.h"
-#include "dawn_native/opengl/InputStateGL.h"
-#include "dawn_native/opengl/PersistentPipelineStateGL.h"
-#include "dawn_native/opengl/PipelineLayoutGL.h"
-#include "dawn_native/opengl/QueueGL.h"
-#include "dawn_native/opengl/RenderPipelineGL.h"
-#include "dawn_native/opengl/SamplerGL.h"
-#include "dawn_native/opengl/ShaderModuleGL.h"
-#include "dawn_native/opengl/SwapChainGL.h"
-#include "dawn_native/opengl/TextureGL.h"
diff --git a/src/dawn_native/opengl/QueueGL.cpp b/src/dawn_native/opengl/QueueGL.cpp
index 5c6d10d..ad17160 100644
--- a/src/dawn_native/opengl/QueueGL.cpp
+++ b/src/dawn_native/opengl/QueueGL.cpp
@@ -22,9 +22,9 @@
     Queue::Queue(Device* device) : QueueBase(device) {
     }
 
-    void Queue::Submit(uint32_t numCommands, CommandBuffer* const* commands) {
+    void Queue::SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) {
         for (uint32_t i = 0; i < numCommands; ++i) {
-            commands[i]->Execute();
+            ToBackend(commands[i])->Execute();
         }
     }
 
diff --git a/src/dawn_native/opengl/QueueGL.h b/src/dawn_native/opengl/QueueGL.h
index d8bbfa7..f473049 100644
--- a/src/dawn_native/opengl/QueueGL.h
+++ b/src/dawn_native/opengl/QueueGL.h
@@ -26,8 +26,8 @@
       public:
         Queue(Device* device);
 
-        // Dawn API
-        void Submit(uint32_t numCommands, CommandBuffer* const* commands);
+      private:
+        void SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) override;
     };
 
 }}  // namespace dawn_native::opengl
diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp
index 914a970..7365ed6 100644
--- a/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/src/dawn_native/vulkan/DeviceVk.cpp
@@ -51,15 +51,16 @@
 #    error "Unimplemented Vulkan backend platform"
 #endif
 
-namespace dawn_native { namespace vulkan {
+namespace dawn_native {
+    dawnProcTable GetProcs();
+}  // namespace dawn_native
 
-    dawnProcTable GetNonValidatingProcs();
-    dawnProcTable GetValidatingProcs();
+namespace dawn_native { namespace vulkan {
 
     void Init(dawnProcTable* procs,
               dawnDevice* device,
               const std::vector<const char*>& requiredInstanceExtensions) {
-        *procs = GetValidatingProcs();
+        *procs = GetProcs();
         *device = reinterpret_cast<dawnDevice>(new Device(requiredInstanceExtensions));
     }
 
diff --git a/src/dawn_native/vulkan/GeneratedCodeIncludes.h b/src/dawn_native/vulkan/GeneratedCodeIncludes.h
deleted file mode 100644
index 2f8beee..0000000
--- a/src/dawn_native/vulkan/GeneratedCodeIncludes.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2017 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.
-
-#include "dawn_native/vulkan/BindGroupLayoutVk.h"
-#include "dawn_native/vulkan/BindGroupVk.h"
-#include "dawn_native/vulkan/BlendStateVk.h"
-#include "dawn_native/vulkan/BufferVk.h"
-#include "dawn_native/vulkan/CommandBufferVk.h"
-#include "dawn_native/vulkan/ComputePipelineVk.h"
-#include "dawn_native/vulkan/DepthStencilStateVk.h"
-#include "dawn_native/vulkan/DeviceVk.h"
-#include "dawn_native/vulkan/InputStateVk.h"
-#include "dawn_native/vulkan/PipelineLayoutVk.h"
-#include "dawn_native/vulkan/QueueVk.h"
-#include "dawn_native/vulkan/RenderPassDescriptorVk.h"
-#include "dawn_native/vulkan/RenderPipelineVk.h"
-#include "dawn_native/vulkan/SamplerVk.h"
-#include "dawn_native/vulkan/ShaderModuleVk.h"
-#include "dawn_native/vulkan/SwapChainVk.h"
-#include "dawn_native/vulkan/TextureVk.h"
diff --git a/src/dawn_native/vulkan/QueueVk.cpp b/src/dawn_native/vulkan/QueueVk.cpp
index c737940..e3de8b3 100644
--- a/src/dawn_native/vulkan/QueueVk.cpp
+++ b/src/dawn_native/vulkan/QueueVk.cpp
@@ -25,12 +25,12 @@
     Queue::~Queue() {
     }
 
-    void Queue::Submit(uint32_t numCommands, CommandBuffer* const* commands) {
+    void Queue::SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) {
         Device* device = ToBackend(GetDevice());
 
         VkCommandBuffer commandBuffer = device->GetPendingCommandBuffer();
         for (uint32_t i = 0; i < numCommands; ++i) {
-            commands[i]->RecordCommands(commandBuffer);
+            ToBackend(commands[i])->RecordCommands(commandBuffer);
         }
 
         device->SubmitPendingCommands();
diff --git a/src/dawn_native/vulkan/QueueVk.h b/src/dawn_native/vulkan/QueueVk.h
index 6745c40..9fc6079 100644
--- a/src/dawn_native/vulkan/QueueVk.h
+++ b/src/dawn_native/vulkan/QueueVk.h
@@ -27,8 +27,8 @@
         Queue(Device* device);
         ~Queue();
 
-        // Dawn API
-        void Submit(uint32_t numCommands, CommandBuffer* const* commands);
+      private:
+        void SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) override;
     };
 
 }}  // namespace dawn_native::vulkan