Validate a subtype exists before decoding a type.

In the IR decoder we may attempt to create a `TexelBuffer` ro
`StorageTexture` based on a given texel format. That format may not be
valid for creating the necessary subtype. Validate in the decoder before
attempting to create the type.

Fixed: 441827896
Change-Id: I4ca3901319659d91fea1790f0dd35aec8fa72daf
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/260436
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
Auto-Submit: dan sinclair <dsinclair@chromium.org>
Commit-Queue: James Price <jrprice@google.com>
diff --git a/src/tint/lang/core/ir/binary/decode.cc b/src/tint/lang/core/ir/binary/decode.cc
index c072019..d895900 100644
--- a/src/tint/lang/core/ir/binary/decode.cc
+++ b/src/tint/lang/core/ir/binary/decode.cc
@@ -935,15 +935,27 @@
         return mod_out_.Types().depth_multisampled_texture(dimension);
     }
 
-    const type::StorageTexture* CreateTypeStorageTexture(const pb::TypeStorageTexture& texture_in) {
+    const type::Type* CreateTypeStorageTexture(const pb::TypeStorageTexture& texture_in) {
         auto dimension = TextureDimension(texture_in.dimension());
         auto texel_format = TexelFormat(texture_in.texel_format());
+        auto sub_ty = mod_out_.Types().SubtypeFor(texel_format);
+        if (!sub_ty) {
+            err_ << "unable to create a sub-type for " << texel_format << "\n";
+            return mod_out_.Types().invalid();
+        }
+
         auto access = AccessControl(texture_in.access());
         return mod_out_.Types().storage_texture(dimension, texel_format, access);
     }
 
-    const type::TexelBuffer* CreateTypeTexelBuffer(const pb::TypeTexelBuffer& buffer_in) {
+    const type::Type* CreateTypeTexelBuffer(const pb::TypeTexelBuffer& buffer_in) {
         auto texel_format = TexelFormat(buffer_in.texel_format());
+        auto sub_ty = mod_out_.Types().SubtypeFor(texel_format);
+        if (!sub_ty) {
+            err_ << "unable to create a sub-type for " << texel_format << "\n";
+            return mod_out_.Types().invalid();
+        }
+
         auto access = AccessControl(buffer_in.access());
         return mod_out_.Types().texel_buffer(texel_format, access);
     }
diff --git a/src/tint/lang/core/type/manager.cc b/src/tint/lang/core/type/manager.cc
index 65ce11c..7a2a843 100644
--- a/src/tint/lang/core/type/manager.cc
+++ b/src/tint/lang/core/type/manager.cc
@@ -54,9 +54,16 @@
 #include "src/tint/utils/macros/compiler.h"
 
 namespace tint::core::type {
-namespace {
 
-const Type* SubtypeFor(core::TexelFormat format, Manager& type_mgr) {
+Manager::Manager() = default;
+
+Manager::Manager(Manager&&) = default;
+
+Manager& Manager::operator=(Manager&& rhs) = default;
+
+Manager::~Manager() = default;
+
+const Type* Manager::SubtypeFor(core::TexelFormat format) {
     switch (format) {
         case core::TexelFormat::kR8Uint:
         case core::TexelFormat::kRg8Uint:
@@ -68,7 +75,7 @@
         case core::TexelFormat::kRg32Uint:
         case core::TexelFormat::kRgba32Uint:
         case core::TexelFormat::kRgb10A2Uint: {
-            return type_mgr.u32();
+            return u32();
         }
 
         case core::TexelFormat::kR8Sint:
@@ -80,7 +87,7 @@
         case core::TexelFormat::kR32Sint:
         case core::TexelFormat::kRg32Sint:
         case core::TexelFormat::kRgba32Sint: {
-            return type_mgr.i32();
+            return i32();
         }
 
         case core::TexelFormat::kR8Unorm:
@@ -104,7 +111,7 @@
         case core::TexelFormat::kRgba32Float:
         case core::TexelFormat::kRgb10A2Unorm:
         case core::TexelFormat::kRg11B10Ufloat: {
-            return type_mgr.f32();
+            return f32();
         }
 
         case core::TexelFormat::kUndefined:
@@ -114,16 +121,6 @@
     return nullptr;
 }
 
-}  // namespace
-
-Manager::Manager() = default;
-
-Manager::Manager(Manager&&) = default;
-
-Manager& Manager::operator=(Manager&& rhs) = default;
-
-Manager::~Manager() = default;
-
 const core::type::Invalid* Manager::invalid() {
     return Get<core::type::Invalid>();
 }
@@ -228,13 +225,13 @@
 const core::type::StorageTexture* Manager::storage_texture(TextureDimension dim,
                                                            core::TexelFormat format,
                                                            core::Access access) {
-    const auto* subtype = SubtypeFor(format, *this);
+    const auto* subtype = SubtypeFor(format);
     return Get<core::type::StorageTexture>(dim, format, access, subtype);
 }
 
 const core::type::TexelBuffer* Manager::texel_buffer(core::TexelFormat format,
                                                      core::Access access) {
-    const auto* subtype = SubtypeFor(format, *this);
+    const auto* subtype = SubtypeFor(format);
     return Get<core::type::TexelBuffer>(format, access, subtype);
 }
 
diff --git a/src/tint/lang/core/type/manager.h b/src/tint/lang/core/type/manager.h
index 42551b7..749a571 100644
--- a/src/tint/lang/core/type/manager.h
+++ b/src/tint/lang/core/type/manager.h
@@ -197,6 +197,9 @@
         return types_.Find<TYPE>(std::forward<ARGS>(args)...);
     }
 
+    /// @returns the subtype for a given `format`
+    const Type* SubtypeFor(core::TexelFormat format);
+
     /// @returns an invalid type
     const core::type::Invalid* invalid();