1 // Tencent is pleased to support the open source community by making ncnn available.
2 //
3 // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
4 //
5 // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
6 // in compliance with the License. You may obtain a copy of the License at
7 //
8 // https://opensource.org/licenses/BSD-3-Clause
9 //
10 // Unless required by applicable law or agreed to in writing, software distributed
11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 // specific language governing permissions and limitations under the License.
14 
15 #include "layer.h"
16 
17 #include "cpu.h"
18 
19 #include <math.h>
20 #include <string.h>
21 
22 #ifdef _MSC_VER
23 #pragma warning(push)
24 #pragma warning(disable : 4250)
25 #endif
26 #ifdef __clang__
27 #pragma clang diagnostic push
28 #pragma clang diagnostic ignored "-Woverloaded-virtual"
29 #endif
30 #include "layer_declaration.h"
31 #ifdef __clang__
32 #pragma clang diagnostic pop
33 #endif
34 #ifdef _MSC_VER
35 #pragma warning(pop)
36 #endif
37 
38 namespace ncnn {
39 
Layer()40 Layer::Layer()
41 {
42     one_blob_only = false;
43     support_inplace = false;
44     support_vulkan = false;
45     support_packing = false;
46 
47     support_bf16_storage = false;
48     support_fp16_storage = false;
49     support_int8_storage = false;
50     support_image_storage = false;
51     support_tensor_storage = false;
52 
53     support_weight_fp16_storage = false;
54 
55     typeindex = -1;
56 
57 #if NCNN_VULKAN
58     vkdev = 0;
59 #endif // NCNN_VULKAN
60 
61     userdata = 0;
62 }
63 
~Layer()64 Layer::~Layer()
65 {
66 }
67 
load_param(const ParamDict &)68 int Layer::load_param(const ParamDict& /*pd*/)
69 {
70     return 0;
71 }
72 
load_model(const ModelBin &)73 int Layer::load_model(const ModelBin& /*mb*/)
74 {
75     return 0;
76 }
77 
create_pipeline(const Option &)78 int Layer::create_pipeline(const Option& /*opt*/)
79 {
80     return 0;
81 }
82 
destroy_pipeline(const Option &)83 int Layer::destroy_pipeline(const Option& /*opt*/)
84 {
85     return 0;
86 }
87 
forward(const std::vector<Mat> & bottom_blobs,std::vector<Mat> & top_blobs,const Option & opt) const88 int Layer::forward(const std::vector<Mat>& bottom_blobs, std::vector<Mat>& top_blobs, const Option& opt) const
89 {
90     if (!support_inplace)
91         return -1;
92 
93     top_blobs = bottom_blobs;
94     for (int i = 0; i < (int)top_blobs.size(); i++)
95     {
96         top_blobs[i] = bottom_blobs[i].clone(opt.blob_allocator);
97         if (top_blobs[i].empty())
98             return -100;
99     }
100 
101     return forward_inplace(top_blobs, opt);
102 }
103 
forward(const Mat & bottom_blob,Mat & top_blob,const Option & opt) const104 int Layer::forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt) const
105 {
106     if (!support_inplace)
107         return -1;
108 
109     top_blob = bottom_blob.clone(opt.blob_allocator);
110     if (top_blob.empty())
111         return -100;
112 
113     return forward_inplace(top_blob, opt);
114 }
115 
forward_inplace(std::vector<Mat> &,const Option &) const116 int Layer::forward_inplace(std::vector<Mat>& /*bottom_top_blobs*/, const Option& /*opt*/) const
117 {
118     return -1;
119 }
120 
forward_inplace(Mat &,const Option &) const121 int Layer::forward_inplace(Mat& /*bottom_top_blob*/, const Option& /*opt*/) const
122 {
123     return -1;
124 }
125 
126 #if NCNN_VULKAN
upload_model(VkTransfer &,const Option &)127 int Layer::upload_model(VkTransfer& /*cmd*/, const Option& /*opt*/)
128 {
129     return 0;
130 }
131 
forward(const std::vector<VkMat> & bottom_blobs,std::vector<VkMat> & top_blobs,VkCompute & cmd,const Option & opt) const132 int Layer::forward(const std::vector<VkMat>& bottom_blobs, std::vector<VkMat>& top_blobs, VkCompute& cmd, const Option& opt) const
133 {
134     if (!support_inplace)
135         return -1;
136 
137     top_blobs.resize(bottom_blobs.size());
138     for (int i = 0; i < (int)top_blobs.size(); i++)
139     {
140         cmd.record_clone(bottom_blobs[i], top_blobs[i], opt);
141     }
142 
143     return forward_inplace(top_blobs, cmd, opt);
144 }
145 
forward(const VkMat & bottom_blob,VkMat & top_blob,VkCompute & cmd,const Option & opt) const146 int Layer::forward(const VkMat& bottom_blob, VkMat& top_blob, VkCompute& cmd, const Option& opt) const
147 {
148     if (!support_inplace)
149         return -1;
150 
151     cmd.record_clone(bottom_blob, top_blob, opt);
152 
153     return forward_inplace(top_blob, cmd, opt);
154 }
155 
forward(const std::vector<VkImageMat> & bottom_blobs,std::vector<VkImageMat> & top_blobs,VkCompute & cmd,const Option & opt) const156 int Layer::forward(const std::vector<VkImageMat>& bottom_blobs, std::vector<VkImageMat>& top_blobs, VkCompute& cmd, const Option& opt) const
157 {
158     if (!support_inplace)
159         return -1;
160 
161     top_blobs.resize(bottom_blobs.size());
162     for (int i = 0; i < (int)top_blobs.size(); i++)
163     {
164         cmd.record_clone(bottom_blobs[i], top_blobs[i], opt);
165     }
166 
167     return forward_inplace(top_blobs, cmd, opt);
168 }
169 
forward(const VkImageMat & bottom_blob,VkImageMat & top_blob,VkCompute & cmd,const Option & opt) const170 int Layer::forward(const VkImageMat& bottom_blob, VkImageMat& top_blob, VkCompute& cmd, const Option& opt) const
171 {
172     if (!support_inplace)
173         return -1;
174 
175     cmd.record_clone(bottom_blob, top_blob, opt);
176 
177     return forward_inplace(top_blob, cmd, opt);
178 }
179 
forward_inplace(std::vector<VkMat> &,VkCompute &,const Option &) const180 int Layer::forward_inplace(std::vector<VkMat>& /*bottom_top_blobs*/, VkCompute& /*cmd*/, const Option& /*opt*/) const
181 {
182     return -1;
183 }
184 
forward_inplace(VkMat &,VkCompute &,const Option &) const185 int Layer::forward_inplace(VkMat& /*bottom_top_blob*/, VkCompute& /*cmd*/, const Option& /*opt*/) const
186 {
187     return -1;
188 }
189 
forward_inplace(std::vector<VkImageMat> &,VkCompute &,const Option &) const190 int Layer::forward_inplace(std::vector<VkImageMat>& /*bottom_top_blobs*/, VkCompute& /*cmd*/, const Option& /*opt*/) const
191 {
192     return -1;
193 }
194 
forward_inplace(VkImageMat &,VkCompute &,const Option &) const195 int Layer::forward_inplace(VkImageMat& /*bottom_top_blob*/, VkCompute& /*cmd*/, const Option& /*opt*/) const
196 {
197     return -1;
198 }
199 #endif // NCNN_VULKAN
200 
201 static const layer_registry_entry layer_registry[] = {
202 #include "layer_registry.h"
203 };
204 
205 #if NCNN_RUNTIME_CPU && NCNN_AVX2
206 static const layer_registry_entry layer_registry_avx2[] = {
207 #include "layer_registry_avx2.h"
208 };
209 #endif // NCNN_RUNTIME_CPU && NCNN_AVX2
210 
211 #if NCNN_RUNTIME_CPU && NCNN_ARM82
212 static const layer_registry_entry layer_registry_arm82[] = {
213 #include "layer_registry_arm82.h"
214 };
215 #endif // NCNN_RUNTIME_CPU && NCNN_ARM82
216 
217 static const int layer_registry_entry_count = sizeof(layer_registry) / sizeof(layer_registry_entry);
218 
219 #if NCNN_STRING
layer_to_index(const char * type)220 int layer_to_index(const char* type)
221 {
222     for (int i = 0; i < layer_registry_entry_count; i++)
223     {
224         if (strcmp(type, layer_registry[i].name) == 0)
225             return i;
226     }
227 
228     return -1;
229 }
230 
create_layer(const char * type)231 Layer* create_layer(const char* type)
232 {
233     int index = layer_to_index(type);
234     if (index == -1)
235         return 0;
236 
237     return create_layer(index);
238 }
239 #endif // NCNN_STRING
240 
create_layer(int index)241 Layer* create_layer(int index)
242 {
243     if (index < 0 || index >= layer_registry_entry_count)
244         return 0;
245 
246     // clang-format off
247     // *INDENT-OFF*
248     layer_creator_func layer_creator = 0;
249 #if NCNN_RUNTIME_CPU && NCNN_AVX2
250     if (ncnn::cpu_support_x86_avx2())
251     {
252         layer_creator = layer_registry_avx2[index].creator;
253     }
254     else
255 #endif // NCNN_RUNTIME_CPU && NCNN_AVX2
256 #if NCNN_RUNTIME_CPU && NCNN_ARM82
257     if (ncnn::cpu_support_arm_asimdhp())
258     {
259         layer_creator = layer_registry_arm82[index].creator;
260     }
261     else
262 #endif // NCNN_RUNTIME_CPU && NCNN_ARM82
263     {
264         layer_creator = layer_registry[index].creator;
265     }
266     // *INDENT-ON*
267     // clang-format on
268     if (!layer_creator)
269         return 0;
270 
271     Layer* layer = layer_creator(0);
272     layer->typeindex = index;
273     return layer;
274 }
275 
276 } // namespace ncnn
277