master
ブランチ master
VulkanExample / dep / include / glm / simd / neon.h
5.2 KB、171行 生 Blame 履歴
1/// @ref simd_neon
2/// @file glm/simd/neon.h
3
4#pragma once
5
6#if GLM_ARCH & GLM_ARCH_NEON_BIT
7#include <arm_neon.h>
8
9namespace glm {
10 namespace neon {
11 static inline float32x4_t dupq_lane(float32x4_t vsrc, int lane) {
12 switch(lane) {
13 default:
14 assert(false); //Unreachable code executed!
15 return vdupq_n_f32(0.0f);
16#if GLM_ARCH & GLM_ARCH_ARMV8_BIT
17 case 0: return vdupq_laneq_f32(vsrc, 0);
18 case 1: return vdupq_laneq_f32(vsrc, 1);
19 case 2: return vdupq_laneq_f32(vsrc, 2);
20 case 3: return vdupq_laneq_f32(vsrc, 3);
21#else
22 case 0: return vdupq_n_f32(vgetq_lane_f32(vsrc, 0));
23 case 1: return vdupq_n_f32(vgetq_lane_f32(vsrc, 1));
24 case 2: return vdupq_n_f32(vgetq_lane_f32(vsrc, 2));
25 case 3: return vdupq_n_f32(vgetq_lane_f32(vsrc, 3));
26#endif
27 }
28 }
29
30 static inline float32x2_t dup_lane(float32x4_t vsrc, int lane) {
31 switch(lane) {
32 default:
33 assert(false); //Unreachable code executed!
34 return vdup_n_f32(0.0f);
35#if GLM_ARCH & GLM_ARCH_ARMV8_BIT
36 case 0: return vdup_laneq_f32(vsrc, 0);
37 case 1: return vdup_laneq_f32(vsrc, 1);
38 case 2: return vdup_laneq_f32(vsrc, 2);
39 case 3: return vdup_laneq_f32(vsrc, 3);
40#else
41 case 0: return vdup_n_f32(vgetq_lane_f32(vsrc, 0));
42 case 1: return vdup_n_f32(vgetq_lane_f32(vsrc, 1));
43 case 2: return vdup_n_f32(vgetq_lane_f32(vsrc, 2));
44 case 3: return vdup_n_f32(vgetq_lane_f32(vsrc, 3));
45#endif
46 }
47 }
48
49 static inline float32x4_t copy_lane(float32x4_t vdst, int dlane, float32x4_t vsrc, int slane) {
50#if GLM_ARCH & GLM_ARCH_ARMV8_BIT
51 switch(dlane) {
52 default:
53 case 0:
54 switch(slane) {
55 default:
56 assert(false); //Unreachable code executed!
57 break;
58 case 0: return vcopyq_laneq_f32(vdst, 0, vsrc, 0);
59 case 1: return vcopyq_laneq_f32(vdst, 0, vsrc, 1);
60 case 2: return vcopyq_laneq_f32(vdst, 0, vsrc, 2);
61 case 3: return vcopyq_laneq_f32(vdst, 0, vsrc, 3);
62 }
63 break;
64 case 1:
65 switch(slane) {
66 default:
67 assert(false); //Unreachable code executed!
68 break;
69 case 0: return vcopyq_laneq_f32(vdst, 1, vsrc, 0);
70 case 1: return vcopyq_laneq_f32(vdst, 1, vsrc, 1);
71 case 2: return vcopyq_laneq_f32(vdst, 1, vsrc, 2);
72 case 3: return vcopyq_laneq_f32(vdst, 1, vsrc, 3);
73 }
74 break;
75 case 2:
76 switch(slane) {
77 default:
78 assert(false); //Unreachable code executed!
79 break;
80 case 0: return vcopyq_laneq_f32(vdst, 2, vsrc, 0);
81 case 1: return vcopyq_laneq_f32(vdst, 2, vsrc, 1);
82 case 2: return vcopyq_laneq_f32(vdst, 2, vsrc, 2);
83 case 3: return vcopyq_laneq_f32(vdst, 2, vsrc, 3);
84 }
85 break;
86 case 3:
87 switch(slane) {
88 default:
89 assert(false); //Unreachable code executed!
90 break;
91 case 0: return vcopyq_laneq_f32(vdst, 3, vsrc, 0);
92 case 1: return vcopyq_laneq_f32(vdst, 3, vsrc, 1);
93 case 2: return vcopyq_laneq_f32(vdst, 3, vsrc, 2);
94 case 3: return vcopyq_laneq_f32(vdst, 3, vsrc, 3);
95 }
96 break;
97 }
98#else
99
100 float l;
101 switch(slane) {
102 default:
103 assert(false); //Unreachable code executed!
104 break;
105 case 0: l = vgetq_lane_f32(vsrc, 0); break;
106 case 1: l = vgetq_lane_f32(vsrc, 1); break;
107 case 2: l = vgetq_lane_f32(vsrc, 2); break;
108 case 3: l = vgetq_lane_f32(vsrc, 3); break;
109 }
110 switch(dlane) {
111 default:
112 assert(false); //Unreachable code executed!
113 break;
114 case 0: return vsetq_lane_f32(l, vdst, 0);
115 case 1: return vsetq_lane_f32(l, vdst, 1);
116 case 2: return vsetq_lane_f32(l, vdst, 2);
117 case 3: return vsetq_lane_f32(l, vdst, 3);
118 }
119#endif
120 return vdupq_n_f32(0.0f);
121 }
122
123 static inline float32x4_t mul_lane(float32x4_t v, float32x4_t vlane, int lane) {
124#if GLM_ARCH & GLM_ARCH_ARMV8_BIT
125 switch(lane) {
126 default:
127 assert(false); //Unreachable code executed!
128 return vdupq_n_f32(0.0f);
129 case 0: return vmulq_laneq_f32(v, vlane, 0); break;
130 case 1: return vmulq_laneq_f32(v, vlane, 1); break;
131 case 2: return vmulq_laneq_f32(v, vlane, 2); break;
132 case 3: return vmulq_laneq_f32(v, vlane, 3); break;
133 }
134#else
135 return vmulq_f32(v, dupq_lane(vlane, lane));
136#endif
137 }
138
139 static inline float32x4_t madd_lane(float32x4_t acc, float32x4_t v, float32x4_t vlane, int lane) {
140#if GLM_ARCH & GLM_ARCH_ARMV8_BIT
141#ifdef GLM_CONFIG_FORCE_FMA
142# define FMADD_LANE(acc, x, y, L) do { asm volatile ("fmla %0.4s, %1.4s, %2.4s" : "+w"(acc) : "w"(x), "w"(dup_lane(y, L))); } while(0)
143#else
144# define FMADD_LANE(acc, x, y, L) do { acc = vmlaq_laneq_f32(acc, x, y, L); } while(0)
145#endif
146
147 switch(lane) {
148 case 0:
149 FMADD_LANE(acc, v, vlane, 0);
150 return acc;
151 case 1:
152 FMADD_LANE(acc, v, vlane, 1);
153 return acc;
154 case 2:
155 FMADD_LANE(acc, v, vlane, 2);
156 return acc;
157 case 3:
158 FMADD_LANE(acc, v, vlane, 3);
159 return acc;
160 default:
161 assert(false); //Unreachable code executed!
162 return vdupq_n_f32(0.0f);
163 }
164# undef FMADD_LANE
165#else
166 return vaddq_f32(acc, vmulq_f32(v, dupq_lane(vlane, lane)));
167#endif
168 }
169 } //namespace neon
170} // namespace glm
171#endif // GLM_ARCH & GLM_ARCH_NEON_BIT