Import Tint changes from Dawn

Changes:
  - 55c0c9d950edb4f45b2f94d5c3e4114fc30609e8 tint: Add abstract numerics to vector and matrix construc... by Ben Clayton <bclayton@google.com>
  - d3de38d7e3880a90cbed8f8fb895729e580c8fbd tint: Simplify the resolver constant evaluation by Ben Clayton <bclayton@google.com>
  - 8f4f4495408cfde7755be8127180178015bf7d40 tint/writer: Do not attempt to use invalid programs by Ben Clayton <bclayton@google.com>
  - 6522837acbf96682583ada4ead5c8e86f28df437 tint: Add `enable_abstract_numerics` flag on Resolver by Ben Clayton <bclayton@google.com>
  - 43581f1fb62ced507e1693c2e8959ed342dd7f6a tint: Add new methods to semantic Switch nodes by Ben Clayton <bclayton@google.com>
  - a2ce4ecc8b325ff79176a867b6074b6ca733851b tint: Add more helpers to resolver_test_helper.h by Ben Clayton <bclayton@google.com>
  - d99af036634c3dc612d18042465bfcc45203fffc tint: Add utils::UniqueVector::data() by Ben Clayton <bclayton@google.com>
  - ab4c0357629178ec2c217b4b05ad715142546fe1 tint: fix HLSL countOneBits and reverseBits for i32 args by Antonio Maiorano <amaiorano@google.com>
  - e9ce8326b7843be34e8a31a5a54600cb924c83f2 tint: Minor, miscellaneous cleanups by Ben Clayton <bclayton@google.com>
  - eee9f88ba21b182d7eb23bbc85af17f69185e34a tint: Extract intrinsic-table common type to helper by Ben Clayton <bclayton@google.com>
  - 1b35e3f9a8c10c11d750fde76f0862e8e9bc9534 tint: Add new sem::Type helpers by Ben Clayton <bclayton@google.com>
  - e5a67ac891a5c8aa584b7998d35453a29b778a93 tint: Remove ast::CallExpression -> sem::Call implicit ma... by Ben Clayton <bclayton@google.com>
  - 7b921fb4c778b324d706f78a91d5e047626f2292 tint: No-op Resolver refactoring by Ben Clayton <bclayton@google.com>
  - 86a617f1108cbfa49c8c1faebc7b4af8acd36588 Add InsertBraces: true to .clang-format by Austin Eng <enga@chromium.org>
  - 2081ee43bf51005e2dbed2b271254d517e998fd0 tint: Add sem::Materialize by Ben Clayton <bclayton@google.com>
  - 6ac00ed0c0cff0401da91b4faad649d0ea81f2d5 tint: IntrinsicTable: Add abstract numeric types by Ben Clayton <bclayton@google.com>
  - b1fa457ab3c362a12bd885254352fc617d89f808 tint: IntrinsicTable: Use [[display]] name for type match... by Ben Clayton <bclayton@google.com>
  - b0664684cd887f8c8163e70b64c797852b86e276 tint: Support tuples in utils::Hash(). by Ben Clayton <bclayton@google.com>
  - 7f2b8cd8fc8edf464602ea64d2145def40fa3475 tint: Refactor Extensions / Enables. by Ben Clayton <bclayton@google.com>
  - 23696b1ba3fd523f9f989677890af18db0d68d7a tint: Implement abstract-numeric overload resolution by Ben Clayton <bclayton@google.com>
  - 2e681052b313ed547189d95d58d73081c028d604 tint: Fix use-after-free by Antonio Maiorano <amaiorano@google.com>
  - c670018aea9f3ff989699b47c0b5d5a977213cc8 tint: intrinsics.def Support [[precedence]] decoration by Ben Clayton <bclayton@google.com>
  - 5ff7d67bf341af630c8945296155b77edc13ef81 tint: Validate that sampled texture type must be f32, i32... by Antonio Maiorano <amaiorano@google.com>
  - e0ff664a7f0dee5ac9c3c19e48121b6cfca89c31 tint: Add sem::Type::ConversionRank() by Ben Clayton <bclayton@google.com>
  - 4c9ed74b5e5bded47aa034026a6ea80b27dd666b tint: IntrinsicTable: Rename open/closed -> template by Ben Clayton <bclayton@google.com>
  - aaa9ba30436bdb23a59b9eaa4e65f1808cba0dec tint: Simplify sem::Constant::Scalar by Ben Clayton <bclayton@google.com>
  - 661e33ca185f766019bd27fedda57a354efed787 tint: Cleanup of IntrinsicTable by Ben Clayton <bclayton@google.com>
  - 8ba6e1d6ecdd3f9438b5034d32b301152cb931f8 tint: limit expression depth to avoid stack overflow in b... by Antonio Maiorano <amaiorano@google.com>
  - 5880ed164abb36f816bbea1a715ad7bc988c3648 tint: Fix edge for CallSiteRequiredToBeUniform by James Price <jrprice@google.com>
  - 3b5edf143505f6b97f065e83de0d63f647fd3e50 tint: Add matrix identify and single-scalar ctors by Ben Clayton <bclayton@google.com>
  - 6ae608cb03840d1f8b075289f4445f149ab33f0a tint: Add constructors and conversions to the intrinsic t... by Ben Clayton <bclayton@google.com>
  - 9ff8abf34711e4e740b68c10fc0c90bbc441c7e5 tint: Fix clang chromium-style warnings treated as errors by Ben Clayton <bclayton@google.com>
  - e6b6777c8e56b0940315b9fef97a13e021c61747 tint: Fix MSL generation of '&' and '|' with booleans by Ben Clayton <bclayton@google.com>
  - 35f0fcaac0f6e0d0a56e8f5f7c00cd297256d518 tint/uniformity: Use non-recursive graph traversal by James Price <jrprice@google.com>
  - a89ff5981bc0c17e980a5dbdb4f2da870ed79db0 tint: Show where control flow became non-uniform by James Price <jrprice@google.com>
  - 1c75921db9c0095d7ab96c686f51efa2951b2f4f tint: fix translation of DP4a on HLSL by Jiawei Shao <jiawei.shao@intel.com>
  - d8e77e2e73afd5bb2238ac322d7acbdd084ec410 tint: Prevent integer overflow in IntrinsicTable by Ben Clayton <bclayton@google.com>
  - 83fc247d4bb9ab23616a697f272d69f29f44447f tint: correctly define user-defined literals by Antonio Maiorano <amaiorano@google.com>
  - 59e23943f3b1442281208e879e6bc4c5f478ca91 tint: Minor IntrinsicTable cleanup by Ben Clayton <bclayton@google.com>
  - 77473b469958b242509c9eb9271bbcf908e791de tint: Split tables for unary and binary operators by Ben Clayton <bclayton@google.com>
  - 62bfd318aefae4b5a1f50813f90bf0b8b821849b tint: Implement `f16` keyword in Tint frontend by Zhaoming Jiang <zhaoming.jiang@intel.com>
  - c4b380b8af94fe8b7a61ae8bd3f735f9d7a51380 tint: Generalize sem::Vector to allow 16bits subtype by Zhaoming Jiang <zhaoming.jiang@intel.com>
  - ed6ff9c948005a23fb2d592c5ea069d778bca083 tint: Rename kNotAnExtenxion to kNoExtension by Zhaoming Jiang <zhaoming.jiang@intel.com>
  - ab9757036bd6b2fe86c4e937db0524463ba0c0f8 tint: Implement DP4a on HLSL writer by Jiawei Shao <jiawei.shao@intel.com>
  - 53547db1d4f045d93ee408b6a30da25eb88ef056 tint: Add missing source information for | and || by James Price <jrprice@google.com>
  - 816148fe3291d3def83de76584cfe32af8572f49 tint: Add implicit CF_return->{last cf} edge by James Price <jrprice@google.com>
  - cd55f15c98de761c6410e19670398c149aa96dbe tint/resolver: Fix chromium-style warning treated as error by Ben Clayton <bclayton@google.com>
  - 7dd0ab791a59c89b628981f82f56b9ee3e8208b6 tint: Show the source of non-uniformity by James Price <jrprice@google.com>
  - 9c03abfb554fd64adb66a9f11d7e84766cdc15b3 tint: Show the reason for a uniformity requirement by James Price <jrprice@google.com>
  - 874b61f1badfe275c480d1dcb6d32b867391de73 tint/uniformity: Retain control flow graphs by James Price <jrprice@google.com>
  - be656f7984a48e3c4e9a3c9dcc0ba7bbdc3da278 tint: Implement uniformity analaysis by James Price <jrprice@google.com>
  - 8e68f0aad7c3994ddbd1914a48d82c43dd6e7e56 tint: Resolve empty loop continuing blocks by James Price <jrprice@google.com>
  - 2cf32b13d7c294a7a3b4e87f9ab11aebbb519e81 tint: Make ScopeStack key type generic by James Price <jrprice@google.com>
  - 791b4351d1860e1d447f182619e8bd1023dc47eb tint: Add transform to disable uniformity analysis by James Price <jrprice@google.com>
GitOrigin-RevId: 55c0c9d950edb4f45b2f94d5c3e4114fc30609e8
Change-Id: I584598c20d24d8cadb29f63b5e1f46aac06aebb2
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/89880
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@chromium.org>
Reviewed-by: Ben Clayton <bclayton@chromium.org>
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index 259a26b..fbf443c 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -226,8 +226,12 @@
     "ast/enable.h",
     "ast/expression.cc",
     "ast/expression.h",
+    "ast/extension.cc",
+    "ast/extension.h",
     "ast/external_texture.cc",
     "ast/external_texture.h",
+    "ast/f16.cc",
+    "ast/f16.h",
     "ast/f32.cc",
     "ast/f32.h",
     "ast/fallthrough_statement.cc",
@@ -342,7 +346,6 @@
     "debug.h",
     "demangler.cc",
     "demangler.h",
-    "number.h",
     "diagnostic/diagnostic.cc",
     "diagnostic/diagnostic.h",
     "diagnostic/formatter.cc",
@@ -357,6 +360,7 @@
     "inspector/resource_binding.h",
     "inspector/scalar.cc",
     "inspector/scalar.h",
+    "number.h",
     "program.cc",
     "program.h",
     "program_builder.cc",
@@ -365,6 +369,8 @@
     "program_id.h",
     "reader/reader.cc",
     "reader/reader.h",
+    "resolver/ctor_conv_intrinsic.cc",
+    "resolver/ctor_conv_intrinsic.h",
     "resolver/dependency_graph.cc",
     "resolver/dependency_graph.h",
     "resolver/intrinsic_table.cc",
@@ -375,9 +381,14 @@
     "resolver/resolver_constants.cc",
     "resolver/sem_helper.cc",
     "resolver/sem_helper.h",
+    "resolver/uniformity.cc",
+    "resolver/uniformity.h",
     "resolver/validator.cc",
     "resolver/validator.h",
     "scope_stack.h",
+    "sem/abstract_float.h",
+    "sem/abstract_int.h",
+    "sem/abstract_numeric.h",
     "sem/array.h",
     "sem/atomic.h",
     "sem/behavior.h",
@@ -392,6 +403,7 @@
     "sem/depth_texture.h",
     "sem/expression.h",
     "sem/external_texture.h",
+    "sem/f16.h",
     "sem/f32.h",
     "sem/for_loop_statement.h",
     "sem/i32.h",
@@ -451,6 +463,8 @@
     "transform/decompose_strided_array.h",
     "transform/decompose_strided_matrix.cc",
     "transform/decompose_strided_matrix.h",
+    "transform/disable_uniformity_analysis.cc",
+    "transform/disable_uniformity_analysis.h",
     "transform/expand_compound_assignment.cc",
     "transform/expand_compound_assignment.h",
     "transform/first_index_offset.cc",
@@ -587,6 +601,8 @@
     "sem/expression.h",
     "sem/external_texture.cc",
     "sem/external_texture.h",
+    "sem/f16.cc",
+    "sem/f16.h",
     "sem/f32.cc",
     "sem/f32.h",
     "sem/for_loop_statement.cc",
@@ -600,6 +616,8 @@
     "sem/info.h",
     "sem/loop_statement.cc",
     "sem/loop_statement.h",
+    "sem/materialize.cc",
+    "sem/materialize.h",
     "sem/matrix.cc",
     "sem/matrix.h",
     "sem/member_accessor_expression.cc",
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index 682817f..85ec3db 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -114,8 +114,12 @@
   ast/enable.h
   ast/expression.cc
   ast/expression.h
+  ast/extension.cc
+  ast/extension.h
   ast/external_texture.cc
   ast/external_texture.h
+  ast/f16.cc
+  ast/f16.h
   ast/f32.cc
   ast/f32.h
   ast/fallthrough_statement.cc
@@ -246,6 +250,8 @@
   program.h
   reader/reader.cc
   reader/reader.h
+  resolver/ctor_conv_intrinsic.cc
+  resolver/ctor_conv_intrinsic.h
   resolver/dependency_graph.cc
   resolver/dependency_graph.h
   resolver/intrinsic_table.cc
@@ -256,6 +262,8 @@
   resolver/resolver.h
   resolver/sem_helper.cc
   resolver/sem_helper.h
+  resolver/uniformity.cc
+  resolver/uniformity.h
   resolver/validator.cc
   resolver/validator.h
   scope_stack.h
@@ -333,6 +341,8 @@
   transform/decompose_strided_array.h
   transform/decompose_strided_matrix.cc
   transform/decompose_strided_matrix.h
+  transform/disable_uniformity_analysis.cc
+  transform/disable_uniformity_analysis.h
   transform/first_index_offset.cc
   transform/first_index_offset.h
   transform/fold_constants.cc
@@ -399,6 +409,8 @@
   sem/depth_texture.h
   sem/external_texture.cc
   sem/external_texture.h
+  sem/f16.cc
+  sem/f16.h
   sem/f32.cc
   sem/f32.h
   sem/for_loop_statement.cc
@@ -409,6 +421,8 @@
   sem/if_statement.h
   sem/loop_statement.cc
   sem/loop_statement.h
+  sem/materialize.cc
+  sem/materialize.h
   sem/matrix.cc
   sem/matrix.h
   sem/multisampled_texture.cc
@@ -681,7 +695,9 @@
     ast/depth_texture_test.cc
     ast/discard_statement_test.cc
     ast/enable_test.cc
+    ast/extension_test.cc
     ast/external_texture_test.cc
+    ast/f16_test.cc
     ast/f32_test.cc
     ast/fallthrough_statement_test.cc
     ast/float_literal_expression_test.cc
@@ -785,7 +801,9 @@
     sem/builtin_test.cc
     sem/depth_multisampled_texture_test.cc
     sem/depth_texture_test.cc
+    sem/expression_test.cc
     sem/external_texture_test.cc
+    sem/f16_test.cc
     sem/f32_test.cc
     sem/i32_test.cc
     sem/matrix_test.cc
@@ -798,6 +816,7 @@
     sem/sem_struct_test.cc
     sem/storage_texture_test.cc
     sem/texture_test.cc
+    sem/type_test.cc
     sem/type_manager_test.cc
     sem/u32_test.cc
     sem/vector_test.cc
@@ -831,6 +850,13 @@
     writer/text_generator_test.cc
   )
 
+  # Uniformity analysis tests depend on WGSL reader
+  if(${TINT_BUILD_WGSL_READER})
+    list(APPEND TINT_TEST_SRCS
+      resolver/uniformity_test.cc
+    )
+  endif()
+
   # Inspector tests depend on WGSL reader
   if(${TINT_BUILD_WGSL_READER})
     list(APPEND TINT_TEST_SRCS
@@ -1044,6 +1070,7 @@
       transform/decompose_memory_access_test.cc
       transform/decompose_strided_array_test.cc
       transform/decompose_strided_matrix_test.cc
+      transform/disable_uniformity_analysis_test.cc
       transform/expand_compound_assignment_test.cc
       transform/first_index_offset_test.cc
       transform/fold_constants_test.cc
diff --git a/src/tint/ast/enable.cc b/src/tint/ast/enable.cc
index 857e110..ef43200 100644
--- a/src/tint/ast/enable.cc
+++ b/src/tint/ast/enable.cc
@@ -21,37 +21,7 @@
 
 namespace tint::ast {
 
-Enable::ExtensionKind Enable::NameToKind(const std::string& name) {
-    if (name == "chromium_experimental_dp4a") {
-        return Enable::ExtensionKind::kChromiumExperimentalDP4a;
-    }
-
-    // The reserved internal extension name for testing
-    if (name == "InternalExtensionForTesting") {
-        return Enable::ExtensionKind::kInternalExtensionForTesting;
-    }
-
-    return Enable::ExtensionKind::kNotAnExtension;
-}
-
-std::string Enable::KindToName(ExtensionKind kind) {
-    switch (kind) {
-        case ExtensionKind::kChromiumExperimentalDP4a:
-            return "chromium_experimental_dp4a";
-        // The reserved internal extension for testing
-        case ExtensionKind::kInternalExtensionForTesting:
-            return "InternalExtensionForTesting";
-        case ExtensionKind::kNotAnExtension:
-            // Return an empty string for kNotAnExtension
-            return {};
-            // No default case, as this switch must cover all ExtensionKind values.
-    }
-    // This return shall never get hit.
-    return {};
-}
-
-Enable::Enable(ProgramID pid, const Source& src, const std::string& ext_name)
-    : Base(pid, src), name(ext_name), kind(NameToKind(ext_name)) {}
+Enable::Enable(ProgramID pid, const Source& src, Extension ext) : Base(pid, src), extension(ext) {}
 
 Enable::Enable(Enable&&) = default;
 
@@ -59,6 +29,6 @@
 
 const Enable* Enable::Clone(CloneContext* ctx) const {
     auto src = ctx->Clone(source);
-    return ctx->dst->create<Enable>(src, name);
+    return ctx->dst->create<Enable>(src, extension);
 }
 }  // namespace tint::ast
diff --git a/src/tint/ast/enable.h b/src/tint/ast/enable.h
index 7bcd20e..674d9cb 100644
--- a/src/tint/ast/enable.h
+++ b/src/tint/ast/enable.h
@@ -16,57 +16,26 @@
 #define SRC_TINT_AST_ENABLE_H_
 
 #include <string>
-#include <unordered_set>
 #include <utility>
+#include <vector>
 
-#include "src/tint/ast/access.h"
-#include "src/tint/ast/expression.h"
+#include "src/tint/ast/extension.h"
+#include "src/tint/ast/node.h"
 
 namespace tint::ast {
 
-/// An instance of this class represents one extension mentioned in a
-/// "enable" derictive. Example:
-///       // Enable an extension named "f16"
-///       enable f16;
-class Enable : public Castable<Enable, Node> {
+/// An "enable" directive. Example:
+/// ```
+///   // Enable an extension named "f16"
+///   enable f16;
+/// ```
+class Enable final : public Castable<Enable, Node> {
   public:
-    ///  The enum class identifing each supported WGSL extension
-    enum class ExtensionKind {
-        /// An extension for the experimental feature
-        /// "chromium_experimental_dp4a".
-        /// See crbug.com/tint/1497 for more details
-        kChromiumExperimentalDP4a,
-
-        /// An internal reserved extension for test, named
-        /// "InternalExtensionForTesting"
-        kInternalExtensionForTesting = -2,
-        kNotAnExtension = -1,
-    };
-
-    /// Convert a string of extension name into one of ExtensionKind enum value,
-    /// the result will be ExtensionKind::kNotAnExtension if the name is not a
-    /// known extension name. A extension node of kind kNotAnExtension must not
-    /// exist in the AST tree, and using a unknown extension name in WGSL code
-    /// should result in a shader-creation error.
-    /// @param name string of the extension name
-    /// @return the ExtensionKind enum value for the extension of given name, or
-    /// kNotAnExtension if no known extension has the given name
-    static ExtensionKind NameToKind(const std::string& name);
-
-    /// Convert the ExtensionKind enum value to corresponding extension name
-    /// string. If the given enum value is kNotAnExtension or don't have a known
-    /// name, return an empty string instead.
-    /// @param kind the ExtensionKind enum value
-    /// @return string of the extension name corresponding to the given kind, or
-    /// an empty string if the given enum value is kNotAnExtension or don't have a
-    /// known corresponding name
-    static std::string KindToName(ExtensionKind kind);
-
     /// Create a extension
     /// @param pid the identifier of the program that owns this node
     /// @param src the source of this node
-    /// @param name the name of extension
-    Enable(ProgramID pid, const Source& src, const std::string& name);
+    /// @param ext the extension
+    Enable(ProgramID pid, const Source& src, Extension ext);
     /// Move constructor
     Enable(Enable&&);
 
@@ -79,14 +48,11 @@
     const Enable* Clone(CloneContext* ctx) const override;
 
     /// The extension name
-    const std::string name;
-
-    /// The extension kind
-    const ExtensionKind kind;
+    const Extension extension;
 };
 
-///  A set of extension kinds
-using ExtensionSet = std::unordered_set<Enable::ExtensionKind>;
+/// A list of enables
+using EnableList = std::vector<const Enable*>;
 
 }  // namespace tint::ast
 
diff --git a/src/tint/ast/enable_test.cc b/src/tint/ast/enable_test.cc
index 9fde780..e8b6e5c 100644
--- a/src/tint/ast/enable_test.cc
+++ b/src/tint/ast/enable_test.cc
@@ -19,40 +19,15 @@
 namespace tint::ast {
 namespace {
 
-using AstExtensionTest = TestHelper;
+using EnableTest = TestHelper;
 
-TEST_F(AstExtensionTest, Creation) {
-    auto* ext =
-        create<Enable>(Source{Source::Range{Source::Location{20, 2}, Source::Location{20, 5}}},
-                       "InternalExtensionForTesting");
+TEST_F(EnableTest, Creation) {
+    auto* ext = create<ast::Enable>(Source{{{20, 2}, {20, 5}}}, Extension::kF16);
     EXPECT_EQ(ext->source.range.begin.line, 20u);
     EXPECT_EQ(ext->source.range.begin.column, 2u);
     EXPECT_EQ(ext->source.range.end.line, 20u);
     EXPECT_EQ(ext->source.range.end.column, 5u);
-    EXPECT_EQ(ext->kind, ast::Enable::ExtensionKind::kInternalExtensionForTesting);
-}
-
-TEST_F(AstExtensionTest, Creation_InvalidName) {
-    auto* ext = create<Enable>(
-        Source{Source::Range{Source::Location{20, 2}, Source::Location{20, 5}}}, std::string());
-    EXPECT_EQ(ext->source.range.begin.line, 20u);
-    EXPECT_EQ(ext->source.range.begin.column, 2u);
-    EXPECT_EQ(ext->source.range.end.line, 20u);
-    EXPECT_EQ(ext->source.range.end.column, 5u);
-    EXPECT_EQ(ext->kind, ast::Enable::ExtensionKind::kNotAnExtension);
-}
-
-TEST_F(AstExtensionTest, NameToKind_InvalidName) {
-    EXPECT_EQ(ast::Enable::NameToKind(std::string()), ast::Enable::ExtensionKind::kNotAnExtension);
-    EXPECT_EQ(ast::Enable::NameToKind("__ImpossibleExtensionName"),
-              ast::Enable::ExtensionKind::kNotAnExtension);
-    EXPECT_EQ(ast::Enable::NameToKind("123"), ast::Enable::ExtensionKind::kNotAnExtension);
-}
-
-TEST_F(AstExtensionTest, KindToName) {
-    EXPECT_EQ(ast::Enable::KindToName(ast::Enable::ExtensionKind::kInternalExtensionForTesting),
-              "InternalExtensionForTesting");
-    EXPECT_EQ(ast::Enable::KindToName(ast::Enable::ExtensionKind::kNotAnExtension), std::string());
+    EXPECT_EQ(ext->extension, Extension::kF16);
 }
 
 }  // namespace
diff --git a/src/tint/ast/extension.cc b/src/tint/ast/extension.cc
new file mode 100644
index 0000000..f03e3a0
--- /dev/null
+++ b/src/tint/ast/extension.cc
@@ -0,0 +1,51 @@
+// Copyright 2022 The Tint 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 "src/tint/ast/extension.h"
+
+namespace tint::ast {
+
+Extension ParseExtension(const std::string& name) {
+    if (name == "chromium_experimental_dp4a") {
+        return Extension::kChromiumExperimentalDP4a;
+    }
+    if (name == "chromium_disable_uniformity_analysis") {
+        return Extension::kChromiumDisableUniformityAnalysis;
+    }
+    if (name == "f16") {
+        return Extension::kF16;
+    }
+    return Extension::kNone;
+}
+
+const char* str(Extension ext) {
+    switch (ext) {
+        case Extension::kChromiumExperimentalDP4a:
+            return "chromium_experimental_dp4a";
+        case Extension::kChromiumDisableUniformityAnalysis:
+            return "chromium_disable_uniformity_analysis";
+        case Extension::kF16:
+            return "f16";
+        case Extension::kNone:
+            return "<none>";
+    }
+    return "<unknown>";
+}
+
+std::ostream& operator<<(std::ostream& out, Extension i) {
+    out << str(i);
+    return out;
+}
+
+}  // namespace tint::ast
diff --git a/src/tint/ast/extension.h b/src/tint/ast/extension.h
new file mode 100644
index 0000000..21e9ac1
--- /dev/null
+++ b/src/tint/ast/extension.h
@@ -0,0 +1,68 @@
+// Copyright 2022 The Tint 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 SRC_TINT_AST_EXTENSION_H_
+#define SRC_TINT_AST_EXTENSION_H_
+
+#include <sstream>
+#include <string>
+
+#include "src/tint/utils/unique_vector.h"
+
+namespace tint::ast {
+
+/// An enumerator of WGSL extensions
+enum class Extension {
+    /// WGSL Extension "f16"
+    kF16,
+
+    /// An extension for the experimental feature
+    /// "chromium_experimental_dp4a".
+    /// See crbug.com/tint/1497 for more details
+    kChromiumExperimentalDP4a,
+    /// A Chromium-specific extension for disabling uniformity analysis.
+    kChromiumDisableUniformityAnalysis,
+
+    /// Reserved for representing "No extension required" or "Not a valid extension".
+    kNone,
+};
+
+/// Convert a string of extension name into one of Extension enum value, the result will be
+/// Extension::kNone if the name is not a known extension name. A extension node of kind
+/// kNone must not exist in the AST tree, and using a unknown extension name in WGSL code
+/// should result in a shader-creation error.
+/// @param name string of the extension name
+/// @return the Extension enum value for the extension of given name, or kNone if no known extension
+/// has the given name
+Extension ParseExtension(const std::string& name);
+
+/// Convert the Extension enum value to corresponding extension name string.
+/// @param ext the Extension enum value
+/// @return string of the extension name corresponding to the given kind, or
+/// an empty string if the given enum value is kNone or don't have a
+/// known corresponding name
+const char* ExtensionName(Extension ext);
+
+/// @returns the name of the extension.
+const char* str(Extension i);
+
+/// Emits the name of the extension type.
+std::ostream& operator<<(std::ostream& out, Extension i);
+
+// A unique vector of extensions
+using Extensions = utils::UniqueVector<Extension>;
+
+}  // namespace tint::ast
+
+#endif  // SRC_TINT_AST_EXTENSION_H_
diff --git a/src/tint/ast/extension_test.cc b/src/tint/ast/extension_test.cc
new file mode 100644
index 0000000..ed27674
--- /dev/null
+++ b/src/tint/ast/extension_test.cc
@@ -0,0 +1,36 @@
+
+// Copyright 2021 The Tint 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 "src/tint/ast/extension.h"
+
+#include "gtest/gtest.h"
+
+namespace tint::ast {
+namespace {
+
+TEST(ExtensionTest, NameToKind_InvalidName) {
+    EXPECT_EQ(ParseExtension("f16"), Extension::kF16);
+    EXPECT_EQ(ParseExtension(""), Extension::kNone);
+    EXPECT_EQ(ParseExtension("__ImpossibleExtensionName"), Extension::kNone);
+    EXPECT_EQ(ParseExtension("123"), Extension::kNone);
+}
+
+TEST(ExtensionTest, KindToName) {
+    EXPECT_EQ(std::string(str(Extension::kF16)), "f16");
+    EXPECT_EQ(std::string(str(Extension::kNone)), "<none>");
+}
+
+}  // namespace
+}  // namespace tint::ast
diff --git a/src/tint/ast/f16.cc b/src/tint/ast/f16.cc
new file mode 100644
index 0000000..0eb1be5
--- /dev/null
+++ b/src/tint/ast/f16.cc
@@ -0,0 +1,38 @@
+// Copyright 2022 The Tint 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 "src/tint/ast/f16.h"
+
+#include "src/tint/program_builder.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::ast::F16);
+
+namespace tint::ast {
+
+F16::F16(ProgramID pid, const Source& src) : Base(pid, src) {}
+
+F16::F16(F16&&) = default;
+
+F16::~F16() = default;
+
+std::string F16::FriendlyName(const SymbolTable&) const {
+    return "f16";
+}
+
+const F16* F16::Clone(CloneContext* ctx) const {
+    auto src = ctx->Clone(source);
+    return ctx->dst->create<F16>(src);
+}
+
+}  // namespace tint::ast
diff --git a/src/tint/ast/f16.h b/src/tint/ast/f16.h
new file mode 100644
index 0000000..1b84f09
--- /dev/null
+++ b/src/tint/ast/f16.h
@@ -0,0 +1,48 @@
+// Copyright 2022 The Tint 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 SRC_TINT_AST_F16_H_
+#define SRC_TINT_AST_F16_H_
+
+#include <string>
+
+#include "src/tint/ast/type.h"
+
+namespace tint::ast {
+
+/// A float 16 type
+class F16 : public Castable<F16, Type> {
+  public:
+    /// Constructor
+    /// @param pid the identifier of the program that owns this node
+    /// @param src the source of this node
+    F16(ProgramID pid, const Source& src);
+    /// Move constructor
+    F16(F16&&);
+    ~F16() override;
+
+    /// @param symbols the program's symbol table
+    /// @returns the name for this type that closely resembles how it would be
+    /// declared in WGSL.
+    std::string FriendlyName(const SymbolTable& symbols) const override;
+
+    /// Clones this type and all transitive types using the `CloneContext` `ctx`.
+    /// @param ctx the clone context
+    /// @return the newly cloned type
+    const F16* Clone(CloneContext* ctx) const override;
+};
+
+}  // namespace tint::ast
+
+#endif  // SRC_TINT_AST_F16_H_
diff --git a/src/tint/ast/f16_test.cc b/src/tint/ast/f16_test.cc
new file mode 100644
index 0000000..48ab284
--- /dev/null
+++ b/src/tint/ast/f16_test.cc
@@ -0,0 +1,30 @@
+// Copyright 2022 The Tint 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 "src/tint/ast/f16.h"
+
+#include "src/tint/ast/test_helper.h"
+
+namespace tint::ast {
+namespace {
+
+using AstF16Test = TestHelper;
+
+TEST_F(AstF16Test, FriendlyName) {
+    auto* f = create<F16>();
+    EXPECT_EQ(f->FriendlyName(Symbols()), "f16");
+}
+
+}  // namespace
+}  // namespace tint::ast
diff --git a/src/tint/ast/float_literal_expression.h b/src/tint/ast/float_literal_expression.h
index 321efc891..72a395f 100644
--- a/src/tint/ast/float_literal_expression.h
+++ b/src/tint/ast/float_literal_expression.h
@@ -30,6 +30,8 @@
         kNone,
         /// 'f' suffix (f32)
         kF,
+        /// 'h' suffix (f16)
+        kH,
     };
 
     /// Constructor
diff --git a/src/tint/ast/module.cc b/src/tint/ast/module.cc
index e163c19..40dff98 100644
--- a/src/tint/ast/module.cc
+++ b/src/tint/ast/module.cc
@@ -68,18 +68,18 @@
             TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, var, program_id);
             global_variables_.push_back(var);
         },
-        [&](const Enable* ext) {
-            TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, ext, program_id);
-            extensions_.insert(ext->kind);
+        [&](const Enable* enable) {
+            TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, enable, program_id);
+            enables_.push_back(enable);
         },
         [&](Default) { TINT_ICE(AST, diags) << "Unknown global declaration type"; });
 }
 
-void Module::AddEnable(const ast::Enable* ext) {
-    TINT_ASSERT(AST, ext);
-    TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, ext, program_id);
-    global_declarations_.push_back(ext);
-    extensions_.insert(ext->kind);
+void Module::AddEnable(const ast::Enable* enable) {
+    TINT_ASSERT(AST, enable);
+    TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, enable, program_id);
+    global_declarations_.push_back(enable);
+    enables_.push_back(enable);
 }
 
 void Module::AddGlobalVariable(const ast::Variable* var) {
@@ -117,7 +117,7 @@
     type_decls_.clear();
     functions_.clear();
     global_variables_.clear();
-    extensions_.clear();
+    enables_.clear();
 
     for (auto* decl : global_declarations_) {
         if (!decl) {
diff --git a/src/tint/ast/module.h b/src/tint/ast/module.h
index d8be2ed..45b1ec6 100644
--- a/src/tint/ast/module.h
+++ b/src/tint/ast/module.h
@@ -78,7 +78,7 @@
     VariableList& GlobalVariables() { return global_variables_; }
 
     /// @returns the extension set for the module
-    const ExtensionSet& Extensions() const { return extensions_; }
+    const EnableList& Enables() const { return enables_; }
 
     /// Adds a type declaration to the Builder.
     /// @param decl the type declaration to add
@@ -120,7 +120,7 @@
     std::vector<const TypeDecl*> type_decls_;
     FunctionList functions_;
     VariableList global_variables_;
-    ExtensionSet extensions_;
+    EnableList enables_;
 };
 
 }  // namespace tint::ast
diff --git a/src/tint/ast/traverse_expressions.h b/src/tint/ast/traverse_expressions.h
index 650273b..59b00e9 100644
--- a/src/tint/ast/traverse_expressions.h
+++ b/src/tint/ast/traverse_expressions.h
@@ -54,40 +54,59 @@
 /// @param root the root expression node
 /// @param diags the diagnostics used for error messages
 /// @param callback the callback function. Must be of the signature:
-///        `TraverseAction(const T*)` where T is an ast::Expression type.
+///        `TraverseAction(const T* expr)` or `TraverseAction(const T* expr, size_t depth)` where T
+///        is an ast::Expression type.
 /// @return true on success, false on error
 template <TraverseOrder ORDER = TraverseOrder::LeftToRight, typename CALLBACK>
 bool TraverseExpressions(const ast::Expression* root, diag::List& diags, CALLBACK&& callback) {
     using EXPR_TYPE = std::remove_pointer_t<traits::ParameterType<CALLBACK, 0>>;
-    std::vector<const ast::Expression*> to_visit{root};
+    constexpr static bool kHasDepthArg = traits::SignatureOfT<CALLBACK>::parameter_count == 2;
 
-    auto push_pair = [&](const ast::Expression* left, const ast::Expression* right) {
+    struct Pending {
+        const ast::Expression* expr;
+        size_t depth;
+    };
+
+    std::vector<Pending> to_visit{{root, 0}};
+
+    auto push_single = [&](const ast::Expression* expr, size_t depth) {
+        to_visit.push_back({expr, depth});
+    };
+    auto push_pair = [&](const ast::Expression* left, const ast::Expression* right, size_t depth) {
         if (ORDER == TraverseOrder::LeftToRight) {
-            to_visit.push_back(right);
-            to_visit.push_back(left);
+            to_visit.push_back({right, depth});
+            to_visit.push_back({left, depth});
         } else {
-            to_visit.push_back(left);
-            to_visit.push_back(right);
+            to_visit.push_back({left, depth});
+            to_visit.push_back({right, depth});
         }
     };
-    auto push_list = [&](const std::vector<const ast::Expression*>& exprs) {
+    auto push_list = [&](const std::vector<const ast::Expression*>& exprs, size_t depth) {
         if (ORDER == TraverseOrder::LeftToRight) {
             for (auto* expr : utils::Reverse(exprs)) {
-                to_visit.push_back(expr);
+                to_visit.push_back({expr, depth});
             }
         } else {
             for (auto* expr : exprs) {
-                to_visit.push_back(expr);
+                to_visit.push_back({expr, depth});
             }
         }
     };
 
     while (!to_visit.empty()) {
-        auto* expr = to_visit.back();
+        auto p = to_visit.back();
         to_visit.pop_back();
+        const ast::Expression* expr = p.expr;
 
-        if (auto* filtered = expr->As<EXPR_TYPE>()) {
-            switch (callback(filtered)) {
+        if (auto* filtered = expr->template As<EXPR_TYPE>()) {
+            TraverseAction result;
+            if constexpr (kHasDepthArg) {
+                result = callback(filtered, p.depth);
+            } else {
+                result = callback(filtered);
+            }
+
+            switch (result) {
                 case TraverseAction::Stop:
                     return true;
                 case TraverseAction::Skip:
@@ -100,32 +119,31 @@
         bool ok = Switch(
             expr,
             [&](const IndexAccessorExpression* idx) {
-                push_pair(idx->object, idx->index);
+                push_pair(idx->object, idx->index, p.depth + 1);
                 return true;
             },
             [&](const BinaryExpression* bin_op) {
-                push_pair(bin_op->lhs, bin_op->rhs);
+                push_pair(bin_op->lhs, bin_op->rhs, p.depth + 1);
                 return true;
             },
             [&](const BitcastExpression* bitcast) {
-                to_visit.push_back(bitcast->expr);
+                push_single(bitcast->expr, p.depth + 1);
                 return true;
             },
             [&](const CallExpression* call) {
                 // TODO(crbug.com/tint/1257): Resolver breaks if we actually include
-                // the function name in the traversal. to_visit.push_back(call->func);
-                push_list(call->args);
+                // the function name in the traversal. push_single(call->func);
+                push_list(call->args, p.depth + 1);
                 return true;
             },
             [&](const MemberAccessorExpression* member) {
                 // TODO(crbug.com/tint/1257): Resolver breaks if we actually include
-                // the member name in the traversal. push_pair(member->structure,
-                // member->member);
-                to_visit.push_back(member->structure);
+                // the member name in the traversal. push_pair(member->member, p.depth + 1);
+                push_single(member->structure, p.depth + 1);
                 return true;
             },
             [&](const UnaryOpExpression* unary) {
-                to_visit.push_back(unary->expr);
+                push_single(unary->expr, p.depth + 1);
                 return true;
             },
             [&](Default) {
diff --git a/src/tint/ast/traverse_expressions_test.cc b/src/tint/ast/traverse_expressions_test.cc
index 622a7ff..e79decb 100644
--- a/src/tint/ast/traverse_expressions_test.cc
+++ b/src/tint/ast/traverse_expressions_test.cc
@@ -73,6 +73,23 @@
     }
 }
 
+TEST_F(TraverseExpressionsTest, Depth) {
+    std::vector<const ast::Expression*> e = {Expr(1_i), Expr(1_i), Expr(1_i), Expr(1_i)};
+    std::vector<const ast::Expression*> i = {Add(e[0], e[1]), Sub(e[2], e[3])};
+    auto* root = Mul(i[0], i[1]);
+
+    size_t j = 0;
+    size_t depths[] = {0, 1, 2, 2, 1, 2, 2};
+    {
+        TraverseExpressions<TraverseOrder::LeftToRight>(  //
+            root, Diagnostics(), [&](const ast::Expression* expr, size_t depth) {
+                (void)expr;
+                EXPECT_THAT(depth, depths[j++]);
+                return ast::TraverseAction::Descend;
+            });
+    }
+}
+
 TEST_F(TraverseExpressionsTest, DescendBitcastExpression) {
     auto* e = Expr(1_i);
     auto* b0 = Bitcast<i32>(e);
diff --git a/src/tint/cmd/main.cc b/src/tint/cmd/main.cc
index 52dfd70..b9c6d04 100644
--- a/src/tint/cmd/main.cc
+++ b/src/tint/cmd/main.cc
@@ -125,30 +125,36 @@
     (void)fmt;
 
 #if TINT_BUILD_SPV_WRITER
-    if (fmt == "spirv")
+    if (fmt == "spirv") {
         return Format::kSpirv;
-    if (fmt == "spvasm")
+    }
+    if (fmt == "spvasm") {
         return Format::kSpvAsm;
+    }
 #endif  // TINT_BUILD_SPV_WRITER
 
 #if TINT_BUILD_WGSL_WRITER
-    if (fmt == "wgsl")
+    if (fmt == "wgsl") {
         return Format::kWgsl;
+    }
 #endif  // TINT_BUILD_WGSL_WRITER
 
 #if TINT_BUILD_MSL_WRITER
-    if (fmt == "msl")
+    if (fmt == "msl") {
         return Format::kMsl;
+    }
 #endif  // TINT_BUILD_MSL_WRITER
 
 #if TINT_BUILD_HLSL_WRITER
-    if (fmt == "hlsl")
+    if (fmt == "hlsl") {
         return Format::kHlsl;
+    }
 #endif  // TINT_BUILD_HLSL_WRITER
 
 #if TINT_BUILD_GLSL_WRITER
-    if (fmt == "glsl")
+    if (fmt == "glsl") {
         return Format::kGlsl;
+    }
 #endif  // TINT_BUILD_GLSL_WRITER
 
     return Format::kNone;
diff --git a/src/tint/inspector/inspector.cc b/src/tint/inspector/inspector.cc
index 36fcfb7..569a104 100644
--- a/src/tint/inspector/inspector.cc
+++ b/src/tint/inspector/inspector.cc
@@ -19,6 +19,7 @@
 
 #include "src/tint/ast/bool_literal_expression.h"
 #include "src/tint/ast/call_expression.h"
+#include "src/tint/ast/extension.h"
 #include "src/tint/ast/float_literal_expression.h"
 #include "src/tint/ast/id_attribute.h"
 #include "src/tint/ast/interpolate_attribute.h"
@@ -27,10 +28,12 @@
 #include "src/tint/sem/array.h"
 #include "src/tint/sem/call.h"
 #include "src/tint/sem/depth_multisampled_texture.h"
+#include "src/tint/sem/f16.h"
 #include "src/tint/sem/f32.h"
 #include "src/tint/sem/function.h"
 #include "src/tint/sem/i32.h"
 #include "src/tint/sem/matrix.h"
+#include "src/tint/sem/module.h"
 #include "src/tint/sem/multisampled_texture.h"
 #include "src/tint/sem/sampled_texture.h"
 #include "src/tint/sem/statement.h"
@@ -543,16 +546,13 @@
 }
 
 std::vector<std::string> Inspector::GetUsedExtensionNames() {
-    std::vector<std::string> result;
-
-    ast::ExtensionSet set = program_->AST().Extensions();
-    result.reserve(set.size());
-    for (auto kind : set) {
-        std::string name = ast::Enable::KindToName(kind);
-        result.push_back(name);
+    auto& extensions = program_->Sem().Module()->Extensions();
+    std::vector<std::string> out;
+    out.reserve(extensions.size());
+    for (auto ext : extensions) {
+        out.push_back(ast::str(ext));
     }
-
-    return result;
+    return out;
 }
 
 std::vector<std::pair<std::string, Source>> Inspector::GetEnableDirectives() {
@@ -562,7 +562,7 @@
     auto global_decls = program_->AST().GlobalDeclarations();
     for (auto* node : global_decls) {
         if (auto* ext = node->As<ast::Enable>()) {
-            result.push_back({ext->name, ext->source});
+            result.push_back({ast::str(ext->extension), ext->source});
         }
     }
 
@@ -777,7 +777,7 @@
             continue;
         }
 
-        auto* call = sem.Get(c);
+        auto* call = sem.Get(c)->UnwrapMaterialize()->As<sem::Call>();
         if (!call) {
             continue;
         }
diff --git a/src/tint/inspector/inspector_test.cc b/src/tint/inspector/inspector_test.cc
index 18a33b1..033f5b8 100644
--- a/src/tint/inspector/inspector_test.cc
+++ b/src/tint/inspector/inspector_test.cc
@@ -2849,7 +2849,7 @@
 // Test calling GetUsedExtensionNames on a shader with valid extension.
 TEST_F(InspectorGetUsedExtensionNamesTest, Simple) {
     std::string shader = R"(
-enable InternalExtensionForTesting;
+enable f16;
 
 @stage(fragment)
 fn main() {
@@ -2859,15 +2859,15 @@
 
     auto result = inspector.GetUsedExtensionNames();
     EXPECT_EQ(result.size(), 1u);
-    EXPECT_EQ(result[0], "InternalExtensionForTesting");
+    EXPECT_EQ(result[0], "f16");
 }
 
 // Test calling GetUsedExtensionNames on a shader with a extension enabled for
 // multiple times.
 TEST_F(InspectorGetUsedExtensionNamesTest, Duplicated) {
     std::string shader = R"(
-enable InternalExtensionForTesting;
-enable InternalExtensionForTesting;
+enable f16;
+enable f16;
 
 @stage(fragment)
 fn main() {
@@ -2877,7 +2877,7 @@
 
     auto result = inspector.GetUsedExtensionNames();
     EXPECT_EQ(result.size(), 1u);
-    EXPECT_EQ(result[0], "InternalExtensionForTesting");
+    EXPECT_EQ(result[0], "f16");
 }
 
 // Test calling GetEnableDirectives on a empty shader.
@@ -2906,7 +2906,7 @@
 // Test calling GetEnableDirectives on a shader with valid extension.
 TEST_F(InspectorGetEnableDirectivesTest, Simple) {
     std::string shader = R"(
-enable InternalExtensionForTesting;
+enable f16;
 
 @stage(fragment)
 fn main() {
@@ -2916,17 +2916,17 @@
 
     auto result = inspector.GetEnableDirectives();
     EXPECT_EQ(result.size(), 1u);
-    EXPECT_EQ(result[0].first, "InternalExtensionForTesting");
-    EXPECT_EQ(result[0].second.range, (Source::Range{{2, 8}, {2, 35}}));
+    EXPECT_EQ(result[0].first, "f16");
+    EXPECT_EQ(result[0].second.range, (Source::Range{{2, 8}, {2, 11}}));
 }
 
 // Test calling GetEnableDirectives on a shader with a extension enabled for
 // multiple times.
 TEST_F(InspectorGetEnableDirectivesTest, Duplicated) {
     std::string shader = R"(
-enable InternalExtensionForTesting;
+enable f16;
 
-enable InternalExtensionForTesting;
+enable f16;
 @stage(fragment)
 fn main() {
 })";
@@ -2935,10 +2935,10 @@
 
     auto result = inspector.GetEnableDirectives();
     EXPECT_EQ(result.size(), 2u);
-    EXPECT_EQ(result[0].first, "InternalExtensionForTesting");
-    EXPECT_EQ(result[0].second.range, (Source::Range{{2, 8}, {2, 35}}));
-    EXPECT_EQ(result[1].first, "InternalExtensionForTesting");
-    EXPECT_EQ(result[1].second.range, (Source::Range{{4, 8}, {4, 35}}));
+    EXPECT_EQ(result[0].first, "f16");
+    EXPECT_EQ(result[0].second.range, (Source::Range{{2, 8}, {2, 11}}));
+    EXPECT_EQ(result[1].first, "f16");
+    EXPECT_EQ(result[1].second.range, (Source::Range{{4, 8}, {4, 11}}));
 }
 
 // Crash was occuring in ::GenerateSamplerTargets, when
diff --git a/src/tint/intrinsics.def b/src/tint/intrinsics.def
index 0bebe4b..bc4bf28 100644
--- a/src/tint/intrinsics.def
+++ b/src/tint/intrinsics.def
@@ -62,16 +62,32 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 // WGSL primitive types                                                       //
+// Types may be decorated with [[precedence(N)]] to prioritize which type     //
+// will be picked when multiple types of a matcher match.                     //
+// This is used to ensure that abstract numerical types materialize to the    //
+// concrete type with the lowest conversion rank.                             //
+// Types with higher the precedence values will be matched first.             //
 ////////////////////////////////////////////////////////////////////////////////
 
 // https://gpuweb.github.io/gpuweb/wgsl/#plain-types-section
 type bool
-type f32
-type i32
-type u32
+[[precedence(4), display("abstract-float")]] type af
+[[precedence(3), display("abstract-int")]]   type ai
+[[precedence(2)]] type i32
+[[precedence(1)]] type u32
+[[precedence(0)]] type f32
 type vec2<T>
 type vec3<T>
 type vec4<T>
+type mat2x2<T>
+type mat2x3<T>
+type mat2x4<T>
+type mat3x2<T>
+type mat3x3<T>
+type mat3x4<T>
+type mat4x2<T>
+type mat4x3<T>
+type mat4x4<T>
 [[display("vec{N}<{T}>")]]     type vec<N: num, T>
 [[display("mat{N}x{M}<{T}>")]] type mat<N: num, M: num, T>
 type ptr<S: storage_class, T, A: access>
@@ -112,6 +128,12 @@
 match fi32: f32 | i32
 match iu32: i32 | u32
 match scalar: f32 | i32 | u32 | bool
+match abstract_or_scalar: ai | af | f32 | i32 | u32 | bool
+match af_f32: af | f32
+match scalar_no_f32: i32 | u32 | bool
+match scalar_no_i32: f32 | u32 | bool
+match scalar_no_u32: f32 | i32 | bool
+match scalar_no_bool: f32 | i32 | u32
 
 ////////////////////////////////////////////////////////////////////////////////
 // Enum matchers                                                              //
@@ -141,7 +163,7 @@
 // functions supported by the WGSL language. This builtin definition          //
 // language supports simple static-type function declarations, as well as     //
 // single overload declarations that can match a number of different          //
-// argument types via the use of 'open-types' and 'open-numbers'.             //
+// argument types via the use of template types and template numbers          //
 //                                                                            //
 // * Basic example:                                                           //
 //                                                                            //
@@ -150,10 +172,9 @@
 //   Declares an overload of the function 'isInf' that accepts a single       //
 //   parameter of type 'f32' and returns a 'bool'.                            //
 //                                                                            //
-// An 'open-type' can be thought as a template type that is determined by the //
-// arguments to the builtin.                                                  //
+// A template type is a type determined by the arguments to the builtin.      //
 //                                                                            //
-// * Open-type example without constraint:                                    //
+// * Template type example without constraint:                                //
 //                                                                            //
 //    fn arrayLength<T>(array<T>) -> u32                                      //
 //                                                                            //
@@ -162,7 +183,7 @@
 //    element type. This overload will always return a value of the same type //
 //    as its single argument.                                                 //
 //                                                                            //
-// * Open-type example with constraint:                                       //
+// * Template type example with constraint:                                   //
 //                                                                            //
 //    fn abs<T: fiu32>(T) -> T                                                //
 //                                                                            //
@@ -170,10 +191,10 @@
 //    argument of type 'f32', 'i32' or 'u32', which returns a value of the    //
 //    same argument type.                                                     //
 //                                                                            //
-// Similarly an 'open-number' can be thought as a template number or          //
-// enumerator that is determined by the arguments to the builtin.             //
+// Similarly a template number is a number or enumerator that is determined   //
+// by the arguments to the builtin.                                           //
 //                                                                            //
-// * Open-number example:                                                     //
+// * Template number example:                                                 //
 //                                                                            //
 //    fn dpdx<N: num>(vec<N, f32>) -> vec<N, f32>                             //
 //                                                                            //
@@ -182,54 +203,76 @@
 //    the same argument type.                                                 //
 //                                                                            //
 //                                                                            //
-// Matching algorithm:                                                        //
-// -------------------                                                        //
+// Matching algorithm for a single overload:                                  //
+// -----------------------------------------                                  //
 //                                                                            //
-// Prior to matching an overload, all open-types are undefined.               //
+// The goal of matching is to compare a function call's arguments in the      //
+// program source against a possibly-templated overload declaration, and      //
+// determine if the call satisfies the form and type constraints of the       //
+// overload. Currently it is impossible for a call to match more than one     //
+// overload definition. In the event that more than one overload matches, an  //
+// ICE will be raised. Note that Tint may need to support multiple-overload   //
+// resolution in the future, depending on future overload definitions.        //
 //                                                                            //
-// Open-types become closed-types (pinned to a fixed type) on the first       //
-// attempt to match an argument to that open-type.                            //
-// Once open-types are closed, they remain that type for the rest of the      //
-// overload evaluation.                                                       //
+// Prior to matching an overload, all template types are undefined.           //
+//                                                                            //
+// Template types are first defined with the type of the leftmost argument    //
+// that matches against that template type name. Subsequent arguments that    //
+// attempt to match against the template type name will either reject the     //
+// overload or refine the template, in one of 3 ways:                         //
+// (a) Fail to match, causing the overload to be immediately rejected.        //
+// (b) Match the existing template type, either exactly or via implicit       //
+//     conversion, and overload resolution continues.                         //
+// (c) Match via implicit conversion of the currently defined template type   //
+//     to the argument type. In this situation, the template type is refined  //
+//     with the more constrained argument type, and overload resolution       //
+//     continues.                                                             //
 //                                                                            //
 // To better understand, let's consider the following hypothetical overload   //
 // declaration:                                                               //
 //                                                                            //
 //    fn foo<T: scalar>(T, T);                                                //
 //                                                                            //
-//    T           - is the open-type                                          //
+//    T           - is the template type name                                 //
 //    scalar      - is a matcher for the types 'f32', 'i32', 'u32' or 'bool'  //
 //                  (declared above)                                          //
-//    <T: scalar> - declares the open-type T, with the constraint that T must //
-//                  match one of 'f32', 'i32', 'u32' or 'bool'.               //
+//    <T: scalar> - declares the template type T, with the constraint that T  //
+//                  must match one of 'f32', 'i32', 'u32' or 'bool'.          //
 //                                                                            //
 // The process for resolving this overload is as follows:                     //
 //                                                                            //
 //   (1) The overload resolver begins by attempting to match the argument     //
 //       types from left to right.                                            //
-//       The first parameter type is compared against the argument type.      //
-//       As the open-type T has not been closed yet, T is closed as the type  //
-//       of the first argument.                                               //
+//       The first parameter type is compared against the argument type T.    //
+//       As the template type T has not been defined yet, T is defined as the //
+//       type of the first argument.                                          //
 //       There's no verification that the T type is a scalar at this stage.   //
 //   (2) The second parameter is then compared against the second argument.   //
-//       As the open-type T is now closed, the argument type is compared      //
-//       against the value of the closed-type of T. If the types match, then  //
-//       the overload is still a candidate for matching, otherwise the        //
-//       overload is no longer considered.                                    //
-//   (3) If all the parameters matched, constraints on the open-types need    //
-//       to be checked next. If the closed-type does not match the 'match'    //
-//       constraint, then the overload is no longer considered.               //
+//       As the template type T is now defined the argument type is compared  //
+//       against the value of the defined type of T. Depending on the         //
+//       comparison of the argument type to the template type, either the     //
+//       actions of (a), (b) or (c) from above will occur.                    //
+//   (3) If all the parameters matched, constraints on the template types     //
+//       need to be checked next. If the defined type does not match the      //
+//       'match' constraint, then the overload is no longer considered.       //
 //                                                                            //
-// The algorithm for matching open-numbers is almost identical to open-types, //
-// except of course, they match against integer numbers or enumerators        //
-// instead of types.                                                          //
+// This algorithm is less general than the overload resolution described in   //
+// the WGSL spec.  But it makes the same decisions because the overloads      //
+// defined by WGSL are monotonic in the sense that once a template parameter  //
+// has been refined, there is never a need to backtrack and un-refine it to   //
+// match a later argument.                                                    //
+//                                                                            //
+// The algorithm for matching template numbers is similar to matching         //
+// template types, except numbers need to exactly match across all uses -     //
+// there is no implicit conversion. Template numbers may match integer        //
+// numbers or enumerators.                                                    //
 //                                                                            //
 //                                                                            //
 // * More examples:                                                           //
 //                                                                            //
 //   fn F()                                                                   //
 //     - Function called F.                                                   //
-//       No open types or numbers, no parameters, no return value             //
+//       No template types or numbers, no parameters, no return value         //
 //                                                                            //
 //   fn F() -> RETURN_TYPE                                                    //
 //     - Function with RETURN_TYPE as the return type value                   //
@@ -243,21 +286,21 @@
 //       some builtin functions                                               //
 //                                                                            //
 //   fn F<T>(T)                                                               //
-//     - Single parameter of unconstrained open-type T (any type)             //
+//     - Single parameter of unconstrained template type T (any type)         //
 //                                                                            //
 //   fn F<T: scalar>(T)                                                       //
-//     - Single parameter of constrained open-type T (must be a scalar)       //
+//     - Single parameter of constrained template type T (must be a scalar)   //
 //                                                                            //
 //   fn F<T: fiu32>(T) -> T                                                   //
-//     - Single parameter of constrained open-type T (must be a one of fiu32) //
-//       Return type matches parameter type                                   //
+//     - Single parameter of constrained template type T (must be a one of    //
+//       fiu32) Return type matches parameter type                            //
 //                                                                            //
 //   fn F<T, N: num>(vec<N, T>)                                               //
-//     - Single parameter of vector type with open-number size N and element  //
-//       open-type T                                                          //
+//     - Single parameter of vector type with template number size N and      //
+//       element template type T                                              //
 //                                                                            //
 //   fn F<A: access>(texture_storage_1d<f32_texel_format, A>)                 //
-//     - Single parameter of texture_storage_1d type with open-number         //
+//     - Single parameter of texture_storage_1d type with template number     //
 //       access-control C, and of a texel format that is listed in            //
 //       f32_texel_format                                                     //
 //                                                                            //
@@ -563,6 +606,140 @@
 [[stage("fragment", "compute")]] fn atomicCompareExchangeWeak<T: iu32, S: workgroup_or_storage>(ptr<S, atomic<T>, read_write>, T, T) -> vec2<T>
 
 ////////////////////////////////////////////////////////////////////////////////
+// Type constructors                                                          //
+////////////////////////////////////////////////////////////////////////////////
+
+// Zero value constructors
+ctor i32() -> i32
+ctor u32() -> u32
+ctor f32() -> f32
+ctor bool() -> bool
+ctor vec2<T: scalar>() -> vec2<T>
+ctor vec3<T: scalar>() -> vec3<T>
+ctor vec4<T: scalar>() -> vec4<T>
+ctor mat2x2() -> mat2x2<f32>
+ctor mat2x3() -> mat2x3<f32>
+ctor mat2x4() -> mat2x4<f32>
+ctor mat3x2() -> mat3x2<f32>
+ctor mat3x3() -> mat3x3<f32>
+ctor mat3x4() -> mat3x4<f32>
+ctor mat4x2() -> mat4x2<f32>
+ctor mat4x3() -> mat4x3<f32>
+ctor mat4x4() -> mat4x4<f32>
+
+// Identity constructors
+ctor i32(i32) -> i32
+ctor u32(u32) -> u32
+ctor f32(f32) -> f32
+ctor bool(bool) -> bool
+ctor vec2<T: scalar>(vec2<T>) -> vec2<T>
+ctor vec3<T: scalar>(vec3<T>) -> vec3<T>
+ctor vec4<T: scalar>(vec4<T>) -> vec4<T>
+ctor mat2x2<f32>(mat2x2<f32>) -> mat2x2<f32>
+ctor mat2x3<f32>(mat2x3<f32>) -> mat2x3<f32>
+ctor mat2x4<f32>(mat2x4<f32>) -> mat2x4<f32>
+ctor mat3x2<f32>(mat3x2<f32>) -> mat3x2<f32>
+ctor mat3x3<f32>(mat3x3<f32>) -> mat3x3<f32>
+ctor mat3x4<f32>(mat3x4<f32>) -> mat3x4<f32>
+ctor mat4x2<f32>(mat4x2<f32>) -> mat4x2<f32>
+ctor mat4x3<f32>(mat4x3<f32>) -> mat4x3<f32>
+ctor mat4x4<f32>(mat4x4<f32>) -> mat4x4<f32>
+
+// Vector constructors
+ctor vec2<T: abstract_or_scalar>(T) -> vec2<T>
+ctor vec2<T: abstract_or_scalar>(x: T, y: T) -> vec2<T>
+ctor vec3<T: abstract_or_scalar>(T) -> vec3<T>
+ctor vec3<T: abstract_or_scalar>(x: T, y: T, z: T) -> vec3<T>
+ctor vec3<T: abstract_or_scalar>(xy: vec2<T>, z: T) -> vec3<T>
+ctor vec3<T: abstract_or_scalar>(x: T, yz: vec2<T>) -> vec3<T>
+ctor vec4<T: abstract_or_scalar>(T) -> vec4<T>
+ctor vec4<T: abstract_or_scalar>(x: T, y: T, z: T, w: T) -> vec4<T>
+ctor vec4<T: abstract_or_scalar>(xy: vec2<T>, z: T, w: T) -> vec4<T>
+ctor vec4<T: abstract_or_scalar>(x: T, yz: vec2<T>, w: T) -> vec4<T>
+ctor vec4<T: abstract_or_scalar>(x: T, y: T, zw: vec2<T>) -> vec4<T>
+ctor vec4<T: abstract_or_scalar>(xy: vec2<T>, zw: vec2<T>) -> vec4<T>
+ctor vec4<T: abstract_or_scalar>(xyz: vec3<T>, w: T) -> vec4<T>
+ctor vec4<T: abstract_or_scalar>(x: T, zyw: vec3<T>) -> vec4<T>
+
+// Matrix constructors
+ctor mat2x2<T: af_f32>(T) -> mat2x2<T>
+ctor mat2x2<T: af_f32>(T, T,
+                       T, T) -> mat2x2<T>
+ctor mat2x2<T: af_f32>(vec2<T>, vec2<T>) -> mat2x2<T>
+
+ctor mat2x3<T: af_f32>(T) -> mat2x3<T>
+ctor mat2x3<T: af_f32>(T, T, T,
+                       T, T, T) -> mat2x3<T>
+ctor mat2x3<T: af_f32>(vec3<T>, vec3<T>) -> mat2x3<T>
+
+ctor mat2x4<T: af_f32>(T) -> mat2x4<T>
+ctor mat2x4<T: af_f32>(T, T, T, T,
+                       T, T, T, T) -> mat2x4<T>
+ctor mat2x4<T: af_f32>(vec4<T>, vec4<T>) -> mat2x4<T>
+
+ctor mat3x2<T: af_f32>(T) -> mat3x2<T>
+ctor mat3x2<T: af_f32>(T, T,
+                       T, T,
+                       T, T) -> mat3x2<T>
+ctor mat3x2<T: af_f32>(vec2<T>, vec2<T>, vec2<T>) -> mat3x2<T>
+
+ctor mat3x3<T: af_f32>(T) -> mat3x3<T>
+ctor mat3x3<T: af_f32>(T, T, T,
+                       T, T, T,
+                       T, T, T) -> mat3x3<T>
+ctor mat3x3<T: af_f32>(vec3<T>, vec3<T>, vec3<T>) -> mat3x3<T>
+
+ctor mat3x4<T: af_f32>(T) -> mat3x4<T>
+ctor mat3x4<T: af_f32>(T, T, T, T,
+                       T, T, T, T,
+                       T, T, T, T) -> mat3x4<T>
+ctor mat3x4<T: af_f32>(vec4<T>, vec4<T>, vec4<T>) -> mat3x4<T>
+
+ctor mat4x2<T: af_f32>(T) -> mat4x2<T>
+ctor mat4x2<T: af_f32>(T, T,
+                       T, T,
+                       T, T,
+                       T, T) -> mat4x2<T>
+ctor mat4x2<T: af_f32>(vec2<T>, vec2<T>, vec2<T>, vec2<T>) -> mat4x2<T>
+
+ctor mat4x3<T: af_f32>(T) -> mat4x3<T>
+ctor mat4x3<T: af_f32>(T, T, T,
+                       T, T, T,
+                       T, T, T,
+                       T, T, T) -> mat4x3<T>
+ctor mat4x3<T: af_f32>(vec3<T>, vec3<T>, vec3<T>, vec3<T>) -> mat4x3<T>
+
+ctor mat4x4<T: af_f32>(T) -> mat4x4<T>
+ctor mat4x4<T: af_f32>(T, T, T, T,
+                       T, T, T, T,
+                       T, T, T, T,
+                       T, T, T, T) -> mat4x4<T>
+ctor mat4x4<T: af_f32>(vec4<T>, vec4<T>, vec4<T>, vec4<T>) -> mat4x4<T>
+
+////////////////////////////////////////////////////////////////////////////////
+// Type conversions                                                           //
+////////////////////////////////////////////////////////////////////////////////
+conv f32<T: scalar_no_f32>(T) -> f32
+conv i32<T: scalar_no_i32>(T) -> i32
+conv u32<T: scalar_no_u32>(T) -> u32
+conv bool<T: scalar_no_bool>(T) -> bool
+
+conv vec2<T: f32, U: scalar_no_f32>(vec2<U>) -> vec2<f32>
+conv vec2<T: i32, U: scalar_no_i32>(vec2<U>) -> vec2<i32>
+conv vec2<T: u32, U: scalar_no_u32>(vec2<U>) -> vec2<u32>
+conv vec2<T: bool, U: scalar_no_bool>(vec2<U>) -> vec2<bool>
+
+conv vec3<T: f32, U: scalar_no_f32>(vec3<U>) -> vec3<f32>
+conv vec3<T: i32, U: scalar_no_i32>(vec3<U>) -> vec3<i32>
+conv vec3<T: u32, U: scalar_no_u32>(vec3<U>) -> vec3<u32>
+conv vec3<T: bool, U: scalar_no_bool>(vec3<U>) -> vec3<bool>
+
+conv vec4<T: f32, U: scalar_no_f32>(vec4<U>) -> vec4<f32>
+conv vec4<T: i32, U: scalar_no_i32>(vec4<U>) -> vec4<i32>
+conv vec4<T: u32, U: scalar_no_u32>(vec4<U>) -> vec4<u32>
+conv vec4<T: bool, U: scalar_no_bool>(vec4<U>) -> vec4<bool>
+
+////////////////////////////////////////////////////////////////////////////////
 // Operators                                                                  //
 //                                                                            //
 // The operator declarations below declare all the unary and binary operators //
diff --git a/src/tint/number.h b/src/tint/number.h
index a4bd369..c3be236 100644
--- a/src/tint/number.h
+++ b/src/tint/number.h
@@ -18,6 +18,12 @@
 #include <stdint.h>
 #include <functional>
 
+namespace tint::detail {
+/// An empty structure used as a unique template type for Number when
+/// specializing for the f16 type.
+struct NumberKindF16 {};
+}  // namespace tint::detail
+
 namespace tint {
 
 /// Number wraps a integer or floating point number, enforcing explicit casting.
@@ -72,6 +78,43 @@
     return Number<A>(a) == b;
 }
 
+/// The partial specification of Number for f16 type, storing the f16 value as float,
+/// and enforcing proper explicit casting.
+template <>
+struct Number<detail::NumberKindF16> {
+    /// Constructor. The value is zero-initialized.
+    Number() = default;
+
+    /// Constructor.
+    /// @param v the value to initialize this Number to
+    template <typename U>
+    explicit Number(U v) : value(static_cast<float>(v)) {}
+
+    /// Constructor.
+    /// @param v the value to initialize this Number to
+    template <typename U>
+    explicit Number(Number<U> v) : value(static_cast<float>(v.value)) {}
+
+    /// Conversion operator
+    /// @returns the value as the internal representation type of F16
+    operator float() const { return value; }
+
+    /// Negation operator
+    /// @returns the negative value of the number
+    Number operator-() const { return Number<detail::NumberKindF16>(-value); }
+
+    /// Assignment operator with parameter as native floating point type
+    /// @param v the new value
+    /// @returns this Number so calls can be chained
+    Number& operator=(float v) {
+        value = v;
+        return *this;
+    }
+
+    /// The number value, stored as float
+    float value = {};
+};
+
 /// `AInt` is a type alias to `Number<int64_t>`.
 using AInt = Number<int64_t>;
 /// `AFloat` is a type alias to `Number<double>`.
@@ -83,41 +126,54 @@
 using u32 = Number<uint32_t>;
 /// `f32` is a type alias to `Number<float>`
 using f32 = Number<float>;
+/// `f16` is a type alias to `Number<detail::NumberKindF16>`, which should be IEEE 754 binary16.
+/// However since C++ don't have native binary16 type, the value is stored as float.
+using f16 = Number<detail::NumberKindF16>;
 
 }  // namespace tint
 
 namespace tint::number_suffixes {
 
 /// Literal suffix for abstract integer literals
-inline AInt operator"" _a(unsigned long long int value) {  // NOLINT
+inline AInt operator""_a(unsigned long long int value) {  // NOLINT
     return AInt(static_cast<int64_t>(value));
 }
 
 /// Literal suffix for abstract float literals
-inline AFloat operator"" _a(long double value) {  // NOLINT
+inline AFloat operator""_a(long double value) {  // NOLINT
     return AFloat(static_cast<double>(value));
 }
 
 /// Literal suffix for i32 literals
-inline i32 operator"" _i(unsigned long long int value) {  // NOLINT
+inline i32 operator""_i(unsigned long long int value) {  // NOLINT
     return i32(static_cast<int32_t>(value));
 }
 
 /// Literal suffix for u32 literals
-inline u32 operator"" _u(unsigned long long int value) {  // NOLINT
+inline u32 operator""_u(unsigned long long int value) {  // NOLINT
     return u32(static_cast<uint32_t>(value));
 }
 
 /// Literal suffix for f32 literals
-inline f32 operator"" _f(long double value) {  // NOLINT
+inline f32 operator""_f(long double value) {  // NOLINT
     return f32(static_cast<double>(value));
 }
 
 /// Literal suffix for f32 literals
-inline f32 operator"" _f(unsigned long long int value) {  // NOLINT
+inline f32 operator""_f(unsigned long long int value) {  // NOLINT
     return f32(static_cast<double>(value));
 }
 
+/// Literal suffix for f16 literals
+inline f16 operator""_h(long double value) {  // NOLINT
+    return f16(static_cast<double>(value));
+}
+
+/// Literal suffix for f16 literals
+inline f16 operator""_h(unsigned long long int value) {  // NOLINT
+    return f16(static_cast<double>(value));
+}
+
 }  // namespace tint::number_suffixes
 
 #endif  // SRC_TINT_NUMBER_H_
diff --git a/src/tint/program_builder.h b/src/tint/program_builder.h
index 7dd2c81..38970a5 100644
--- a/src/tint/program_builder.h
+++ b/src/tint/program_builder.h
@@ -39,7 +39,9 @@
 #include "src/tint/ast/disable_validation_attribute.h"
 #include "src/tint/ast/discard_statement.h"
 #include "src/tint/ast/enable.h"
+#include "src/tint/ast/extension.h"
 #include "src/tint/ast/external_texture.h"
+#include "src/tint/ast/f16.h"
 #include "src/tint/ast/f32.h"
 #include "src/tint/ast/fallthrough_statement.h"
 #include "src/tint/ast/float_literal_expression.h"
@@ -82,6 +84,7 @@
 #include "src/tint/sem/bool.h"
 #include "src/tint/sem/depth_texture.h"
 #include "src/tint/sem/external_texture.h"
+#include "src/tint/sem/f16.h"
 #include "src/tint/sem/f32.h"
 #include "src/tint/sem/i32.h"
 #include "src/tint/sem/matrix.h"
@@ -385,6 +388,15 @@
             return builder->create<ast::Bool>(source);
         }
 
+        /// @returns a f16 type
+        const ast::F16* f16() const { return builder->create<ast::F16>(); }
+
+        /// @param source the Source of the node
+        /// @returns a f16 type
+        const ast::F16* f16(const Source& source) const {
+            return builder->create<ast::F16>(source);
+        }
+
         /// @returns a f32 type
         const ast::F32* f32() const { return builder->create<ast::F32>(); }
 
@@ -1005,6 +1017,21 @@
     }
 
     /// @param source the source information
+    /// @param value the float value
+    /// @return a 'h'-suffixed FloatLiteralExpression for the f16 value
+    const ast::FloatLiteralExpression* Expr(const Source& source, f16 value) {
+        return create<ast::FloatLiteralExpression>(source, static_cast<double>(value.value),
+                                                   ast::FloatLiteralExpression::Suffix::kH);
+    }
+
+    /// @param value the float value
+    /// @return a 'h'-suffixed FloatLiteralExpression for the f16 value
+    const ast::FloatLiteralExpression* Expr(f16 value) {
+        return create<ast::FloatLiteralExpression>(static_cast<double>(value.value),
+                                                   ast::FloatLiteralExpression::Suffix::kH);
+    }
+
+    /// @param source the source information
     /// @param value the integer value
     /// @return an unsuffixed IntLiteralExpression for the AInt value
     const ast::IntLiteralExpression* Expr(const Source& source, AInt value) {
@@ -1281,6 +1308,15 @@
         return Construct(ty.array(subtype, std::forward<EXPR>(n)), std::forward<ARGS>(args)...);
     }
 
+    /// Adds the extension to the list of enable directives at the top of the module.
+    /// @param ext the extension to enable
+    /// @return an `ast::Enable` enabling the given extension.
+    const ast::Enable* Enable(ast::Extension ext) {
+        auto* enable = create<ast::Enable>(ext);
+        AST().AddEnable(enable);
+        return enable;
+    }
+
     /// @param name the variable name
     /// @param type the variable type
     /// @param optional the optional variable settings.
@@ -2600,6 +2636,25 @@
     /// the type declaration has no resolved type.
     const sem::Type* TypeOf(const ast::TypeDecl* type_decl) const;
 
+    /// @param type a type
+    /// @returns the name for `type` that closely resembles how it would be
+    /// declared in WGSL.
+    std::string FriendlyName(const ast::Type* type) {
+        return type ? type->FriendlyName(Symbols()) : "<null>";
+    }
+
+    /// @param type a type
+    /// @returns the name for `type` that closely resembles how it would be
+    /// declared in WGSL.
+    std::string FriendlyName(const sem::Type* type) {
+        return type ? type->FriendlyName(Symbols()) : "<null>";
+    }
+
+    /// Overload of FriendlyName, which removes an ambiguity when passing nullptr.
+    /// Simplifies test code.
+    /// @returns "<null>"
+    std::string FriendlyName(std::nullptr_t) { return "<null>"; }
+
     /// Wraps the ast::Expression in a statement. This is used by tests that
     /// construct a partial AST and require the Resolver to reach these
     /// nodes.
@@ -2675,6 +2730,10 @@
     static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->f32(); }
 };
 template <>
+struct ProgramBuilder::TypesBuilder::CToAST<f16> {
+    static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->f16(); }
+};
+template <>
 struct ProgramBuilder::TypesBuilder::CToAST<bool> {
     static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->bool_(); }
 };
diff --git a/src/tint/reader/spirv/function.cc b/src/tint/reader/spirv/function.cc
index 82f6224..d88773e 100644
--- a/src/tint/reader/spirv/function.cc
+++ b/src/tint/reader/spirv/function.cc
@@ -602,10 +602,12 @@
     // header, we will visit its merge block, then its continue target (if any).
     // Also records the post order ordering.
     void VisitBackward(uint32_t id) {
-        if (id == 0)
+        if (id == 0) {
             return;
-        if (visited_.count(id))
+        }
+        if (visited_.count(id)) {
             return;
+        }
         visited_.insert(id);
 
         const spvtools::opt::BasicBlock* bb = id_to_block_[id];  // non-null for valid modules
@@ -1600,8 +1602,9 @@
         bool is_single_block_loop = false;
         block_info->basic_block->ForEachSuccessorLabel(
             [&is_single_block_loop, block_id](const uint32_t succ) {
-                if (block_id == succ)
+                if (block_id == succ) {
                     is_single_block_loop = true;
+                }
             });
         const auto ct = block_info->continue_for_header;
         block_info->is_continue_entire_loop = ct == block_id;
diff --git a/src/tint/reader/spirv/parser_impl_barrier_test.cc b/src/tint/reader/spirv/parser_impl_barrier_test.cc
index 0549bd1..fdfa3bf 100644
--- a/src/tint/reader/spirv/parser_impl_barrier_test.cc
+++ b/src/tint/reader/spirv/parser_impl_barrier_test.cc
@@ -69,7 +69,7 @@
     auto* call = helper->body->statements[0]->As<ast::CallStatement>();
     ASSERT_NE(call, nullptr);
     EXPECT_EQ(call->expr->args.size(), 0u);
-    auto* sem_call = program.Sem().Get(call->expr);
+    auto* sem_call = program.Sem().Get<sem::Call>(call->expr);
     ASSERT_NE(sem_call, nullptr);
     auto* builtin = sem_call->Target()->As<sem::Builtin>();
     ASSERT_NE(builtin, nullptr);
@@ -102,7 +102,7 @@
     auto* call = helper->body->statements[0]->As<ast::CallStatement>();
     ASSERT_NE(call, nullptr);
     EXPECT_EQ(call->expr->args.size(), 0u);
-    auto* sem_call = program.Sem().Get(call->expr);
+    auto* sem_call = program.Sem().Get<sem::Call>(call->expr);
     ASSERT_NE(sem_call, nullptr);
     auto* builtin = sem_call->Target()->As<sem::Builtin>();
     ASSERT_NE(builtin, nullptr);
diff --git a/src/tint/reader/wgsl/lexer.cc b/src/tint/reader/wgsl/lexer.cc
index db75613..20b3364 100644
--- a/src/tint/reader/wgsl/lexer.cc
+++ b/src/tint/reader/wgsl/lexer.cc
@@ -232,8 +232,9 @@
 }
 
 bool Lexer::matches(size_t pos, std::string_view sub_string) {
-    if (pos >= length())
+    if (pos >= length()) {
         return false;
+    }
     return substr(pos, sub_string.size()) == sub_string;
 }
 
@@ -265,8 +266,9 @@
 
         // If the cursor didn't advance we didn't remove any blankspace
         // so we're done.
-        if (loc == location_)
+        if (loc == location_) {
             break;
+        }
     }
     if (is_eof()) {
         return {Token::Type::kEOF, begin_source()};
@@ -1043,108 +1045,159 @@
 }
 
 Token Lexer::check_keyword(const Source& source, std::string_view str) {
-    if (str == "array")
+    if (str == "array") {
         return {Token::Type::kArray, source, "array"};
-    if (str == "atomic")
+    }
+    if (str == "atomic") {
         return {Token::Type::kAtomic, source, "atomic"};
-    if (str == "bitcast")
+    }
+    if (str == "bitcast") {
         return {Token::Type::kBitcast, source, "bitcast"};
-    if (str == "bool")
+    }
+    if (str == "bool") {
         return {Token::Type::kBool, source, "bool"};
-    if (str == "break")
+    }
+    if (str == "break") {
         return {Token::Type::kBreak, source, "break"};
-    if (str == "case")
+    }
+    if (str == "case") {
         return {Token::Type::kCase, source, "case"};
-    if (str == "continue")
+    }
+    if (str == "continue") {
         return {Token::Type::kContinue, source, "continue"};
-    if (str == "continuing")
+    }
+    if (str == "continuing") {
         return {Token::Type::kContinuing, source, "continuing"};
-    if (str == "discard")
+    }
+    if (str == "discard") {
         return {Token::Type::kDiscard, source, "discard"};
-    if (str == "default")
+    }
+    if (str == "default") {
         return {Token::Type::kDefault, source, "default"};
-    if (str == "else")
+    }
+    if (str == "else") {
         return {Token::Type::kElse, source, "else"};
-    if (str == "enable")
+    }
+    if (str == "enable") {
         return {Token::Type::kEnable, source, "enable"};
-    if (str == "f32")
+    }
+    if (str == "f16") {
+        return {Token::Type::kF16, source, "f16"};
+    }
+    if (str == "f32") {
         return {Token::Type::kF32, source, "f32"};
-    if (str == "fallthrough")
+    }
+    if (str == "fallthrough") {
         return {Token::Type::kFallthrough, source, "fallthrough"};
-    if (str == "false")
+    }
+    if (str == "false") {
         return {Token::Type::kFalse, source, "false"};
-    if (str == "fn")
+    }
+    if (str == "fn") {
         return {Token::Type::kFn, source, "fn"};
-    if (str == "for")
+    }
+    if (str == "for") {
         return {Token::Type::kFor, source, "for"};
-    if (str == "function")
+    }
+    if (str == "function") {
         return {Token::Type::kFunction, source, "function"};
-    if (str == "i32")
+    }
+    if (str == "i32") {
         return {Token::Type::kI32, source, "i32"};
-    if (str == "if")
+    }
+    if (str == "if") {
         return {Token::Type::kIf, source, "if"};
-    if (str == "import")
+    }
+    if (str == "import") {
         return {Token::Type::kImport, source, "import"};
-    if (str == "let")
+    }
+    if (str == "let") {
         return {Token::Type::kLet, source, "let"};
-    if (str == "loop")
+    }
+    if (str == "loop") {
         return {Token::Type::kLoop, source, "loop"};
-    if (str == "mat2x2")
+    }
+    if (str == "mat2x2") {
         return {Token::Type::kMat2x2, source, "mat2x2"};
-    if (str == "mat2x3")
+    }
+    if (str == "mat2x3") {
         return {Token::Type::kMat2x3, source, "mat2x3"};
-    if (str == "mat2x4")
+    }
+    if (str == "mat2x4") {
         return {Token::Type::kMat2x4, source, "mat2x4"};
-    if (str == "mat3x2")
+    }
+    if (str == "mat3x2") {
         return {Token::Type::kMat3x2, source, "mat3x2"};
-    if (str == "mat3x3")
+    }
+    if (str == "mat3x3") {
         return {Token::Type::kMat3x3, source, "mat3x3"};
-    if (str == "mat3x4")
+    }
+    if (str == "mat3x4") {
         return {Token::Type::kMat3x4, source, "mat3x4"};
-    if (str == "mat4x2")
+    }
+    if (str == "mat4x2") {
         return {Token::Type::kMat4x2, source, "mat4x2"};
-    if (str == "mat4x3")
+    }
+    if (str == "mat4x3") {
         return {Token::Type::kMat4x3, source, "mat4x3"};
-    if (str == "mat4x4")
+    }
+    if (str == "mat4x4") {
         return {Token::Type::kMat4x4, source, "mat4x4"};
-    if (str == "override")
+    }
+    if (str == "override") {
         return {Token::Type::kOverride, source, "override"};
-    if (str == "private")
+    }
+    if (str == "private") {
         return {Token::Type::kPrivate, source, "private"};
-    if (str == "ptr")
+    }
+    if (str == "ptr") {
         return {Token::Type::kPtr, source, "ptr"};
-    if (str == "return")
+    }
+    if (str == "return") {
         return {Token::Type::kReturn, source, "return"};
-    if (str == "sampler")
+    }
+    if (str == "sampler") {
         return {Token::Type::kSampler, source, "sampler"};
-    if (str == "sampler_comparison")
+    }
+    if (str == "sampler_comparison") {
         return {Token::Type::kComparisonSampler, source, "sampler_comparison"};
-    if (str == "storage_buffer" || str == "storage")
+    }
+    if (str == "storage_buffer" || str == "storage") {
         return {Token::Type::kStorage, source, "storage"};
-    if (str == "struct")
+    }
+    if (str == "struct") {
         return {Token::Type::kStruct, source, "struct"};
-    if (str == "switch")
+    }
+    if (str == "switch") {
         return {Token::Type::kSwitch, source, "switch"};
-    if (str == "texture_1d")
+    }
+    if (str == "texture_1d") {
         return {Token::Type::kTextureSampled1d, source, "texture_1d"};
-    if (str == "texture_2d")
+    }
+    if (str == "texture_2d") {
         return {Token::Type::kTextureSampled2d, source, "texture_2d"};
-    if (str == "texture_2d_array")
+    }
+    if (str == "texture_2d_array") {
         return {Token::Type::kTextureSampled2dArray, source, "texture_2d_array"};
-    if (str == "texture_3d")
+    }
+    if (str == "texture_3d") {
         return {Token::Type::kTextureSampled3d, source, "texture_3d"};
-    if (str == "texture_cube")
+    }
+    if (str == "texture_cube") {
         return {Token::Type::kTextureSampledCube, source, "texture_cube"};
+    }
     if (str == "texture_cube_array") {
         return {Token::Type::kTextureSampledCubeArray, source, "texture_cube_array"};
     }
-    if (str == "texture_depth_2d")
+    if (str == "texture_depth_2d") {
         return {Token::Type::kTextureDepth2d, source, "texture_depth_2d"};
+    }
     if (str == "texture_depth_2d_array") {
         return {Token::Type::kTextureDepth2dArray, source, "texture_depth_2d_array"};
     }
-    if (str == "texture_depth_cube")
+    if (str == "texture_depth_cube") {
         return {Token::Type::kTextureDepthCube, source, "texture_depth_cube"};
+    }
     if (str == "texture_depth_cube_array") {
         return {Token::Type::kTextureDepthCubeArray, source, "texture_depth_cube_array"};
     }
@@ -1169,24 +1222,33 @@
     if (str == "texture_storage_3d") {
         return {Token::Type::kTextureStorage3d, source, "texture_storage_3d"};
     }
-    if (str == "true")
+    if (str == "true") {
         return {Token::Type::kTrue, source, "true"};
-    if (str == "type")
+    }
+    if (str == "type") {
         return {Token::Type::kType, source, "type"};
-    if (str == "u32")
+    }
+    if (str == "u32") {
         return {Token::Type::kU32, source, "u32"};
-    if (str == "uniform")
+    }
+    if (str == "uniform") {
         return {Token::Type::kUniform, source, "uniform"};
-    if (str == "var")
+    }
+    if (str == "var") {
         return {Token::Type::kVar, source, "var"};
-    if (str == "vec2")
+    }
+    if (str == "vec2") {
         return {Token::Type::kVec2, source, "vec2"};
-    if (str == "vec3")
+    }
+    if (str == "vec3") {
         return {Token::Type::kVec3, source, "vec3"};
-    if (str == "vec4")
+    }
+    if (str == "vec4") {
         return {Token::Type::kVec4, source, "vec4"};
-    if (str == "workgroup")
+    }
+    if (str == "workgroup") {
         return {Token::Type::kWorkgroup, source, "workgroup"};
+    }
     return {};
 }
 
diff --git a/src/tint/reader/wgsl/parser_impl.cc b/src/tint/reader/wgsl/parser_impl.cc
index b2b9a03..4ad0f76 100644
--- a/src/tint/reader/wgsl/parser_impl.cc
+++ b/src/tint/reader/wgsl/parser_impl.cc
@@ -124,8 +124,8 @@
 
 // https://gpuweb.github.io/gpuweb/wgsl.html#reserved-keywords
 bool is_reserved(Token t) {
-    return t == "asm" || t == "bf16" || t == "const" || t == "do" || t == "enum" || t == "f16" ||
-           t == "f64" || t == "handle" || t == "i8" || t == "i16" || t == "i64" || t == "mat" ||
+    return t == "asm" || t == "bf16" || t == "const" || t == "do" || t == "enum" || t == "f64" ||
+           t == "handle" || t == "i8" || t == "i16" || t == "i64" || t == "mat" ||
            t == "premerge" || t == "regardless" || t == "typedef" || t == "u8" || t == "u16" ||
            t == "u64" || t == "unless" || t == "using" || t == "vec" || t == "void" || t == "while";
 }
@@ -141,18 +141,24 @@
     /// @return the current enter-exit depth for the given block token type. If
     /// `t` is not a block token type, then 0 is always returned.
     int consume(const Token& t) {
-        if (t.Is(Token::Type::kBraceLeft))
+        if (t.Is(Token::Type::kBraceLeft)) {
             return brace++;
-        if (t.Is(Token::Type::kBraceRight))
+        }
+        if (t.Is(Token::Type::kBraceRight)) {
             return brace--;
-        if (t.Is(Token::Type::kBracketLeft))
+        }
+        if (t.Is(Token::Type::kBracketLeft)) {
             return bracket++;
-        if (t.Is(Token::Type::kBracketRight))
+        }
+        if (t.Is(Token::Type::kBracketRight)) {
             return bracket--;
-        if (t.Is(Token::Type::kParenLeft))
+        }
+        if (t.Is(Token::Type::kParenLeft)) {
             return paren++;
-        if (t.Is(Token::Type::kParenRight))
+        }
+        if (t.Is(Token::Type::kParenRight)) {
             return paren--;
+        }
         return 0;
     }
 };
@@ -310,6 +316,9 @@
             if (after_global_decl) {
                 add_error(p, "enable directives must come before all global declarations");
             }
+        } else if (ed.errored) {
+            // Found a invalid enable directive.
+            continue;
         } else {
             auto gd = global_decl();
 
@@ -345,6 +354,11 @@
             synchronized_ = true;
             next();
             name = {t.to_str(), t.source()};
+        } else if (t.Is(Token::Type::kF16)) {
+            // `f16` is a valid extension name and also a keyword
+            synchronized_ = true;
+            next();
+            name = {"f16", t.source()};
         } else if (handle_error(t)) {
             // The token might itself be an error.
             return Failure::kErrored;
@@ -358,13 +372,11 @@
             return Failure::kErrored;
         }
 
-        if (ast::Enable::NameToKind(name.value) != ast::Enable::ExtensionKind::kNotAnExtension) {
-            const ast::Enable* extension = create<ast::Enable>(name.source, name.value);
-            builder_.AST().AddEnable(extension);
-        } else {
-            // Error if an unknown extension is used
+        auto extension = ast::ParseExtension(name.value);
+        if (extension == ast::Extension::kNone) {
             return add_error(name.source, "unsupported extension: '" + name.value + "'");
         }
+        builder_.AST().AddEnable(create<ast::Enable>(name.source, extension));
 
         return true;
     });
@@ -387,56 +399,66 @@
 //  | struct_decl
 //  | function_decl
 Maybe<bool> ParserImpl::global_decl() {
-    if (match(Token::Type::kSemicolon) || match(Token::Type::kEOF))
+    if (match(Token::Type::kSemicolon) || match(Token::Type::kEOF)) {
         return true;
+    }
 
     bool errored = false;
 
     auto attrs = attribute_list();
-    if (attrs.errored)
+    if (attrs.errored) {
         errored = true;
-    if (!continue_parsing())
+    }
+    if (!continue_parsing()) {
         return Failure::kErrored;
+    }
 
     auto decl = sync(Token::Type::kSemicolon, [&]() -> Maybe<bool> {
         auto gv = global_variable_decl(attrs.value);
-        if (gv.errored)
+        if (gv.errored) {
             return Failure::kErrored;
+        }
         if (gv.matched) {
-            if (!expect("variable declaration", Token::Type::kSemicolon))
+            if (!expect("variable declaration", Token::Type::kSemicolon)) {
                 return Failure::kErrored;
+            }
 
             builder_.AST().AddGlobalVariable(gv.value);
             return true;
         }
 
         auto gc = global_constant_decl(attrs.value);
-        if (gc.errored)
+        if (gc.errored) {
             return Failure::kErrored;
+        }
 
         if (gc.matched) {
-            if (!expect("let declaration", Token::Type::kSemicolon))
+            if (!expect("let declaration", Token::Type::kSemicolon)) {
                 return Failure::kErrored;
+            }
 
             builder_.AST().AddGlobalVariable(gc.value);
             return true;
         }
 
         auto ta = type_alias();
-        if (ta.errored)
+        if (ta.errored) {
             return Failure::kErrored;
+        }
 
         if (ta.matched) {
-            if (!expect("type alias", Token::Type::kSemicolon))
+            if (!expect("type alias", Token::Type::kSemicolon)) {
                 return Failure::kErrored;
+            }
 
             builder_.AST().AddTypeDecl(ta.value);
             return true;
         }
 
         auto str = struct_decl();
-        if (str.errored)
+        if (str.errored) {
             return Failure::kErrored;
+        }
 
         if (str.matched) {
             builder_.AST().AddTypeDecl(str.value);
@@ -504,16 +526,19 @@
 //  | variable_attribute_list* variable_decl EQUAL const_expr
 Maybe<const ast::Variable*> ParserImpl::global_variable_decl(ast::AttributeList& attrs) {
     auto decl = variable_decl();
-    if (decl.errored)
+    if (decl.errored) {
         return Failure::kErrored;
-    if (!decl.matched)
+    }
+    if (!decl.matched) {
         return Failure::kNoMatch;
+    }
 
     const ast::Expression* constructor = nullptr;
     if (match(Token::Type::kEqual)) {
         auto expr = expect_const_expr();
-        if (expr.errored)
+        if (expr.errored) {
             return Failure::kErrored;
+        }
         constructor = expr.value;
     }
 
@@ -546,8 +571,9 @@
     }
 
     auto decl = expect_variable_ident_decl(use, /* allow_inferred = */ true);
-    if (decl.errored)
+    if (decl.errored) {
         return Failure::kErrored;
+    }
 
     const ast::Expression* initializer = nullptr;
     if (match(Token::Type::kEqual)) {
@@ -573,20 +599,23 @@
 //   : VAR variable_qualifier? variable_ident_decl
 Maybe<ParserImpl::VarDeclInfo> ParserImpl::variable_decl(bool allow_inferred) {
     Source source;
-    if (!match(Token::Type::kVar, &source))
+    if (!match(Token::Type::kVar, &source)) {
         return Failure::kNoMatch;
+    }
 
     VariableQualifier vq;
     auto explicit_vq = variable_qualifier();
-    if (explicit_vq.errored)
+    if (explicit_vq.errored) {
         return Failure::kErrored;
+    }
     if (explicit_vq.matched) {
         vq = explicit_vq.value;
     }
 
     auto decl = expect_variable_ident_decl("variable declaration", allow_inferred);
-    if (decl.errored)
+    if (decl.errored) {
         return Failure::kErrored;
+    }
 
     return VarDeclInfo{decl->source, decl->name, vq.storage_class, vq.access, decl->type};
 }
@@ -600,16 +629,19 @@
 //                         COMMA access GREATER_THAN
 Maybe<const ast::Type*> ParserImpl::texture_samplers() {
     auto type = sampler();
-    if (type.matched)
+    if (type.matched) {
         return type;
+    }
 
     type = depth_texture();
-    if (type.matched)
+    if (type.matched) {
         return type;
+    }
 
     type = external_texture();
-    if (type.matched)
+    if (type.matched) {
         return type.value;
+    }
 
     auto source_range = make_source_range();
 
@@ -618,8 +650,9 @@
         const char* use = "sampled texture type";
 
         auto subtype = expect_lt_gt_block(use, [&] { return expect_type(use); });
-        if (subtype.errored)
+        if (subtype.errored) {
             return Failure::kErrored;
+        }
 
         return builder_.ty.sampled_texture(source_range, dim.value, subtype.value);
     }
@@ -629,8 +662,9 @@
         const char* use = "multisampled texture type";
 
         auto subtype = expect_lt_gt_block(use, [&] { return expect_type(use); });
-        if (subtype.errored)
+        if (subtype.errored) {
             return Failure::kErrored;
+        }
 
         return builder_.ty.multisampled_texture(source_range, ms_dim.value, subtype.value);
     }
@@ -673,11 +707,13 @@
 //  | SAMPLER_COMPARISON
 Maybe<const ast::Type*> ParserImpl::sampler() {
     Source source;
-    if (match(Token::Type::kSampler, &source))
+    if (match(Token::Type::kSampler, &source)) {
         return builder_.ty.sampler(source, ast::SamplerKind::kSampler);
+    }
 
-    if (match(Token::Type::kComparisonSampler, &source))
+    if (match(Token::Type::kComparisonSampler, &source)) {
         return builder_.ty.sampler(source, ast::SamplerKind::kComparisonSampler);
+    }
 
     return Failure::kNoMatch;
 }
@@ -690,23 +726,29 @@
 //  | TEXTURE_SAMPLED_CUBE
 //  | TEXTURE_SAMPLED_CUBE_ARRAY
 Maybe<const ast::TextureDimension> ParserImpl::sampled_texture() {
-    if (match(Token::Type::kTextureSampled1d))
+    if (match(Token::Type::kTextureSampled1d)) {
         return ast::TextureDimension::k1d;
+    }
 
-    if (match(Token::Type::kTextureSampled2d))
+    if (match(Token::Type::kTextureSampled2d)) {
         return ast::TextureDimension::k2d;
+    }
 
-    if (match(Token::Type::kTextureSampled2dArray))
+    if (match(Token::Type::kTextureSampled2dArray)) {
         return ast::TextureDimension::k2dArray;
+    }
 
-    if (match(Token::Type::kTextureSampled3d))
+    if (match(Token::Type::kTextureSampled3d)) {
         return ast::TextureDimension::k3d;
+    }
 
-    if (match(Token::Type::kTextureSampledCube))
+    if (match(Token::Type::kTextureSampledCube)) {
         return ast::TextureDimension::kCube;
+    }
 
-    if (match(Token::Type::kTextureSampledCubeArray))
+    if (match(Token::Type::kTextureSampledCubeArray)) {
         return ast::TextureDimension::kCubeArray;
+    }
 
     return Failure::kNoMatch;
 }
@@ -725,8 +767,9 @@
 // multisampled_texture
 //  : TEXTURE_MULTISAMPLED_2D
 Maybe<const ast::TextureDimension> ParserImpl::multisampled_texture() {
-    if (match(Token::Type::kTextureMultisampled2d))
+    if (match(Token::Type::kTextureMultisampled2d)) {
         return ast::TextureDimension::k2d;
+    }
 
     return Failure::kNoMatch;
 }
@@ -737,14 +780,18 @@
 //  | TEXTURE_STORAGE_2D_ARRAY
 //  | TEXTURE_STORAGE_3D
 Maybe<const ast::TextureDimension> ParserImpl::storage_texture() {
-    if (match(Token::Type::kTextureStorage1d))
+    if (match(Token::Type::kTextureStorage1d)) {
         return ast::TextureDimension::k1d;
-    if (match(Token::Type::kTextureStorage2d))
+    }
+    if (match(Token::Type::kTextureStorage2d)) {
         return ast::TextureDimension::k2d;
-    if (match(Token::Type::kTextureStorage2dArray))
+    }
+    if (match(Token::Type::kTextureStorage2dArray)) {
         return ast::TextureDimension::k2dArray;
-    if (match(Token::Type::kTextureStorage3d))
+    }
+    if (match(Token::Type::kTextureStorage3d)) {
         return ast::TextureDimension::k3d;
+    }
 
     return Failure::kNoMatch;
 }
@@ -850,37 +897,45 @@
 Expect<ParserImpl::TypedIdentifier> ParserImpl::expect_variable_ident_decl(std::string_view use,
                                                                            bool allow_inferred) {
     auto ident = expect_ident(use);
-    if (ident.errored)
+    if (ident.errored) {
         return Failure::kErrored;
+    }
 
     if (allow_inferred && !peek_is(Token::Type::kColon)) {
         return TypedIdentifier{nullptr, ident.value, ident.source};
     }
 
-    if (!expect(use, Token::Type::kColon))
+    if (!expect(use, Token::Type::kColon)) {
         return Failure::kErrored;
+    }
 
     auto t = peek();
     auto type = type_decl();
-    if (type.errored)
+    if (type.errored) {
         return Failure::kErrored;
-    if (!type.matched)
+    }
+    if (!type.matched) {
         return add_error(t.source(), "invalid type", use);
+    }
 
     return TypedIdentifier{type.value, ident.value, ident.source};
 }
 
 Expect<ast::Access> ParserImpl::expect_access(std::string_view use) {
     auto ident = expect_ident(use);
-    if (ident.errored)
+    if (ident.errored) {
         return Failure::kErrored;
+    }
 
-    if (ident.value == kReadAccess)
+    if (ident.value == kReadAccess) {
         return {ast::Access::kRead, ident.source};
-    if (ident.value == kWriteAccess)
+    }
+    if (ident.value == kWriteAccess) {
         return {ast::Access::kWrite, ident.source};
-    if (ident.value == kReadWriteAccess)
+    }
+    if (ident.value == kReadWriteAccess) {
         return {ast::Access::kReadWrite, ident.source};
+    }
 
     return add_error(ident.source, "invalid value for access control");
 }
@@ -920,24 +975,29 @@
 // type_alias
 //   : TYPE IDENT EQUAL type_decl
 Maybe<const ast::Alias*> ParserImpl::type_alias() {
-    if (!peek_is(Token::Type::kType))
+    if (!peek_is(Token::Type::kType)) {
         return Failure::kNoMatch;
+    }
 
     auto t = next();
     const char* use = "type alias";
 
     auto name = expect_ident(use);
-    if (name.errored)
+    if (name.errored) {
         return Failure::kErrored;
+    }
 
-    if (!expect(use, Token::Type::kEqual))
+    if (!expect(use, Token::Type::kEqual)) {
         return Failure::kErrored;
+    }
 
     auto type = type_decl();
-    if (type.errored)
+    if (type.errored) {
         return Failure::kErrored;
-    if (!type.matched)
+    }
+    if (!type.matched) {
         return add_error(peek(), "invalid type alias");
+    }
 
     return builder_.ty.alias(make_source_range_from(t.source()), name.value, type.value);
 }
@@ -973,17 +1033,25 @@
         return builder_.create<ast::TypeName>(source, builder_.Symbols().Register(t.to_str()));
     }
 
-    if (match(Token::Type::kBool, &source))
+    if (match(Token::Type::kBool, &source)) {
         return builder_.ty.bool_(source);
+    }
 
-    if (match(Token::Type::kF32, &source))
+    if (match(Token::Type::kF16, &source)) {
+        return builder_.ty.f16(source);
+    }
+
+    if (match(Token::Type::kF32, &source)) {
         return builder_.ty.f32(source);
+    }
 
-    if (match(Token::Type::kI32, &source))
+    if (match(Token::Type::kI32, &source)) {
         return builder_.ty.i32(source);
+    }
 
-    if (match(Token::Type::kU32, &source))
+    if (match(Token::Type::kU32, &source)) {
         return builder_.ty.u32(source);
+    }
 
     if (t.IsVector()) {
         next();  // Consume the peek
@@ -1008,20 +1076,24 @@
     }
 
     auto texture_or_sampler = texture_samplers();
-    if (texture_or_sampler.errored)
+    if (texture_or_sampler.errored) {
         return Failure::kErrored;
-    if (texture_or_sampler.matched)
+    }
+    if (texture_or_sampler.matched) {
         return texture_or_sampler;
+    }
 
     return Failure::kNoMatch;
 }
 
 Expect<const ast::Type*> ParserImpl::expect_type(std::string_view use) {
     auto type = type_decl();
-    if (type.errored)
+    if (type.errored) {
         return Failure::kErrored;
-    if (!type.matched)
+    }
+    if (!type.matched) {
         return add_error(peek().source(), "invalid type", use);
+    }
     return type.value;
 }
 
@@ -1105,8 +1177,9 @@
 
     auto subtype = expect_lt_gt_block(use, [&]() -> Expect<const ast::Type*> {
         auto type = expect_type(use);
-        if (type.errored)
+        if (type.errored) {
             return Failure::kErrored;
+        }
 
         if (match(Token::Type::kComma)) {
             auto expr = primary_expression();
@@ -1167,20 +1240,25 @@
 Expect<ast::StorageClass> ParserImpl::expect_storage_class(std::string_view use) {
     auto source = peek().source();
 
-    if (match(Token::Type::kUniform))
+    if (match(Token::Type::kUniform)) {
         return {ast::StorageClass::kUniform, source};
+    }
 
-    if (match(Token::Type::kWorkgroup))
+    if (match(Token::Type::kWorkgroup)) {
         return {ast::StorageClass::kWorkgroup, source};
+    }
 
-    if (match(Token::Type::kStorage))
+    if (match(Token::Type::kStorage)) {
         return {ast::StorageClass::kStorage, source};
+    }
 
-    if (match(Token::Type::kPrivate))
+    if (match(Token::Type::kPrivate)) {
         return {ast::StorageClass::kPrivate, source};
+    }
 
-    if (match(Token::Type::kFunction))
+    if (match(Token::Type::kFunction)) {
         return {ast::StorageClass::kFunction, source};
+    }
 
     return add_error(source, "invalid storage class", use);
 }
@@ -1191,16 +1269,19 @@
     auto t = peek();
     auto source = t.source();
 
-    if (!match(Token::Type::kStruct))
+    if (!match(Token::Type::kStruct)) {
         return Failure::kNoMatch;
+    }
 
     auto name = expect_ident("struct declaration");
-    if (name.errored)
+    if (name.errored) {
         return Failure::kErrored;
+    }
 
     auto body = expect_struct_body_decl();
-    if (body.errored)
+    if (body.errored) {
         return Failure::kErrored;
+    }
 
     auto sym = builder_.Symbols().Register(name.value);
     return create<ast::Struct>(source, sym, std::move(body.value), ast::AttributeList{});
@@ -1235,8 +1316,9 @@
                 next();
                 continue;
             }
-            if (!match(Token::Type::kComma))
+            if (!match(Token::Type::kComma)) {
                 break;
+            }
         }
         if (errored) {
             return Failure::kErrored;
@@ -1254,8 +1336,9 @@
     }
 
     auto decl = expect_variable_ident_decl("struct member");
-    if (decl.errored)
+    if (decl.errored) {
         return Failure::kErrored;
+    }
 
     return create<ast::StructMember>(decl->source, builder_.Symbols().Register(decl->name),
                                      decl->type, std::move(attrs.value));
@@ -1277,17 +1360,20 @@
         }
         return Failure::kErrored;
     }
-    if (!header.matched)
+    if (!header.matched) {
         return Failure::kNoMatch;
+    }
 
     bool errored = false;
 
     auto body = expect_body_stmt();
-    if (body.errored)
+    if (body.errored) {
         errored = true;
+    }
 
-    if (errored)
+    if (errored) {
         return Failure::kErrored;
+    }
 
     return create<ast::Function>(header->source, builder_.Symbols().Register(header->name),
                                  header->params, header->return_type, body.value, attrs,
@@ -1367,12 +1453,14 @@
         }
 
         auto param = expect_param();
-        if (param.errored)
+        if (param.errored) {
             return Failure::kErrored;
+        }
         ret.push_back(param.value);
 
-        if (!match(Token::Type::kComma))
+        if (!match(Token::Type::kComma)) {
             break;
+        }
     }
 
     return ret;
@@ -1384,8 +1472,9 @@
     auto attrs = attribute_list();
 
     auto decl = expect_variable_ident_decl("parameter");
-    if (decl.errored)
+    if (decl.errored) {
         return Failure::kErrored;
+    }
 
     auto* var = create<ast::Variable>(decl->source,                             // source
                                       builder_.Symbols().Register(decl->name),  // symbol
@@ -1427,12 +1516,14 @@
 
 Expect<ast::Builtin> ParserImpl::expect_builtin() {
     auto ident = expect_ident("builtin");
-    if (ident.errored)
+    if (ident.errored) {
         return Failure::kErrored;
+    }
 
     ast::Builtin builtin = ident_to_builtin(ident.value);
-    if (builtin == ast::Builtin::kNone)
+    if (builtin == ast::Builtin::kNone) {
         return add_error(ident.source, "invalid value for builtin attribute");
+    }
 
     return {builtin, ident.source};
 }
@@ -1442,8 +1533,9 @@
 Expect<ast::BlockStatement*> ParserImpl::expect_body_stmt() {
     return expect_brace_block("", [&]() -> Expect<ast::BlockStatement*> {
         auto stmts = expect_statements();
-        if (stmts.errored)
+        if (stmts.errored) {
             return Failure::kErrored;
+        }
         return create<ast::BlockStatement>(Source{}, stmts.value);
     });
 }
@@ -1453,10 +1545,12 @@
 Expect<const ast::Expression*> ParserImpl::expect_paren_rhs_stmt() {
     return expect_paren_block("", [&]() -> Expect<const ast::Expression*> {
         auto expr = logical_or_expression();
-        if (expr.errored)
+        if (expr.errored) {
             return Failure::kErrored;
-        if (!expr.matched)
+        }
+        if (!expr.matched) {
             return add_error(peek(), "unable to parse expression");
+        }
 
         return expr.value;
     });
@@ -1479,8 +1573,9 @@
         }
     }
 
-    if (errored)
+    if (errored) {
         return Failure::kErrored;
+    }
 
     return stmts;
 }
@@ -1510,39 +1605,50 @@
     // Non-block statments that error can resynchronize on semicolon.
     auto stmt = sync(Token::Type::kSemicolon, [&] { return non_block_statement(); });
 
-    if (stmt.errored)
+    if (stmt.errored) {
         return Failure::kErrored;
-    if (stmt.matched)
+    }
+    if (stmt.matched) {
         return stmt;
+    }
 
     auto stmt_if = if_stmt();
-    if (stmt_if.errored)
+    if (stmt_if.errored) {
         return Failure::kErrored;
-    if (stmt_if.matched)
+    }
+    if (stmt_if.matched) {
         return stmt_if.value;
+    }
 
     auto sw = switch_stmt();
-    if (sw.errored)
+    if (sw.errored) {
         return Failure::kErrored;
-    if (sw.matched)
+    }
+    if (sw.matched) {
         return sw.value;
+    }
 
     auto loop = loop_stmt();
-    if (loop.errored)
+    if (loop.errored) {
         return Failure::kErrored;
-    if (loop.matched)
+    }
+    if (loop.matched) {
         return loop.value;
+    }
 
     auto stmt_for = for_stmt();
-    if (stmt_for.errored)
+    if (stmt_for.errored) {
         return Failure::kErrored;
-    if (stmt_for.matched)
+    }
+    if (stmt_for.matched) {
         return stmt_for.value;
+    }
 
     if (peek_is(Token::Type::kBraceLeft)) {
         auto body = expect_body_stmt();
-        if (body.errored)
+        if (body.errored) {
             return Failure::kErrored;
+        }
         return body.value;
     }
 
@@ -1562,50 +1668,64 @@
 Maybe<const ast::Statement*> ParserImpl::non_block_statement() {
     auto stmt = [&]() -> Maybe<const ast::Statement*> {
         auto ret_stmt = return_stmt();
-        if (ret_stmt.errored)
+        if (ret_stmt.errored) {
             return Failure::kErrored;
-        if (ret_stmt.matched)
+        }
+        if (ret_stmt.matched) {
             return ret_stmt.value;
+        }
 
         auto func = func_call_stmt();
-        if (func.errored)
+        if (func.errored) {
             return Failure::kErrored;
-        if (func.matched)
+        }
+        if (func.matched) {
             return func.value;
+        }
 
         auto var = variable_stmt();
-        if (var.errored)
+        if (var.errored) {
             return Failure::kErrored;
-        if (var.matched)
+        }
+        if (var.matched) {
             return var.value;
+        }
 
         auto b = break_stmt();
-        if (b.errored)
+        if (b.errored) {
             return Failure::kErrored;
-        if (b.matched)
+        }
+        if (b.matched) {
             return b.value;
+        }
 
         auto cont = continue_stmt();
-        if (cont.errored)
+        if (cont.errored) {
             return Failure::kErrored;
-        if (cont.matched)
+        }
+        if (cont.matched) {
             return cont.value;
+        }
 
         auto assign = assignment_stmt();
-        if (assign.errored)
+        if (assign.errored) {
             return Failure::kErrored;
-        if (assign.matched)
+        }
+        if (assign.matched) {
             return assign.value;
+        }
 
         Source source;
-        if (match(Token::Type::kDiscard, &source))
+        if (match(Token::Type::kDiscard, &source)) {
             return create<ast::DiscardStatement>(source);
+        }
 
         return Failure::kNoMatch;
     }();
 
-    if (stmt.matched && !expect(stmt->Name(), Token::Type::kSemicolon))
+    if (stmt.matched && !expect(stmt->Name(), Token::Type::kSemicolon)) {
         return Failure::kErrored;
+    }
 
     return stmt;
 }
@@ -1614,15 +1734,18 @@
 //   : RETURN logical_or_expression?
 Maybe<const ast::ReturnStatement*> ParserImpl::return_stmt() {
     Source source;
-    if (!match(Token::Type::kReturn, &source))
+    if (!match(Token::Type::kReturn, &source)) {
         return Failure::kNoMatch;
+    }
 
-    if (peek_is(Token::Type::kSemicolon))
+    if (peek_is(Token::Type::kSemicolon)) {
         return create<ast::ReturnStatement>(source, nullptr);
+    }
 
     auto expr = logical_or_expression();
-    if (expr.errored)
+    if (expr.errored) {
         return Failure::kErrored;
+    }
 
     // TODO(bclayton): Check matched?
     return create<ast::ReturnStatement>(source, expr.value);
@@ -1636,17 +1759,21 @@
     if (match(Token::Type::kLet)) {
         auto decl = expect_variable_ident_decl("let declaration",
                                                /*allow_inferred = */ true);
-        if (decl.errored)
+        if (decl.errored) {
             return Failure::kErrored;
+        }
 
-        if (!expect("let declaration", Token::Type::kEqual))
+        if (!expect("let declaration", Token::Type::kEqual)) {
             return Failure::kErrored;
+        }
 
         auto constructor = logical_or_expression();
-        if (constructor.errored)
+        if (constructor.errored) {
             return Failure::kErrored;
-        if (!constructor.matched)
+        }
+        if (!constructor.matched) {
             return add_error(peek(), "missing constructor for let declaration");
+        }
 
         auto* var = create<ast::Variable>(decl->source,                             // source
                                           builder_.Symbols().Register(decl->name),  // symbol
@@ -1662,18 +1789,22 @@
     }
 
     auto decl = variable_decl(/*allow_inferred = */ true);
-    if (decl.errored)
+    if (decl.errored) {
         return Failure::kErrored;
-    if (!decl.matched)
+    }
+    if (!decl.matched) {
         return Failure::kNoMatch;
+    }
 
     const ast::Expression* constructor = nullptr;
     if (match(Token::Type::kEqual)) {
         auto constructor_expr = logical_or_expression();
-        if (constructor_expr.errored)
+        if (constructor_expr.errored) {
             return Failure::kErrored;
-        if (!constructor_expr.matched)
+        }
+        if (!constructor_expr.matched) {
             return add_error(peek(), "missing constructor for variable declaration");
+        }
 
         constructor = constructor_expr.value;
     }
@@ -1777,12 +1908,14 @@
 //   : SWITCH paren_rhs_stmt BRACKET_LEFT switch_body+ BRACKET_RIGHT
 Maybe<const ast::SwitchStatement*> ParserImpl::switch_stmt() {
     Source source;
-    if (!match(Token::Type::kSwitch, &source))
+    if (!match(Token::Type::kSwitch, &source)) {
         return Failure::kNoMatch;
+    }
 
     auto condition = logical_or_expression();
-    if (condition.errored)
+    if (condition.errored) {
         return Failure::kErrored;
+    }
     if (!condition.matched) {
         return add_error(peek(), "unable to parse selector expression");
     }
@@ -1796,17 +1929,20 @@
                 errored = true;
                 continue;
             }
-            if (!stmt.matched)
+            if (!stmt.matched) {
                 break;
+            }
             list.push_back(stmt.value);
         }
-        if (errored)
+        if (errored) {
             return Failure::kErrored;
+        }
         return list;
     });
 
-    if (body.errored)
+    if (body.errored) {
         return Failure::kErrored;
+    }
 
     return create<ast::SwitchStatement>(source, condition.value, body.value);
 }
@@ -1815,8 +1951,9 @@
 //   : CASE case_selectors COLON? BRACKET_LEFT case_body BRACKET_RIGHT
 //   | DEFAULT COLON? BRACKET_LEFT case_body BRACKET_RIGHT
 Maybe<const ast::CaseStatement*> ParserImpl::switch_body() {
-    if (!peek_is(Token::Type::kCase) && !peek_is(Token::Type::kDefault))
+    if (!peek_is(Token::Type::kCase) && !peek_is(Token::Type::kDefault)) {
         return Failure::kNoMatch;
+    }
 
     auto t = next();
     auto source = t.source();
@@ -1824,8 +1961,9 @@
     ast::CaseSelectorList selector_list;
     if (t.Is(Token::Type::kCase)) {
         auto selectors = expect_case_selectors();
-        if (selectors.errored)
+        if (selectors.errored) {
             return Failure::kErrored;
+        }
 
         selector_list = std::move(selectors.value);
     }
@@ -1836,10 +1974,12 @@
     const char* use = "case statement";
     auto body = expect_brace_block(use, [&] { return case_body(); });
 
-    if (body.errored)
+    if (body.errored) {
         return Failure::kErrored;
-    if (!body.matched)
+    }
+    if (!body.matched) {
         return add_error(body.source, "expected case body");
+    }
 
     return create<ast::CaseStatement>(source, selector_list, body.value);
 }
@@ -1866,8 +2006,9 @@
         }
     }
 
-    if (selectors.empty())
+    if (selectors.empty()) {
         return add_error(peek(), "unable to parse case selectors");
+    }
 
     return selectors;
 }
@@ -1881,18 +2022,21 @@
     while (continue_parsing()) {
         Source source;
         if (match(Token::Type::kFallthrough, &source)) {
-            if (!expect("fallthrough statement", Token::Type::kSemicolon))
+            if (!expect("fallthrough statement", Token::Type::kSemicolon)) {
                 return Failure::kErrored;
+            }
 
             stmts.emplace_back(create<ast::FallthroughStatement>(source));
             break;
         }
 
         auto stmt = statement();
-        if (stmt.errored)
+        if (stmt.errored) {
             return Failure::kErrored;
-        if (!stmt.matched)
+        }
+        if (!stmt.matched) {
             break;
+        }
 
         stmts.emplace_back(stmt.value);
     }
@@ -1904,17 +2048,20 @@
 //   : LOOP BRACKET_LEFT statements continuing_stmt? BRACKET_RIGHT
 Maybe<const ast::LoopStatement*> ParserImpl::loop_stmt() {
     Source source;
-    if (!match(Token::Type::kLoop, &source))
+    if (!match(Token::Type::kLoop, &source)) {
         return Failure::kNoMatch;
+    }
 
     return expect_brace_block("loop", [&]() -> Maybe<const ast::LoopStatement*> {
         auto stmts = expect_statements();
-        if (stmts.errored)
+        if (stmts.errored) {
             return Failure::kErrored;
+        }
 
         auto continuing = continuing_stmt();
-        if (continuing.errored)
+        if (continuing.errored) {
             return Failure::kErrored;
+        }
 
         auto* body = create<ast::BlockStatement>(source, stmts.value);
         return create<ast::LoopStatement>(source, body, continuing.value);
@@ -1932,22 +2079,28 @@
 // func_call_stmt)?
 Maybe<const ast::Statement*> ParserImpl::for_header_initializer() {
     auto call = func_call_stmt();
-    if (call.errored)
+    if (call.errored) {
         return Failure::kErrored;
-    if (call.matched)
+    }
+    if (call.matched) {
         return call.value;
+    }
 
     auto var = variable_stmt();
-    if (var.errored)
+    if (var.errored) {
         return Failure::kErrored;
-    if (var.matched)
+    }
+    if (var.matched) {
         return var.value;
+    }
 
     auto assign = assignment_stmt();
-    if (assign.errored)
+    if (assign.errored) {
         return Failure::kErrored;
-    if (assign.matched)
+    }
+    if (assign.matched) {
         return assign.value;
+    }
 
     return Failure::kNoMatch;
 }
@@ -1955,16 +2108,20 @@
 // (increment_stmt | decrement_stmt | assignment_stmt | func_call_stmt)?
 Maybe<const ast::Statement*> ParserImpl::for_header_continuing() {
     auto call_stmt = func_call_stmt();
-    if (call_stmt.errored)
+    if (call_stmt.errored) {
         return Failure::kErrored;
-    if (call_stmt.matched)
+    }
+    if (call_stmt.matched) {
         return call_stmt.value;
+    }
 
     auto assign = assignment_stmt();
-    if (assign.errored)
+    if (assign.errored) {
         return Failure::kErrored;
-    if (assign.matched)
+    }
+    if (assign.matched) {
         return assign.value;
+    }
 
     return Failure::kNoMatch;
 }
@@ -1976,22 +2133,27 @@
 //      (assignment_stmt | func_call_stmt)?
 Expect<std::unique_ptr<ForHeader>> ParserImpl::expect_for_header() {
     auto initializer = for_header_initializer();
-    if (initializer.errored)
+    if (initializer.errored) {
         return Failure::kErrored;
+    }
 
-    if (!expect("initializer in for loop", Token::Type::kSemicolon))
+    if (!expect("initializer in for loop", Token::Type::kSemicolon)) {
         return Failure::kErrored;
+    }
 
     auto condition = logical_or_expression();
-    if (condition.errored)
+    if (condition.errored) {
         return Failure::kErrored;
+    }
 
-    if (!expect("condition in for loop", Token::Type::kSemicolon))
+    if (!expect("condition in for loop", Token::Type::kSemicolon)) {
         return Failure::kErrored;
+    }
 
     auto continuing = for_header_continuing();
-    if (continuing.errored)
+    if (continuing.errored) {
         return Failure::kErrored;
+    }
 
     return std::make_unique<ForHeader>(initializer.value, condition.value, continuing.value);
 }
@@ -2000,16 +2162,19 @@
 //   : FOR PAREN_LEFT for_header PAREN_RIGHT BRACE_LEFT statements BRACE_RIGHT
 Maybe<const ast::ForLoopStatement*> ParserImpl::for_stmt() {
     Source source;
-    if (!match(Token::Type::kFor, &source))
+    if (!match(Token::Type::kFor, &source)) {
         return Failure::kNoMatch;
+    }
 
     auto header = expect_paren_block("for loop", [&] { return expect_for_header(); });
-    if (header.errored)
+    if (header.errored) {
         return Failure::kErrored;
+    }
 
     auto stmts = expect_brace_block("for loop", [&] { return expect_statements(); });
-    if (stmts.errored)
+    if (stmts.errored) {
         return Failure::kErrored;
+    }
 
     return create<ast::ForLoopStatement>(source, header->initializer, header->condition,
                                          header->continuing,
@@ -2021,8 +2186,9 @@
 Maybe<const ast::CallStatement*> ParserImpl::func_call_stmt() {
     auto t = peek();
     auto t2 = peek(1);
-    if (!t.IsIdentifier() || !t2.Is(Token::Type::kParenLeft))
+    if (!t.IsIdentifier() || !t2.Is(Token::Type::kParenLeft)) {
         return Failure::kNoMatch;
+    }
 
     next();  // Consume the first peek
 
@@ -2030,8 +2196,9 @@
     auto name = t.to_str();
 
     auto params = expect_argument_expression_list("function call");
-    if (params.errored)
+    if (params.errored) {
         return Failure::kErrored;
+    }
 
     return create<ast::CallStatement>(
         source,
@@ -2044,8 +2211,9 @@
 //   : BREAK
 Maybe<const ast::BreakStatement*> ParserImpl::break_stmt() {
     Source source;
-    if (!match(Token::Type::kBreak, &source))
+    if (!match(Token::Type::kBreak, &source)) {
         return Failure::kNoMatch;
+    }
 
     return create<ast::BreakStatement>(source);
 }
@@ -2054,8 +2222,9 @@
 //   : CONTINUE
 Maybe<const ast::ContinueStatement*> ParserImpl::continue_stmt() {
     Source source;
-    if (!match(Token::Type::kContinue, &source))
+    if (!match(Token::Type::kContinue, &source)) {
         return Failure::kNoMatch;
+    }
 
     return create<ast::ContinueStatement>(source);
 }
@@ -2063,8 +2232,9 @@
 // continuing_stmt
 //   : CONTINUING body_stmt
 Maybe<const ast::BlockStatement*> ParserImpl::continuing_stmt() {
-    if (!match(Token::Type::kContinuing))
+    if (!match(Token::Type::kContinuing)) {
         return create<ast::BlockStatement>(Source{}, ast::StatementList{});
+    }
 
     return expect_body_stmt();
 }
@@ -2100,12 +2270,14 @@
         const char* use = "bitcast expression";
 
         auto type = expect_lt_gt_block(use, [&] { return expect_type(use); });
-        if (type.errored)
+        if (type.errored) {
             return Failure::kErrored;
+        }
 
         auto params = expect_paren_rhs_stmt();
-        if (params.errored)
+        if (params.errored) {
             return Failure::kErrored;
+        }
 
         return create<ast::BitcastExpression>(source, type.value, params.value);
     }
@@ -2118,8 +2290,9 @@
 
         if (peek_is(Token::Type::kParenLeft)) {
             auto params = expect_argument_expression_list("function call");
-            if (params.errored)
+            if (params.errored) {
                 return Failure::kErrored;
+            }
 
             return create<ast::CallExpression>(source, ident, std::move(params.value));
         }
@@ -2128,12 +2301,14 @@
     }
 
     auto type = type_decl();
-    if (type.errored)
+    if (type.errored) {
         return Failure::kErrored;
+    }
     if (type.matched) {
         auto params = expect_argument_expression_list("type constructor");
-        if (params.errored)
+        if (params.errored) {
             return Failure::kErrored;
+        }
 
         return builder_.Construct(source, type.value, std::move(params.value));
     }
@@ -2152,8 +2327,9 @@
         if (match(Token::Type::kBracketLeft, &source)) {
             auto res = sync(Token::Type::kBracketRight, [&]() -> Maybe<const ast::Expression*> {
                 auto param = logical_or_expression();
-                if (param.errored)
+                if (param.errored) {
                     return Failure::kErrored;
+                }
                 if (!param.matched) {
                     return add_error(peek(), "unable to parse expression inside []");
                 }
@@ -2195,10 +2371,12 @@
 //   : primary_expression postfix_expr
 Maybe<const ast::Expression*> ParserImpl::singular_expression() {
     auto prefix = primary_expression();
-    if (prefix.errored)
+    if (prefix.errored) {
         return Failure::kErrored;
-    if (!prefix.matched)
+    }
+    if (!prefix.matched) {
         return Failure::kNoMatch;
+    }
 
     return postfix_expression(prefix.value);
 }
@@ -2289,22 +2467,24 @@
 Expect<const ast::Expression*> ParserImpl::expect_multiplicative_expr(const ast::Expression* lhs) {
     while (continue_parsing()) {
         ast::BinaryOp op = ast::BinaryOp::kNone;
-        if (peek_is(Token::Type::kStar))
+        if (peek_is(Token::Type::kStar)) {
             op = ast::BinaryOp::kMultiply;
-        else if (peek_is(Token::Type::kForwardSlash))
+        } else if (peek_is(Token::Type::kForwardSlash)) {
             op = ast::BinaryOp::kDivide;
-        else if (peek_is(Token::Type::kMod))
+        } else if (peek_is(Token::Type::kMod)) {
             op = ast::BinaryOp::kModulo;
-        else
+        } else {
             return lhs;
+        }
 
         auto t = next();
         auto source = t.source();
         auto name = t.to_name();
 
         auto rhs = unary_expression();
-        if (rhs.errored)
+        if (rhs.errored) {
             return Failure::kErrored;
+        }
         if (!rhs.matched) {
             return add_error(peek(),
                              "unable to parse right side of " + std::string(name) + " expression");
@@ -2319,10 +2499,12 @@
 //   : unary_expression multiplicative_expr
 Maybe<const ast::Expression*> ParserImpl::multiplicative_expression() {
     auto lhs = unary_expression();
-    if (lhs.errored)
+    if (lhs.errored) {
         return Failure::kErrored;
-    if (!lhs.matched)
+    }
+    if (!lhs.matched) {
         return Failure::kNoMatch;
+    }
 
     return expect_multiplicative_expr(lhs.value);
 }
@@ -2334,21 +2516,24 @@
 Expect<const ast::Expression*> ParserImpl::expect_additive_expr(const ast::Expression* lhs) {
     while (continue_parsing()) {
         ast::BinaryOp op = ast::BinaryOp::kNone;
-        if (peek_is(Token::Type::kPlus))
+        if (peek_is(Token::Type::kPlus)) {
             op = ast::BinaryOp::kAdd;
-        else if (peek_is(Token::Type::kMinus))
+        } else if (peek_is(Token::Type::kMinus)) {
             op = ast::BinaryOp::kSubtract;
-        else
+        } else {
             return lhs;
+        }
 
         auto t = next();
         auto source = t.source();
 
         auto rhs = multiplicative_expression();
-        if (rhs.errored)
+        if (rhs.errored) {
             return Failure::kErrored;
-        if (!rhs.matched)
+        }
+        if (!rhs.matched) {
             return add_error(peek(), "unable to parse right side of + expression");
+        }
 
         lhs = create<ast::BinaryExpression>(source, op, lhs, rhs.value);
     }
@@ -2359,10 +2544,12 @@
 //   : multiplicative_expression additive_expr
 Maybe<const ast::Expression*> ParserImpl::additive_expression() {
     auto lhs = multiplicative_expression();
-    if (lhs.errored)
+    if (lhs.errored) {
         return Failure::kErrored;
-    if (!lhs.matched)
+    }
+    if (!lhs.matched) {
         return Failure::kNoMatch;
+    }
 
     return expect_additive_expr(lhs.value);
 }
@@ -2388,8 +2575,9 @@
         auto t = next();
         auto source = t.source();
         auto rhs = additive_expression();
-        if (rhs.errored)
+        if (rhs.errored) {
             return Failure::kErrored;
+        }
         if (!rhs.matched) {
             return add_error(peek(),
                              std::string("unable to parse right side of ") + name + " expression");
@@ -2404,10 +2592,12 @@
 //   : additive_expression shift_expr
 Maybe<const ast::Expression*> ParserImpl::shift_expression() {
     auto lhs = additive_expression();
-    if (lhs.errored)
+    if (lhs.errored) {
         return Failure::kErrored;
-    if (!lhs.matched)
+    }
+    if (!lhs.matched) {
         return Failure::kNoMatch;
+    }
 
     return expect_shift_expr(lhs.value);
 }
@@ -2421,24 +2611,26 @@
 Expect<const ast::Expression*> ParserImpl::expect_relational_expr(const ast::Expression* lhs) {
     while (continue_parsing()) {
         ast::BinaryOp op = ast::BinaryOp::kNone;
-        if (peek_is(Token::Type::kLessThan))
+        if (peek_is(Token::Type::kLessThan)) {
             op = ast::BinaryOp::kLessThan;
-        else if (peek_is(Token::Type::kGreaterThan))
+        } else if (peek_is(Token::Type::kGreaterThan)) {
             op = ast::BinaryOp::kGreaterThan;
-        else if (peek_is(Token::Type::kLessThanEqual))
+        } else if (peek_is(Token::Type::kLessThanEqual)) {
             op = ast::BinaryOp::kLessThanEqual;
-        else if (peek_is(Token::Type::kGreaterThanEqual))
+        } else if (peek_is(Token::Type::kGreaterThanEqual)) {
             op = ast::BinaryOp::kGreaterThanEqual;
-        else
+        } else {
             return lhs;
+        }
 
         auto t = next();
         auto source = t.source();
         auto name = t.to_name();
 
         auto rhs = shift_expression();
-        if (rhs.errored)
+        if (rhs.errored) {
             return Failure::kErrored;
+        }
         if (!rhs.matched) {
             return add_error(peek(),
                              "unable to parse right side of " + std::string(name) + " expression");
@@ -2453,10 +2645,12 @@
 //   : shift_expression relational_expr
 Maybe<const ast::Expression*> ParserImpl::relational_expression() {
     auto lhs = shift_expression();
-    if (lhs.errored)
+    if (lhs.errored) {
         return Failure::kErrored;
-    if (!lhs.matched)
+    }
+    if (!lhs.matched) {
         return Failure::kNoMatch;
+    }
 
     return expect_relational_expr(lhs.value);
 }
@@ -2468,20 +2662,22 @@
 Expect<const ast::Expression*> ParserImpl::expect_equality_expr(const ast::Expression* lhs) {
     while (continue_parsing()) {
         ast::BinaryOp op = ast::BinaryOp::kNone;
-        if (peek_is(Token::Type::kEqualEqual))
+        if (peek_is(Token::Type::kEqualEqual)) {
             op = ast::BinaryOp::kEqual;
-        else if (peek_is(Token::Type::kNotEqual))
+        } else if (peek_is(Token::Type::kNotEqual)) {
             op = ast::BinaryOp::kNotEqual;
-        else
+        } else {
             return lhs;
+        }
 
         auto t = next();
         auto source = t.source();
         auto name = t.to_name();
 
         auto rhs = relational_expression();
-        if (rhs.errored)
+        if (rhs.errored) {
             return Failure::kErrored;
+        }
         if (!rhs.matched) {
             return add_error(peek(),
                              "unable to parse right side of " + std::string(name) + " expression");
@@ -2496,10 +2692,12 @@
 //   : relational_expression equality_expr
 Maybe<const ast::Expression*> ParserImpl::equality_expression() {
     auto lhs = relational_expression();
-    if (lhs.errored)
+    if (lhs.errored) {
         return Failure::kErrored;
-    if (!lhs.matched)
+    }
+    if (!lhs.matched) {
         return Failure::kNoMatch;
+    }
 
     return expect_equality_expr(lhs.value);
 }
@@ -2517,10 +2715,12 @@
         auto source = t.source();
 
         auto rhs = equality_expression();
-        if (rhs.errored)
+        if (rhs.errored) {
             return Failure::kErrored;
-        if (!rhs.matched)
+        }
+        if (!rhs.matched) {
             return add_error(peek(), "unable to parse right side of & expression");
+        }
 
         lhs = create<ast::BinaryExpression>(source, ast::BinaryOp::kAnd, lhs, rhs.value);
     }
@@ -2531,10 +2731,12 @@
 //   : equality_expression and_expr
 Maybe<const ast::Expression*> ParserImpl::and_expression() {
     auto lhs = equality_expression();
-    if (lhs.errored)
+    if (lhs.errored) {
         return Failure::kErrored;
-    if (!lhs.matched)
+    }
+    if (!lhs.matched) {
         return Failure::kNoMatch;
+    }
 
     return expect_and_expr(lhs.value);
 }
@@ -2545,14 +2747,17 @@
 Expect<const ast::Expression*> ParserImpl::expect_exclusive_or_expr(const ast::Expression* lhs) {
     while (continue_parsing()) {
         Source source;
-        if (!match(Token::Type::kXor, &source))
+        if (!match(Token::Type::kXor, &source)) {
             return lhs;
+        }
 
         auto rhs = and_expression();
-        if (rhs.errored)
+        if (rhs.errored) {
             return Failure::kErrored;
-        if (!rhs.matched)
+        }
+        if (!rhs.matched) {
             return add_error(peek(), "unable to parse right side of ^ expression");
+        }
 
         lhs = create<ast::BinaryExpression>(source, ast::BinaryOp::kXor, lhs, rhs.value);
     }
@@ -2563,10 +2768,12 @@
 //   : and_expression exclusive_or_expr
 Maybe<const ast::Expression*> ParserImpl::exclusive_or_expression() {
     auto lhs = and_expression();
-    if (lhs.errored)
+    if (lhs.errored) {
         return Failure::kErrored;
-    if (!lhs.matched)
+    }
+    if (!lhs.matched) {
         return Failure::kNoMatch;
+    }
 
     return expect_exclusive_or_expr(lhs.value);
 }
@@ -2577,14 +2784,17 @@
 Expect<const ast::Expression*> ParserImpl::expect_inclusive_or_expr(const ast::Expression* lhs) {
     while (continue_parsing()) {
         Source source;
-        if (!match(Token::Type::kOr))
+        if (!match(Token::Type::kOr, &source)) {
             return lhs;
+        }
 
         auto rhs = exclusive_or_expression();
-        if (rhs.errored)
+        if (rhs.errored) {
             return Failure::kErrored;
-        if (!rhs.matched)
+        }
+        if (!rhs.matched) {
             return add_error(peek(), "unable to parse right side of | expression");
+        }
 
         lhs = create<ast::BinaryExpression>(source, ast::BinaryOp::kOr, lhs, rhs.value);
     }
@@ -2595,10 +2805,12 @@
 //   : exclusive_or_expression inclusive_or_expr
 Maybe<const ast::Expression*> ParserImpl::inclusive_or_expression() {
     auto lhs = exclusive_or_expression();
-    if (lhs.errored)
+    if (lhs.errored) {
         return Failure::kErrored;
-    if (!lhs.matched)
+    }
+    if (!lhs.matched) {
         return Failure::kNoMatch;
+    }
 
     return expect_inclusive_or_expr(lhs.value);
 }
@@ -2616,10 +2828,12 @@
         auto source = t.source();
 
         auto rhs = inclusive_or_expression();
-        if (rhs.errored)
+        if (rhs.errored) {
             return Failure::kErrored;
-        if (!rhs.matched)
+        }
+        if (!rhs.matched) {
             return add_error(peek(), "unable to parse right side of && expression");
+        }
 
         lhs = create<ast::BinaryExpression>(source, ast::BinaryOp::kLogicalAnd, lhs, rhs.value);
     }
@@ -2630,10 +2844,12 @@
 //   : inclusive_or_expression logical_and_expr
 Maybe<const ast::Expression*> ParserImpl::logical_and_expression() {
     auto lhs = inclusive_or_expression();
-    if (lhs.errored)
+    if (lhs.errored) {
         return Failure::kErrored;
-    if (!lhs.matched)
+    }
+    if (!lhs.matched) {
         return Failure::kNoMatch;
+    }
 
     return expect_logical_and_expr(lhs.value);
 }
@@ -2644,14 +2860,17 @@
 Expect<const ast::Expression*> ParserImpl::expect_logical_or_expr(const ast::Expression* lhs) {
     while (continue_parsing()) {
         Source source;
-        if (!match(Token::Type::kOrOr))
+        if (!match(Token::Type::kOrOr, &source)) {
             return lhs;
+        }
 
         auto rhs = logical_and_expression();
-        if (rhs.errored)
+        if (rhs.errored) {
             return Failure::kErrored;
-        if (!rhs.matched)
+        }
+        if (!rhs.matched) {
             return add_error(peek(), "unable to parse right side of || expression");
+        }
 
         lhs = create<ast::BinaryExpression>(source, ast::BinaryOp::kLogicalOr, lhs, rhs.value);
     }
@@ -2662,10 +2881,12 @@
 //   : logical_and_expression logical_or_expr
 Maybe<const ast::Expression*> ParserImpl::logical_or_expression() {
     auto lhs = logical_and_expression();
-    if (lhs.errored)
+    if (lhs.errored) {
         return Failure::kErrored;
-    if (!lhs.matched)
+    }
+    if (!lhs.matched) {
         return Failure::kNoMatch;
+    }
 
     return expect_logical_or_expr(lhs.value);
 }
@@ -2852,8 +3073,9 @@
             return list;
         });
 
-        if (params.errored)
+        if (params.errored) {
             return Failure::kErrored;
+        }
 
         return builder_.Construct(source, type.value, params.value);
     }
@@ -2876,11 +3098,13 @@
         }
     }
 
-    if (errored)
+    if (errored) {
         return Failure::kErrored;
+    }
 
-    if (attrs.empty())
+    if (attrs.empty()) {
         return Failure::kNoMatch;
+    }
 
     return attrs;
 }
@@ -2888,10 +3112,12 @@
 Expect<const ast::Attribute*> ParserImpl::expect_attribute() {
     auto t = peek();
     auto attr = attribute();
-    if (attr.errored)
+    if (attr.errored) {
         return Failure::kErrored;
-    if (attr.matched)
+    }
+    if (attr.matched) {
         return attr.value;
+    }
     return add_error(t, "expected attribute");
 }
 
@@ -2907,8 +3133,9 @@
         const char* use = "location attribute";
         return expect_paren_block(use, [&]() -> Result {
             auto val = expect_positive_sint(use);
-            if (val.errored)
+            if (val.errored) {
                 return Failure::kErrored;
+            }
 
             return create<ast::LocationAttribute>(t.source(), val.value);
         });
@@ -2918,8 +3145,9 @@
         const char* use = "binding attribute";
         return expect_paren_block(use, [&]() -> Result {
             auto val = expect_positive_sint(use);
-            if (val.errored)
+            if (val.errored) {
                 return Failure::kErrored;
+            }
 
             return create<ast::BindingAttribute>(t.source(), val.value);
         });
@@ -2929,8 +3157,9 @@
         const char* use = "group attribute";
         return expect_paren_block(use, [&]() -> Result {
             auto val = expect_positive_sint(use);
-            if (val.errored)
+            if (val.errored) {
                 return Failure::kErrored;
+            }
 
             return create<ast::GroupAttribute>(t.source(), val.value);
         });
@@ -2976,8 +3205,9 @@
     if (t == kBuiltinAttribute) {
         return expect_paren_block("builtin attribute", [&]() -> Result {
             auto builtin = expect_builtin();
-            if (builtin.errored)
+            if (builtin.errored) {
                 return Failure::kErrored;
+            }
 
             return create<ast::BuiltinAttribute>(t.source(), builtin.value);
         });
@@ -3024,8 +3254,9 @@
     if (t == kStageAttribute) {
         return expect_paren_block("stage attribute", [&]() -> Result {
             auto stage = expect_pipeline_stage();
-            if (stage.errored)
+            if (stage.errored) {
                 return Failure::kErrored;
+            }
 
             return create<ast::StageAttribute>(t.source(), stage.value);
         });
@@ -3035,8 +3266,9 @@
         const char* use = "size attribute";
         return expect_paren_block(use, [&]() -> Result {
             auto val = expect_positive_sint(use);
-            if (val.errored)
+            if (val.errored) {
                 return Failure::kErrored;
+            }
 
             return create<ast::StructMemberSizeAttribute>(t.source(), val.value);
         });
@@ -3046,8 +3278,9 @@
         const char* use = "align attribute";
         return expect_paren_block(use, [&]() -> Result {
             auto val = expect_positive_sint(use);
-            if (val.errored)
+            if (val.errored) {
                 return Failure::kErrored;
+            }
 
             return create<ast::StructMemberAlignAttribute>(t.source(), val.value);
         });
@@ -3057,8 +3290,9 @@
         const char* use = "id attribute";
         return expect_paren_block(use, [&]() -> Result {
             auto val = expect_positive_sint(use);
-            if (val.errored)
+            if (val.errored) {
                 return Failure::kErrored;
+            }
 
             return create<ast::IdAttribute>(t.source(), val.value);
         });
@@ -3078,8 +3312,9 @@
 bool ParserImpl::match(Token::Type tok, Source* source /*= nullptr*/) {
     auto t = peek();
 
-    if (source != nullptr)
+    if (source != nullptr) {
         *source = t.source();
+    }
 
     if (t.Is(tok)) {
         next();
@@ -3148,22 +3383,26 @@
 
 Expect<uint32_t> ParserImpl::expect_positive_sint(std::string_view use) {
     auto sint = expect_sint(use);
-    if (sint.errored)
+    if (sint.errored) {
         return Failure::kErrored;
+    }
 
-    if (sint.value < 0)
+    if (sint.value < 0) {
         return add_error(sint.source, std::string(use) + " must be positive");
+    }
 
     return {static_cast<uint32_t>(sint.value), sint.source};
 }
 
 Expect<uint32_t> ParserImpl::expect_nonzero_positive_sint(std::string_view use) {
     auto sint = expect_sint(use);
-    if (sint.errored)
+    if (sint.errored) {
         return Failure::kErrored;
+    }
 
-    if (sint.value <= 0)
+    if (sint.value <= 0) {
         return add_error(sint.source, std::string(use) + " must be greater than 0");
+    }
 
     return {static_cast<uint32_t>(sint.value), sint.source};
 }
@@ -3196,11 +3435,13 @@
     return sync(end, [&]() -> T {
         auto res = body();
 
-        if (res.errored)
+        if (res.errored) {
             return Failure::kErrored;
+        }
 
-        if (!expect(use, end))
+        if (!expect(use, end)) {
             return Failure::kErrored;
+        }
 
         return res;
     });
diff --git a/src/tint/reader/wgsl/parser_impl_additive_expression_test.cc b/src/tint/reader/wgsl/parser_impl_additive_expression_test.cc
index 51cf90e..4573b84 100644
--- a/src/tint/reader/wgsl/parser_impl_additive_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_additive_expression_test.cc
@@ -25,6 +25,11 @@
     EXPECT_FALSE(p->has_error()) << p->error();
     ASSERT_NE(e.value, nullptr);
 
+    EXPECT_EQ(e->source.range.begin.line, 1u);
+    EXPECT_EQ(e->source.range.begin.column, 3u);
+    EXPECT_EQ(e->source.range.end.line, 1u);
+    EXPECT_EQ(e->source.range.end.column, 4u);
+
     ASSERT_TRUE(e->Is<ast::BinaryExpression>());
     auto* rel = e->As<ast::BinaryExpression>();
     EXPECT_EQ(ast::BinaryOp::kAdd, rel->op);
diff --git a/src/tint/reader/wgsl/parser_impl_and_expression_test.cc b/src/tint/reader/wgsl/parser_impl_and_expression_test.cc
index 1ed8a9c..fd90460 100644
--- a/src/tint/reader/wgsl/parser_impl_and_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_and_expression_test.cc
@@ -25,6 +25,11 @@
     EXPECT_FALSE(p->has_error()) << p->error();
     ASSERT_NE(e.value, nullptr);
 
+    EXPECT_EQ(e->source.range.begin.line, 1u);
+    EXPECT_EQ(e->source.range.begin.column, 3u);
+    EXPECT_EQ(e->source.range.end.line, 1u);
+    EXPECT_EQ(e->source.range.end.column, 4u);
+
     ASSERT_TRUE(e->Is<ast::BinaryExpression>());
     auto* rel = e->As<ast::BinaryExpression>();
     EXPECT_EQ(ast::BinaryOp::kAnd, rel->op);
diff --git a/src/tint/reader/wgsl/parser_impl_enable_directive_test.cc b/src/tint/reader/wgsl/parser_impl_enable_directive_test.cc
index 0fd6b80..bdf7eeb 100644
--- a/src/tint/reader/wgsl/parser_impl_enable_directive_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_enable_directive_test.cc
@@ -23,41 +23,36 @@
 
 // Test a valid enable directive.
 TEST_F(EnableDirectiveTest, Valid) {
-    auto p = parser("enable InternalExtensionForTesting;");
+    auto p = parser("enable f16;");
     p->enable_directive();
     EXPECT_FALSE(p->has_error()) << p->error();
     auto program = p->program();
     auto& ast = program.AST();
-    EXPECT_EQ(ast.Extensions(),
-              ast::ExtensionSet{ast::Enable::ExtensionKind::kInternalExtensionForTesting});
-    EXPECT_EQ(ast.GlobalDeclarations().size(), 1u);
-    auto* node = ast.GlobalDeclarations()[0]->As<ast::Enable>();
-    EXPECT_TRUE(node != nullptr);
-    EXPECT_EQ(node->name, "InternalExtensionForTesting");
-    EXPECT_EQ(node->kind, ast::Enable::ExtensionKind::kInternalExtensionForTesting);
+    ASSERT_EQ(ast.Enables().size(), 1u);
+    auto* enable = ast.Enables()[0];
+    EXPECT_EQ(enable->extension, ast::Extension::kF16);
+    ASSERT_EQ(ast.GlobalDeclarations().size(), 1u);
+    EXPECT_EQ(ast.GlobalDeclarations()[0], enable);
 }
 
 // Test multiple enable directives for a same extension.
 TEST_F(EnableDirectiveTest, EnableMultipleTime) {
     auto p = parser(R"(
-enable InternalExtensionForTesting;
-enable InternalExtensionForTesting;
+enable f16;
+enable f16;
 )");
     p->translation_unit();
     EXPECT_FALSE(p->has_error()) << p->error();
     auto program = p->program();
     auto& ast = program.AST();
-    EXPECT_EQ(ast.Extensions(),
-              ast::ExtensionSet{ast::Enable::ExtensionKind::kInternalExtensionForTesting});
-    EXPECT_EQ(ast.GlobalDeclarations().size(), 2u);
-    auto* node1 = ast.GlobalDeclarations()[0]->As<ast::Enable>();
-    EXPECT_TRUE(node1 != nullptr);
-    EXPECT_EQ(node1->name, "InternalExtensionForTesting");
-    EXPECT_EQ(node1->kind, ast::Enable::ExtensionKind::kInternalExtensionForTesting);
-    auto* node2 = ast.GlobalDeclarations()[1]->As<ast::Enable>();
-    EXPECT_TRUE(node2 != nullptr);
-    EXPECT_EQ(node2->name, "InternalExtensionForTesting");
-    EXPECT_EQ(node2->kind, ast::Enable::ExtensionKind::kInternalExtensionForTesting);
+    ASSERT_EQ(ast.Enables().size(), 2u);
+    auto* enable_a = ast.Enables()[0];
+    auto* enable_b = ast.Enables()[1];
+    EXPECT_EQ(enable_a->extension, ast::Extension::kF16);
+    EXPECT_EQ(enable_b->extension, ast::Extension::kF16);
+    ASSERT_EQ(ast.GlobalDeclarations().size(), 2u);
+    EXPECT_EQ(ast.GlobalDeclarations()[0], enable_a);
+    EXPECT_EQ(ast.GlobalDeclarations()[1], enable_b);
 }
 
 // Test an unknown extension identifier.
@@ -69,42 +64,42 @@
     EXPECT_EQ(p->error(), "1:8: unsupported extension: 'NotAValidExtensionName'");
     auto program = p->program();
     auto& ast = program.AST();
-    EXPECT_EQ(ast.Extensions().size(), 0u);
+    EXPECT_EQ(ast.Enables().size(), 0u);
     EXPECT_EQ(ast.GlobalDeclarations().size(), 0u);
 }
 
-// Test an enable directive missing ending semiclon.
-TEST_F(EnableDirectiveTest, MissingEndingSemiclon) {
-    auto p = parser("enable InternalExtensionForTesting");
+// Test an enable directive missing ending semicolon.
+TEST_F(EnableDirectiveTest, MissingEndingSemicolon) {
+    auto p = parser("enable f16");
     p->translation_unit();
     EXPECT_TRUE(p->has_error());
-    EXPECT_EQ(p->error(), "1:35: expected ';' for enable directive");
+    EXPECT_EQ(p->error(), "1:11: expected ';' for enable directive");
     auto program = p->program();
     auto& ast = program.AST();
-    EXPECT_EQ(ast.Extensions().size(), 0u);
+    EXPECT_EQ(ast.Enables().size(), 0u);
     EXPECT_EQ(ast.GlobalDeclarations().size(), 0u);
 }
 
 // Test using invalid tokens in an enable directive.
 TEST_F(EnableDirectiveTest, InvalidTokens) {
     {
-        auto p = parser("enable InternalExtensionForTesting<;");
+        auto p = parser("enable f16<;");
         p->translation_unit();
         EXPECT_TRUE(p->has_error());
-        EXPECT_EQ(p->error(), "1:35: expected ';' for enable directive");
+        EXPECT_EQ(p->error(), "1:11: expected ';' for enable directive");
         auto program = p->program();
         auto& ast = program.AST();
-        EXPECT_EQ(ast.Extensions().size(), 0u);
+        EXPECT_EQ(ast.Enables().size(), 0u);
         EXPECT_EQ(ast.GlobalDeclarations().size(), 0u);
     }
     {
-        auto p = parser("enable <InternalExtensionForTesting;");
+        auto p = parser("enable <f16;");
         p->translation_unit();
         EXPECT_TRUE(p->has_error());
         EXPECT_EQ(p->error(), "1:8: invalid extension name");
         auto program = p->program();
         auto& ast = program.AST();
-        EXPECT_EQ(ast.Extensions().size(), 0u);
+        EXPECT_EQ(ast.Enables().size(), 0u);
         EXPECT_EQ(ast.GlobalDeclarations().size(), 0u);
     }
     {
@@ -114,7 +109,7 @@
         EXPECT_EQ(p->error(), "1:8: invalid extension name");
         auto program = p->program();
         auto& ast = program.AST();
-        EXPECT_EQ(ast.Extensions().size(), 0u);
+        EXPECT_EQ(ast.Enables().size(), 0u);
         EXPECT_EQ(ast.GlobalDeclarations().size(), 0u);
     }
     {
@@ -124,7 +119,7 @@
         EXPECT_EQ(p->error(), "1:8: invalid extension name");
         auto program = p->program();
         auto& ast = program.AST();
-        EXPECT_EQ(ast.Extensions().size(), 0u);
+        EXPECT_EQ(ast.Enables().size(), 0u);
         EXPECT_EQ(ast.GlobalDeclarations().size(), 0u);
     }
 }
@@ -133,35 +128,39 @@
 TEST_F(EnableDirectiveTest, FollowingOtherGlobalDecl) {
     auto p = parser(R"(
 var<private> t: f32 = 0f;
-enable InternalExtensionForTesting;
+enable f16;
 )");
     p->translation_unit();
     EXPECT_TRUE(p->has_error());
     EXPECT_EQ(p->error(), "3:1: enable directives must come before all global declarations");
     auto program = p->program();
     auto& ast = program.AST();
-    // Accept the enable directive although it cause an error
-    EXPECT_EQ(ast.Extensions(),
-              ast::ExtensionSet{ast::Enable::ExtensionKind::kInternalExtensionForTesting});
-    EXPECT_EQ(ast.GlobalDeclarations().size(), 2u);
+    // Accept the enable directive although it caused an error
+    ASSERT_EQ(ast.Enables().size(), 1u);
+    auto* enable = ast.Enables()[0];
+    EXPECT_EQ(enable->extension, ast::Extension::kF16);
+    ASSERT_EQ(ast.GlobalDeclarations().size(), 2u);
+    EXPECT_EQ(ast.GlobalDeclarations()[1], enable);
 }
 
-// Test an enable directive go after an empty semiclon.
-TEST_F(EnableDirectiveTest, FollowingEmptySemiclon) {
+// Test an enable directive go after an empty semicolon.
+TEST_F(EnableDirectiveTest, FollowingEmptySemicolon) {
     auto p = parser(R"(
 ;
-enable InternalExtensionForTesting;
+enable f16;
 )");
     p->translation_unit();
-    // An empty semiclon is treated as a global declaration
+    // An empty semicolon is treated as a global declaration
     EXPECT_TRUE(p->has_error());
     EXPECT_EQ(p->error(), "3:1: enable directives must come before all global declarations");
     auto program = p->program();
     auto& ast = program.AST();
     // Accept the enable directive although it cause an error
-    EXPECT_EQ(ast.Extensions(),
-              ast::ExtensionSet{ast::Enable::ExtensionKind::kInternalExtensionForTesting});
-    EXPECT_EQ(ast.GlobalDeclarations().size(), 1u);
+    ASSERT_EQ(ast.Enables().size(), 1u);
+    auto* enable = ast.Enables()[0];
+    EXPECT_EQ(enable->extension, ast::Extension::kF16);
+    ASSERT_EQ(ast.GlobalDeclarations().size(), 1u);
+    EXPECT_EQ(ast.GlobalDeclarations()[0], enable);
 }
 
 }  // namespace
diff --git a/src/tint/reader/wgsl/parser_impl_equality_expression_test.cc b/src/tint/reader/wgsl/parser_impl_equality_expression_test.cc
index 4e1f5a3..158227d 100644
--- a/src/tint/reader/wgsl/parser_impl_equality_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_equality_expression_test.cc
@@ -25,6 +25,11 @@
     EXPECT_FALSE(p->has_error()) << p->error();
     ASSERT_NE(e.value, nullptr);
 
+    EXPECT_EQ(e->source.range.begin.line, 1u);
+    EXPECT_EQ(e->source.range.begin.column, 3u);
+    EXPECT_EQ(e->source.range.end.line, 1u);
+    EXPECT_EQ(e->source.range.end.column, 5u);
+
     ASSERT_TRUE(e->Is<ast::BinaryExpression>());
     auto* rel = e->As<ast::BinaryExpression>();
     EXPECT_EQ(ast::BinaryOp::kEqual, rel->op);
@@ -45,6 +50,11 @@
     EXPECT_FALSE(p->has_error()) << p->error();
     ASSERT_NE(e.value, nullptr);
 
+    EXPECT_EQ(e->source.range.begin.line, 1u);
+    EXPECT_EQ(e->source.range.begin.column, 3u);
+    EXPECT_EQ(e->source.range.end.line, 1u);
+    EXPECT_EQ(e->source.range.end.column, 5u);
+
     ASSERT_TRUE(e->Is<ast::BinaryExpression>());
     auto* rel = e->As<ast::BinaryExpression>();
     EXPECT_EQ(ast::BinaryOp::kNotEqual, rel->op);
diff --git a/src/tint/reader/wgsl/parser_impl_exclusive_or_expression_test.cc b/src/tint/reader/wgsl/parser_impl_exclusive_or_expression_test.cc
index c6f8ad4..2994ae8 100644
--- a/src/tint/reader/wgsl/parser_impl_exclusive_or_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_exclusive_or_expression_test.cc
@@ -25,6 +25,11 @@
     EXPECT_FALSE(p->has_error()) << p->error();
     ASSERT_NE(e.value, nullptr);
 
+    EXPECT_EQ(e->source.range.begin.line, 1u);
+    EXPECT_EQ(e->source.range.begin.column, 3u);
+    EXPECT_EQ(e->source.range.end.line, 1u);
+    EXPECT_EQ(e->source.range.end.column, 4u);
+
     ASSERT_TRUE(e->Is<ast::BinaryExpression>());
     auto* rel = e->As<ast::BinaryExpression>();
     EXPECT_EQ(ast::BinaryOp::kXor, rel->op);
diff --git a/src/tint/reader/wgsl/parser_impl_inclusive_or_expression_test.cc b/src/tint/reader/wgsl/parser_impl_inclusive_or_expression_test.cc
index 83b9358..f534ff7 100644
--- a/src/tint/reader/wgsl/parser_impl_inclusive_or_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_inclusive_or_expression_test.cc
@@ -25,6 +25,11 @@
     EXPECT_FALSE(p->has_error()) << p->error();
     ASSERT_NE(e.value, nullptr);
 
+    EXPECT_EQ(e->source.range.begin.line, 1u);
+    EXPECT_EQ(e->source.range.begin.column, 3u);
+    EXPECT_EQ(e->source.range.end.line, 1u);
+    EXPECT_EQ(e->source.range.end.column, 4u);
+
     ASSERT_TRUE(e->Is<ast::BinaryExpression>());
     auto* rel = e->As<ast::BinaryExpression>();
     EXPECT_EQ(ast::BinaryOp::kOr, rel->op);
diff --git a/src/tint/reader/wgsl/parser_impl_logical_and_expression_test.cc b/src/tint/reader/wgsl/parser_impl_logical_and_expression_test.cc
index 57624a5..8baadaf 100644
--- a/src/tint/reader/wgsl/parser_impl_logical_and_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_logical_and_expression_test.cc
@@ -25,6 +25,11 @@
     EXPECT_FALSE(p->has_error()) << p->error();
     ASSERT_NE(e.value, nullptr);
 
+    EXPECT_EQ(e->source.range.begin.line, 1u);
+    EXPECT_EQ(e->source.range.begin.column, 3u);
+    EXPECT_EQ(e->source.range.end.line, 1u);
+    EXPECT_EQ(e->source.range.end.column, 5u);
+
     ASSERT_TRUE(e->Is<ast::BinaryExpression>());
     auto* rel = e->As<ast::BinaryExpression>();
     EXPECT_EQ(ast::BinaryOp::kLogicalAnd, rel->op);
diff --git a/src/tint/reader/wgsl/parser_impl_logical_or_expression_test.cc b/src/tint/reader/wgsl/parser_impl_logical_or_expression_test.cc
index 6bde6bd..943b059 100644
--- a/src/tint/reader/wgsl/parser_impl_logical_or_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_logical_or_expression_test.cc
@@ -25,6 +25,11 @@
     EXPECT_FALSE(p->has_error()) << p->error();
     ASSERT_NE(e.value, nullptr);
 
+    EXPECT_EQ(e->source.range.begin.line, 1u);
+    EXPECT_EQ(e->source.range.begin.column, 3u);
+    EXPECT_EQ(e->source.range.end.line, 1u);
+    EXPECT_EQ(e->source.range.end.column, 5u);
+
     ASSERT_TRUE(e->Is<ast::BinaryExpression>());
     auto* rel = e->As<ast::BinaryExpression>();
     EXPECT_EQ(ast::BinaryOp::kLogicalOr, rel->op);
diff --git a/src/tint/reader/wgsl/parser_impl_multiplicative_expression_test.cc b/src/tint/reader/wgsl/parser_impl_multiplicative_expression_test.cc
index 6d77fd5..28ac568 100644
--- a/src/tint/reader/wgsl/parser_impl_multiplicative_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_multiplicative_expression_test.cc
@@ -25,6 +25,11 @@
     EXPECT_FALSE(p->has_error()) << p->error();
     ASSERT_NE(e.value, nullptr);
 
+    EXPECT_EQ(e->source.range.begin.line, 1u);
+    EXPECT_EQ(e->source.range.begin.column, 3u);
+    EXPECT_EQ(e->source.range.end.line, 1u);
+    EXPECT_EQ(e->source.range.end.column, 4u);
+
     ASSERT_TRUE(e->Is<ast::BinaryExpression>());
     auto* rel = e->As<ast::BinaryExpression>();
     EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
diff --git a/src/tint/reader/wgsl/parser_impl_relational_expression_test.cc b/src/tint/reader/wgsl/parser_impl_relational_expression_test.cc
index 725761b..7ad161f 100644
--- a/src/tint/reader/wgsl/parser_impl_relational_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_relational_expression_test.cc
@@ -25,6 +25,11 @@
     EXPECT_FALSE(p->has_error()) << p->error();
     ASSERT_NE(e.value, nullptr);
 
+    EXPECT_EQ(e->source.range.begin.line, 1u);
+    EXPECT_EQ(e->source.range.begin.column, 3u);
+    EXPECT_EQ(e->source.range.end.line, 1u);
+    EXPECT_EQ(e->source.range.end.column, 4u);
+
     ASSERT_TRUE(e->Is<ast::BinaryExpression>());
     auto* rel = e->As<ast::BinaryExpression>();
     EXPECT_EQ(ast::BinaryOp::kLessThan, rel->op);
@@ -45,6 +50,11 @@
     EXPECT_FALSE(p->has_error()) << p->error();
     ASSERT_NE(e.value, nullptr);
 
+    EXPECT_EQ(e->source.range.begin.line, 1u);
+    EXPECT_EQ(e->source.range.begin.column, 3u);
+    EXPECT_EQ(e->source.range.end.line, 1u);
+    EXPECT_EQ(e->source.range.end.column, 4u);
+
     ASSERT_TRUE(e->Is<ast::BinaryExpression>());
     auto* rel = e->As<ast::BinaryExpression>();
     EXPECT_EQ(ast::BinaryOp::kGreaterThan, rel->op);
@@ -65,6 +75,11 @@
     EXPECT_FALSE(p->has_error()) << p->error();
     ASSERT_NE(e.value, nullptr);
 
+    EXPECT_EQ(e->source.range.begin.line, 1u);
+    EXPECT_EQ(e->source.range.begin.column, 3u);
+    EXPECT_EQ(e->source.range.end.line, 1u);
+    EXPECT_EQ(e->source.range.end.column, 5u);
+
     ASSERT_TRUE(e->Is<ast::BinaryExpression>());
     auto* rel = e->As<ast::BinaryExpression>();
     EXPECT_EQ(ast::BinaryOp::kLessThanEqual, rel->op);
@@ -85,6 +100,11 @@
     EXPECT_FALSE(p->has_error()) << p->error();
     ASSERT_NE(e.value, nullptr);
 
+    EXPECT_EQ(e->source.range.begin.line, 1u);
+    EXPECT_EQ(e->source.range.begin.column, 3u);
+    EXPECT_EQ(e->source.range.end.line, 1u);
+    EXPECT_EQ(e->source.range.end.column, 5u);
+
     ASSERT_TRUE(e->Is<ast::BinaryExpression>());
     auto* rel = e->As<ast::BinaryExpression>();
     EXPECT_EQ(ast::BinaryOp::kGreaterThanEqual, rel->op);
diff --git a/src/tint/reader/wgsl/parser_impl_reserved_keyword_test.cc b/src/tint/reader/wgsl/parser_impl_reserved_keyword_test.cc
index 3226ef5..e840af7 100644
--- a/src/tint/reader/wgsl/parser_impl_reserved_keyword_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_reserved_keyword_test.cc
@@ -88,7 +88,6 @@
                                          "const",
                                          "do",
                                          "enum",
-                                         "f16",
                                          "f64",
                                          "handle",
                                          "i8",
diff --git a/src/tint/reader/wgsl/parser_impl_shift_expression_test.cc b/src/tint/reader/wgsl/parser_impl_shift_expression_test.cc
index fd612b5..83c1255 100644
--- a/src/tint/reader/wgsl/parser_impl_shift_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_shift_expression_test.cc
@@ -25,6 +25,11 @@
     EXPECT_FALSE(p->has_error()) << p->error();
     ASSERT_NE(e.value, nullptr);
 
+    EXPECT_EQ(e->source.range.begin.line, 1u);
+    EXPECT_EQ(e->source.range.begin.column, 3u);
+    EXPECT_EQ(e->source.range.end.line, 1u);
+    EXPECT_EQ(e->source.range.end.column, 5u);
+
     ASSERT_TRUE(e->Is<ast::BinaryExpression>());
     auto* rel = e->As<ast::BinaryExpression>();
     EXPECT_EQ(ast::BinaryOp::kShiftLeft, rel->op);
@@ -45,6 +50,11 @@
     EXPECT_FALSE(p->has_error()) << p->error();
     ASSERT_NE(e.value, nullptr);
 
+    EXPECT_EQ(e->source.range.begin.line, 1u);
+    EXPECT_EQ(e->source.range.begin.column, 3u);
+    EXPECT_EQ(e->source.range.end.line, 1u);
+    EXPECT_EQ(e->source.range.end.column, 5u);
+
     ASSERT_TRUE(e->Is<ast::BinaryExpression>());
     auto* rel = e->As<ast::BinaryExpression>();
     EXPECT_EQ(ast::BinaryOp::kShiftRight, rel->op);
diff --git a/src/tint/reader/wgsl/parser_impl_type_decl_test.cc b/src/tint/reader/wgsl/parser_impl_type_decl_test.cc
index a721d77..bc2bfe5 100644
--- a/src/tint/reader/wgsl/parser_impl_type_decl_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_type_decl_test.cc
@@ -55,6 +55,17 @@
     EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 5u}}));
 }
 
+TEST_F(ParserImplTest, TypeDecl_F16) {
+    auto p = parser("f16");
+
+    auto t = p->type_decl();
+    EXPECT_TRUE(t.matched);
+    EXPECT_FALSE(t.errored);
+    ASSERT_NE(t.value, nullptr) << p->error();
+    ASSERT_TRUE(t.value->Is<ast::F16>());
+    EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 4u}}));
+}
+
 TEST_F(ParserImplTest, TypeDecl_F32) {
     auto p = parser("f32");
 
diff --git a/src/tint/reader/wgsl/token.cc b/src/tint/reader/wgsl/token.cc
index 06eb6fb..4680eee 100644
--- a/src/tint/reader/wgsl/token.cc
+++ b/src/tint/reader/wgsl/token.cc
@@ -151,6 +151,8 @@
             return "else";
         case Token::Type::kEnable:
             return "enable";
+        case Token::Type::kF16:
+            return "f16";
         case Token::Type::kF32:
             return "f32";
         case Token::Type::kFallthrough:
diff --git a/src/tint/reader/wgsl/token.h b/src/tint/reader/wgsl/token.h
index 82b3fab..0a68f9b0 100644
--- a/src/tint/reader/wgsl/token.h
+++ b/src/tint/reader/wgsl/token.h
@@ -162,6 +162,8 @@
         kElse,
         /// A 'enable'
         kEnable,
+        /// A 'f16'
+        kF16,
         /// A 'f32'
         kF32,
         /// A 'fallthrough'
diff --git a/src/tint/resolver/builtin_test.cc b/src/tint/resolver/builtin_test.cc
index 6020eae..74a898c 100644
--- a/src/tint/resolver/builtin_test.cc
+++ b/src/tint/resolver/builtin_test.cc
@@ -1924,7 +1924,7 @@
         }
     }
 
-    auto* call_sem = Sem().Get(call);
+    auto* call_sem = Sem().Get<sem::Call>(call);
     ASSERT_NE(call_sem, nullptr);
     auto* target = call_sem->Target();
     ASSERT_NE(target, nullptr);
diff --git a/src/tint/resolver/builtin_validation_test.cc b/src/tint/resolver/builtin_validation_test.cc
index 0e48b55..770d8d0 100644
--- a/src/tint/resolver/builtin_validation_test.cc
+++ b/src/tint/resolver/builtin_validation_test.cc
@@ -378,10 +378,7 @@
 TEST_F(ResolverDP4aExtensionValidationTest, Dot4I8PackedWithExtension) {
     // enable chromium_experimental_dp4a;
     // fn func { return dot4I8Packed(1u, 2u); }
-    auto* ext =
-        create<ast::Enable>(Source{Source::Range{Source::Location{10, 2}, Source::Location{10, 5}}},
-                            "chromium_experimental_dp4a");
-    AST().AddEnable(ext);
+    Enable(ast::Extension::kChromiumExperimentalDP4a);
 
     Func("func", {}, ty.i32(),
          {
@@ -409,10 +406,7 @@
 TEST_F(ResolverDP4aExtensionValidationTest, Dot4U8PackedWithExtension) {
     // enable chromium_experimental_dp4a;
     // fn func { return dot4U8Packed(1u, 2u); }
-    auto* ext =
-        create<ast::Enable>(Source{Source::Range{Source::Location{10, 2}, Source::Location{10, 5}}},
-                            "chromium_experimental_dp4a");
-    AST().AddEnable(ext);
+    Enable(ast::Extension::kChromiumExperimentalDP4a);
 
     Func("func", {}, ty.u32(),
          {
diff --git a/src/tint/resolver/call_test.cc b/src/tint/resolver/call_test.cc
index d84f300..39a6eb4 100644
--- a/src/tint/resolver/call_test.cc
+++ b/src/tint/resolver/call_test.cc
@@ -94,7 +94,7 @@
 
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
-    auto* call = Sem().Get(call_expr);
+    auto* call = Sem().Get<sem::Call>(call_expr);
     EXPECT_NE(call, nullptr);
     EXPECT_EQ(call->Target(), Sem().Get(func));
 }
@@ -106,7 +106,7 @@
 
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
-    auto* call = Sem().Get(call_expr);
+    auto* call = Sem().Get<sem::Call>(call_expr);
     EXPECT_NE(call, nullptr);
     EXPECT_EQ(call->Target(), Sem().Get(b));
 }
diff --git a/src/tint/resolver/compound_statement_test.cc b/src/tint/resolver/compound_statement_test.cc
index 4061a62..0444bd3 100644
--- a/src/tint/resolver/compound_statement_test.cc
+++ b/src/tint/resolver/compound_statement_test.cc
@@ -144,6 +144,35 @@
     }
 }
 
+TEST_F(ResolverCompoundStatementTest, Loop_EmptyContinuing) {
+    // fn F() {
+    //   loop {
+    //     break;
+    //     continuing {
+    //     }
+    //   }
+    // }
+    auto* brk = Break();
+    auto* loop = Loop(Block(brk), Block());
+    Func("F", {}, ty.void_(), {loop});
+
+    ASSERT_TRUE(r()->Resolve()) << r()->error();
+
+    {
+        auto* s = Sem().Get(loop);
+        ASSERT_NE(s, nullptr);
+        EXPECT_TRUE(s->Is<sem::LoopStatement>());
+        EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::FunctionBlockStatement>());
+        EXPECT_EQ(s->Parent(), s->Block());
+    }
+    {
+        auto* s = Sem().Get(loop->continuing);
+        ASSERT_NE(s, nullptr);
+        EXPECT_TRUE(Is<sem::LoopContinuingBlockStatement>(s));
+        EXPECT_TRUE(Is<sem::LoopStatement>(s->Parent()->Parent()));
+    }
+}
+
 TEST_F(ResolverCompoundStatementTest, ForLoop) {
     // fn F() {
     //   for (var i : u32; true; i = i + 1u) {
diff --git a/src/tint/resolver/ctor_conv_intrinsic.cc b/src/tint/resolver/ctor_conv_intrinsic.cc
new file mode 100644
index 0000000..5618fba
--- /dev/null
+++ b/src/tint/resolver/ctor_conv_intrinsic.cc
@@ -0,0 +1,70 @@
+// Copyright 2021 The Tint 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.
+
+////////////////////////////////////////////////////////////////////////////////
+// File generated by tools/intrinsic-gen
+// using the template:
+//   src/tint/resolver/ctor_conv_intrinsic.cc.tmpl
+// and the intrinsic defintion file:
+//   src/tint/intrinsics.def
+//
+// Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
+#include "src/tint/resolver/ctor_conv_intrinsic.h"
+
+namespace tint::resolver {
+
+const char* str(CtorConvIntrinsic i) {
+    switch (i) {
+        case CtorConvIntrinsic::kNone:
+            return "<none>";
+        case CtorConvIntrinsic::kI32:
+            return "i32";
+        case CtorConvIntrinsic::kU32:
+            return "u32";
+        case CtorConvIntrinsic::kF32:
+            return "f32";
+        case CtorConvIntrinsic::kBool:
+            return "bool";
+        case CtorConvIntrinsic::kVec2:
+            return "vec2";
+        case CtorConvIntrinsic::kVec3:
+            return "vec3";
+        case CtorConvIntrinsic::kVec4:
+            return "vec4";
+        case CtorConvIntrinsic::kMat2x2:
+            return "mat2x2";
+        case CtorConvIntrinsic::kMat2x3:
+            return "mat2x3";
+        case CtorConvIntrinsic::kMat2x4:
+            return "mat2x4";
+        case CtorConvIntrinsic::kMat3x2:
+            return "mat3x2";
+        case CtorConvIntrinsic::kMat3x3:
+            return "mat3x3";
+        case CtorConvIntrinsic::kMat3x4:
+            return "mat3x4";
+        case CtorConvIntrinsic::kMat4x2:
+            return "mat4x2";
+        case CtorConvIntrinsic::kMat4x3:
+            return "mat4x3";
+        case CtorConvIntrinsic::kMat4x4:
+            return "mat4x4";
+    }
+    return "<unknown>";
+}
+
+}  // namespace tint::resolver
+
diff --git a/src/tint/resolver/ctor_conv_intrinsic.cc.tmpl b/src/tint/resolver/ctor_conv_intrinsic.cc.tmpl
new file mode 100644
index 0000000..ac98c4d
--- /dev/null
+++ b/src/tint/resolver/ctor_conv_intrinsic.cc.tmpl
@@ -0,0 +1,28 @@
+{{- /*
+--------------------------------------------------------------------------------
+Template file for use with tools/builtin-gen to generate ctor_conv_intrinsic.cc
+
+See:
+* tools/cmd/intrinsic-gen/gen for structures used by this template
+* https://golang.org/pkg/text/template/ for documentation on the template syntax
+--------------------------------------------------------------------------------
+*/ -}}
+
+#include "src/tint/resolver/ctor_conv_intrinsic.h"
+
+namespace tint::resolver {
+
+const char* str(CtorConvIntrinsic i) {
+    switch (i) {
+        case CtorConvIntrinsic::kNone:
+            return "<none>";
+{{- range .Sem.ConstructorsAndConverters  }}
+        case CtorConvIntrinsic::k{{Title .Name}}:
+            return "{{.Name}}";
+{{- end  }}
+    }
+    return "<unknown>";
+}
+
+}  // namespace tint::resolver
+
diff --git a/src/tint/resolver/ctor_conv_intrinsic.h b/src/tint/resolver/ctor_conv_intrinsic.h
new file mode 100644
index 0000000..7c68658
--- /dev/null
+++ b/src/tint/resolver/ctor_conv_intrinsic.h
@@ -0,0 +1,100 @@
+// Copyright 2021 The Tint 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.
+
+////////////////////////////////////////////////////////////////////////////////
+// File generated by tools/intrinsic-gen
+// using the template:
+//   src/tint/resolver/ctor_conv_intrinsic.h.tmpl
+// and the intrinsic defintion file:
+//   src/tint/intrinsics.def
+//
+// Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef SRC_TINT_RESOLVER_CTOR_CONV_INTRINSIC_H_
+#define SRC_TINT_RESOLVER_CTOR_CONV_INTRINSIC_H_
+
+#include <cstdint>
+
+namespace tint::resolver {
+
+/// CtorConvIntrinsic is an enumerator of types that have a constructor or converter overload
+/// declared in the intrinsic table.
+enum class CtorConvIntrinsic {
+    kNone = -1,
+    kI32,
+    kU32,
+    kF32,
+    kBool,
+    kVec2,
+    kVec3,
+    kVec4,
+    kMat2x2,
+    kMat2x3,
+    kMat2x4,
+    kMat3x2,
+    kMat3x3,
+    kMat3x4,
+    kMat4x2,
+    kMat4x3,
+    kMat4x4,
+};
+
+/// @returns the name of the type.
+const char* str(CtorConvIntrinsic i);
+
+/// @param n the width of the vector
+/// @return the CtorConvIntrinsic for a vector of width `n`
+inline CtorConvIntrinsic VectorCtorConvIntrinsic(uint32_t n) {
+    switch (n) {
+        case 2:
+            return CtorConvIntrinsic::kVec2;
+        case 3:
+            return CtorConvIntrinsic::kVec3;
+        case 4:
+            return CtorConvIntrinsic::kVec4;
+    }
+    return CtorConvIntrinsic::kNone;
+}
+
+/// @param c the number of columns in the matrix
+/// @param r the number of rows in the matrix
+/// @return the CtorConvIntrinsic for a matrix with `c` columns and `r` rows
+inline CtorConvIntrinsic MatrixCtorConvIntrinsic(uint32_t c, uint32_t r) {
+    switch ((c - 2) * 3 + (r - 2)) {
+        case 0:
+            return CtorConvIntrinsic::kMat2x2;
+        case 1:
+            return CtorConvIntrinsic::kMat2x3;
+        case 2:
+            return CtorConvIntrinsic::kMat2x4;
+        case 3:
+            return CtorConvIntrinsic::kMat3x2;
+        case 4:
+            return CtorConvIntrinsic::kMat3x3;
+        case 5:
+            return CtorConvIntrinsic::kMat3x4;
+        case 6:
+            return CtorConvIntrinsic::kMat4x2;
+        case 7:
+            return CtorConvIntrinsic::kMat4x3;
+        case 8:
+            return CtorConvIntrinsic::kMat4x4;
+    }
+    return CtorConvIntrinsic::kNone;
+}
+
+}  // namespace tint::resolver
+
+#endif  // SRC_TINT_RESOLVER_CTOR_CONV_INTRINSIC_H_
diff --git a/src/tint/resolver/ctor_conv_intrinsic.h.tmpl b/src/tint/resolver/ctor_conv_intrinsic.h.tmpl
new file mode 100644
index 0000000..9c0da25
--- /dev/null
+++ b/src/tint/resolver/ctor_conv_intrinsic.h.tmpl
@@ -0,0 +1,73 @@
+{{- /*
+--------------------------------------------------------------------------------
+Template file for use with tools/builtin-gen to generate ctor_conv_intrinsic.h
+
+See:
+* tools/cmd/intrinsic-gen/gen for structures used by this template
+* https://golang.org/pkg/text/template/ for documentation on the template syntax
+--------------------------------------------------------------------------------
+*/ -}}
+
+#ifndef SRC_TINT_RESOLVER_CTOR_CONV_INTRINSIC_H_
+#define SRC_TINT_RESOLVER_CTOR_CONV_INTRINSIC_H_
+
+#include <cstdint>
+
+namespace tint::resolver {
+
+/// CtorConvIntrinsic is an enumerator of types that have a constructor or converter overload
+/// declared in the intrinsic table.
+enum class CtorConvIntrinsic {
+    kNone = -1,
+{{- range .Sem.ConstructorsAndConverters }}
+    k{{Title .Name}},
+{{- end }}
+};
+
+/// @returns the name of the type.
+const char* str(CtorConvIntrinsic i);
+
+/// @param n the width of the vector
+/// @return the CtorConvIntrinsic for a vector of width `n`
+inline CtorConvIntrinsic VectorCtorConvIntrinsic(uint32_t n) {
+    switch (n) {
+        case 2:
+            return CtorConvIntrinsic::kVec2;
+        case 3:
+            return CtorConvIntrinsic::kVec3;
+        case 4:
+            return CtorConvIntrinsic::kVec4;
+    }
+    return CtorConvIntrinsic::kNone;
+}
+
+/// @param c the number of columns in the matrix
+/// @param r the number of rows in the matrix
+/// @return the CtorConvIntrinsic for a matrix with `c` columns and `r` rows
+inline CtorConvIntrinsic MatrixCtorConvIntrinsic(uint32_t c, uint32_t r) {
+    switch ((c - 2) * 3 + (r - 2)) {
+        case 0:
+            return CtorConvIntrinsic::kMat2x2;
+        case 1:
+            return CtorConvIntrinsic::kMat2x3;
+        case 2:
+            return CtorConvIntrinsic::kMat2x4;
+        case 3:
+            return CtorConvIntrinsic::kMat3x2;
+        case 4:
+            return CtorConvIntrinsic::kMat3x3;
+        case 5:
+            return CtorConvIntrinsic::kMat3x4;
+        case 6:
+            return CtorConvIntrinsic::kMat4x2;
+        case 7:
+            return CtorConvIntrinsic::kMat4x3;
+        case 8:
+            return CtorConvIntrinsic::kMat4x4;
+    }
+    return CtorConvIntrinsic::kNone;
+}
+
+}  // namespace tint::resolver
+
+#endif  // SRC_TINT_RESOLVER_CTOR_CONV_INTRINSIC_H_
diff --git a/src/tint/resolver/dependency_graph.cc b/src/tint/resolver/dependency_graph.cc
index 0a9bdc0..7e66899 100644
--- a/src/tint/resolver/dependency_graph.cc
+++ b/src/tint/resolver/dependency_graph.cc
@@ -342,7 +342,7 @@
                 TraverseType(tex->type);
             },
             [&](Default) {
-                if (!ty->IsAnyOf<ast::Void, ast::Bool, ast::I32, ast::U32, ast::F32,
+                if (!ty->IsAnyOf<ast::Void, ast::Bool, ast::I32, ast::U32, ast::F16, ast::F32,
                                  ast::DepthTexture, ast::DepthMultisampledTexture,
                                  ast::StorageTexture, ast::ExternalTexture, ast::Sampler>()) {
                     UnhandledNode(diagnostics_, ty);
@@ -420,7 +420,7 @@
     DependencyGraph& graph_;
     DependencyEdges& dependency_edges_;
 
-    ScopeStack<const ast::Node*> scope_stack_;
+    ScopeStack<Symbol, const ast::Node*> scope_stack_;
     Global* current_global_ = nullptr;
 };
 
diff --git a/src/tint/resolver/intrinsic_table.cc b/src/tint/resolver/intrinsic_table.cc
index fa9dbf8..6c19f7c 100644
--- a/src/tint/resolver/intrinsic_table.cc
+++ b/src/tint/resolver/intrinsic_table.cc
@@ -20,6 +20,9 @@
 #include <utility>
 
 #include "src/tint/program_builder.h"
+#include "src/tint/sem/abstract_float.h"
+#include "src/tint/sem/abstract_int.h"
+#include "src/tint/sem/abstract_numeric.h"
 #include "src/tint/sem/atomic.h"
 #include "src/tint/sem/depth_multisampled_texture.h"
 #include "src/tint/sem/depth_texture.h"
@@ -28,12 +31,14 @@
 #include "src/tint/sem/pipeline_stage_set.h"
 #include "src/tint/sem/sampled_texture.h"
 #include "src/tint/sem/storage_texture.h"
+#include "src/tint/sem/type_constructor.h"
+#include "src/tint/sem/type_conversion.h"
 #include "src/tint/utils/hash.h"
 #include "src/tint/utils/map.h"
 #include "src/tint/utils/math.h"
 #include "src/tint/utils/scoped_assignment.h"
 
-namespace tint {
+namespace tint::resolver {
 namespace {
 
 // Forward declarations
@@ -98,83 +103,86 @@
 const Number Number::any{Number::kAny};
 const Number Number::invalid{Number::kInvalid};
 
-/// ClosedState holds the state of the open / closed numbers and types.
+/// TemplateState holds the state of the template numbers and types.
 /// Used by the MatchState.
-class ClosedState {
+class TemplateState {
   public:
-    explicit ClosedState(ProgramBuilder& b) : builder(b) {}
-
-    /// If the type with index `idx` is open, then it is closed with type `ty` and
-    /// Type() returns true. If the type is closed, then `Type()` returns true iff
-    /// it is equal to `ty`.
-    bool Type(uint32_t idx, const sem::Type* ty) {
+    /// If the template type with index `idx` is undefined, then it is defined with the `ty` and
+    /// Type() returns `ty`.
+    /// If the template type is defined, and `ty` can be converted to the template type then the
+    /// template type is returned.
+    /// If the template type is defined, and the template type can be converted to `ty`, then the
+    /// template type is replaced with `ty`, and `ty` is returned.
+    /// If none of the above applies, then `ty` is a type mismatch for the template type, and
+    /// nullptr is returned.
+    const sem::Type* Type(size_t idx, const sem::Type* ty) {
         auto res = types_.emplace(idx, ty);
-        return res.second || res.first->second == ty;
+        if (res.second) {
+            return ty;
+        }
+        auto* existing = res.first->second;
+        if (existing == ty) {
+            return ty;
+        }
+        ty = sem::Type::Common({existing, ty});
+        if (ty) {
+            res.first->second = ty;
+        }
+        return ty;
     }
 
-    /// If the number with index `idx` is open, then it is closed with number
-    /// `number` and Num() returns true. If the number is closed, then `Num()`
-    /// returns true iff it is equal to `ty`.
-    bool Num(uint32_t idx, Number number) {
+    /// If the number with index `idx` is undefined, then it is defined with the number `number` and
+    /// Num() returns true. If the number is defined, then `Num()` returns true iff it is equal to
+    /// `ty`.
+    bool Num(size_t idx, Number number) {
         auto res = numbers_.emplace(idx, number.Value());
         return res.second || res.first->second == number.Value();
     }
 
-    /// Type returns the closed type with index `idx`.
-    /// An ICE is raised if the type is not closed.
-    const sem::Type* Type(uint32_t idx) const {
+    /// Type returns the template type with index `idx`, or nullptr if the type was not defined.
+    const sem::Type* Type(size_t idx) const {
         auto it = types_.find(idx);
-        if (it == types_.end()) {
-            TINT_ICE(Resolver, builder.Diagnostics())
-                << "type with index " << idx << " is not closed";
-            return nullptr;
-        }
-        TINT_ASSERT(Resolver, it != types_.end());
-        return it->second;
+        return (it != types_.end()) ? it->second : nullptr;
     }
 
+    /// SetType replaces the template type with index `idx` with type `ty`.
+    void SetType(size_t idx, const sem::Type* ty) { types_[idx] = ty; }
+
     /// Type returns the number type with index `idx`.
-    /// An ICE is raised if the number is not closed.
-    Number Num(uint32_t idx) const {
+    Number Num(size_t idx) const {
         auto it = numbers_.find(idx);
-        if (it == numbers_.end()) {
-            TINT_ICE(Resolver, builder.Diagnostics())
-                << "number with index " << idx << " is not closed";
-            return Number::invalid;
-        }
-        return Number(it->second);
+        return (it != numbers_.end()) ? Number(it->second) : Number::invalid;
     }
 
   private:
-    ProgramBuilder& builder;
-    std::unordered_map<uint32_t, const sem::Type*> types_;
-    std::unordered_map<uint32_t, uint32_t> numbers_;
+    std::unordered_map<size_t, const sem::Type*> types_;
+    std::unordered_map<size_t, uint32_t> numbers_;
 };
 
 /// Index type used for matcher indices
 using MatcherIndex = uint8_t;
 
-/// Index value used for open types / numbers that do not have a constraint
+/// Index value used for template types / numbers that do not have a constraint
 constexpr MatcherIndex kNoMatcher = std::numeric_limits<MatcherIndex>::max();
 
 /// MatchState holds the state used to match an overload.
 class MatchState {
   public:
     MatchState(ProgramBuilder& b,
-               ClosedState& c,
+               TemplateState& t,
                const Matchers& m,
-               const OverloadInfo& o,
+               const OverloadInfo* o,
                MatcherIndex const* matcher_indices)
-        : builder(b), closed(c), matchers(m), overload(o), matcher_indices_(matcher_indices) {}
+        : builder(b), templates(t), matchers(m), overload(o), matcher_indices_(matcher_indices) {}
 
     /// The program builder
     ProgramBuilder& builder;
-    /// The open / closed types and numbers
-    ClosedState& closed;
+    /// The template types and numbers
+    TemplateState& templates;
     /// The type and number matchers
     Matchers const& matchers;
     /// The current overload being evaluated
-    OverloadInfo const& overload;
+    OverloadInfo const* overload;
 
     /// Type uses the next TypeMatcher from the matcher indices to match the type
     /// `ty`. If the type matches, the canonical expected type is returned. If the
@@ -211,14 +219,14 @@
 
     /// Checks whether the given type matches the matcher rules, and returns the
     /// expected, canonicalized type on success.
-    /// Match may close open types and numbers in state.
+    /// Match may define and refine the template types and numbers in state.
     /// @param type the type to match
     /// @returns the canonicalized type on match, otherwise nullptr
     virtual const sem::Type* Match(MatchState& state, const sem::Type* type) const = 0;
 
     /// @return a string representation of the matcher. Used for printing error
     /// messages when no overload is found.
-    virtual std::string String(MatchState& state) const = 0;
+    virtual std::string String(MatchState* state) const = 0;
 };
 
 /// A NumberMatcher is the interface used to match a number or enumerator used
@@ -229,55 +237,58 @@
     virtual ~NumberMatcher() = default;
 
     /// Checks whether the given number matches the matcher rules.
-    /// Match may close open numbers in state.
+    /// Match may define template numbers in state.
     /// @param number the number to match
     /// @returns true if the argument type is as expected.
     virtual Number Match(MatchState& state, Number number) const = 0;
 
     /// @return a string representation of the matcher. Used for printing error
     /// messages when no overload is found.
-    virtual std::string String(MatchState& state) const = 0;
+    virtual std::string String(MatchState* state) const = 0;
 };
 
-/// OpenTypeMatcher is a Matcher for an open type.
-/// The OpenTypeMatcher will match against any type (so long as it is consistent
-/// across all uses in the overload)
-class OpenTypeMatcher : public TypeMatcher {
+/// TemplateTypeMatcher is a Matcher for a template type.
+/// The TemplateTypeMatcher will initially match against any type, and then will only be further
+/// constrained based on the conversion rules defined at https://www.w3.org/TR/WGSL/#conversion-rank
+class TemplateTypeMatcher : public TypeMatcher {
   public:
     /// Constructor
-    explicit OpenTypeMatcher(uint32_t index) : index_(index) {}
+    explicit TemplateTypeMatcher(size_t index) : index_(index) {}
 
     const sem::Type* Match(MatchState& state, const sem::Type* type) const override {
         if (type->Is<Any>()) {
-            return state.closed.Type(index_);
+            return state.templates.Type(index_);
         }
-        return state.closed.Type(index_, type) ? type : nullptr;
+        if (auto* templates = state.templates.Type(index_, type)) {
+            return templates;
+        }
+        return nullptr;
     }
 
-    std::string String(MatchState& state) const override;
+    std::string String(MatchState* state) const override;
 
   private:
-    uint32_t index_;
+    size_t index_;
 };
 
-/// OpenNumberMatcher is a Matcher for an open number.
-/// The OpenNumberMatcher will match against any number (so long as it is
-/// consistent for the overload)
-class OpenNumberMatcher : public NumberMatcher {
+/// TemplateNumberMatcher is a Matcher for a template number.
+/// The TemplateNumberMatcher will match against any number (so long as it is
+/// consistent for all uses in the overload)
+class TemplateNumberMatcher : public NumberMatcher {
   public:
-    explicit OpenNumberMatcher(uint32_t index) : index_(index) {}
+    explicit TemplateNumberMatcher(size_t index) : index_(index) {}
 
     Number Match(MatchState& state, Number number) const override {
         if (number.IsAny()) {
-            return state.closed.Num(index_);
+            return state.templates.Num(index_);
         }
-        return state.closed.Num(index_, number) ? number : Number::invalid;
+        return state.templates.Num(index_, number) ? number : Number::invalid;
     }
 
-    std::string String(MatchState& state) const override;
+    std::string String(MatchState* state) const override;
 
   private:
-    uint32_t index_;
+    size_t index_;
 };
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -289,19 +300,53 @@
 using Access = ast::Access;
 using StorageClass = ast::StorageClass;
 using ParameterUsage = sem::ParameterUsage;
-using PipelineStageSet = sem::PipelineStageSet;
 using PipelineStage = ast::PipelineStage;
 
+/// Unique flag bits for overloads
+enum class OverloadFlag {
+    kIsBuiltin,                 // The overload is a builtin ('fn')
+    kIsOperator,                // The overload is an operator ('op')
+    kIsConstructor,             // The overload is a type constructor ('ctor')
+    kIsConverter,               // The overload is a type converter ('conv')
+    kSupportsVertexPipeline,    // The overload can be used in vertex shaders
+    kSupportsFragmentPipeline,  // The overload can be used in fragment shaders
+    kSupportsComputePipeline,   // The overload can be used in compute shaders
+    kIsDeprecated,              // The overload is deprecated
+};
+
+// An enum set of OverloadFlag, used by OperatorInfo
+using OverloadFlags = utils::EnumSet<OverloadFlag>;
+
 bool match_bool(const sem::Type* ty) {
     return ty->IsAnyOf<Any, sem::Bool>();
 }
 
+const sem::AbstractFloat* build_af(MatchState& state) {
+    return state.builder.create<sem::AbstractFloat>();
+}
+
+bool match_af(const sem::Type* ty) {
+    return ty->IsAnyOf<Any, sem::AbstractFloat>();
+}
+
+const sem::AbstractInt* build_ai(MatchState& state) {
+    return state.builder.create<sem::AbstractInt>();
+}
+
+bool match_ai(const sem::Type* ty) {
+    return ty->IsAnyOf<Any, sem::AbstractInt>();
+}
+
 const sem::Bool* build_bool(MatchState& state) {
     return state.builder.create<sem::Bool>();
 }
 
+const sem::F32* build_f32(MatchState& state) {
+    return state.builder.create<sem::F32>();
+}
+
 bool match_f32(const sem::Type* ty) {
-    return ty->IsAnyOf<Any, sem::F32>();
+    return ty->IsAnyOf<Any, sem::F32, sem::AbstractNumeric>();
 }
 
 const sem::I32* build_i32(MatchState& state) {
@@ -309,7 +354,7 @@
 }
 
 bool match_i32(const sem::Type* ty) {
-    return ty->IsAnyOf<Any, sem::I32>();
+    return ty->IsAnyOf<Any, sem::I32, sem::AbstractInt>();
 }
 
 const sem::U32* build_u32(MatchState& state) {
@@ -317,11 +362,7 @@
 }
 
 bool match_u32(const sem::Type* ty) {
-    return ty->IsAnyOf<Any, sem::U32>();
-}
-
-const sem::F32* build_f32(MatchState& state) {
-    return state.builder.create<sem::F32>();
+    return ty->IsAnyOf<Any, sem::U32, sem::AbstractInt>();
 }
 
 bool match_vec(const sem::Type* ty, Number& N, const sem::Type*& T) {
@@ -339,11 +380,7 @@
     return false;
 }
 
-const sem::Vector* build_vec(MatchState& state, Number N, const sem::Type* el) {
-    return state.builder.create<sem::Vector>(el, N.Value());
-}
-
-template <int N>
+template <uint32_t N>
 bool match_vec(const sem::Type* ty, const sem::Type*& T) {
     if (ty->Is<Any>()) {
         T = ty;
@@ -359,29 +396,22 @@
     return false;
 }
 
-bool match_vec2(const sem::Type* ty, const sem::Type*& T) {
-    return match_vec<2>(ty, T);
+const sem::Vector* build_vec(MatchState& state, Number N, const sem::Type* el) {
+    return state.builder.create<sem::Vector>(el, N.Value());
 }
 
-const sem::Vector* build_vec2(MatchState& state, const sem::Type* T) {
-    return build_vec(state, Number(2), T);
+template <uint32_t N>
+const sem::Vector* build_vec(MatchState& state, const sem::Type* el) {
+    return state.builder.create<sem::Vector>(el, N);
 }
 
-bool match_vec3(const sem::Type* ty, const sem::Type*& T) {
-    return match_vec<3>(ty, T);
-}
+constexpr auto match_vec2 = match_vec<2>;
+constexpr auto match_vec3 = match_vec<3>;
+constexpr auto match_vec4 = match_vec<4>;
 
-const sem::Vector* build_vec3(MatchState& state, const sem::Type* T) {
-    return build_vec(state, Number(3), T);
-}
-
-bool match_vec4(const sem::Type* ty, const sem::Type*& T) {
-    return match_vec<4>(ty, T);
-}
-
-const sem::Vector* build_vec4(MatchState& state, const sem::Type* T) {
-    return build_vec(state, Number(4), T);
-}
+constexpr auto build_vec2 = build_vec<2>;
+constexpr auto build_vec3 = build_vec<3>;
+constexpr auto build_vec4 = build_vec<4>;
 
 bool match_mat(const sem::Type* ty, Number& M, Number& N, const sem::Type*& T) {
     if (ty->Is<Any>()) {
@@ -399,11 +429,52 @@
     return false;
 }
 
-const sem::Matrix* build_mat(MatchState& state, Number N, Number M, const sem::Type* T) {
-    auto* column_type = state.builder.create<sem::Vector>(T, M.Value());
-    return state.builder.create<sem::Matrix>(column_type, N.Value());
+template <uint32_t C, uint32_t R>
+bool match_mat(const sem::Type* ty, const sem::Type*& T) {
+    if (ty->Is<Any>()) {
+        T = ty;
+        return true;
+    }
+    if (auto* m = ty->As<sem::Matrix>()) {
+        if (m->columns() == C && m->rows() == R) {
+            T = m->type();
+            return true;
+        }
+    }
+    return false;
 }
 
+const sem::Matrix* build_mat(MatchState& state, Number C, Number R, const sem::Type* T) {
+    auto* column_type = state.builder.create<sem::Vector>(T, R.Value());
+    return state.builder.create<sem::Matrix>(column_type, C.Value());
+}
+
+template <uint32_t C, uint32_t R>
+const sem::Matrix* build_mat(MatchState& state, const sem::Type* T) {
+    auto* column_type = state.builder.create<sem::Vector>(T, R);
+    return state.builder.create<sem::Matrix>(column_type, C);
+}
+
+constexpr auto build_mat2x2 = build_mat<2, 2>;
+constexpr auto build_mat2x3 = build_mat<2, 3>;
+constexpr auto build_mat2x4 = build_mat<2, 4>;
+constexpr auto build_mat3x2 = build_mat<3, 2>;
+constexpr auto build_mat3x3 = build_mat<3, 3>;
+constexpr auto build_mat3x4 = build_mat<3, 4>;
+constexpr auto build_mat4x2 = build_mat<4, 2>;
+constexpr auto build_mat4x3 = build_mat<4, 3>;
+constexpr auto build_mat4x4 = build_mat<4, 4>;
+
+constexpr auto match_mat2x2 = match_mat<2, 2>;
+constexpr auto match_mat2x3 = match_mat<2, 3>;
+constexpr auto match_mat2x4 = match_mat<2, 4>;
+constexpr auto match_mat3x2 = match_mat<3, 2>;
+constexpr auto match_mat3x3 = match_mat<3, 3>;
+constexpr auto match_mat3x4 = match_mat<3, 4>;
+constexpr auto match_mat4x2 = match_mat<4, 2>;
+constexpr auto match_mat4x3 = match_mat<4, 3>;
+constexpr auto match_mat4x4 = match_mat<4, 4>;
+
 bool match_array(const sem::Type* ty, const sem::Type*& T) {
     if (ty->Is<Any>()) {
         T = ty;
@@ -720,18 +791,18 @@
     MatcherIndex const* const matcher_indices;
 };
 
-/// OpenTypeInfo describes an open type
-struct OpenTypeInfo {
-    /// Name of the open type (e.g. 'T')
+/// TemplateTypeInfo describes an template type
+struct TemplateTypeInfo {
+    /// Name of the template type (e.g. 'T')
     const char* name;
     /// Optional type matcher constraint.
     /// Either an index in Matchers::type, or kNoMatcher
     const MatcherIndex matcher_index;
 };
 
-/// OpenNumberInfo describes an open number
-struct OpenNumberInfo {
-    /// Name of the open number (e.g. 'N')
+/// TemplateNumberInfo describes a template number
+struct TemplateNumberInfo {
+    /// Name of the template number (e.g. 'N')
     const char* name;
     /// Optional number matcher constraint.
     /// Either an index in Matchers::number, or kNoMatcher
@@ -742,24 +813,22 @@
 struct OverloadInfo {
     /// Total number of parameters for the overload
     const uint8_t num_parameters;
-    /// Total number of open types for the overload
-    const uint8_t num_open_types;
-    /// Total number of open numbers for the overload
-    const uint8_t num_open_numbers;
-    /// Pointer to the first open type
-    OpenTypeInfo const* const open_types;
-    /// Pointer to the first open number
-    OpenNumberInfo const* const open_numbers;
+    /// Total number of template types for the overload
+    const uint8_t num_template_types;
+    /// Total number of template numbers for the overload
+    const uint8_t num_template_numbers;
+    /// Pointer to the first template type
+    TemplateTypeInfo const* const template_types;
+    /// Pointer to the first template number
+    TemplateNumberInfo const* const template_numbers;
     /// Pointer to the first parameter
     ParameterInfo const* const parameters;
     /// Pointer to a list of matcher indices that index on Matchers::type and
     /// Matchers::number, used to build the return type. If the function has no
     /// return type then this is null
     MatcherIndex const* const return_matcher_indices;
-    /// The pipeline stages that this overload can be used in
-    PipelineStageSet supported_stages;
-    /// True if the overload is marked as deprecated
-    bool is_deprecated;
+    /// The flags for the overload
+    OverloadFlags flags;
 };
 
 /// IntrinsicInfo describes a builtin function or operator overload
@@ -791,21 +860,18 @@
             for (auto& p : i.parameters) {
                 utils::HashCombine(&hash, p.type, p.usage);
             }
-            return utils::Hash(hash, i.index, i.return_type, i.supported_stages, i.is_deprecated);
+            return utils::Hash(hash, i.overload, i.return_type);
         }
     };
 
-    uint32_t index = 0;  // Index of the intrinsic (builtin or operator)
-    std::vector<Parameter> parameters;
+    const OverloadInfo* overload = nullptr;
     sem::Type const* return_type = nullptr;
-    PipelineStageSet supported_stages;
-    bool is_deprecated = false;
+    std::vector<Parameter> parameters;
 };
 
 /// Equality operator for IntrinsicPrototype
 bool operator==(const IntrinsicPrototype& a, const IntrinsicPrototype& b) {
-    if (a.index != b.index || a.supported_stages != b.supported_stages ||
-        a.return_type != b.return_type || a.is_deprecated != b.is_deprecated ||
+    if (a.overload != b.overload || a.return_type != b.return_type ||
         a.parameters.size() != b.parameters.size()) {
         return false;
     }
@@ -836,38 +902,108 @@
                           const Source& source,
                           bool is_compound) override;
 
+    const sem::CallTarget* Lookup(CtorConvIntrinsic type,
+                                  const sem::Type* template_arg,
+                                  const std::vector<const sem::Type*>& args,
+                                  const Source& source) override;
+
   private:
-    // Candidate holds information about a mismatched overload that could be what the user intended
-    // to call.
+    /// Candidate holds information about an overload evaluated for resolution.
     struct Candidate {
+        /// The candidate overload
         const OverloadInfo* overload;
-        int score;
+        /// The template types and numbers
+        TemplateState templates;
+        /// The parameter types for the candidate overload
+        std::vector<IntrinsicPrototype::Parameter> parameters;
+        /// The match-score of the candidate overload.
+        /// A score of zero indicates an exact match.
+        /// Non-zero scores are used for diagnostics when no overload matches.
+        /// Lower scores are displayed first (top-most).
+        size_t score;
     };
 
-    const IntrinsicPrototype Match(const char* intrinsic_name,
-                                   uint32_t intrinsic_index,
-                                   const OverloadInfo& overload,
-                                   const std::vector<const sem::Type*>& args,
-                                   int& match_score);
+    /// A list of candidates
+    using Candidates = std::vector<Candidate>;
 
-    MatchState Match(ClosedState& closed,
-                     const OverloadInfo& overload,
+    /// Callback function when no overloads match.
+    using OnNoMatch = std::function<void(Candidates)>;
+
+    /// Attempts to find a single intrinsic overload that matches the provided argument types.
+    /// @param intrinsic the intrinsic being called
+    /// @param intrinsic_name the name of the intrinsic
+    /// @param args the argument types
+    /// @param templates initial template state. This may contain explicitly specified template
+    ///                  arguments. For example `vec3<f32>()` would have the first template-type
+    ///                  defined as `f32`.
+    /// @param on_no_match an error callback when no intrinsic overloads matched the provided
+    ///                    arguments.
+    /// @returns the matched intrinsic. If no intrinsic could be matched then IntrinsicPrototype
+    ///          will hold nullptrs for IntrinsicPrototype::overload and
+    ///          IntrinsicPrototype::return_type.
+    IntrinsicPrototype MatchIntrinsic(const IntrinsicInfo& intrinsic,
+                                      const char* intrinsic_name,
+                                      const std::vector<const sem::Type*>& args,
+                                      TemplateState templates,
+                                      OnNoMatch on_no_match) const;
+
+    /// Evaluates the overload for the provided argument types.
+    /// @param overload the overload being considered
+    /// @param args the argument types
+    /// @param templates initial template state. This may contain explicitly specified template
+    ///                  arguments. For example `vec3<f32>()` would have the first template-type
+    ///                  template as `f32`.
+    /// @returns the evaluated Candidate information.
+    Candidate ScoreOverload(const OverloadInfo* overload,
+                            const std::vector<const sem::Type*>& args,
+                            TemplateState templates) const;
+
+    /// Match constructs a new MatchState
+    /// @param templates the template state used for matcher evaluation
+    /// @param overload the overload being evaluated
+    /// @param matcher_indices pointer to a list of matcher indices
+    MatchState Match(TemplateState& templates,
+                     const OverloadInfo* overload,
                      MatcherIndex const* matcher_indices) const;
 
-    void PrintOverload(std::ostream& ss, const OverloadInfo& overload, const char* name) const;
+    // Prints the overload for emitting diagnostics
+    void PrintOverload(std::ostream& ss,
+                       const OverloadInfo* overload,
+                       const char* intrinsic_name) const;
+
+    // Prints the list of candidates for emitting diagnostics
+    void PrintCandidates(std::ostream& ss,
+                         const Candidates& candidates,
+                         const char* intrinsic_name) const;
+
+    /// Raises an ICE when multiple overload candidates match, as this should never happen.
+    void ErrMultipleOverloadsMatched(size_t num_matched,
+                                     const char* intrinsic_name,
+                                     const std::vector<const sem::Type*>& args,
+                                     TemplateState templates,
+                                     Candidates candidates) const;
 
     ProgramBuilder& builder;
     Matchers matchers;
     std::unordered_map<IntrinsicPrototype, sem::Builtin*, IntrinsicPrototype::Hasher> builtins;
+    std::unordered_map<IntrinsicPrototype, sem::TypeConstructor*, IntrinsicPrototype::Hasher>
+        constructors;
+    std::unordered_map<IntrinsicPrototype, sem::TypeConversion*, IntrinsicPrototype::Hasher>
+        converters;
 };
 
 /// @return a string representing a call to a builtin with the given argument
 /// types.
 std::string CallSignature(ProgramBuilder& builder,
                           const char* intrinsic_name,
-                          const std::vector<const sem::Type*>& args) {
+                          const std::vector<const sem::Type*>& args,
+                          const sem::Type* template_arg = nullptr) {
     std::stringstream ss;
-    ss << intrinsic_name << "(";
+    ss << intrinsic_name;
+    if (template_arg) {
+        ss << "<" << template_arg->FriendlyName(builder.Symbols()) << ">";
+    }
+    ss << "(";
     {
         bool first = true;
         for (auto* arg : args) {
@@ -883,12 +1019,12 @@
     return ss.str();
 }
 
-std::string OpenTypeMatcher::String(MatchState& state) const {
-    return state.overload.open_types[index_].name;
+std::string TemplateTypeMatcher::String(MatchState* state) const {
+    return state->overload->template_types[index_].name;
 }
 
-std::string OpenNumberMatcher::String(MatchState& state) const {
-    return state.overload.open_numbers[index_].name;
+std::string TemplateNumberMatcher::String(MatchState* state) const {
+    return state->overload->template_numbers[index_].name;
 }
 
 Impl::Impl(ProgramBuilder& b) : builder(b) {}
@@ -896,110 +1032,90 @@
 const sem::Builtin* Impl::Lookup(sem::BuiltinType builtin_type,
                                  const std::vector<const sem::Type*>& args,
                                  const Source& source) {
-    // The list of failed matches that had promise.
-    std::vector<Candidate> candidates;
-
-    uint32_t intrinsic_index = static_cast<uint32_t>(builtin_type);
     const char* intrinsic_name = sem::str(builtin_type);
-    auto& builtin = kBuiltins[intrinsic_index];
-    for (uint32_t o = 0; o < builtin.num_overloads; o++) {
-        int match_score = 1000;
-        auto& overload = builtin.overloads[o];
-        auto match = Match(intrinsic_name, intrinsic_index, overload, args, match_score);
-        if (match.return_type) {
-            // De-duplicate builtins that are identical.
-            return utils::GetOrCreate(builtins, match, [&] {
-                std::vector<sem::Parameter*> params;
-                params.reserve(match.parameters.size());
-                for (auto& p : match.parameters) {
-                    params.emplace_back(builder.create<sem::Parameter>(
-                        nullptr, static_cast<uint32_t>(params.size()), p.type,
-                        ast::StorageClass::kNone, ast::Access::kUndefined, p.usage));
-                }
-                return builder.create<sem::Builtin>(builtin_type, match.return_type,
-                                                    std::move(params), match.supported_stages,
-                                                    match.is_deprecated);
-            });
+
+    // Generates an error when no overloads match the provided arguments
+    auto on_no_match = [&](Candidates candidates) {
+        std::stringstream ss;
+        ss << "no matching call to " << CallSignature(builder, intrinsic_name, args) << std::endl;
+        if (!candidates.empty()) {
+            ss << std::endl
+               << candidates.size() << " candidate function" << (candidates.size() > 1 ? "s:" : ":")
+               << std::endl;
+            PrintCandidates(ss, candidates, intrinsic_name);
         }
-        if (match_score > 0) {
-            candidates.emplace_back(Candidate{&overload, match_score});
-        }
+        builder.Diagnostics().add_error(diag::System::Resolver, ss.str(), source);
+    };
+
+    // Resolve the intrinsic overload
+    auto match = MatchIntrinsic(kBuiltins[static_cast<size_t>(builtin_type)], intrinsic_name, args,
+                                TemplateState{}, on_no_match);
+    if (!match.overload) {
+        return {};
     }
 
-    // Sort the candidates with the most promising first
-    std::stable_sort(candidates.begin(), candidates.end(),
-                     [](const Candidate& a, const Candidate& b) { return a.score > b.score; });
-
-    // Generate an error message
-    std::stringstream ss;
-    ss << "no matching call to " << CallSignature(builder, intrinsic_name, args) << std::endl;
-    if (!candidates.empty()) {
-        ss << std::endl;
-        ss << candidates.size() << " candidate function" << (candidates.size() > 1 ? "s:" : ":")
-           << std::endl;
-        for (auto& candidate : candidates) {
-            ss << "  ";
-            PrintOverload(ss, *candidate.overload, intrinsic_name);
-            ss << std::endl;
+    // De-duplicate builtins that are identical.
+    return utils::GetOrCreate(builtins, match, [&] {
+        std::vector<sem::Parameter*> params;
+        params.reserve(match.parameters.size());
+        for (auto& p : match.parameters) {
+            params.emplace_back(builder.create<sem::Parameter>(
+                nullptr, static_cast<uint32_t>(params.size()), p.type, ast::StorageClass::kNone,
+                ast::Access::kUndefined, p.usage));
         }
-    }
-    builder.Diagnostics().add_error(diag::System::Resolver, ss.str(), source);
-    return nullptr;
+        sem::PipelineStageSet supported_stages;
+        if (match.overload->flags.Contains(OverloadFlag::kSupportsVertexPipeline)) {
+            supported_stages.Add(ast::PipelineStage::kVertex);
+        }
+        if (match.overload->flags.Contains(OverloadFlag::kSupportsFragmentPipeline)) {
+            supported_stages.Add(ast::PipelineStage::kFragment);
+        }
+        if (match.overload->flags.Contains(OverloadFlag::kSupportsComputePipeline)) {
+            supported_stages.Add(ast::PipelineStage::kCompute);
+        }
+        return builder.create<sem::Builtin>(
+            builtin_type, match.return_type, std::move(params), supported_stages,
+            match.overload->flags.Contains(OverloadFlag::kIsDeprecated));
+    });
 }
 
 IntrinsicTable::UnaryOperator Impl::Lookup(ast::UnaryOp op,
                                            const sem::Type* arg,
                                            const Source& source) {
-    // The list of failed matches that had promise.
-    std::vector<Candidate> candidates;
-
-    auto [intrinsic_index, intrinsic_name] = [&]() -> std::pair<uint32_t, const char*> {
+    auto [intrinsic_index, intrinsic_name] = [&]() -> std::pair<size_t, const char*> {
         switch (op) {
             case ast::UnaryOp::kComplement:
-                return {kOperatorComplement, "operator ~ "};
+                return {kUnaryOperatorComplement, "operator ~ "};
             case ast::UnaryOp::kNegation:
-                return {kOperatorMinus, "operator - "};
+                return {kUnaryOperatorMinus, "operator - "};
             case ast::UnaryOp::kNot:
-                return {kOperatorNot, "operator ! "};
+                return {kUnaryOperatorNot, "operator ! "};
             default:
                 return {0, "<unknown>"};
         }
     }();
 
-    auto& builtin = kOperators[intrinsic_index];
-    for (uint32_t o = 0; o < builtin.num_overloads; o++) {
-        int match_score = 1000;
-        auto& overload = builtin.overloads[o];
-        if (overload.num_parameters == 1) {
-            auto match = Match(intrinsic_name, intrinsic_index, overload, {arg}, match_score);
-            if (match.return_type) {
-                return UnaryOperator{match.return_type, match.parameters[0].type};
-            }
-            if (match_score > 0) {
-                candidates.emplace_back(Candidate{&overload, match_score});
-            }
+    // Generates an error when no overloads match the provided arguments
+    auto on_no_match = [&, name = intrinsic_name](Candidates candidates) {
+        std::stringstream ss;
+        ss << "no matching overload for " << CallSignature(builder, name, {arg}) << std::endl;
+        if (!candidates.empty()) {
+            ss << std::endl
+               << candidates.size() << " candidate operator" << (candidates.size() > 1 ? "s:" : ":")
+               << std::endl;
+            PrintCandidates(ss, candidates, name);
         }
+        builder.Diagnostics().add_error(diag::System::Resolver, ss.str(), source);
+    };
+
+    // Resolve the intrinsic overload
+    auto match = MatchIntrinsic(kUnaryOperators[intrinsic_index], intrinsic_name, {arg},
+                                TemplateState{}, on_no_match);
+    if (!match.overload) {
+        return {};
     }
 
-    // Sort the candidates with the most promising first
-    std::stable_sort(candidates.begin(), candidates.end(),
-                     [](const Candidate& a, const Candidate& b) { return a.score > b.score; });
-
-    // Generate an error message
-    std::stringstream ss;
-    ss << "no matching overload for " << CallSignature(builder, intrinsic_name, {arg}) << std::endl;
-    if (!candidates.empty()) {
-        ss << std::endl;
-        ss << candidates.size() << " candidate operator" << (candidates.size() > 1 ? "s:" : ":")
-           << std::endl;
-        for (auto& candidate : candidates) {
-            ss << "  ";
-            PrintOverload(ss, *candidate.overload, intrinsic_name);
-            ss << std::endl;
-        }
-    }
-    builder.Diagnostics().add_error(diag::System::Resolver, ss.str(), source);
-    return {};
+    return UnaryOperator{match.return_type, match.parameters[0].type};
 }
 
 IntrinsicTable::BinaryOperator Impl::Lookup(ast::BinaryOp op,
@@ -1007,200 +1123,305 @@
                                             const sem::Type* rhs,
                                             const Source& source,
                                             bool is_compound) {
-    // The list of failed matches that had promise.
-    std::vector<Candidate> candidates;
-
-    auto [intrinsic_index, intrinsic_name] = [&]() -> std::pair<uint32_t, const char*> {
+    auto [intrinsic_index, intrinsic_name] = [&]() -> std::pair<size_t, const char*> {
         switch (op) {
             case ast::BinaryOp::kAnd:
-                return {kOperatorAnd, is_compound ? "operator &= " : "operator & "};
+                return {kBinaryOperatorAnd, is_compound ? "operator &= " : "operator & "};
             case ast::BinaryOp::kOr:
-                return {kOperatorOr, is_compound ? "operator |= " : "operator | "};
+                return {kBinaryOperatorOr, is_compound ? "operator |= " : "operator | "};
             case ast::BinaryOp::kXor:
-                return {kOperatorXor, is_compound ? "operator ^= " : "operator ^ "};
+                return {kBinaryOperatorXor, is_compound ? "operator ^= " : "operator ^ "};
             case ast::BinaryOp::kLogicalAnd:
-                return {kOperatorLogicalAnd, "operator && "};
+                return {kBinaryOperatorLogicalAnd, "operator && "};
             case ast::BinaryOp::kLogicalOr:
-                return {kOperatorLogicalOr, "operator || "};
+                return {kBinaryOperatorLogicalOr, "operator || "};
             case ast::BinaryOp::kEqual:
-                return {kOperatorEqual, "operator == "};
+                return {kBinaryOperatorEqual, "operator == "};
             case ast::BinaryOp::kNotEqual:
-                return {kOperatorNotEqual, "operator != "};
+                return {kBinaryOperatorNotEqual, "operator != "};
             case ast::BinaryOp::kLessThan:
-                return {kOperatorLessThan, "operator < "};
+                return {kBinaryOperatorLessThan, "operator < "};
             case ast::BinaryOp::kGreaterThan:
-                return {kOperatorGreaterThan, "operator > "};
+                return {kBinaryOperatorGreaterThan, "operator > "};
             case ast::BinaryOp::kLessThanEqual:
-                return {kOperatorLessThanEqual, "operator <= "};
+                return {kBinaryOperatorLessThanEqual, "operator <= "};
             case ast::BinaryOp::kGreaterThanEqual:
-                return {kOperatorGreaterThanEqual, "operator >= "};
+                return {kBinaryOperatorGreaterThanEqual, "operator >= "};
             case ast::BinaryOp::kShiftLeft:
-                return {kOperatorShiftLeft, is_compound ? "operator <<= " : "operator << "};
+                return {kBinaryOperatorShiftLeft, is_compound ? "operator <<= " : "operator << "};
             case ast::BinaryOp::kShiftRight:
-                return {kOperatorShiftRight, is_compound ? "operator >>= " : "operator >> "};
+                return {kBinaryOperatorShiftRight, is_compound ? "operator >>= " : "operator >> "};
             case ast::BinaryOp::kAdd:
-                return {kOperatorPlus, is_compound ? "operator += " : "operator + "};
+                return {kBinaryOperatorPlus, is_compound ? "operator += " : "operator + "};
             case ast::BinaryOp::kSubtract:
-                return {kOperatorMinus, is_compound ? "operator -= " : "operator - "};
+                return {kBinaryOperatorMinus, is_compound ? "operator -= " : "operator - "};
             case ast::BinaryOp::kMultiply:
-                return {kOperatorStar, is_compound ? "operator *= " : "operator * "};
+                return {kBinaryOperatorStar, is_compound ? "operator *= " : "operator * "};
             case ast::BinaryOp::kDivide:
-                return {kOperatorDivide, is_compound ? "operator /= " : "operator / "};
+                return {kBinaryOperatorDivide, is_compound ? "operator /= " : "operator / "};
             case ast::BinaryOp::kModulo:
-                return {kOperatorModulo, is_compound ? "operator %= " : "operator % "};
+                return {kBinaryOperatorModulo, is_compound ? "operator %= " : "operator % "};
             default:
                 return {0, "<unknown>"};
         }
     }();
 
-    auto& builtin = kOperators[intrinsic_index];
-    for (uint32_t o = 0; o < builtin.num_overloads; o++) {
-        int match_score = 1000;
-        auto& overload = builtin.overloads[o];
-        if (overload.num_parameters == 2) {
-            auto match = Match(intrinsic_name, intrinsic_index, overload, {lhs, rhs}, match_score);
-            if (match.return_type) {
-                return BinaryOperator{match.return_type, match.parameters[0].type,
-                                      match.parameters[1].type};
-            }
-            if (match_score > 0) {
-                candidates.emplace_back(Candidate{&overload, match_score});
+    // Generates an error when no overloads match the provided arguments
+    auto on_no_match = [&, name = intrinsic_name](Candidates candidates) {
+        std::stringstream ss;
+        ss << "no matching overload for " << CallSignature(builder, name, {lhs, rhs}) << std::endl;
+        if (!candidates.empty()) {
+            ss << std::endl
+               << candidates.size() << " candidate operator" << (candidates.size() > 1 ? "s:" : ":")
+               << std::endl;
+            PrintCandidates(ss, candidates, name);
+        }
+        builder.Diagnostics().add_error(diag::System::Resolver, ss.str(), source);
+    };
+
+    // Resolve the intrinsic overload
+    auto match = MatchIntrinsic(kBinaryOperators[intrinsic_index], intrinsic_name, {lhs, rhs},
+                                TemplateState{}, on_no_match);
+    if (!match.overload) {
+        return {};
+    }
+
+    return BinaryOperator{match.return_type, match.parameters[0].type, match.parameters[1].type};
+}
+
+const sem::CallTarget* Impl::Lookup(CtorConvIntrinsic type,
+                                    const sem::Type* template_arg,
+                                    const std::vector<const sem::Type*>& args,
+                                    const Source& source) {
+    auto name = str(type);
+
+    // Generates an error when no overloads match the provided arguments
+    auto on_no_match = [&](Candidates candidates) {
+        std::stringstream ss;
+        ss << "no matching constructor for " << CallSignature(builder, name, args, template_arg)
+           << std::endl;
+        Candidates ctor, conv;
+        for (auto candidate : candidates) {
+            if (candidate.overload->flags.Contains(OverloadFlag::kIsConstructor)) {
+                ctor.emplace_back(candidate);
+            } else {
+                conv.emplace_back(candidate);
             }
         }
+        if (!ctor.empty()) {
+            ss << std::endl
+               << ctor.size() << " candidate constructor" << (ctor.size() > 1 ? "s:" : ":")
+               << std::endl;
+            PrintCandidates(ss, ctor, name);
+        }
+        if (!conv.empty()) {
+            ss << std::endl
+               << conv.size() << " candidate conversion" << (conv.size() > 1 ? "s:" : ":")
+               << std::endl;
+            PrintCandidates(ss, conv, name);
+        }
+        builder.Diagnostics().add_error(diag::System::Resolver, ss.str(), source);
+    };
+
+    // If a template type was provided, then close the 0'th type with this.
+    TemplateState templates;
+    if (template_arg) {
+        templates.Type(0, template_arg);
+    }
+
+    // Resolve the intrinsic overload
+    auto match = MatchIntrinsic(kConstructorsAndConverters[static_cast<size_t>(type)], name, args,
+                                templates, on_no_match);
+    if (!match.overload) {
+        return {};
+    }
+
+    // Was this overload a constructor or conversion?
+    if (match.overload->flags.Contains(OverloadFlag::kIsConstructor)) {
+        sem::ParameterList params;
+        params.reserve(match.parameters.size());
+        for (auto& p : match.parameters) {
+            params.emplace_back(builder.create<sem::Parameter>(
+                nullptr, static_cast<uint32_t>(params.size()), p.type, ast::StorageClass::kNone,
+                ast::Access::kUndefined, p.usage));
+        }
+        return utils::GetOrCreate(constructors, match, [&]() {
+            return builder.create<sem::TypeConstructor>(match.return_type, std::move(params));
+        });
+    }
+
+    // Conversion.
+    return utils::GetOrCreate(converters, match, [&]() {
+        auto param = builder.create<sem::Parameter>(
+            nullptr, 0, match.parameters[0].type, ast::StorageClass::kNone, ast::Access::kUndefined,
+            match.parameters[0].usage);
+        return builder.create<sem::TypeConversion>(match.return_type, param);
+    });
+}
+
+IntrinsicPrototype Impl::MatchIntrinsic(const IntrinsicInfo& intrinsic,
+                                        const char* intrinsic_name,
+                                        const std::vector<const sem::Type*>& args,
+                                        TemplateState templates,
+                                        OnNoMatch on_no_match) const {
+    size_t num_matched = 0;
+    Candidates candidates;
+    candidates.reserve(intrinsic.num_overloads);
+    for (size_t overload_idx = 0; overload_idx < static_cast<size_t>(intrinsic.num_overloads);
+         overload_idx++) {
+        auto candidate = ScoreOverload(&intrinsic.overloads[overload_idx], args, templates);
+        if (candidate.score == 0) {
+            num_matched++;
+        }
+        candidates.emplace_back(std::move(candidate));
     }
 
     // Sort the candidates with the most promising first
     std::stable_sort(candidates.begin(), candidates.end(),
-                     [](const Candidate& a, const Candidate& b) { return a.score > b.score; });
+                     [&](const Candidate& a, const Candidate& b) { return a.score < b.score; });
 
-    // Generate an error message
-    std::stringstream ss;
-    ss << "no matching overload for " << CallSignature(builder, intrinsic_name, {lhs, rhs})
-       << std::endl;
-    if (!candidates.empty()) {
-        ss << std::endl;
-        ss << candidates.size() << " candidate operator" << (candidates.size() > 1 ? "s:" : ":")
-           << std::endl;
-        for (auto& candidate : candidates) {
-            ss << "  ";
-            PrintOverload(ss, *candidate.overload, intrinsic_name);
-            ss << std::endl;
-        }
-    }
-    builder.Diagnostics().add_error(diag::System::Resolver, ss.str(), source);
-    return {};
-}
-
-const IntrinsicPrototype Impl::Match(const char* intrinsic_name,
-                                     uint32_t intrinsic_index,
-                                     const OverloadInfo& overload,
-                                     const std::vector<const sem::Type*>& args,
-                                     int& match_score) {
-    // Score wait for argument <-> parameter count matches / mismatches
-    constexpr int kScorePerParamArgMismatch = -1;
-    constexpr int kScorePerMatchedParam = 2;
-    constexpr int kScorePerMatchedOpenType = 1;
-    constexpr int kScorePerMatchedOpenNumber = 1;
-
-    auto num_parameters = overload.num_parameters;
-    auto num_arguments = static_cast<decltype(num_parameters)>(args.size());
-
-    bool overload_matched = true;
-
-    if (num_parameters != num_arguments) {
-        match_score += kScorePerParamArgMismatch * (std::max(num_parameters, num_arguments) -
-                                                    std::min(num_parameters, num_arguments));
-        overload_matched = false;
+    // How many candidates matched?
+    switch (num_matched) {
+        case 0:
+            on_no_match(std::move(candidates));
+            return {};
+        case 1:
+            break;
+        default:
+            // Note: Currently the intrinsic table does not contain any overloads which may result
+            // in ambiguities, so here we call ErrMultipleOverloadsMatched() which will produce and
+            // ICE. If we end up in the situation where this is unavoidable, we'll need to perform
+            // further overload resolution as described in
+            // https://www.w3.org/TR/WGSL/#overload-resolution-section.
+            ErrMultipleOverloadsMatched(num_matched, intrinsic_name, args, templates, candidates);
     }
 
-    ClosedState closed(builder);
-
-    std::vector<IntrinsicPrototype::Parameter> parameters;
-
-    auto num_params = std::min(num_parameters, num_arguments);
-    for (uint32_t p = 0; p < num_params; p++) {
-        auto& parameter = overload.parameters[p];
-        auto* indices = parameter.matcher_indices;
-        auto* type = Match(closed, overload, indices).Type(args[p]->UnwrapRef());
-        if (type) {
-            parameters.emplace_back(IntrinsicPrototype::Parameter{type, parameter.usage});
-            match_score += kScorePerMatchedParam;
-        } else {
-            overload_matched = false;
-        }
-    }
-
-    if (overload_matched) {
-        // Check all constrained open types matched
-        for (uint32_t ot = 0; ot < overload.num_open_types; ot++) {
-            auto& open_type = overload.open_types[ot];
-            if (open_type.matcher_index != kNoMatcher) {
-                auto* index = &open_type.matcher_index;
-                if (Match(closed, overload, index).Type(closed.Type(ot))) {
-                    match_score += kScorePerMatchedOpenType;
-                } else {
-                    overload_matched = false;
-                }
-            }
-        }
-    }
-
-    if (overload_matched) {
-        // Check all constrained open numbers matched
-        for (uint32_t on = 0; on < overload.num_open_numbers; on++) {
-            auto& open_number = overload.open_numbers[on];
-            if (open_number.matcher_index != kNoMatcher) {
-                auto* index = &open_number.matcher_index;
-                if (Match(closed, overload, index).Num(closed.Num(on)).IsValid()) {
-                    match_score += kScorePerMatchedOpenNumber;
-                } else {
-                    overload_matched = false;
-                }
-            }
-        }
-    }
-
-    if (!overload_matched) {
-        return {};
-    }
+    auto match = candidates[0];
 
     // Build the return type
     const sem::Type* return_type = nullptr;
-    if (auto* indices = overload.return_matcher_indices) {
+    if (auto* indices = match.overload->return_matcher_indices) {
         Any any;
-        return_type = Match(closed, overload, indices).Type(&any);
+        return_type = Match(match.templates, match.overload, indices).Type(&any);
         if (!return_type) {
-            std::stringstream ss;
-            PrintOverload(ss, overload, intrinsic_name);
-            TINT_ICE(Resolver, builder.Diagnostics())
-                << "MatchState.Match() returned null for " << ss.str();
+            TINT_ICE(Resolver, builder.Diagnostics()) << "MatchState.Match() returned null";
             return {};
         }
     } else {
         return_type = builder.create<sem::Void>();
     }
 
-    IntrinsicPrototype builtin;
-    builtin.index = intrinsic_index;
-    builtin.return_type = return_type;
-    builtin.parameters = std::move(parameters);
-    builtin.supported_stages = overload.supported_stages;
-    builtin.is_deprecated = overload.is_deprecated;
-    return builtin;
+    return IntrinsicPrototype{match.overload, return_type, std::move(match.parameters)};
 }
 
-MatchState Impl::Match(ClosedState& closed,
-                       const OverloadInfo& overload,
+Impl::Candidate Impl::ScoreOverload(const OverloadInfo* overload,
+                                    const std::vector<const sem::Type*>& args,
+                                    TemplateState templates) const {
+    // Penalty weights for overload mismatching.
+    // This scoring is used to order the suggested overloads in diagnostic on overload mismatch, and
+    // has no impact for a correct program.
+    // The overloads with the lowest score will be displayed first (top-most).
+    constexpr int kMismatchedParamCountPenalty = 3;
+    constexpr int kMismatchedParamTypePenalty = 2;
+    constexpr int kMismatchedTemplateTypePenalty = 1;
+    constexpr int kMismatchedTemplateNumberPenalty = 1;
+
+    size_t num_parameters = static_cast<size_t>(overload->num_parameters);
+    size_t num_arguments = static_cast<size_t>(args.size());
+
+    size_t score = 0;
+
+    if (num_parameters != num_arguments) {
+        score += kMismatchedParamCountPenalty * (std::max(num_parameters, num_arguments) -
+                                                 std::min(num_parameters, num_arguments));
+    }
+
+    // Invoke the matchers for each parameter <-> argument pair.
+    // If any arguments cannot be matched, then `score` will be increased.
+    // If the overload has any template types or numbers then these will be set based on the
+    // argument types. Template types may be refined by constraining with later argument types. For
+    // example calling `F<T>(T, T)` with the argument types (abstract-int, i32) will first set T to
+    // abstract-int when matching the first argument, and then constrained down to i32 when matching
+    // the second argument.
+    // Note that inferred template types are not tested against their matchers at this point.
+    auto num_params = std::min(num_parameters, num_arguments);
+    for (size_t p = 0; p < num_params; p++) {
+        auto& parameter = overload->parameters[p];
+        auto* indices = parameter.matcher_indices;
+        if (!Match(templates, overload, indices).Type(args[p]->UnwrapRef())) {
+            score += kMismatchedParamTypePenalty;
+        }
+    }
+
+    if (score == 0) {
+        // Check all constrained template types matched their constraint matchers.
+        // If the template type *does not* match any of the types in the constraint matcher, then
+        // `score` is incremented. If the template type *does* match a type, then the template type
+        // is replaced with the first matching type. The order of types in the template matcher is
+        // important here, which can be controlled with the [[precedence(N)]] decorations on the
+        // types in intrinsics.def.
+        for (size_t ot = 0; ot < overload->num_template_types; ot++) {
+            auto* matcher_index = &overload->template_types[ot].matcher_index;
+            if (*matcher_index != kNoMatcher) {
+                if (auto* template_type = templates.Type(ot)) {
+                    if (auto* ty = Match(templates, overload, matcher_index).Type(template_type)) {
+                        // Template type matched one of the types in the template type's matcher.
+                        // Replace the template type with this type.
+                        templates.SetType(ot, ty);
+                        continue;
+                    }
+                }
+                score += kMismatchedTemplateTypePenalty;
+            }
+        }
+    }
+
+    if (score == 0) {
+        // Check all constrained open numbers matched.
+        // Unlike template types, numbers are not constrained, so we're just checking that the
+        // inferred number matches the constraints on the overload. Increments `score` if the
+        // template numbers do not match their constraint matchers.
+        for (size_t on = 0; on < overload->num_template_numbers; on++) {
+            auto* matcher_index = &overload->template_numbers[on].matcher_index;
+            if (*matcher_index != kNoMatcher) {
+                auto template_num = templates.Num(on);
+                if (!template_num.IsValid() ||
+                    !Match(templates, overload, matcher_index).Num(template_num).IsValid()) {
+                    score += kMismatchedTemplateNumberPenalty;
+                }
+            }
+        }
+    }
+
+    // Now that all the template types have been finalized, we can construct the parameters.
+    std::vector<IntrinsicPrototype::Parameter> parameters;
+    if (score == 0) {
+        parameters.reserve(num_params);
+        for (size_t p = 0; p < num_params; p++) {
+            auto& parameter = overload->parameters[p];
+            auto* indices = parameter.matcher_indices;
+            auto* ty = Match(templates, overload, indices).Type(args[p]->UnwrapRef());
+            parameters.emplace_back(IntrinsicPrototype::Parameter{ty, parameter.usage});
+        }
+    }
+
+    return Candidate{overload, templates, parameters, score};
+}
+
+MatchState Impl::Match(TemplateState& templates,
+                       const OverloadInfo* overload,
                        MatcherIndex const* matcher_indices) const {
-    return MatchState(builder, closed, matchers, overload, matcher_indices);
+    return MatchState(builder, templates, matchers, overload, matcher_indices);
 }
 
-void Impl::PrintOverload(std::ostream& ss, const OverloadInfo& overload, const char* name) const {
-    ClosedState closed(builder);
+void Impl::PrintOverload(std::ostream& ss,
+                         const OverloadInfo* overload,
+                         const char* intrinsic_name) const {
+    TemplateState templates;
 
-    ss << name << "(";
-    for (uint32_t p = 0; p < overload.num_parameters; p++) {
-        auto& parameter = overload.parameters[p];
+    ss << intrinsic_name << "(";
+    for (size_t p = 0; p < overload->num_parameters; p++) {
+        auto& parameter = overload->parameters[p];
         if (p > 0) {
             ss << ", ";
         }
@@ -1208,13 +1429,13 @@
             ss << sem::str(parameter.usage) << ": ";
         }
         auto* indices = parameter.matcher_indices;
-        ss << Match(closed, overload, indices).TypeName();
+        ss << Match(templates, overload, indices).TypeName();
     }
     ss << ")";
-    if (overload.return_matcher_indices) {
+    if (overload->return_matcher_indices) {
         ss << " -> ";
-        auto* indices = overload.return_matcher_indices;
-        ss << Match(closed, overload, indices).TypeName();
+        auto* indices = overload->return_matcher_indices;
+        ss << Match(templates, overload, indices).TypeName();
     }
 
     bool first = true;
@@ -1222,26 +1443,36 @@
         ss << (first ? "  where: " : ", ");
         first = false;
     };
-    for (uint32_t i = 0; i < overload.num_open_types; i++) {
-        auto& open_type = overload.open_types[i];
-        if (open_type.matcher_index != kNoMatcher) {
+    for (size_t i = 0; i < overload->num_template_types; i++) {
+        auto& template_type = overload->template_types[i];
+        if (template_type.matcher_index != kNoMatcher) {
             separator();
-            ss << open_type.name;
-            auto* index = &open_type.matcher_index;
-            ss << " is " << Match(closed, overload, index).TypeName();
+            ss << template_type.name;
+            auto* index = &template_type.matcher_index;
+            ss << " is " << Match(templates, overload, index).TypeName();
         }
     }
-    for (uint32_t i = 0; i < overload.num_open_numbers; i++) {
-        auto& open_number = overload.open_numbers[i];
-        if (open_number.matcher_index != kNoMatcher) {
+    for (size_t i = 0; i < overload->num_template_numbers; i++) {
+        auto& template_number = overload->template_numbers[i];
+        if (template_number.matcher_index != kNoMatcher) {
             separator();
-            ss << open_number.name;
-            auto* index = &open_number.matcher_index;
-            ss << " is " << Match(closed, overload, index).NumName();
+            ss << template_number.name;
+            auto* index = &template_number.matcher_index;
+            ss << " is " << Match(templates, overload, index).NumName();
         }
     }
 }
 
+void Impl::PrintCandidates(std::ostream& ss,
+                           const Candidates& candidates,
+                           const char* intrinsic_name) const {
+    for (auto& candidate : candidates) {
+        ss << "  ";
+        PrintOverload(ss, candidate.overload, intrinsic_name);
+        ss << std::endl;
+    }
+}
+
 const sem::Type* MatchState::Type(const sem::Type* ty) {
     MatcherIndex matcher_index = *matcher_indices_++;
     auto* matcher = matchers.type[matcher_index];
@@ -1257,13 +1488,50 @@
 std::string MatchState::TypeName() {
     MatcherIndex matcher_index = *matcher_indices_++;
     auto* matcher = matchers.type[matcher_index];
-    return matcher->String(*this);
+    return matcher->String(this);
 }
 
 std::string MatchState::NumName() {
     MatcherIndex matcher_index = *matcher_indices_++;
     auto* matcher = matchers.number[matcher_index];
-    return matcher->String(*this);
+    return matcher->String(this);
+}
+
+void Impl::ErrMultipleOverloadsMatched(size_t num_matched,
+                                       const char* intrinsic_name,
+                                       const std::vector<const sem::Type*>& args,
+                                       TemplateState templates,
+                                       Candidates candidates) const {
+    std::stringstream ss;
+    ss << num_matched << " overloads matched " << intrinsic_name;
+    for (size_t i = 0; i < std::numeric_limits<size_t>::max(); i++) {
+        if (auto* ty = templates.Type(i)) {
+            ss << ((i == 0) ? "<" : ", ") << ty->FriendlyName(builder.Symbols());
+        } else {
+            if (i > 0) {
+                ss << ">";
+            }
+            break;
+        }
+    }
+    ss << "(";
+    bool first = true;
+    for (auto* arg : args) {
+        if (!first) {
+            ss << ", ";
+        }
+        first = false;
+        ss << arg->FriendlyName(builder.Symbols());
+    }
+    ss << "):\n";
+    for (auto& candidate : candidates) {
+        if (candidate.score == 0) {
+            ss << "  ";
+            PrintOverload(ss, candidate.overload, intrinsic_name);
+            ss << std::endl;
+        }
+    }
+    TINT_ICE(Resolver, builder.Diagnostics()) << ss.str();
 }
 
 }  // namespace
@@ -1274,7 +1542,7 @@
 
 IntrinsicTable::~IntrinsicTable() = default;
 
-/// TypeInfo for the Any type declared in the anonymous namespace above
-TINT_INSTANTIATE_TYPEINFO(Any);
+}  // namespace tint::resolver
 
-}  // namespace tint
+/// TypeInfo for the Any type declared in the anonymous namespace above
+TINT_INSTANTIATE_TYPEINFO(tint::resolver::Any);
diff --git a/src/tint/resolver/intrinsic_table.h b/src/tint/resolver/intrinsic_table.h
index e873202..5a8985f 100644
--- a/src/tint/resolver/intrinsic_table.h
+++ b/src/tint/resolver/intrinsic_table.h
@@ -19,6 +19,7 @@
 #include <string>
 #include <vector>
 
+#include "src/tint/resolver/ctor_conv_intrinsic.h"
 #include "src/tint/sem/builtin.h"
 
 // Forward declarations
@@ -26,7 +27,7 @@
 class ProgramBuilder;
 }  // namespace tint
 
-namespace tint {
+namespace tint::resolver {
 
 /// IntrinsicTable is a lookup table of all the WGSL builtin functions and intrinsic operators
 class IntrinsicTable {
@@ -89,8 +90,20 @@
                                   const sem::Type* rhs,
                                   const Source& source,
                                   bool is_compound) = 0;
+
+    /// Lookup looks for the type constructor or conversion overload for the given
+    /// CtorConvIntrinsic.
+    /// @param type the type being constructed or converted
+    /// @param template_arg the optional template argument
+    /// @param args the argument types passed to the constructor / conversion call
+    /// @param source the source of the call
+    /// @return a sem::TypeConstructor, sem::TypeConversion or nullptr if nothing matched
+    virtual const sem::CallTarget* Lookup(CtorConvIntrinsic type,
+                                          const sem::Type* template_arg,
+                                          const std::vector<const sem::Type*>& args,
+                                          const Source& source) = 0;
 };
 
-}  // namespace tint
+}  // namespace tint::resolver
 
 #endif  // SRC_TINT_RESOLVER_INTRINSIC_TABLE_H_
diff --git a/src/tint/resolver/intrinsic_table.inl b/src/tint/resolver/intrinsic_table.inl
index 9981bb8..c518e58 100644
--- a/src/tint/resolver/intrinsic_table.inl
+++ b/src/tint/resolver/intrinsic_table.inl
@@ -25,11 +25,11 @@
 // clang-format off
 
 /// TypeMatcher for 'type bool'
-/// @see src/tint/intrinsics.def:68:6
+/// @see src/tint/intrinsics.def:73:6
 class Bool : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -37,7 +37,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Bool::Match(MatchState& state, const sem::Type* ty) const {
@@ -47,16 +47,16 @@
   return build_bool(state);
 }
 
-std::string Bool::String(MatchState&) const {
+std::string Bool::String(MatchState*) const {
   return "bool";
 }
 
-/// TypeMatcher for 'type f32'
-/// @see src/tint/intrinsics.def:69:6
-class F32 : public TypeMatcher {
+/// TypeMatcher for 'type af'
+/// @see src/tint/intrinsics.def:74:51
+class Af : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -64,26 +64,57 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
-const sem::Type* F32::Match(MatchState& state, const sem::Type* ty) const {
-  if (!match_f32(ty)) {
+const sem::Type* Af::Match(MatchState& state, const sem::Type* ty) const {
+  if (!match_af(ty)) {
     return nullptr;
   }
-  return build_f32(state);
+  return build_af(state);
 }
 
-std::string F32::String(MatchState&) const {
-  return "f32";
+std::string Af::String(MatchState*) const {
+  std::stringstream ss;
+  ss << "abstract-float";
+  return ss.str();
+}
+
+/// TypeMatcher for 'type ai'
+/// @see src/tint/intrinsics.def:75:51
+class Ai : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
+};
+
+const sem::Type* Ai::Match(MatchState& state, const sem::Type* ty) const {
+  if (!match_ai(ty)) {
+    return nullptr;
+  }
+  return build_ai(state);
+}
+
+std::string Ai::String(MatchState*) const {
+  std::stringstream ss;
+  ss << "abstract-int";
+  return ss.str();
 }
 
 /// TypeMatcher for 'type i32'
-/// @see src/tint/intrinsics.def:70:6
+/// @see src/tint/intrinsics.def:76:24
 class I32 : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -91,7 +122,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* I32::Match(MatchState& state, const sem::Type* ty) const {
@@ -101,16 +132,16 @@
   return build_i32(state);
 }
 
-std::string I32::String(MatchState&) const {
+std::string I32::String(MatchState*) const {
   return "i32";
 }
 
 /// TypeMatcher for 'type u32'
-/// @see src/tint/intrinsics.def:71:6
+/// @see src/tint/intrinsics.def:77:24
 class U32 : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -118,7 +149,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* U32::Match(MatchState& state, const sem::Type* ty) const {
@@ -128,16 +159,16 @@
   return build_u32(state);
 }
 
-std::string U32::String(MatchState&) const {
+std::string U32::String(MatchState*) const {
   return "u32";
 }
 
-/// TypeMatcher for 'type vec2'
-/// @see src/tint/intrinsics.def:72:6
-class Vec2 : public TypeMatcher {
+/// TypeMatcher for 'type f32'
+/// @see src/tint/intrinsics.def:78:24
+class F32 : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -145,7 +176,34 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
+};
+
+const sem::Type* F32::Match(MatchState& state, const sem::Type* ty) const {
+  if (!match_f32(ty)) {
+    return nullptr;
+  }
+  return build_f32(state);
+}
+
+std::string F32::String(MatchState*) const {
+  return "f32";
+}
+
+/// TypeMatcher for 'type vec2'
+/// @see src/tint/intrinsics.def:79:6
+class Vec2 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Vec2::Match(MatchState& state, const sem::Type* ty) const {
@@ -160,17 +218,17 @@
   return build_vec2(state, T);
 }
 
-std::string Vec2::String(MatchState& state) const {
-  const std::string T = state.TypeName();
+std::string Vec2::String(MatchState* state) const {
+  const std::string T = state->TypeName();
   return "vec2<" + T + ">";
 }
 
 /// TypeMatcher for 'type vec3'
-/// @see src/tint/intrinsics.def:73:6
+/// @see src/tint/intrinsics.def:80:6
 class Vec3 : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -178,7 +236,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Vec3::Match(MatchState& state, const sem::Type* ty) const {
@@ -193,17 +251,17 @@
   return build_vec3(state, T);
 }
 
-std::string Vec3::String(MatchState& state) const {
-  const std::string T = state.TypeName();
+std::string Vec3::String(MatchState* state) const {
+  const std::string T = state->TypeName();
   return "vec3<" + T + ">";
 }
 
 /// TypeMatcher for 'type vec4'
-/// @see src/tint/intrinsics.def:74:6
+/// @see src/tint/intrinsics.def:81:6
 class Vec4 : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -211,7 +269,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Vec4::Match(MatchState& state, const sem::Type* ty) const {
@@ -226,17 +284,17 @@
   return build_vec4(state, T);
 }
 
-std::string Vec4::String(MatchState& state) const {
-  const std::string T = state.TypeName();
+std::string Vec4::String(MatchState* state) const {
+  const std::string T = state->TypeName();
   return "vec4<" + T + ">";
 }
 
-/// TypeMatcher for 'type vec'
-/// @see src/tint/intrinsics.def:75:37
-class Vec : public TypeMatcher {
+/// TypeMatcher for 'type mat2x2'
+/// @see src/tint/intrinsics.def:82:6
+class Mat2X2 : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -244,7 +302,304 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
+};
+
+const sem::Type* Mat2X2::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_mat2x2(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_mat2x2(state, T);
+}
+
+std::string Mat2X2::String(MatchState* state) const {
+  const std::string T = state->TypeName();
+  return "mat2x2<" + T + ">";
+}
+
+/// TypeMatcher for 'type mat2x3'
+/// @see src/tint/intrinsics.def:83:6
+class Mat2X3 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
+};
+
+const sem::Type* Mat2X3::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_mat2x3(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_mat2x3(state, T);
+}
+
+std::string Mat2X3::String(MatchState* state) const {
+  const std::string T = state->TypeName();
+  return "mat2x3<" + T + ">";
+}
+
+/// TypeMatcher for 'type mat2x4'
+/// @see src/tint/intrinsics.def:84:6
+class Mat2X4 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
+};
+
+const sem::Type* Mat2X4::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_mat2x4(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_mat2x4(state, T);
+}
+
+std::string Mat2X4::String(MatchState* state) const {
+  const std::string T = state->TypeName();
+  return "mat2x4<" + T + ">";
+}
+
+/// TypeMatcher for 'type mat3x2'
+/// @see src/tint/intrinsics.def:85:6
+class Mat3X2 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
+};
+
+const sem::Type* Mat3X2::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_mat3x2(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_mat3x2(state, T);
+}
+
+std::string Mat3X2::String(MatchState* state) const {
+  const std::string T = state->TypeName();
+  return "mat3x2<" + T + ">";
+}
+
+/// TypeMatcher for 'type mat3x3'
+/// @see src/tint/intrinsics.def:86:6
+class Mat3X3 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
+};
+
+const sem::Type* Mat3X3::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_mat3x3(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_mat3x3(state, T);
+}
+
+std::string Mat3X3::String(MatchState* state) const {
+  const std::string T = state->TypeName();
+  return "mat3x3<" + T + ">";
+}
+
+/// TypeMatcher for 'type mat3x4'
+/// @see src/tint/intrinsics.def:87:6
+class Mat3X4 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
+};
+
+const sem::Type* Mat3X4::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_mat3x4(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_mat3x4(state, T);
+}
+
+std::string Mat3X4::String(MatchState* state) const {
+  const std::string T = state->TypeName();
+  return "mat3x4<" + T + ">";
+}
+
+/// TypeMatcher for 'type mat4x2'
+/// @see src/tint/intrinsics.def:88:6
+class Mat4X2 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
+};
+
+const sem::Type* Mat4X2::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_mat4x2(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_mat4x2(state, T);
+}
+
+std::string Mat4X2::String(MatchState* state) const {
+  const std::string T = state->TypeName();
+  return "mat4x2<" + T + ">";
+}
+
+/// TypeMatcher for 'type mat4x3'
+/// @see src/tint/intrinsics.def:89:6
+class Mat4X3 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
+};
+
+const sem::Type* Mat4X3::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_mat4x3(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_mat4x3(state, T);
+}
+
+std::string Mat4X3::String(MatchState* state) const {
+  const std::string T = state->TypeName();
+  return "mat4x3<" + T + ">";
+}
+
+/// TypeMatcher for 'type mat4x4'
+/// @see src/tint/intrinsics.def:90:6
+class Mat4X4 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
+};
+
+const sem::Type* Mat4X4::Match(MatchState& state, const sem::Type* ty) const {
+  const sem::Type* T = nullptr;
+  if (!match_mat4x4(ty, T)) {
+    return nullptr;
+  }
+  T = state.Type(T);
+  if (T == nullptr) {
+    return nullptr;
+  }
+  return build_mat4x4(state, T);
+}
+
+std::string Mat4X4::String(MatchState* state) const {
+  const std::string T = state->TypeName();
+  return "mat4x4<" + T + ">";
+}
+
+/// TypeMatcher for 'type vec'
+/// @see src/tint/intrinsics.def:91:37
+class Vec : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Vec::Match(MatchState& state, const sem::Type* ty) const {
@@ -264,20 +619,20 @@
   return build_vec(state, N, T);
 }
 
-std::string Vec::String(MatchState& state) const {
-  const std::string N = state.NumName();
-  const std::string T = state.TypeName();
+std::string Vec::String(MatchState* state) const {
+  const std::string N = state->NumName();
+  const std::string T = state->TypeName();
   std::stringstream ss;
   ss << "vec" << N << "<" << T << ">";
   return ss.str();
 }
 
 /// TypeMatcher for 'type mat'
-/// @see src/tint/intrinsics.def:76:37
+/// @see src/tint/intrinsics.def:92:37
 class Mat : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -285,7 +640,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Mat::Match(MatchState& state, const sem::Type* ty) const {
@@ -310,21 +665,21 @@
   return build_mat(state, N, M, T);
 }
 
-std::string Mat::String(MatchState& state) const {
-  const std::string N = state.NumName();
-  const std::string M = state.NumName();
-  const std::string T = state.TypeName();
+std::string Mat::String(MatchState* state) const {
+  const std::string N = state->NumName();
+  const std::string M = state->NumName();
+  const std::string T = state->TypeName();
   std::stringstream ss;
   ss << "mat" << N << "x" << M << "<" << T << ">";
   return ss.str();
 }
 
 /// TypeMatcher for 'type ptr'
-/// @see src/tint/intrinsics.def:77:6
+/// @see src/tint/intrinsics.def:93:6
 class Ptr : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -332,7 +687,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Ptr::Match(MatchState& state, const sem::Type* ty) const {
@@ -357,19 +712,19 @@
   return build_ptr(state, S, T, A);
 }
 
-std::string Ptr::String(MatchState& state) const {
-  const std::string S = state.NumName();
-  const std::string T = state.TypeName();
-  const std::string A = state.NumName();
+std::string Ptr::String(MatchState* state) const {
+  const std::string S = state->NumName();
+  const std::string T = state->TypeName();
+  const std::string A = state->NumName();
   return "ptr<" + S + ", " + T + ", " + A + ">";
 }
 
 /// TypeMatcher for 'type atomic'
-/// @see src/tint/intrinsics.def:78:6
+/// @see src/tint/intrinsics.def:94:6
 class Atomic : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -377,7 +732,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Atomic::Match(MatchState& state, const sem::Type* ty) const {
@@ -392,17 +747,17 @@
   return build_atomic(state, T);
 }
 
-std::string Atomic::String(MatchState& state) const {
-  const std::string T = state.TypeName();
+std::string Atomic::String(MatchState* state) const {
+  const std::string T = state->TypeName();
   return "atomic<" + T + ">";
 }
 
 /// TypeMatcher for 'type array'
-/// @see src/tint/intrinsics.def:79:6
+/// @see src/tint/intrinsics.def:95:6
 class Array : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -410,7 +765,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Array::Match(MatchState& state, const sem::Type* ty) const {
@@ -425,17 +780,17 @@
   return build_array(state, T);
 }
 
-std::string Array::String(MatchState& state) const {
-  const std::string T = state.TypeName();
+std::string Array::String(MatchState* state) const {
+  const std::string T = state->TypeName();
   return "array<" + T + ">";
 }
 
 /// TypeMatcher for 'type sampler'
-/// @see src/tint/intrinsics.def:80:6
+/// @see src/tint/intrinsics.def:96:6
 class Sampler : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -443,7 +798,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Sampler::Match(MatchState& state, const sem::Type* ty) const {
@@ -453,16 +808,16 @@
   return build_sampler(state);
 }
 
-std::string Sampler::String(MatchState&) const {
+std::string Sampler::String(MatchState*) const {
   return "sampler";
 }
 
 /// TypeMatcher for 'type sampler_comparison'
-/// @see src/tint/intrinsics.def:81:6
+/// @see src/tint/intrinsics.def:97:6
 class SamplerComparison : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -470,7 +825,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* SamplerComparison::Match(MatchState& state, const sem::Type* ty) const {
@@ -480,16 +835,16 @@
   return build_sampler_comparison(state);
 }
 
-std::string SamplerComparison::String(MatchState&) const {
+std::string SamplerComparison::String(MatchState*) const {
   return "sampler_comparison";
 }
 
 /// TypeMatcher for 'type texture_1d'
-/// @see src/tint/intrinsics.def:82:6
+/// @see src/tint/intrinsics.def:98:6
 class Texture1D : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -497,7 +852,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Texture1D::Match(MatchState& state, const sem::Type* ty) const {
@@ -512,17 +867,17 @@
   return build_texture_1d(state, T);
 }
 
-std::string Texture1D::String(MatchState& state) const {
-  const std::string T = state.TypeName();
+std::string Texture1D::String(MatchState* state) const {
+  const std::string T = state->TypeName();
   return "texture_1d<" + T + ">";
 }
 
 /// TypeMatcher for 'type texture_2d'
-/// @see src/tint/intrinsics.def:83:6
+/// @see src/tint/intrinsics.def:99:6
 class Texture2D : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -530,7 +885,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Texture2D::Match(MatchState& state, const sem::Type* ty) const {
@@ -545,17 +900,17 @@
   return build_texture_2d(state, T);
 }
 
-std::string Texture2D::String(MatchState& state) const {
-  const std::string T = state.TypeName();
+std::string Texture2D::String(MatchState* state) const {
+  const std::string T = state->TypeName();
   return "texture_2d<" + T + ">";
 }
 
 /// TypeMatcher for 'type texture_2d_array'
-/// @see src/tint/intrinsics.def:84:6
+/// @see src/tint/intrinsics.def:100:6
 class Texture2DArray : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -563,7 +918,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Texture2DArray::Match(MatchState& state, const sem::Type* ty) const {
@@ -578,17 +933,17 @@
   return build_texture_2d_array(state, T);
 }
 
-std::string Texture2DArray::String(MatchState& state) const {
-  const std::string T = state.TypeName();
+std::string Texture2DArray::String(MatchState* state) const {
+  const std::string T = state->TypeName();
   return "texture_2d_array<" + T + ">";
 }
 
 /// TypeMatcher for 'type texture_3d'
-/// @see src/tint/intrinsics.def:85:6
+/// @see src/tint/intrinsics.def:101:6
 class Texture3D : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -596,7 +951,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Texture3D::Match(MatchState& state, const sem::Type* ty) const {
@@ -611,17 +966,17 @@
   return build_texture_3d(state, T);
 }
 
-std::string Texture3D::String(MatchState& state) const {
-  const std::string T = state.TypeName();
+std::string Texture3D::String(MatchState* state) const {
+  const std::string T = state->TypeName();
   return "texture_3d<" + T + ">";
 }
 
 /// TypeMatcher for 'type texture_cube'
-/// @see src/tint/intrinsics.def:86:6
+/// @see src/tint/intrinsics.def:102:6
 class TextureCube : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -629,7 +984,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* TextureCube::Match(MatchState& state, const sem::Type* ty) const {
@@ -644,17 +999,17 @@
   return build_texture_cube(state, T);
 }
 
-std::string TextureCube::String(MatchState& state) const {
-  const std::string T = state.TypeName();
+std::string TextureCube::String(MatchState* state) const {
+  const std::string T = state->TypeName();
   return "texture_cube<" + T + ">";
 }
 
 /// TypeMatcher for 'type texture_cube_array'
-/// @see src/tint/intrinsics.def:87:6
+/// @see src/tint/intrinsics.def:103:6
 class TextureCubeArray : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -662,7 +1017,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* TextureCubeArray::Match(MatchState& state, const sem::Type* ty) const {
@@ -677,17 +1032,17 @@
   return build_texture_cube_array(state, T);
 }
 
-std::string TextureCubeArray::String(MatchState& state) const {
-  const std::string T = state.TypeName();
+std::string TextureCubeArray::String(MatchState* state) const {
+  const std::string T = state->TypeName();
   return "texture_cube_array<" + T + ">";
 }
 
 /// TypeMatcher for 'type texture_multisampled_2d'
-/// @see src/tint/intrinsics.def:88:6
+/// @see src/tint/intrinsics.def:104:6
 class TextureMultisampled2D : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -695,7 +1050,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* TextureMultisampled2D::Match(MatchState& state, const sem::Type* ty) const {
@@ -710,17 +1065,17 @@
   return build_texture_multisampled_2d(state, T);
 }
 
-std::string TextureMultisampled2D::String(MatchState& state) const {
-  const std::string T = state.TypeName();
+std::string TextureMultisampled2D::String(MatchState* state) const {
+  const std::string T = state->TypeName();
   return "texture_multisampled_2d<" + T + ">";
 }
 
 /// TypeMatcher for 'type texture_depth_2d'
-/// @see src/tint/intrinsics.def:89:6
+/// @see src/tint/intrinsics.def:105:6
 class TextureDepth2D : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -728,7 +1083,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* TextureDepth2D::Match(MatchState& state, const sem::Type* ty) const {
@@ -738,16 +1093,16 @@
   return build_texture_depth_2d(state);
 }
 
-std::string TextureDepth2D::String(MatchState&) const {
+std::string TextureDepth2D::String(MatchState*) const {
   return "texture_depth_2d";
 }
 
 /// TypeMatcher for 'type texture_depth_2d_array'
-/// @see src/tint/intrinsics.def:90:6
+/// @see src/tint/intrinsics.def:106:6
 class TextureDepth2DArray : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -755,7 +1110,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* TextureDepth2DArray::Match(MatchState& state, const sem::Type* ty) const {
@@ -765,16 +1120,16 @@
   return build_texture_depth_2d_array(state);
 }
 
-std::string TextureDepth2DArray::String(MatchState&) const {
+std::string TextureDepth2DArray::String(MatchState*) const {
   return "texture_depth_2d_array";
 }
 
 /// TypeMatcher for 'type texture_depth_cube'
-/// @see src/tint/intrinsics.def:91:6
+/// @see src/tint/intrinsics.def:107:6
 class TextureDepthCube : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -782,7 +1137,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* TextureDepthCube::Match(MatchState& state, const sem::Type* ty) const {
@@ -792,16 +1147,16 @@
   return build_texture_depth_cube(state);
 }
 
-std::string TextureDepthCube::String(MatchState&) const {
+std::string TextureDepthCube::String(MatchState*) const {
   return "texture_depth_cube";
 }
 
 /// TypeMatcher for 'type texture_depth_cube_array'
-/// @see src/tint/intrinsics.def:92:6
+/// @see src/tint/intrinsics.def:108:6
 class TextureDepthCubeArray : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -809,7 +1164,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* TextureDepthCubeArray::Match(MatchState& state, const sem::Type* ty) const {
@@ -819,16 +1174,16 @@
   return build_texture_depth_cube_array(state);
 }
 
-std::string TextureDepthCubeArray::String(MatchState&) const {
+std::string TextureDepthCubeArray::String(MatchState*) const {
   return "texture_depth_cube_array";
 }
 
 /// TypeMatcher for 'type texture_depth_multisampled_2d'
-/// @see src/tint/intrinsics.def:93:6
+/// @see src/tint/intrinsics.def:109:6
 class TextureDepthMultisampled2D : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -836,7 +1191,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* TextureDepthMultisampled2D::Match(MatchState& state, const sem::Type* ty) const {
@@ -846,16 +1201,16 @@
   return build_texture_depth_multisampled_2d(state);
 }
 
-std::string TextureDepthMultisampled2D::String(MatchState&) const {
+std::string TextureDepthMultisampled2D::String(MatchState*) const {
   return "texture_depth_multisampled_2d";
 }
 
 /// TypeMatcher for 'type texture_storage_1d'
-/// @see src/tint/intrinsics.def:94:6
+/// @see src/tint/intrinsics.def:110:6
 class TextureStorage1D : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -863,7 +1218,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* TextureStorage1D::Match(MatchState& state, const sem::Type* ty) const {
@@ -883,18 +1238,18 @@
   return build_texture_storage_1d(state, F, A);
 }
 
-std::string TextureStorage1D::String(MatchState& state) const {
-  const std::string F = state.NumName();
-  const std::string A = state.NumName();
+std::string TextureStorage1D::String(MatchState* state) const {
+  const std::string F = state->NumName();
+  const std::string A = state->NumName();
   return "texture_storage_1d<" + F + ", " + A + ">";
 }
 
 /// TypeMatcher for 'type texture_storage_2d'
-/// @see src/tint/intrinsics.def:95:6
+/// @see src/tint/intrinsics.def:111:6
 class TextureStorage2D : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -902,7 +1257,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* TextureStorage2D::Match(MatchState& state, const sem::Type* ty) const {
@@ -922,18 +1277,18 @@
   return build_texture_storage_2d(state, F, A);
 }
 
-std::string TextureStorage2D::String(MatchState& state) const {
-  const std::string F = state.NumName();
-  const std::string A = state.NumName();
+std::string TextureStorage2D::String(MatchState* state) const {
+  const std::string F = state->NumName();
+  const std::string A = state->NumName();
   return "texture_storage_2d<" + F + ", " + A + ">";
 }
 
 /// TypeMatcher for 'type texture_storage_2d_array'
-/// @see src/tint/intrinsics.def:96:6
+/// @see src/tint/intrinsics.def:112:6
 class TextureStorage2DArray : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -941,7 +1296,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* TextureStorage2DArray::Match(MatchState& state, const sem::Type* ty) const {
@@ -961,18 +1316,18 @@
   return build_texture_storage_2d_array(state, F, A);
 }
 
-std::string TextureStorage2DArray::String(MatchState& state) const {
-  const std::string F = state.NumName();
-  const std::string A = state.NumName();
+std::string TextureStorage2DArray::String(MatchState* state) const {
+  const std::string F = state->NumName();
+  const std::string A = state->NumName();
   return "texture_storage_2d_array<" + F + ", " + A + ">";
 }
 
 /// TypeMatcher for 'type texture_storage_3d'
-/// @see src/tint/intrinsics.def:97:6
+/// @see src/tint/intrinsics.def:113:6
 class TextureStorage3D : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -980,7 +1335,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* TextureStorage3D::Match(MatchState& state, const sem::Type* ty) const {
@@ -1000,18 +1355,18 @@
   return build_texture_storage_3d(state, F, A);
 }
 
-std::string TextureStorage3D::String(MatchState& state) const {
-  const std::string F = state.NumName();
-  const std::string A = state.NumName();
+std::string TextureStorage3D::String(MatchState* state) const {
+  const std::string F = state->NumName();
+  const std::string A = state->NumName();
   return "texture_storage_3d<" + F + ", " + A + ">";
 }
 
 /// TypeMatcher for 'type texture_external'
-/// @see src/tint/intrinsics.def:98:6
+/// @see src/tint/intrinsics.def:114:6
 class TextureExternal : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -1019,7 +1374,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* TextureExternal::Match(MatchState& state, const sem::Type* ty) const {
@@ -1029,16 +1384,16 @@
   return build_texture_external(state);
 }
 
-std::string TextureExternal::String(MatchState&) const {
+std::string TextureExternal::String(MatchState*) const {
   return "texture_external";
 }
 
 /// TypeMatcher for 'type __modf_result'
-/// @see src/tint/intrinsics.def:100:6
+/// @see src/tint/intrinsics.def:116:6
 class ModfResult : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -1046,7 +1401,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* ModfResult::Match(MatchState& state, const sem::Type* ty) const {
@@ -1056,16 +1411,16 @@
   return build_modf_result(state);
 }
 
-std::string ModfResult::String(MatchState&) const {
+std::string ModfResult::String(MatchState*) const {
   return "__modf_result";
 }
 
 /// TypeMatcher for 'type __modf_result_vec'
-/// @see src/tint/intrinsics.def:101:42
+/// @see src/tint/intrinsics.def:117:42
 class ModfResultVec : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -1073,7 +1428,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* ModfResultVec::Match(MatchState& state, const sem::Type* ty) const {
@@ -1088,19 +1443,19 @@
   return build_modf_result_vec(state, N);
 }
 
-std::string ModfResultVec::String(MatchState& state) const {
-  const std::string N = state.NumName();
+std::string ModfResultVec::String(MatchState* state) const {
+  const std::string N = state->NumName();
   std::stringstream ss;
   ss << "__modf_result_vec" << N;
   return ss.str();
 }
 
 /// TypeMatcher for 'type __frexp_result'
-/// @see src/tint/intrinsics.def:102:6
+/// @see src/tint/intrinsics.def:118:6
 class FrexpResult : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -1108,7 +1463,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* FrexpResult::Match(MatchState& state, const sem::Type* ty) const {
@@ -1118,16 +1473,16 @@
   return build_frexp_result(state);
 }
 
-std::string FrexpResult::String(MatchState&) const {
+std::string FrexpResult::String(MatchState*) const {
   return "__frexp_result";
 }
 
 /// TypeMatcher for 'type __frexp_result_vec'
-/// @see src/tint/intrinsics.def:103:43
+/// @see src/tint/intrinsics.def:119:43
 class FrexpResultVec : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -1135,7 +1490,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* FrexpResultVec::Match(MatchState& state, const sem::Type* ty) const {
@@ -1150,20 +1505,20 @@
   return build_frexp_result_vec(state, N);
 }
 
-std::string FrexpResultVec::String(MatchState& state) const {
-  const std::string N = state.NumName();
+std::string FrexpResultVec::String(MatchState* state) const {
+  const std::string N = state->NumName();
   std::stringstream ss;
   ss << "__frexp_result_vec" << N;
   return ss.str();
 }
 
 /// TypeMatcher for 'match fiu32'
-/// @see src/tint/intrinsics.def:111:7
+/// @see src/tint/intrinsics.def:127:7
 class Fiu32 : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules, and returns the
   /// expected, canonicalized type on success.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -1171,33 +1526,37 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Fiu32::Match(MatchState& state, const sem::Type* ty) const {
-  if (match_f32(ty)) {
-    return build_f32(state);
-  }
   if (match_i32(ty)) {
     return build_i32(state);
   }
   if (match_u32(ty)) {
     return build_u32(state);
   }
+  if (match_f32(ty)) {
+    return build_f32(state);
+  }
   return nullptr;
 }
 
-std::string Fiu32::String(MatchState&) const {
-  return "f32, i32 or u32";
+std::string Fiu32::String(MatchState*) const {
+  std::stringstream ss;
+  // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+  // template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
+  ss << F32().String(nullptr) << ", " << I32().String(nullptr) << " or " << U32().String(nullptr);
+  return ss.str();
 }
 
 /// TypeMatcher for 'match fi32'
-/// @see src/tint/intrinsics.def:112:7
+/// @see src/tint/intrinsics.def:128:7
 class Fi32 : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules, and returns the
   /// expected, canonicalized type on success.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -1205,30 +1564,34 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Fi32::Match(MatchState& state, const sem::Type* ty) const {
-  if (match_f32(ty)) {
-    return build_f32(state);
-  }
   if (match_i32(ty)) {
     return build_i32(state);
   }
+  if (match_f32(ty)) {
+    return build_f32(state);
+  }
   return nullptr;
 }
 
-std::string Fi32::String(MatchState&) const {
-  return "f32 or i32";
+std::string Fi32::String(MatchState*) const {
+  std::stringstream ss;
+  // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+  // template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
+  ss << F32().String(nullptr) << " or " << I32().String(nullptr);
+  return ss.str();
 }
 
 /// TypeMatcher for 'match iu32'
-/// @see src/tint/intrinsics.def:113:7
+/// @see src/tint/intrinsics.def:129:7
 class Iu32 : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules, and returns the
   /// expected, canonicalized type on success.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -1236,7 +1599,7 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Iu32::Match(MatchState& state, const sem::Type* ty) const {
@@ -1249,17 +1612,21 @@
   return nullptr;
 }
 
-std::string Iu32::String(MatchState&) const {
-  return "i32 or u32";
+std::string Iu32::String(MatchState*) const {
+  std::stringstream ss;
+  // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+  // template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
+  ss << I32().String(nullptr) << " or " << U32().String(nullptr);
+  return ss.str();
 }
 
 /// TypeMatcher for 'match scalar'
-/// @see src/tint/intrinsics.def:114:7
+/// @see src/tint/intrinsics.def:130:7
 class Scalar : public TypeMatcher {
  public:
   /// Checks whether the given type matches the matcher rules, and returns the
   /// expected, canonicalized type on success.
-  /// Match may close open types and numbers in state.
+  /// Match may define and refine the template types and numbers in state.
   /// @param state the MatchState
   /// @param type the type to match
   /// @returns the canonicalized type on match, otherwise nullptr
@@ -1267,13 +1634,133 @@
                          const sem::Type* type) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 const sem::Type* Scalar::Match(MatchState& state, const sem::Type* ty) const {
+  if (match_i32(ty)) {
+    return build_i32(state);
+  }
+  if (match_u32(ty)) {
+    return build_u32(state);
+  }
   if (match_f32(ty)) {
     return build_f32(state);
   }
+  if (match_bool(ty)) {
+    return build_bool(state);
+  }
+  return nullptr;
+}
+
+std::string Scalar::String(MatchState*) const {
+  std::stringstream ss;
+  // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+  // template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
+  ss << F32().String(nullptr) << ", " << I32().String(nullptr) << ", " << U32().String(nullptr) << " or " << Bool().String(nullptr);
+  return ss.str();
+}
+
+/// TypeMatcher for 'match abstract_or_scalar'
+/// @see src/tint/intrinsics.def:131:7
+class AbstractOrScalar : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules, and returns the
+  /// expected, canonicalized type on success.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
+};
+
+const sem::Type* AbstractOrScalar::Match(MatchState& state, const sem::Type* ty) const {
+  if (match_af(ty)) {
+    return build_af(state);
+  }
+  if (match_ai(ty)) {
+    return build_ai(state);
+  }
+  if (match_i32(ty)) {
+    return build_i32(state);
+  }
+  if (match_u32(ty)) {
+    return build_u32(state);
+  }
+  if (match_f32(ty)) {
+    return build_f32(state);
+  }
+  if (match_bool(ty)) {
+    return build_bool(state);
+  }
+  return nullptr;
+}
+
+std::string AbstractOrScalar::String(MatchState*) const {
+  std::stringstream ss;
+  // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+  // template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
+  ss << Ai().String(nullptr) << ", " << Af().String(nullptr) << ", " << F32().String(nullptr) << ", " << I32().String(nullptr) << ", " << U32().String(nullptr) << " or " << Bool().String(nullptr);
+  return ss.str();
+}
+
+/// TypeMatcher for 'match af_f32'
+/// @see src/tint/intrinsics.def:132:7
+class AfF32 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules, and returns the
+  /// expected, canonicalized type on success.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
+};
+
+const sem::Type* AfF32::Match(MatchState& state, const sem::Type* ty) const {
+  if (match_af(ty)) {
+    return build_af(state);
+  }
+  if (match_f32(ty)) {
+    return build_f32(state);
+  }
+  return nullptr;
+}
+
+std::string AfF32::String(MatchState*) const {
+  std::stringstream ss;
+  // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+  // template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
+  ss << Af().String(nullptr) << " or " << F32().String(nullptr);
+  return ss.str();
+}
+
+/// TypeMatcher for 'match scalar_no_f32'
+/// @see src/tint/intrinsics.def:133:7
+class ScalarNoF32 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules, and returns the
+  /// expected, canonicalized type on success.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
+};
+
+const sem::Type* ScalarNoF32::Match(MatchState& state, const sem::Type* ty) const {
   if (match_i32(ty)) {
     return build_i32(state);
   }
@@ -1286,23 +1773,141 @@
   return nullptr;
 }
 
-std::string Scalar::String(MatchState&) const {
-  return "f32, i32, u32 or bool";
+std::string ScalarNoF32::String(MatchState*) const {
+  std::stringstream ss;
+  // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+  // template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
+  ss << I32().String(nullptr) << ", " << U32().String(nullptr) << " or " << Bool().String(nullptr);
+  return ss.str();
+}
+
+/// TypeMatcher for 'match scalar_no_i32'
+/// @see src/tint/intrinsics.def:134:7
+class ScalarNoI32 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules, and returns the
+  /// expected, canonicalized type on success.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
+};
+
+const sem::Type* ScalarNoI32::Match(MatchState& state, const sem::Type* ty) const {
+  if (match_u32(ty)) {
+    return build_u32(state);
+  }
+  if (match_f32(ty)) {
+    return build_f32(state);
+  }
+  if (match_bool(ty)) {
+    return build_bool(state);
+  }
+  return nullptr;
+}
+
+std::string ScalarNoI32::String(MatchState*) const {
+  std::stringstream ss;
+  // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+  // template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
+  ss << F32().String(nullptr) << ", " << U32().String(nullptr) << " or " << Bool().String(nullptr);
+  return ss.str();
+}
+
+/// TypeMatcher for 'match scalar_no_u32'
+/// @see src/tint/intrinsics.def:135:7
+class ScalarNoU32 : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules, and returns the
+  /// expected, canonicalized type on success.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
+};
+
+const sem::Type* ScalarNoU32::Match(MatchState& state, const sem::Type* ty) const {
+  if (match_i32(ty)) {
+    return build_i32(state);
+  }
+  if (match_f32(ty)) {
+    return build_f32(state);
+  }
+  if (match_bool(ty)) {
+    return build_bool(state);
+  }
+  return nullptr;
+}
+
+std::string ScalarNoU32::String(MatchState*) const {
+  std::stringstream ss;
+  // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+  // template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
+  ss << F32().String(nullptr) << ", " << I32().String(nullptr) << " or " << Bool().String(nullptr);
+  return ss.str();
+}
+
+/// TypeMatcher for 'match scalar_no_bool'
+/// @see src/tint/intrinsics.def:136:7
+class ScalarNoBool : public TypeMatcher {
+ public:
+  /// Checks whether the given type matches the matcher rules, and returns the
+  /// expected, canonicalized type on success.
+  /// Match may define and refine the template types and numbers in state.
+  /// @param state the MatchState
+  /// @param type the type to match
+  /// @returns the canonicalized type on match, otherwise nullptr
+  const sem::Type* Match(MatchState& state,
+                         const sem::Type* type) const override;
+  /// @param state the MatchState
+  /// @return a string representation of the matcher.
+  std::string String(MatchState* state) const override;
+};
+
+const sem::Type* ScalarNoBool::Match(MatchState& state, const sem::Type* ty) const {
+  if (match_i32(ty)) {
+    return build_i32(state);
+  }
+  if (match_u32(ty)) {
+    return build_u32(state);
+  }
+  if (match_f32(ty)) {
+    return build_f32(state);
+  }
+  return nullptr;
+}
+
+std::string ScalarNoBool::String(MatchState*) const {
+  std::stringstream ss;
+  // Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
+  // template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
+  ss << F32().String(nullptr) << ", " << I32().String(nullptr) << " or " << U32().String(nullptr);
+  return ss.str();
 }
 
 /// EnumMatcher for 'match f32_texel_format'
-/// @see src/tint/intrinsics.def:125:7
+/// @see src/tint/intrinsics.def:147:7
 class F32TexelFormat : public NumberMatcher {
  public:
   /// Checks whether the given number matches the enum matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define template numbers in state.
   /// @param state the MatchState
   /// @param number the enum value as a Number
   /// @return true if the enum value matches the set
   Number Match(MatchState& state, Number number) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 Number F32TexelFormat::Match(MatchState&, Number number) const {
@@ -1319,23 +1924,23 @@
   }
 }
 
-std::string F32TexelFormat::String(MatchState&) const {
+std::string F32TexelFormat::String(MatchState*) const {
   return "rgba8unorm, rgba8snorm, rgba16float, r32float, rg32float or rgba32float";
 }
 
 /// EnumMatcher for 'match i32_texel_format'
-/// @see src/tint/intrinsics.def:127:7
+/// @see src/tint/intrinsics.def:149:7
 class I32TexelFormat : public NumberMatcher {
  public:
   /// Checks whether the given number matches the enum matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define template numbers in state.
   /// @param state the MatchState
   /// @param number the enum value as a Number
   /// @return true if the enum value matches the set
   Number Match(MatchState& state, Number number) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 Number I32TexelFormat::Match(MatchState&, Number number) const {
@@ -1351,23 +1956,23 @@
   }
 }
 
-std::string I32TexelFormat::String(MatchState&) const {
+std::string I32TexelFormat::String(MatchState*) const {
   return "rgba8sint, rgba16sint, r32sint, rg32sint or rgba32sint";
 }
 
 /// EnumMatcher for 'match u32_texel_format'
-/// @see src/tint/intrinsics.def:129:7
+/// @see src/tint/intrinsics.def:151:7
 class U32TexelFormat : public NumberMatcher {
  public:
   /// Checks whether the given number matches the enum matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define template numbers in state.
   /// @param state the MatchState
   /// @param number the enum value as a Number
   /// @return true if the enum value matches the set
   Number Match(MatchState& state, Number number) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 Number U32TexelFormat::Match(MatchState&, Number number) const {
@@ -1383,23 +1988,23 @@
   }
 }
 
-std::string U32TexelFormat::String(MatchState&) const {
+std::string U32TexelFormat::String(MatchState*) const {
   return "rgba8uint, rgba16uint, r32uint, rg32uint or rgba32uint";
 }
 
 /// EnumMatcher for 'match write_only'
-/// @see src/tint/intrinsics.def:132:7
+/// @see src/tint/intrinsics.def:154:7
 class WriteOnly : public NumberMatcher {
  public:
   /// Checks whether the given number matches the enum matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define template numbers in state.
   /// @param state the MatchState
   /// @param number the enum value as a Number
   /// @return true if the enum value matches the set
   Number Match(MatchState& state, Number number) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 Number WriteOnly::Match(MatchState&, Number number) const {
@@ -1409,23 +2014,23 @@
   return Number::invalid;
 }
 
-std::string WriteOnly::String(MatchState&) const {
+std::string WriteOnly::String(MatchState*) const {
   return "write";
 }
 
 /// EnumMatcher for 'match function_private_workgroup'
-/// @see src/tint/intrinsics.def:134:7
+/// @see src/tint/intrinsics.def:156:7
 class FunctionPrivateWorkgroup : public NumberMatcher {
  public:
   /// Checks whether the given number matches the enum matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define template numbers in state.
   /// @param state the MatchState
   /// @param number the enum value as a Number
   /// @return true if the enum value matches the set
   Number Match(MatchState& state, Number number) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 Number FunctionPrivateWorkgroup::Match(MatchState&, Number number) const {
@@ -1439,23 +2044,23 @@
   }
 }
 
-std::string FunctionPrivateWorkgroup::String(MatchState&) const {
+std::string FunctionPrivateWorkgroup::String(MatchState*) const {
   return "function, private or workgroup";
 }
 
 /// EnumMatcher for 'match workgroup_or_storage'
-/// @see src/tint/intrinsics.def:135:7
+/// @see src/tint/intrinsics.def:157:7
 class WorkgroupOrStorage : public NumberMatcher {
  public:
   /// Checks whether the given number matches the enum matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define template numbers in state.
   /// @param state the MatchState
   /// @param number the enum value as a Number
   /// @return true if the enum value matches the set
   Number Match(MatchState& state, Number number) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 Number WorkgroupOrStorage::Match(MatchState&, Number number) const {
@@ -1468,7 +2073,7 @@
   }
 }
 
-std::string WorkgroupOrStorage::String(MatchState&) const {
+std::string WorkgroupOrStorage::String(MatchState*) const {
   return "workgroup or storage";
 }
 
@@ -1476,14 +2081,14 @@
 class Storage : public NumberMatcher {
  public:
   /// Checks whether the given number matches the enum matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define template numbers in state.
   /// @param state the MatchState
   /// @param number the enum value as a Number
   /// @return true if the enum value matches the set
   Number Match(MatchState& state, Number number) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 Number Storage::Match(MatchState&, Number number) const {
@@ -1493,7 +2098,7 @@
   return Number::invalid;
 }
 
-std::string Storage::String(MatchState&) const {
+std::string Storage::String(MatchState*) const {
   return "storage";
 }
 
@@ -1501,14 +2106,14 @@
 class Write : public NumberMatcher {
  public:
   /// Checks whether the given number matches the enum matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define template numbers in state.
   /// @param state the MatchState
   /// @param number the enum value as a Number
   /// @return true if the enum value matches the set
   Number Match(MatchState& state, Number number) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 Number Write::Match(MatchState&, Number number) const {
@@ -1518,7 +2123,7 @@
   return Number::invalid;
 }
 
-std::string Write::String(MatchState&) const {
+std::string Write::String(MatchState*) const {
   return "write";
 }
 
@@ -1526,14 +2131,14 @@
 class ReadWrite : public NumberMatcher {
  public:
   /// Checks whether the given number matches the enum matcher rules.
-  /// Match may close open types and numbers in state.
+  /// Match may define template numbers in state.
   /// @param state the MatchState
   /// @param number the enum value as a Number
   /// @return true if the enum value matches the set
   Number Match(MatchState& state, Number number) const override;
   /// @param state the MatchState
   /// @return a string representation of the matcher.
-  std::string String(MatchState& state) const override;
+  std::string String(MatchState* state) const override;
 };
 
 Number ReadWrite::Match(MatchState&, Number number) const {
@@ -1543,24 +2148,36 @@
   return Number::invalid;
 }
 
-std::string ReadWrite::String(MatchState&) const {
+std::string ReadWrite::String(MatchState*) const {
   return "read_write";
 }
 
 /// Matchers holds type and number matchers
 class Matchers {
  private:
-  OpenTypeMatcher open_type_0_{0};
-  OpenNumberMatcher open_number_0_{0};
-  OpenNumberMatcher open_number_1_{1};
-  OpenNumberMatcher open_number_2_{2};
+  TemplateTypeMatcher template_type_0_{0};
+  TemplateTypeMatcher template_type_1_{1};
+  TemplateNumberMatcher template_number_0_{0};
+  TemplateNumberMatcher template_number_1_{1};
+  TemplateNumberMatcher template_number_2_{2};
   Bool Bool_;
-  F32 F32_;
+  Af Af_;
+  Ai Ai_;
   I32 I32_;
   U32 U32_;
+  F32 F32_;
   Vec2 Vec2_;
   Vec3 Vec3_;
   Vec4 Vec4_;
+  Mat2X2 Mat2X2_;
+  Mat2X3 Mat2X3_;
+  Mat2X4 Mat2X4_;
+  Mat3X2 Mat3X2_;
+  Mat3X3 Mat3X3_;
+  Mat3X4 Mat3X4_;
+  Mat4X2 Mat4X2_;
+  Mat4X3 Mat4X3_;
+  Mat4X4 Mat4X4_;
   Vec Vec_;
   Mat Mat_;
   Ptr Ptr_;
@@ -1593,6 +2210,12 @@
   Fi32 Fi32_;
   Iu32 Iu32_;
   Scalar Scalar_;
+  AbstractOrScalar AbstractOrScalar_;
+  AfF32 AfF32_;
+  ScalarNoF32 ScalarNoF32_;
+  ScalarNoI32 ScalarNoI32_;
+  ScalarNoU32 ScalarNoU32_;
+  ScalarNoBool ScalarNoBool_;
   F32TexelFormat F32TexelFormat_;
   I32TexelFormat I32TexelFormat_;
   U32TexelFormat U32TexelFormat_;
@@ -1609,55 +2232,73 @@
   /// Destructor
   ~Matchers();
 
-  /// The open-types, types, and type matchers
-  TypeMatcher const* const type[40] = {
-    /* [0] */ &open_type_0_,
-    /* [1] */ &Bool_,
-    /* [2] */ &F32_,
-    /* [3] */ &I32_,
-    /* [4] */ &U32_,
-    /* [5] */ &Vec2_,
-    /* [6] */ &Vec3_,
-    /* [7] */ &Vec4_,
-    /* [8] */ &Vec_,
-    /* [9] */ &Mat_,
-    /* [10] */ &Ptr_,
-    /* [11] */ &Atomic_,
-    /* [12] */ &Array_,
-    /* [13] */ &Sampler_,
-    /* [14] */ &SamplerComparison_,
-    /* [15] */ &Texture1D_,
-    /* [16] */ &Texture2D_,
-    /* [17] */ &Texture2DArray_,
-    /* [18] */ &Texture3D_,
-    /* [19] */ &TextureCube_,
-    /* [20] */ &TextureCubeArray_,
-    /* [21] */ &TextureMultisampled2D_,
-    /* [22] */ &TextureDepth2D_,
-    /* [23] */ &TextureDepth2DArray_,
-    /* [24] */ &TextureDepthCube_,
-    /* [25] */ &TextureDepthCubeArray_,
-    /* [26] */ &TextureDepthMultisampled2D_,
-    /* [27] */ &TextureStorage1D_,
-    /* [28] */ &TextureStorage2D_,
-    /* [29] */ &TextureStorage2DArray_,
-    /* [30] */ &TextureStorage3D_,
-    /* [31] */ &TextureExternal_,
-    /* [32] */ &ModfResult_,
-    /* [33] */ &ModfResultVec_,
-    /* [34] */ &FrexpResult_,
-    /* [35] */ &FrexpResultVec_,
-    /* [36] */ &Fiu32_,
-    /* [37] */ &Fi32_,
-    /* [38] */ &Iu32_,
-    /* [39] */ &Scalar_,
+  /// The template types, types, and type matchers
+  TypeMatcher const* const type[58] = {
+    /* [0] */ &template_type_0_,
+    /* [1] */ &template_type_1_,
+    /* [2] */ &Bool_,
+    /* [3] */ &Af_,
+    /* [4] */ &Ai_,
+    /* [5] */ &I32_,
+    /* [6] */ &U32_,
+    /* [7] */ &F32_,
+    /* [8] */ &Vec2_,
+    /* [9] */ &Vec3_,
+    /* [10] */ &Vec4_,
+    /* [11] */ &Mat2X2_,
+    /* [12] */ &Mat2X3_,
+    /* [13] */ &Mat2X4_,
+    /* [14] */ &Mat3X2_,
+    /* [15] */ &Mat3X3_,
+    /* [16] */ &Mat3X4_,
+    /* [17] */ &Mat4X2_,
+    /* [18] */ &Mat4X3_,
+    /* [19] */ &Mat4X4_,
+    /* [20] */ &Vec_,
+    /* [21] */ &Mat_,
+    /* [22] */ &Ptr_,
+    /* [23] */ &Atomic_,
+    /* [24] */ &Array_,
+    /* [25] */ &Sampler_,
+    /* [26] */ &SamplerComparison_,
+    /* [27] */ &Texture1D_,
+    /* [28] */ &Texture2D_,
+    /* [29] */ &Texture2DArray_,
+    /* [30] */ &Texture3D_,
+    /* [31] */ &TextureCube_,
+    /* [32] */ &TextureCubeArray_,
+    /* [33] */ &TextureMultisampled2D_,
+    /* [34] */ &TextureDepth2D_,
+    /* [35] */ &TextureDepth2DArray_,
+    /* [36] */ &TextureDepthCube_,
+    /* [37] */ &TextureDepthCubeArray_,
+    /* [38] */ &TextureDepthMultisampled2D_,
+    /* [39] */ &TextureStorage1D_,
+    /* [40] */ &TextureStorage2D_,
+    /* [41] */ &TextureStorage2DArray_,
+    /* [42] */ &TextureStorage3D_,
+    /* [43] */ &TextureExternal_,
+    /* [44] */ &ModfResult_,
+    /* [45] */ &ModfResultVec_,
+    /* [46] */ &FrexpResult_,
+    /* [47] */ &FrexpResultVec_,
+    /* [48] */ &Fiu32_,
+    /* [49] */ &Fi32_,
+    /* [50] */ &Iu32_,
+    /* [51] */ &Scalar_,
+    /* [52] */ &AbstractOrScalar_,
+    /* [53] */ &AfF32_,
+    /* [54] */ &ScalarNoF32_,
+    /* [55] */ &ScalarNoI32_,
+    /* [56] */ &ScalarNoU32_,
+    /* [57] */ &ScalarNoBool_,
   };
 
-  /// The open-numbers, and number matchers
+  /// The template numbers, and number matchers
   NumberMatcher const* const number[12] = {
-    /* [0] */ &open_number_0_,
-    /* [1] */ &open_number_1_,
-    /* [2] */ &open_number_2_,
+    /* [0] */ &template_number_0_,
+    /* [1] */ &template_number_1_,
+    /* [2] */ &template_number_2_,
     /* [3] */ &F32TexelFormat_,
     /* [4] */ &I32TexelFormat_,
     /* [5] */ &U32TexelFormat_,
@@ -1674,159 +2315,207 @@
 Matchers::~Matchers() = default;
 
 constexpr MatcherIndex kMatcherIndices[] = {
-  /* [0] */ 30,
-  /* [1] */ 4,
-  /* [2] */ 10,
+  /* [0] */ 22,
+  /* [1] */ 0,
+  /* [2] */ 23,
   /* [3] */ 0,
   /* [4] */ 11,
-  /* [5] */ 0,
-  /* [6] */ 11,
-  /* [7] */ 10,
-  /* [8] */ 9,
-  /* [9] */ 12,
+  /* [5] */ 7,
+  /* [6] */ 22,
+  /* [7] */ 9,
+  /* [8] */ 24,
+  /* [9] */ 0,
   /* [10] */ 0,
-  /* [11] */ 0,
-  /* [12] */ 9,
-  /* [13] */ 0,
-  /* [14] */ 0,
-  /* [15] */ 2,
-  /* [16] */ 9,
+  /* [11] */ 21,
+  /* [12] */ 0,
+  /* [13] */ 1,
+  /* [14] */ 7,
+  /* [15] */ 21,
+  /* [16] */ 0,
   /* [17] */ 0,
-  /* [18] */ 1,
-  /* [19] */ 2,
-  /* [20] */ 9,
-  /* [21] */ 1,
-  /* [22] */ 0,
-  /* [23] */ 2,
-  /* [24] */ 9,
+  /* [18] */ 7,
+  /* [19] */ 21,
+  /* [20] */ 0,
+  /* [21] */ 2,
+  /* [22] */ 7,
+  /* [23] */ 21,
+  /* [24] */ 1,
   /* [25] */ 0,
-  /* [26] */ 2,
-  /* [27] */ 2,
-  /* [28] */ 9,
-  /* [29] */ 1,
-  /* [30] */ 2,
-  /* [31] */ 2,
-  /* [32] */ 8,
-  /* [33] */ 0,
-  /* [34] */ 2,
-  /* [35] */ 8,
-  /* [36] */ 0,
-  /* [37] */ 1,
-  /* [38] */ 8,
+  /* [26] */ 7,
+  /* [27] */ 21,
+  /* [28] */ 1,
+  /* [29] */ 2,
+  /* [30] */ 7,
+  /* [31] */ 20,
+  /* [32] */ 0,
+  /* [33] */ 7,
+  /* [34] */ 41,
+  /* [35] */ 0,
+  /* [36] */ 1,
+  /* [37] */ 20,
+  /* [38] */ 0,
   /* [39] */ 0,
-  /* [40] */ 0,
-  /* [41] */ 29,
-  /* [42] */ 0,
-  /* [43] */ 1,
-  /* [44] */ 30,
-  /* [45] */ 0,
-  /* [46] */ 1,
-  /* [47] */ 8,
-  /* [48] */ 1,
-  /* [49] */ 2,
-  /* [50] */ 28,
-  /* [51] */ 0,
-  /* [52] */ 1,
-  /* [53] */ 27,
-  /* [54] */ 0,
-  /* [55] */ 1,
-  /* [56] */ 8,
-  /* [57] */ 0,
-  /* [58] */ 3,
-  /* [59] */ 8,
-  /* [60] */ 0,
-  /* [61] */ 4,
-  /* [62] */ 27,
-  /* [63] */ 3,
-  /* [64] */ 10,
-  /* [65] */ 28,
-  /* [66] */ 3,
-  /* [67] */ 10,
-  /* [68] */ 29,
-  /* [69] */ 3,
-  /* [70] */ 10,
-  /* [71] */ 30,
-  /* [72] */ 3,
-  /* [73] */ 10,
-  /* [74] */ 27,
-  /* [75] */ 4,
-  /* [76] */ 10,
-  /* [77] */ 28,
-  /* [78] */ 4,
-  /* [79] */ 10,
-  /* [80] */ 30,
-  /* [81] */ 5,
-  /* [82] */ 10,
-  /* [83] */ 29,
-  /* [84] */ 5,
-  /* [85] */ 10,
-  /* [86] */ 29,
-  /* [87] */ 4,
-  /* [88] */ 10,
-  /* [89] */ 28,
-  /* [90] */ 5,
-  /* [91] */ 10,
-  /* [92] */ 27,
-  /* [93] */ 5,
-  /* [94] */ 10,
-  /* [95] */ 6,
-  /* [96] */ 3,
-  /* [97] */ 7,
-  /* [98] */ 3,
+  /* [40] */ 20,
+  /* [41] */ 0,
+  /* [42] */ 2,
+  /* [43] */ 42,
+  /* [44] */ 5,
+  /* [45] */ 10,
+  /* [46] */ 7,
+  /* [47] */ 41,
+  /* [48] */ 5,
+  /* [49] */ 10,
+  /* [50] */ 0,
+  /* [51] */ 40,
+  /* [52] */ 5,
+  /* [53] */ 10,
+  /* [54] */ 1,
+  /* [55] */ 39,
+  /* [56] */ 5,
+  /* [57] */ 10,
+  /* [58] */ 5,
+  /* [59] */ 42,
+  /* [60] */ 4,
+  /* [61] */ 10,
+  /* [62] */ 6,
+  /* [63] */ 41,
+  /* [64] */ 4,
+  /* [65] */ 10,
+  /* [66] */ 2,
+  /* [67] */ 40,
+  /* [68] */ 4,
+  /* [69] */ 10,
+  /* [70] */ 39,
+  /* [71] */ 4,
+  /* [72] */ 10,
+  /* [73] */ 42,
+  /* [74] */ 3,
+  /* [75] */ 10,
+  /* [76] */ 20,
+  /* [77] */ 1,
+  /* [78] */ 7,
+  /* [79] */ 42,
+  /* [80] */ 0,
+  /* [81] */ 1,
+  /* [82] */ 40,
+  /* [83] */ 0,
+  /* [84] */ 1,
+  /* [85] */ 39,
+  /* [86] */ 0,
+  /* [87] */ 1,
+  /* [88] */ 41,
+  /* [89] */ 3,
+  /* [90] */ 10,
+  /* [91] */ 40,
+  /* [92] */ 3,
+  /* [93] */ 10,
+  /* [94] */ 39,
+  /* [95] */ 3,
+  /* [96] */ 10,
+  /* [97] */ 20,
+  /* [98] */ 0,
   /* [99] */ 5,
-  /* [100] */ 3,
-  /* [101] */ 7,
-  /* [102] */ 4,
-  /* [103] */ 15,
-  /* [104] */ 0,
-  /* [105] */ 7,
+  /* [100] */ 20,
+  /* [101] */ 0,
+  /* [102] */ 6,
+  /* [103] */ 8,
+  /* [104] */ 7,
+  /* [105] */ 8,
   /* [106] */ 0,
-  /* [107] */ 16,
-  /* [108] */ 0,
-  /* [109] */ 7,
-  /* [110] */ 2,
-  /* [111] */ 17,
-  /* [112] */ 0,
-  /* [113] */ 5,
+  /* [107] */ 8,
+  /* [108] */ 1,
+  /* [109] */ 8,
+  /* [110] */ 5,
+  /* [111] */ 8,
+  /* [112] */ 6,
+  /* [113] */ 8,
   /* [114] */ 2,
-  /* [115] */ 33,
+  /* [115] */ 9,
   /* [116] */ 0,
-  /* [117] */ 18,
+  /* [117] */ 45,
   /* [118] */ 0,
-  /* [119] */ 21,
-  /* [120] */ 0,
-  /* [121] */ 6,
-  /* [122] */ 2,
-  /* [123] */ 20,
-  /* [124] */ 2,
-  /* [125] */ 19,
-  /* [126] */ 0,
-  /* [127] */ 19,
+  /* [119] */ 9,
+  /* [120] */ 1,
+  /* [121] */ 9,
+  /* [122] */ 7,
+  /* [123] */ 9,
+  /* [124] */ 5,
+  /* [125] */ 9,
+  /* [126] */ 6,
+  /* [127] */ 9,
   /* [128] */ 2,
-  /* [129] */ 20,
+  /* [129] */ 27,
   /* [130] */ 0,
-  /* [131] */ 18,
-  /* [132] */ 2,
-  /* [133] */ 17,
-  /* [134] */ 2,
-  /* [135] */ 5,
+  /* [131] */ 28,
+  /* [132] */ 0,
+  /* [133] */ 29,
+  /* [134] */ 0,
+  /* [135] */ 47,
   /* [136] */ 0,
-  /* [137] */ 35,
+  /* [137] */ 19,
   /* [138] */ 0,
-  /* [139] */ 16,
-  /* [140] */ 2,
-  /* [141] */ 15,
-  /* [142] */ 2,
-  /* [143] */ 13,
-  /* [144] */ 23,
-  /* [145] */ 24,
-  /* [146] */ 25,
-  /* [147] */ 22,
-  /* [148] */ 26,
-  /* [149] */ 14,
-  /* [150] */ 31,
-  /* [151] */ 32,
-  /* [152] */ 34,
+  /* [139] */ 30,
+  /* [140] */ 0,
+  /* [141] */ 31,
+  /* [142] */ 0,
+  /* [143] */ 32,
+  /* [144] */ 0,
+  /* [145] */ 33,
+  /* [146] */ 0,
+  /* [147] */ 11,
+  /* [148] */ 0,
+  /* [149] */ 12,
+  /* [150] */ 7,
+  /* [151] */ 12,
+  /* [152] */ 0,
+  /* [153] */ 13,
+  /* [154] */ 7,
+  /* [155] */ 13,
+  /* [156] */ 0,
+  /* [157] */ 14,
+  /* [158] */ 7,
+  /* [159] */ 14,
+  /* [160] */ 0,
+  /* [161] */ 15,
+  /* [162] */ 7,
+  /* [163] */ 15,
+  /* [164] */ 0,
+  /* [165] */ 16,
+  /* [166] */ 7,
+  /* [167] */ 16,
+  /* [168] */ 0,
+  /* [169] */ 17,
+  /* [170] */ 7,
+  /* [171] */ 17,
+  /* [172] */ 0,
+  /* [173] */ 18,
+  /* [174] */ 7,
+  /* [175] */ 18,
+  /* [176] */ 0,
+  /* [177] */ 27,
+  /* [178] */ 7,
+  /* [179] */ 28,
+  /* [180] */ 7,
+  /* [181] */ 29,
+  /* [182] */ 7,
+  /* [183] */ 19,
+  /* [184] */ 7,
+  /* [185] */ 30,
+  /* [186] */ 7,
+  /* [187] */ 31,
+  /* [188] */ 7,
+  /* [189] */ 32,
+  /* [190] */ 7,
+  /* [191] */ 25,
+  /* [192] */ 26,
+  /* [193] */ 37,
+  /* [194] */ 36,
+  /* [195] */ 35,
+  /* [196] */ 34,
+  /* [197] */ 43,
+  /* [198] */ 38,
+  /* [199] */ 44,
+  /* [200] */ 46,
 };
 
 // Assert that the MatcherIndex is big enough to index all the matchers, plus
@@ -1838,1363 +2527,1363 @@
 constexpr ParameterInfo kParameters[] = {
   {
     /* [0] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[133],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [1] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [2] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [3] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [4] */
-    /* usage */ ParameterUsage::kDdx,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [5] */
-    /* usage */ ParameterUsage::kDdy,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [6] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [7] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[133],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [8] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [9] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [10] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [11] */
-    /* usage */ ParameterUsage::kDdx,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [12] */
-    /* usage */ ParameterUsage::kDdy,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [13] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[144],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [14] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [15] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [16] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [17] */
-    /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [18] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [19] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[133],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [20] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [21] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [22] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [23] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [24] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [25] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[123],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [26] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [27] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [28] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [29] */
-    /* usage */ ParameterUsage::kDdx,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [30] */
-    /* usage */ ParameterUsage::kDdy,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [31] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[144],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [32] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [33] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [34] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [35] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [36] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [37] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[144],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [38] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [39] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [40] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [41] */
-    /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [42] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [43] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[131],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [44] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [45] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [46] */
-    /* usage */ ParameterUsage::kDdx,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [47] */
-    /* usage */ ParameterUsage::kDdy,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [48] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[95],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [49] */
-    /* usage */ ParameterUsage::kComponent,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [50] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[111],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [51] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [52] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [53] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [54] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [55] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[133],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [56] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [57] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [58] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [59] */
-    /* usage */ ParameterUsage::kBias,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [60] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [61] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[144],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [62] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [63] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [64] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [65] */
-    /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[181],
   },
   {
     /* [66] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [67] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[139],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [68] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [69] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kDdx,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [70] */
-    /* usage */ ParameterUsage::kDdx,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kDdy,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [71] */
-    /* usage */ ParameterUsage::kDdy,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [72] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[195],
   },
   {
     /* [73] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[131],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [74] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [75] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [76] */
-    /* usage */ ParameterUsage::kBias,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [77] */
     /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[95],
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [78] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[144],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [79] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [80] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [81] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [82] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [83] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[144],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [84] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[179],
   },
   {
     /* [85] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [86] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [87] */
-    /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kDdx,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [88] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[139],
+    /* usage */ ParameterUsage::kDdy,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [89] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [90] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [91] */
-    /* usage */ ParameterUsage::kBias,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [92] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [93] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[131],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [94] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [95] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [96] */
-    /* usage */ ParameterUsage::kDdx,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kComponent,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [97] */
-    /* usage */ ParameterUsage::kDdy,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[133],
   },
   {
     /* [98] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[144],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [99] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [100] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [101] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [102] */
-    /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[181],
   },
   {
     /* [103] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[139],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [104] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [105] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [106] */
     /* usage */ ParameterUsage::kDdx,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [107] */
     /* usage */ ParameterUsage::kDdy,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [108] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[123],
+    /* matcher indices */ &kMatcherIndices[195],
   },
   {
     /* [109] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* matcher indices */ &kMatcherIndices[192],
   },
   {
     /* [110] */
     /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [111] */
     /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [112] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [113] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[133],
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [114] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[185],
   },
   {
     /* [115] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [116] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [117] */
-    /* usage */ ParameterUsage::kBias,
-    /* matcher indices */ &kMatcherIndices[15],
-  },
-  {
-    /* [118] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[146],
-  },
-  {
-    /* [119] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
-  },
-  {
-    /* [120] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
-  },
-  {
-    /* [121] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
-  },
-  {
-    /* [122] */
-    /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
-  },
-  {
-    /* [123] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[123],
-  },
-  {
-    /* [124] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
-  },
-  {
-    /* [125] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
-  },
-  {
-    /* [126] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
-  },
-  {
-    /* [127] */
-    /* usage */ ParameterUsage::kBias,
-    /* matcher indices */ &kMatcherIndices[15],
-  },
-  {
-    /* [128] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[146],
-  },
-  {
-    /* [129] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
-  },
-  {
-    /* [130] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
-  },
-  {
-    /* [131] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
-  },
-  {
-    /* [132] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
-  },
-  {
-    /* [133] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[146],
-  },
-  {
-    /* [134] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
-  },
-  {
-    /* [135] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
-  },
-  {
-    /* [136] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
-  },
-  {
-    /* [137] */
-    /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
-  },
-  {
-    /* [138] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[144],
-  },
-  {
-    /* [139] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
-  },
-  {
-    /* [140] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
-  },
-  {
-    /* [141] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
-  },
-  {
-    /* [142] */
-    /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
-  },
-  {
-    /* [143] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[127],
-  },
-  {
-    /* [144] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
-  },
-  {
-    /* [145] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
-  },
-  {
-    /* [146] */
     /* usage */ ParameterUsage::kDdx,
     /* matcher indices */ &kMatcherIndices[121],
   },
   {
-    /* [147] */
+    /* [118] */
     /* usage */ ParameterUsage::kDdy,
     /* matcher indices */ &kMatcherIndices[121],
   },
   {
-    /* [148] */
+    /* [119] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[123],
+  },
+  {
+    /* [120] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[133],
+    /* matcher indices */ &kMatcherIndices[189],
+  },
+  {
+    /* [121] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
+  },
+  {
+    /* [122] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
+  },
+  {
+    /* [123] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
+  },
+  {
+    /* [124] */
+    /* usage */ ParameterUsage::kDdx,
+    /* matcher indices */ &kMatcherIndices[121],
+  },
+  {
+    /* [125] */
+    /* usage */ ParameterUsage::kDdy,
+    /* matcher indices */ &kMatcherIndices[121],
+  },
+  {
+    /* [126] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[181],
+  },
+  {
+    /* [127] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
+  },
+  {
+    /* [128] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
+  },
+  {
+    /* [129] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
+  },
+  {
+    /* [130] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [131] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
+  },
+  {
+    /* [132] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[181],
+  },
+  {
+    /* [133] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
+  },
+  {
+    /* [134] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
+  },
+  {
+    /* [135] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
+  },
+  {
+    /* [136] */
+    /* usage */ ParameterUsage::kBias,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [137] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
+  },
+  {
+    /* [138] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[195],
+  },
+  {
+    /* [139] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[192],
+  },
+  {
+    /* [140] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
+  },
+  {
+    /* [141] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
+  },
+  {
+    /* [142] */
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [143] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
+  },
+  {
+    /* [144] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[195],
+  },
+  {
+    /* [145] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[192],
+  },
+  {
+    /* [146] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
+  },
+  {
+    /* [147] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
+  },
+  {
+    /* [148] */
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [149] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [150] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[195],
   },
   {
     /* [151] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [152] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [153] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[147],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [154] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [155] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[196],
   },
   {
     /* [156] */
-    /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [157] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [158] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[147],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [159] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [160] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[193],
   },
   {
     /* [161] */
-    /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[192],
   },
   {
     /* [162] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [163] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[146],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [164] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [165] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[189],
   },
   {
     /* [166] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [167] */
-    /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [168] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[147],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [169] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [170] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[193],
   },
   {
     /* [171] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [172] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [173] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[144],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [174] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [175] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[185],
   },
   {
     /* [176] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [177] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [178] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[144],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [179] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[123],
   },
   {
     /* [180] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[179],
   },
   {
     /* [181] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [182] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [183] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[139],
+    /* usage */ ParameterUsage::kBias,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [184] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [185] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[195],
   },
   {
     /* [186] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[192],
   },
   {
     /* [187] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [188] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[147],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [189] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [190] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[181],
   },
   {
     /* [191] */
-    /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [192] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [193] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[133],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [194] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [195] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[179],
   },
   {
     /* [196] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [197] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [198] */
-    /* usage */ ParameterUsage::kComponent,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [199] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[129],
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [200] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[195],
   },
   {
     /* [201] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [202] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [203] */
-    /* usage */ ParameterUsage::kComponent,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [204] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[107],
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [205] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[196],
   },
   {
     /* [206] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[192],
   },
   {
     /* [207] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [208] */
-    /* usage */ ParameterUsage::kComponent,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [209] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[111],
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [210] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[187],
   },
   {
     /* [211] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [212] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [213] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[131],
+    /* usage */ ParameterUsage::kDdx,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [214] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kDdy,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [215] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[181],
   },
   {
     /* [216] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [217] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[95],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [218] */
-    /* usage */ ParameterUsage::kComponent,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [219] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[125],
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [220] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[185],
   },
   {
     /* [221] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
+  },
+  {
+    /* [222] */
     /* usage */ ParameterUsage::kCoords,
     /* matcher indices */ &kMatcherIndices[121],
   },
   {
-    /* [222] */
-    /* usage */ ParameterUsage::kComponent,
-    /* matcher indices */ &kMatcherIndices[58],
-  },
-  {
     /* [223] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[107],
+    /* usage */ ParameterUsage::kDdx,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [224] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kDdy,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [225] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[195],
   },
   {
     /* [226] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[147],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [227] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [228] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [229] */
     /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [230] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[144],
+    /* usage */ ParameterUsage::kComponent,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [231] */
-    /* usage */ ParameterUsage::kSampler,
+    /* usage */ ParameterUsage::kTexture,
     /* matcher indices */ &kMatcherIndices[143],
   },
   {
     /* [232] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [233] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [234] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[146],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [235] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kComponent,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [236] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[133],
   },
   {
     /* [237] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [238] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[145],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [239] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [240] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[179],
+  },
+  {
+    /* [241] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
+  },
+  {
+    /* [242] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
+  },
+  {
+    /* [243] */
+    /* usage */ ParameterUsage::kDdx,
+    /* matcher indices */ &kMatcherIndices[103],
+  },
+  {
+    /* [244] */
+    /* usage */ ParameterUsage::kDdy,
+    /* matcher indices */ &kMatcherIndices[103],
+  },
+  {
+    /* [245] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[193],
+  },
+  {
+    /* [246] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[192],
+  },
+  {
+    /* [247] */
     /* usage */ ParameterUsage::kCoords,
     /* matcher indices */ &kMatcherIndices[121],
   },
   {
-    /* [241] */
-    /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
-  },
-  {
-    /* [242] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[147],
-  },
-  {
-    /* [243] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
-  },
-  {
-    /* [244] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
-  },
-  {
-    /* [245] */
-    /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
-  },
-  {
-    /* [246] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[147],
-  },
-  {
-    /* [247] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
-  },
-  {
     /* [248] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [249] */
     /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [250] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[68],
+    /* matcher indices */ &kMatcherIndices[185],
   },
   {
     /* [251] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [252] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [253] */
-    /* usage */ ParameterUsage::kValue,
-    /* matcher indices */ &kMatcherIndices[109],
+    /* usage */ ParameterUsage::kBias,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [254] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[145],
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[123],
   },
   {
     /* [255] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
+    /* usage */ ParameterUsage::kComponent,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [256] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
-  },
-  {
-    /* [257] */
-    /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
-  },
-  {
-    /* [258] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[147],
-  },
-  {
-    /* [259] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
-  },
-  {
-    /* [260] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
-  },
-  {
-    /* [261] */
-    /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
-  },
-  {
-    /* [262] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[145],
-  },
-  {
-    /* [263] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[149],
-  },
-  {
-    /* [264] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
-  },
-  {
-    /* [265] */
-    /* usage */ ParameterUsage::kDepthRef,
-    /* matcher indices */ &kMatcherIndices[15],
-  },
-  {
-    /* [266] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[127],
-  },
-  {
-    /* [267] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
-  },
-  {
-    /* [268] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
-  },
-  {
-    /* [269] */
-    /* usage */ ParameterUsage::kBias,
-    /* matcher indices */ &kMatcherIndices[15],
-  },
-  {
-    /* [270] */
     /* usage */ ParameterUsage::kTexture,
     /* matcher indices */ &kMatcherIndices[131],
   },
   {
+    /* [257] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
+  },
+  {
+    /* [258] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
+  },
+  {
+    /* [259] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
+  },
+  {
+    /* [260] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[195],
+  },
+  {
+    /* [261] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[192],
+  },
+  {
+    /* [262] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
+  },
+  {
+    /* [263] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
+  },
+  {
+    /* [264] */
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [265] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[196],
+  },
+  {
+    /* [266] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[192],
+  },
+  {
+    /* [267] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
+  },
+  {
+    /* [268] */
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [269] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
+  },
+  {
+    /* [270] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[189],
+  },
+  {
     /* [271] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [272] */
@@ -3203,1928 +3892,1928 @@
   },
   {
     /* [273] */
-    /* usage */ ParameterUsage::kBias,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [274] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[147],
+    /* usage */ ParameterUsage::kBias,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [275] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[193],
   },
   {
     /* [276] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[192],
   },
   {
     /* [277] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [278] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[127],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [279] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [280] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[196],
   },
   {
     /* [281] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[192],
   },
   {
     /* [282] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[145],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [283] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [284] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [285] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[195],
   },
   {
     /* [286] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[144],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[192],
   },
   {
     /* [287] */
     /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [288] */
     /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [289] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [290] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[146],
+    /* matcher indices */ &kMatcherIndices[181],
   },
   {
     /* [291] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [292] */
     /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [293] */
     /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [294] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[111],
+    /* usage */ ParameterUsage::kBias,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [295] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[194],
   },
   {
     /* [296] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[192],
   },
   {
     /* [297] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [298] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[144],
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [299] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[196],
   },
   {
     /* [300] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[192],
   },
   {
     /* [301] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [302] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[147],
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [303] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[196],
   },
   {
     /* [304] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[192],
   },
   {
     /* [305] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [306] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[83],
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [307] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[187],
   },
   {
     /* [308] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [309] */
-    /* usage */ ParameterUsage::kValue,
-    /* matcher indices */ &kMatcherIndices[101],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [310] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kBias,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [311] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[194],
   },
   {
     /* [312] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[1],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[192],
   },
   {
     /* [313] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[1],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [314] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[123],
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [315] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[185],
   },
   {
     /* [316] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [317] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
-  },
-  {
-    /* [318] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[131],
-  },
-  {
-    /* [319] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
-  },
-  {
-    /* [320] */
     /* usage */ ParameterUsage::kCoords,
     /* matcher indices */ &kMatcherIndices[121],
   },
   {
+    /* [318] */
+    /* usage */ ParameterUsage::kBias,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [319] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[179],
+  },
+  {
+    /* [320] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
+  },
+  {
     /* [321] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[95],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [322] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[86],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [323] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[99],
-  },
-  {
-    /* [324] */
-    /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
-  },
-  {
-    /* [325] */
-    /* usage */ ParameterUsage::kValue,
-    /* matcher indices */ &kMatcherIndices[97],
-  },
-  {
-    /* [326] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[139],
-  },
-  {
-    /* [327] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
-  },
-  {
-    /* [328] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
-  },
-  {
-    /* [329] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[15],
-  },
-  {
-    /* [330] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[139],
-  },
-  {
-    /* [331] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
-  },
-  {
-    /* [332] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
-  },
-  {
-    /* [333] */
-    /* usage */ ParameterUsage::kOffset,
-    /* matcher indices */ &kMatcherIndices[99],
-  },
-  {
-    /* [334] */
     /* usage */ ParameterUsage::kTexture,
     /* matcher indices */ &kMatcherIndices[133],
   },
   {
-    /* [335] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
-  },
-  {
-    /* [336] */
+    /* [324] */
     /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
-    /* [337] */
+    /* [325] */
     /* usage */ ParameterUsage::kArrayIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
-    /* [338] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* [326] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
-    /* [339] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
-  },
-  {
-    /* [340] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[1],
-  },
-  {
-    /* [341] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[1],
-  },
-  {
-    /* [342] */
+    /* [327] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[131],
+    /* matcher indices */ &kMatcherIndices[185],
   },
   {
-    /* [343] */
+    /* [328] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
-    /* [344] */
+    /* [329] */
     /* usage */ ParameterUsage::kCoords,
     /* matcher indices */ &kMatcherIndices[121],
   },
   {
-    /* [345] */
+    /* [330] */
     /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [331] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[179],
+  },
+  {
+    /* [332] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
+  },
+  {
+    /* [333] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
+  },
+  {
+    /* [334] */
+    /* usage */ ParameterUsage::kBias,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [335] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[193],
+  },
+  {
+    /* [336] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
+  },
+  {
+    /* [337] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
+  },
+  {
+    /* [338] */
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
+  },
+  {
+    /* [339] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[187],
+  },
+  {
+    /* [340] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
+  },
+  {
+    /* [341] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
+  },
+  {
+    /* [342] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [343] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[195],
+  },
+  {
+    /* [344] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
+  },
+  {
+    /* [345] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [346] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[139],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [347] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[196],
   },
   {
     /* [348] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [349] */
-    /* usage */ ParameterUsage::kBias,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [350] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[74],
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [351] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[189],
   },
   {
     /* [352] */
-    /* usage */ ParameterUsage::kValue,
-    /* matcher indices */ &kMatcherIndices[97],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [353] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[2],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [354] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [355] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[185],
   },
   {
     /* [356] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [357] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [358] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[123],
   },
   {
     /* [359] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kComponent,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [360] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[131],
   },
   {
     /* [361] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [362] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [363] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[181],
   },
   {
     /* [364] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [365] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [366] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[1],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [367] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[1],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[179],
   },
   {
     /* [368] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [369] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[1],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [370] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[1],
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [371] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[147],
+    /* matcher indices */ &kMatcherIndices[196],
   },
   {
     /* [372] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [373] */
     /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [374] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[145],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [375] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[194],
   },
   {
     /* [376] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[192],
   },
   {
     /* [377] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[131],
-  },
-  {
-    /* [378] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
-  },
-  {
-    /* [379] */
     /* usage */ ParameterUsage::kCoords,
     /* matcher indices */ &kMatcherIndices[121],
   },
   {
+    /* [378] */
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [379] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[194],
+  },
+  {
     /* [380] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [381] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [382] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [383] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[88],
   },
   {
     /* [384] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [385] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [386] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[148],
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[45],
   },
   {
     /* [387] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[63],
   },
   {
     /* [388] */
-    /* usage */ ParameterUsage::kSampleIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [389] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [390] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[57],
   },
   {
     /* [391] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[196],
   },
   {
     /* [392] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[192],
   },
   {
     /* [393] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [394] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kDepthRef,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [395] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[193],
   },
   {
     /* [396] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [397] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [398] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [399] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[47],
   },
   {
     /* [400] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [401] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [402] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[61],
   },
   {
     /* [403] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [404] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [405] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[62],
   },
   {
     /* [406] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[62],
   },
   {
     /* [407] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[195],
   },
   {
     /* [408] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [409] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [410] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[147],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [411] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[195],
   },
   {
     /* [412] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [413] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[119],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [414] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kArrayIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [415] */
-    /* usage */ ParameterUsage::kSampleIndex,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[196],
   },
   {
     /* [416] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[117],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [417] */
     /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[95],
-  },
-  {
-    /* [418] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
-  },
-  {
-    /* [419] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[145],
-  },
-  {
-    /* [420] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
-  },
-  {
-    /* [421] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
-  },
-  {
-    /* [422] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[107],
-  },
-  {
-    /* [423] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[99],
-  },
-  {
-    /* [424] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
-  },
-  {
-    /* [425] */
-    /* usage */ ParameterUsage::kTexture,
     /* matcher indices */ &kMatcherIndices[103],
   },
   {
-    /* [426] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* [418] */
+    /* usage */ ParameterUsage::kOffset,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
-    /* [427] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* [419] */
+    /* usage */ ParameterUsage::kX,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
-    /* [428] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[80],
+    /* [420] */
+    /* usage */ ParameterUsage::kY,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
-    /* [429] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[95],
+    /* [421] */
+    /* usage */ ParameterUsage::kZ,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
-    /* [430] */
-    /* usage */ ParameterUsage::kValue,
-    /* matcher indices */ &kMatcherIndices[101],
+    /* [422] */
+    /* usage */ ParameterUsage::kW,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
-    /* [431] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[147],
+    /* [423] */
+    /* usage */ ParameterUsage::kComponent,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
-    /* [432] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
-  },
-  {
-    /* [433] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
-  },
-  {
-    /* [434] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[127],
-  },
-  {
-    /* [435] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
-  },
-  {
-    /* [436] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[121],
-  },
-  {
-    /* [437] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[150],
-  },
-  {
-    /* [438] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
-  },
-  {
-    /* [439] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
-  },
-  {
-    /* [440] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[89],
-  },
-  {
-    /* [441] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[99],
-  },
-  {
-    /* [442] */
-    /* usage */ ParameterUsage::kValue,
-    /* matcher indices */ &kMatcherIndices[101],
-  },
-  {
-    /* [443] */
+    /* [424] */
     /* usage */ ParameterUsage::kTexture,
     /* matcher indices */ &kMatcherIndices[141],
   },
   {
-    /* [444] */
+    /* [425] */
     /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
-    /* [445] */
+    /* [426] */
     /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
-    /* [446] */
-    /* usage */ ParameterUsage::kTexture,
+    /* [427] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [428] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [429] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [430] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [431] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[105],
+  },
+  {
+    /* [432] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[105],
+  },
+  {
+    /* [433] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[105],
+  },
+  {
+    /* [434] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[105],
+  },
+  {
+    /* [435] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[115],
+  },
+  {
+    /* [436] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[115],
+  },
+  {
+    /* [437] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[115],
+  },
+  {
+    /* [438] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[115],
+  },
+  {
+    /* [439] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [440] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [441] */
+    /* usage */ ParameterUsage::kNone,
     /* matcher indices */ &kMatcherIndices[62],
   },
   {
+    /* [442] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[62],
+  },
+  {
+    /* [443] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[49],
+  },
+  {
+    /* [444] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[49],
+  },
+  {
+    /* [445] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[49],
+  },
+  {
+    /* [446] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[49],
+  },
+  {
     /* [447] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[196],
   },
   {
     /* [448] */
-    /* usage */ ParameterUsage::kValue,
-    /* matcher indices */ &kMatcherIndices[109],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [449] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [450] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [451] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [452] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[0],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [453] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[95],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [454] */
-    /* usage */ ParameterUsage::kValue,
-    /* matcher indices */ &kMatcherIndices[97],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [455] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[139],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [456] */
-    /* usage */ ParameterUsage::kSampler,
-    /* matcher indices */ &kMatcherIndices[143],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[197],
   },
   {
     /* [457] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [458] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[77],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [459] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [460] */
-    /* usage */ ParameterUsage::kValue,
-    /* matcher indices */ &kMatcherIndices[97],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [461] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[65],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [462] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [463] */
-    /* usage */ ParameterUsage::kValue,
-    /* matcher indices */ &kMatcherIndices[109],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [464] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [465] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [466] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[18],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [467] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [468] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[49],
   },
   {
     /* [469] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[18],
+    /* matcher indices */ &kMatcherIndices[49],
   },
   {
     /* [470] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[49],
   },
   {
     /* [471] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[115],
   },
   {
     /* [472] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[35],
+    /* matcher indices */ &kMatcherIndices[115],
   },
   {
     /* [473] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[71],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[115],
   },
   {
     /* [474] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[95],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[105],
   },
   {
     /* [475] */
-    /* usage */ ParameterUsage::kValue,
-    /* matcher indices */ &kMatcherIndices[109],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[105],
   },
   {
     /* [476] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[92],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[105],
   },
   {
     /* [477] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[94],
   },
   {
     /* [478] */
-    /* usage */ ParameterUsage::kValue,
-    /* matcher indices */ &kMatcherIndices[101],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [479] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[45],
   },
   {
     /* [480] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[59],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[91],
   },
   {
     /* [481] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [482] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[45],
   },
   {
     /* [483] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[73],
   },
   {
     /* [484] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[123],
   },
   {
     /* [485] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[45],
   },
   {
     /* [486] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[70],
   },
   {
     /* [487] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [488] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[57],
   },
   {
     /* [489] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[67],
   },
   {
     /* [490] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [491] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[57],
   },
   {
     /* [492] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[59],
   },
   {
     /* [493] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[150],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[123],
   },
   {
     /* [494] */
-    /* usage */ ParameterUsage::kCoords,
-    /* matcher indices */ &kMatcherIndices[99],
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[57],
   },
   {
     /* [495] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[2],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [496] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[62],
   },
   {
     /* [497] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[2],
+    /* matcher indices */ &kMatcherIndices[62],
   },
   {
     /* [498] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [499] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[62],
   },
   {
     /* [500] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[62],
   },
   {
     /* [501] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kX,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [502] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kY,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [503] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[2],
+    /* usage */ ParameterUsage::kZw,
+    /* matcher indices */ &kMatcherIndices[105],
   },
   {
     /* [504] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [505] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[2],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [506] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [507] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [508] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [509] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [510] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[56],
+    /* usage */ ParameterUsage::kX,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [511] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[2],
+    /* usage */ ParameterUsage::kYz,
+    /* matcher indices */ &kMatcherIndices[105],
   },
   {
     /* [512] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kW,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [513] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[2],
+    /* usage */ ParameterUsage::kXy,
+    /* matcher indices */ &kMatcherIndices[105],
   },
   {
     /* [514] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kZ,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [515] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[2],
+    /* usage */ ParameterUsage::kW,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [516] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[55],
   },
   {
     /* [517] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[2],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [518] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[61],
   },
   {
     /* [519] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[2],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[51],
   },
   {
     /* [520] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [521] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[61],
   },
   {
     /* [522] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [523] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [524] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[21],
   },
   {
     /* [525] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [526] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [527] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[21],
   },
   {
     /* [528] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [529] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[16],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [530] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[16],
+    /* matcher indices */ &kMatcherIndices[40],
   },
   {
     /* [531] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kX,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [532] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kY,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [533] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[103],
+    /* usage */ ParameterUsage::kZ,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [534] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[194],
   },
   {
     /* [535] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [536] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [537] */
     /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[107],
+    /* matcher indices */ &kMatcherIndices[43],
   },
   {
     /* [538] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[123],
   },
   {
     /* [539] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kValue,
+    /* matcher indices */ &kMatcherIndices[61],
   },
   {
     /* [540] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
-  },
-  {
-    /* [541] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[111],
-  },
-  {
-    /* [542] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
-  },
-  {
-    /* [543] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
-  },
-  {
-    /* [544] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
-  },
-  {
-    /* [545] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[117],
-  },
-  {
-    /* [546] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
-  },
-  {
-    /* [547] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[16],
-  },
-  {
-    /* [548] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[16],
-  },
-  {
-    /* [549] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[125],
-  },
-  {
-    /* [550] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
-  },
-  {
-    /* [551] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
-  },
-  {
-    /* [552] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
-  },
-  {
-    /* [553] */
     /* usage */ ParameterUsage::kTexture,
     /* matcher indices */ &kMatcherIndices[129],
   },
   {
-    /* [554] */
+    /* [541] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[44],
+  },
+  {
+    /* [542] */
     /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* matcher indices */ &kMatcherIndices[44],
+  },
+  {
+    /* [543] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[131],
+  },
+  {
+    /* [544] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[109],
+  },
+  {
+    /* [545] */
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
+  },
+  {
+    /* [546] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[196],
+  },
+  {
+    /* [547] */
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
+  },
+  {
+    /* [548] */
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
+  },
+  {
+    /* [549] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [550] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [551] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [552] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [553] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [554] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [555] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [556] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [557] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [558] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [559] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[147],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [560] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [561] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [562] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[16],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [563] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[144],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [564] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[187],
   },
   {
     /* [565] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[16],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [566] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [567] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[145],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [568] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [569] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[16],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [570] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[185],
   },
   {
     /* [571] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[146],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [572] */
-    /* usage */ ParameterUsage::kLevel,
-    /* matcher indices */ &kMatcherIndices[58],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [573] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[47],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[139],
   },
   {
     /* [574] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[16],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[123],
   },
   {
     /* [575] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[24],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [576] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[20],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[145],
   },
   {
     /* [577] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [578] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kSampleIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [579] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[196],
   },
   {
     /* [580] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [581] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [582] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[179],
   },
   {
     /* [583] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [584] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[103],
   },
   {
     /* [585] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[177],
   },
   {
     /* [586] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [587] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [588] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[198],
   },
   {
     /* [589] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [590] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kSampleIndex,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [591] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[0],
   },
   {
     /* [592] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [593] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [594] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[194],
   },
   {
     /* [595] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[1],
+    /* usage */ ParameterUsage::kSampler,
+    /* matcher indices */ &kMatcherIndices[191],
   },
   {
     /* [596] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[1],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [597] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[1],
+    /* matcher indices */ &kMatcherIndices[62],
   },
   {
     /* [598] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[1],
+    /* matcher indices */ &kMatcherIndices[62],
   },
   {
     /* [599] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [600] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [601] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [602] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [603] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[21],
   },
   {
     /* [604] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[21],
   },
   {
     /* [605] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[21],
   },
   {
     /* [606] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[21],
   },
   {
     /* [607] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [608] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [609] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[18],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [610] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[18],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [611] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[129],
   },
   {
     /* [612] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[121],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [613] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[35],
+    /* matcher indices */ &kMatcherIndices[40],
   },
   {
     /* [614] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[35],
+    /* matcher indices */ &kMatcherIndices[40],
   },
   {
     /* [615] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[131],
   },
   {
     /* [616] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [617] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[18],
+    /* matcher indices */ &kMatcherIndices[21],
   },
   {
     /* [618] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[18],
+    /* matcher indices */ &kMatcherIndices[21],
   },
   {
     /* [619] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[35],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[133],
   },
   {
     /* [620] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[35],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [621] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [622] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [623] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[139],
   },
   {
     /* [624] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [625] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[18],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [626] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[18],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [627] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[18],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[141],
   },
   {
     /* [628] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[18],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [629] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[40],
   },
   {
     /* [630] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[40],
   },
   {
     /* [631] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[143],
   },
   {
     /* [632] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [633] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[21],
   },
   {
     /* [634] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[21],
   },
   {
     /* [635] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [636] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [637] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[196],
   },
   {
     /* [638] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [639] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [640] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [641] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[195],
   },
   {
     /* [642] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [643] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [644] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [645] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[194],
   },
   {
     /* [646] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [647] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [648] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [649] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[193],
   },
   {
     /* [650] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kLevel,
+    /* matcher indices */ &kMatcherIndices[44],
   },
   {
     /* [651] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [652] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [653] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [654] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [655] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [656] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [657] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [658] */
@@ -5134,17 +5823,17 @@
   {
     /* [659] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [660] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[59],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [661] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [662] */
@@ -5154,212 +5843,212 @@
   {
     /* [663] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[19],
   },
   {
     /* [664] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[23],
   },
   {
     /* [665] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[76],
   },
   {
     /* [666] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[11],
   },
   {
     /* [667] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[148],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[11],
   },
   {
     /* [668] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[119],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [669] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[146],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[11],
   },
   {
     /* [670] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[145],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [671] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[144],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [672] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[147],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[11],
   },
   {
     /* [673] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[129],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [674] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[125],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [675] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[117],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [676] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[111],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [677] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[107],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [678] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[16],
-  },
-  {
-    /* [679] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[103],
-  },
-  {
-    /* [680] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[41],
-  },
-  {
-    /* [681] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[146],
-  },
-  {
-    /* [682] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[144],
-  },
-  {
-    /* [683] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[129],
-  },
-  {
-    /* [684] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[111],
-  },
-  {
-    /* [685] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[150],
-  },
-  {
-    /* [686] */
-    /* usage */ ParameterUsage::kTexture,
     /* matcher indices */ &kMatcherIndices[44],
   },
   {
+    /* [679] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
+  },
+  {
+    /* [680] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [681] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
+  },
+  {
+    /* [682] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
+  },
+  {
+    /* [683] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
+  },
+  {
+    /* [684] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
+  },
+  {
+    /* [685] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [686] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
     /* [687] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[41],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[11],
   },
   {
     /* [688] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[50],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[11],
   },
   {
     /* [689] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[53],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [690] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[148],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [691] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[146],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [692] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[145],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [693] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[144],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [694] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[147],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [695] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[119],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [696] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[129],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [697] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[125],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[11],
   },
   {
     /* [698] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[117],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[11],
   },
   {
     /* [699] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[111],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [700] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[107],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [701] */
-    /* usage */ ParameterUsage::kTexture,
-    /* matcher indices */ &kMatcherIndices[103],
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [702] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [703] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[1],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [704] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[1],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [705] */
@@ -5379,544 +6068,1519 @@
   {
     /* [708] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [709] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[0],
   },
   {
     /* [710] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [711] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[0],
   },
   {
     /* [712] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [713] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[0],
   },
   {
     /* [714] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [715] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[0],
   },
   {
     /* [716] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [717] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[0],
   },
   {
     /* [718] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [719] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[0],
   },
   {
     /* [720] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [721] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[0],
   },
   {
     /* [722] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [723] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[0],
   },
   {
     /* [724] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [725] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[0],
   },
   {
     /* [726] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [727] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[197],
   },
   {
     /* [728] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kCoords,
+    /* matcher indices */ &kMatcherIndices[109],
   },
   {
     /* [729] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[109],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [730] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[109],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [731] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [732] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [733] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[113],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [734] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [735] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [736] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [737] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [738] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [739] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [740] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[2],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [741] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [742] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [743] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [744] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [745] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [746] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [747] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [748] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [749] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [750] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [751] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[18],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [752] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[35],
+    /* matcher indices */ &kMatcherIndices[62],
   },
   {
     /* [753] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [754] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[100],
   },
   {
     /* [755] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [756] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[62],
   },
   {
     /* [757] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [758] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[100],
   },
   {
     /* [759] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kX,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [760] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kY,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [761] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [762] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [763] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kXy,
+    /* matcher indices */ &kMatcherIndices[105],
   },
   {
     /* [764] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kZ,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [765] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* usage */ ParameterUsage::kX,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [766] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* usage */ ParameterUsage::kYz,
+    /* matcher indices */ &kMatcherIndices[105],
   },
   {
     /* [767] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [768] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [769] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kXy,
+    /* matcher indices */ &kMatcherIndices[105],
   },
   {
     /* [770] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kZw,
+    /* matcher indices */ &kMatcherIndices[105],
   },
   {
     /* [771] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [772] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [773] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [774] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [775] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kXyz,
+    /* matcher indices */ &kMatcherIndices[115],
   },
   {
     /* [776] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* usage */ ParameterUsage::kW,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [777] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kX,
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [778] */
-    /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* usage */ ParameterUsage::kZyw,
+    /* matcher indices */ &kMatcherIndices[115],
   },
   {
     /* [779] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[105],
   },
   {
     /* [780] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[105],
   },
   {
     /* [781] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[115],
   },
   {
     /* [782] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[115],
   },
   {
     /* [783] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[49],
   },
   {
     /* [784] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[12],
+    /* matcher indices */ &kMatcherIndices[49],
   },
   {
     /* [785] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [786] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [787] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [788] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[1],
   },
   {
     /* [789] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [790] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [791] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[38],
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [792] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[3],
+    /* matcher indices */ &kMatcherIndices[121],
   },
   {
     /* [793] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [794] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [795] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [796] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [797] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [798] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[37],
   },
   {
     /* [799] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[62],
   },
   {
     /* [800] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[62],
   },
   {
     /* [801] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [802] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[15],
+    /* matcher indices */ &kMatcherIndices[97],
   },
   {
     /* [803] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[7],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [804] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[35],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [805] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[18],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [806] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[35],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [807] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[18],
+    /* matcher indices */ &kMatcherIndices[5],
   },
   {
     /* [808] */
     /* usage */ ParameterUsage::kNone,
-    /* matcher indices */ &kMatcherIndices[32],
+    /* matcher indices */ &kMatcherIndices[31],
   },
   {
     /* [809] */
     /* usage */ ParameterUsage::kNone,
     /* matcher indices */ &kMatcherIndices[15],
   },
+  {
+    /* [810] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [811] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [812] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [813] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
+  },
+  {
+    /* [814] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [815] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
+  },
+  {
+    /* [816] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [817] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
+  },
+  {
+    /* [818] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [819] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [820] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [821] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [822] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [823] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [824] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [825] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [826] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [827] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [828] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [829] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [830] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [831] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [832] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [833] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [834] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [835] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
+  },
+  {
+    /* [836] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [837] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
+  },
+  {
+    /* [838] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [839] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [840] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[34],
+  },
+  {
+    /* [841] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [842] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [843] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [844] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[198],
+  },
+  {
+    /* [845] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[145],
+  },
+  {
+    /* [846] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[193],
+  },
+  {
+    /* [847] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[0],
+  },
+  {
+    /* [848] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[194],
+  },
+  {
+    /* [849] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[195],
+  },
+  {
+    /* [850] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[196],
+  },
+  {
+    /* [851] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[143],
+  },
+  {
+    /* [852] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[141],
+  },
+  {
+    /* [853] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[139],
+  },
+  {
+    /* [854] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[133],
+  },
+  {
+    /* [855] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[131],
+  },
+  {
+    /* [856] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[129],
+  },
+  {
+    /* [857] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[34],
+  },
+  {
+    /* [858] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[21],
+  },
+  {
+    /* [859] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[40],
+  },
+  {
+    /* [860] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [861] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
+  },
+  {
+    /* [862] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [863] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
+  },
+  {
+    /* [864] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[193],
+  },
+  {
+    /* [865] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[195],
+  },
+  {
+    /* [866] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[143],
+  },
+  {
+    /* [867] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[133],
+  },
+  {
+    /* [868] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [869] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [870] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [871] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [872] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [873] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [874] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [875] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [876] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [877] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [878] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [879] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [880] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [881] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [882] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [883] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[197],
+  },
+  {
+    /* [884] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[79],
+  },
+  {
+    /* [885] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [886] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[82],
+  },
+  {
+    /* [887] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[85],
+  },
+  {
+    /* [888] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[198],
+  },
+  {
+    /* [889] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[193],
+  },
+  {
+    /* [890] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[194],
+  },
+  {
+    /* [891] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[195],
+  },
+  {
+    /* [892] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[196],
+  },
+  {
+    /* [893] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[145],
+  },
+  {
+    /* [894] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[143],
+  },
+  {
+    /* [895] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[141],
+  },
+  {
+    /* [896] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[139],
+  },
+  {
+    /* [897] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[133],
+  },
+  {
+    /* [898] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[131],
+  },
+  {
+    /* [899] */
+    /* usage */ ParameterUsage::kTexture,
+    /* matcher indices */ &kMatcherIndices[129],
+  },
+  {
+    /* [900] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[37],
+  },
+  {
+    /* [901] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[62],
+  },
+  {
+    /* [902] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[62],
+  },
+  {
+    /* [903] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[62],
+  },
+  {
+    /* [904] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[62],
+  },
+  {
+    /* [905] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [906] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [907] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [908] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[11],
+  },
+  {
+    /* [909] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [910] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [911] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [912] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [913] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [914] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [915] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [916] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [917] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [918] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [919] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[183],
+  },
+  {
+    /* [920] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[44],
+  },
+  {
+    /* [921] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [922] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [923] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[62],
+  },
+  {
+    /* [924] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [925] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [926] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [927] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [928] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [929] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[21],
+  },
+  {
+    /* [930] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [931] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[173],
+  },
+  {
+    /* [932] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[105],
+  },
+  {
+    /* [933] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [934] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [935] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[107],
+  },
+  {
+    /* [936] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[107],
+  },
+  {
+    /* [937] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[107],
+  },
+  {
+    /* [938] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[107],
+  },
+  {
+    /* [939] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[21],
+  },
+  {
+    /* [940] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[115],
+  },
+  {
+    /* [941] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[1],
+  },
+  {
+    /* [942] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [943] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[31],
+  },
+  {
+    /* [944] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[5],
+  },
+  {
+    /* [945] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[119],
+  },
+  {
+    /* [946] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[119],
+  },
+  {
+    /* [947] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[119],
+  },
+  {
+    /* [948] */
+    /* usage */ ParameterUsage::kNone,
+    /* matcher indices */ &kMatcherIndices[119],
+  },
+  {
+    /* [949] */
+    /* usage */ ParameterUsage::kNone,