From e243edf991e9c696e1d2161e4420eb82da33eb2b Mon Sep 17 00:00:00 2001 From: nihui Date: Mon, 11 Jan 2021 21:56:03 +0800 Subject: [PATCH] interp align_corner vulkan implementation --- src/layer/vulkan/interp_vulkan.cpp | 40 ++++++++++++++--------- src/layer/vulkan/shader/interp.comp | 13 ++++++-- src/layer/vulkan/shader/interp_pack4.comp | 13 ++++++-- src/layer/vulkan/shader/interp_pack8.comp | 13 ++++++-- 4 files changed, 57 insertions(+), 22 deletions(-) diff --git a/src/layer/vulkan/interp_vulkan.cpp b/src/layer/vulkan/interp_vulkan.cpp index a5cd6080f..52e27b656 100644 --- a/src/layer/vulkan/interp_vulkan.cpp +++ b/src/layer/vulkan/interp_vulkan.cpp @@ -87,18 +87,19 @@ int Interp_vulkan::create_pipeline(const Option& _opt) if (resize_type == 1 || resize_type == 2) { - std::vector specializations(1 + 10); + std::vector specializations(2 + 10); specializations[0].i = resize_type; - specializations[1 + 0].i = shape_packed.dims; - specializations[1 + 1].i = shape_packed.w; - specializations[1 + 2].i = shape_packed.h; - specializations[1 + 3].i = shape_packed.c; - specializations[1 + 4].i = shape_packed.cstep; - specializations[1 + 5].i = out_shape_packed.dims; - specializations[1 + 6].i = out_shape_packed.w; - specializations[1 + 7].i = out_shape_packed.h; - specializations[1 + 8].i = out_shape_packed.c; - specializations[1 + 9].i = out_shape_packed.cstep; + specializations[1].i = align_corner; + specializations[2 + 0].i = shape_packed.dims; + specializations[2 + 1].i = shape_packed.w; + specializations[2 + 2].i = shape_packed.h; + specializations[2 + 3].i = shape_packed.c; + specializations[2 + 4].i = shape_packed.cstep; + specializations[2 + 5].i = out_shape_packed.dims; + specializations[2 + 6].i = out_shape_packed.w; + specializations[2 + 7].i = out_shape_packed.h; + specializations[2 + 8].i = out_shape_packed.c; + specializations[2 + 9].i = out_shape_packed.cstep; Mat local_size_xyz; if (out_shape_packed.dims == 2) @@ -227,11 +228,6 @@ int Interp_vulkan::create_pipeline(const Option& _opt) } } - // todo support align_corner in vulkan implementation - if (align_corner) - { - support_vulkan = false; - } return 0; } @@ -412,6 +408,12 @@ int Interp_vulkan::forward(const std::vector& bottom_blobs, std::vector& bottom_blobs, std::vec constants[10].f = w / (float)outw; constants[11].f = h / (float)outh; + if (resize_type == 2 && align_corner) + { + constants[10].f = (w - 1) / (float)(outw - 1); + constants[11].f = (h - 1) / (float)(outh - 1); + } + const Pipeline* pipeline = elempack == 8 ? pipeline_interp_pack8 : elempack == 4 ? pipeline_interp_pack4 : pipeline_interp; diff --git a/src/layer/vulkan/shader/interp.comp b/src/layer/vulkan/shader/interp.comp index 72ae76b0b..acf954c47 100644 --- a/src/layer/vulkan/shader/interp.comp +++ b/src/layer/vulkan/shader/interp.comp @@ -22,8 +22,9 @@ #endif layout (constant_id = 0) const int resize_type = 0; +layout (constant_id = 1) const int align_corner = 0; -#define shape_constant_id_offset 1 +#define shape_constant_id_offset 2 layout (constant_id = shape_constant_id_offset + 0) const int dims = 0; layout (constant_id = shape_constant_id_offset + 1) const int w = 0; layout (constant_id = shape_constant_id_offset + 2) const int h = 0; @@ -106,7 +107,15 @@ void main() if (resize_type == 2) // bilinear { afpvec2 gxy = afpvec2(gx, gy); - afpvec2 fxy = (gxy + afp(0.5f)) * afpvec2(p.scale_x, p.scale_y) - afp(0.5f); + afpvec2 fxy; + if (align_corner == 1) + { + fxy = gxy * afpvec2(p.scale_x, p.scale_y); + } + else + { + fxy = (gxy + afp(0.5f)) * afpvec2(p.scale_x, p.scale_y) - afp(0.5f); + } ivec2 sxy = ivec2(floor(fxy)); diff --git a/src/layer/vulkan/shader/interp_pack4.comp b/src/layer/vulkan/shader/interp_pack4.comp index 7a5a3e24b..422263ea3 100644 --- a/src/layer/vulkan/shader/interp_pack4.comp +++ b/src/layer/vulkan/shader/interp_pack4.comp @@ -22,8 +22,9 @@ #endif layout (constant_id = 0) const int resize_type = 0; +layout (constant_id = 1) const int align_corner = 0; -#define shape_constant_id_offset 1 +#define shape_constant_id_offset 2 layout (constant_id = shape_constant_id_offset + 0) const int dims = 0; layout (constant_id = shape_constant_id_offset + 1) const int w = 0; layout (constant_id = shape_constant_id_offset + 2) const int h = 0; @@ -106,7 +107,15 @@ void main() if (resize_type == 2) // bilinear { afpvec2 gxy = afpvec2(gx, gy); - afpvec2 fxy = (gxy + afp(0.5f)) * afpvec2(p.scale_x, p.scale_y) - afp(0.5f); + afpvec2 fxy; + if (align_corner == 1) + { + fxy = gxy * afpvec2(p.scale_x, p.scale_y); + } + else + { + fxy = (gxy + afp(0.5f)) * afpvec2(p.scale_x, p.scale_y) - afp(0.5f); + } ivec2 sxy = ivec2(floor(fxy)); diff --git a/src/layer/vulkan/shader/interp_pack8.comp b/src/layer/vulkan/shader/interp_pack8.comp index 03a8d7ee3..cc6b3b23b 100644 --- a/src/layer/vulkan/shader/interp_pack8.comp +++ b/src/layer/vulkan/shader/interp_pack8.comp @@ -23,8 +23,9 @@ struct sfpvec8 { f16vec4 abcd; f16vec4 efgh; }; #endif layout (constant_id = 0) const int resize_type = 0; +layout (constant_id = 1) const int align_corner = 0; -#define shape_constant_id_offset 1 +#define shape_constant_id_offset 2 layout (constant_id = shape_constant_id_offset + 0) const int dims = 0; layout (constant_id = shape_constant_id_offset + 1) const int w = 0; layout (constant_id = shape_constant_id_offset + 2) const int h = 0; @@ -107,7 +108,15 @@ void main() if (resize_type == 2) // bilinear { afpvec2 gxy = afpvec2(gx, gy); - afpvec2 fxy = (gxy + afp(0.5f)) * afpvec2(p.scale_x, p.scale_y) - afp(0.5f); + afpvec2 fxy; + if (align_corner == 1) + { + fxy = gxy * afpvec2(p.scale_x, p.scale_y); + } + else + { + fxy = (gxy + afp(0.5f)) * afpvec2(p.scale_x, p.scale_y) - afp(0.5f); + } ivec2 sxy = ivec2(floor(fxy));