From 3b159cdf021f9e77ba3edc202ffa9e57615ff76a Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 11 Jul 2017 16:33:41 +0300 Subject: [PATCH] neon: implement matrix multiplication for ARM Neon --- .gitignore | 3 ++ include/arch/simd/neon/mat4.h | 57 +++++++++++++++++++++++++++++++++++ include/cglm-mat.h | 16 ++++++++-- 3 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 include/arch/simd/neon/mat4.h diff --git a/.gitignore b/.gitignore index 96858dc..09c8746 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,6 @@ test/test_* test-* test/.libs/* test/tests +cglm_arm/* +cglm_test_ios/* +cglm_test_iosTests/* \ No newline at end of file diff --git a/include/arch/simd/neon/mat4.h b/include/arch/simd/neon/mat4.h new file mode 100644 index 0000000..8694ea2 --- /dev/null +++ b/include/arch/simd/neon/mat4.h @@ -0,0 +1,57 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_mat4_neon_h +#define cglm_mat4_neon_h +#if defined(__ARM_NEON_FP) + +#include "../../../cglm-common.h" +#include + +CGLM_INLINE +void +glm_mat4_mul_neon(mat4 m1, mat4 m2, mat4 dest) { + /* D = R * L (Column-Major) */ + float32x4_t l0, l1, l2, l3, r, d0, d1, d2, d3; + + l0 = vld1q_f32(m2[0]); + l1 = vld1q_f32(m2[1]); + l2 = vld1q_f32(m2[2]); + l3 = vld1q_f32(m2[3]); + + r = vld1q_f32(m1[0]); + d0 = vmulq_lane_f32(r, vget_low_f32(l0), 0); + d1 = vmulq_lane_f32(r, vget_low_f32(l1), 0); + d2 = vmulq_lane_f32(r, vget_low_f32(l2), 0); + d3 = vmulq_lane_f32(r, vget_low_f32(l3), 0); + + r = vld1q_f32(m1[1]); + d0 = vmlaq_lane_f32(d0, r, vget_low_f32(l0), 1); + d1 = vmlaq_lane_f32(d1, r, vget_low_f32(l1), 1); + d2 = vmlaq_lane_f32(d2, r, vget_low_f32(l2), 1); + d3 = vmlaq_lane_f32(d3, r, vget_low_f32(l3), 1); + + r = vld1q_f32(m1[2]); + d0 = vmlaq_lane_f32(d0, r, vget_high_f32(l0), 0); + d1 = vmlaq_lane_f32(d1, r, vget_high_f32(l1), 0); + d2 = vmlaq_lane_f32(d2, r, vget_high_f32(l2), 0); + d3 = vmlaq_lane_f32(d3, r, vget_high_f32(l3), 0); + + r = vld1q_f32(m1[3]); + d0 = vmlaq_lane_f32(d0, r, vget_high_f32(l0), 1); + d1 = vmlaq_lane_f32(d1, r, vget_high_f32(l1), 1); + d2 = vmlaq_lane_f32(d2, r, vget_high_f32(l2), 1); + d3 = vmlaq_lane_f32(d3, r, vget_high_f32(l3), 1); + + vst1q_f32(dest[0], d0); + vst1q_f32(dest[1], d1); + vst1q_f32(dest[2], d2); + vst1q_f32(dest[3], d3); +} + +#endif +#endif /* cglm_mat4_neon_h */ diff --git a/include/cglm-mat.h b/include/cglm-mat.h index 6ced3a4..c5dad6a 100644 --- a/include/cglm-mat.h +++ b/include/cglm-mat.h @@ -45,8 +45,18 @@ #define cglm_mat_h #include "cglm-common.h" -#include "arch/simd/cglm-mat-simd-sse2.h" -#include "arch/simd/cglm-mat-simd-avx.h" + +#ifdef CGLM_SSE_FP +# include "arch/simd/cglm-mat-simd-sse2.h" +#endif + +#ifdef CGLM_AVX_FP +# include "arch/simd/cglm-mat-simd-avx.h" +#endif + +#ifdef CGLM_NEON_FP +# include "arch/simd/neon/mat4.h" +#endif #include @@ -215,6 +225,8 @@ glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest) { glm_mat4_mul_avx(m1, m2, dest); #elif defined( __SSE__ ) || defined( __SSE2__ ) glm_mat4_mul_sse2(m1, m2, dest); +#elif defined( __ARM_NEON_FP ) + glm_mat4_mul_neon(m1, m2, dest); #else float a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2], a03 = m1[0][3], a10 = m1[1][0], a11 = m1[1][1], a12 = m1[1][2], a13 = m1[1][3],