From bb56b5439f98070a5ae06d9538b6b714fa762bdf Mon Sep 17 00:00:00 2001 From: nihuini Date: Tue, 2 Jun 2020 15:12:17 +0800 Subject: [PATCH] fix vkmat download on integrated gpu, workaround priorbox fp16s with online spirv, fix #1700 fix #1805 --- src/command.cpp | 30 ++- src/gpu.cpp | 15 +- src/layer/vulkan/packing_vulkan.cpp | 288 +++++++++++++-------------- src/layer/vulkan/priorbox_vulkan.cpp | 10 + 4 files changed, 177 insertions(+), 166 deletions(-) diff --git a/src/command.cpp b/src/command.cpp index 289518d40..6752bb639 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -144,6 +144,7 @@ void VkCompute::record_upload(const Mat& src, VkMat& dst, const Option& opt) else dst_elempack = elemcount % 4 == 0 ? 4 : 1; + // gpu cast to fp16 on the fly (integrated gpu) vkdev->convert_packing(dst_staging, dst, dst_elempack, *this, opt); } @@ -206,6 +207,7 @@ void VkCompute::record_upload(const Mat& src, VkImageMat& dst, const Option& opt else dst_elempack = elemcount % 4 == 0 ? 4 : 1; + // gpu cast to fp16 on the fly (integrated gpu) vkdev->convert_packing(dst_staging, dst, dst_elempack, *this, opt); } @@ -226,14 +228,21 @@ void VkCompute::record_download(const VkMat& src, Mat& dst, const Option& opt) else dst_elempack = 1; + // gpu cast to fp32 on the fly (integrated gpu) + Option opt_staging = opt; + if (vkdev->info.type == 1) + { + opt_staging.use_fp16_packed = false; + opt_staging.use_fp16_storage = false; + } + VkMat dst_staging; - if (opt.blob_vkallocator->mappable) + if (opt_staging.blob_vkallocator->mappable) { - vkdev->convert_packing(src, dst_staging, dst_elempack, *this, opt); + vkdev->convert_packing(src, dst_staging, dst_elempack, *this, opt_staging); } else { - Option opt_staging = opt; opt_staging.blob_vkallocator = opt.staging_vkallocator; vkdev->convert_packing(src, dst_staging, dst_elempack, *this, opt_staging); } @@ -310,7 +319,6 @@ void VkCompute::record_download(const VkMat& src, Mat& dst, const Option& opt) if (dims == 3) dst.create(dst_fp16.w, dst_fp16.h, dst_fp16.c, (size_t)(dst_fp16.elempack * 4u), dst_fp16.elempack, opt.blob_allocator); - download_post_mats_fp16.push_back(dst_fp16); download_post_mats.push_back(dst); record r; @@ -348,14 +356,21 @@ void VkCompute::record_download(const VkImageMat& src, Mat& dst, const Option& o else dst_elempack = 1; + // gpu cast to fp32 on the fly (integrated gpu) + Option opt_staging = opt; + if (vkdev->info.type == 1) + { + opt_staging.use_fp16_packed = false; + opt_staging.use_fp16_storage = false; + } + VkMat dst_staging; - if (opt.blob_vkallocator->mappable) + if (opt_staging.blob_vkallocator->mappable) { - vkdev->convert_packing(src, dst_staging, dst_elempack, *this, opt); + vkdev->convert_packing(src, dst_staging, dst_elempack, *this, opt_staging); } else { - Option opt_staging = opt; opt_staging.blob_vkallocator = opt.staging_vkallocator; vkdev->convert_packing(src, dst_staging, dst_elempack, *this, opt_staging); } @@ -432,7 +447,6 @@ void VkCompute::record_download(const VkImageMat& src, Mat& dst, const Option& o if (dims == 3) dst.create(dst_fp16.w, dst_fp16.h, dst_fp16.c, (size_t)(dst_fp16.elempack * 4u), dst_fp16.elempack, opt.blob_allocator); - download_post_mats_fp16.push_back(dst_fp16); download_post_mats.push_back(dst); record r; diff --git a/src/gpu.cpp b/src/gpu.cpp index 9192182e6..bf1ed0f1c 100644 --- a/src/gpu.cpp +++ b/src/gpu.cpp @@ -1687,7 +1687,7 @@ void VulkanDevice::convert_packing(const VkMat& src, VkMat& dst, int dst_elempac Option opt = _opt; opt.use_image_storage = false; - int cast_type_from_index = src.elemsize == src.elempack * 4u ? 0 : opt.use_fp16_storage ? 2 : 1; + int cast_type_from_index = src.elemsize == src.elempack * 4u ? 0 : src.elemsize == src.elempack * 2u && info.support_fp16_storage ? 2 : 1; int cast_type_to_index = opt.use_fp16_storage ? 2 : opt.use_fp16_packed && dst_elempack % 4 == 0 ? 1 : 0; int packing_type_to_index = dst_elempack == 1 ? 0 : dst_elempack == 4 ? 1 : 2; @@ -1705,7 +1705,7 @@ void VulkanDevice::convert_packing(const VkImageMat& src, VkImageMat& dst, int d return; } - int cast_type_from_index = src.elemsize == src.elempack * 4u ? 0 : opt.use_fp16_storage ? 2 : 1; + int cast_type_from_index = src.elemsize == src.elempack * 4u ? 0 : src.elemsize == src.elempack * 2u && info.support_fp16_storage ? 2 : 1; int cast_type_to_index = opt.use_fp16_storage ? 2 : opt.use_fp16_packed && dst_elempack % 4 == 0 ? 1 : 0; int packing_type_to_index = dst_elempack == 1 ? 0 : dst_elempack == 4 ? 1 : 2; @@ -1723,7 +1723,7 @@ void VulkanDevice::convert_packing(const VkMat& src, VkImageMat& dst, int dst_el return; } - int cast_type_from_index = src.elemsize == src.elempack * 4u ? 0 : opt.use_fp16_storage ? 2 : 1; + int cast_type_from_index = src.elemsize == src.elempack * 4u ? 0 : src.elemsize == src.elempack * 2u && info.support_fp16_storage ? 2 : 1; int cast_type_to_index = opt.use_fp16_storage ? 2 : opt.use_fp16_packed && dst_elempack % 4 == 0 ? 1 : 0; int packing_type_to_index = dst_elempack == 1 ? 0 : dst_elempack == 4 ? 1 : 2; @@ -1741,7 +1741,7 @@ void VulkanDevice::convert_packing(const VkImageMat& src, VkMat& dst, int dst_el return; } - int cast_type_from_index = src.elemsize == src.elempack * 4u ? 0 : opt.use_fp16_storage ? 2 : 1; + int cast_type_from_index = src.elemsize == src.elempack * 4u ? 0 : src.elemsize == src.elempack * 2u && info.support_fp16_storage ? 2 : 1; int cast_type_to_index = opt.use_fp16_storage ? 2 : opt.use_fp16_packed && dst_elempack % 4 == 0 ? 1 : 0; int packing_type_to_index = dst_elempack == 1 ? 0 : dst_elempack == 4 ? 1 : 2; @@ -2082,7 +2082,7 @@ int VulkanDevice::create_utility_operator() if (!info.support_fp16_storage && opt.use_fp16_storage) continue; - // from pack1 | pack4 | pack8 + // to pack1 | pack4 | pack8 for (int k=0; k<3; k++) { // enable pack8 for pack8to1/pack8to4 @@ -2141,10 +2141,11 @@ void VulkanDevice::destroy_utility_operator() if (!info.support_fp16_storage && opt.use_fp16_storage) continue; - // from pack1 | pack4 | pack8 + // to pack1 | pack4 | pack8 for (int k=0; k<3; k++) { - opt.use_shader_pack8 = (k == 2 || k == 2); + // enable pack8 for pack8to1/pack8to4 + opt.use_shader_pack8 = true; ncnn::Layer* uop = uop_packing[i0][i1][j0][j1][k]; diff --git a/src/layer/vulkan/packing_vulkan.cpp b/src/layer/vulkan/packing_vulkan.cpp index ac41a225a..599f7215a 100644 --- a/src/layer/vulkan/packing_vulkan.cpp +++ b/src/layer/vulkan/packing_vulkan.cpp @@ -42,23 +42,36 @@ int Packing_vulkan::create_pipeline(const Option& _opt) const Mat& out_shape = top_shapes.empty() ? Mat() : top_shapes[0]; size_t out_elemsize; - if (opt.use_fp16_storage) + if (cast_type_to == 0) { - out_elemsize = out_elempack * 2u; + if (opt.use_fp16_storage) + { + out_elemsize = out_elempack * 2u; + } + else if (opt.use_fp16_packed) + { + if (out_elempack == 8) out_elemsize = 8*2u; + if (out_elempack == 4) out_elemsize = 4*2u; + if (out_elempack == 1) out_elemsize = 4u; + } + else + { + out_elemsize = out_elempack * 4u; + } } - else if (opt.use_fp16_packed) + else if (cast_type_to == 1) { - out_elemsize = out_elempack == 1 ? 4u : out_elempack * 2u; + out_elemsize = out_elempack * 4u; } - else + else if (cast_type_to == 2) { - out_elemsize = out_elempack * 4u; + if (out_elempack == 8) out_elemsize = 8*2u; + if (out_elempack == 4) out_elemsize = 4*2u; + if (out_elempack == 1) out_elemsize = 4u; } - - // type casting override - if (cast_type_to == 1) + else // if (cast_type_to == 3) { - out_elemsize = out_elempack * 4u; + out_elemsize = out_elempack * 2u; } Mat out_shape_packed; @@ -272,6 +285,39 @@ int Packing_vulkan::forward(const VkMat& bottom_blob, VkMat& top_blob, VkCompute } } + size_t out_elemsize; + if (cast_type_to == 0) + { + if (opt.use_fp16_storage) + { + out_elemsize = out_elempack * 2u; + } + else if (opt.use_fp16_packed) + { + if (out_elempack == 8) out_elemsize = 8*2u; + if (out_elempack == 4) out_elemsize = 4*2u; + if (out_elempack == 1) out_elemsize = 4u; + } + else + { + out_elemsize = out_elempack * 4u; + } + } + else if (cast_type_to == 1) + { + out_elemsize = out_elempack * 4u; + } + else if (cast_type_to == 2) + { + if (out_elempack == 8) out_elemsize = 8*2u; + if (out_elempack == 4) out_elemsize = 4*2u; + if (out_elempack == 1) out_elemsize = 4u; + } + else // if (cast_type_to == 3) + { + out_elemsize = out_elempack * 2u; + } + if (dims == 1) { if (opt.use_fp16_storage && out_elempack == 1 && cast_type_from == cast_type_to && bottom_blob.allocator == opt.blob_vkallocator) @@ -285,19 +331,6 @@ int Packing_vulkan::forward(const VkMat& bottom_blob, VkMat& top_blob, VkCompute } int outw = (w * elempack + out_elempack - 1) / out_elempack; - size_t out_elemsize = elemsize / elempack * out_elempack; - if (opt.use_fp16_packed && !opt.use_fp16_storage) - { - if (out_elempack == 8) out_elemsize = 8*2u; - if (out_elempack == 4) out_elemsize = 4*2u; - if (out_elempack == 1) out_elemsize = 4u; - } - - // type casting override - if (cast_type_to == 1) - { - out_elemsize = out_elempack * 4u; - } top_blob.create(outw, out_elemsize, out_elempack, opt.blob_vkallocator); if (top_blob.empty()) @@ -307,19 +340,6 @@ int Packing_vulkan::forward(const VkMat& bottom_blob, VkMat& top_blob, VkCompute if (dims == 2) { int outh = (h * elempack + out_elempack - 1) / out_elempack; - size_t out_elemsize = elemsize / elempack * out_elempack; - if (opt.use_fp16_packed && !opt.use_fp16_storage) - { - if (out_elempack == 8) out_elemsize = 8*2u; - if (out_elempack == 4) out_elemsize = 4*2u; - if (out_elempack == 1) out_elemsize = 4u; - } - - // type casting override - if (cast_type_to == 1) - { - out_elemsize = out_elempack * 4u; - } top_blob.create(w, outh, out_elemsize, out_elempack, opt.blob_vkallocator); if (top_blob.empty()) @@ -329,19 +349,6 @@ int Packing_vulkan::forward(const VkMat& bottom_blob, VkMat& top_blob, VkCompute if (dims == 3) { int outc = (channels * elempack + out_elempack - 1) / out_elempack; - size_t out_elemsize = elemsize / elempack * out_elempack; - if (opt.use_fp16_packed && !opt.use_fp16_storage) - { - if (out_elempack == 8) out_elemsize = 8*2u; - if (out_elempack == 4) out_elemsize = 4*2u; - if (out_elempack == 1) out_elemsize = 4u; - } - - // type casting override - if (cast_type_to == 1) - { - out_elemsize = out_elempack * 4u; - } top_blob.create(w, h, outc, out_elemsize, out_elempack, opt.blob_vkallocator); if (top_blob.empty()) @@ -425,7 +432,6 @@ int Packing_vulkan::forward(const VkImageMat& bottom_blob, VkImageMat& top_blob, int h = bottom_blob.h; int channels = bottom_blob.c; int dims = bottom_blob.dims; - size_t elemsize = bottom_blob.elemsize; if (!use_padding) { @@ -447,22 +453,42 @@ int Packing_vulkan::forward(const VkImageMat& bottom_blob, VkImageMat& top_blob, } } - if (dims == 1) + size_t out_elemsize; + if (cast_type_to == 0) { - int outw = (w * elempack + out_elempack - 1) / out_elempack; - size_t out_elemsize = elemsize / elempack * out_elempack; - if (opt.use_fp16_packed && !opt.use_fp16_storage) + if (opt.use_fp16_storage) + { + out_elemsize = out_elempack * 2u; + } + else if (opt.use_fp16_packed) { if (out_elempack == 8) out_elemsize = 8*2u; if (out_elempack == 4) out_elemsize = 4*2u; if (out_elempack == 1) out_elemsize = 4u; } - - // type casting override - if (cast_type_to == 1) + else { out_elemsize = out_elempack * 4u; } + } + else if (cast_type_to == 1) + { + out_elemsize = out_elempack * 4u; + } + else if (cast_type_to == 2) + { + if (out_elempack == 8) out_elemsize = 8*2u; + if (out_elempack == 4) out_elemsize = 4*2u; + if (out_elempack == 1) out_elemsize = 4u; + } + else // if (cast_type_to == 3) + { + out_elemsize = out_elempack * 2u; + } + + if (dims == 1) + { + int outw = (w * elempack + out_elempack - 1) / out_elempack; top_blob.create(outw, out_elemsize, out_elempack, opt.blob_vkallocator); if (top_blob.empty()) @@ -472,19 +498,6 @@ int Packing_vulkan::forward(const VkImageMat& bottom_blob, VkImageMat& top_blob, if (dims == 2) { int outh = (h * elempack + out_elempack - 1) / out_elempack; - size_t out_elemsize = elemsize / elempack * out_elempack; - if (opt.use_fp16_packed && !opt.use_fp16_storage) - { - if (out_elempack == 8) out_elemsize = 8*2u; - if (out_elempack == 4) out_elemsize = 4*2u; - if (out_elempack == 1) out_elemsize = 4u; - } - - // type casting override - if (cast_type_to == 1) - { - out_elemsize = out_elempack * 4u; - } top_blob.create(w, outh, out_elemsize, out_elempack, opt.blob_vkallocator); if (top_blob.empty()) @@ -494,19 +507,6 @@ int Packing_vulkan::forward(const VkImageMat& bottom_blob, VkImageMat& top_blob, if (dims == 3) { int outc = (channels * elempack + out_elempack - 1) / out_elempack; - size_t out_elemsize = elemsize / elempack * out_elempack; - if (opt.use_fp16_packed && !opt.use_fp16_storage) - { - if (out_elempack == 8) out_elemsize = 8*2u; - if (out_elempack == 4) out_elemsize = 4*2u; - if (out_elempack == 1) out_elemsize = 4u; - } - - // type casting override - if (cast_type_to == 1) - { - out_elemsize = out_elempack * 4u; - } top_blob.create(w, h, outc, out_elemsize, out_elempack, opt.blob_vkallocator); if (top_blob.empty()) @@ -580,7 +580,6 @@ int Packing_vulkan::forward(const VkMat& bottom_blob, VkImageMat& top_blob, VkCo int h = bottom_blob.h; int channels = bottom_blob.c; int dims = bottom_blob.dims; - size_t elemsize = bottom_blob.elemsize; // if (!use_padding) // { @@ -589,22 +588,42 @@ int Packing_vulkan::forward(const VkMat& bottom_blob, VkImageMat& top_blob, VkCo // return -1; // } - if (dims == 1) + size_t out_elemsize; + if (cast_type_to == 0) { - int outw = (w * elempack + out_elempack - 1) / out_elempack; - size_t out_elemsize = elemsize / elempack * out_elempack; - if (opt.use_fp16_packed && !opt.use_fp16_storage) + if (opt.use_fp16_storage) + { + out_elemsize = out_elempack * 2u; + } + else if (opt.use_fp16_packed) { if (out_elempack == 8) out_elemsize = 8*2u; if (out_elempack == 4) out_elemsize = 4*2u; if (out_elempack == 1) out_elemsize = 4u; } - - // type casting override - if (cast_type_to == 1) + else { out_elemsize = out_elempack * 4u; } + } + else if (cast_type_to == 1) + { + out_elemsize = out_elempack * 4u; + } + else if (cast_type_to == 2) + { + if (out_elempack == 8) out_elemsize = 8*2u; + if (out_elempack == 4) out_elemsize = 4*2u; + if (out_elempack == 1) out_elemsize = 4u; + } + else // if (cast_type_to == 3) + { + out_elemsize = out_elempack * 2u; + } + + if (dims == 1) + { + int outw = (w * elempack + out_elempack - 1) / out_elempack; top_blob.create(outw, out_elemsize, out_elempack, opt.blob_vkallocator); if (top_blob.empty()) @@ -614,19 +633,6 @@ int Packing_vulkan::forward(const VkMat& bottom_blob, VkImageMat& top_blob, VkCo if (dims == 2) { int outh = (h * elempack + out_elempack - 1) / out_elempack; - size_t out_elemsize = elemsize / elempack * out_elempack; - if (opt.use_fp16_packed && !opt.use_fp16_storage) - { - if (out_elempack == 8) out_elemsize = 8*2u; - if (out_elempack == 4) out_elemsize = 4*2u; - if (out_elempack == 1) out_elemsize = 4u; - } - - // type casting override - if (cast_type_to == 1) - { - out_elemsize = out_elempack * 4u; - } top_blob.create(w, outh, out_elemsize, out_elempack, opt.blob_vkallocator); if (top_blob.empty()) @@ -636,19 +642,6 @@ int Packing_vulkan::forward(const VkMat& bottom_blob, VkImageMat& top_blob, VkCo if (dims == 3) { int outc = (channels * elempack + out_elempack - 1) / out_elempack; - size_t out_elemsize = elemsize / elempack * out_elempack; - if (opt.use_fp16_packed && !opt.use_fp16_storage) - { - if (out_elempack == 8) out_elemsize = 8*2u; - if (out_elempack == 4) out_elemsize = 4*2u; - if (out_elempack == 1) out_elemsize = 4u; - } - - // type casting override - if (cast_type_to == 1) - { - out_elemsize = out_elempack * 4u; - } top_blob.create(w, h, outc, out_elemsize, out_elempack, opt.blob_vkallocator); if (top_blob.empty()) @@ -722,7 +715,6 @@ int Packing_vulkan::forward(const VkImageMat& bottom_blob, VkMat& top_blob, VkCo int h = bottom_blob.h; int channels = bottom_blob.c; int dims = bottom_blob.dims; - size_t elemsize = bottom_blob.elemsize; // if (!use_padding) // { @@ -731,22 +723,42 @@ int Packing_vulkan::forward(const VkImageMat& bottom_blob, VkMat& top_blob, VkCo // return -1; // } - if (dims == 1) + size_t out_elemsize; + if (cast_type_to == 0) { - int outw = (w * elempack + out_elempack - 1) / out_elempack; - size_t out_elemsize = elemsize / elempack * out_elempack; - if (opt.use_fp16_packed && !opt.use_fp16_storage) + if (opt.use_fp16_storage) + { + out_elemsize = out_elempack * 2u; + } + else if (opt.use_fp16_packed) { if (out_elempack == 8) out_elemsize = 8*2u; if (out_elempack == 4) out_elemsize = 4*2u; if (out_elempack == 1) out_elemsize = 4u; } - - // type casting override - if (cast_type_to == 1) + else { out_elemsize = out_elempack * 4u; } + } + else if (cast_type_to == 1) + { + out_elemsize = out_elempack * 4u; + } + else if (cast_type_to == 2) + { + if (out_elempack == 8) out_elemsize = 8*2u; + if (out_elempack == 4) out_elemsize = 4*2u; + if (out_elempack == 1) out_elemsize = 4u; + } + else // if (cast_type_to == 3) + { + out_elemsize = out_elempack * 2u; + } + + if (dims == 1) + { + int outw = (w * elempack + out_elempack - 1) / out_elempack; top_blob.create(outw, out_elemsize, out_elempack, opt.blob_vkallocator); if (top_blob.empty()) @@ -756,19 +768,6 @@ int Packing_vulkan::forward(const VkImageMat& bottom_blob, VkMat& top_blob, VkCo if (dims == 2) { int outh = (h * elempack + out_elempack - 1) / out_elempack; - size_t out_elemsize = elemsize / elempack * out_elempack; - if (opt.use_fp16_packed && !opt.use_fp16_storage) - { - if (out_elempack == 8) out_elemsize = 8*2u; - if (out_elempack == 4) out_elemsize = 4*2u; - if (out_elempack == 1) out_elemsize = 4u; - } - - // type casting override - if (cast_type_to == 1) - { - out_elemsize = out_elempack * 4u; - } top_blob.create(w, outh, out_elemsize, out_elempack, opt.blob_vkallocator); if (top_blob.empty()) @@ -778,19 +777,6 @@ int Packing_vulkan::forward(const VkImageMat& bottom_blob, VkMat& top_blob, VkCo if (dims == 3) { int outc = (channels * elempack + out_elempack - 1) / out_elempack; - size_t out_elemsize = elemsize / elempack * out_elempack; - if (opt.use_fp16_packed && !opt.use_fp16_storage) - { - if (out_elempack == 8) out_elemsize = 8*2u; - if (out_elempack == 4) out_elemsize = 4*2u; - if (out_elempack == 1) out_elemsize = 4u; - } - - // type casting override - if (cast_type_to == 1) - { - out_elemsize = out_elempack * 4u; - } top_blob.create(w, h, outc, out_elemsize, out_elempack, opt.blob_vkallocator); if (top_blob.empty()) diff --git a/src/layer/vulkan/priorbox_vulkan.cpp b/src/layer/vulkan/priorbox_vulkan.cpp index 2701b154a..80d6b284f 100644 --- a/src/layer/vulkan/priorbox_vulkan.cpp +++ b/src/layer/vulkan/priorbox_vulkan.cpp @@ -16,6 +16,7 @@ #include #include #include "layer_shader_type.h" +#include "platform.h" namespace ncnn { @@ -31,6 +32,15 @@ PriorBox_vulkan::PriorBox_vulkan() int PriorBox_vulkan::create_pipeline(const Option& opt) { +#if NCNN_VULKAN_ONLINE_SPIRV + if (opt.use_fp16_storage) + { + // TODO investigate why fp16s produce wrong output + support_vulkan = false; + return 0; + } +#endif + const Mat& shape = bottom_shapes.empty() ? Mat() : bottom_shapes[0]; int elempack = 1;