CanCreateTensorWithShape moved into TensorDescriptor.

PiperOrigin-RevId: 431424284
diff --git a/tensorflow/lite/delegates/gpu/common/gpu_model.cc b/tensorflow/lite/delegates/gpu/common/gpu_model.cc
index 34195f0..b018835 100644
--- a/tensorflow/lite/delegates/gpu/common/gpu_model.cc
+++ b/tensorflow/lite/delegates/gpu/common/gpu_model.cc
@@ -162,7 +162,7 @@
   if (!has_batch && shape.b != 1) {
     return absl::InvalidArgumentError("Wrong layout, batch mismatch.");
   }
-  if (!CanCreateTensorWithShape(gpu_info, shape, tensor_desc).ok()) {
+  if (!tensor_desc.CanCreateTensorWithShape(gpu_info, shape).ok()) {
     return absl::UnavailableError(
         "Current device can not allocate tensor with this shape for "
         "predefined/external descriptor.");
@@ -241,10 +241,9 @@
           storage_type == TensorStorageType::TEXTURE_ARRAY;
       if (graph.IsGraphInput(t->id) || graph.IsGraphOutput(t->id)) {
         if (shape.c < 4 && can_use_single_texture &&
-            CanCreateTensorWithShape(
-                gpu_info, shape,
-                TensorDescriptor{data_type,
-                                 TensorStorageType::SINGLE_TEXTURE_2D, layout})
+            TensorDescriptor{data_type, TensorStorageType::SINGLE_TEXTURE_2D,
+                             layout}
+                .CanCreateTensorWithShape(gpu_info, shape)
                 .ok()) {
           storage_type = TensorStorageType::SINGLE_TEXTURE_2D;
         }
diff --git a/tensorflow/lite/delegates/gpu/common/task/storage_type_util.cc b/tensorflow/lite/delegates/gpu/common/task/storage_type_util.cc
index 1572070..f233608 100644
--- a/tensorflow/lite/delegates/gpu/common/task/storage_type_util.cc
+++ b/tensorflow/lite/delegates/gpu/common/task/storage_type_util.cc
@@ -26,227 +26,50 @@
 namespace tflite {
 namespace gpu {
 
-absl::Status CanCreateTensorWithShape(const GpuInfo& gpu_info,
-                                      const BHWDC& shape,
-                                      const TensorDescriptor& descriptor) {
-  const int slices = DivideRoundUp(shape.c, 4);
-  const uint64_t flt_size = descriptor.data_type == DataType::FLOAT32 ? 4 : 2;
-  const uint64_t channels =
-      descriptor.storage_type == TensorStorageType::SINGLE_TEXTURE_2D
-          ? shape.c
-          : slices * 4;
-  const uint64_t allocation_size =
-      flt_size * channels * shape.b * shape.w * shape.h * shape.d;
-  const std::string common_desc = "Shape - " + ToString(shape) +
-                                  ", data type - " +
-                                  ToString(descriptor.data_type) + ".";
-  if (allocation_size > gpu_info.GetMaxMemoryAllocationSize()) {
-    return absl::ResourceExhaustedError(absl::StrCat(
-        "Requested allocation size - ", allocation_size,
-        " bytes. Max allocation size for this GPU - ",
-        gpu_info.GetMaxMemoryAllocationSize(), " bytes. ", common_desc));
-  }
-  switch (descriptor.storage_type) {
-    case TensorStorageType::BUFFER: {
-      const uint64_t flt4_size =
-          4 * (descriptor.data_type == DataType::FLOAT32 ? 4 : 2);
-      const uint64_t buffer_size =
-          flt4_size * shape.b * shape.w * shape.h * shape.d * slices;
-      if (buffer_size > gpu_info.GetMaxBufferSize()) {
-        return absl::ResourceExhaustedError(absl::StrCat(
-            "Buffer with size - ", buffer_size,
-            " bytes can not be created. Max buffer size for this GPU - ",
-            gpu_info.GetMaxBufferSize(), " bytes. ", common_desc));
-      } else {
-        return absl::OkStatus();
-      }
-    }
-    case TensorStorageType::IMAGE_BUFFER: {
-      const uint64_t flt4_size =
-          4 * (descriptor.data_type == DataType::FLOAT32 ? 4 : 2);
-      const uint64_t buffer_size =
-          flt4_size * shape.b * shape.w * shape.h * shape.d * slices;
-      const uint64_t image_width = buffer_size / flt4_size;
-      if (image_width > gpu_info.GetMaxImageBufferWidth()) {
-        return absl::ResourceExhaustedError(absl::StrCat(
-            "Image buffer with width - ", image_width,
-            " can not be created. Max image buffer width for this GPU - ",
-            gpu_info.GetMaxImageBufferWidth(), ". ", common_desc));
-      } else if (buffer_size > gpu_info.GetMaxBufferSize()) {
-        return absl::ResourceExhaustedError(absl::StrCat(
-            "Buffer with size - ", buffer_size,
-            " bytes can not be created. Max buffer size for this GPU - ",
-            gpu_info.GetMaxBufferSize(), " bytes. ", common_desc));
-      } else {
-        return absl::OkStatus();
-      }
-    }
-    case TensorStorageType::TEXTURE_3D: {
-      if (gpu_info.IsApiOpenCl() &&
-          gpu_info.opencl_info.cl_version < OpenClVersion::kCl1_2 &&
-          slices == 1) {
-        return absl::InternalError(
-            "clCreateImage3D (that used in CL 1.0/1.1) can not create image "
-            "with depth = 1 by specification.");
-      }
-      const int image_width = shape.w * shape.b;
-      const int image_height = shape.h;
-      const int image_depth = slices * shape.d;
-      if (image_width > gpu_info.GetMaxImage3DWidth()) {
-        return absl::ResourceExhaustedError(absl::StrCat(
-            "Image3D with width - ", image_width,
-            " can not be created. Max Image3D width for this GPU - ",
-            gpu_info.GetMaxImage3DWidth(), ". ", common_desc));
-      } else if (image_height > gpu_info.GetMaxImage3DHeight()) {
-        return absl::ResourceExhaustedError(absl::StrCat(
-            "Image3D with height - ", image_height,
-            " can not be created. Max Image3D height for this GPU - ",
-            gpu_info.GetMaxImage3DHeight(), ". ", common_desc));
-      } else if (image_depth > gpu_info.GetMaxImage3DDepth()) {
-        return absl::ResourceExhaustedError(absl::StrCat(
-            "Image3D with depth - ", image_depth,
-            " can not be created. Max Image3D depth for this GPU - ",
-            gpu_info.GetMaxImage3DDepth(), ". ", common_desc));
-      } else {
-        return absl::OkStatus();
-      }
-    }
-    case TensorStorageType::TEXTURE_ARRAY: {
-      // Bug on some Adreno. b/131099086
-      if (gpu_info.IsApiOpenCl() && slices == 1 && gpu_info.IsAdreno() &&
-          !gpu_info.adreno_info.support_one_layer_texture_array) {
-        return absl::InternalError(
-            "Image2DArray with layer = 1 works incorrect on some Adreno in "
-            "OpenCL. Can not be created.");
-      }
-      const int image_width = shape.w * shape.b;
-      const int image_height = shape.h;
-      const int image_layers = slices * shape.d;
-      if (image_width > gpu_info.GetMaxImage2DWidth()) {
-        return absl::ResourceExhaustedError(absl::StrCat(
-            "Image2DArray with width - ", image_width,
-            " can not be created. Max Image2DArray width for this GPU - ",
-            gpu_info.GetMaxImage2DWidth(), ". ", common_desc));
-      } else if (image_height > gpu_info.GetMaxImage2DHeight()) {
-        return absl::ResourceExhaustedError(absl::StrCat(
-            "Image2DArray with height - ", image_height,
-            " can not be created. Max Image2DArray height for this GPU - ",
-            gpu_info.GetMaxImage2DHeight(), ". ", common_desc));
-      } else if (image_layers > gpu_info.GetMaxImage2DArrayLayers()) {
-        return absl::ResourceExhaustedError(absl::StrCat(
-            "Image2DArray with layers - ", image_layers,
-            " can not be created. Max Image2DArray layers for this GPU - ",
-            gpu_info.GetMaxImage2DArrayLayers(), ". ", common_desc));
-      } else {
-        return absl::OkStatus();
-      }
-    }
-    case TensorStorageType::TEXTURE_2D: {
-      const int image_width = shape.w * shape.b * shape.d;
-      const int image_height = shape.h * slices;
-      if (image_width > gpu_info.GetMaxImage2DWidth()) {
-        return absl::ResourceExhaustedError(absl::StrCat(
-            "Image2D with width - ", image_width,
-            " can not be created. Max Image2D width for this GPU - ",
-            gpu_info.GetMaxImage2DWidth(), ". ", common_desc));
-      } else if (image_height > gpu_info.GetMaxImage2DHeight()) {
-        return absl::ResourceExhaustedError(absl::StrCat(
-            "Image2D with height - ", image_height,
-            " can not be created. Max Image2D height for this GPU - ",
-            gpu_info.GetMaxImage2DHeight(), ". ", common_desc));
-      } else {
-        return absl::OkStatus();
-      }
-    }
-    case TensorStorageType::SINGLE_TEXTURE_2D: {
-      const int image_width = shape.w * shape.b * shape.d;
-      const int image_height = shape.h;
-      if (shape.c > 4) {
-        return absl::ResourceExhaustedError(absl::StrCat(
-            "Image2D with channels - ", shape.c, " can not be created."));
-      } else if (!gpu_info.SupportsFloatImage2D(descriptor.data_type,
-                                                shape.c)) {
-        return absl::ResourceExhaustedError(
-            "Image2D doesn't support this pixel layout.");
-      } else if (image_width > gpu_info.GetMaxImage2DWidth()) {
-        return absl::ResourceExhaustedError(absl::StrCat(
-            "Image2D with width - ", image_width,
-            " can not be created. Max Image2D width for this GPU - ",
-            gpu_info.GetMaxImage2DWidth(), ". ", common_desc));
-      } else if (image_height > gpu_info.GetMaxImage2DHeight()) {
-        return absl::ResourceExhaustedError(absl::StrCat(
-            "Image2D with height - ", image_height,
-            " can not be created. Max Image2D height for this GPU - ",
-            gpu_info.GetMaxImage2DHeight(), ". ", common_desc));
-      } else {
-        return absl::OkStatus();
-      }
-    }
-    default:
-      return absl::UnimplementedError(
-          "Can not create resources for unknown storage type.");
-  }
-}
-
-absl::Status CanCreateTensorWithShape(const GpuInfo& gpu_info,
-                                      const BHWC& shape,
-                                      const TensorDescriptor& descriptor) {
-  const BHWDC shape5D(shape.b, shape.h, shape.w, 1, shape.c);
-  return CanCreateTensorWithShape(gpu_info, shape5D, descriptor);
-}
-
 absl::Status SelectBestStorageType(const GpuInfo& gpu_info, const BHWC& shape,
                                    TensorStorageType desired,
                                    DataType data_type, Layout layout,
                                    TensorStorageType* result) {
-  if (CanCreateTensorWithShape(gpu_info, shape,
-                               TensorDescriptor{data_type, desired, layout})
+  if (TensorDescriptor{data_type, desired, layout}
+          .CanCreateTensorWithShape(gpu_info, shape)
           .ok()) {
     *result = desired;
     return absl::OkStatus();
   }
   if (gpu_info.IsApiMetal()) {
     *result = TensorStorageType::BUFFER;
-    return CanCreateTensorWithShape(
-        gpu_info, shape,
-        TensorDescriptor{data_type, TensorStorageType::BUFFER, layout});
+    return TensorDescriptor{data_type, TensorStorageType::BUFFER, layout}
+        .CanCreateTensorWithShape(gpu_info, shape);
   }
   auto GetBestTypeAfterTexture2D = [&]() {
     if (gpu_info.SupportsImageBuffer() &&
-        CanCreateTensorWithShape(
-            gpu_info, shape,
-            TensorDescriptor{data_type, TensorStorageType::IMAGE_BUFFER,
-                             layout})
+        TensorDescriptor{data_type, TensorStorageType::IMAGE_BUFFER, layout}
+            .CanCreateTensorWithShape(gpu_info, shape)
             .ok()) {
       *result = TensorStorageType::IMAGE_BUFFER;
       return absl::OkStatus();
     } else {
       *result = TensorStorageType::BUFFER;
-      return CanCreateTensorWithShape(
-          gpu_info, shape,
-          TensorDescriptor{data_type, TensorStorageType::BUFFER, layout});
+      return TensorDescriptor{data_type, TensorStorageType::BUFFER, layout}
+          .CanCreateTensorWithShape(gpu_info, shape);
     }
   };
   auto GetBestTypeAfterTextureArray = [&]() {
     if (gpu_info.SupportsImageBuffer() &&
-        CanCreateTensorWithShape(
-            gpu_info, shape,
-            TensorDescriptor{data_type, TensorStorageType::IMAGE_BUFFER,
-                             layout})
+        TensorDescriptor{data_type, TensorStorageType::IMAGE_BUFFER, layout}
+            .CanCreateTensorWithShape(gpu_info, shape)
             .ok()) {
       *result = TensorStorageType::IMAGE_BUFFER;
       return absl::OkStatus();
     } else {
       *result = TensorStorageType::BUFFER;
-      return CanCreateTensorWithShape(
-          gpu_info, shape,
-          TensorDescriptor{data_type, TensorStorageType::BUFFER, layout});
+      return TensorDescriptor{data_type, TensorStorageType::BUFFER, layout}
+          .CanCreateTensorWithShape(gpu_info, shape);
     }
   };
   auto GetBestTypeAfterTexture3D = [&]() {
-    if (CanCreateTensorWithShape(
-            gpu_info, shape,
-            TensorDescriptor{data_type, TensorStorageType::TEXTURE_2D, layout})
+    if (TensorDescriptor{data_type, TensorStorageType::TEXTURE_2D, layout}
+            .CanCreateTensorWithShape(gpu_info, shape)
             .ok()) {
       *result = TensorStorageType::TEXTURE_2D;
       return absl::OkStatus();
@@ -263,25 +86,21 @@
     case TensorStorageType::TEXTURE_3D:
       return GetBestTypeAfterTexture3D();
     case TensorStorageType::IMAGE_BUFFER: {
-      if (CanCreateTensorWithShape(
-              gpu_info, shape,
-              TensorDescriptor{data_type, TensorStorageType::IMAGE_BUFFER,
-                               layout})
+      if (TensorDescriptor{data_type, TensorStorageType::IMAGE_BUFFER, layout}
+              .CanCreateTensorWithShape(gpu_info, shape)
               .ok()) {
         *result = TensorStorageType::IMAGE_BUFFER;
         return absl::OkStatus();
       } else {
         *result = TensorStorageType::BUFFER;
-        return CanCreateTensorWithShape(
-            gpu_info, shape,
-            TensorDescriptor{data_type, TensorStorageType::BUFFER, layout});
+        return TensorDescriptor{data_type, TensorStorageType::BUFFER, layout}
+            .CanCreateTensorWithShape(gpu_info, shape);
       }
     }
     case TensorStorageType::BUFFER: {
       *result = TensorStorageType::BUFFER;
-      return CanCreateTensorWithShape(
-          gpu_info, shape,
-          TensorDescriptor{data_type, TensorStorageType::BUFFER, layout});
+      return TensorDescriptor{data_type, TensorStorageType::BUFFER, layout}
+          .CanCreateTensorWithShape(gpu_info, shape);
     }
     default:
       return absl::UnimplementedError(absl::StrCat(
diff --git a/tensorflow/lite/delegates/gpu/common/task/storage_type_util.h b/tensorflow/lite/delegates/gpu/common/task/storage_type_util.h
index 7053817..3da4a64 100644
--- a/tensorflow/lite/delegates/gpu/common/task/storage_type_util.h
+++ b/tensorflow/lite/delegates/gpu/common/task/storage_type_util.h
@@ -26,14 +26,6 @@
 namespace tflite {
 namespace gpu {
 
-absl::Status CanCreateTensorWithShape(const GpuInfo& gpu_info,
-                                      const BHWDC& shape,
-                                      const TensorDescriptor& descriptor);
-
-absl::Status CanCreateTensorWithShape(const GpuInfo& gpu_info,
-                                      const BHWC& shape,
-                                      const TensorDescriptor& descriptor);
-
 absl::Status SelectBestStorageType(const GpuInfo& gpu_info, const BHWC& shape,
                                    TensorStorageType desired,
                                    DataType data_type, Layout layout,
diff --git a/tensorflow/lite/delegates/gpu/common/task/tensor_desc.cc b/tensorflow/lite/delegates/gpu/common/task/tensor_desc.cc
index 2efb71a..dc562ed 100644
--- a/tensorflow/lite/delegates/gpu/common/task/tensor_desc.cc
+++ b/tensorflow/lite/delegates/gpu/common/task/tensor_desc.cc
@@ -1229,6 +1229,168 @@
   return storage_type == TensorStorageType::IMAGE_BUFFER;
 }
 
+absl::Status TensorDescriptor::CanCreateTensorWithShape(
+    const GpuInfo& gpu_info, const BHWDC& shape) const {
+  const int slices = DivideRoundUp(shape.c, 4);
+  const uint64_t flt_size = data_type == DataType::FLOAT32 ? 4 : 2;
+  const uint64_t channels = storage_type == TensorStorageType::SINGLE_TEXTURE_2D
+                                ? shape.c
+                                : slices * 4;
+  const uint64_t allocation_size =
+      flt_size * channels * shape.b * shape.w * shape.h * shape.d;
+  const std::string common_desc = "Shape - " + ToString(shape) +
+                                  ", data type - " + ToString(data_type) + ".";
+  if (allocation_size > gpu_info.GetMaxMemoryAllocationSize()) {
+    return absl::ResourceExhaustedError(absl::StrCat(
+        "Requested allocation size - ", allocation_size,
+        " bytes. Max allocation size for this GPU - ",
+        gpu_info.GetMaxMemoryAllocationSize(), " bytes. ", common_desc));
+  }
+  switch (storage_type) {
+    case TensorStorageType::BUFFER: {
+      const uint64_t flt4_size = 4 * (data_type == DataType::FLOAT32 ? 4 : 2);
+      const uint64_t buffer_size =
+          flt4_size * shape.b * shape.w * shape.h * shape.d * slices;
+      if (buffer_size > gpu_info.GetMaxBufferSize()) {
+        return absl::ResourceExhaustedError(absl::StrCat(
+            "Buffer with size - ", buffer_size,
+            " bytes can not be created. Max buffer size for this GPU - ",
+            gpu_info.GetMaxBufferSize(), " bytes. ", common_desc));
+      } else {
+        return absl::OkStatus();
+      }
+    }
+    case TensorStorageType::IMAGE_BUFFER: {
+      const uint64_t flt4_size = 4 * (data_type == DataType::FLOAT32 ? 4 : 2);
+      const uint64_t buffer_size =
+          flt4_size * shape.b * shape.w * shape.h * shape.d * slices;
+      const uint64_t image_width = buffer_size / flt4_size;
+      if (image_width > gpu_info.GetMaxImageBufferWidth()) {
+        return absl::ResourceExhaustedError(absl::StrCat(
+            "Image buffer with width - ", image_width,
+            " can not be created. Max image buffer width for this GPU - ",
+            gpu_info.GetMaxImageBufferWidth(), ". ", common_desc));
+      } else if (buffer_size > gpu_info.GetMaxBufferSize()) {
+        return absl::ResourceExhaustedError(absl::StrCat(
+            "Buffer with size - ", buffer_size,
+            " bytes can not be created. Max buffer size for this GPU - ",
+            gpu_info.GetMaxBufferSize(), " bytes. ", common_desc));
+      } else {
+        return absl::OkStatus();
+      }
+    }
+    case TensorStorageType::TEXTURE_3D: {
+      if (gpu_info.IsApiOpenCl() &&
+          gpu_info.opencl_info.cl_version < OpenClVersion::kCl1_2 &&
+          slices == 1) {
+        return absl::InternalError(
+            "clCreateImage3D (that used in CL 1.0/1.1) can not create image "
+            "with depth = 1 by specification.");
+      }
+      const int image_width = shape.w * shape.b;
+      const int image_height = shape.h;
+      const int image_depth = slices * shape.d;
+      if (image_width > gpu_info.GetMaxImage3DWidth()) {
+        return absl::ResourceExhaustedError(absl::StrCat(
+            "Image3D with width - ", image_width,
+            " can not be created. Max Image3D width for this GPU - ",
+            gpu_info.GetMaxImage3DWidth(), ". ", common_desc));
+      } else if (image_height > gpu_info.GetMaxImage3DHeight()) {
+        return absl::ResourceExhaustedError(absl::StrCat(
+            "Image3D with height - ", image_height,
+            " can not be created. Max Image3D height for this GPU - ",
+            gpu_info.GetMaxImage3DHeight(), ". ", common_desc));
+      } else if (image_depth > gpu_info.GetMaxImage3DDepth()) {
+        return absl::ResourceExhaustedError(absl::StrCat(
+            "Image3D with depth - ", image_depth,
+            " can not be created. Max Image3D depth for this GPU - ",
+            gpu_info.GetMaxImage3DDepth(), ". ", common_desc));
+      } else {
+        return absl::OkStatus();
+      }
+    }
+    case TensorStorageType::TEXTURE_ARRAY: {
+      // Bug on some Adreno. b/131099086
+      if (gpu_info.IsApiOpenCl() && slices == 1 && gpu_info.IsAdreno() &&
+          !gpu_info.adreno_info.support_one_layer_texture_array) {
+        return absl::InternalError(
+            "Image2DArray with layer = 1 works incorrect on some Adreno in "
+            "OpenCL. Can not be created.");
+      }
+      const int image_width = shape.w * shape.b;
+      const int image_height = shape.h;
+      const int image_layers = slices * shape.d;
+      if (image_width > gpu_info.GetMaxImage2DWidth()) {
+        return absl::ResourceExhaustedError(absl::StrCat(
+            "Image2DArray with width - ", image_width,
+            " can not be created. Max Image2DArray width for this GPU - ",
+            gpu_info.GetMaxImage2DWidth(), ". ", common_desc));
+      } else if (image_height > gpu_info.GetMaxImage2DHeight()) {
+        return absl::ResourceExhaustedError(absl::StrCat(
+            "Image2DArray with height - ", image_height,
+            " can not be created. Max Image2DArray height for this GPU - ",
+            gpu_info.GetMaxImage2DHeight(), ". ", common_desc));
+      } else if (image_layers > gpu_info.GetMaxImage2DArrayLayers()) {
+        return absl::ResourceExhaustedError(absl::StrCat(
+            "Image2DArray with layers - ", image_layers,
+            " can not be created. Max Image2DArray layers for this GPU - ",
+            gpu_info.GetMaxImage2DArrayLayers(), ". ", common_desc));
+      } else {
+        return absl::OkStatus();
+      }
+    }
+    case TensorStorageType::TEXTURE_2D: {
+      const int image_width = shape.w * shape.b * shape.d;
+      const int image_height = shape.h * slices;
+      if (image_width > gpu_info.GetMaxImage2DWidth()) {
+        return absl::ResourceExhaustedError(absl::StrCat(
+            "Image2D with width - ", image_width,
+            " can not be created. Max Image2D width for this GPU - ",
+            gpu_info.GetMaxImage2DWidth(), ". ", common_desc));
+      } else if (image_height > gpu_info.GetMaxImage2DHeight()) {
+        return absl::ResourceExhaustedError(absl::StrCat(
+            "Image2D with height - ", image_height,
+            " can not be created. Max Image2D height for this GPU - ",
+            gpu_info.GetMaxImage2DHeight(), ". ", common_desc));
+      } else {
+        return absl::OkStatus();
+      }
+    }
+    case TensorStorageType::SINGLE_TEXTURE_2D: {
+      const int image_width = shape.w * shape.b * shape.d;
+      const int image_height = shape.h;
+      if (shape.c > 4) {
+        return absl::ResourceExhaustedError(absl::StrCat(
+            "Image2D with channels - ", shape.c, " can not be created."));
+      } else if (!gpu_info.SupportsFloatImage2D(data_type, shape.c)) {
+        return absl::ResourceExhaustedError(
+            "Image2D doesn't support this pixel layout.");
+      } else if (image_width > gpu_info.GetMaxImage2DWidth()) {
+        return absl::ResourceExhaustedError(absl::StrCat(
+            "Image2D with width - ", image_width,
+            " can not be created. Max Image2D width for this GPU - ",
+            gpu_info.GetMaxImage2DWidth(), ". ", common_desc));
+      } else if (image_height > gpu_info.GetMaxImage2DHeight()) {
+        return absl::ResourceExhaustedError(absl::StrCat(
+            "Image2D with height - ", image_height,
+            " can not be created. Max Image2D height for this GPU - ",
+            gpu_info.GetMaxImage2DHeight(), ". ", common_desc));
+      } else {
+        return absl::OkStatus();
+      }
+    }
+    default:
+      return absl::UnimplementedError(
+          "Can not create resources for unknown storage type.");
+  }
+}
+
+absl::Status TensorDescriptor::CanCreateTensorWithShape(
+    const GpuInfo& gpu_info, const BHWC& shape) const {
+  const BHWDC shape5D(shape.b, shape.h, shape.w, 1, shape.c);
+  return CanCreateTensorWithShape(gpu_info, shape5D);
+}
+
 namespace {
 int GetLinearIndex(const TensorDescriptor& desc, const BHWDC& shape, int b,
                    int x, int y, int d, int s, int sub_c) {
diff --git a/tensorflow/lite/delegates/gpu/common/task/tensor_desc.h b/tensorflow/lite/delegates/gpu/common/task/tensor_desc.h
index 487512d..765f1ba 100644
--- a/tensorflow/lite/delegates/gpu/common/task/tensor_desc.h
+++ b/tensorflow/lite/delegates/gpu/common/task/tensor_desc.h
@@ -97,6 +97,12 @@
   // returns true, otherwise false
   bool ReturnsZeroForNegOneRead() const;
 
+  absl::Status CanCreateTensorWithShape(const GpuInfo& gpu_info,
+                                        const BHWDC& shape) const;
+
+  absl::Status CanCreateTensorWithShape(const GpuInfo& gpu_info,
+                                        const BHWC& shape) const;
+
   DataType data_type = DataType::UNKNOWN;
   TensorStorageType storage_type = TensorStorageType::UNKNOWN;
   // This field describes logical layout, actual(physical) GPU layout can be