BVB Source Codes

CRYENGINE Show VMath_NEON.hpp Source code

Return Download CRYENGINE: download VMath_NEON.hpp Source code - Download CRYENGINE Source code - Type:.hpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  Version:     v1.00
  5. //  Created:     Michael Kopietz
  6. //  Description: unified vector math lib
  7. // -------------------------------------------------------------------------
  8. //  History:            - created 1999  for Katmai and K3
  9. //                                                      -       ...
  10. //                                                      -       integrated into cryengine
  11. //
  12. ////////////////////////////////////////////////////////////////////////////
  13.  
  14. #pragma once
  15.  
  16. #include <arm_neon.h>
  17.  
  18. namespace NVMath
  19. {
  20.  
  21.         typedef float32x4_t vec4;
  22.  
  23.         #include "VMath_Prototypes.hpp"
  24.  
  25.         #define AVOID_COMPILER_BUG
  26.  
  27.         #ifdef AVOID_COMPILER_BUG
  28.  
  29.                 #define SWIZZLEMASK5(X, Y, Z, W) ((X) | (Y << 2) | (Z << 4) | (W << 6))
  30.                 #define SWIZZLEMASK4(N, X, Y, Z) N ## x = SWIZZLEMASK5(X, Y, Z, 0), \
  31.                   N ## y = SWIZZLEMASK5(X, Y, Z, 1),                                \
  32.                   N ## z = SWIZZLEMASK5(X, Y, Z, 2),                                \
  33.                   N ## w = SWIZZLEMASK5(X, Y, Z, 3),
  34.                 #define SWIZZLEMASK3(N, X, Y)    SWIZZLEMASK4(N ## x, X, Y, 0) \
  35.                   SWIZZLEMASK4(N ## y, X, Y, 1)                                \
  36.                   SWIZZLEMASK4(N ## z, X, Y, 2)                                \
  37.                   SWIZZLEMASK4(N ## w, X, Y, 3)
  38.                 #define SWIZZLEMASK2(N, X)       SWIZZLEMASK3(N ## x, X, 0) \
  39.                   SWIZZLEMASK3(N ## y, X, 1)                                \
  40.                   SWIZZLEMASK3(N ## z, X, 2)                                \
  41.                   SWIZZLEMASK3(N ## w, X, 3)
  42.                 #define SWIZZLEMASK1 SWIZZLEMASK2(x, 0) \
  43.                   SWIZZLEMASK2(y, 1)                    \
  44.                   SWIZZLEMASK2(z, 2)                    \
  45.                   SWIZZLEMASK2(w, 3)
  46.  
  47. enum ESwizzleMask
  48. {
  49.         SWIZZLEMASK1
  50. };
  51.  
  52.         #else
  53.  
  54.                 #define SWIZZLEMASK5(X, Y, Z, W) { (X + 0), (X + 1), (X + 2), (X + 3), (Y + 0), (Y + 1), (Y + 2), (Y + 3), (Z + 16), (Z + 17), (Z + 18), (Z + 19), (W + 16), (W + 17), (W + 18), (W + 19) }
  55.                 #define SWIZZLEMASK4(N, X, Y, Z) SWIZZLEMASK5(X, Y, Z, 0), \
  56.                   SWIZZLEMASK5(X, Y, Z, 4),                                \
  57.                   SWIZZLEMASK5(X, Y, Z, 8),                                \
  58.                   SWIZZLEMASK5(X, Y, Z, 12),
  59.                 #define SWIZZLEMASK3(N, X, Y)    SWIZZLEMASK4(N ## x, X, Y, 0) \
  60.                   SWIZZLEMASK4(N ## y, X, Y, 4)                                \
  61.                   SWIZZLEMASK4(N ## z, X, Y, 8)                                \
  62.                   SWIZZLEMASK4(N ## w, X, Y, 12)
  63.                 #define SWIZZLEMASK2(N, X)       SWIZZLEMASK3(N ## x, X, 0) \
  64.                   SWIZZLEMASK3(N ## y, X, 4)                                \
  65.                   SWIZZLEMASK3(N ## z, X, 8)                                \
  66.                   SWIZZLEMASK3(N ## w, X, 12)
  67.                 #define SWIZZLEMASK1 SWIZZLEMASK2(x, 0) \
  68.                   SWIZZLEMASK2(y, 4)                    \
  69.                   SWIZZLEMASK2(z, 8)                    \
  70.                   SWIZZLEMASK2(w, 12)
  71.  
  72.                 #define SWIZZLEINDEX5(X, Y, Z, W) (X + Y + Z + W)
  73.                 #define SWIZZLEINDEX4(N, X, Y, Z) N ## x = SWIZZLEINDEX5(X, Y, Z, 0), \
  74.                   N ## y = SWIZZLEINDEX5(X, Y, Z, 1),                                 \
  75.                   N ## z = SWIZZLEINDEX5(X, Y, Z, 2),                                 \
  76.                   N ## w = SWIZZLEINDEX5(X, Y, Z, 3),
  77.                 #define SWIZZLEINDEX3(N, X, Y)    SWIZZLEINDEX4(N ## x, X, Y, 0) \
  78.                   SWIZZLEINDEX4(N ## y, X, Y, 1)                                 \
  79.                   SWIZZLEINDEX4(N ## z, X, Y, 2)                                 \
  80.                   SWIZZLEINDEX4(N ## w, X, Y, 3)
  81.                 #define SWIZZLEINDEX2(N, X)       SWIZZLEINDEX3(N ## x, X, 0) \
  82.                   SWIZZLEINDEX3(N ## y, X, 1)                                 \
  83.                   SWIZZLEINDEX3(N ## z, X, 2)                                 \
  84.                   SWIZZLEINDEX3(N ## w, X, 3)
  85.                 #define SWIZZLEINDEX1 SWIZZLEINDEX2(x, 0) \
  86.                   SWIZZLEINDEX2(y, 1)                     \
  87.                   SWIZZLEINDEX2(z, 2)                     \
  88.                   SWIZZLEINDEX2(w, 3)
  89.  
  90. enum ESwizzleMask
  91. {
  92.         SWIZZLEINDEX1
  93. };
  94.  
  95. namespace cryengine_vmath_neon_internal
  96. {
  97. // Contains pre-calculated lookup indices for Shuffle().  Indexed by ESwizzleMask
  98. static const uint8x16_t g_SwizzleMasks[] = {
  99.         SWIZZLEMASK1
  100. };
  101. } // namespace cryengine_vmath_neon_internal
  102.  
  103.         #endif // AVOID_COMPILER_BUG
  104.  
  105. enum ECacheLvl
  106. {
  107.         ECL_LVL1,
  108.         ECL_LVL2,
  109.         ECL_LVL3,
  110. };
  111.  
  112. /**
  113.  * Bit masks for use with result from SignMask()
  114.  */
  115. static const uint32 BitX = 0x00000080;
  116. static const uint32 BitY = 0x00008000;
  117. static const uint32 BitZ = 0x00800000;
  118. static const uint32 BitW = 0x80000000;
  119.  
  120. ILINE vec4 Vec4(float x, float y, float z, float w)
  121. {
  122.         const vec4 Ret = { x, y, z, w };
  123.         return Ret;
  124. }
  125.  
  126. ILINE vec4 Vec4(uint32 x, uint32 y, uint32 z, uint32 w)
  127. {
  128.         const uint32x4_t Ret = { x, y, z, w };
  129.         return (float32x4_t)Ret;
  130. }
  131.  
  132. ILINE vec4 Vec4(float x)
  133. {
  134.         return Vec4(x, x, x, x);
  135. }
  136.  
  137. template<int Idx>
  138. ILINE int32 Vec4int32(vec4 V)
  139. {
  140.         return vgetq_lane_s32((int32x4_t)V, Idx);
  141. }
  142.  
  143. template<int Idx>
  144. ILINE float Vec4float(vec4 V)
  145. {
  146.         return vgetq_lane_f32(V, Idx);
  147. }
  148.  
  149. ILINE int32 Vec4int32(vec4 V, uint32 Idx)
  150. {
  151.         switch (Idx)
  152.         {
  153.         case 0:
  154.                 return vgetq_lane_s32((int32x4_t)V, 0);
  155.         case 1:
  156.                 return vgetq_lane_s32((int32x4_t)V, 1);
  157.         case 2:
  158.                 return vgetq_lane_s32((int32x4_t)V, 2);
  159.         case 3:
  160.                 return vgetq_lane_s32((int32x4_t)V, 3);
  161.         default:
  162.                 assert(0);
  163.                 return 0;
  164.         }
  165.         //return V.m_s[Idx];
  166. }
  167.  
  168. ILINE float Vec4float(vec4 V, uint32 Idx)
  169. {
  170.         switch (Idx)
  171.         {
  172.         case 0:
  173.                 return vgetq_lane_f32(V, 0);
  174.         case 1:
  175.                 return vgetq_lane_f32(V, 1);
  176.         case 2:
  177.                 return vgetq_lane_f32(V, 2);
  178.         case 3:
  179.                 return vgetq_lane_f32(V, 3);
  180.         default:
  181.                 assert(0);
  182.                 return 0;
  183.         }
  184. }
  185.  
  186. ILINE vec4 Vec4Zero()
  187. {
  188.         static const float32x4_t V = { 0.f, 0.f, 0.f, 0.f };
  189.         return V;
  190. }
  191.  
  192. ILINE vec4 Vec4One()
  193. {
  194.         static const float32x4_t V = { 1.f, 1.f, 1.f, 1.f };
  195.         return V;
  196. }
  197. ILINE vec4 Vec4Four()
  198. {
  199.         static const float32x4_t V = { 4.f, 4.f, 4.f, 4.f };
  200.         return V;
  201. }
  202. ILINE vec4 Vec4ZeroOneTwoThree()
  203. {
  204.         static const float32x4_t V = { 0.f, 1.f, 2.f, 3.f };
  205.         return V;
  206. }
  207. ILINE vec4 Vec4FFFFFFFF()
  208. {
  209.         return Vec4(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
  210. }
  211. ILINE vec4 Vec4Epsilon()
  212. {
  213.         static const float32x4_t V = { FLT_EPSILON, FLT_EPSILON, FLT_EPSILON, FLT_EPSILON };
  214.         return V;
  215. }
  216.  
  217. /**
  218.  * Creates vector where each word element is set to value of specified element.
  219.  * INDEX 0 is x, 1 is y, etc.
  220.  * @returns {V[INDEX], V[INDEX], V[INDEX], V[INDEX]}
  221.  */
  222. template<int INDEX>
  223. ILINE vec4 Splat(vec4 V)
  224. {
  225.         switch (INDEX)
  226.         {
  227.         case 0:
  228.         case 1:
  229.                 return vdupq_lane_f32(vget_low_f32(V), INDEX);
  230.         case 2:
  231.                 // expanded to fix a clang compiler error with the preprocessor
  232.                 return vdupq_lane_f32(vget_high_f32(V), 0);
  233.         case 3:
  234.                 // expanded to fix a clang compiler error with the preprocessor
  235.                 return vdupq_lane_f32(vget_high_f32(V), 1);
  236.         default:
  237.                 assert(0);
  238.                 return Vec4FFFFFFFF();
  239.         }
  240. }
  241.  
  242. template<ECacheLvl L>
  243. ILINE void Prefetch(const void* pData)
  244. {
  245.         __builtin_prefetch(pData);
  246. }
  247.  
  248. /**
  249.  * Return vector containing words from V0 and V1 based on mask M.
  250.  * First two elements of M specify word index in V0 and last two elements
  251.  * specify word index in V1.
  252.  *
  253.  * e.g.
  254.  * Shuffle( M={0,1,2,3} ) => {V0[0], V0[1], V1[2], V1[3]}
  255.  */
  256. template<ESwizzleMask M>
  257. ILINE vec4 Shuffle(vec4 V0, vec4 V1)
  258. {
  259.         #ifdef AVOID_COMPILER_BUG
  260.         return Vec4(Vec4float(V0, M & 3), Vec4float(V0, (M >> 2) & 3), Vec4float(V1, (M >> 4) & 3), Vec4float(V1, (M >> 6) & 3));
  261.         #else
  262.         //return Vec4(V0.m_u[M&3],V0.m_u[(M>>2)&3],V1.m_u[(M>>4)&3],V1.m_u[(M>>6)&3]);
  263.         assert(M >= 0 && M < sizeof(cryengine_vmath_neon_internal::g_SwizzleMasks) / sizeof(cryengine_vmath_neon_internal::g_SwizzleMasks[0]));
  264.         // Get precomputed vector containing lookup indices for swizzle
  265.         const uint8x16_t mask = cryengine_vmath_neon_internal::g_SwizzleMasks[M];
  266.         // Split the lookup indexes into xy and zw pair
  267.         const uint8x8_t low_index = vget_low_u8(mask);
  268.         const uint8x8_t high_index = vget_high_u8(mask);
  269.         // Combine inputs into table; VO=xyzw, V1=XYZW => xyzwXYZW
  270.         const uint8x8x4_t tbl = {
  271.                 {
  272.                         (uint8x8_t)vget_low_f32(V0),
  273.                         (uint8x8_t)vget_high_f32(V0),
  274.                         (uint8x8_t)vget_low_f32(V1),
  275.                         (uint8x8_t)vget_high_f32(V1),
  276.                 }
  277.         };
  278.         // Look up the xy values, then zw values, then combine them
  279.         const uint8x8_t low = vtbl4_u8(tbl, low_index);
  280.         const uint8x8_t high = vtbl4_u8(tbl, high_index);
  281.         const uint8x16_t ret = vcombine_u8(low, high);
  282.         return (float32x4_t)ret;
  283.         #endif // AVOID_COMPILER_BUG
  284. }
  285.  
  286. template<ESwizzleMask M>
  287. ILINE vec4 Swizzle(vec4 V)
  288. {
  289.         return Shuffle<M>(V, V);
  290. }
  291.  
  292. /**
  293.  * @returns V0 + V1
  294.  */
  295. ILINE vec4 Add(vec4 V0, vec4 V1)
  296. {
  297.         return vaddq_f32(V0, V1);
  298. }
  299.  
  300. /**
  301.  * @returns V0 - V1
  302.  */
  303. ILINE vec4 Sub(vec4 V0, vec4 V1)
  304. {
  305.         return vsubq_f32(V0, V1);
  306. }
  307.  
  308. /**
  309.  * @returns V0 * V1
  310.  */
  311. ILINE vec4 Mul(vec4 V0, vec4 V1)
  312. {
  313.         return vmulq_f32(V0, V1);
  314. }
  315.  
  316. /**
  317.  * @returns V0 / V1
  318.  */
  319. ILINE vec4 Div(vec4 V0, vec4 V1)
  320. {
  321.         return Mul(V0, Rcp(V1));
  322. }
  323.  
  324. /**
  325.  * @returns 1 / V
  326.  */
  327. ILINE vec4 RcpFAST(vec4 V)
  328. {
  329.         return vrecpeq_f32(V);
  330. }
  331.  
  332. /**
  333.  * @returns V0 / V1
  334.  */
  335. ILINE vec4 DivFAST(vec4 V0, vec4 V1)
  336. {
  337.         return Mul(V0, RcpFAST(V1));
  338. }
  339.  
  340. /**
  341.  * @returns 1 / V
  342.  */
  343. ILINE vec4 Rcp(vec4 V)
  344. {
  345.         // Improve estimate precision with a single Newton-Raphson iteration
  346.         vec4 vEstimate = RcpFAST(V);
  347.         return vmulq_f32(vrecpsq_f32(V, vEstimate), vEstimate);
  348. }
  349.  
  350. /**
  351.  * @returns V0 * V1 + V2
  352.  */
  353. ILINE vec4 Madd(vec4 V0, vec4 V1, vec4 V2)
  354. {
  355.         // Madd return V0*V1+V2 but vmla(a,b,c) does b*c+a
  356.         return vmlaq_f32(V2, V0, V1);
  357. }
  358.  
  359. /**
  360.  * @returns V0 * V1 - V2
  361.  */
  362. ILINE vec4 Msub(vec4 V0, vec4 V1, vec4 V2)
  363. {
  364.         // Msub returns V0*V1-V2 but vmls(a,b,c) does a-b*c
  365.         return Sub(Mul(V0, V1), V2);
  366. }
  367.  
  368. ILINE vec4 Min(vec4 V0, vec4 V1)
  369. {
  370.         return vminq_f32(V0, V1);
  371. }
  372.  
  373. ILINE vec4 Max(vec4 V0, vec4 V1)
  374. {
  375.         return vmaxq_f32(V0, V1);
  376. }
  377.  
  378. ILINE vec4 floatToint32(vec4 V)
  379. {
  380.         return (float32x4_t)vcvtq_s32_f32(V);
  381. }
  382.  
  383. ILINE vec4 int32Tofloat(vec4 V)
  384. {
  385.         return vcvtq_f32_s32((int32x4_t)V);
  386. }
  387.  
  388. ILINE vec4 CmpLE(vec4 V0, vec4 V1)
  389. {
  390.         return (float32x4_t)vcleq_f32(V0, V1);
  391. }
  392.  
  393. /**
  394.  * Return sign bit of each word as a single word.  Each is accessible via
  395.  * Bit[X|Y|Z|W] mask.
  396.  */
  397. ILINE uint32 SignMask(vec4 V)
  398. {
  399.         #ifndef __AARCH64_SIMD__
  400.                 #if 1
  401.         // Create table from which be select bytes with msb (sign) and combine into
  402.         // single word
  403.         const uint8x8x2_t tbl = {
  404.                 {
  405.                         (uint8x8_t)vget_low_f32(V),
  406.                         (uint8x8_t)vget_high_f32(V),
  407.                 }
  408.         };
  409.         const uint8x8_t idx_sign = { 3, 7, 11, 15 }; // MSB -> LSB = W -> X (0xWWZZYYXX)
  410.         const uint8x8_t sign_bytes = vtbl2_u8(tbl, idx_sign);
  411.                 #else
  412.         const int32x4_t rev = vshrq_n_s32((int32x4_t)V, 24);
  413.         const int16x4_t shorts = vmovn_s32(rev);
  414.         const uint8x8_t tbl = (uint8x8_t)shorts;
  415.         const uint8x8_t index = { 1, 3, 5, 7 };
  416.         const uint8x8_t sign_bytes = vtbl1_u8(tbl, index);
  417.                 #endif
  418.         return vget_lane_u32((uint32x2_t)sign_bytes, 0);
  419.         //return (V.m_Xu>>31)|((V.m_Yu>>31)<<1)|((V.m_Zu>>31)<<2)|((V.m_Wu>>31)<<3);
  420.         #else
  421.         const uint8x16_t tbl = vcombine_u8((uint8x8_t)vget_low_f32(V), (uint8x8_t)vget_high_f32(V));
  422.         const uint8x8_t idx_sign = { 3, 7, 11, 15 }; // MSB -> LSB = W -> X (0xWWZZYYXX)
  423.         const uint8x8_t sign_bytes = vtbl1q_u8(tbl, idx_sign);
  424.         return vget_lane_u32((uint32x2_t)sign_bytes, 0);
  425.         #endif
  426. }
  427.  
  428. /**
  429.  * @returns V0 & V1
  430.  */
  431. ILINE vec4 And(vec4 V0, vec4 V1)
  432. {
  433.         return (float32x4_t)vandq_u32((uint32x4_t)V0, (uint32x4_t)V1);
  434. }
  435.  
  436. /**
  437.  * @returns ~V0 & V1
  438.  */
  439. ILINE vec4 AndNot(vec4 V0, vec4 V1)
  440. {
  441.         return (float32x4_t)vandq_u32(vmvnq_u32((uint32x4_t)V0), (uint32x4_t)V1);
  442. }
  443.  
  444. /**
  445.  * @returns V0 | V1
  446.  */
  447. ILINE vec4 Or(vec4 V0, vec4 V1)
  448. {
  449.         return (float32x4_t)vorrq_u32((uint32x4_t)V0, (uint32x4_t)V1);
  450. }
  451.  
  452. /**
  453.  * @returns V0 ^ V1
  454.  */
  455. ILINE vec4 Xor(vec4 V0, vec4 V1)
  456. {
  457.         return (float32x4_t)veorq_u32((uint32x4_t)V0, (uint32x4_t)V1);
  458. }
  459.  
  460. ILINE vec4 Select(vec4 V0, vec4 V1, vec4 M)
  461. {
  462.         return SelectSign(V0, V1, M);
  463. }
  464.  
  465. /**
  466.  * Returns new vector where each word element comes from V0 if the sign of
  467.  * the corresponding word in M is 0 (+), otherwise the word element comes from
  468.  * V1.
  469.  *
  470.  * e.g.
  471.  * SelectSign( {0.f,1.f,2.f,3.f}, {a.f,b.f,c.f,d.f}, {0.f,0.f,-1.f,-1.f} )
  472.  * => {0.f, 1.f, c.f, d.f}
  473.  */
  474. ILINE vec4 SelectSign(vec4 V0, vec4 V1, vec4 M)
  475. {
  476.         const int32x4_t mask = vshrq_n_s32((int32x4_t)M, 31);
  477.         return vbslq_f32((uint32x4_t)mask, V1, V0);
  478.         //M     =       ShiftAR(M,31);
  479.         //return Or(AndNot(M,V0),And(M,V1));
  480. }
  481.  
  482. /**
  483.  * Expands each byte of VIn as a float.
  484.  *
  485.  * e.g.
  486.  * ExtractByteToFloat( {0x00010203, 0x04...} ) => {3.f, 2.f, 1.f, 0.f} ...
  487.  */
  488. static ILINE void ExtractByteToFloat(vec4& rVout0, vec4& rVout1, vec4& rVout2, vec4& rVout3, vec4 VIn)
  489. {
  490.         // 16 bytes => 2x 8 shorts
  491.         const int8x8_t XY8 = vget_low_s8((int8x16_t)VIn);
  492.         const int8x8_t ZW8 = vget_high_s8((int8x16_t)VIn);
  493.         const int16x8_t XY16 = vmovl_s8(XY8);
  494.         const int16x8_t ZW16 = vmovl_s8(ZW8);
  495.  
  496.         // 2x 8 shorts => 4x 4 int
  497.         const int16x4_t X16 = vget_low_s16(XY16);
  498.         const int16x4_t Y16 = vget_high_s16(XY16);
  499.         const int16x4_t Z16 = vget_low_s16(ZW16);
  500.         const int16x4_t W16 = vget_high_s16(ZW16);
  501.         const int32x4_t X32 = vmovl_s16(X16);
  502.         const int32x4_t Y32 = vmovl_s16(Y16);
  503.         const int32x4_t Z32 = vmovl_s16(Z16);
  504.         const int32x4_t W32 = vmovl_s16(W16);
  505.  
  506.         // 4x 4 int => 4x 4 float
  507.         rVout0 = vcvtq_f32_s32(X32);
  508.         rVout1 = vcvtq_f32_s32(Y32);
  509.         rVout2 = vcvtq_f32_s32(Z32);
  510.         rVout3 = vcvtq_f32_s32(W32);
  511. }
  512.  
  513. /**
  514.  * Returns vector where each bit is from V0 if the corresponding bit in
  515.  * M is 0, otherwise the bit is from V1 (i.e. vsel instruction from PowerPC, or selb from SPU).
  516.  *
  517.  * e.g.
  518.  * SelectBits(b0001, b1110, b0011) => b0010
  519.  */
  520. ILINE vec4 SelectBits(vec4 V0, vec4 V1, vec4 M)
  521. {
  522.         // Order of args to vbsl is exact opposite of SelectBits()
  523.         return vbslq_f32((uint32x4_t)M, V1, V0);
  524.         //return Or(AndNot(M,V0),And(M,V1));
  525. }
  526.  
  527. /**
  528.  * Returns vector where, for each word, all bits are set to 1 if the
  529.  * corresponding words in V0 and V1 are equal.
  530.  *
  531.  * e.g.
  532.  * CmpEq( {0.f...}, {0.f, 1.f, 2.f...} ) => {0xffffffff, 0x0, 0x0, 0x0}
  533.  */
  534. ILINE vec4 CmpEq(vec4 V0, vec4 V1)
  535. {
  536.         return (float32x4_t)vceqq_f32(V0, V1);
  537. }
  538.  
  539. template<int M>
  540. ILINE vec4 SelectStatic(vec4 V0, vec4 V1)
  541. {
  542.         const vec4 mask = Vec4(M & 0x1 ? ~0x0u : 0x0u, M & 0x2 ? ~0x0u : 0x0u, M & 0x4 ? ~0x0u : 0x0u, M & 0x8 ? ~0x0u : 0x0u);
  543.         return Select(V0, V1, mask);
  544. }
  545.  
  546. }
  547.  
  548. #undef AVOID_COMPILER_BUG
  549.  
downloadVMath_NEON.hpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top