• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #include "tensorflow/lite/delegates/gpu/common/task/storage_type_util.h"
17 
18 #include "tensorflow/lite/delegates/gpu/common/data_type.h"
19 #include "tensorflow/lite/delegates/gpu/common/shape.h"
20 #include "tensorflow/lite/delegates/gpu/common/task/tensor_desc.h"
21 #include "tensorflow/lite/delegates/gpu/common/util.h"
22 
23 namespace tflite {
24 namespace gpu {
25 
CanCreateTensorWithShape(const GpuInfo & gpu_info,const BHWDC & shape,const TensorDescriptor & descriptor)26 bool CanCreateTensorWithShape(const GpuInfo& gpu_info, const BHWDC& shape,
27                               const TensorDescriptor& descriptor) {
28   const int slices = DivideRoundUp(shape.c, 4);
29   switch (descriptor.storage_type) {
30     case TensorStorageType::BUFFER: {
31       const int flt4_size =
32           4 * (descriptor.data_type == DataType::FLOAT32 ? 4 : 2);
33       const int buffer_size =
34           shape.b * shape.w * shape.h * shape.d * slices * flt4_size;
35       return buffer_size <= gpu_info.GetMaxBufferSize();
36     }
37     case TensorStorageType::IMAGE_BUFFER:
38       return shape.b * shape.w * shape.h * shape.d * slices <=
39              gpu_info.GetMaxImageBufferWidth();
40     case TensorStorageType::TEXTURE_3D:
41       if (gpu_info.opencl_info.cl_version < OpenClVersion::kCl1_2 &&
42           slices == 1) {
43         // clCreateImage3D (that used in CL 1.0/1.1) can not create image with
44         // depth = 1 by specification;
45         return false;
46       }
47       return shape.w * shape.b <= gpu_info.GetMaxImage3DWidth() &&
48              shape.h <= gpu_info.GetMaxImage3DHeight() &&
49              slices * shape.d <= gpu_info.GetMaxImage3DDepth();
50     case TensorStorageType::TEXTURE_ARRAY:
51       // Bug on some Adreno. b/131099086
52       if (slices == 1 && gpu_info.IsAdreno() &&
53           !gpu_info.adreno_info.support_one_layer_texture_array) {
54         return false;
55       }
56       return shape.w * shape.b <= gpu_info.GetMaxImage2DWidth() &&
57              shape.h <= gpu_info.GetMaxImage2DHeight() &&
58              slices * shape.d <= gpu_info.GetMaxImage2DArrayLayers();
59     case TensorStorageType::TEXTURE_2D:
60       return shape.w * shape.b * shape.d <= gpu_info.GetMaxImage2DWidth() &&
61              shape.h * slices <= gpu_info.GetMaxImage2DHeight();
62     case TensorStorageType::SINGLE_TEXTURE_2D:
63       return shape.c <= 4 &&
64              gpu_info.SupportsFloatImage2D(descriptor.data_type, shape.c) &&
65              shape.w * shape.b * shape.d <= gpu_info.GetMaxImage2DWidth() &&
66              shape.h <= gpu_info.GetMaxImage2DHeight();
67     default:
68       return false;
69   }
70 }
71 
CanCreateTensorWithShape(const GpuInfo & gpu_info,const BHWC & shape,const TensorDescriptor & descriptor)72 bool CanCreateTensorWithShape(const GpuInfo& gpu_info, const BHWC& shape,
73                               const TensorDescriptor& descriptor) {
74   const BHWDC shape5D(shape.b, shape.h, shape.w, 1, shape.c);
75   return CanCreateTensorWithShape(gpu_info, shape5D, descriptor);
76 }
77 
SelectBestStorageType(const GpuInfo & gpu_info,const BHWC & shape,const TensorStorageType & desired,const DataType & data_type,const Layout & layout)78 TensorStorageType SelectBestStorageType(const GpuInfo& gpu_info,
79                                         const BHWC& shape,
80                                         const TensorStorageType& desired,
81                                         const DataType& data_type,
82                                         const Layout& layout) {
83   if (CanCreateTensorWithShape(gpu_info, shape,
84                                TensorDescriptor{data_type, desired, layout})) {
85     return desired;
86   }
87   if (gpu_info.IsApiMetal()) {
88     return TensorStorageType::BUFFER;
89   }
90   auto GetBestTypeAfterTextureArray = [&]() {
91     if (gpu_info.SupportsImageBuffer() &&
92         CanCreateTensorWithShape(
93             gpu_info, shape,
94             TensorDescriptor{data_type, TensorStorageType::IMAGE_BUFFER,
95                              layout})) {
96       return TensorStorageType::IMAGE_BUFFER;
97     } else {
98       return TensorStorageType::BUFFER;
99     }
100   };
101   auto GetBestTypeAfterTexture2D = [&]() {
102     if (gpu_info.SupportsTextureArray() &&
103         CanCreateTensorWithShape(
104             gpu_info, shape,
105             TensorDescriptor{data_type, TensorStorageType::TEXTURE_ARRAY,
106                              layout})) {
107       return TensorStorageType::TEXTURE_ARRAY;
108     } else {
109       return GetBestTypeAfterTextureArray();
110     }
111   };
112   auto GetBestTypeAfterTexture3D = [&]() {
113     if (CanCreateTensorWithShape(
114             gpu_info, shape,
115             TensorDescriptor{data_type, TensorStorageType::TEXTURE_2D,
116                              layout})) {
117       return TensorStorageType::TEXTURE_2D;
118     } else {
119       return GetBestTypeAfterTexture2D();
120     }
121   };
122   switch (desired) {
123     case TensorStorageType::TEXTURE_2D:
124     case TensorStorageType::SINGLE_TEXTURE_2D:
125       return GetBestTypeAfterTexture2D();
126     case TensorStorageType::TEXTURE_ARRAY:
127       return GetBestTypeAfterTextureArray();
128     case TensorStorageType::TEXTURE_3D:
129       return GetBestTypeAfterTexture3D();
130     case TensorStorageType::IMAGE_BUFFER:
131     case TensorStorageType::BUFFER:
132       return TensorStorageType::BUFFER;
133     default:
134       return TensorStorageType::BUFFER;
135   }
136 }
137 
DeduceLinearStorageType(TensorStorageType tensor_storage_type)138 LinearStorageType DeduceLinearStorageType(
139     TensorStorageType tensor_storage_type) {
140   if (tensor_storage_type == TensorStorageType::BUFFER) {
141     return LinearStorageType::BUFFER;
142   } else {
143     return LinearStorageType::TEXTURE_2D;
144   }
145 }
146 
147 }  // namespace gpu
148 }  // namespace tflite
149