Browse Source

add more pack8 shaders

tags/20200226
nihui 6 years ago
parent
commit
e8052e830e
12 changed files with 1188 additions and 35 deletions
  1. +65
    -0
      src/layer/vulkan/shader/instancenorm_coeffs_pack8.comp
  2. +61
    -0
      src/layer/vulkan/shader/instancenorm_norm_pack8.comp
  3. +64
    -0
      src/layer/vulkan/shader/instancenorm_reduce_mean_pack8.comp
  4. +92
    -0
      src/layer/vulkan/shader/instancenorm_reduce_sum4_fp16_to_fp32_pack8.comp
  5. +92
    -0
      src/layer/vulkan/shader/instancenorm_reduce_sum4_fp32_pack8.comp
  6. +62
    -0
      src/layer/vulkan/shader/instancenorm_sub_mean_square_pack8.comp
  7. +79
    -0
      src/layer/vulkan/shader/normalize_coeffs_pack8.comp
  8. +91
    -0
      src/layer/vulkan/shader/normalize_norm_pack8.comp
  9. +29
    -35
      src/layer/vulkan/shader/normalize_reduce_sum4_fp16_to_fp32_pack4.comp
  10. +227
    -0
      src/layer/vulkan/shader/normalize_reduce_sum4_fp16_to_fp32_pack8.comp
  11. +203
    -0
      src/layer/vulkan/shader/normalize_reduce_sum4_fp32_pack8.comp
  12. +123
    -0
      src/layer/vulkan/shader/permute_pack8to1.comp

+ 65
- 0
src/layer/vulkan/shader/instancenorm_coeffs_pack8.comp View File

@@ -0,0 +1,65 @@
// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2020 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

#if NCNN_fp16_storage
#extension GL_EXT_shader_16bit_storage: require
struct sfpvec8 { f16vec4 abcd; f16vec4 efgh; };
#endif
#if NCNN_fp16_arithmetic
#extension GL_EXT_shader_explicit_arithmetic_types_float16: require
#endif

layout (constant_id = 0) const float eps = 0;

layout (local_size_x_id = 233) in;
layout (local_size_y_id = 234) in;
layout (local_size_z_id = 235) in;

layout (binding = 0) writeonly buffer coeffs_blob { sfpvec8 coeffs_blob_data[]; };
layout (binding = 1) readonly buffer mean_blob { sfpvec8 mean_data[]; };
layout (binding = 2) readonly buffer var_blob { sfpvec8 var_data[]; };
layout (binding = 3) readonly buffer gamma_blob { sfpvec8 gamma_data[]; };
layout (binding = 4) readonly buffer beta_blob { sfpvec8 beta_data[]; };

layout (push_constant) uniform parameter
{
int w;
} 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 >= 1 || gz >= 1)
return;

afpvec8 mean = buffer_ld8(mean_data, gx);
afpvec8 var = buffer_ld8(var_data, gx);
afpvec8 gamma = buffer_ld8(gamma_data, gx);
afpvec8 beta = buffer_ld8(beta_data, gx);

afpvec8 a;
afpvec8 b;
a[0] = gamma[0] / (sqrt(var[0] + afp(eps)));
a[1] = gamma[1] / (sqrt(var[1] + afp(eps)));
b[0] = - mean[0] * a[0] + beta[0];
b[1] = - mean[1] * a[1] + beta[1];

buffer_st8(coeffs_blob_data, gx*2, a);
buffer_st8(coeffs_blob_data, gx*2 +1, b);
}

+ 61
- 0
src/layer/vulkan/shader/instancenorm_norm_pack8.comp View File

@@ -0,0 +1,61 @@
// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2020 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

#if NCNN_fp16_storage
#extension GL_EXT_shader_16bit_storage: require
struct sfpvec8 { f16vec4 abcd; f16vec4 efgh; };
#endif
#if NCNN_fp16_arithmetic
#extension GL_EXT_shader_explicit_arithmetic_types_float16: require
#endif

layout (local_size_x_id = 233) in;
layout (local_size_y_id = 234) in;
layout (local_size_z_id = 235) in;

layout (binding = 0) buffer bottom_top_blob { sfpvec8 bottom_top_blob_data[]; };
layout (binding = 1) readonly buffer coeffs_blob { sfpvec8 coeffs_blob_data[]; };

layout (push_constant) uniform parameter
{
int dims;
int w;
int h;
int c;
int cstep;
} 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;

const int gi = gz * p.cstep + gy * p.w + gx;

afpvec8 v = buffer_ld8(bottom_top_blob_data, gi);

afpvec8 a = buffer_ld8(coeffs_blob_data, gz*2);
afpvec8 b = buffer_ld8(coeffs_blob_data, gz*2 +1);

v[0] = v[0] * a[0] + b[0];
v[1] = v[1] * a[1] + b[1];

buffer_st8(bottom_top_blob_data, gi, v);
}

+ 64
- 0
src/layer/vulkan/shader/instancenorm_reduce_mean_pack8.comp View File

@@ -0,0 +1,64 @@
// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2020 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

#if NCNN_fp16_storage
#extension GL_EXT_shader_16bit_storage: require
struct sfpvec8 { f16vec4 abcd; f16vec4 efgh; };
#endif
#if NCNN_fp16_arithmetic
#extension GL_EXT_shader_explicit_arithmetic_types_float16: require
#endif

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_top_blob { mat2x4 bottom_top_blob_data[]; };
layout (binding = 1) writeonly buffer mean_blob { sfpvec8 mean_data[]; };

layout (push_constant) uniform parameter
{
int size;
int c;
int cstep;
float area;
} p;

void main()
{
int gx = int(gl_GlobalInvocationID.x);
int gy = int(gl_GlobalInvocationID.y);
int gz = int(gl_GlobalInvocationID.z);

if (gx >= p.c || gy >= 1 || gz >= 1)
return;

afpvec8 sum = afpvec8(afpvec4(0.f), afpvec4(0.f));

int v_offset = gx * p.cstep;

for (int i = 0; i < p.size; i++)
{
sum += afpvec8(bottom_top_blob_data[v_offset]);
v_offset += 1;
}

afpvec8 mean;
mean[0] = sum[0] / afp(p.area);
mean[1] = sum[1] / afp(p.area);

buffer_st8(mean_data, gx, mean);
}

+ 92
- 0
src/layer/vulkan/shader/instancenorm_reduce_sum4_fp16_to_fp32_pack8.comp View File

@@ -0,0 +1,92 @@
// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2020 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

#if NCNN_fp16_storage
#extension GL_EXT_shader_16bit_storage: require
struct sfpvec8 { f16vec4 abcd; f16vec4 efgh; };
#endif
#if NCNN_fp16_arithmetic
#extension GL_EXT_shader_explicit_arithmetic_types_float16: require
#endif

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_top_blob { sfpvec8 bottom_top_blob_data[]; };
layout (binding = 1) writeonly buffer sum_blob { mat2x4 sum_blob_data[]; };

layout (push_constant) uniform parameter
{
int size;
int c;
int cstep;

int outsize;
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.outsize || gy >= 1 || gz >= p.outc)
return;

int gi = gz * p.outcstep + gx;

int sx = gx * 4;

int v_offset = gz * p.cstep + sx;

if (sx == p.size - 1)
{
sum_blob_data[gi] = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset));
}
else if (sx == p.size - 2)
{
mat2x4 v0 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset));
mat2x4 v1 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset + 1));

mat2x4 sum = v0 + v1;

sum_blob_data[gi] = sum;
}
else if (sx == p.size - 3)
{
mat2x4 v0 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset));
mat2x4 v1 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset + 1));
mat2x4 v2 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset + 2));

mat2x4 sum = v0 + v1 + v2;

sum_blob_data[gi] = sum;
}
else
{
mat2x4 v0 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset));
mat2x4 v1 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset + 1));
mat2x4 v2 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset + 2));
mat2x4 v3 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset + 3));

mat2x4 sum = v0 + v1 + v2 + v3;

sum_blob_data[gi] = sum;
}
}

+ 92
- 0
src/layer/vulkan/shader/instancenorm_reduce_sum4_fp32_pack8.comp View File

@@ -0,0 +1,92 @@
// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2020 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

#if NCNN_fp16_storage
#extension GL_EXT_shader_16bit_storage: require
struct sfpvec8 { f16vec4 abcd; f16vec4 efgh; };
#endif
#if NCNN_fp16_arithmetic
#extension GL_EXT_shader_explicit_arithmetic_types_float16: require
#endif

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 square_blob { mat2x4 square_blob_data[]; };
layout (binding = 1) writeonly buffer sqsum_blob { mat2x4 sqsum_blob_data[]; };

layout (push_constant) uniform parameter
{
int size;
int c;
int cstep;

int outsize;
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.outsize || gy >= 1 || gz >= p.outc)
return;

int gi = gz * p.outcstep + gx;

int sx = gx * 4;

int v_offset = gz * p.cstep + sx;

if (sx == p.size - 1)
{
sqsum_blob_data[gi] = square_blob_data[v_offset];
}
else if (sx == p.size - 2)
{
mat2x4 v0 = square_blob_data[v_offset];
mat2x4 v1 = square_blob_data[v_offset + 1];

mat2x4 sum = v0 + v1;

sqsum_blob_data[gi] = sum;
}
else if (sx == p.size - 3)
{
mat2x4 v0 = square_blob_data[v_offset];
mat2x4 v1 = square_blob_data[v_offset + 1];
mat2x4 v2 = square_blob_data[v_offset + 2];

mat2x4 sum = v0 + v1 + v2;

sqsum_blob_data[gi] = sum;
}
else
{
mat2x4 v0 = square_blob_data[v_offset];
mat2x4 v1 = square_blob_data[v_offset + 1];
mat2x4 v2 = square_blob_data[v_offset + 2];
mat2x4 v3 = square_blob_data[v_offset + 3];

mat2x4 sum = v0 + v1 + v2 + v3;

sqsum_blob_data[gi] = sum;
}
}

+ 62
- 0
src/layer/vulkan/shader/instancenorm_sub_mean_square_pack8.comp View File

@@ -0,0 +1,62 @@
// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2020 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

#if NCNN_fp16_storage
#extension GL_EXT_shader_16bit_storage: require
struct sfpvec8 { f16vec4 abcd; f16vec4 efgh; };
#endif
#if NCNN_fp16_arithmetic
#extension GL_EXT_shader_explicit_arithmetic_types_float16: require
#endif

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_top_blob { sfpvec8 bottom_top_blob_data[]; };
layout (binding = 1) readonly buffer mean_blob { sfpvec8 mean_data[]; };
layout (binding = 2) writeonly buffer square_blob { mat2x4 square_blob_data[]; };

layout (push_constant) uniform parameter
{
int dims;
int w;
int h;
int c;
int cstep;
} 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;

const int gi = gz * p.cstep + gy * p.w + gx;

afpvec8 v = buffer_ld8(bottom_top_blob_data, gi);
afpvec8 mean = buffer_ld8(mean_data, gz);

v[0] = v[0] - mean[0];
v[1] = v[1] - mean[1];
v[0] = v[0] * v[0];
v[1] = v[1] * v[1];

square_blob_data[gi] = mat2x4(v);
}

+ 79
- 0
src/layer/vulkan/shader/normalize_coeffs_pack8.comp View File

@@ -0,0 +1,79 @@
// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2020 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

#if NCNN_fp16_storage
#extension GL_EXT_shader_16bit_storage: require
struct sfpvec8 { f16vec4 abcd; f16vec4 efgh; };
#endif
#if NCNN_fp16_arithmetic
#extension GL_EXT_shader_explicit_arithmetic_types_float16: require
#endif

layout (constant_id = 0) const float eps = 0.f;
layout (constant_id = 1) const int eps_mode = 0;

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 sqsum_blob { mat2x4 sqsum_blob_data[]; };
layout (binding = 1) writeonly buffer coeffs_blob { sfpvec8 coeffs_blob_data[]; };

layout (push_constant) uniform parameter
{
int size;
int c;
int cstep;
} p;

void main()
{
int gx = int(gl_GlobalInvocationID.x);
int gy = int(gl_GlobalInvocationID.y);
int gz = int(gl_GlobalInvocationID.z);

if (gx >= p.size || gy >= 1 || gz >= p.c)
return;

int gi = gz * p.cstep + gx;

mat2x4 sqsum_8 = sqsum_blob_data[gi];

vec4 sqsum_4 = sqsum_8[0] + sqsum_8[1];

afp sqsum = afp(sqsum_4.r + sqsum_4.g + sqsum_4.b + sqsum_4.a);

afp a;

if (eps_mode == 0) // caffe/mxnet
{
a = afp(1.f) / sqrt(sqsum + afp(eps));
}

if (eps_mode == 1) // pytorch
{
a = afp(1.f) / max(sqrt(sqsum), afp(eps));
}

if (eps_mode == 2) // tensorflow
{
a = afp(1.f) / sqrt(max(sqsum, afp(eps)));
}

afpvec8 a8 = afpvec8(afpvec4(a), afpvec4(a));

buffer_st8(coeffs_blob_data, gi, a8);
}

+ 91
- 0
src/layer/vulkan/shader/normalize_norm_pack8.comp View File

@@ -0,0 +1,91 @@
// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2020 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

#if NCNN_fp16_storage
#extension GL_EXT_shader_16bit_storage: require
struct sfpvec8 { f16vec4 abcd; f16vec4 efgh; };
#endif
#if NCNN_fp16_arithmetic
#extension GL_EXT_shader_explicit_arithmetic_types_float16: require
#endif

layout (constant_id = 0) const int across_spatial = 0;
layout (constant_id = 1) const int across_channel = 0;
layout (constant_id = 2) const int channel_shared = 0;
layout (constant_id = 3) const int scale_term = 0;

layout (local_size_x_id = 233) in;
layout (local_size_y_id = 234) in;
layout (local_size_z_id = 235) in;

layout (binding = 0) buffer bottom_top_blob { sfpvec8 bottom_top_blob_data[]; };
layout (binding = 1) readonly buffer coeffs_blob { sfpvec8 coeffs_blob_data[]; };
layout (binding = 2) readonly buffer scale_blob { sfpvec8 scale_blob_data[]; };

layout (push_constant) uniform parameter
{
int dims;
int w;
int h;
int c;
int cstep;
} 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;

const int gi = gz * p.cstep + gy * p.w + gx;

afpvec8 v = buffer_ld8(bottom_top_blob_data, gi);

afpvec8 a;

if (across_spatial == 1 && across_channel == 1)
{
a = buffer_ld8(coeffs_blob_data, 0);
}

if (across_spatial == 1 && across_channel == 0)
{
a = buffer_ld8(coeffs_blob_data, gz);
}

if (across_spatial == 0 && across_channel == 1)
{
a = buffer_ld8(coeffs_blob_data, gy * p.w + gx);
}

v[0] = v[0] * a[0];
v[1] = v[1] * a[1];

if (scale_term == 1)
{
int si = channel_shared == 1 ? 0 : gz;

afpvec8 scale = buffer_ld8(scale_blob_data, si);

v[0] = v[0] * scale[0];
v[1] = v[1] * scale[1];
}

buffer_st8(bottom_top_blob_data, gi, v);
}

+ 29
- 35
src/layer/vulkan/shader/normalize_reduce_sum4_fp16_to_fp32_pack4.comp View File

@@ -21,12 +21,6 @@
#extension GL_EXT_shader_explicit_arithmetic_types_float16: require
#endif

#if NCNN_fp16_packed
#define sfp2floatvec4(v) vec4(unpackHalf2x16(v.x), unpackHalf2x16(v.y))
#else
#define sfp2floatvec4(v) vec4(v)
#endif

layout (constant_id = 0) const int across_spatial = 0;
layout (constant_id = 1) const int across_channel = 0;

@@ -71,7 +65,7 @@ void main()
{
if (sx == p.size - 1)
{
vec4 v0 = sfp2floatvec4(bottom_top_blob_data[v_offset0.r]);
vec4 v0 = vec4(buffer_ld4(bottom_top_blob_data, v_offset0.r));

vec4 sqsum = v0 * v0;

@@ -79,8 +73,8 @@ void main()
}
else
{
vec4 v0 = sfp2floatvec4(bottom_top_blob_data[v_offset0.r]);
vec4 v1 = sfp2floatvec4(bottom_top_blob_data[v_offset0.g]);
vec4 v0 = vec4(buffer_ld4(bottom_top_blob_data, v_offset0.r));
vec4 v1 = vec4(buffer_ld4(bottom_top_blob_data, v_offset0.g));

vec4 sqsum = v0 * v0 + v1 * v1;

@@ -91,8 +85,8 @@ void main()
{
if (sx == p.size - 1)
{
vec4 v0 = sfp2floatvec4(bottom_top_blob_data[v_offset0.r]);
vec4 v2 = sfp2floatvec4(bottom_top_blob_data[v_offset1.r]);
vec4 v0 = vec4(buffer_ld4(bottom_top_blob_data, v_offset0.r));
vec4 v2 = vec4(buffer_ld4(bottom_top_blob_data, v_offset1.r));

vec4 sqsum = v0 * v0 + v2 * v2;

@@ -100,10 +94,10 @@ void main()
}
else
{
vec4 v0 = sfp2floatvec4(bottom_top_blob_data[v_offset0.r]);
vec4 v1 = sfp2floatvec4(bottom_top_blob_data[v_offset0.g]);
vec4 v2 = sfp2floatvec4(bottom_top_blob_data[v_offset1.r]);
vec4 v3 = sfp2floatvec4(bottom_top_blob_data[v_offset1.g]);
vec4 v0 = vec4(buffer_ld4(bottom_top_blob_data, v_offset0.r));
vec4 v1 = vec4(buffer_ld4(bottom_top_blob_data, v_offset0.g));
vec4 v2 = vec4(buffer_ld4(bottom_top_blob_data, v_offset1.r));
vec4 v3 = vec4(buffer_ld4(bottom_top_blob_data, v_offset1.g));

vec4 sqsum = v0 * v0 + v1 * v1 + v2 * v2 + v3 * v3;

@@ -121,7 +115,7 @@ void main()

if (sx == p.size - 1)
{
vec4 v0 = sfp2floatvec4(bottom_top_blob_data[v_offset.r]);
vec4 v0 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.r));

vec4 sqsum = v0 * v0;

@@ -129,8 +123,8 @@ void main()
}
else if (sx == p.size - 2)
{
vec4 v0 = sfp2floatvec4(bottom_top_blob_data[v_offset.r]);
vec4 v1 = sfp2floatvec4(bottom_top_blob_data[v_offset.g]);
vec4 v0 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.r));
vec4 v1 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.g));

vec4 sqsum = v0 * v0 + v1 * v1;

@@ -138,9 +132,9 @@ void main()
}
else if (sx == p.size - 3)
{
vec4 v0 = sfp2floatvec4(bottom_top_blob_data[v_offset.r]);
vec4 v1 = sfp2floatvec4(bottom_top_blob_data[v_offset.g]);
vec4 v2 = sfp2floatvec4(bottom_top_blob_data[v_offset.b]);
vec4 v0 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.r));
vec4 v1 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.g));
vec4 v2 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.b));

vec4 sqsum = v0 * v0 + v1 * v1 + v2 * v2;

@@ -148,10 +142,10 @@ void main()
}
else
{
vec4 v0 = sfp2floatvec4(bottom_top_blob_data[v_offset.r]);
vec4 v1 = sfp2floatvec4(bottom_top_blob_data[v_offset.g]);
vec4 v2 = sfp2floatvec4(bottom_top_blob_data[v_offset.b]);
vec4 v3 = sfp2floatvec4(bottom_top_blob_data[v_offset.a]);
vec4 v0 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.r));
vec4 v1 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.g));
vec4 v2 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.b));
vec4 v3 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.a));

vec4 sqsum = v0 * v0 + v1 * v1 + v2 * v2 + v3 * v3;

@@ -168,7 +162,7 @@ void main()

if (sz == p.c - 1)
{
vec4 v0 = sfp2floatvec4(bottom_top_blob_data[v_offset.r]);
vec4 v0 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.r));

vec4 sqsum = v0 * v0;

@@ -176,8 +170,8 @@ void main()
}
else if (sz == p.c - 2)
{
vec4 v0 = sfp2floatvec4(bottom_top_blob_data[v_offset.r]);
vec4 v1 = sfp2floatvec4(bottom_top_blob_data[v_offset.g]);
vec4 v0 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.r));
vec4 v1 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.g));

vec4 sqsum = v0 * v0 + v1 * v1;

@@ -185,9 +179,9 @@ void main()
}
else if (sz == p.c - 3)
{
vec4 v0 = sfp2floatvec4(bottom_top_blob_data[v_offset.r]);
vec4 v1 = sfp2floatvec4(bottom_top_blob_data[v_offset.g]);
vec4 v2 = sfp2floatvec4(bottom_top_blob_data[v_offset.b]);
vec4 v0 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.r));
vec4 v1 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.g));
vec4 v2 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.b));

vec4 sqsum = v0 * v0 + v1 * v1 + v2 * v2;

@@ -195,10 +189,10 @@ void main()
}
else
{
vec4 v0 = sfp2floatvec4(bottom_top_blob_data[v_offset.r]);
vec4 v1 = sfp2floatvec4(bottom_top_blob_data[v_offset.g]);
vec4 v2 = sfp2floatvec4(bottom_top_blob_data[v_offset.b]);
vec4 v3 = sfp2floatvec4(bottom_top_blob_data[v_offset.a]);
vec4 v0 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.r));
vec4 v1 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.g));
vec4 v2 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.b));
vec4 v3 = vec4(buffer_ld4(bottom_top_blob_data, v_offset.a));

vec4 sqsum = v0 * v0 + v1 * v1 + v2 * v2 + v3 * v3;



+ 227
- 0
src/layer/vulkan/shader/normalize_reduce_sum4_fp16_to_fp32_pack8.comp View File

@@ -0,0 +1,227 @@
// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2020 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

#if NCNN_fp16_storage
#extension GL_EXT_shader_16bit_storage: require
struct sfpvec8 { f16vec4 abcd; f16vec4 efgh; };
#endif
#if NCNN_fp16_arithmetic
#extension GL_EXT_shader_explicit_arithmetic_types_float16: require
#endif

layout (constant_id = 0) const int across_spatial = 0;
layout (constant_id = 1) const int across_channel = 0;

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_top_blob { sfpvec8 bottom_top_blob_data[]; };
layout (binding = 1) writeonly buffer sqsum_blob { mat2x4 sqsum_blob_data[]; };

layout (push_constant) uniform parameter
{
int size;
int c;
int cstep;

int outsize;
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.outsize || gy >= 1 || gz >= p.outc)
return;

int gi = gz * p.outcstep + gx;

if (across_spatial == 1 && across_channel == 1)
{
int sz = gz * 2;
int sx = gx * 2;

ivec2 v_offset0 = sz * p.cstep + sx + ivec2(0, 1);
ivec2 v_offset1 = v_offset0 + p.cstep;

if (sz == p.c - 1)
{
if (sx == p.size - 1)
{
mat2x4 v0 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset0.r));

mat2x4 sqsum;
sqsum[0] = v0[0] * v0[0];
sqsum[1] = v0[1] * v0[1];

sqsum_blob_data[gi] = sqsum;
}
else
{
mat2x4 v0 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset0.r));
mat2x4 v1 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset0.g));

mat2x4 sqsum;
sqsum[0] = v0[0] * v0[0] + v1[0] * v1[0];
sqsum[1] = v0[1] * v0[1] + v1[1] * v1[1];

sqsum_blob_data[gi] = sqsum;
}
}
else
{
if (sx == p.size - 1)
{
mat2x4 v0 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset0.r));
mat2x4 v2 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset1.r));

mat2x4 sqsum;
sqsum[0] = v0[0] * v0[0] + v2[0] * v2[0];
sqsum[1] = v0[1] * v0[1] + v2[1] * v2[1];

sqsum_blob_data[gi] = sqsum;
}
else
{
mat2x4 v0 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset0.r));
mat2x4 v1 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset0.g));
mat2x4 v2 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset1.r));
mat2x4 v3 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset1.g));

mat2x4 sqsum;
sqsum[0] = v0[0] * v0[0] + v1[0] * v1[0] + v2[0] * v2[0] + v3[0] * v3[0];
sqsum[1] = v0[1] * v0[1] + v1[1] * v1[1] + v2[1] * v2[1] + v3[1] * v3[1];

sqsum_blob_data[gi] = sqsum;
}
}
}

if (across_spatial == 1 && across_channel == 0)
{
int sz = gz;
int sx = gx * 4;

ivec4 v_offset = sz * p.cstep + sx + ivec4(0, 1, 2, 3);

if (sx == p.size - 1)
{
mat2x4 v0 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.r));

mat2x4 sqsum;
sqsum[0] = v0[0] * v0[0];
sqsum[1] = v0[1] * v0[1];

sqsum_blob_data[gi] = sqsum;
}
else if (sx == p.size - 2)
{
mat2x4 v0 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.r));
mat2x4 v1 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.g));

mat2x4 sqsum;
sqsum[0] = v0[0] * v0[0] + v1[0] * v1[0];
sqsum[1] = v0[1] * v0[1] + v1[1] * v1[1];

sqsum_blob_data[gi] = sqsum;
}
else if (sx == p.size - 3)
{
mat2x4 v0 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.r));
mat2x4 v1 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.g));
mat2x4 v2 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.b));

mat2x4 sqsum;
sqsum[0] = v0[0] * v0[0] + v1[0] * v1[0] + v2[0] * v2[0];
sqsum[1] = v0[1] * v0[1] + v1[1] * v1[1] + v2[1] * v2[1];

sqsum_blob_data[gi] = sqsum;
}
else
{
mat2x4 v0 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.r));
mat2x4 v1 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.g));
mat2x4 v2 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.b));
mat2x4 v3 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.a));

mat2x4 sqsum;
sqsum[0] = v0[0] * v0[0] + v1[0] * v1[0] + v2[0] * v2[0] + v3[0] * v3[0];
sqsum[1] = v0[1] * v0[1] + v1[1] * v1[1] + v2[1] * v2[1] + v3[1] * v3[1];

sqsum_blob_data[gi] = sqsum;
}
}

if (across_spatial == 0 && across_channel == 1)
{
int sz = gz * 4;
int sx = gx;

ivec4 v_offset = (sz + ivec4(0, 1, 2, 3)) * p.cstep + sx;

if (sz == p.c - 1)
{
mat2x4 v0 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.r));

mat2x4 sqsum;
sqsum[0] = v0[0] * v0[0];
sqsum[1] = v0[1] * v0[1];

sqsum_blob_data[gi] = sqsum;
}
else if (sz == p.c - 2)
{
mat2x4 v0 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.r));
mat2x4 v1 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.g));

mat2x4 sqsum;
sqsum[0] = v0[0] * v0[0] + v1[0] * v1[0];
sqsum[1] = v0[1] * v0[1] + v1[1] * v1[1];

sqsum_blob_data[gi] = sqsum;
}
else if (sz == p.c - 3)
{
mat2x4 v0 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.r));
mat2x4 v1 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.g));
mat2x4 v2 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.b));

mat2x4 sqsum;
sqsum[0] = v0[0] * v0[0] + v1[0] * v1[0] + v2[0] * v2[0];
sqsum[1] = v0[1] * v0[1] + v1[1] * v1[1] + v2[1] * v2[1];

sqsum_blob_data[gi] = sqsum;
}
else
{
mat2x4 v0 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.r));
mat2x4 v1 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.g));
mat2x4 v2 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.b));
mat2x4 v3 = mat2x4(buffer_ld8(bottom_top_blob_data, v_offset.a));

mat2x4 sqsum;
sqsum[0] = v0[0] * v0[0] + v1[0] * v1[0] + v2[0] * v2[0] + v3[0] * v3[0];
sqsum[1] = v0[1] * v0[1] + v1[1] * v1[1] + v2[1] * v2[1] + v3[1] * v3[1];

sqsum_blob_data[gi] = sqsum;
}
}
}

+ 203
- 0
src/layer/vulkan/shader/normalize_reduce_sum4_fp32_pack8.comp View File

@@ -0,0 +1,203 @@
// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2020 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

#if NCNN_fp16_storage
#extension GL_EXT_shader_16bit_storage: require
struct sfpvec8 { f16vec4 abcd; f16vec4 efgh; };
#endif
#if NCNN_fp16_arithmetic
#extension GL_EXT_shader_explicit_arithmetic_types_float16: require
#endif

layout (constant_id = 0) const int across_spatial = 0;
layout (constant_id = 1) const int across_channel = 0;

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 square_blob { mat2x4 square_blob_data[]; };
layout (binding = 1) writeonly buffer sqsum_blob { mat2x4 sqsum_blob_data[]; };

layout (push_constant) uniform parameter
{
int size;
int c;
int cstep;

int outsize;
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.outsize || gy >= 1 || gz >= p.outc)
return;

int gi = gz * p.outcstep + gx;

if (across_spatial == 1 && across_channel == 1)
{
int sz = gz * 2;
int sx = gx * 2;

ivec2 v_offset0 = sz * p.cstep + sx + ivec2(0, 1);
ivec2 v_offset1 = v_offset0 + p.cstep;

if (sz == p.c - 1)
{
if (sx == p.size - 1)
{
mat2x4 v0 = square_blob_data[v_offset0.r];

mat2x4 sqsum = v0;

sqsum_blob_data[gi] = sqsum;
}
else
{
mat2x4 v0 = square_blob_data[v_offset0.r];
mat2x4 v1 = square_blob_data[v_offset0.g];

mat2x4 sqsum = v0 + v1;

sqsum_blob_data[gi] = sqsum;
}
}
else
{
if (sx == p.size - 1)
{
mat2x4 v0 = square_blob_data[v_offset0.r];
mat2x4 v2 = square_blob_data[v_offset1.r];

mat2x4 sqsum = v0 + v2;

sqsum_blob_data[gi] = sqsum;
}
else
{
mat2x4 v0 = square_blob_data[v_offset0.r];
mat2x4 v1 = square_blob_data[v_offset0.g];
mat2x4 v2 = square_blob_data[v_offset1.r];
mat2x4 v3 = square_blob_data[v_offset1.g];

mat2x4 sqsum = v0 + v1 + v2 + v3;

sqsum_blob_data[gi] = sqsum;
}
}
}

if (across_spatial == 1 && across_channel == 0)
{
int sz = gz;
int sx = gx * 4;

ivec4 v_offset = sz * p.cstep + sx + ivec4(0, 1, 2, 3);

if (sx == p.size - 1)
{
mat2x4 v0 = square_blob_data[v_offset.r];

mat2x4 sqsum = v0;

sqsum_blob_data[gi] = sqsum;
}
else if (sx == p.size - 2)
{
mat2x4 v0 = square_blob_data[v_offset.r];
mat2x4 v1 = square_blob_data[v_offset.g];

mat2x4 sqsum = v0 + v1;

sqsum_blob_data[gi] = sqsum;
}
else if (sx == p.size - 3)
{
mat2x4 v0 = square_blob_data[v_offset.r];
mat2x4 v1 = square_blob_data[v_offset.g];
mat2x4 v2 = square_blob_data[v_offset.b];

mat2x4 sqsum = v0 + v1 + v2;

sqsum_blob_data[gi] = sqsum;
}
else
{
mat2x4 v0 = square_blob_data[v_offset.r];
mat2x4 v1 = square_blob_data[v_offset.g];
mat2x4 v2 = square_blob_data[v_offset.b];
mat2x4 v3 = square_blob_data[v_offset.a];

mat2x4 sqsum = v0 + v1 + v2 + v3;

sqsum_blob_data[gi] = sqsum;
}
}

if (across_spatial == 0 && across_channel == 1)
{
int sz = gz * 4;
int sx = gx;

ivec4 v_offset = (sz + ivec4(0, 1, 2, 3)) * p.cstep + sx;

if (sz == p.c - 1)
{
mat2x4 v0 = square_blob_data[v_offset.r];

mat2x4 sqsum = v0;

sqsum_blob_data[gi] = sqsum;
}
else if (sz == p.c - 2)
{
mat2x4 v0 = square_blob_data[v_offset.r];
mat2x4 v1 = square_blob_data[v_offset.g];

mat2x4 sqsum = v0 + v1;

sqsum_blob_data[gi] = sqsum;
}
else if (sz == p.c - 3)
{
mat2x4 v0 = square_blob_data[v_offset.r];
mat2x4 v1 = square_blob_data[v_offset.g];
mat2x4 v2 = square_blob_data[v_offset.b];

mat2x4 sqsum = v0 + v1 + v2;

sqsum_blob_data[gi] = sqsum;
}
else
{
mat2x4 v0 = square_blob_data[v_offset.r];
mat2x4 v1 = square_blob_data[v_offset.g];
mat2x4 v2 = square_blob_data[v_offset.b];
mat2x4 v3 = square_blob_data[v_offset.a];

mat2x4 sqsum = v0 + v1 + v2 + v3;

sqsum_blob_data[gi] = sqsum;
}
}
}

+ 123
- 0
src/layer/vulkan/shader/permute_pack8to1.comp View File

@@ -0,0 +1,123 @@
// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2020 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

#if NCNN_fp16_storage
#extension GL_EXT_shader_16bit_storage: require
struct sfpvec8 { f16vec4 abcd; f16vec4 efgh; };
#endif
#if NCNN_fp16_arithmetic
#extension GL_EXT_shader_explicit_arithmetic_types_float16: require
#endif

layout (constant_id = 0) const int order_type = 0;

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 { sfpvec8 bottom_blob_data[]; };
layout (binding = 1) writeonly buffer top_blob { sfp 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 v_offset;
ivec4 vv_offset;

if (p.dims == 2)
{
// order_type
// 0 = w h
// 1 = h w

if (order_type == 0)
{
v_offset = ivec4((gy * 8) * p.outw + gx) + ivec4(0, 1, 2, 3) * p.outw;
vv_offset = v_offset + 4 * p.outw;
}
if (order_type == 1)
{
v_offset = ivec4(gx * p.outw + gy * 8) + ivec4(0, 1, 2, 3);
vv_offset = v_offset + 4;
}
}
else if (p.dims == 3)
{
// order_type
// 0 = w h c
// 1 = h w c
// 2 = w c h
// 3 = c w h
// 4 = h c w
// 5 = c h w

if (order_type == 0)
{
v_offset = ivec4((gz * 8) * p.outcstep + gy * p.outw + gx) + ivec4(0, 1, 2, 3) * p.outcstep;
vv_offset = v_offset + 4 * p.outcstep;
}
if (order_type == 1)
{
v_offset = ivec4((gz * 8) * p.outcstep + gx * p.outw + gy) + ivec4(0, 1, 2, 3) * p.outcstep;
vv_offset = v_offset + 4 * p.outcstep;
}
if (order_type == 2)
{
v_offset = ivec4(gy * p.outcstep + (gz * 8) * p.outw + gx) + ivec4(0, 1, 2, 3) * p.outw;
vv_offset = v_offset + 4 * p.outw;
}
if (order_type == 3)
{
v_offset = ivec4(gy * p.outcstep + gx * p.outw + gz * 8) + ivec4(0, 1, 2, 3);
vv_offset = v_offset + 4;
}
if (order_type == 4)
{
v_offset = ivec4(gx * p.outcstep + (gz * 8) * p.outw + gy) + ivec4(0, 1, 2, 3) * p.outw;
vv_offset = v_offset + 4 * p.outw;
}
if (order_type == 5)
{
v_offset = ivec4(gx * p.outcstep + gy * p.outw + gz * 8) + ivec4(0, 1, 2, 3);
vv_offset = v_offset + 4;
}
}

int gi = gz * p.cstep + gy * p.w + gx;

buffer_cp8to1(top_blob_data, v_offset, vv_offset, bottom_blob_data, gi);
}

Loading…
Cancel
Save