You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

innerproduct_vulkan.cpp 16 kB

adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
adreno image shader + fp16 + fp16a (#1714) * wip * wip * fix * image and imageview can not be destroyed until command execution ends * fast copy path for tightly packed data * wip * texture load works * 1d 3d image * record clone image, multiple commands share one image reference * upload download image * layer forward accept vkimagemat * vkimagemat graph works * staging vkimagemat for passing dynamic parameters, macro for fp32+image shader, padding image shader * vkimagemat elemsize * convolution test pass * conv1x1s1 image shader * fast staging image allocator from host memory, pooling image shader * convolutiondepthwise image shader * innerproduct image shader * packing image shader * crop deconvolution image shader * resolve spirv binding types * image fp16 and fp16a, cast image shader * eltwise image shader * wip * absval image shader * deconvolutiondepthwise image shader * concat image shader, squeezenet works * noop split image shader * uniform precision hint * layer support_image_storage * wip * vulkan device utility operator * command is storage and packing option aware * fallback to cpu on image allocation failed, mobilenetssd works * flatten image shader, enable more test * ci test * check imgfp32 imgfp16 imgfp16a features * fix ci test * fix ci test * upgrade swiftshader * wip * opt aggressive * imgfp16p * opt none * convolution winograd image shader * fix flush range, fast copy path for continous buffer * minor fix * fix innerproduct * wip ... * wip * cast fix * packing test * wip * image fp16p is fp16p * wip * silence * more line info * code clean * softmax image shader
6 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. // Tencent is pleased to support the open source community by making ncnn available.
  2. //
  3. // Copyright (C) 2019 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. #include "innerproduct_vulkan.h"
  15. #include <algorithm>
  16. #include "layer_type.h"
  17. #include "layer_shader_type.h"
  18. namespace ncnn {
  19. DEFINE_LAYER_CREATOR(InnerProduct_vulkan)
  20. InnerProduct_vulkan::InnerProduct_vulkan()
  21. {
  22. support_vulkan = true;
  23. support_image_storage = true;
  24. flatten = 0;
  25. pipeline_innerproduct = 0;
  26. pipeline_innerproduct_pack4 = 0;
  27. pipeline_innerproduct_pack1to4 = 0;
  28. pipeline_innerproduct_pack4to1 = 0;
  29. pipeline_innerproduct_pack8 = 0;
  30. pipeline_innerproduct_pack1to8 = 0;
  31. pipeline_innerproduct_pack4to8 = 0;
  32. pipeline_innerproduct_pack8to4 = 0;
  33. pipeline_innerproduct_pack8to1 = 0;
  34. }
  35. int InnerProduct_vulkan::create_pipeline(const Option& opt)
  36. {
  37. const Mat& shape = bottom_shapes.empty() ? Mat() : bottom_shapes[0];
  38. const Mat& out_shape = top_shapes.empty() ? Mat() : top_shapes[0];
  39. Mat shape_flatten;
  40. if (shape.dims != 0)
  41. {
  42. shape_flatten = Mat(shape.w * shape.h * shape.c, (void*)0);
  43. }
  44. {
  45. flatten = ncnn::create_layer(ncnn::LayerType::Flatten);
  46. flatten->vkdev = vkdev;
  47. flatten->bottom_shapes.resize(1);
  48. flatten->bottom_shapes[0] = shape;
  49. flatten->top_shapes.resize(1);
  50. flatten->top_shapes[0] = shape_flatten;
  51. ncnn::ParamDict pd;
  52. flatten->load_param(pd);
  53. flatten->create_pipeline(opt);
  54. }
  55. int num_input = weight_data_size / num_output;
  56. int elempack = opt.use_shader_pack8 && num_input % 8 == 0 ? 8 : num_input % 4 == 0 ? 4 : 1;
  57. int out_elempack = opt.use_shader_pack8 && num_output % 8 == 0 ? 8 : num_output % 4 == 0 ? 4 : 1;
  58. size_t elemsize;
  59. size_t out_elemsize;
  60. if (opt.use_image_storage && opt.use_fp16_storage)
  61. {
  62. elemsize = elempack * 2u;
  63. out_elemsize = out_elempack * 2u;
  64. }
  65. else if (opt.use_image_storage)
  66. {
  67. elemsize = elempack * 4u;
  68. out_elemsize = out_elempack * 4u;
  69. }
  70. else if (opt.use_fp16_storage)
  71. {
  72. elemsize = elempack * 2u;
  73. out_elemsize = out_elempack * 2u;
  74. }
  75. else if (opt.use_fp16_packed)
  76. {
  77. elemsize = elempack == 1 ? 4u : elempack * 2u;
  78. out_elemsize = out_elempack == 1 ? 4u : out_elempack * 2u;
  79. }
  80. else
  81. {
  82. elemsize = elempack * 4u;
  83. out_elemsize = out_elempack * 4u;
  84. }
  85. Mat shape_flatten_packed;
  86. if (shape_flatten.dims == 3) shape_flatten_packed = Mat(shape_flatten.w / elempack, (void*)0, elemsize, elempack);
  87. Mat out_shape_packed;
  88. if (out_shape.dims == 1) out_shape_packed = Mat(out_shape.w / out_elempack, (void*)0, out_elemsize, out_elempack);
  89. std::vector<vk_specialization_type> specializations(4 + 10);
  90. specializations[0].i = bias_term;
  91. specializations[1].i = activation_type;
  92. specializations[2].f = activation_params.w >= 1 ? activation_params[0] : 0.f;
  93. specializations[3].f = activation_params.w == 2 ? activation_params[1] : 0.f;
  94. specializations[4 + 0].i = shape_flatten_packed.dims;
  95. specializations[4 + 1].i = shape_flatten_packed.w;
  96. specializations[4 + 2].i = shape_flatten_packed.h;
  97. specializations[4 + 3].i = shape_flatten_packed.c;
  98. specializations[4 + 4].i = shape_flatten_packed.cstep;
  99. specializations[4 + 5].i = out_shape_packed.dims;
  100. specializations[4 + 6].i = out_shape_packed.w;
  101. specializations[4 + 7].i = out_shape_packed.h;
  102. specializations[4 + 8].i = out_shape_packed.c;
  103. specializations[4 + 9].i = out_shape_packed.cstep;
  104. Mat local_size_xyz(std::min(64, num_output / out_elempack), 1, 1, (void*)0);
  105. if (out_shape_packed.dims != 0)
  106. {
  107. local_size_xyz.w = std::min(64, out_shape_packed.w);
  108. local_size_xyz.h = 1;
  109. local_size_xyz.c = 1;
  110. }
  111. // pack1
  112. if (elempack == 1 && out_elempack == 1)
  113. {
  114. pipeline_innerproduct = new Pipeline(vkdev);
  115. pipeline_innerproduct->set_optimal_local_size_xyz(local_size_xyz);
  116. pipeline_innerproduct->create(LayerShaderType::innerproduct, opt, specializations);
  117. }
  118. // pack4
  119. if (elempack == 4 && out_elempack == 4)
  120. {
  121. pipeline_innerproduct_pack4 = new Pipeline(vkdev);
  122. pipeline_innerproduct_pack4->set_optimal_local_size_xyz(local_size_xyz);
  123. pipeline_innerproduct_pack4->create(LayerShaderType::innerproduct_pack4, opt, specializations);
  124. }
  125. // pack1to4
  126. if (elempack == 1 && out_elempack == 4)
  127. {
  128. pipeline_innerproduct_pack1to4 = new Pipeline(vkdev);
  129. pipeline_innerproduct_pack1to4->set_optimal_local_size_xyz(local_size_xyz);
  130. pipeline_innerproduct_pack1to4->create(LayerShaderType::innerproduct_pack1to4, opt, specializations);
  131. }
  132. // pack4to1
  133. if (elempack == 4 && out_elempack == 1)
  134. {
  135. pipeline_innerproduct_pack4to1 = new Pipeline(vkdev);
  136. pipeline_innerproduct_pack4to1->set_optimal_local_size_xyz(local_size_xyz);
  137. pipeline_innerproduct_pack4to1->create(LayerShaderType::innerproduct_pack4to1, opt, specializations);
  138. }
  139. // pack8
  140. if (elempack == 8 && out_elempack == 8)
  141. {
  142. pipeline_innerproduct_pack8 = new Pipeline(vkdev);
  143. pipeline_innerproduct_pack8->set_optimal_local_size_xyz(local_size_xyz);
  144. pipeline_innerproduct_pack8->create(LayerShaderType::innerproduct_pack8, opt, specializations);
  145. }
  146. // pack1to8
  147. if (elempack == 1 && out_elempack == 8)
  148. {
  149. pipeline_innerproduct_pack1to8 = new Pipeline(vkdev);
  150. pipeline_innerproduct_pack1to8->set_optimal_local_size_xyz(local_size_xyz);
  151. pipeline_innerproduct_pack1to8->create(LayerShaderType::innerproduct_pack1to8, opt, specializations);
  152. }
  153. // pack4to8
  154. if (elempack == 4 && out_elempack == 8)
  155. {
  156. pipeline_innerproduct_pack4to8 = new Pipeline(vkdev);
  157. pipeline_innerproduct_pack4to8->set_optimal_local_size_xyz(local_size_xyz);
  158. pipeline_innerproduct_pack4to8->create(LayerShaderType::innerproduct_pack4to8, opt, specializations);
  159. }
  160. // pack8to4
  161. if (elempack == 8 && out_elempack == 4)
  162. {
  163. pipeline_innerproduct_pack8to4 = new Pipeline(vkdev);
  164. pipeline_innerproduct_pack8to4->set_optimal_local_size_xyz(local_size_xyz);
  165. pipeline_innerproduct_pack8to4->create(LayerShaderType::innerproduct_pack8to4, opt, specializations);
  166. }
  167. // pack8to1
  168. if (elempack == 8 && out_elempack == 1)
  169. {
  170. pipeline_innerproduct_pack8to1 = new Pipeline(vkdev);
  171. pipeline_innerproduct_pack8to1->set_optimal_local_size_xyz(local_size_xyz);
  172. pipeline_innerproduct_pack8to1->create(LayerShaderType::innerproduct_pack8to1, opt, specializations);
  173. }
  174. return 0;
  175. }
  176. int InnerProduct_vulkan::destroy_pipeline(const Option& opt)
  177. {
  178. if (flatten)
  179. {
  180. flatten->destroy_pipeline(opt);
  181. delete flatten;
  182. flatten = 0;
  183. }
  184. delete pipeline_innerproduct;
  185. pipeline_innerproduct = 0;
  186. delete pipeline_innerproduct_pack4;
  187. pipeline_innerproduct_pack4 = 0;
  188. delete pipeline_innerproduct_pack1to4;
  189. pipeline_innerproduct_pack1to4 = 0;
  190. delete pipeline_innerproduct_pack4to1;
  191. pipeline_innerproduct_pack4to1 = 0;
  192. delete pipeline_innerproduct_pack8;
  193. pipeline_innerproduct_pack8 = 0;
  194. delete pipeline_innerproduct_pack1to8;
  195. pipeline_innerproduct_pack1to8 = 0;
  196. delete pipeline_innerproduct_pack4to8;
  197. pipeline_innerproduct_pack4to8 = 0;
  198. delete pipeline_innerproduct_pack8to4;
  199. pipeline_innerproduct_pack8to4 = 0;
  200. delete pipeline_innerproduct_pack8to1;
  201. pipeline_innerproduct_pack8to1 = 0;
  202. return 0;
  203. }
  204. int InnerProduct_vulkan::upload_model(VkTransfer& cmd, const Option& opt)
  205. {
  206. int num_input = weight_data_size / num_output;
  207. int elempack = opt.use_shader_pack8 && num_input % 8 == 0 ? 8 : num_input % 4 == 0 ? 4 : 1;
  208. int out_elempack = opt.use_shader_pack8 && num_output % 8 == 0 ? 8 : num_output % 4 == 0 ? 4 : 1;
  209. // src = inch-outch
  210. // dst = pa-pb-inch/pa-outch/pb
  211. Mat weight_data_packed;
  212. {
  213. Mat weight_data_r2 = weight_data.reshape(num_input, num_output);
  214. weight_data_packed.create(num_input/elempack, num_output/out_elempack, (size_t)4*elempack*out_elempack, elempack*out_elempack);
  215. for (int q=0; q+(out_elempack-1)<num_output; q+=out_elempack)
  216. {
  217. float* g00 = weight_data_packed.row(q/out_elempack);
  218. for (int p=0; p+(elempack-1)<num_input; p+=elempack)
  219. {
  220. for (int i=0; i<out_elempack; i++)
  221. {
  222. const float* k0 = weight_data_r2.row(q+i);
  223. k0 += p;
  224. for (int j=0; j<elempack; j++)
  225. {
  226. g00[0] = k0[j];
  227. g00++;
  228. }
  229. }
  230. }
  231. }
  232. }
  233. if (opt.use_image_storage)
  234. {
  235. cmd.record_upload(weight_data_packed, weight_data_gpu_image, opt);
  236. }
  237. else
  238. {
  239. cmd.record_upload(weight_data_packed, weight_data_gpu, opt);
  240. }
  241. if (bias_term)
  242. {
  243. Mat bias_data_packed;
  244. convert_packing(bias_data, bias_data_packed, out_elempack);
  245. if (opt.use_image_storage)
  246. {
  247. cmd.record_upload(bias_data_packed, bias_data_gpu_image, opt);
  248. }
  249. else
  250. {
  251. cmd.record_upload(bias_data_packed, bias_data_gpu, opt);
  252. }
  253. }
  254. return 0;
  255. }
  256. int InnerProduct_vulkan::forward(const VkMat& bottom_blob, VkMat& top_blob, VkCompute& cmd, const Option& opt) const
  257. {
  258. // flatten
  259. VkMat bottom_blob_flattened = bottom_blob;
  260. {
  261. Option opt_flatten = opt;
  262. opt_flatten.blob_vkallocator = opt.workspace_vkallocator;
  263. flatten->forward(bottom_blob, bottom_blob_flattened, cmd, opt_flatten);
  264. }
  265. size_t elemsize = bottom_blob_flattened.elemsize;
  266. int elempack = bottom_blob_flattened.elempack;
  267. int out_elempack = opt.use_shader_pack8 && num_output % 8 == 0 ? 8 : num_output % 4 == 0 ? 4 : 1;
  268. size_t out_elemsize = elemsize / elempack * out_elempack;
  269. if (opt.use_fp16_packed && !opt.use_fp16_storage)
  270. {
  271. if (out_elempack == 8) out_elemsize = 8*2u;
  272. if (out_elempack == 4) out_elemsize = 4*2u;
  273. if (out_elempack == 1) out_elemsize = 4u;
  274. }
  275. top_blob.create(num_output / out_elempack, out_elemsize, out_elempack, opt.blob_vkallocator);
  276. if (top_blob.empty())
  277. return -100;
  278. std::vector<VkMat> bindings(4);
  279. bindings[0] = bottom_blob_flattened;
  280. bindings[1] = top_blob;
  281. bindings[2] = weight_data_gpu;
  282. bindings[3] = bias_data_gpu;
  283. std::vector<vk_constant_type> constants(10);
  284. constants[0].i = bottom_blob_flattened.dims;
  285. constants[1].i = bottom_blob_flattened.w;
  286. constants[2].i = bottom_blob_flattened.h;
  287. constants[3].i = bottom_blob_flattened.c;
  288. constants[4].i = bottom_blob_flattened.cstep;
  289. constants[5].i = top_blob.dims;
  290. constants[6].i = top_blob.w;
  291. constants[7].i = top_blob.h;
  292. constants[8].i = top_blob.c;
  293. constants[9].i = top_blob.cstep;
  294. const Pipeline* pipeline = 0;
  295. if (elempack == 1 && out_elempack == 1)
  296. {
  297. pipeline = pipeline_innerproduct;
  298. }
  299. else if (elempack == 4 && out_elempack == 4)
  300. {
  301. pipeline = pipeline_innerproduct_pack4;
  302. }
  303. else if (elempack == 1 && out_elempack == 4)
  304. {
  305. pipeline = pipeline_innerproduct_pack1to4;
  306. }
  307. else if (elempack == 4 && out_elempack == 1)
  308. {
  309. pipeline = pipeline_innerproduct_pack4to1;
  310. }
  311. else if (elempack == 8 && out_elempack == 8)
  312. {
  313. pipeline = pipeline_innerproduct_pack8;
  314. }
  315. else if (elempack == 1 && out_elempack == 8)
  316. {
  317. pipeline = pipeline_innerproduct_pack1to8;
  318. }
  319. else if (elempack == 4 && out_elempack == 8)
  320. {
  321. pipeline = pipeline_innerproduct_pack4to8;
  322. }
  323. else if (elempack == 8 && out_elempack == 4)
  324. {
  325. pipeline = pipeline_innerproduct_pack8to4;
  326. }
  327. else if (elempack == 8 && out_elempack == 1)
  328. {
  329. pipeline = pipeline_innerproduct_pack8to1;
  330. }
  331. cmd.record_pipeline(pipeline, bindings, constants, top_blob);
  332. return 0;
  333. }
  334. int InnerProduct_vulkan::forward(const VkImageMat& bottom_blob, VkImageMat& top_blob, VkCompute& cmd, const Option& opt) const
  335. {
  336. // flatten
  337. VkImageMat bottom_blob_flattened = bottom_blob;
  338. {
  339. Option opt_flatten = opt;
  340. opt_flatten.blob_vkallocator = opt.workspace_vkallocator;
  341. flatten->forward(bottom_blob, bottom_blob_flattened, cmd, opt_flatten);
  342. }
  343. size_t elemsize = bottom_blob_flattened.elemsize;
  344. int elempack = bottom_blob_flattened.elempack;
  345. int out_elempack = opt.use_shader_pack8 && num_output % 8 == 0 ? 8 : num_output % 4 == 0 ? 4 : 1;
  346. size_t out_elemsize = elemsize / elempack * out_elempack;
  347. if (opt.use_fp16_packed && !opt.use_fp16_storage)
  348. {
  349. if (out_elempack == 8) out_elemsize = 8*2u;
  350. if (out_elempack == 4) out_elemsize = 4*2u;
  351. if (out_elempack == 1) out_elemsize = 4u;
  352. }
  353. top_blob.create(num_output / out_elempack, out_elemsize, out_elempack, opt.blob_vkallocator);
  354. if (top_blob.empty())
  355. return -100;
  356. std::vector<VkImageMat> bindings(4);
  357. bindings[0] = bottom_blob_flattened;
  358. bindings[1] = top_blob;
  359. bindings[2] = weight_data_gpu_image;
  360. bindings[3] = bias_data_gpu_image;
  361. std::vector<vk_constant_type> constants(10);
  362. constants[0].i = bottom_blob_flattened.dims;
  363. constants[1].i = bottom_blob_flattened.w;
  364. constants[2].i = bottom_blob_flattened.h;
  365. constants[3].i = bottom_blob_flattened.c;
  366. constants[4].i = 0;//bottom_blob_flattened.cstep;
  367. constants[5].i = top_blob.dims;
  368. constants[6].i = top_blob.w;
  369. constants[7].i = top_blob.h;
  370. constants[8].i = top_blob.c;
  371. constants[9].i = 0;//top_blob.cstep;
  372. const Pipeline* pipeline = 0;
  373. if (elempack == 1 && out_elempack == 1)
  374. {
  375. pipeline = pipeline_innerproduct;
  376. }
  377. else if (elempack == 4 && out_elempack == 4)
  378. {
  379. pipeline = pipeline_innerproduct_pack4;
  380. }
  381. else if (elempack == 1 && out_elempack == 4)
  382. {
  383. pipeline = pipeline_innerproduct_pack1to4;
  384. }
  385. else if (elempack == 4 && out_elempack == 1)
  386. {
  387. pipeline = pipeline_innerproduct_pack4to1;
  388. }
  389. else if (elempack == 8 && out_elempack == 8)
  390. {
  391. pipeline = pipeline_innerproduct_pack8;
  392. }
  393. else if (elempack == 1 && out_elempack == 8)
  394. {
  395. pipeline = pipeline_innerproduct_pack1to8;
  396. }
  397. else if (elempack == 4 && out_elempack == 8)
  398. {
  399. pipeline = pipeline_innerproduct_pack4to8;
  400. }
  401. else if (elempack == 8 && out_elempack == 4)
  402. {
  403. pipeline = pipeline_innerproduct_pack8to4;
  404. }
  405. else if (elempack == 8 && out_elempack == 1)
  406. {
  407. pipeline = pipeline_innerproduct_pack8to1;
  408. }
  409. cmd.record_pipeline(pipeline, bindings, constants, top_blob);
  410. return 0;
  411. }
  412. } // namespace ncnn