Factor autogen validation utilities out of ProcTable
diff --git a/generator/main.py b/generator/main.py
index 0f58ed2..8f028f0 100644
--- a/generator/main.py
+++ b/generator/main.py
@@ -434,7 +434,11 @@
         backend_params = {
             'namespace': backend,
         }
-        renders.append(FileRender('BackendProcTable.cpp', backend + '/ProcTable.' + extension, base_backend_params + [backend_params]))
+        renders.append(FileRender('backend/ProcTable.cpp', 'backend/' + backend + '/ProcTable.' + extension, base_backend_params + [backend_params]))
+
+    if 'backend_utils' in targets:
+        renders.append(FileRender('backend/ValidationUtils.h', 'backend/ValidationUtils_autogen.h', base_backend_params))
+        renders.append(FileRender('backend/ValidationUtils.cpp', 'backend/ValidationUtils_autogen.cpp', base_backend_params))
 
     if 'wire' in targets:
         renders.append(FileRender('wire/WireCmd.h', 'wire/WireCmd_autogen.h', base_backend_params))
diff --git a/generator/templates/BackendProcTable.cpp b/generator/templates/backend/ProcTable.cpp
similarity index 87%
rename from generator/templates/BackendProcTable.cpp
rename to generator/templates/backend/ProcTable.cpp
index e6a62e0..df0054e 100644
--- a/generator/templates/BackendProcTable.cpp
+++ b/generator/templates/backend/ProcTable.cpp
@@ -17,6 +17,7 @@
 
 #include "common/Assert.h"
 
+#include "backend/ValidationUtils_autogen.h"
 #include "backend/{{namespace}}/GeneratedCodeIncludes.h"
 
 namespace backend {
@@ -24,28 +25,6 @@
 
     namespace {
 
-        //* Helper functions to check the value of enums
-        {% for type in by_category["enum"] %}
-            {% set cType = as_cType(type.name) %}
-            bool CheckEnum{{cType}}({{cType}} value) {
-                switch (value) {
-                    {% for value in type.values %}
-                        case {{as_cEnum(type.name, value.name)}}:
-                            return true;
-                    {% endfor %}
-                    default:
-                        return false;
-                }
-            }
-        {% endfor %}
-
-        {% for type in by_category["bitmask"] %}
-            {% set cType = as_cType(type.name) %}
-            bool CheckBitmask{{cType}}({{cType}} value) {
-                return (value & ~{{type.full_mask}}) == 0;
-            }
-        {% endfor %}
-
         {% set methodsWithExtraValidation = (
             "CommandBufferBuilderGetResult",
             "QueueSubmit",
@@ -100,10 +79,9 @@
                     {% endif %}
                     bool error = false;
                     {% for arg in method.arguments %}
-                        {% if arg.type.category == "enum" %}
-                            if (!CheckEnum{{as_cType(arg.type.name)}}({{as_varName(arg.name)}})) error = true;;
-                        {% elif arg.type.category == "bitmask" %}
-                            if (!CheckBitmask{{as_cType(arg.type.name)}}({{as_varName(arg.name)}})) error = true;
+                        {% set cppType = as_cppType(arg.type.name) %}
+                        {% if arg.type.category in ["enum", "bitmask"] %}
+                            if (!IsValid{{cppType}}(static_cast<nxt::{{cppType}}>({{as_varName(arg.name)}}))) error = true;
                         {% else %}
                             (void) {{as_varName(arg.name)}};
                         {% endif %}
diff --git a/generator/templates/backend/ValidationUtils.cpp b/generator/templates/backend/ValidationUtils.cpp
new file mode 100644
index 0000000..0de1f66
--- /dev/null
+++ b/generator/templates/backend/ValidationUtils.cpp
@@ -0,0 +1,40 @@
+//* Copyright 2018 The NXT 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 "backend/ValidationUtils_autogen.h"
+
+namespace backend {
+
+    {% for type in by_category["enum"] %}
+        bool IsValid{{type.name.CamelCase()}}(nxt::{{as_cppType(type.name)}} value) {
+            switch (value) {
+                {% for value in type.values %}
+                    case nxt::{{as_cppType(type.name)}}::{{as_cppEnum(value.name)}}:
+                        return true;
+                {% endfor %}
+                default:
+                    return false;
+            }
+        }
+
+    {% endfor %}
+
+    {% for type in by_category["bitmask"] %}
+        bool IsValid{{type.name.CamelCase()}}(nxt::{{as_cppType(type.name)}} value) {
+            return (value & static_cast<nxt::{{as_cppType(type.name)}}>(~{{type.full_mask}})) == 0;
+        }
+
+    {% endfor %}
+
+} // namespace backend
diff --git a/generator/templates/backend/ValidationUtils.h b/generator/templates/backend/ValidationUtils.h
new file mode 100644
index 0000000..944a027
--- /dev/null
+++ b/generator/templates/backend/ValidationUtils.h
@@ -0,0 +1,29 @@
+//* Copyright 2018 The NXT 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.
+
+#ifndef BACKEND_VALIDATIONUTILS_H_
+#define BACKEND_VALIDATIONUTILS_H_
+
+#include "nxt/nxtcpp.h"
+
+namespace backend {
+
+    // Helper functions to check the value of enums and bitmasks
+    {% for type in by_category["enum"] + by_category["bitmask"] %}
+        bool IsValid{{type.name.CamelCase()}}(nxt::{{as_cppType(type.name)}} value);
+    {% endfor %}
+
+} // namespace backend
+
+#endif  // BACKEND_VALIDATIONUTILS_H_
diff --git a/src/backend/CMakeLists.txt b/src/backend/CMakeLists.txt
index 1136e7f..4d6cb62 100644
--- a/src/backend/CMakeLists.txt
+++ b/src/backend/CMakeLists.txt
@@ -19,6 +19,18 @@
 set(OPENGL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/opengl)
 set(VULKAN_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vulkan)
 
+Generate(
+    LIB_NAME backend_utils_autogen
+    LIB_TYPE STATIC
+    FOLDER "backend"
+    PRINT_NAME "Autogenerated backend utilities"
+    COMMAND_LINE_ARGS
+        ${GENERATOR_COMMON_ARGS}
+        -T backend_utils
+)
+target_link_libraries(backend_utils_autogen nxtcpp)
+target_include_directories(backend_utils_autogen PUBLIC ${GENERATED_DIR})
+
 function(GenerateProcTable backend)
     Generate(
         LIB_NAME ${backend}_autogen
@@ -29,7 +41,7 @@
             ${GENERATOR_COMMON_ARGS}
             -T ${backend}
     )
-    target_link_libraries(${backend}_autogen nxtcpp)
+    target_link_libraries(${backend}_autogen nxtcpp backend_utils_autogen)
     target_include_directories(${backend}_autogen PRIVATE ${SRC_DIR})
     target_include_directories(${backend}_autogen PUBLIC ${GENERATED_DIR})
 endfunction()
@@ -304,7 +316,7 @@
 endif()
 
 ################################################################################
-# Common sources definition of the library
+# Common sources and definition of the library
 ################################################################################
 
 list(APPEND BACKEND_SOURCES