1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-31 00:03:03 +04:00

Merge pull request #18068 from lionkunonly:gsoc_2020_simd

[GSoC] OpenCV.js: WASM SIMD optimization 2.0

* gsoc_2020_simd Add perf test for filter2d

* add perf test for kernel scharr and kernel gaussianBlur

* add perf test for blur, medianBlur, erode, dilate

* fix the errors for the opencv PR robot

fix the trailing whitespace.

* add perf tests for kernel remap, warpAffine, warpPersepective, pyrDown

* fix a bug in  modules/js/perf/perf_imgproc/perf_remap.js

* add function smoothBorder in helpfun.js and remove replicated function in perf test of warpAffine and warpPrespective

* fix the trailing white space issues

* add OpenCV.js loader

* Implement the Loader with help of WebAssembly Feature Detection, remove trailing whitespaces

* modify the explantion for loader in js_setup.markdown and fix bug in loader.js
This commit is contained in:
Kun Liang
2020-10-19 04:30:36 +08:00
committed by GitHub
parent bd19f991a5
commit c82417697a
36 changed files with 3513 additions and 847 deletions
@@ -207,13 +207,7 @@ struct v_uint64x2
uint64 get0() const
{
#ifdef __wasm_unimplemented_simd128__
return (uint64)wasm_i64x2_extract_lane(val, 0);
#else
uint64 des[2];
wasm_v128_store(des, val);
return des[0];
#endif
}
v128_t val;
@@ -235,13 +229,7 @@ struct v_int64x2
int64 get0() const
{
#ifdef __wasm_unimplemented_simd128__
return wasm_i64x2_extract_lane(val, 0);
#else
int64 des[2];
wasm_v128_store(des, val);
return des[0];
#endif
}
v128_t val;
@@ -263,13 +251,7 @@ struct v_float64x2
double get0() const
{
#ifdef __wasm_unimplemented_simd128__
return wasm_f64x2_extract_lane(val, 0);
#else
double des[2];
wasm_v128_store(des, val);
return des[0];
#endif
}
v128_t val;
@@ -1797,22 +1779,9 @@ OPENCV_HAL_IMPL_WASM_INITVEC(v_int16x8, short, s16, i16x8, short)
OPENCV_HAL_IMPL_WASM_INITVEC(v_uint32x4, unsigned, u32, i32x4, int)
OPENCV_HAL_IMPL_WASM_INITVEC(v_int32x4, int, s32, i32x4, int)
OPENCV_HAL_IMPL_WASM_INITVEC(v_float32x4, float, f32, f32x4, float)
#ifdef __wasm_unimplemented_simd128__
OPENCV_HAL_IMPL_WASM_INITVEC(v_uint64x2, uint64, u64, i64x2, int64)
OPENCV_HAL_IMPL_WASM_INITVEC(v_int64x2, int64, s64, i64x2, int64)
OPENCV_HAL_IMPL_WASM_INITVEC(v_float64x2, double, f64, f64x2, double)
#else
#define OPENCV_HAL_IMPL_FALLBACK_INITVEC(_Tpvec, _Tp, suffix, _Tps) \
inline _Tpvec v_setzero_##suffix() { return _Tpvec((_Tps)0, (_Tps)0); } \
inline _Tpvec v_setall_##suffix(_Tp v) { return _Tpvec((_Tps)v, (_Tps)v); } \
template<typename _Tpvec0> inline _Tpvec v_reinterpret_as_##suffix(const _Tpvec0& a) \
{ return _Tpvec(a.val); }
OPENCV_HAL_IMPL_FALLBACK_INITVEC(v_uint64x2, uint64, u64, int64)
OPENCV_HAL_IMPL_FALLBACK_INITVEC(v_int64x2, int64, s64, int64)
OPENCV_HAL_IMPL_FALLBACK_INITVEC(v_float64x2, double, f64, double)
#endif
//////////////// PACK ///////////////
inline v_uint8x16 v_pack(const v_uint16x8& a, const v_uint16x8& b)
@@ -1931,28 +1900,18 @@ inline v_int16x8 v_rshr_pack(const v_int32x4& a, const v_int32x4& b)
template<int n>
inline v_uint32x4 v_rshr_pack(const v_uint64x2& a, const v_uint64x2& b)
{
#ifdef __wasm_unimplemented_simd128__
v128_t delta = wasm_i64x2_splat(((int64)1 << (n-1)));
v128_t a1 = wasm_u64x2_shr(wasm_i64x2_add(a.val, delta), n);
v128_t b1 = wasm_u64x2_shr(wasm_i64x2_add(b.val, delta), n);
return v_uint32x4(wasm_v8x16_shuffle(a1, b1, 0,1,2,3,8,9,10,11,16,17,18,19,24,25,26,27));
#else
fallback::v_uint64x2 a_(a), b_(b);
return fallback::v_rshr_pack<n>(a_, b_);
#endif
}
template<int n>
inline v_int32x4 v_rshr_pack(const v_int64x2& a, const v_int64x2& b)
{
#ifdef __wasm_unimplemented_simd128__
v128_t delta = wasm_i64x2_splat(((int64)1 << (n-1)));
v128_t a1 = wasm_i64x2_shr(wasm_i64x2_add(a.val, delta), n);
v128_t b1 = wasm_i64x2_shr(wasm_i64x2_add(b.val, delta), n);
return v_int32x4(wasm_v8x16_shuffle(a1, b1, 0,1,2,3,8,9,10,11,16,17,18,19,24,25,26,27));
#else
fallback::v_int64x2 a_(a), b_(b);
return fallback::v_rshr_pack<n>(a_, b_);
#endif
}
template<int n>
inline v_uint8x16 v_rshr_pack_u(const v_int16x8& a, const v_int16x8& b)
@@ -2139,7 +2098,6 @@ inline void v_rshr_pack_store(short* ptr, const v_int32x4& a)
template<int n>
inline void v_rshr_pack_store(unsigned* ptr, const v_uint64x2& a)
{
#ifdef __wasm_unimplemented_simd128__
v128_t delta = wasm_i64x2_splat(((int64)1 << (n-1)));
v128_t a1 = wasm_u64x2_shr(wasm_i64x2_add(a.val, delta), n);
v128_t r = wasm_v8x16_shuffle(a1, a1, 0,1,2,3,8,9,10,11,0,1,2,3,8,9,10,11);
@@ -2148,15 +2106,10 @@ inline void v_rshr_pack_store(unsigned* ptr, const v_uint64x2& a)
for (int i=0; i<2; ++i) {
ptr[i] = t_ptr[i];
}
#else
fallback::v_uint64x2 _a(a);
fallback::v_rshr_pack_store<n>(ptr, _a);
#endif
}
template<int n>
inline void v_rshr_pack_store(int* ptr, const v_int64x2& a)
{
#ifdef __wasm_unimplemented_simd128__
v128_t delta = wasm_i64x2_splat(((int64)1 << (n-1)));
v128_t a1 = wasm_i64x2_shr(wasm_i64x2_add(a.val, delta), n);
v128_t r = wasm_v8x16_shuffle(a1, a1, 0,1,2,3,8,9,10,11,0,1,2,3,8,9,10,11);
@@ -2165,10 +2118,6 @@ inline void v_rshr_pack_store(int* ptr, const v_int64x2& a)
for (int i=0; i<2; ++i) {
ptr[i] = t_ptr[i];
}
#else
fallback::v_int64x2 _a(a);
fallback::v_rshr_pack_store<n>(ptr, _a);
#endif
}
template<int n>
inline void v_rshr_pack_u_store(uchar* ptr, const v_int16x8& a)
@@ -2228,7 +2177,6 @@ inline v_uint8x16 v_pack_b(const v_uint64x2& a, const v_uint64x2& b, const v_uin
const v_uint64x2& d, const v_uint64x2& e, const v_uint64x2& f,
const v_uint64x2& g, const v_uint64x2& h)
{
#ifdef __wasm_unimplemented_simd128__
v128_t maxval = wasm_i32x4_splat(255);
v128_t a1 = wasm_v128_bitselect(maxval, a.val, ((__u64x2)(a.val) > (__u64x2)maxval));
v128_t b1 = wasm_v128_bitselect(maxval, b.val, ((__u64x2)(b.val) > (__u64x2)maxval));
@@ -2245,10 +2193,6 @@ inline v_uint8x16 v_pack_b(const v_uint64x2& a, const v_uint64x2& b, const v_uin
v128_t abcd = wasm_v8x16_shuffle(ab, cd, 0,1,2,3,16,17,18,19,0,1,2,3,16,17,18,19);
v128_t efgh = wasm_v8x16_shuffle(ef, gh, 0,1,2,3,16,17,18,19,0,1,2,3,16,17,18,19);
return v_uint8x16(wasm_v8x16_shuffle(abcd, efgh, 0,1,2,3,4,5,6,7,16,17,18,19,20,21,22,23));
#else
fallback::v_uint64x2 a_(a), b_(b), c_(c), d_(d), e_(e), f_(f), g_(g), h_(h);
return fallback::v_pack_b(a_, b_, c_, d_, e_, f_, g_, h_);
#endif
}
inline v_float32x4 v_matmul(const v_float32x4& v, const v_float32x4& m0,
@@ -2310,8 +2254,6 @@ OPENCV_HAL_IMPL_WASM_BIN_OP(+, v_float32x4, wasm_f32x4_add)
OPENCV_HAL_IMPL_WASM_BIN_OP(-, v_float32x4, wasm_f32x4_sub)
OPENCV_HAL_IMPL_WASM_BIN_OP(*, v_float32x4, wasm_f32x4_mul)
OPENCV_HAL_IMPL_WASM_BIN_OP(/, v_float32x4, wasm_f32x4_div)
#ifdef __wasm_unimplemented_simd128__
OPENCV_HAL_IMPL_WASM_BIN_OP(+, v_uint64x2, wasm_i64x2_add)
OPENCV_HAL_IMPL_WASM_BIN_OP(-, v_uint64x2, wasm_i64x2_sub)
OPENCV_HAL_IMPL_WASM_BIN_OP(+, v_int64x2, wasm_i64x2_add)
@@ -2320,30 +2262,6 @@ OPENCV_HAL_IMPL_WASM_BIN_OP(+, v_float64x2, wasm_f64x2_add)
OPENCV_HAL_IMPL_WASM_BIN_OP(-, v_float64x2, wasm_f64x2_sub)
OPENCV_HAL_IMPL_WASM_BIN_OP(*, v_float64x2, wasm_f64x2_mul)
OPENCV_HAL_IMPL_WASM_BIN_OP(/, v_float64x2, wasm_f64x2_div)
#else
#define OPENCV_HAL_IMPL_FALLBACK_BIN_OP(bin_op, _Tpvec) \
inline _Tpvec operator bin_op (const _Tpvec& a, const _Tpvec& b) \
{ \
fallback::_Tpvec a_(a), b_(b); \
return _Tpvec((a_) bin_op (b_)); \
} \
inline _Tpvec& operator bin_op##= (_Tpvec& a, const _Tpvec& b) \
{ \
fallback::_Tpvec a_(a), b_(b); \
a_ bin_op##= b_; \
a = _Tpvec(a_); \
return a; \
}
OPENCV_HAL_IMPL_FALLBACK_BIN_OP(+, v_uint64x2)
OPENCV_HAL_IMPL_FALLBACK_BIN_OP(-, v_uint64x2)
OPENCV_HAL_IMPL_FALLBACK_BIN_OP(+, v_int64x2)
OPENCV_HAL_IMPL_FALLBACK_BIN_OP(-, v_int64x2)
OPENCV_HAL_IMPL_FALLBACK_BIN_OP(+, v_float64x2)
OPENCV_HAL_IMPL_FALLBACK_BIN_OP(-, v_float64x2)
OPENCV_HAL_IMPL_FALLBACK_BIN_OP(*, v_float64x2)
OPENCV_HAL_IMPL_FALLBACK_BIN_OP(/, v_float64x2)
#endif
// saturating multiply 8-bit, 16-bit
#define OPENCV_HAL_IMPL_WASM_MUL_SAT(_Tpvec, _Tpwvec) \
@@ -2405,19 +2323,11 @@ inline void v_mul_expand(const v_uint16x8& a, const v_uint16x8& b,
inline void v_mul_expand(const v_uint32x4& a, const v_uint32x4& b,
v_uint64x2& c, v_uint64x2& d)
{
#ifdef __wasm_unimplemented_simd128__
v_uint64x2 a0, a1, b0, b1;
v_expand(a, a0, a1);
v_expand(b, b0, b1);
c.val = ((__u64x2)(a0.val) * (__u64x2)(b0.val));
d.val = ((__u64x2)(a1.val) * (__u64x2)(b1.val));
#else
fallback::v_uint32x4 a_(a), b_(b);
fallback::v_uint64x2 c_, d_;
fallback::v_mul_expand(a_, b_, c_, d_);
c = v_uint64x2(c_);
d = v_uint64x2(d_);
#endif
}
inline v_int16x8 v_mul_hi(const v_int16x8& a, const v_int16x8& b)
@@ -2457,7 +2367,6 @@ inline v_int32x4 v_dotprod(const v_int16x8& a, const v_int16x8& b, const v_int32
inline v_int64x2 v_dotprod(const v_int32x4& a, const v_int32x4& b)
{
#ifdef __wasm_unimplemented_simd128__
v128_t a0 = wasm_i64x2_shr(wasm_i64x2_shl(a.val, 32), 32);
v128_t a1 = wasm_i64x2_shr(a.val, 32);
v128_t b0 = wasm_i64x2_shr(wasm_i64x2_shl(b.val, 32), 32);
@@ -2465,22 +2374,10 @@ inline v_int64x2 v_dotprod(const v_int32x4& a, const v_int32x4& b)
v128_t c = (v128_t)((__i64x2)a0 * (__i64x2)b0);
v128_t d = (v128_t)((__i64x2)a1 * (__i64x2)b1);
return v_int64x2(wasm_i64x2_add(c, d));
#else
fallback::v_int32x4 a_(a);
fallback::v_int32x4 b_(b);
return fallback::v_dotprod(a_, b_);
#endif
}
inline v_int64x2 v_dotprod(const v_int32x4& a, const v_int32x4& b, const v_int64x2& c)
{
#ifdef __wasm_unimplemented_simd128__
return v_dotprod(a, b) + c;
#else
fallback::v_int32x4 a_(a);
fallback::v_int32x4 b_(b);
fallback::v_int64x2 c_(c);
return fallback::v_dotprod(a_, b_, c_);
#endif
}
// 8 >> 32
@@ -2515,32 +2412,32 @@ inline v_int32x4 v_dotprod_expand(const v_int8x16& a, const v_int8x16& b, const
// 16 >> 64
inline v_uint64x2 v_dotprod_expand(const v_uint16x8& a, const v_uint16x8& b)
{
fallback::v_uint16x8 a_(a);
fallback::v_uint16x8 b_(b);
return fallback::v_dotprod_expand(a_, b_);
v128_t a0 = wasm_u32x4_shr(wasm_i32x4_shl(a.val, 16), 16);
v128_t a1 = wasm_u32x4_shr(a.val, 16);
v128_t b0 = wasm_u32x4_shr(wasm_i32x4_shl(b.val, 16), 16);
v128_t b1 = wasm_u32x4_shr(b.val, 16);
return v_uint64x2((
v_dotprod(v_int32x4(a0), v_int32x4(b0)) +
v_dotprod(v_int32x4(a1), v_int32x4(b1))).val
);
}
inline v_uint64x2 v_dotprod_expand(const v_uint16x8& a, const v_uint16x8& b, const v_uint64x2& c)
{
fallback::v_uint16x8 a_(a);
fallback::v_uint16x8 b_(b);
fallback::v_uint64x2 c_(c);
return fallback::v_dotprod_expand(a_, b_, c_);
}
{ return v_dotprod_expand(a, b) + c; }
inline v_int64x2 v_dotprod_expand(const v_int16x8& a, const v_int16x8& b)
{
fallback::v_int16x8 a_(a);
fallback::v_int16x8 b_(b);
return fallback::v_dotprod_expand(a_, b_);
v128_t a0 = wasm_i32x4_shr(wasm_i32x4_shl(a.val, 16), 16);
v128_t a1 = wasm_i32x4_shr(a.val, 16);
v128_t b0 = wasm_i32x4_shr(wasm_i32x4_shl(b.val, 16), 16);
v128_t b1 = wasm_i32x4_shr(b.val, 16);
return v_int64x2((
v_dotprod(v_int32x4(a0), v_int32x4(b0)) +
v_dotprod(v_int32x4(a1), v_int32x4(b1)))
);
}
inline v_int64x2 v_dotprod_expand(const v_int16x8& a, const v_int16x8& b, const v_int64x2& c)
{
fallback::v_int16x8 a_(a);
fallback::v_int16x8 b_(b);
fallback::v_int64x2 c_(c);
return fallback::v_dotprod_expand(a_, b_, c_);
}
{ return v_dotprod_expand(a, b) + c; }
// 32 >> 64f
inline v_float64x2 v_dotprod_expand(const v_int32x4& a, const v_int32x4& b)
@@ -2610,44 +2507,24 @@ OPENCV_HAL_IMPL_WASM_LOGIC_OP(v_float64x2)
inline v_float32x4 v_sqrt(const v_float32x4& x)
{
#ifdef __wasm_unimplemented_simd128__
return v_float32x4(wasm_f32x4_sqrt(x.val));
#else
fallback::v_float32x4 x_(x);
return fallback::v_sqrt(x_);
#endif
}
inline v_float32x4 v_invsqrt(const v_float32x4& x)
{
#ifdef __wasm_unimplemented_simd128__
const v128_t _1_0 = wasm_f32x4_splat(1.0);
return v_float32x4(wasm_f32x4_div(_1_0, wasm_f32x4_sqrt(x.val)));
#else
fallback::v_float32x4 x_(x);
return fallback::v_invsqrt(x_);
#endif
}
inline v_float64x2 v_sqrt(const v_float64x2& x)
{
#ifdef __wasm_unimplemented_simd128__
return v_float64x2(wasm_f64x2_sqrt(x.val));
#else
fallback::v_float64x2 x_(x);
return fallback::v_sqrt(x_);
#endif
}
inline v_float64x2 v_invsqrt(const v_float64x2& x)
{
#ifdef __wasm_unimplemented_simd128__
const v128_t _1_0 = wasm_f64x2_splat(1.0);
return v_float64x2(wasm_f64x2_div(_1_0, wasm_f64x2_sqrt(x.val)));
#else
fallback::v_float64x2 x_(x);
return fallback::v_invsqrt(x_);
#endif
}
#define OPENCV_HAL_IMPL_WASM_ABS_INT_FUNC(_Tpuvec, _Tpsvec, suffix, zsuffix, shiftWidth) \
@@ -2666,12 +2543,7 @@ inline v_float32x4 v_abs(const v_float32x4& x)
{ return v_float32x4(wasm_f32x4_abs(x.val)); }
inline v_float64x2 v_abs(const v_float64x2& x)
{
#ifdef __wasm_unimplemented_simd128__
return v_float64x2(wasm_f64x2_abs(x.val));
#else
fallback::v_float64x2 x_(x);
return fallback::v_abs(x_);
#endif
}
// TODO: exp, log, sin, cos
@@ -2684,21 +2556,8 @@ inline _Tpvec func(const _Tpvec& a, const _Tpvec& b) \
OPENCV_HAL_IMPL_WASM_BIN_FUNC(v_float32x4, v_min, wasm_f32x4_min)
OPENCV_HAL_IMPL_WASM_BIN_FUNC(v_float32x4, v_max, wasm_f32x4_max)
#ifdef __wasm_unimplemented_simd128__
OPENCV_HAL_IMPL_WASM_BIN_FUNC(v_float64x2, v_min, wasm_f64x2_min)
OPENCV_HAL_IMPL_WASM_BIN_FUNC(v_float64x2, v_max, wasm_f64x2_max)
#else
#define OPENCV_HAL_IMPL_WASM_MINMAX_64f_FUNC(func) \
inline v_float64x2 func(const v_float64x2& a, const v_float64x2& b) \
{ \
fallback::v_float64x2 a_(a), b_(b); \
return fallback::func(a_, b_); \
}
OPENCV_HAL_IMPL_WASM_MINMAX_64f_FUNC(v_min)
OPENCV_HAL_IMPL_WASM_MINMAX_64f_FUNC(v_max)
#endif
#define OPENCV_HAL_IMPL_WASM_MINMAX_S_INIT_FUNC(_Tpvec, suffix) \
inline _Tpvec v_min(const _Tpvec& a, const _Tpvec& b) \
@@ -2753,24 +2612,7 @@ OPENCV_HAL_IMPL_WASM_INIT_CMP_OP(v_int16x8, i16x8, i16x8)
OPENCV_HAL_IMPL_WASM_INIT_CMP_OP(v_uint32x4, u32x4, i32x4)
OPENCV_HAL_IMPL_WASM_INIT_CMP_OP(v_int32x4, i32x4, i32x4)
OPENCV_HAL_IMPL_WASM_INIT_CMP_OP(v_float32x4, f32x4, f32x4)
#ifdef __wasm_unimplemented_simd128__
OPENCV_HAL_IMPL_WASM_INIT_CMP_OP(v_float64x2, f64x2, f64x2)
#else
#define OPENCV_HAL_IMPL_INIT_FALLBACK_CMP_OP(_Tpvec, bin_op) \
inline _Tpvec operator bin_op (const _Tpvec& a, const _Tpvec& b) \
{ \
fallback::_Tpvec a_(a), b_(b); \
return _Tpvec((a_) bin_op (b_));\
} \
OPENCV_HAL_IMPL_INIT_FALLBACK_CMP_OP(v_float64x2, ==)
OPENCV_HAL_IMPL_INIT_FALLBACK_CMP_OP(v_float64x2, !=)
OPENCV_HAL_IMPL_INIT_FALLBACK_CMP_OP(v_float64x2, <)
OPENCV_HAL_IMPL_INIT_FALLBACK_CMP_OP(v_float64x2, >)
OPENCV_HAL_IMPL_INIT_FALLBACK_CMP_OP(v_float64x2, <=)
OPENCV_HAL_IMPL_INIT_FALLBACK_CMP_OP(v_float64x2, >=)
#endif
#define OPENCV_HAL_IMPL_WASM_64BIT_CMP_OP(_Tpvec, cast) \
inline _Tpvec operator == (const _Tpvec& a, const _Tpvec& b) \
@@ -2789,14 +2631,9 @@ inline v_float32x4 v_not_nan(const v_float32x4& a)
}
inline v_float64x2 v_not_nan(const v_float64x2& a)
{
#ifdef __wasm_unimplemented_simd128__
v128_t z = wasm_i64x2_splat(0x7fffffffffffffff);
v128_t t = wasm_i64x2_splat(0x7ff0000000000000);
return v_float64x2((__u64x2)(wasm_v128_and(a.val, z)) < (__u64x2)t);
#else
fallback::v_float64x2 a_(a);
return fallback::v_not_nan(a_);
#endif
}
OPENCV_HAL_IMPL_WASM_BIN_FUNC(v_uint8x16, v_add_wrap, wasm_i8x16_add)
@@ -2877,32 +2714,30 @@ inline v_float32x4 v_absdiff(const v_float32x4& a, const v_float32x4& b)
}
inline v_float64x2 v_absdiff(const v_float64x2& a, const v_float64x2& b)
{
#ifdef __wasm_unimplemented_simd128__
v128_t absmask_vec = wasm_u64x2_shr(wasm_i32x4_splat(-1), 1);
return v_float64x2(wasm_v128_and(wasm_f64x2_sub(a.val, b.val), absmask_vec));
#else
fallback::v_float64x2 a_(a), b_(b);
return fallback::v_absdiff(a_, b_);
#endif
}
#define OPENCV_HAL_IMPL_WASM_MISC_FLT_OP(_Tpvec) \
#define OPENCV_HAL_IMPL_WASM_MISC_FLT_OP(_Tpvec, suffix) \
inline _Tpvec v_magnitude(const _Tpvec& a, const _Tpvec& b) \
{ \
fallback::_Tpvec a_(a), b_(b); \
return fallback::v_magnitude(a_, b_); \
v128_t a_Square = wasm_##suffix##_mul(a.val, a.val); \
v128_t b_Square = wasm_##suffix##_mul(b.val, b.val); \
return _Tpvec(wasm_##suffix##_sqrt(wasm_##suffix##_add(a_Square, b_Square))); \
} \
inline _Tpvec v_sqr_magnitude(const _Tpvec& a, const _Tpvec& b) \
{ \
return v_fma(a, a, b*b); \
v128_t a_Square = wasm_##suffix##_mul(a.val, a.val); \
v128_t b_Square = wasm_##suffix##_mul(b.val, b.val); \
return _Tpvec(wasm_##suffix##_add(a_Square, b_Square)); \
} \
inline _Tpvec v_muladd(const _Tpvec& a, const _Tpvec& b, const _Tpvec& c) \
{ \
return v_fma(a, b, c); \
return _Tpvec(wasm_##suffix##_add(wasm_##suffix##_mul(a.val, b.val), c.val)); \
}
OPENCV_HAL_IMPL_WASM_MISC_FLT_OP(v_float32x4)
OPENCV_HAL_IMPL_WASM_MISC_FLT_OP(v_float64x2)
OPENCV_HAL_IMPL_WASM_MISC_FLT_OP(v_float32x4, f32x4)
OPENCV_HAL_IMPL_WASM_MISC_FLT_OP(v_float64x2, f64x2)
#define OPENCV_HAL_IMPL_WASM_SHIFT_OP(_Tpuvec, _Tpsvec, suffix, ssuffix) \
inline _Tpuvec operator << (const _Tpuvec& a, int imm) \
@@ -2945,37 +2780,7 @@ inline _Tpsvec v_shr(const _Tpsvec& a) \
OPENCV_HAL_IMPL_WASM_SHIFT_OP(v_uint8x16, v_int8x16, i8x16, u8x16)
OPENCV_HAL_IMPL_WASM_SHIFT_OP(v_uint16x8, v_int16x8, i16x8, u16x8)
OPENCV_HAL_IMPL_WASM_SHIFT_OP(v_uint32x4, v_int32x4, i32x4, u32x4)
#ifdef __wasm_unimplemented_simd128__
OPENCV_HAL_IMPL_WASM_SHIFT_OP(v_uint64x2, v_int64x2, i64x2, u64x2)
#else
#define OPENCV_HAL_IMPL_FALLBACK_SHIFT_OP(_Tpvec) \
inline _Tpvec operator << (const _Tpvec& a, int imm) \
{ \
fallback::_Tpvec a_(a); \
return a_ << imm; \
} \
inline _Tpvec operator >> (const _Tpvec& a, int imm) \
{ \
fallback::_Tpvec a_(a); \
return a_ >> imm; \
} \
template<int imm> \
inline _Tpvec v_shl(const _Tpvec& a) \
{ \
fallback::_Tpvec a_(a); \
return fallback::v_shl<imm>(a_); \
} \
template<int imm> \
inline _Tpvec v_shr(const _Tpvec& a) \
{ \
fallback::_Tpvec a_(a); \
return fallback::v_shr<imm>(a_); \
} \
OPENCV_HAL_IMPL_FALLBACK_SHIFT_OP(v_uint64x2)
OPENCV_HAL_IMPL_FALLBACK_SHIFT_OP(v_int64x2)
#endif
namespace hal_wasm_internal
{
@@ -3180,9 +2985,18 @@ OPENCV_HAL_IMPL_FALLBACK_REDUCE_OP_SUM(v_uint8x16, unsigned)
OPENCV_HAL_IMPL_FALLBACK_REDUCE_OP_SUM(v_int8x16, int)
OPENCV_HAL_IMPL_FALLBACK_REDUCE_OP_SUM(v_uint16x8, unsigned)
OPENCV_HAL_IMPL_FALLBACK_REDUCE_OP_SUM(v_int16x8, int)
OPENCV_HAL_IMPL_FALLBACK_REDUCE_OP_SUM(v_uint64x2, uint64)
OPENCV_HAL_IMPL_FALLBACK_REDUCE_OP_SUM(v_int64x2, int64)
OPENCV_HAL_IMPL_FALLBACK_REDUCE_OP_SUM(v_float64x2, double)
#define OPENCV_HAL_IMPL_WASM_REDUCE_OP_2_SUM(_Tpvec, scalartype, regtype, suffix, esuffix) \
inline scalartype v_reduce_sum(const _Tpvec& a) \
{ \
regtype val = a.val; \
val = wasm_##suffix##_add(val, wasm_v8x16_shuffle(val, val, 8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7)); \
return (scalartype)wasm_##esuffix##_extract_lane(val, 0); \
}
OPENCV_HAL_IMPL_WASM_REDUCE_OP_2_SUM(v_uint64x2, uint64, v128_t, i64x2, i64x2)
OPENCV_HAL_IMPL_WASM_REDUCE_OP_2_SUM(v_int64x2, int64, v128_t, i64x2, i64x2)
OPENCV_HAL_IMPL_WASM_REDUCE_OP_2_SUM(v_float64x2, double, v128_t, f64x2,f64x2)
inline v_float32x4 v_reduce_sum4(const v_float32x4& a, const v_float32x4& b,
const v_float32x4& c, const v_float32x4& d)
@@ -3318,30 +3132,27 @@ OPENCV_HAL_IMPL_WASM_CHECK_SIGNS(v_int16x8, i16x8, short)
OPENCV_HAL_IMPL_WASM_CHECK_SIGNS(v_uint32x4, i32x4, int)
OPENCV_HAL_IMPL_WASM_CHECK_SIGNS(v_int32x4, i32x4, int)
OPENCV_HAL_IMPL_WASM_CHECK_SIGNS(v_float32x4, i32x4, float)
OPENCV_HAL_IMPL_WASM_CHECK_SIGNS(v_float64x2, f64x2, double)
#define OPENCV_HAL_IMPL_WASM_CHECK_ALL_ANY(_Tpvec, suffix, esuffix) \
inline bool v_check_all(const _Tpvec& a) \
{ \
v128_t masked = v_reinterpret_as_##esuffix(a).val; \
masked = wasm_i32x4_replace_lane(masked, 0, 0xffffffff); \
masked = wasm_i32x4_replace_lane(masked, 2, 0xffffffff); \
return wasm_i8x16_all_true(wasm_##suffix##_lt(masked, wasm_##suffix##_splat(0))); \
} \
inline bool v_check_any(const _Tpvec& a) \
{ \
v128_t masked = v_reinterpret_as_##esuffix(a).val; \
masked = wasm_i32x4_replace_lane(masked, 0, 0x0); \
masked = wasm_i32x4_replace_lane(masked, 2, 0x0); \
return wasm_i8x16_any_true(wasm_##suffix##_lt(masked, wasm_##suffix##_splat(0))); \
} \
OPENCV_HAL_IMPL_WASM_CHECK_ALL_ANY(v_int64x2, i32x4, s32)
OPENCV_HAL_IMPL_WASM_CHECK_ALL_ANY(v_uint64x2, i32x4, u32)
inline int v_signmask(const v_float64x2& a)
{
fallback::v_float64x2 a_(a);
return fallback::v_signmask(a_);
}
inline bool v_check_all(const v_float64x2& a)
{
#ifdef __wasm_unimplemented_simd128__
return wasm_i8x16_all_true((__i64x2)(a.val) < (__i64x2)(wasm_i64x2_splat(0)));
#else
fallback::v_float64x2 a_(a);
return fallback::v_check_all(a_);
#endif
}
inline bool v_check_any(const v_float64x2& a)
{
#ifdef __wasm_unimplemented_simd128__
return wasm_i8x16_any_true((__i64x2)(a.val) < (__i64x2)(wasm_i64x2_splat(0)));;
#else
fallback::v_float64x2 a_(a);
return fallback::v_check_any(a_);
#endif
}
inline int v_scan_forward(const v_int8x16& a) { return trailingZeros32(v_signmask(v_reinterpret_as_s8(a))); }
inline int v_scan_forward(const v_uint8x16& a) { return trailingZeros32(v_signmask(v_reinterpret_as_s8(a))); }
@@ -3366,8 +3177,8 @@ OPENCV_HAL_IMPL_WASM_SELECT(v_uint16x8)
OPENCV_HAL_IMPL_WASM_SELECT(v_int16x8)
OPENCV_HAL_IMPL_WASM_SELECT(v_uint32x4)
OPENCV_HAL_IMPL_WASM_SELECT(v_int32x4)
// OPENCV_HAL_IMPL_WASM_SELECT(v_uint64x2)
// OPENCV_HAL_IMPL_WASM_SELECT(v_int64x2)
OPENCV_HAL_IMPL_WASM_SELECT(v_uint64x2)
OPENCV_HAL_IMPL_WASM_SELECT(v_int64x2)
OPENCV_HAL_IMPL_WASM_SELECT(v_float32x4)
OPENCV_HAL_IMPL_WASM_SELECT(v_float64x2)