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