1 /* Copyright 2019 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 "absl/memory/memory.h"
17 #include "tensorflow/lite/delegates/gpu/common/model_hints.h"
18 #include "tensorflow/lite/delegates/gpu/common/operations.h"
19 #include "tensorflow/lite/delegates/gpu/common/shape.h"
20 #include "tensorflow/lite/delegates/gpu/common/status.h"
21 #include "tensorflow/lite/delegates/gpu/common/task/gpu_operation.h"
22 #include "tensorflow/lite/delegates/gpu/common/task/tensor_desc.h"
23 #include "tensorflow/lite/delegates/gpu/common/task/weights_layout.h"
24 #include "tensorflow/lite/delegates/gpu/common/task/work_group_picking.h"
25 #include "tensorflow/lite/delegates/gpu/common/tasks/conv_buffer_1x1.h"
26 #include "tensorflow/lite/delegates/gpu/common/tasks/conv_constants.h"
27 #include "tensorflow/lite/delegates/gpu/common/tasks/conv_metal.h"
28 #include "tensorflow/lite/delegates/gpu/common/tasks/conv_powervr.h"
29 #include "tensorflow/lite/delegates/gpu/common/tasks/conv_weights_converter.h"
30 #include "tensorflow/lite/delegates/gpu/common/util.h"
31
32 namespace tflite {
33 namespace gpu {
34 namespace {
35
SelectConvolutionAdreno(const Convolution2DAttributes & attr,const BHWC & dst_shape,const GpuInfo & gpu_info,const OperationDef & op_def,ModelHints hints)36 std::unique_ptr<GPUOperation> SelectConvolutionAdreno(
37 const Convolution2DAttributes& attr, const BHWC& dst_shape,
38 const GpuInfo& gpu_info, const OperationDef& op_def,
39 ModelHints hints) {
40 if (IsConvConstantsSupported(gpu_info, op_def, attr)) {
41 GPUOperation conv = CreateConvConstants(gpu_info, op_def, attr);
42 return absl::make_unique<GPUOperation>(std::move(conv));
43 } else {
44 ConvPowerVR conv = CreateConvPowerVR(gpu_info, op_def, attr, &dst_shape);
45 return absl::make_unique<ConvPowerVR>(std::move(conv));
46 }
47 }
48
SelectConvolutionWinogradAdreno(const Convolution2DAttributes & attr,const BHWC & dst_shape,const GpuInfo & gpu_info,const OperationDef & op_def,ModelHints hints)49 std::unique_ptr<GPUOperation> SelectConvolutionWinogradAdreno(
50 const Convolution2DAttributes& attr, const BHWC& dst_shape,
51 const GpuInfo& gpu_info, const OperationDef& op_def,
52 ModelHints hints) {
53 ConvPowerVR conv =
54 CreateConvPowerVRWino4x4To6x6(gpu_info, op_def, attr, &dst_shape);
55 return absl::make_unique<ConvPowerVR>(std::move(conv));
56 }
57
SelectConvolutionDynamicWeightsAdreno(const Convolution2DAttributes & attr,const BHWC & weights_shape,const BHWC & dst_shape,const GpuInfo & gpu_info,const OperationDef & op_def,ModelHints hints,WeightsDescription * weights_desc)58 std::unique_ptr<GPUOperation> SelectConvolutionDynamicWeightsAdreno(
59 const Convolution2DAttributes& attr, const BHWC& weights_shape,
60 const BHWC& dst_shape, const GpuInfo& gpu_info,
61 const OperationDef& op_def, ModelHints hints,
62 WeightsDescription* weights_desc) {
63 ConvPowerVR conv = CreateConvPowerVRDynamicWeights(
64 gpu_info, op_def, attr, weights_shape, &dst_shape);
65 *weights_desc = conv.GetWeightsDescription();
66 return absl::make_unique<ConvPowerVR>(std::move(conv));
67 }
68
SelectConvolutionNVidia(const Convolution2DAttributes & attr,const BHWC & dst_shape,const GpuInfo & gpu_info,const OperationDef & op_def)69 std::unique_ptr<GPUOperation> SelectConvolutionNVidia(
70 const Convolution2DAttributes& attr, const BHWC& dst_shape,
71 const GpuInfo& gpu_info, const OperationDef& op_def) {
72 if (IsConvConstantsSupported(gpu_info, op_def, attr)) {
73 GPUOperation conv = CreateConvConstants(gpu_info, op_def, attr);
74 return absl::make_unique<GPUOperation>(std::move(conv));
75 } else {
76 ConvPowerVR conv = CreateConvPowerVR(gpu_info, op_def, attr, &dst_shape);
77 return absl::make_unique<ConvPowerVR>(std::move(conv));
78 }
79 }
80
SelectConvolutionPowerVR(const Convolution2DAttributes & attr,const GpuInfo & gpu_info,const OperationDef & op_def)81 std::unique_ptr<GPUOperation> SelectConvolutionPowerVR(
82 const Convolution2DAttributes& attr, const GpuInfo& gpu_info,
83 const OperationDef& op_def) {
84 ConvPowerVR conv = CreateConvPowerVR(gpu_info, op_def, attr);
85 return absl::make_unique<ConvPowerVR>(std::move(conv));
86 }
87
SelectConvolutionMali(const Convolution2DAttributes & attr,const BHWC & dst_shape,const GpuInfo & gpu_info,const OperationDef & op_def)88 std::unique_ptr<GPUOperation> SelectConvolutionMali(
89 const Convolution2DAttributes& attr, const BHWC& dst_shape,
90 const GpuInfo& gpu_info, const OperationDef& op_def) {
91 if (op_def.src_tensors[0].storage_type == TensorStorageType::BUFFER &&
92 IsConvBuffer1x1Supported(op_def, attr)) {
93 ConvBuffer1x1 conv =
94 CreateConvBuffer1x1(gpu_info, op_def, attr, &dst_shape);
95 return absl::make_unique<ConvBuffer1x1>(std::move(conv));
96 } else {
97 ConvPowerVR conv = CreateConvPowerVR(gpu_info, op_def, attr, &dst_shape);
98 return absl::make_unique<ConvPowerVR>(std::move(conv));
99 }
100 }
101
SelectConvolutionWinogradMali(const Convolution2DAttributes & attr,const BHWC & dst_shape,const GpuInfo & gpu_info,const OperationDef & op_def)102 std::unique_ptr<GPUOperation> SelectConvolutionWinogradMali(
103 const Convolution2DAttributes& attr, const BHWC& dst_shape,
104 const GpuInfo& gpu_info, const OperationDef& op_def) {
105 if (op_def.src_tensors[0].storage_type == TensorStorageType::BUFFER) {
106 ConvBuffer1x1 conv =
107 CreateConvBuffer1x1Wino4x4To6x6(gpu_info, op_def, attr, &dst_shape);
108 return absl::make_unique<ConvBuffer1x1>(std::move(conv));
109 } else {
110 ConvPowerVR conv =
111 CreateConvPowerVRWino4x4To6x6(gpu_info, op_def, attr, &dst_shape);
112 return absl::make_unique<ConvPowerVR>(std::move(conv));
113 }
114 }
115
SelectConvolutionDynamicWeightsMali(const Convolution2DAttributes & attr,const BHWC & weights_shape,const BHWC & dst_shape,const GpuInfo & gpu_info,const OperationDef & op_def,ModelHints hints,WeightsDescription * weights_desc)116 std::unique_ptr<GPUOperation> SelectConvolutionDynamicWeightsMali(
117 const Convolution2DAttributes& attr, const BHWC& weights_shape,
118 const BHWC& dst_shape, const GpuInfo& gpu_info,
119 const OperationDef& op_def, ModelHints hints,
120 WeightsDescription* weights_desc) {
121 if (op_def.src_tensors[0].storage_type == TensorStorageType::BUFFER &&
122 IsConvBuffer1x1Supported(op_def, weights_shape, attr)) {
123 ConvBuffer1x1 conv = CreateConvBuffer1x1DynamicWeights(
124 gpu_info, op_def, attr, weights_shape, &dst_shape);
125 *weights_desc = conv.GetWeightsDescription();
126 return absl::make_unique<ConvBuffer1x1>(std::move(conv));
127 } else {
128 ConvPowerVR conv = CreateConvPowerVRDynamicWeights(
129 gpu_info, op_def, attr, weights_shape, &dst_shape);
130 *weights_desc = conv.GetWeightsDescription();
131 return absl::make_unique<ConvPowerVR>(std::move(conv));
132 }
133 }
134
135 } // namespace
136
SelectConvolution(const Convolution2DAttributes & attr,const BHWC & dst_shape,const GpuInfo & gpu_info,const OperationDef & op_def,ModelHints hints)137 std::unique_ptr<GPUOperation> SelectConvolution(
138 const Convolution2DAttributes& attr, const BHWC& dst_shape,
139 const GpuInfo& gpu_info, const OperationDef& op_def,
140 ModelHints hints) {
141 if (gpu_info.IsApiMetal() && IsConvolutionMetalSupported(op_def)) {
142 ConvolutionMetal conv =
143 CreateConvolutionMetal(op_def, dst_shape, attr, gpu_info);
144 return absl::make_unique<ConvolutionMetal>(std::move(conv));
145 } else if (gpu_info.IsAdreno()) {
146 return SelectConvolutionAdreno(attr, dst_shape, gpu_info, op_def, hints);
147 } else if (gpu_info.IsPowerVR() || gpu_info.IsAMD() || gpu_info.IsIntel() ||
148 gpu_info.IsApple()) {
149 return SelectConvolutionPowerVR(attr, gpu_info, op_def);
150 } else if (gpu_info.IsNvidia()) {
151 return SelectConvolutionNVidia(attr, dst_shape, gpu_info, op_def);
152 } else if (gpu_info.IsMali()) {
153 return SelectConvolutionMali(attr, dst_shape, gpu_info, op_def);
154 } else {
155 return SelectConvolutionAdreno(attr, dst_shape, gpu_info, op_def, hints);
156 }
157 }
158
SelectConvolutionForWinograd(const Convolution2DAttributes & attr,const BHWC & dst_shape,const GpuInfo & gpu_info,const OperationDef & op_def,ModelHints hints)159 std::unique_ptr<GPUOperation> SelectConvolutionForWinograd(
160 const Convolution2DAttributes& attr, const BHWC& dst_shape,
161 const GpuInfo& gpu_info, const OperationDef& op_def,
162 ModelHints hints) {
163 if (gpu_info.IsApiMetal() && IsConvolutionMetalSupported(op_def)) {
164 ConvolutionMetal conv =
165 CreateConvolutionMetalWino4x4To6x6(op_def, dst_shape, attr, gpu_info);
166 return absl::make_unique<ConvolutionMetal>(std::move(conv));
167 } else if (gpu_info.IsAdreno()) {
168 return SelectConvolutionWinogradAdreno(attr, dst_shape, gpu_info, op_def,
169 hints);
170 } else if (gpu_info.IsPowerVR() || gpu_info.IsAMD() || gpu_info.IsNvidia() ||
171 gpu_info.IsIntel() || gpu_info.IsApple()) {
172 ConvPowerVR conv =
173 CreateConvPowerVRWino4x4To6x6(gpu_info, op_def, attr, &dst_shape);
174 return absl::make_unique<ConvPowerVR>(std::move(conv));
175 } else if (gpu_info.IsMali()) {
176 return SelectConvolutionWinogradMali(attr, dst_shape, gpu_info, op_def);
177 } else {
178 return SelectConvolutionWinogradAdreno(attr, dst_shape, gpu_info, op_def,
179 hints);
180 }
181 }
182
SelectConvolutionWithDynamicWeights(const Convolution2DAttributes & attr,const BHWC & weights_shape,const BHWC & dst_shape,const GpuInfo & gpu_info,const OperationDef & op_def,ModelHints hints,WeightsDescription * weights_desc)183 std::unique_ptr<GPUOperation> SelectConvolutionWithDynamicWeights(
184 const Convolution2DAttributes& attr, const BHWC& weights_shape,
185 const BHWC& dst_shape, const GpuInfo& gpu_info,
186 const OperationDef& op_def, ModelHints hints,
187 WeightsDescription* weights_desc) {
188 if (gpu_info.IsApiMetal() && IsConvolutionMetalSupported(op_def)) {
189 Convolution2DAttributes attr_copy = attr;
190 attr_copy.weights.shape = OHWI(weights_shape.b, weights_shape.h,
191 weights_shape.w, weights_shape.c);
192 ConvolutionMetal conv =
193 CreateConvolutionMetal(op_def, dst_shape, attr_copy, gpu_info);
194 return absl::make_unique<ConvolutionMetal>(std::move(conv));
195 } else if (gpu_info.IsAdreno()) {
196 return SelectConvolutionDynamicWeightsAdreno(attr, weights_shape, dst_shape,
197 gpu_info, op_def, hints,
198 weights_desc);
199 } else if (gpu_info.IsMali()) {
200 return SelectConvolutionDynamicWeightsMali(attr, weights_shape, dst_shape,
201 gpu_info, op_def, hints,
202 weights_desc);
203 } else {
204 ConvPowerVR conv = CreateConvPowerVRDynamicWeights(
205 gpu_info, op_def, attr, weights_shape, &dst_shape);
206 *weights_desc = conv.GetWeightsDescription();
207 return absl::make_unique<ConvPowerVR>(std::move(conv));
208 }
209 }
210
SelectConverterToConvWeights(const WeightsDescription & weights_desc,const OperationDef & op_def,ModelHints hints)211 std::unique_ptr<GPUOperation> SelectConverterToConvWeights(
212 const WeightsDescription& weights_desc, const OperationDef& op_def,
213 ModelHints hints) {
214 ConverterToConvWeights converter =
215 ConverterToConvWeights(op_def, weights_desc);
216 return absl::make_unique<ConverterToConvWeights>(std::move(converter));
217 }
218
219 } // namespace gpu
220 } // namespace tflite
221