simd_t.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. /*
  2. * Copyright 2010-2018 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
  4. */
  5. #ifndef BX_SIMD_T_H_HEADER_GUARD
  6. #define BX_SIMD_T_H_HEADER_GUARD
  7. #include "bx.h"
  8. #define BX_SIMD_FORCE_INLINE BX_FORCE_INLINE
  9. #define BX_SIMD_INLINE inline
  10. #define BX_SIMD_AVX 0
  11. #define BX_SIMD_LANGEXT 0
  12. #define BX_SIMD_NEON 0
  13. #define BX_SIMD_SSE 0
  14. #define BX_CONFIG_SUPPORTS_SIMD 0
  15. #if defined(__AVX__) || defined(__AVX2__)
  16. # include <immintrin.h>
  17. # undef BX_SIMD_AVX
  18. # define BX_SIMD_AVX 1
  19. #endif //
  20. #if defined(__SSE2__) || (BX_COMPILER_MSVC && (BX_ARCH_64BIT || _M_IX86_FP >= 2) )
  21. # include <emmintrin.h> // __m128i
  22. # if defined(__SSE4_1__)
  23. # include <smmintrin.h>
  24. # endif // defined(__SSE4_1__)
  25. # include <xmmintrin.h> // __m128
  26. # undef BX_SIMD_SSE
  27. # define BX_SIMD_SSE 1
  28. #elif defined(__ARM_NEON__) && !BX_COMPILER_CLANG
  29. # include <arm_neon.h>
  30. # undef BX_SIMD_NEON
  31. # define BX_SIMD_NEON 1
  32. #elif BX_COMPILER_CLANG \
  33. && !BX_PLATFORM_EMSCRIPTEN \
  34. && !BX_PLATFORM_IOS \
  35. && BX_CLANG_HAS_EXTENSION(attribute_ext_vector_type)
  36. # undef BX_SIMD_LANGEXT
  37. # define BX_SIMD_LANGEXT 1
  38. #endif //
  39. namespace bx
  40. {
  41. #define ELEMx 0
  42. #define ELEMy 1
  43. #define ELEMz 2
  44. #define ELEMw 3
  45. #define BX_SIMD128_IMPLEMENT_SWIZZLE(_x, _y, _z, _w) \
  46. template<typename Ty> \
  47. Ty simd_swiz_##_x##_y##_z##_w(Ty _a);
  48. #include "inline/simd128_swizzle.inl"
  49. #undef BX_SIMD128_IMPLEMENT_SWIZZLE
  50. #undef ELEMw
  51. #undef ELEMz
  52. #undef ELEMy
  53. #undef ELEMx
  54. #define BX_SIMD128_IMPLEMENT_TEST(_xyzw) \
  55. template<typename Ty> \
  56. BX_SIMD_FORCE_INLINE bool simd_test_any_##_xyzw(Ty _test); \
  57. \
  58. template<typename Ty> \
  59. BX_SIMD_FORCE_INLINE bool simd_test_all_##_xyzw(Ty _test)
  60. BX_SIMD128_IMPLEMENT_TEST(x );
  61. BX_SIMD128_IMPLEMENT_TEST(y );
  62. BX_SIMD128_IMPLEMENT_TEST(xy );
  63. BX_SIMD128_IMPLEMENT_TEST(z );
  64. BX_SIMD128_IMPLEMENT_TEST(xz );
  65. BX_SIMD128_IMPLEMENT_TEST(yz );
  66. BX_SIMD128_IMPLEMENT_TEST(xyz );
  67. BX_SIMD128_IMPLEMENT_TEST(w );
  68. BX_SIMD128_IMPLEMENT_TEST(xw );
  69. BX_SIMD128_IMPLEMENT_TEST(yw );
  70. BX_SIMD128_IMPLEMENT_TEST(xyw );
  71. BX_SIMD128_IMPLEMENT_TEST(zw );
  72. BX_SIMD128_IMPLEMENT_TEST(xzw );
  73. BX_SIMD128_IMPLEMENT_TEST(yzw );
  74. BX_SIMD128_IMPLEMENT_TEST(xyzw);
  75. #undef BX_SIMD128_IMPLEMENT_TEST
  76. template<typename Ty>
  77. Ty simd_shuf_xyAB(Ty _a, Ty _b);
  78. template<typename Ty>
  79. Ty simd_shuf_ABxy(Ty _a, Ty _b);
  80. template<typename Ty>
  81. Ty simd_shuf_CDzw(Ty _a, Ty _b);
  82. template<typename Ty>
  83. Ty simd_shuf_zwCD(Ty _a, Ty _b);
  84. template<typename Ty>
  85. Ty simd_shuf_xAyB(Ty _a, Ty _b);
  86. template<typename Ty>
  87. Ty simd_shuf_AxBy(Ty _a, Ty _b);
  88. template<typename Ty>
  89. Ty simd_shuf_zCwD(Ty _a, Ty _b);
  90. template<typename Ty>
  91. Ty simd_shuf_CzDw(Ty _a, Ty _b);
  92. template<typename Ty>
  93. float simd_x(Ty _a);
  94. template<typename Ty>
  95. float simd_y(Ty _a);
  96. template<typename Ty>
  97. float simd_z(Ty _a);
  98. template<typename Ty>
  99. float simd_w(Ty _a);
  100. template<typename Ty>
  101. Ty simd_ld(const void* _ptr);
  102. template<typename Ty>
  103. void simd_st(void* _ptr, Ty _a);
  104. template<typename Ty>
  105. void simd_stx(void* _ptr, Ty _a);
  106. template<typename Ty>
  107. void simd_stream(void* _ptr, Ty _a);
  108. template<typename Ty>
  109. Ty simd_ld(float _x, float _y, float _z, float _w);
  110. template<typename Ty>
  111. Ty simd_ld(float _x, float _y, float _z, float _w, float _a, float _b, float _c, float _d);
  112. template<typename Ty>
  113. Ty simd_ild(uint32_t _x, uint32_t _y, uint32_t _z, uint32_t _w);
  114. template<typename Ty>
  115. Ty simd_ild(uint32_t _x, uint32_t _y, uint32_t _z, uint32_t _w, uint32_t _a, uint32_t _b, uint32_t _c, uint32_t _d);
  116. template<typename Ty>
  117. Ty simd_splat(const void* _ptr);
  118. template<typename Ty>
  119. Ty simd_splat(float _a);
  120. template<typename Ty>
  121. Ty simd_isplat(uint32_t _a);
  122. template<typename Ty>
  123. Ty simd_zero();
  124. template<typename Ty>
  125. Ty simd_itof(Ty _a);
  126. template<typename Ty>
  127. Ty simd_ftoi(Ty _a);
  128. template<typename Ty>
  129. Ty simd_round(Ty _a);
  130. template<typename Ty>
  131. Ty simd_add(Ty _a, Ty _b);
  132. template<typename Ty>
  133. Ty simd_sub(Ty _a, Ty _b);
  134. template<typename Ty>
  135. Ty simd_mul(Ty _a, Ty _b);
  136. template<typename Ty>
  137. Ty simd_div(Ty _a, Ty _b);
  138. template<typename Ty>
  139. Ty simd_rcp_est(Ty _a);
  140. template<typename Ty>
  141. Ty simd_sqrt(Ty _a);
  142. template<typename Ty>
  143. Ty simd_rsqrt_est(Ty _a);
  144. template<typename Ty>
  145. Ty simd_dot3(Ty _a, Ty _b);
  146. template<typename Ty>
  147. Ty simd_dot(Ty _a, Ty _b);
  148. template<typename Ty>
  149. Ty simd_cmpeq(Ty _a, Ty _b);
  150. template<typename Ty>
  151. Ty simd_cmplt(Ty _a, Ty _b);
  152. template<typename Ty>
  153. Ty simd_cmple(Ty _a, Ty _b);
  154. template<typename Ty>
  155. Ty simd_cmpgt(Ty _a, Ty _b);
  156. template<typename Ty>
  157. Ty simd_cmpge(Ty _a, Ty _b);
  158. template<typename Ty>
  159. Ty simd_min(Ty _a, Ty _b);
  160. template<typename Ty>
  161. Ty simd_max(Ty _a, Ty _b);
  162. template<typename Ty>
  163. Ty simd_and(Ty _a, Ty _b);
  164. template<typename Ty>
  165. Ty simd_andc(Ty _a, Ty _b);
  166. template<typename Ty>
  167. Ty simd_or(Ty _a, Ty _b);
  168. template<typename Ty>
  169. Ty simd_xor(Ty _a, Ty _b);
  170. template<typename Ty>
  171. Ty simd_sll(Ty _a, int _count);
  172. template<typename Ty>
  173. Ty simd_srl(Ty _a, int _count);
  174. template<typename Ty>
  175. Ty simd_sra(Ty _a, int _count);
  176. template<typename Ty>
  177. Ty simd_icmpeq(Ty _a, Ty _b);
  178. template<typename Ty>
  179. Ty simd_icmplt(Ty _a, Ty _b);
  180. template<typename Ty>
  181. Ty simd_icmpgt(Ty _a, Ty _b);
  182. template<typename Ty>
  183. Ty simd_imin(Ty _a, Ty _b);
  184. template<typename Ty>
  185. Ty simd_imax(Ty _a, Ty _b);
  186. template<typename Ty>
  187. Ty simd_iadd(Ty _a, Ty _b);
  188. template<typename Ty>
  189. Ty simd_isub(Ty _a, Ty _b);
  190. template<typename Ty>
  191. Ty simd_shuf_xAzC(Ty _a, Ty _b);
  192. template<typename Ty>
  193. Ty simd_shuf_yBwD(Ty _a, Ty _b);
  194. template<typename Ty>
  195. Ty simd_rcp(Ty _a);
  196. template<typename Ty>
  197. Ty simd_orx(Ty _a);
  198. template<typename Ty>
  199. Ty simd_orc(Ty _a, Ty _b);
  200. template<typename Ty>
  201. Ty simd_neg(Ty _a);
  202. template<typename Ty>
  203. Ty simd_madd(Ty _a, Ty _b, Ty _c);
  204. template<typename Ty>
  205. Ty simd_nmsub(Ty _a, Ty _b, Ty _c);
  206. template<typename Ty>
  207. Ty simd_div_nr(Ty _a, Ty _b);
  208. template<typename Ty>
  209. Ty simd_selb(Ty _mask, Ty _a, Ty _b);
  210. template<typename Ty>
  211. Ty simd_sels(Ty _test, Ty _a, Ty _b);
  212. template<typename Ty>
  213. Ty simd_not(Ty _a);
  214. template<typename Ty>
  215. Ty simd_abs(Ty _a);
  216. template<typename Ty>
  217. Ty simd_clamp(Ty _a, Ty _min, Ty _max);
  218. template<typename Ty>
  219. Ty simd_lerp(Ty _a, Ty _b, Ty _s);
  220. template<typename Ty>
  221. Ty simd_rsqrt(Ty _a);
  222. template<typename Ty>
  223. Ty simd_rsqrt_nr(Ty _a);
  224. template<typename Ty>
  225. Ty simd_rsqrt_carmack(Ty _a);
  226. template<typename Ty>
  227. Ty simd_sqrt_nr(Ty _a);
  228. template<typename Ty>
  229. Ty simd_log2(Ty _a);
  230. template<typename Ty>
  231. Ty simd_exp2(Ty _a);
  232. template<typename Ty>
  233. Ty simd_pow(Ty _a, Ty _b);
  234. template<typename Ty>
  235. Ty simd_cross3(Ty _a, Ty _b);
  236. template<typename Ty>
  237. Ty simd_normalize3(Ty _a);
  238. template<typename Ty>
  239. Ty simd_ceil(Ty _a);
  240. template<typename Ty>
  241. Ty simd_floor(Ty _a);
  242. template<typename Ty>
  243. Ty simd_shuf_xAzC_ni(Ty _a, Ty _b);
  244. template<typename Ty>
  245. Ty simd_shuf_yBwD_ni(Ty _a, Ty _b);
  246. template<typename Ty>
  247. Ty simd_madd_ni(Ty _a, Ty _b, Ty _c);
  248. template<typename Ty>
  249. Ty simd_nmsub_ni(Ty _a, Ty _b, Ty _c);
  250. template<typename Ty>
  251. Ty simd_div_nr_ni(Ty _a, Ty _b);
  252. template<typename Ty>
  253. Ty simd_rcp_ni(Ty _a);
  254. template<typename Ty>
  255. Ty simd_orx_ni(Ty _a);
  256. template<typename Ty>
  257. Ty simd_orc_ni(Ty _a, Ty _b);
  258. template<typename Ty>
  259. Ty simd_neg_ni(Ty _a);
  260. template<typename Ty>
  261. Ty simd_selb_ni(Ty _mask, Ty _a, Ty _b);
  262. template<typename Ty>
  263. Ty simd_sels_ni(Ty _test, Ty _a, Ty _b);
  264. template<typename Ty>
  265. Ty simd_not_ni(Ty _a);
  266. template<typename Ty>
  267. Ty simd_min_ni(Ty _a, Ty _b);
  268. template<typename Ty>
  269. Ty simd_max_ni(Ty _a, Ty _b);
  270. template<typename Ty>
  271. Ty simd_abs_ni(Ty _a);
  272. template<typename Ty>
  273. Ty simd_imin_ni(Ty _a, Ty _b);
  274. template<typename Ty>
  275. Ty simd_imax_ni(Ty _a, Ty _b);
  276. template<typename Ty>
  277. Ty simd_clamp_ni(Ty _a, Ty _min, Ty _max);
  278. template<typename Ty>
  279. Ty simd_lerp_ni(Ty _a, Ty _b, Ty _s);
  280. template<typename Ty>
  281. Ty simd_sqrt_nr_ni(Ty _a);
  282. template<typename Ty>
  283. Ty simd_sqrt_nr1_ni(Ty _a);
  284. template<typename Ty>
  285. Ty simd_rsqrt_ni(Ty _a);
  286. template<typename Ty>
  287. Ty simd_rsqrt_nr_ni(Ty _a);
  288. template<typename Ty>
  289. Ty simd_rsqrt_carmack_ni(Ty _a);
  290. template<typename Ty>
  291. Ty simd_log2_ni(Ty _a);
  292. template<typename Ty>
  293. Ty simd_exp2_ni(Ty _a);
  294. template<typename Ty>
  295. Ty simd_pow_ni(Ty _a, Ty _b);
  296. template<typename Ty>
  297. Ty simd_dot3_ni(Ty _a, Ty _b);
  298. template<typename Ty>
  299. Ty simd_cross3_ni(Ty _a, Ty _b);
  300. template<typename Ty>
  301. Ty simd_normalize3_ni(Ty _a);
  302. template<typename Ty>
  303. Ty simd_dot_ni(Ty _a, Ty _b);
  304. template<typename Ty>
  305. Ty simd_ceil_ni(Ty _a);
  306. template<typename Ty>
  307. Ty simd_floor_ni(Ty _a);
  308. template<typename Ty>
  309. Ty simd_round_ni(Ty _a);
  310. template<typename Ty>
  311. bool simd_test_any_ni(Ty _a);
  312. template<typename Ty>
  313. bool simd_test_all_ni(Ty _a);
  314. #if BX_SIMD_AVX
  315. typedef __m256 simd256_avx_t;
  316. #endif // BX_SIMD_SSE
  317. #if BX_SIMD_LANGEXT
  318. union simd128_langext_t
  319. {
  320. float __attribute__((vector_size(16))) vf;
  321. int32_t __attribute__((vector_size(16))) vi;
  322. uint32_t __attribute__((vector_size(16))) vu;
  323. float fxyzw[4];
  324. int32_t ixyzw[4];
  325. uint32_t uxyzw[4];
  326. };
  327. #endif // BX_SIMD_LANGEXT
  328. #if BX_SIMD_NEON
  329. typedef float32x4_t simd128_neon_t;
  330. #endif // BX_SIMD_NEON
  331. #if BX_SIMD_SSE
  332. typedef __m128 simd128_sse_t;
  333. #endif // BX_SIMD_SSE
  334. } // namespace bx
  335. #if BX_SIMD_AVX
  336. # include "inline/simd256_avx.inl"
  337. #endif // BX_SIMD_AVX
  338. #if BX_SIMD_LANGEXT
  339. # include "inline/simd128_langext.inl"
  340. #endif // BX_SIMD_LANGEXT
  341. #if BX_SIMD_NEON
  342. # include "inline/simd128_neon.inl"
  343. #endif // BX_SIMD_NEON
  344. #if BX_SIMD_SSE
  345. # include "inline/simd128_sse.inl"
  346. #endif // BX_SIMD_SSE
  347. #if ( BX_SIMD_LANGEXT \
  348. || BX_SIMD_NEON \
  349. || BX_SIMD_SSE \
  350. || BX_SIMD_AVX \
  351. )
  352. # undef BX_CONFIG_SUPPORTS_SIMD
  353. # define BX_CONFIG_SUPPORTS_SIMD 1
  354. #endif // BX_SIMD_*
  355. namespace bx
  356. {
  357. union simd128_ref_t
  358. {
  359. float fxyzw[4];
  360. int32_t ixyzw[4];
  361. uint32_t uxyzw[4];
  362. };
  363. #ifndef BX_SIMD_WARN_REFERENCE_IMPL
  364. # define BX_SIMD_WARN_REFERENCE_IMPL 0
  365. #endif // BX_SIMD_WARN_REFERENCE_IMPL
  366. #if !BX_CONFIG_SUPPORTS_SIMD
  367. # if BX_SIMD_WARN_REFERENCE_IMPL
  368. # pragma message("*** Using SIMD128 reference implementation! ***")
  369. # endif // BX_SIMD_WARN_REFERENCE_IMPL
  370. typedef simd128_ref_t simd128_t;
  371. #endif // BX_SIMD_REFERENCE
  372. struct simd256_ref_t
  373. {
  374. #if BX_COMPILER_MSVC
  375. typedef simd128_ref_t type;
  376. #else
  377. typedef simd128_t type;
  378. #endif // BX_COMPILER_MSVC
  379. type simd128_0;
  380. type simd128_1;
  381. };
  382. #if !BX_SIMD_AVX
  383. # if BX_SIMD_WARN_REFERENCE_IMPL
  384. # pragma message("*** Using SIMD256 reference implementation! ***")
  385. # endif // BX_SIMD_WARN_REFERENCE_IMPL
  386. typedef simd256_ref_t simd256_t;
  387. #endif // !BX_SIMD_AVX
  388. simd128_t simd_zero();
  389. simd128_t simd_ld(const void* _ptr);
  390. simd128_t simd_ld(float _x, float _y, float _z, float _w);
  391. simd128_t simd_ild(uint32_t _x, uint32_t _y, uint32_t _z, uint32_t _w);
  392. simd128_t simd_splat(const void* _ptr);
  393. simd128_t simd_splat(float _a);
  394. simd128_t simd_isplat(uint32_t _a);
  395. } // namespace bx
  396. #include "inline/simd128_ref.inl"
  397. #include "inline/simd256_ref.inl"
  398. #include "inline/simd_ni.inl"
  399. #endif // BX_SIMD_T_H_HEADER_GUARD