diff --git a/src/layer.cpp b/src/layer.cpp index ed28091fafa9..253430a19740 100644 --- a/src/layer.cpp +++ b/src/layer.cpp @@ -317,11 +317,6 @@ class Layer_final : public Layer virtual int load_param(const ParamDict& pd) { set_layer_properties(); - { - int ret = layer_cpu->load_param(pd); - if (ret) - return ret; - } #if NCNN_VULKAN if (layer_vulkan && vkdev) { @@ -329,18 +324,19 @@ class Layer_final : public Layer if (ret) return ret; } + else #endif // NCNN_VULKAN + { + int ret = layer_cpu->load_param(pd); + if (ret) + return ret; + } get_layer_properties(); return 0; } virtual int load_model(const ModelBin& mb) { - { - int ret = layer_cpu->load_model(mb); - if (ret) - return ret; - } #if NCNN_VULKAN if (layer_vulkan && vkdev) { @@ -348,7 +344,13 @@ class Layer_final : public Layer if (ret) return ret; } + else #endif // NCNN_VULKAN + { + int ret = layer_cpu->load_model(mb); + if (ret) + return ret; + } get_layer_properties(); return 0; } @@ -356,11 +358,6 @@ class Layer_final : public Layer virtual int create_pipeline(const Option& opt) { set_layer_properties(); - { - int ret = layer_cpu->create_pipeline(opt); - if (ret) - return ret; - } #if NCNN_VULKAN if (layer_vulkan && vkdev) { @@ -368,18 +365,19 @@ class Layer_final : public Layer if (ret) return ret; } + else #endif // NCNN_VULKAN + { + int ret = layer_cpu->create_pipeline(opt); + if (ret) + return ret; + } get_layer_properties(); return 0; } virtual int destroy_pipeline(const Option& opt) { - { - int ret = layer_cpu->destroy_pipeline(opt); - if (ret) - return ret; - } #if NCNN_VULKAN if (layer_vulkan && vkdev) { @@ -387,7 +385,13 @@ class Layer_final : public Layer if (ret) return ret; } + else #endif // NCNN_VULKAN + { + int ret = layer_cpu->destroy_pipeline(opt); + if (ret) + return ret; + } return 0; } diff --git a/src/layer/vulkan/convolution1d_vulkan.cpp b/src/layer/vulkan/convolution1d_vulkan.cpp index a69a48d822ea..12162c5b7fc0 100644 --- a/src/layer/vulkan/convolution1d_vulkan.cpp +++ b/src/layer/vulkan/convolution1d_vulkan.cpp @@ -29,15 +29,23 @@ Convolution1D_vulkan::Convolution1D_vulkan() pipeline_convolution1d = 0; } -int Convolution1D_vulkan::create_pipeline(const Option& _opt) +int Convolution1D_vulkan::load_param(const ParamDict& pd) { + int ret = Convolution1D::load_param(pd); + if (ret) + return ret; + if (dynamic_weight) { support_vulkan = false; support_image_storage = false; - return 0; } + return 0; +} + +int Convolution1D_vulkan::create_pipeline(const Option& _opt) +{ Option opt = _opt; const int maxk = kernel_w; diff --git a/src/layer/vulkan/convolution1d_vulkan.h b/src/layer/vulkan/convolution1d_vulkan.h index f01e1523161c..28d692ae618f 100644 --- a/src/layer/vulkan/convolution1d_vulkan.h +++ b/src/layer/vulkan/convolution1d_vulkan.h @@ -24,6 +24,8 @@ class Convolution1D_vulkan : public Convolution1D public: Convolution1D_vulkan(); + virtual int load_param(const ParamDict& pd); + virtual int create_pipeline(const Option& opt); virtual int destroy_pipeline(const Option& opt); diff --git a/src/layer/vulkan/convolution_vulkan.cpp b/src/layer/vulkan/convolution_vulkan.cpp index 4b93baefb1a7..5e3bffca51b6 100644 --- a/src/layer/vulkan/convolution_vulkan.cpp +++ b/src/layer/vulkan/convolution_vulkan.cpp @@ -43,15 +43,23 @@ Convolution_vulkan::Convolution_vulkan() reshape_w = 0; } -int Convolution_vulkan::create_pipeline(const Option& _opt) +int Convolution_vulkan::load_param(const ParamDict& pd) { + int ret = Convolution::load_param(pd); + if (ret) + return ret; + if (dynamic_weight) { support_vulkan = false; support_image_storage = false; - return 0; } + return 0; +} + +int Convolution_vulkan::create_pipeline(const Option& _opt) +{ Option opt = _opt; const Mat& shape = bottom_shapes.empty() ? Mat() : bottom_shapes[0]; const Mat& out_shape = top_shapes.empty() ? Mat() : top_shapes[0]; diff --git a/src/layer/vulkan/convolution_vulkan.h b/src/layer/vulkan/convolution_vulkan.h index 90d6471d58b4..fa4bdbc5350d 100644 --- a/src/layer/vulkan/convolution_vulkan.h +++ b/src/layer/vulkan/convolution_vulkan.h @@ -24,6 +24,8 @@ class Convolution_vulkan : public Convolution public: Convolution_vulkan(); + virtual int load_param(const ParamDict& pd); + virtual int create_pipeline(const Option& opt); virtual int destroy_pipeline(const Option& opt); diff --git a/src/layer/vulkan/convolutiondepthwise_vulkan.cpp b/src/layer/vulkan/convolutiondepthwise_vulkan.cpp index 0fbae3341842..23405a6269d8 100644 --- a/src/layer/vulkan/convolutiondepthwise_vulkan.cpp +++ b/src/layer/vulkan/convolutiondepthwise_vulkan.cpp @@ -41,15 +41,23 @@ ConvolutionDepthWise_vulkan::ConvolutionDepthWise_vulkan() pipeline_convolutiondepthwise_group_pack8to1 = 0; } -int ConvolutionDepthWise_vulkan::create_pipeline(const Option& _opt) +int ConvolutionDepthWise_vulkan::load_param(const ParamDict& pd) { + int ret = ConvolutionDepthWise::load_param(pd); + if (ret) + return ret; + if (dynamic_weight) { support_vulkan = false; support_image_storage = false; - return 0; } + return 0; +} + +int ConvolutionDepthWise_vulkan::create_pipeline(const Option& _opt) +{ Option opt = _opt; const Mat& shape = bottom_shapes.empty() ? Mat() : bottom_shapes[0]; const Mat& out_shape = top_shapes.empty() ? Mat() : top_shapes[0]; diff --git a/src/layer/vulkan/convolutiondepthwise_vulkan.h b/src/layer/vulkan/convolutiondepthwise_vulkan.h index 47785b707e27..7a6cfe1f6403 100644 --- a/src/layer/vulkan/convolutiondepthwise_vulkan.h +++ b/src/layer/vulkan/convolutiondepthwise_vulkan.h @@ -24,6 +24,8 @@ class ConvolutionDepthWise_vulkan : public ConvolutionDepthWise public: ConvolutionDepthWise_vulkan(); + virtual int load_param(const ParamDict& pd); + virtual int create_pipeline(const Option& opt); virtual int destroy_pipeline(const Option& opt); diff --git a/src/layer/vulkan/deconvolution_vulkan.cpp b/src/layer/vulkan/deconvolution_vulkan.cpp index de530e546211..33d56e34ada9 100644 --- a/src/layer/vulkan/deconvolution_vulkan.cpp +++ b/src/layer/vulkan/deconvolution_vulkan.cpp @@ -33,15 +33,23 @@ Deconvolution_vulkan::Deconvolution_vulkan() pipeline_deconvolution_col2im = 0; } -int Deconvolution_vulkan::create_pipeline(const Option& _opt) +int Deconvolution_vulkan::load_param(const ParamDict& pd) { + int ret = Deconvolution::load_param(pd); + if (ret) + return ret; + if (dynamic_weight) { support_vulkan = false; support_image_storage = false; - return 0; } + return 0; +} + +int Deconvolution_vulkan::create_pipeline(const Option& _opt) +{ Option opt = _opt; const Mat& shape = bottom_shapes.empty() ? Mat() : bottom_shapes[0]; const Mat& out_shape = top_shapes.empty() ? Mat() : top_shapes[0]; diff --git a/src/layer/vulkan/deconvolution_vulkan.h b/src/layer/vulkan/deconvolution_vulkan.h index a4bee03c5e48..6e18c38d681f 100644 --- a/src/layer/vulkan/deconvolution_vulkan.h +++ b/src/layer/vulkan/deconvolution_vulkan.h @@ -24,6 +24,8 @@ class Deconvolution_vulkan : public Deconvolution public: Deconvolution_vulkan(); + virtual int load_param(const ParamDict& pd); + virtual int create_pipeline(const Option& opt); virtual int destroy_pipeline(const Option& opt); diff --git a/src/layer/vulkan/deconvolutiondepthwise_vulkan.cpp b/src/layer/vulkan/deconvolutiondepthwise_vulkan.cpp index cf8744396198..08e6b1a23c04 100644 --- a/src/layer/vulkan/deconvolutiondepthwise_vulkan.cpp +++ b/src/layer/vulkan/deconvolutiondepthwise_vulkan.cpp @@ -42,15 +42,23 @@ DeconvolutionDepthWise_vulkan::DeconvolutionDepthWise_vulkan() pipeline_deconvolutiondepthwise_group_pack8to1 = 0; } -int DeconvolutionDepthWise_vulkan::create_pipeline(const Option& _opt) +int DeconvolutionDepthWise_vulkan::load_param(const ParamDict& pd) { + int ret = DeconvolutionDepthWise::load_param(pd); + if (ret) + return ret; + if (dynamic_weight) { support_vulkan = false; support_image_storage = false; - return 0; } + return 0; +} + +int DeconvolutionDepthWise_vulkan::create_pipeline(const Option& _opt) +{ Option opt = _opt; const Mat& shape = bottom_shapes.empty() ? Mat() : bottom_shapes[0]; const Mat& out_shape = top_shapes.empty() ? Mat() : top_shapes[0]; diff --git a/src/layer/vulkan/deconvolutiondepthwise_vulkan.h b/src/layer/vulkan/deconvolutiondepthwise_vulkan.h index 6ea7931e32a2..5346de8e6288 100644 --- a/src/layer/vulkan/deconvolutiondepthwise_vulkan.h +++ b/src/layer/vulkan/deconvolutiondepthwise_vulkan.h @@ -24,6 +24,8 @@ class DeconvolutionDepthWise_vulkan : public DeconvolutionDepthWise public: DeconvolutionDepthWise_vulkan(); + virtual int load_param(const ParamDict& pd); + virtual int create_pipeline(const Option& opt); virtual int destroy_pipeline(const Option& opt); diff --git a/src/net.cpp b/src/net.cpp index a7198d0a16e1..0d3c1a1272b5 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1377,9 +1377,15 @@ int Net::load_param(const DataReader& dr) SCAN_VALUE("%d", top_count) Layer* layer = create_overwrite_builtin_layer(layer_type); +#if NCNN_VULKAN + if (!layer && opt.use_vulkan_compute && d->vkdev) + { + layer = create_layer_vulkan(layer_type); + } +#endif // NCNN_VULKAN if (!layer) { - layer = create_layer(layer_type); + layer = create_layer_cpu(layer_type); } if (!layer) { @@ -1402,7 +1408,6 @@ int Net::load_param(const DataReader& dr) // NCNN_LOGE("new layer %d %s", i, layer_name); layer->bottoms.resize(bottom_count); - for (int j = 0; j < bottom_count; j++) { char bottom_name[256]; @@ -1446,20 +1451,16 @@ int Net::load_param(const DataReader& dr) blob_index++; } + int layer_support_vulkan = layer->support_vulkan; + // layer specific params int pdlr = pd.load_param(dr); if (pdlr != 0) { - NCNN_LOGE("ParamDict load_param %d %s failed", i, layer->name.c_str()); + NCNN_LOGE("ParamDict load_param %d %s failed", i, layer_name); continue; } - if (layer->support_int8_storage) - { - // no int8 gpu support yet - opt.use_vulkan_compute = false; - } - // pull out top shape hints Mat shape_hints = pd.get(30, Mat()); if (!shape_hints.empty()) @@ -1503,13 +1504,70 @@ int Net::load_param(const DataReader& dr) // pull out layer specific feature disabled set layer->featmask = pd.get(31, 0); + if (layer->support_int8_storage) + { + // no int8 gpu support yet + opt.use_vulkan_compute = false; + } + + Option opt1 = get_masked_option(opt, layer->featmask); +#if NCNN_VULKAN + if (opt1.use_vulkan_compute) + { + if (!layer->support_image_storage) opt1.use_image_storage = false; + } + else + { + layer->vkdev = 0; + layer->support_vulkan = false; + } +#endif // NCNN_VULKAN + int lr = layer->load_param(pd); if (lr != 0) { - NCNN_LOGE("layer load_param %d %s failed", i, layer->name.c_str()); + NCNN_LOGE("layer load_param %d %s failed", i, layer_name); continue; } + if (layer_support_vulkan && (!layer->support_vulkan || !opt1.use_vulkan_compute)) + { + // vulkan layer cannot handle these param, recreate cpu layer + Layer* layer_cpu = create_overwrite_builtin_layer(layer_type); + if (!layer_cpu) + { + layer_cpu = create_layer_cpu(layer_type); + } + if (!layer_cpu) + { + layer_cpu = create_custom_layer(layer_type); + } + if (!layer_cpu) + { + NCNN_LOGE("layer %s not exists or registered", layer_type); + clear(); + return -1; + } + + layer_cpu->type = layer->type; + layer_cpu->name = layer->name; + layer_cpu->bottoms = layer->bottoms; + layer_cpu->tops = layer->tops; + layer_cpu->bottom_shapes = layer->bottom_shapes; + layer_cpu->top_shapes = layer->top_shapes; + layer_cpu->featmask = layer->featmask; + + int lr = layer_cpu->load_param(pd); + if (lr != 0) + { + NCNN_LOGE("layer load_param %d %s failed", i, layer_name); + continue; + } + + delete layer; + layer = layer_cpu; + } + d->layers[i] = layer; } @@ -1611,9 +1669,15 @@ int Net::load_param_bin(const DataReader& dr) READ_VALUE(top_count) Layer* layer = create_overwrite_builtin_layer(typeindex); +#if NCNN_VULKAN + if (!layer && opt.use_vulkan_compute && d->vkdev) + { + layer = create_layer_vulkan(typeindex); + } +#endif // NCNN_VULKAN if (!layer) { - layer = create_layer(typeindex); + layer = create_layer_cpu(typeindex); } if (!layer) { @@ -1665,24 +1729,16 @@ int Net::load_param_bin(const DataReader& dr) layer->tops[j] = top_blob_index; } + int layer_support_vulkan = layer->support_vulkan; + // layer specific params int pdlr = pd.load_param_bin(dr); if (pdlr != 0) { -#if NCNN_STRING - NCNN_LOGE("ParamDict load_param %d %s failed", i, layer->name.c_str()); -#else - NCNN_LOGE("ParamDict load_param %d failed", i); -#endif + NCNN_LOGE("ParamDict load_param_bin %d failed", i); continue; } - if (layer->support_int8_storage) - { - // no int8 gpu support yet - opt.use_vulkan_compute = false; - } - // pull out top blob shape hints Mat shape_hints = pd.get(30, Mat()); if (!shape_hints.empty()) @@ -1729,14 +1785,68 @@ int Net::load_param_bin(const DataReader& dr) int lr = layer->load_param(pd); if (lr != 0) { -#if NCNN_STRING - NCNN_LOGE("layer load_param %d %s failed", i, layer->name.c_str()); -#else NCNN_LOGE("layer load_param %d failed", i); -#endif continue; } + if (layer->support_int8_storage) + { + // no int8 gpu support yet + opt.use_vulkan_compute = false; + } + + Option opt1 = get_masked_option(opt, layer->featmask); +#if NCNN_VULKAN + if (opt1.use_vulkan_compute) + { + if (!layer->support_image_storage) opt1.use_image_storage = false; + } + else + { + layer->vkdev = 0; + layer->support_vulkan = false; + } +#endif // NCNN_VULKAN + + if (layer_support_vulkan && (!layer->support_vulkan || !opt1.use_vulkan_compute)) + { + // vulkan layer cannot handle these param, recreate cpu layer + Layer* layer_cpu = create_overwrite_builtin_layer(typeindex); + if (!layer_cpu) + { + layer_cpu = create_layer_cpu(typeindex); + } + if (!layer_cpu) + { + int custom_index = typeindex & ~LayerType::CustomBit; + layer_cpu = create_custom_layer(custom_index); + } + if (!layer_cpu) + { + NCNN_LOGE("layer %d not exists or registered", typeindex); + clear(); + return -1; + } + + layer_cpu->type = layer->type; + layer_cpu->name = layer->name; + layer_cpu->bottoms = layer->bottoms; + layer_cpu->tops = layer->tops; + layer_cpu->bottom_shapes = layer->bottom_shapes; + layer_cpu->top_shapes = layer->top_shapes; + layer_cpu->featmask = layer->featmask; + + int lr = layer_cpu->load_param(pd); + if (lr != 0) + { + NCNN_LOGE("layer load_param %d failed", i); + continue; + } + + delete layer; + layer = layer_cpu; + } + d->layers[i] = layer; } @@ -1796,24 +1906,7 @@ int Net::load_model(const DataReader& dr) break; } - if (layer->support_int8_storage) - { - // no int8 gpu support yet - opt.use_vulkan_compute = false; - } - Option opt1 = get_masked_option(opt, layer->featmask); -#if NCNN_VULKAN - if (opt1.use_vulkan_compute) - { - if (!layer->support_image_storage) opt1.use_image_storage = false; - } - else - { - layer->vkdev = 0; - layer->support_vulkan = false; - } -#endif // NCNN_VULKAN int cret = layer->create_pipeline(opt1); if (cret != 0) diff --git a/tests/testutil.cpp b/tests/testutil.cpp index b5f2fd34148f..1bcc6ff5237c 100644 --- a/tests/testutil.cpp +++ b/tests/testutil.cpp @@ -630,6 +630,8 @@ int test_layer_gpu(int typeindex, const ncnn::ParamDict& pd, const std::vectorload_param(pd); + if (!op->support_vulkan) { delete op; @@ -651,8 +653,6 @@ int test_layer_gpu(int typeindex, const ncnn::ParamDict& pd, const std::vectortop_shapes = top_shapes; } - op->load_param(pd); - if (op->one_blob_only && a.size() != 1) { fprintf(stderr, "layer with one_blob_only but consume multiple inputs\n"); @@ -1130,6 +1130,8 @@ int test_layer_gpu(int typeindex, const ncnn::ParamDict& pd, const std::vectorload_param(pd); + if (!op->support_vulkan) { delete op; @@ -1153,8 +1155,6 @@ int test_layer_gpu(int typeindex, const ncnn::ParamDict& pd, const std::vectortop_shapes[0] = top_shape; } - op->load_param(pd); - ncnn::ModelBinFromMatArray mb(weights.data()); op->load_model(mb);