1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4 //
5 // Copyright (C) 2018, Intel Corporation, all rights reserved.
6 // Third party copyrights are property of their respective owners.
7
8 #include "../../precomp.hpp"
9 #include <limits>
10 #include "common.hpp"
11 #include "internal.hpp"
12 #include "../include/op_prior_box.hpp"
13
14 namespace cv { namespace dnn { namespace vkcom {
15
16 #ifdef HAVE_VULKAN
17
18 #define LOCAL_SZ_X 256
19 struct PriorBoxParam {
20 int global_size;
21 int nthreads;
22 float step_x;
23 float step_y;
24 int offsets_x_size;
25 int width_size;
26 int layer_w;
27 int image_h;
28 int image_w;
29 int clip;
30 int variance_off;
31 };
32
OpPriorBox(float step_x,float step_y,bool clip,int num_priors,std::vector<float> & variance,std::vector<float> & offsets_x,std::vector<float> & offsets_y,std::vector<float> & box_widths,std::vector<float> & box_heights)33 OpPriorBox::OpPriorBox(float step_x,
34 float step_y,
35 bool clip,
36 int num_priors,
37 std::vector<float>& variance,
38 std::vector<float>& offsets_x,
39 std::vector<float>& offsets_y,
40 std::vector<float>& box_widths,
41 std::vector<float>& box_heights)
42 {
43 step_x_ = step_x;
44 step_y_ = step_y;
45 clip_ = clip;
46 num_priors_ = num_priors;
47 variance_ = variance;
48 offsets_x_ = offsets_x;
49 offsets_y_ = offsets_y;
50 box_widths_ = box_widths;
51 box_heights_ = box_heights;
52 type_ = "PriorBox";
53 #define BUFFER_NUM 6
54 OpBase::initVulkanThing(BUFFER_NUM);
55 }
56
reshapeOutTensor(std::vector<Tensor * > & ins,Tensor & out)57 void OpPriorBox::reshapeOutTensor(std::vector<Tensor *>& ins, Tensor& out)
58 {
59 assert(!ins.empty());
60
61 Shape in_shape = ins[0]->getShape();
62 int layer_h = in_shape[kShapeIdxHeight];
63 int layer_w = in_shape[kShapeIdxWidth];
64 int out_num = 1;
65 int out_channel = 2;
66 Shape out_shape = {out_num, out_channel, layer_h * layer_w * num_priors_ * 4};
67 out.reshape(NULL, out_shape);
68 }
69
forward(std::vector<Tensor> & ins,std::vector<Tensor> & blobs,std::vector<Tensor> & outs)70 bool OpPriorBox::forward(std::vector<Tensor>& ins,
71 std::vector<Tensor>& blobs,
72 std::vector<Tensor>& outs)
73 {
74 return forward(ins, outs[0]);
75 }
76
forward(std::vector<Tensor> & ins,Tensor & out)77 bool OpPriorBox::forward(std::vector<Tensor>& ins, Tensor& out)
78 {
79 assert(ins.size() == 2);
80 Shape in_shape = ins[0].getShape();
81 Shape img_shape = ins[1].getShape();
82
83 in_h_ = in_shape[kShapeIdxHeight];
84 in_w_ = in_shape[kShapeIdxWidth];
85 img_h_ = img_shape[kShapeIdxHeight];
86 img_w_ = img_shape[kShapeIdxWidth];
87 out_channel_ = out.dimSize(1);
88 out_channel_size_ = out.dimSize(2);
89 nthreads_ = in_h_ * in_w_;
90 global_size_ = alignSize(nthreads_, LOCAL_SZ_X);
91
92 if (pipeline_ == VK_NULL_HANDLE)
93 {
94 createShaderModule(prior_box_spv, sizeof(prior_box_spv));
95 createPipeline(sizeof(PriorBoxParam));
96 computeGroupCount();
97 }
98
99 std::vector<int>shape;
100 shape.push_back(offsets_x_.size());
101 tensor_offsets_x_.reshape((const char*)offsets_x_.data(), shape);
102 tensor_offsets_y_.reshape((const char*)offsets_y_.data(), shape);
103
104 shape[0] = box_widths_.size();
105 tensor_widths_.reshape((const char*)box_widths_.data(), shape);
106 tensor_heights_.reshape((const char*)box_heights_.data(), shape);
107
108 float variance[4] = {variance_[0], variance_[0], variance_[0], variance_[0]};
109 if (variance_.size() > 1)
110 {
111 assert(variance_.size() == 4);
112 for (int i = 1; i < variance_.size(); i++)
113 variance[i] = variance_[i];
114 }
115 shape[0] = 4;
116 tensor_variance_.reshape((const char*)variance, shape);
117
118 bindTensor(device_, tensor_offsets_x_, 0, descriptor_set_);
119 bindTensor(device_, tensor_offsets_y_, 1, descriptor_set_);
120 bindTensor(device_, tensor_widths_, 2, descriptor_set_);
121 bindTensor(device_, tensor_heights_, 3, descriptor_set_);
122 bindTensor(device_, tensor_variance_, 4, descriptor_set_);
123 bindTensor(device_, out, 5, descriptor_set_);
124
125 PriorBoxParam param = {global_size_,
126 nthreads_,
127 step_x_,
128 step_y_,
129 (int)offsets_x_.size(),
130 (int)box_widths_.size(),
131 in_w_,
132 img_h_,
133 img_w_,
134 clip_ ? 1 : 0,
135 out_channel_size_ / 4};
136 recordCommandBuffer((void *)¶m, sizeof(PriorBoxParam));
137 runCommandBuffer();
138 return true;
139 }
140
computeGroupCount()141 bool OpPriorBox::computeGroupCount()
142 {
143 group_x_ = global_size_ / LOCAL_SZ_X;
144 group_y_ = 1;
145 group_z_ = 1;
146 return true;
147 }
148
149 #endif // HAVE_VULKAN
150
151 }}} // namespace cv::dnn::vkcom
152