package iron.culling; #if cpp @:include("smmintrin.h") @:include("emmintrin.h") @:include("xmmintrin.h") #end class SimdOps { public static inline function dot4( a0: Float, a1: Float, a2: Float, a3: Float, b0: Float, b1: Float, b2: Float, b3: Float ): Float { #if cpp return untyped __cpp__("_mm_cvtss_f32(_mm_dp_ps(_mm_setr_ps({0}, {1}, {2}, {3}), _mm_setr_ps({4}, {5}, {6}, {7}), 0xF1))", a0, a1, a2, a3, b0, b1, b2, b3); #else return a0 * b0 + a1 * b1 + a2 * b2 + a3 * b3; #end } public static inline function dot3( a0: Float, a1: Float, a2: Float, b0: Float, b1: Float, b2: Float ): Float { #if cpp return untyped __cpp__("_mm_cvtss_f32(_mm_dp_ps(_mm_setr_ps({0}, {1}, {2}, 0.0f), _mm_setr_ps({3}, {4}, {5}, 0.0f), 0x71))", a0, a1, a2, b0, b1, b2); #else return a0 * b0 + a1 * b1 + a2 * b2; #end } public static inline function reciprocal(x: Float): Float { #if cpp return untyped __cpp__("({ auto _r = _mm_rcp_ss(_mm_set_ss({0})); _mm_cvtss_f32(_mm_add_ss(_mm_mul_ss(_r, _mm_sub_ss(_mm_set_ss(2.0f), _mm_mul_ss(_r, _mm_set_ss({0})))), _r)); })", x); #else return 1.0 / x; #end } public static inline function max4f( a: Float, b: Float, c: Float, d: Float ): Float { #if cpp return untyped __cpp__("_mm_cvtss_f32(_mm_max_ss(_mm_max_ss(_mm_set_ss({0}), _mm_set_ss({1})), _mm_max_ss(_mm_set_ss({2}), _mm_set_ss({3}))))", a, b, c, d); #else var m = a; if (b > m) m = b; if (c > m) m = c; if (d > m) m = d; return m; #end } public static inline function min4f( a: Float, b: Float, c: Float, d: Float ): Float { #if cpp return untyped __cpp__("_mm_cvtss_f32(_mm_min_ss(_mm_min_ss(_mm_set_ss({0}), _mm_set_ss({1})), _mm_min_ss(_mm_set_ss({2}), _mm_set_ss({3}))))", a, b, c, d); #else var m = a; if (b < m) m = b; if (c < m) m = c; if (d < m) m = d; return m; #end } public static inline function frustumSphereTest6( planeData: kha.arrays.Float32Array, cx: Float, cy: Float, cz: Float, radius: Float ): Bool { for (i in 0...6) { var base = i * 4; var dist = dot3(cx, cy, cz, planeData[base], planeData[base + 1], planeData[base + 2]) + planeData[base + 3]; if (dist + radius < 0) return false; } return true; } }