From 9e2b327c17811e883af2f0de0215fae3fa7e0e45 Mon Sep 17 00:00:00 2001 From: nihui Date: Sat, 2 Feb 2019 22:17:42 +0800 Subject: [PATCH] packing shader for 3-dim blob --- src/layer/packing.cpp | 106 +++++++++++++++++++++++++++++ src/layer/packing.h | 12 ++++ src/layer/shader/packing_1to4.comp | 63 +++++++++++++++++ src/layer/shader/packing_4to1.comp | 58 ++++++++++++++++ 4 files changed, 239 insertions(+) create mode 100644 src/layer/shader/packing_1to4.comp create mode 100644 src/layer/shader/packing_4to1.comp diff --git a/src/layer/packing.cpp b/src/layer/packing.cpp index 0ca63f8a0..c48292173 100644 --- a/src/layer/packing.cpp +++ b/src/layer/packing.cpp @@ -23,6 +23,11 @@ Packing::Packing() one_blob_only = true; support_inplace = false; support_vulkan = false; + +#if NCNN_VULKAN + pipeline_packing_1to4 = 0; + pipeline_packing_4to1 = 0; +#endif // NCNN_VULKAN } int Packing::load_param(const ParamDict& pd) @@ -147,4 +152,105 @@ int Packing::forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt) c return 0; } +#if NCNN_VULKAN +int Packing::create_pipeline() +{ + std::vector specializations; + + pipeline_packing_1to4 = new Pipeline(vkdev); + pipeline_packing_1to4->set_optimal_local_size_xyz(); + pipeline_packing_1to4->create("packing_1to4", specializations, 2, 10); + + pipeline_packing_4to1 = new Pipeline(vkdev); + pipeline_packing_4to1->set_optimal_local_size_xyz(); + pipeline_packing_4to1->create("packing_4to1", specializations, 2, 10); + + return 0; +} + +int Packing::destroy_pipeline() +{ + delete pipeline_packing_1to4; + pipeline_packing_1to4 = 0; + + delete pipeline_packing_4to1; + pipeline_packing_4to1 = 0; + + return 0; +} + +int Packing::forward(const VkMat& bottom_blob, VkMat& top_blob, VkCompute& cmd, const Option& opt) const +{ + int packing = bottom_blob.packing; + + if (packing == out_packing) + { + top_blob = bottom_blob; + return 0; + } + + int w = bottom_blob.w; + int h = bottom_blob.h; + int channels = bottom_blob.c; + int dims = bottom_blob.dims; + size_t elemsize = bottom_blob.elemsize; + + if (dims == 1) + { + // TODO + return -1; + } + + if (dims == 2) + { + // TODO + return -1; + } + + if (dims == 3) + { + int outc = (channels * packing + out_packing - 1) / out_packing; + size_t out_elemsize = elemsize / packing * out_packing; + + top_blob.create(w, h, outc, out_elemsize, out_packing, opt.blob_vkallocator, opt.staging_vkallocator); + if (top_blob.empty()) + return -100; + } + +// fprintf(stderr, "Packing::forward %p %p\n", bottom_blob.buffer(), top_blob.buffer()); + + std::vector bindings(2); + bindings[0] = bottom_blob; + bindings[1] = top_blob; + + std::vector constants(10); + constants[0].i = bottom_blob.dims; + constants[1].i = bottom_blob.w; + constants[2].i = bottom_blob.h; + constants[3].i = bottom_blob.c; + constants[4].i = bottom_blob.cstep; + constants[5].i = top_blob.dims; + constants[6].i = top_blob.w; + constants[7].i = top_blob.h; + constants[8].i = top_blob.c; + constants[9].i = top_blob.cstep; + + // record + cmd.record_prepare_compute_barrier(bottom_blob); + cmd.record_prepare_compute_barrier(top_blob); + + if (packing == 1 && out_packing == 4) + { + cmd.record_pipeline(pipeline_packing_1to4, bindings, constants, top_blob); + } + + if (packing == 4 && out_packing == 1) + { + cmd.record_pipeline(pipeline_packing_4to1, bindings, constants, bottom_blob); + } + + return 0; +} +#endif // NCNN_VULKAN + } // namespace ncnn diff --git a/src/layer/packing.h b/src/layer/packing.h index 0ece599b9..aa67decf6 100644 --- a/src/layer/packing.h +++ b/src/layer/packing.h @@ -28,8 +28,20 @@ public: virtual int forward(const Mat& bottom_blob, Mat& top_blob, const Option& opt) const; +#if NCNN_VULKAN + virtual int create_pipeline(); + virtual int destroy_pipeline(); + + virtual int forward(const VkMat& bottom_blob, VkMat& top_blob, VkCompute& cmd, const Option& opt) const; +#endif // NCNN_VULKAN + private: int out_packing; + +#if NCNN_VULKAN + Pipeline* pipeline_packing_1to4; + Pipeline* pipeline_packing_4to1; +#endif // NCNN_VULKAN }; } // namespace ncnn diff --git a/src/layer/shader/packing_1to4.comp b/src/layer/shader/packing_1to4.comp new file mode 100644 index 000000000..0f756e891 --- /dev/null +++ b/src/layer/shader/packing_1to4.comp @@ -0,0 +1,63 @@ +// Tencent is pleased to support the open source community by making ncnn available. +// +// Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#version 450 + +layout (local_size_x_id = 233) in; +layout (local_size_y_id = 234) in; +layout (local_size_z_id = 235) in; + +layout (binding = 0) readonly buffer bottom_blob { float bottom_blob_data[]; }; +layout (binding = 1) writeonly buffer top_blob { vec4 top_blob_data[]; }; + +layout (push_constant) uniform parameter +{ + int dims; + int w; + int h; + int c; + int cstep; + + int outdims; + int outw; + int outh; + int outc; + int outcstep; +} p; + +void main() +{ + int gx = int(gl_GlobalInvocationID.x); + int gy = int(gl_GlobalInvocationID.y); + int gz = int(gl_GlobalInvocationID.z); + + if (gx >= p.outw || gy >= p.outh || gz >= p.outc) + return; + + ivec4 z4 = ivec4(gz * 4) + ivec4(0, 1, 2, 3); + + // prevent out of range access + z4 = min(z4, p.c - 1); + + ivec4 v_offset = z4 * p.cstep + ivec4(gy * p.w + gx); + + vec4 v; + + v.r = bottom_blob_data[v_offset.r]; + v.g = bottom_blob_data[v_offset.g]; + v.b = bottom_blob_data[v_offset.b]; + v.a = bottom_blob_data[v_offset.a]; + + top_blob_data[gz * p.outcstep + gy * p.outw + gx] = v; +} diff --git a/src/layer/shader/packing_4to1.comp b/src/layer/shader/packing_4to1.comp new file mode 100644 index 000000000..b7968a945 --- /dev/null +++ b/src/layer/shader/packing_4to1.comp @@ -0,0 +1,58 @@ +// Tencent is pleased to support the open source community by making ncnn available. +// +// Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. +// +// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// https://opensource.org/licenses/BSD-3-Clause +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#version 450 + +layout (local_size_x_id = 233) in; +layout (local_size_y_id = 234) in; +layout (local_size_z_id = 235) in; + +layout (binding = 0) readonly buffer bottom_blob { vec4 bottom_blob_data[]; }; +layout (binding = 1) writeonly buffer top_blob { float top_blob_data[]; }; + +layout (push_constant) uniform parameter +{ + int dims; + int w; + int h; + int c; + int cstep; + + int outdims; + int outw; + int outh; + int outc; + int outcstep; +} p; + +void main() +{ + int gx = int(gl_GlobalInvocationID.x); + int gy = int(gl_GlobalInvocationID.y); + int gz = int(gl_GlobalInvocationID.z); + + if (gx >= p.w || gy >= p.h || gz >= p.c) + return; + + ivec4 z4 = ivec4(gz * 4) + ivec4(0, 1, 2, 3); + + ivec4 v_offset = z4 * p.cstep + ivec4(gy * p.w + gx); + + vec4 v = bottom_blob_data[gz * p.outcstep + gy * p.outw + gx]; + + top_blob_data[v_offset.r] = v.r; + top_blob_data[v_offset.g] = v.g; + top_blob_data[v_offset.b] = v.b; + top_blob_data[v_offset.a] = v.a; +}