ncnn

Форк
0
/
interp_vulkan.cpp 
897 строк · 30.6 Кб
1
// Tencent is pleased to support the open source community by making ncnn available.
2
//
3
// Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
4
//
5
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
6
// in compliance with the License. You may obtain a copy of the License at
7
//
8
// https://opensource.org/licenses/BSD-3-Clause
9
//
10
// Unless required by applicable law or agreed to in writing, software distributed
11
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
13
// specific language governing permissions and limitations under the License.
14

15
#include "interp_vulkan.h"
16

17
#include "layer_shader_type.h"
18

19
namespace ncnn {
20

21
Interp_vulkan::Interp_vulkan()
22
{
23
    support_vulkan = true;
24
    support_image_storage = true;
25

26
    pipeline_interp = 0;
27
    pipeline_interp_pack4 = 0;
28
    pipeline_interp_pack8 = 0;
29

30
    pipeline_interp_bicubic_coeffs_x = 0;
31
    pipeline_interp_bicubic_coeffs_y = 0;
32
    pipeline_interp_bicubic = 0;
33
    pipeline_interp_bicubic_pack4 = 0;
34
    pipeline_interp_bicubic_pack8 = 0;
35
}
36

37
int Interp_vulkan::create_pipeline(const Option& _opt)
38
{
39
    Option opt = _opt;
40
    const Mat& shape = bottom_shapes.empty() ? Mat() : bottom_shapes[0];
41
    const Mat& out_shape = top_shapes.empty() ? Mat() : top_shapes[0];
42

43
    int elempack = 1;
44
    if (shape.dims == 1) elempack = opt.use_shader_pack8 && shape.w % 8 == 0 ? 8 : shape.w % 4 == 0 ? 4 : 1;
45
    if (shape.dims == 2) elempack = opt.use_shader_pack8 && shape.h % 8 == 0 ? 8 : shape.h % 4 == 0 ? 4 : 1;
46
    if (shape.dims == 3) elempack = opt.use_shader_pack8 && shape.c % 8 == 0 ? 8 : shape.c % 4 == 0 ? 4 : 1;
47

48
    int out_elempack = 1;
49
    if (out_shape.dims == 1) out_elempack = opt.use_shader_pack8 && out_shape.w % 8 == 0 ? 8 : out_shape.w % 4 == 0 ? 4 : 1;
50
    if (out_shape.dims == 2) out_elempack = opt.use_shader_pack8 && out_shape.h % 8 == 0 ? 8 : out_shape.h % 4 == 0 ? 4 : 1;
51
    if (out_shape.dims == 3) out_elempack = opt.use_shader_pack8 && out_shape.c % 8 == 0 ? 8 : out_shape.c % 4 == 0 ? 4 : 1;
52

53
    size_t elemsize;
54
    size_t out_elemsize;
55
    if (opt.use_fp16_storage)
56
    {
57
        elemsize = elempack * 2u;
58
        out_elemsize = out_elempack * 2u;
59
    }
60
    else if (opt.use_fp16_packed)
61
    {
62
        elemsize = elempack == 1 ? 4u : elempack * 2u;
63
        out_elemsize = out_elempack == 1 ? 4u : out_elempack * 2u;
64
    }
65
    else
66
    {
67
        elemsize = elempack * 4u;
68
        out_elemsize = out_elempack * 4u;
69
    }
70

71
    Mat shape_packed;
72
    if (shape.dims == 1) shape_packed = Mat(shape.w / elempack, (void*)0, elemsize, elempack);
73
    if (shape.dims == 2) shape_packed = Mat(shape.w, shape.h / elempack, (void*)0, elemsize, elempack);
74
    if (shape.dims == 3) shape_packed = Mat(shape.w, shape.h, shape.c / elempack, (void*)0, elemsize, elempack);
75

76
    Mat out_shape_packed;
77
    if (out_shape.dims == 1) out_shape_packed = Mat(out_shape.w / out_elempack, (void*)0, out_elemsize, out_elempack);
78
    if (out_shape.dims == 2) out_shape_packed = Mat(out_shape.w, out_shape.h / out_elempack, (void*)0, out_elemsize, out_elempack);
79
    if (out_shape.dims == 3) out_shape_packed = Mat(out_shape.w, out_shape.h, out_shape.c / out_elempack, (void*)0, out_elemsize, out_elempack);
80

81
    // check blob shape
82
    if (!vkdev->shape_support_image_storage(shape_packed) || !vkdev->shape_support_image_storage(out_shape_packed))
83
    {
84
        support_image_storage = false;
85
        opt.use_image_storage = false;
86
    }
87

88
    if (resize_type == 1 || resize_type == 2)
89
    {
90
        std::vector<vk_specialization_type> specializations(2 + 10);
91
        specializations[0].i = resize_type;
92
        specializations[1].i = align_corner;
93
        specializations[2 + 0].i = shape_packed.dims;
94
        specializations[2 + 1].i = shape_packed.w;
95
        specializations[2 + 2].i = shape_packed.h;
96
        specializations[2 + 3].i = shape_packed.c;
97
        specializations[2 + 4].i = shape_packed.cstep;
98
        specializations[2 + 5].i = out_shape_packed.dims;
99
        specializations[2 + 6].i = out_shape_packed.w;
100
        specializations[2 + 7].i = out_shape_packed.h;
101
        specializations[2 + 8].i = out_shape_packed.c;
102
        specializations[2 + 9].i = out_shape_packed.cstep;
103

104
        Mat local_size_xyz;
105
        if (out_shape_packed.dims == 2)
106
        {
107
            local_size_xyz.w = std::min(8, out_shape_packed.w);
108
            local_size_xyz.h = std::min(8, out_shape_packed.h);
109
            local_size_xyz.c = 1;
110
        }
111
        if (out_shape_packed.dims == 3)
112
        {
113
            local_size_xyz.w = std::min(4, out_shape_packed.w);
114
            local_size_xyz.h = std::min(4, out_shape_packed.h);
115
            local_size_xyz.c = std::min(4, out_shape_packed.c);
116
        }
117

118
        // pack1
119
        if (shape.dims == 0 || elempack == 1)
120
        {
121
            pipeline_interp = new Pipeline(vkdev);
122
            pipeline_interp->set_optimal_local_size_xyz(local_size_xyz);
123
            pipeline_interp->create(LayerShaderType::interp, opt, specializations);
124
        }
125

126
        // pack4
127
        if (shape.dims == 0 || elempack == 4)
128
        {
129
            pipeline_interp_pack4 = new Pipeline(vkdev);
130
            pipeline_interp_pack4->set_optimal_local_size_xyz(local_size_xyz);
131
            pipeline_interp_pack4->create(LayerShaderType::interp_pack4, opt, specializations);
132
        }
133

134
        // pack8
135
        if ((opt.use_shader_pack8 && shape.dims == 0) || elempack == 8)
136
        {
137
            pipeline_interp_pack8 = new Pipeline(vkdev);
138
            pipeline_interp_pack8->set_optimal_local_size_xyz(local_size_xyz);
139
            pipeline_interp_pack8->create(LayerShaderType::interp_pack8, opt, specializations);
140
        }
141
    }
142

143
    if (resize_type == 3)
144
    {
145
        {
146
            std::vector<vk_specialization_type> specializations(1 + 2);
147
            specializations[0].i = align_corner;
148
            specializations[1 + 0].i = shape_packed.w;
149
            specializations[1 + 1].i = out_shape_packed.w;
150

151
            Mat local_size_xyz(64, 1, 1, (void*)0);
152
            if (out_shape_packed.dims != 0)
153
            {
154
                local_size_xyz.w = std::min(64, out_shape_packed.w);
155
                local_size_xyz.h = 1;
156
                local_size_xyz.c = 1;
157
            }
158

159
            pipeline_interp_bicubic_coeffs_x = new Pipeline(vkdev);
160
            pipeline_interp_bicubic_coeffs_x->set_optimal_local_size_xyz(local_size_xyz);
161
            pipeline_interp_bicubic_coeffs_x->create(LayerShaderType::interp_bicubic_coeffs, opt, specializations);
162
        }
163
        {
164
            std::vector<vk_specialization_type> specializations(1 + 2);
165
            specializations[0].i = align_corner;
166
            specializations[1 + 0].i = shape_packed.h;
167
            specializations[1 + 1].i = out_shape_packed.h;
168

169
            Mat local_size_xyz(64, 1, 1, (void*)0);
170
            if (out_shape_packed.dims != 0)
171
            {
172
                local_size_xyz.w = std::min(64, out_shape_packed.h);
173
                local_size_xyz.h = 1;
174
                local_size_xyz.c = 1;
175
            }
176

177
            pipeline_interp_bicubic_coeffs_y = new Pipeline(vkdev);
178
            pipeline_interp_bicubic_coeffs_y->set_optimal_local_size_xyz(local_size_xyz);
179
            pipeline_interp_bicubic_coeffs_y->create(LayerShaderType::interp_bicubic_coeffs, opt, specializations);
180
        }
181

182
        std::vector<vk_specialization_type> specializations(0 + 10);
183
        specializations[0 + 0].i = shape_packed.dims;
184
        specializations[0 + 1].i = shape_packed.w;
185
        specializations[0 + 2].i = shape_packed.h;
186
        specializations[0 + 3].i = shape_packed.c;
187
        specializations[0 + 4].i = shape_packed.cstep;
188
        specializations[0 + 5].i = out_shape_packed.dims;
189
        specializations[0 + 6].i = out_shape_packed.w;
190
        specializations[0 + 7].i = out_shape_packed.h;
191
        specializations[0 + 8].i = out_shape_packed.c;
192
        specializations[0 + 9].i = out_shape_packed.cstep;
193

194
        Mat local_size_xyz;
195
        if (out_shape_packed.dims == 2)
196
        {
197
            local_size_xyz.w = std::min(8, out_shape_packed.w);
198
            local_size_xyz.h = std::min(8, out_shape_packed.h);
199
            local_size_xyz.c = 1;
200
        }
201
        if (out_shape_packed.dims == 3)
202
        {
203
            local_size_xyz.w = std::min(4, out_shape_packed.w);
204
            local_size_xyz.h = std::min(4, out_shape_packed.h);
205
            local_size_xyz.c = std::min(4, out_shape_packed.c);
206
        }
207

208
        // pack1
209
        if (shape.dims == 0 || elempack == 1)
210
        {
211
            pipeline_interp_bicubic = new Pipeline(vkdev);
212
            pipeline_interp_bicubic->set_optimal_local_size_xyz(local_size_xyz);
213
            pipeline_interp_bicubic->create(LayerShaderType::interp_bicubic, opt, specializations);
214
        }
215

216
        // pack4
217
        if (shape.dims == 0 || elempack == 4)
218
        {
219
            pipeline_interp_bicubic_pack4 = new Pipeline(vkdev);
220
            pipeline_interp_bicubic_pack4->set_optimal_local_size_xyz(local_size_xyz);
221
            pipeline_interp_bicubic_pack4->create(LayerShaderType::interp_bicubic_pack4, opt, specializations);
222
        }
223

224
        // pack8
225
        if ((opt.use_shader_pack8 && shape.dims == 0) || elempack == 8)
226
        {
227
            pipeline_interp_bicubic_pack8 = new Pipeline(vkdev);
228
            pipeline_interp_bicubic_pack8->set_optimal_local_size_xyz(local_size_xyz);
229
            pipeline_interp_bicubic_pack8->create(LayerShaderType::interp_bicubic_pack8, opt, specializations);
230
        }
231
    }
232

233
    return 0;
234
}
235

236
int Interp_vulkan::destroy_pipeline(const Option& /*opt*/)
237
{
238
    delete pipeline_interp;
239
    pipeline_interp = 0;
240

241
    delete pipeline_interp_pack4;
242
    pipeline_interp_pack4 = 0;
243

244
    delete pipeline_interp_pack8;
245
    pipeline_interp_pack8 = 0;
246

247
    delete pipeline_interp_bicubic_coeffs_x;
248
    pipeline_interp_bicubic_coeffs_x = 0;
249

250
    delete pipeline_interp_bicubic_coeffs_y;
251
    pipeline_interp_bicubic_coeffs_y = 0;
252

253
    delete pipeline_interp_bicubic;
254
    pipeline_interp_bicubic = 0;
255

256
    delete pipeline_interp_bicubic_pack4;
257
    pipeline_interp_bicubic_pack4 = 0;
258

259
    delete pipeline_interp_bicubic_pack8;
260
    pipeline_interp_bicubic_pack8 = 0;
261

262
    return 0;
263
}
264

265
int Interp_vulkan::forward(const VkMat& bottom_blob, VkMat& top_blob, VkCompute& cmd, const Option& opt) const
266
{
267
    int w = bottom_blob.w;
268
    int h = bottom_blob.h;
269

270
    int outw = output_width;
271
    int outh = output_height;
272
    if (bottom_blob.dims == 1)
273
    {
274
        w = 1;
275
        h = 1;
276
    }
277
    if (outw == 0 || outh == 0)
278
    {
279
        outw = static_cast<int>(w * width_scale);
280
        outh = static_cast<int>(h * height_scale);
281
    }
282

283
    VkMat reference_blob;
284
    reference_blob.w = outw;
285
    reference_blob.h = outh;
286

287
    std::vector<VkMat> bottom_blobs(2);
288
    bottom_blobs[0] = bottom_blob;
289
    bottom_blobs[1] = reference_blob;
290

291
    std::vector<VkMat> top_blobs(1);
292

293
    int ret = forward(bottom_blobs, top_blobs, cmd, opt);
294

295
    top_blob = top_blobs[0];
296

297
    return ret;
298
}
299

300
int Interp_vulkan::forward(const VkImageMat& bottom_blob, VkImageMat& top_blob, VkCompute& cmd, const Option& opt) const
301
{
302
    int w = bottom_blob.w;
303
    int h = bottom_blob.h;
304

305
    int outw = output_width;
306
    int outh = output_height;
307
    if (bottom_blob.dims == 1)
308
    {
309
        w = 1;
310
        h = 1;
311
    }
312
    if (outw == 0 || outh == 0)
313
    {
314
        outw = static_cast<int>(w * width_scale);
315
        outh = static_cast<int>(h * height_scale);
316
    }
317

318
    VkImageMat reference_blob;
319
    reference_blob.w = outw;
320
    reference_blob.h = outh;
321

322
    std::vector<VkImageMat> bottom_blobs(2);
323
    bottom_blobs[0] = bottom_blob;
324
    bottom_blobs[1] = reference_blob;
325

326
    std::vector<VkImageMat> top_blobs(1);
327

328
    int ret = forward(bottom_blobs, top_blobs, cmd, opt);
329

330
    top_blob = top_blobs[0];
331

332
    return ret;
333
}
334

335
int Interp_vulkan::forward(const std::vector<VkMat>& bottom_blobs, std::vector<VkMat>& top_blobs, VkCompute& cmd, const Option& opt) const
336
{
337
    const VkMat& bottom_blob = bottom_blobs[0];
338
    const VkMat& reference_blob = bottom_blobs[1];
339
    VkMat& top_blob = top_blobs[0];
340

341
    int w = bottom_blob.w;
342
    int h = bottom_blob.h;
343
    int channels = bottom_blob.c;
344
    int dims = bottom_blob.dims;
345
    size_t elemsize = bottom_blob.elemsize;
346
    int elempack = bottom_blob.elempack;
347

348
    int outw = reference_blob.w;
349
    int outh = reference_blob.h;
350

351
    if (dims == 1)
352
    {
353
        top_blob.create(outw, outh, w, elemsize, elempack, opt.blob_vkallocator);
354
        if (top_blob.empty())
355
            return -100;
356

357
        std::vector<VkMat> bindings(2);
358
        bindings[0] = bottom_blob;
359
        bindings[1] = top_blob;
360

361
        std::vector<vk_constant_type> constants(12);
362
        constants[0].i = bottom_blob.dims;
363
        constants[1].i = bottom_blob.w;
364
        constants[2].i = bottom_blob.h;
365
        constants[3].i = bottom_blob.c;
366
        constants[4].i = bottom_blob.cstep;
367
        constants[5].i = top_blob.dims;
368
        constants[6].i = top_blob.w;
369
        constants[7].i = top_blob.h;
370
        constants[8].i = top_blob.c;
371
        constants[9].i = top_blob.cstep;
372
        constants[10].f = (resize_type == 2 || output_width) ? w / (float)outw : 1.f / width_scale;
373
        constants[11].f = (resize_type == 2 || output_height) ? h / (float)outh : 1.f / height_scale;
374

375
        const Pipeline* pipeline = elempack == 8 ? pipeline_interp_pack8
376
                                   : elempack == 4 ? pipeline_interp_pack4
377
                                   : pipeline_interp;
378

379
        cmd.record_pipeline(pipeline, bindings, constants, top_blob);
380

381
        return 0;
382
    }
383

384
    if (dims == 2)
385
    {
386
        if (outw == w)
387
        {
388
            top_blob = bottom_blob;
389
            return 0;
390
        }
391

392
        top_blob.create(outw, h, elemsize, elempack, opt.blob_vkallocator);
393
        if (top_blob.empty())
394
            return -100;
395

396
        if (resize_type == 1 || resize_type == 2) // nearest or bilinear
397
        {
398
            std::vector<VkMat> bindings(2);
399
            bindings[0] = bottom_blob;
400
            bindings[1] = top_blob;
401

402
            std::vector<vk_constant_type> constants(12);
403
            constants[0].i = bottom_blob.dims;
404
            constants[1].i = bottom_blob.w;
405
            constants[2].i = bottom_blob.h;
406
            constants[3].i = bottom_blob.c;
407
            constants[4].i = bottom_blob.cstep;
408
            constants[5].i = top_blob.dims;
409
            constants[6].i = top_blob.w;
410
            constants[7].i = top_blob.h;
411
            constants[8].i = top_blob.c;
412
            constants[9].i = top_blob.cstep;
413
            constants[10].f = (resize_type == 2 || output_width) ? w / (float)outw : 1.f / width_scale;
414
            constants[11].f = 1.f;
415

416
            if (resize_type == 2 && align_corner)
417
            {
418
                constants[10].f = (w - 1) / (float)(outw - 1);
419
            }
420

421
            const Pipeline* pipeline = elempack == 8 ? pipeline_interp_pack8
422
                                       : elempack == 4 ? pipeline_interp_pack4
423
                                       : pipeline_interp;
424

425
            cmd.record_pipeline(pipeline, bindings, constants, top_blob);
426
        }
427

428
        if (resize_type == 3) // bicubic
429
        {
430
            VkMat alpha(outw, (size_t)(elemsize / elempack * 4), 4, opt.workspace_vkallocator);
431
            if (alpha.empty())
432
                return -100;
433

434
            VkMat xofs(outw, (size_t)4u, 1, opt.workspace_vkallocator);
435
            if (xofs.empty())
436
                return -100;
437

438
            {
439
                std::vector<VkMat> bindings(2);
440
                bindings[0] = alpha;
441
                bindings[1] = xofs;
442

443
                std::vector<vk_constant_type> constants(3);
444
                constants[0].i = bottom_blob.w;
445
                constants[1].i = outw;
446
                constants[2].f = (float)bottom_blob.w / outw;
447

448
                if (align_corner)
449
                {
450
                    constants[2].f = (w - 1) / (float)(outw - 1);
451
                }
452

453
                // record
454
                cmd.record_pipeline(pipeline_interp_bicubic_coeffs_x, bindings, constants, alpha);
455
            }
456

457
            std::vector<VkMat> bindings(6);
458
            bindings[0] = bottom_blob;
459
            bindings[1] = top_blob;
460
            bindings[2] = alpha;
461
            bindings[3] = xofs;
462
            bindings[4] = alpha; // dummy
463
            bindings[5] = xofs;  // dummy
464

465
            std::vector<vk_constant_type> constants(10);
466
            constants[0].i = bottom_blob.dims;
467
            constants[1].i = bottom_blob.w;
468
            constants[2].i = bottom_blob.h;
469
            constants[3].i = bottom_blob.c;
470
            constants[4].i = bottom_blob.cstep;
471
            constants[5].i = top_blob.dims;
472
            constants[6].i = top_blob.w;
473
            constants[7].i = top_blob.h;
474
            constants[8].i = top_blob.c;
475
            constants[9].i = top_blob.cstep;
476

477
            const Pipeline* pipeline = elempack == 8 ? pipeline_interp_bicubic_pack8
478
                                       : elempack == 4 ? pipeline_interp_bicubic_pack4
479
                                       : pipeline_interp_bicubic;
480

481
            cmd.record_pipeline(pipeline, bindings, constants, top_blob);
482
        }
483

484
        return 0;
485
    }
486

487
    if (outw == w && outh == h)
488
    {
489
        top_blob = bottom_blob;
490
        return 0;
491
    }
492

493
    top_blob.create(outw, outh, channels, elemsize, elempack, opt.blob_vkallocator);
494
    if (top_blob.empty())
495
        return -100;
496

497
    if (resize_type == 1 || resize_type == 2) // nearest or bilinear
498
    {
499
        std::vector<VkMat> bindings(2);
500
        bindings[0] = bottom_blob;
501
        bindings[1] = top_blob;
502

503
        std::vector<vk_constant_type> constants(12);
504
        constants[0].i = bottom_blob.dims;
505
        constants[1].i = bottom_blob.w;
506
        constants[2].i = bottom_blob.h;
507
        constants[3].i = bottom_blob.c;
508
        constants[4].i = bottom_blob.cstep;
509
        constants[5].i = top_blob.dims;
510
        constants[6].i = top_blob.w;
511
        constants[7].i = top_blob.h;
512
        constants[8].i = top_blob.c;
513
        constants[9].i = top_blob.cstep;
514
        constants[10].f = (resize_type == 2 || output_width) ? w / (float)outw : 1.f / width_scale;
515
        constants[11].f = (resize_type == 2 || output_height) ? h / (float)outh : 1.f / height_scale;
516

517
        if (resize_type == 2 && align_corner)
518
        {
519
            constants[10].f = (w - 1) / (float)(outw - 1);
520
            constants[11].f = (h - 1) / (float)(outh - 1);
521
        }
522

523
        const Pipeline* pipeline = elempack == 8 ? pipeline_interp_pack8
524
                                   : elempack == 4 ? pipeline_interp_pack4
525
                                   : pipeline_interp;
526

527
        cmd.record_pipeline(pipeline, bindings, constants, top_blob);
528
    }
529
    else if (resize_type == 3) // bicubic
530
    {
531
        VkMat alpha(outw, (size_t)(elemsize / elempack * 4), 4, opt.workspace_vkallocator);
532
        if (alpha.empty())
533
            return -100;
534

535
        VkMat xofs(outw, (size_t)4u, 1, opt.workspace_vkallocator);
536
        if (xofs.empty())
537
            return -100;
538

539
        {
540
            std::vector<VkMat> bindings(2);
541
            bindings[0] = alpha;
542
            bindings[1] = xofs;
543

544
            std::vector<vk_constant_type> constants(3);
545
            constants[0].i = bottom_blob.w;
546
            constants[1].i = outw;
547
            constants[2].f = (float)bottom_blob.w / outw;
548

549
            if (align_corner)
550
            {
551
                constants[2].f = (w - 1) / (float)(outw - 1);
552
            }
553

554
            // record
555
            cmd.record_pipeline(pipeline_interp_bicubic_coeffs_x, bindings, constants, alpha);
556
        }
557

558
        VkMat beta(outh, (size_t)(elemsize / elempack * 4), 4, opt.workspace_vkallocator);
559
        if (beta.empty())
560
            return -100;
561

562
        VkMat yofs(outh, (size_t)4u, 1, opt.workspace_vkallocator);
563
        if (yofs.empty())
564
            return -100;
565

566
        {
567
            std::vector<VkMat> bindings(2);
568
            bindings[0] = beta;
569
            bindings[1] = yofs;
570

571
            std::vector<vk_constant_type> constants(3);
572
            constants[0].i = bottom_blob.h;
573
            constants[1].i = outh;
574
            constants[2].f = (float)bottom_blob.h / outh;
575

576
            if (align_corner)
577
            {
578
                constants[2].f = (h - 1) / (float)(outh - 1);
579
            }
580

581
            // record
582
            cmd.record_pipeline(pipeline_interp_bicubic_coeffs_y, bindings, constants, beta);
583
        }
584

585
        std::vector<VkMat> bindings(6);
586
        bindings[0] = bottom_blob;
587
        bindings[1] = top_blob;
588
        bindings[2] = alpha;
589
        bindings[3] = xofs;
590
        bindings[4] = beta;
591
        bindings[5] = yofs;
592

593
        std::vector<vk_constant_type> constants(10);
594
        constants[0].i = bottom_blob.dims;
595
        constants[1].i = bottom_blob.w;
596
        constants[2].i = bottom_blob.h;
597
        constants[3].i = bottom_blob.c;
598
        constants[4].i = bottom_blob.cstep;
599
        constants[5].i = top_blob.dims;
600
        constants[6].i = top_blob.w;
601
        constants[7].i = top_blob.h;
602
        constants[8].i = top_blob.c;
603
        constants[9].i = top_blob.cstep;
604

605
        const Pipeline* pipeline = elempack == 8 ? pipeline_interp_bicubic_pack8
606
                                   : elempack == 4 ? pipeline_interp_bicubic_pack4
607
                                   : pipeline_interp_bicubic;
608

609
        cmd.record_pipeline(pipeline, bindings, constants, top_blob);
610
    }
611

612
    return 0;
613
}
614

615
int Interp_vulkan::forward(const std::vector<VkImageMat>& bottom_blobs, std::vector<VkImageMat>& top_blobs, VkCompute& cmd, const Option& opt) const
616
{
617
    const VkImageMat& bottom_blob = bottom_blobs[0];
618
    const VkImageMat& reference_blob = bottom_blobs[1];
619
    VkImageMat& top_blob = top_blobs[0];
620

621
    int w = bottom_blob.w;
622
    int h = bottom_blob.h;
623
    int channels = bottom_blob.c;
624
    int dims = bottom_blob.dims;
625
    size_t elemsize = bottom_blob.elemsize;
626
    int elempack = bottom_blob.elempack;
627

628
    int outw = reference_blob.w;
629
    int outh = reference_blob.h;
630

631
    if (dims == 1)
632
    {
633
        top_blob.create(outw, outh, w, elemsize, elempack, opt.blob_vkallocator);
634
        if (top_blob.empty())
635
            return -100;
636

637
        std::vector<VkImageMat> bindings(2);
638
        bindings[0] = bottom_blob;
639
        bindings[1] = top_blob;
640

641
        std::vector<vk_constant_type> constants(12);
642
        constants[0].i = bottom_blob.dims;
643
        constants[1].i = bottom_blob.w;
644
        constants[2].i = bottom_blob.h;
645
        constants[3].i = bottom_blob.c;
646
        constants[4].i = 0; //bottom_blob.cstep;
647
        constants[5].i = top_blob.dims;
648
        constants[6].i = top_blob.w;
649
        constants[7].i = top_blob.h;
650
        constants[8].i = top_blob.c;
651
        constants[9].i = 0; //top_blob.cstep;
652
        constants[10].f = (resize_type == 2 || output_width) ? w / (float)outw : 1.f / width_scale;
653
        constants[11].f = (resize_type == 2 || output_height) ? h / (float)outh : 1.f / height_scale;
654

655
        const Pipeline* pipeline = elempack == 8 ? pipeline_interp_pack8
656
                                   : elempack == 4 ? pipeline_interp_pack4
657
                                   : pipeline_interp;
658

659
        cmd.record_pipeline(pipeline, bindings, constants, top_blob);
660

661
        return 0;
662
    }
663

664
    if (dims == 2)
665
    {
666
        if (outw == w)
667
        {
668
            top_blob = bottom_blob;
669
            return 0;
670
        }
671

672
        top_blob.create(outw, h, elemsize, elempack, opt.blob_vkallocator);
673
        if (top_blob.empty())
674
            return -100;
675

676
        if (resize_type == 1 || resize_type == 2) // nearest or bilinear
677
        {
678
            std::vector<VkImageMat> bindings(2);
679
            bindings[0] = bottom_blob;
680
            bindings[1] = top_blob;
681

682
            std::vector<vk_constant_type> constants(12);
683
            constants[0].i = bottom_blob.dims;
684
            constants[1].i = bottom_blob.w;
685
            constants[2].i = bottom_blob.h;
686
            constants[3].i = bottom_blob.c;
687
            constants[4].i = 0; //bottom_blob.cstep;
688
            constants[5].i = top_blob.dims;
689
            constants[6].i = top_blob.w;
690
            constants[7].i = top_blob.h;
691
            constants[8].i = top_blob.c;
692
            constants[9].i = 0; //top_blob.cstep;
693
            constants[10].f = (resize_type == 2 || output_width) ? w / (float)outw : 1.f / width_scale;
694
            constants[11].f = 1.f;
695

696
            if (resize_type == 2 && align_corner)
697
            {
698
                constants[10].f = (w - 1) / (float)(outw - 1);
699
            }
700

701
            const Pipeline* pipeline = elempack == 8 ? pipeline_interp_pack8
702
                                       : elempack == 4 ? pipeline_interp_pack4
703
                                       : pipeline_interp;
704

705
            cmd.record_pipeline(pipeline, bindings, constants, top_blob);
706
        }
707

708
        if (resize_type == 3) // bicubic
709
        {
710
            VkMat alpha(outw, (size_t)(elemsize / elempack * 4), 4, opt.workspace_vkallocator);
711
            if (alpha.empty())
712
                return -100;
713

714
            VkMat xofs(outw, (size_t)4u, 1, opt.workspace_vkallocator);
715
            if (xofs.empty())
716
                return -100;
717

718
            {
719
                std::vector<VkMat> bindings(2);
720
                bindings[0] = alpha;
721
                bindings[1] = xofs;
722

723
                std::vector<vk_constant_type> constants(3);
724
                constants[0].i = bottom_blob.w;
725
                constants[1].i = outw;
726
                constants[2].f = (float)bottom_blob.w / outw;
727

728
                if (align_corner)
729
                {
730
                    constants[2].f = (w - 1) / (float)(outw - 1);
731
                }
732

733
                // record
734
                cmd.record_pipeline(pipeline_interp_bicubic_coeffs_x, bindings, constants, alpha);
735
            }
736

737
            std::vector<VkMat> buffer_bindings(4);
738
            buffer_bindings[0] = alpha;
739
            buffer_bindings[1] = xofs;
740

741
            std::vector<VkImageMat> image_bindings(2);
742
            image_bindings[0] = bottom_blob;
743
            image_bindings[1] = top_blob;
744

745
            std::vector<vk_constant_type> constants(10);
746
            constants[0].i = bottom_blob.dims;
747
            constants[1].i = bottom_blob.w;
748
            constants[2].i = bottom_blob.h;
749
            constants[3].i = bottom_blob.c;
750
            constants[4].i = 0; //bottom_blob.cstep;
751
            constants[5].i = top_blob.dims;
752
            constants[6].i = top_blob.w;
753
            constants[7].i = top_blob.h;
754
            constants[8].i = top_blob.c;
755
            constants[9].i = 0; //top_blob.cstep;
756

757
            const Pipeline* pipeline = elempack == 8 ? pipeline_interp_bicubic_pack8
758
                                       : elempack == 4 ? pipeline_interp_bicubic_pack4
759
                                       : pipeline_interp_bicubic;
760

761
            cmd.record_pipeline(pipeline, buffer_bindings, image_bindings, constants, top_blob);
762
        }
763

764
        return 0;
765
    }
766

767
    if (outw == w && outh == h)
768
    {
769
        top_blob = bottom_blob;
770
        return 0;
771
    }
772

773
    top_blob.create(outw, outh, channels, elemsize, elempack, opt.blob_vkallocator);
774
    if (top_blob.empty())
775
        return -100;
776

777
    if (resize_type == 1 || resize_type == 2) // nearest or bilinear
778
    {
779
        std::vector<VkImageMat> bindings(2);
780
        bindings[0] = bottom_blob;
781
        bindings[1] = top_blob;
782

783
        std::vector<vk_constant_type> constants(12);
784
        constants[0].i = bottom_blob.dims;
785
        constants[1].i = bottom_blob.w;
786
        constants[2].i = bottom_blob.h;
787
        constants[3].i = bottom_blob.c;
788
        constants[4].i = 0; //bottom_blob.cstep;
789
        constants[5].i = top_blob.dims;
790
        constants[6].i = top_blob.w;
791
        constants[7].i = top_blob.h;
792
        constants[8].i = top_blob.c;
793
        constants[9].i = 0; //top_blob.cstep;
794
        constants[10].f = (resize_type == 2 || output_width) ? w / (float)outw : 1.f / width_scale;
795
        constants[11].f = (resize_type == 2 || output_height) ? h / (float)outh : 1.f / height_scale;
796

797
        if (resize_type == 2 && align_corner)
798
        {
799
            constants[10].f = (w - 1) / (float)(outw - 1);
800
            constants[11].f = (h - 1) / (float)(outh - 1);
801
        }
802

803
        const Pipeline* pipeline = elempack == 8 ? pipeline_interp_pack8
804
                                   : elempack == 4 ? pipeline_interp_pack4
805
                                   : pipeline_interp;
806

807
        cmd.record_pipeline(pipeline, bindings, constants, top_blob);
808
    }
809
    else if (resize_type == 3) // bicubic
810
    {
811
        VkMat alpha(outw, (size_t)(elemsize / elempack * 4), 4, opt.workspace_vkallocator);
812
        if (alpha.empty())
813
            return -100;
814

815
        VkMat xofs(outw, (size_t)4u, 1, opt.workspace_vkallocator);
816
        if (xofs.empty())
817
            return -100;
818

819
        {
820
            std::vector<VkMat> bindings(2);
821
            bindings[0] = alpha;
822
            bindings[1] = xofs;
823

824
            std::vector<vk_constant_type> constants(3);
825
            constants[0].i = bottom_blob.w;
826
            constants[1].i = outw;
827
            constants[2].f = (float)bottom_blob.w / outw;
828

829
            if (align_corner)
830
            {
831
                constants[2].f = (w - 1) / (float)(outw - 1);
832
            }
833

834
            // record
835
            cmd.record_pipeline(pipeline_interp_bicubic_coeffs_x, bindings, constants, alpha);
836
        }
837

838
        VkMat beta(outh, (size_t)(elemsize / elempack * 4), 4, opt.workspace_vkallocator);
839
        if (beta.empty())
840
            return -100;
841

842
        VkMat yofs(outh, (size_t)4u, 1, opt.workspace_vkallocator);
843
        if (yofs.empty())
844
            return -100;
845

846
        {
847
            std::vector<VkMat> bindings(2);
848
            bindings[0] = beta;
849
            bindings[1] = yofs;
850

851
            std::vector<vk_constant_type> constants(3);
852
            constants[0].i = bottom_blob.h;
853
            constants[1].i = outh;
854
            constants[2].f = (float)bottom_blob.h / outh;
855

856
            if (align_corner)
857
            {
858
                constants[2].f = (h - 1) / (float)(outh - 1);
859
            }
860

861
            // record
862
            cmd.record_pipeline(pipeline_interp_bicubic_coeffs_y, bindings, constants, beta);
863
        }
864

865
        std::vector<VkMat> buffer_bindings(4);
866
        buffer_bindings[0] = alpha;
867
        buffer_bindings[1] = xofs;
868
        buffer_bindings[2] = beta;
869
        buffer_bindings[3] = yofs;
870

871
        std::vector<VkImageMat> image_bindings(2);
872
        image_bindings[0] = bottom_blob;
873
        image_bindings[1] = top_blob;
874

875
        std::vector<vk_constant_type> constants(10);
876
        constants[0].i = bottom_blob.dims;
877
        constants[1].i = bottom_blob.w;
878
        constants[2].i = bottom_blob.h;
879
        constants[3].i = bottom_blob.c;
880
        constants[4].i = 0; //bottom_blob.cstep;
881
        constants[5].i = top_blob.dims;
882
        constants[6].i = top_blob.w;
883
        constants[7].i = top_blob.h;
884
        constants[8].i = top_blob.c;
885
        constants[9].i = 0; //top_blob.cstep;
886

887
        const Pipeline* pipeline = elempack == 8 ? pipeline_interp_bicubic_pack8
888
                                   : elempack == 4 ? pipeline_interp_bicubic_pack4
889
                                   : pipeline_interp_bicubic;
890

891
        cmd.record_pipeline(pipeline, buffer_bindings, image_bindings, constants, top_blob);
892
    }
893

894
    return 0;
895
}
896

897
} // namespace ncnn
898

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.