Merge pull request #286 from myfreeer/master

WIP: Wasm simd128 support
This commit is contained in:
Recep Aslantas
2023-04-21 16:49:51 +03:00
committed by GitHub
18 changed files with 1283 additions and 47 deletions

97
.github/workflows/cmake-wasm.yml vendored Normal file
View File

@@ -0,0 +1,97 @@
name: CMake WebAssembly
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
env:
wasmtime_version: v7.0.0
wasmer_version: v3.1.1
jobs:
build_wasi_sdk:
strategy:
matrix:
BUILD_TYPE: [Release, Debug, RelWithDebInfo, MinSizeRel]
C_FLAGS: ['', '-msimd128']
wasi_sdk_version: [19, 20]
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
# You can convert this to a matrix build if you need cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Downloading wasi-sdk
run: |
cd ${{github.workspace}}
wget --no-verbose https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${{matrix.wasi_sdk_version}}/wasi-sdk-${{matrix.wasi_sdk_version}}.0-linux.tar.gz
tar xf wasi-sdk-${{matrix.wasi_sdk_version}}.0-linux.tar.gz
- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.BUILD_TYPE}} -DCMAKE_C_FLAGS="${{matrix.C_FLAGS}}" -DCMAKE_TOOLCHAIN_FILE=${{github.workspace}}/wasi-sdk-${{matrix.wasi_sdk_version}}.0/share/cmake/wasi-sdk.cmake -DWASI_SDK_PREFIX=${{github.workspace}}/wasi-sdk-${{matrix.wasi_sdk_version}}.0 -DCGLM_USE_TEST=ON
- name: Build
# Build your program with the given configuration
run: cmake --build ${{github.workspace}}/build --config ${{matrix.BUILD_TYPE}}
- name: Test with wasmtime
run: |
cd ${{github.workspace}}
ls -lh ${{github.workspace}}/build/
wget --no-verbose https://github.com/bytecodealliance/wasmtime/releases/download/${{env.wasmtime_version}}/wasmtime-${{env.wasmtime_version}}-x86_64-linux.tar.xz
tar xf wasmtime-${{env.wasmtime_version}}-x86_64-linux.tar.xz
./wasmtime-${{env.wasmtime_version}}-x86_64-linux/wasmtime run --wasm-features simd ${{github.workspace}}/build/tests
- name: Test with wasmer
run: |
cd ${{github.workspace}}
mkdir wasmer
cd wasmer
wget --no-verbose https://github.com/wasmerio/wasmer/releases/download/${{env.wasmer_version}}/wasmer-linux-amd64.tar.gz
tar xf wasmer-linux-amd64.tar.gz
./bin/wasmer run --enable-simd ${{github.workspace}}/build/tests
build_emsdk:
strategy:
matrix:
BUILD_TYPE: [Release, Debug, RelWithDebInfo, MinSizeRel]
C_FLAGS: ['', '-msimd128', '-msse -msse2 -msimd128', '-msse -msse2 -msse3 -msse4 -msimd128']
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup emsdk
uses: mymindstorm/setup-emsdk@v11
- name: Verify emsdk
run: emcc -v
- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: emcmake cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.BUILD_TYPE}} -DCMAKE_C_FLAGS="${{matrix.C_FLAGS}}" -DCMAKE_EXE_LINKER_FLAGS="-s STANDALONE_WASM" -DCGLM_STATIC=ON -DCGLM_USE_TEST=ON
- name: Build
# Build your program with the given configuration
run: cmake --build ${{github.workspace}}/build --config ${{matrix.BUILD_TYPE}}
- name: Test with wasmtime
run: |
cd ${{github.workspace}}
ls -lh ${{github.workspace}}/build/
wget --no-verbose https://github.com/bytecodealliance/wasmtime/releases/download/${{env.wasmtime_version}}/wasmtime-${{env.wasmtime_version}}-x86_64-linux.tar.xz
tar xf wasmtime-${{env.wasmtime_version}}-x86_64-linux.tar.xz
./wasmtime-${{env.wasmtime_version}}-x86_64-linux/wasmtime run --wasm-features simd ${{github.workspace}}/build/tests.wasm
- name: Test with wasmer
run: |
cd ${{github.workspace}}
mkdir wasmer
cd wasmer
wget --no-verbose https://github.com/wasmerio/wasmer/releases/download/${{env.wasmer_version}}/wasmer-linux-amd64.tar.gz
tar xf wasmer-linux-amd64.tar.gz
./bin/wasmer run --enable-simd ${{github.workspace}}/build/tests.wasm

View File

@@ -16,6 +16,11 @@ option(CGLM_STATIC "Static build" OFF)
option(CGLM_USE_C99 "" OFF)
option(CGLM_USE_TEST "Enable Tests" OFF)
if(CMAKE_SYSTEM_NAME STREQUAL WASI)
set(CGLM_STATIC ON CACHE BOOL "Static option" FORCE)
set(CGLM_SHARED OFF CACHE BOOL "Shared option" FORCE)
endif()
if(NOT CGLM_STATIC AND CGLM_SHARED)
set(CGLM_BUILD SHARED)
else(CGLM_STATIC)

View File

@@ -30,6 +30,10 @@
# include "simd/neon/affine.h"
#endif
#ifdef CGLM_SIMD_WASM
# include "simd/wasm/affine.h"
#endif
/*!
* @brief this is similar to glm_mat4_mul but specialized to affine transform
*
@@ -49,7 +53,9 @@
CGLM_INLINE
void
glm_mul(mat4 m1, mat4 m2, mat4 dest) {
#ifdef __AVX__
#if defined(__wasm__) && defined(__wasm_simd128__)
glm_mul_wasm(m1, m2, dest);
#elif defined(__AVX__)
glm_mul_avx(m1, m2, dest);
#elif defined( __SSE__ ) || defined( __SSE2__ )
glm_mul_sse2(m1, m2, dest);
@@ -107,7 +113,9 @@ glm_mul(mat4 m1, mat4 m2, mat4 dest) {
CGLM_INLINE
void
glm_mul_rot(mat4 m1, mat4 m2, mat4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glm_mul_rot_wasm(m1, m2, dest);
#elif defined( __SSE__ ) || defined( __SSE2__ )
glm_mul_rot_sse2(m1, m2, dest);
#elif defined(CGLM_NEON_FP)
glm_mul_rot_neon(m1, m2, dest);
@@ -156,7 +164,9 @@ glm_mul_rot(mat4 m1, mat4 m2, mat4 dest) {
CGLM_INLINE
void
glm_inv_tr(mat4 mat) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glm_inv_tr_wasm(mat);
#elif defined( __SSE__ ) || defined( __SSE2__ )
glm_inv_tr_sse2(mat);
#elif defined(CGLM_NEON_FP)
glm_inv_tr_neon(mat);

View File

@@ -68,7 +68,10 @@
CGLM_INLINE
void
glm_arch_print_name(FILE* __restrict ostream) {
#ifdef CGLM_SIMD_x86
#if defined(CGLM_SIMD_WASM)
fprintf(ostream, CGLM_PRINT_COLOR "\ncglm arch: wasm SIMD128"
"\n\n" CGLM_PRINT_COLOR_RESET);
#elif defined(CGLM_SIMD_x86)
fprintf(ostream, CGLM_PRINT_COLOR "\ncglm arch: x86 SSE*"
#ifdef __AVX__
" AVX"

View File

@@ -44,6 +44,10 @@
# include "simd/neon/mat2.h"
#endif
#ifdef CGLM_SIMD_WASM
# include "simd/wasm/mat2.h"
#endif
#define GLM_MAT2_IDENTITY_INIT {{1.0f, 0.0f}, {0.0f, 1.0f}}
#define GLM_MAT2_ZERO_INIT {{0.0f, 0.0f}, {0.0f, 0.0f}}
@@ -132,7 +136,9 @@ glm_mat2_zero(mat2 mat) {
CGLM_INLINE
void
glm_mat2_mul(mat2 m1, mat2 m2, mat2 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glm_mat2_mul_wasm(m1, m2, dest);
#elif defined( __SSE__ ) || defined( __SSE2__ )
glm_mat2_mul_sse2(m1, m2, dest);
#elif defined(CGLM_NEON_FP)
glm_mat2_mul_neon(m1, m2, dest);
@@ -160,7 +166,9 @@ glm_mat2_mul(mat2 m1, mat2 m2, mat2 dest) {
CGLM_INLINE
void
glm_mat2_transpose_to(mat2 m, mat2 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glm_mat2_transp_wasm(m, dest);
#elif defined( __SSE__ ) || defined( __SSE2__ )
glm_mat2_transp_sse2(m, dest);
#else
dest[0][0] = m[0][0];
@@ -222,7 +230,10 @@ glm_mat2_trace(mat2 m) {
CGLM_INLINE
void
glm_mat2_scale(mat2 m, float s) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(m[0], wasm_f32x4_mul(wasm_v128_load(m[0]),
wasm_f32x4_splat(s)));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(m[0], _mm_mul_ps(_mm_loadu_ps(m[0]), _mm_set1_ps(s)));
#elif defined(CGLM_NEON_FP)
vst1q_f32(m[0], vmulq_f32(vld1q_f32(m[0]), vdupq_n_f32(s)));

View File

@@ -42,6 +42,10 @@
# include "simd/sse2/mat3.h"
#endif
#ifdef CGLM_SIMD_WASM
# include "simd/wasm/mat3.h"
#endif
#define GLM_MAT3_IDENTITY_INIT {{1.0f, 0.0f, 0.0f}, \
{0.0f, 1.0f, 0.0f}, \
{0.0f, 0.0f, 1.0f}}
@@ -148,7 +152,9 @@ glm_mat3_zero(mat3 mat) {
CGLM_INLINE
void
glm_mat3_mul(mat3 m1, mat3 m2, mat3 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glm_mat3_mul_wasm(m1, m2, dest);
#elif defined( __SSE__ ) || defined( __SSE2__ )
glm_mat3_mul_sse2(m1, m2, dest);
#else
float a00 = m1[0][0], a01 = m1[0][1], a02 = m1[0][2],

View File

@@ -64,6 +64,10 @@
# include "simd/neon/mat4.h"
#endif
#ifdef CGLM_SIMD_WASM
# include "simd/wasm/mat4.h"
#endif
#ifdef DEBUG
# include <assert.h>
#endif
@@ -121,7 +125,12 @@ glm_mat4_ucopy(mat4 mat, mat4 dest) {
CGLM_INLINE
void
glm_mat4_copy(mat4 mat, mat4 dest) {
#ifdef __AVX__
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest[0], glmm_load(mat[0]));
glmm_store(dest[1], glmm_load(mat[1]));
glmm_store(dest[2], glmm_load(mat[2]));
glmm_store(dest[3], glmm_load(mat[3]));
#elif defined(__AVX__)
glmm_store256(dest[0], glmm_load256(mat[0]));
glmm_store256(dest[2], glmm_load256(mat[2]));
#elif defined( __SSE__ ) || defined( __SSE2__ )
@@ -187,7 +196,14 @@ glm_mat4_identity_array(mat4 * __restrict mat, size_t count) {
CGLM_INLINE
void
glm_mat4_zero(mat4 mat) {
#ifdef __AVX__
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_128 x0;
x0 = wasm_f32x4_const_splat(0.f);
glmm_store(mat[0], x0);
glmm_store(mat[1], x0);
glmm_store(mat[2], x0);
glmm_store(mat[3], x0);
#elif defined(__AVX__)
__m256 y0;
y0 = _mm256_setzero_ps();
glmm_store256(mat[0], y0);
@@ -297,7 +313,9 @@ glm_mat4_ins3(mat3 mat, mat4 dest) {
CGLM_INLINE
void
glm_mat4_mul(mat4 m1, mat4 m2, mat4 dest) {
#ifdef __AVX__
#if defined(__wasm__) && defined(__wasm_simd128__)
glm_mat4_mul_wasm(m1, m2, dest);
#elif defined(__AVX__)
glm_mat4_mul_avx(m1, m2, dest);
#elif defined( __SSE__ ) || defined( __SSE2__ )
glm_mat4_mul_sse2(m1, m2, dest);
@@ -377,7 +395,9 @@ glm_mat4_mulN(mat4 * __restrict matrices[], uint32_t len, mat4 dest) {
CGLM_INLINE
void
glm_mat4_mulv(mat4 m, vec4 v, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glm_mat4_mulv_wasm(m, v, dest);
#elif defined( __SSE__ ) || defined( __SSE2__ )
glm_mat4_mulv_sse2(m, v, dest);
#elif defined(CGLM_NEON_FP)
glm_mat4_mulv_neon(m, v, dest);
@@ -497,7 +517,9 @@ glm_mat4_mulv3(mat4 m, vec3 v, float last, vec3 dest) {
CGLM_INLINE
void
glm_mat4_transpose_to(mat4 m, mat4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glm_mat4_transp_wasm(m, dest);
#elif defined( __SSE__ ) || defined( __SSE2__ )
glm_mat4_transp_sse2(m, dest);
#elif defined(CGLM_NEON_FP)
glm_mat4_transp_neon(m, dest);
@@ -521,7 +543,9 @@ glm_mat4_transpose_to(mat4 m, mat4 dest) {
CGLM_INLINE
void
glm_mat4_transpose(mat4 m) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glm_mat4_transp_wasm(m, m);
#elif defined( __SSE__ ) || defined( __SSE2__ )
glm_mat4_transp_sse2(m, m);
#elif defined(CGLM_NEON_FP)
glm_mat4_transp_neon(m, m);
@@ -560,7 +584,9 @@ glm_mat4_scale_p(mat4 m, float s) {
CGLM_INLINE
void
glm_mat4_scale(mat4 m, float s) {
#ifdef __AVX__
#if defined(__wasm__) && defined(__wasm_simd128__)
glm_mat4_scale_wasm(m, s);
#elif defined(__AVX__)
glm_mat4_scale_avx(m, s);
#elif defined( __SSE__ ) || defined( __SSE2__ )
glm_mat4_scale_sse2(m, s);
@@ -581,7 +607,9 @@ glm_mat4_scale(mat4 m, float s) {
CGLM_INLINE
float
glm_mat4_det(mat4 mat) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
return glm_mat4_det_wasm(mat);
#elif defined( __SSE__ ) || defined( __SSE2__ )
return glm_mat4_det_sse2(mat);
#elif defined(CGLM_NEON_FP)
return glm_mat4_det_neon(mat);
@@ -679,7 +707,9 @@ glm_mat4_inv(mat4 mat, mat4 dest) {
CGLM_INLINE
void
glm_mat4_inv_fast(mat4 mat, mat4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glm_mat4_inv_fast_wasm(mat, dest);
#elif defined( __SSE__ ) || defined( __SSE2__ )
glm_mat4_inv_fast_sse2(mat, dest);
#else
glm_mat4_inv(mat, dest);

View File

@@ -70,6 +70,10 @@
# include "simd/neon/quat.h"
#endif
#ifdef CGLM_SIMD_WASM
# include "simd/wasm/quat.h"
#endif
CGLM_INLINE void glm_quat_normalize(versor q);
/*
@@ -238,7 +242,22 @@ glm_quat_norm(versor q) {
CGLM_INLINE
void
glm_quat_normalize_to(versor q, versor dest) {
#if defined( __SSE2__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_128 xdot, x0;
float dot;
x0 = glmm_load(q);
xdot = glmm_vdot(x0, x0);
/* dot = _mm_cvtss_f32(xdot); */
dot = wasm_f32x4_extract_lane(xdot, 0);
if (dot <= 0.0f) {
glm_quat_identity(dest);
return;
}
glmm_store(dest, wasm_f32x4_div(x0, wasm_f32x4_sqrt(xdot)));
#elif defined( __SSE2__ ) || defined( __SSE2__ )
__m128 xdot, x0;
float dot;
@@ -438,7 +457,9 @@ glm_quat_mul(versor p, versor q, versor dest) {
+ (a1 d2 + b1 c2 c1 b2 + d1 a2)k
a1 a2 b1 b2 c1 c2 d1 d2
*/
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glm_quat_mul_wasm(p, q, dest);
#elif defined( __SSE__ ) || defined( __SSE2__ )
glm_quat_mul_sse2(p, q, dest);
#elif defined(CGLM_NEON_FP)
glm_quat_mul_neon(p, q, dest);

View File

@@ -99,13 +99,21 @@
# endif
#endif
#if defined(CGLM_SIMD_x86) || defined(CGLM_SIMD_ARM)
/* WebAssembly */
#if defined(__wasm__) && defined(__wasm_simd128__)
# ifndef CGLM_SIMD_WASM
# define CGLM_SIMD_WASM
# endif
#endif
#if defined(CGLM_SIMD_x86) || defined(CGLM_SIMD_ARM) || defined(CGLM_SIMD_WASM)
# ifndef CGLM_SIMD
# define CGLM_SIMD
# endif
#endif
#if defined(CGLM_SIMD_x86)
#if defined(CGLM_SIMD_x86) && !defined(CGLM_SIMD_WASM)
# include "x86.h"
#endif
@@ -113,4 +121,8 @@
# include "arm.h"
#endif
#if defined(CGLM_SIMD_WASM)
# include "wasm.h"
#endif
#endif /* cglm_intrin_h */

188
include/cglm/simd/wasm.h Normal file
View File

@@ -0,0 +1,188 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglm_simd_wasm_h
#define cglm_simd_wasm_h
#include "intrin.h"
#ifdef CGLM_SIMD_WASM
#include <wasm_simd128.h>
#define glmm_load(p) wasm_v128_load(p)
#define glmm_store(p, a) wasm_v128_store(p, (a))
#define glmm_set1(x) wasm_f32x4_splat(x)
#define glmm_128 v128_t
#define glmm_shuff1(xmm, z, y, x, w) wasm_i32x4_shuffle(xmm, xmm, w, x, y, z)
#define glmm_splat(x, lane) glmm_shuff1(x, lane, lane, lane, lane)
#define glmm_splat_x(x) glmm_splat(x, 0)
#define glmm_splat_y(x) glmm_splat(x, 1)
#define glmm_splat_z(x) glmm_splat(x, 2)
#define glmm_splat_w(x) glmm_splat(x, 3)
static inline
glmm_128
glmm_abs(glmm_128 x) {
return wasm_f32x4_abs(x);
}
static inline
glmm_128
glmm_vhadd(glmm_128 v) {
glmm_128 x0;
x0 = wasm_f32x4_add(v, glmm_shuff1(v, 0, 1, 2, 3));
x0 = wasm_f32x4_add(x0, glmm_shuff1(x0, 1, 0, 0, 1));
return x0;
}
static inline
glmm_128
glmm_vhadds(glmm_128 v) {
glmm_128 shuf, sums;
shuf = glmm_shuff1(v, 2, 3, 0, 1);
sums = wasm_f32x4_add(v, shuf);
/* shuf = _mm_movehl_ps(shuf, sums); */
shuf = wasm_i32x4_shuffle(shuf, sums, 6, 7, 2, 3);
sums = wasm_i32x4_shuffle(sums, wasm_f32x4_add(sums, shuf), 4, 1, 2, 3);
return sums;
}
static inline
float
glmm_hadd(glmm_128 v) {
return wasm_f32x4_extract_lane(glmm_vhadds(v), 0);
}
static inline
glmm_128
glmm_vhmin(glmm_128 v) {
glmm_128 x0, x1, x2;
x0 = glmm_shuff1(v, 2, 3, 2, 3); /* [2, 3, 2, 3] */
x1 = wasm_f32x4_pmin(x0, v); /* [0|2, 1|3, 2|2, 3|3] */
x2 = glmm_splat(x1, 1); /* [1|3, 1|3, 1|3, 1|3] */
return wasm_f32x4_pmin(x1, x2);
}
static inline
float
glmm_hmin(glmm_128 v) {
return wasm_f32x4_extract_lane(glmm_vhmin(v), 0);
}
static inline
glmm_128
glmm_vhmax(glmm_128 v) {
glmm_128 x0, x1, x2;
x0 = glmm_shuff1(v, 2, 3, 2, 3); /* [2, 3, 2, 3] */
x1 = wasm_f32x4_pmax(x0, v); /* [0|2, 1|3, 2|2, 3|3] */
x2 = glmm_splat(x1, 1); /* [1|3, 1|3, 1|3, 1|3] */
/* _mm_max_ss */
return wasm_i32x4_shuffle(x1, wasm_f32x4_pmax(x1, x2), 4, 1, 2, 3);
}
static inline
float
glmm_hmax(glmm_128 v) {
return wasm_f32x4_extract_lane(glmm_vhmax(v), 0);
}
static inline
glmm_128
glmm_vdots(glmm_128 a, glmm_128 b) {
return glmm_vhadds(wasm_f32x4_mul(a, b));
}
static inline
glmm_128
glmm_vdot(glmm_128 a, glmm_128 b) {
glmm_128 x0;
x0 = wasm_f32x4_mul(a, b);
x0 = wasm_f32x4_add(x0, glmm_shuff1(x0, 1, 0, 3, 2));
return wasm_f32x4_add(x0, glmm_shuff1(x0, 0, 1, 0, 1));
}
static inline
float
glmm_dot(glmm_128 a, glmm_128 b) {
return wasm_f32x4_extract_lane(glmm_vdots(a, b), 0);
}
static inline
float
glmm_norm(glmm_128 a) {
glmm_128 x0;
x0 = glmm_vhadds(wasm_f32x4_mul(a, a));
return wasm_f32x4_extract_lane(
wasm_i32x4_shuffle(x0, wasm_f32x4_sqrt(x0),4, 1, 2, 3), 0);
}
static inline
float
glmm_norm2(glmm_128 a) {
return wasm_f32x4_extract_lane(glmm_vhadds(wasm_f32x4_mul(a, a)), 0);
}
static inline
float
glmm_norm_one(glmm_128 a) {
return wasm_f32x4_extract_lane(glmm_vhadds(glmm_abs(a)), 0);
}
static inline
float
glmm_norm_inf(glmm_128 a) {
return wasm_f32x4_extract_lane(glmm_vhmax(glmm_abs(a)), 0);
}
static inline
glmm_128
glmm_load3(float v[3]) {
glmm_128 xy = wasm_v128_load64_zero(v);
return wasm_f32x4_replace_lane(xy, 2, v[2]);
}
static inline
void
glmm_store3(float v[3], glmm_128 vx) {
wasm_v128_store64_lane(v, vx, 0);
wasm_v128_store32_lane(&v[2], vx, 2);
}
static inline
glmm_128
glmm_div(glmm_128 a, glmm_128 b) {
return wasm_f32x4_div(a, b);
}
static inline
glmm_128
glmm_fmadd(glmm_128 a, glmm_128 b, glmm_128 c) {
return wasm_f32x4_add(c, wasm_f32x4_mul(a, b));
}
static inline
glmm_128
glmm_fnmadd(glmm_128 a, glmm_128 b, glmm_128 c) {
return wasm_f32x4_sub(c, wasm_f32x4_mul(a, b));
}
static inline
glmm_128
glmm_fmsub(glmm_128 a, glmm_128 b, glmm_128 c) {
return wasm_f32x4_sub(wasm_f32x4_mul(a, b), c);
}
static inline
glmm_128
glmm_fnmsub(glmm_128 a, glmm_128 b, glmm_128 c) {
return wasm_f32x4_neg(wasm_f32x4_add(wasm_f32x4_mul(a, b), c));
}
#endif
#endif /* cglm_simd_wasm_h */

View File

@@ -0,0 +1,127 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglm_affine_mat_wasm_h
#define cglm_affine_mat_wasm_h
#if defined(__wasm__) && defined(__wasm_simd128__)
#include "../../common.h"
#include "../intrin.h"
CGLM_INLINE
void
glm_mul_wasm(mat4 m1, mat4 m2, mat4 dest) {
/* D = R * L (Column-Major) */
glmm_128 l, r0, r1, r2, r3, v0, v1, v2, v3;
l = glmm_load(m1[0]);
r0 = glmm_load(m2[0]);
r1 = glmm_load(m2[1]);
r2 = glmm_load(m2[2]);
r3 = glmm_load(m2[3]);
v0 = wasm_f32x4_mul(glmm_splat_x(r0), l);
v1 = wasm_f32x4_mul(glmm_splat_x(r1), l);
v2 = wasm_f32x4_mul(glmm_splat_x(r2), l);
v3 = wasm_f32x4_mul(glmm_splat_x(r3), l);
l = glmm_load(m1[1]);
v0 = glmm_fmadd(glmm_splat_y(r0), l, v0);
v1 = glmm_fmadd(glmm_splat_y(r1), l, v1);
v2 = glmm_fmadd(glmm_splat_y(r2), l, v2);
v3 = glmm_fmadd(glmm_splat_y(r3), l, v3);
l = glmm_load(m1[2]);
v0 = glmm_fmadd(glmm_splat_z(r0), l, v0);
v1 = glmm_fmadd(glmm_splat_z(r1), l, v1);
v2 = glmm_fmadd(glmm_splat_z(r2), l, v2);
v3 = glmm_fmadd(glmm_splat_z(r3), l, v3);
l = glmm_load(m1[3]);
v3 = glmm_fmadd(glmm_splat_w(r3), l, v3);
glmm_store(dest[0], v0);
glmm_store(dest[1], v1);
glmm_store(dest[2], v2);
glmm_store(dest[3], v3);
}
CGLM_INLINE
void
glm_mul_rot_wasm(mat4 m1, mat4 m2, mat4 dest) {
/* D = R * L (Column-Major) */
glmm_128 l, r0, r1, r2, v0, v1, v2;
l = glmm_load(m1[0]);
r0 = glmm_load(m2[0]);
r1 = glmm_load(m2[1]);
r2 = glmm_load(m2[2]);
v0 = wasm_f32x4_mul(glmm_splat_x(r0), l);
v1 = wasm_f32x4_mul(glmm_splat_x(r1), l);
v2 = wasm_f32x4_mul(glmm_splat_x(r2), l);
l = glmm_load(m1[1]);
v0 = glmm_fmadd(glmm_splat_y(r0), l, v0);
v1 = glmm_fmadd(glmm_splat_y(r1), l, v1);
v2 = glmm_fmadd(glmm_splat_y(r2), l, v2);
l = glmm_load(m1[2]);
v0 = glmm_fmadd(glmm_splat_z(r0), l, v0);
v1 = glmm_fmadd(glmm_splat_z(r1), l, v1);
v2 = glmm_fmadd(glmm_splat_z(r2), l, v2);
glmm_store(dest[0], v0);
glmm_store(dest[1], v1);
glmm_store(dest[2], v2);
glmm_store(dest[3], glmm_load(m1[3]));
}
CGLM_INLINE
void
glm_inv_tr_wasm(mat4 mat) {
glmm_128 r0, r1, r2, r3, x0, x1, x2, x3, x4, x5;
r0 = glmm_load(mat[0]);
r1 = glmm_load(mat[1]);
r2 = glmm_load(mat[2]);
r3 = glmm_load(mat[3]);
x1 = wasm_f32x4_const(0.0f, 0.0f, 0.0f, 1.0f);
/* _MM_TRANSPOSE4_PS(r0, r1, r2, x1); */
x2 = wasm_i32x4_shuffle(r0, r1, 0, 4, 1, 5);
x3 = wasm_i32x4_shuffle(r0, r1, 2, 6, 3, 7);
x4 = wasm_i32x4_shuffle(r2, x1, 0, 4, 1, 5);
x5 = wasm_i32x4_shuffle(r2, x1, 2, 6, 3, 7);
/* r0 = _mm_movelh_ps(x2, x4); */
r0 = wasm_i32x4_shuffle(x2, x4, 0, 1, 4, 5);
/* r1 = _mm_movehl_ps(x4, x2); */
r1 = wasm_i32x4_shuffle(x4, x2, 6, 7, 2, 3);
/* r2 = _mm_movelh_ps(x3, x5); */
r2 = wasm_i32x4_shuffle(x3, x5, 0, 1, 4, 5);
/* x1 = _mm_movehl_ps(x5, x3); */
x1 = wasm_i32x4_shuffle(x5, x3, 6, 7, 2, 3);
x2 = glmm_shuff1(r3, 0, 0, 0, 0);
x3 = glmm_shuff1(r3, 1, 1, 1, 1);
x4 = glmm_shuff1(r3, 2, 2, 2, 2);
x0 = glmm_fmadd(r0, x2,
glmm_fmadd(r1, x3, wasm_f32x4_mul(r2, x4)));
x0 = wasm_f32x4_neg(x0);
x0 = wasm_f32x4_add(x0, x1);
glmm_store(mat[0], r0);
glmm_store(mat[1], r1);
glmm_store(mat[2], r2);
glmm_store(mat[3], x0);
}
#endif
#endif /* cglm_affine_mat_wasm_h */

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglm_mat2_wasm_h
#define cglm_mat2_wasm_h
#if defined(__wasm__) && defined(__wasm_simd128__)
#include "../../common.h"
#include "../intrin.h"
CGLM_INLINE
void
glm_mat2_mul_wasm(mat2 m1, mat2 m2, mat2 dest) {
glmm_128 x0, x1, x2, x3, x4;
x1 = glmm_load(m1[0]); /* d c b a */
x2 = glmm_load(m2[0]); /* h g f e */
x3 = glmm_shuff1(x2, 2, 2, 0, 0);
x4 = glmm_shuff1(x2, 3, 3, 1, 1);
/* x0 = _mm_movelh_ps(x1, x1); */
x0 = wasm_i32x4_shuffle(x1, x1, 0, 1, 4, 5);
/* x2 = _mm_movehl_ps(x1, x1); */
x2 = wasm_i32x4_shuffle(x1, x1, 6, 7, 2, 3);
/*
dest[0][0] = a * e + c * f;
dest[0][1] = b * e + d * f;
dest[1][0] = a * g + c * h;
dest[1][1] = b * g + d * h;
*/
x0 = glmm_fmadd(x0, x3, wasm_f32x4_mul(x2, x4));
glmm_store(dest[0], x0);
}
CGLM_INLINE
void
glm_mat2_transp_wasm(mat2 m, mat2 dest) {
/* d c b a */
/* d b c a */
glmm_store(dest[0], glmm_shuff1(glmm_load(m[0]), 3, 1, 2, 0));
}
#endif
#endif /* cglm_mat2_wasm_h */

View File

@@ -0,0 +1,85 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglm_mat3_wasm_h
#define cglm_mat3_wasm_h
#if defined(__wasm__) && defined(__wasm_simd128__)
#include "../../common.h"
#include "../intrin.h"
CGLM_INLINE
void
glm_mat3_mul_wasm(mat3 m1, mat3 m2, mat3 dest) {
glmm_128 l0, l1, l2, r0, r1, r2, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9;
l0 = wasm_v128_load(m1[0]);
l1 = wasm_v128_load(&m1[1][1]);
r0 = wasm_v128_load(m2[0]);
r1 = wasm_v128_load(&m2[1][1]);
x8 = glmm_shuff1(l0, 0, 2, 1, 0); /* a00 a02 a01 a00 */
x1 = glmm_shuff1(r0, 3, 0, 0, 0); /* b10 b00 b00 b00 */
x2 = wasm_i32x4_shuffle(l0, l1, 3, 3, 4, 5); /* a12 a11 a10 a10 */
x3 = wasm_i32x4_shuffle(r0, r1, 1, 3, 4, 6); /* b20 b11 b10 b01 */
x0 = wasm_f32x4_mul(x8, x1);
x6 = glmm_shuff1(l0, 1, 0, 2, 1); /* a01 a00 a02 a01 */
x7 = glmm_shuff1(x3, 3, 3, 1, 1); /* b20 b20 b10 b10 */
l2 = wasm_v128_load32_zero(&m1[2][2]);
r2 = wasm_v128_load32_zero(&m2[2][2]);
x1 = wasm_f32x4_mul(x6, x7);
l2 = glmm_shuff1(l2, 0, 0, 1, 0); /* a22 a22 0.f a22 */
r2 = glmm_shuff1(r2, 0, 0, 1, 0); /* b22 b22 0.f b22 */
x4 = glmm_shuff1(x2, 0, 3, 2, 0); /* a10 a12 a11 a10 */
x5 = glmm_shuff1(x2, 2, 0, 3, 2); /* a11 a10 a12 a11 */
x6 = glmm_shuff1(x3, 2, 0, 0, 0); /* b11 b01 b01 b01 */
x2 = glmm_shuff1(r1, 3, 3, 0, 0); /* b21 b21 b11 b11 */
/* x8 = _mm_unpackhi_ps(x8, x4); */
/* x9 = _mm_unpackhi_ps(x7, x2); */
x8 = wasm_i32x4_shuffle(x8, x4, 2, 6, 3, 7); /* a10 a00 a12 a02 */
x9 = wasm_i32x4_shuffle(x7, x2, 2, 6, 3, 7); /* b21 b20 b21 b20 */
x0 = glmm_fmadd(x4, x6, x0);
x1 = glmm_fmadd(x5, x2, x1);
/* x2 = _mm_movehl_ps(l2, l1); */
x2 = wasm_i32x4_shuffle(l2, l1, 6, 7, 2, 3); /* a22 a22 a21 a20 */
x3 = glmm_shuff1(x2, 0, 2, 1, 0); /* a20 a22 a21 a20 */
x2 = glmm_shuff1(x2, 1, 0, 2, 1); /* a21 a20 a22 a21 */
x4 = wasm_i32x4_shuffle(r0, r1, 2, 2, 5, 5); /* b12 b12 b02 b02 */
x5 = glmm_shuff1(x4, 3, 0, 0, 0); /* b12 b02 b02 b02 */
/* x4 = _mm_movehl_ps(r2, x4); */
x4 = wasm_i32x4_shuffle(r2, x4, 6, 7, 2, 3); /* b22 b22 b12 b12 */
x0 = glmm_fmadd(x3, x5, x0);
x1 = glmm_fmadd(x2, x4, x1);
/*
Dot Product : dest[2][2] = a02 * b20 +
a12 * b21 +
a22 * b22 +
0 * 00 */
/* x2 = _mm_movelh_ps(x8, l2); */
/* x3 = _mm_movelh_ps(x9, r2); */
x2 = wasm_i32x4_shuffle(x8, l2, 0, 1, 4, 5); /* 0.f a22 a12 a02 */
x3 = wasm_i32x4_shuffle(x9, r2, 0, 1, 4, 5); /* 0.f b22 b21 b20 */
x2 = glmm_vdots(x2, x3);
/* _mm_storeu_ps(&dest[0][0], x0); */
wasm_v128_store(&dest[0][0], x0);
/* _mm_storeu_ps(&dest[1][1], x1); */
wasm_v128_store(&dest[1][1], x1);
/* _mm_store_ss (&dest[2][2], x2); */
wasm_v128_store32_lane(&dest[2][2], x2, 0);
}
#endif
#endif /* cglm_mat3_wasm_h */

View File

@@ -0,0 +1,452 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglm_mat_wasm_h
#define cglm_mat_wasm_h
#if defined(__wasm__) && defined(__wasm_simd128__)
#include "../../common.h"
#include "../intrin.h"
#define glm_mat4_inv_precise_wasm(mat, dest) glm_mat4_inv_wasm(mat, dest)
CGLM_INLINE
void
glm_mat4_scale_wasm(mat4 m, float s) {
glmm_128 x0;
x0 = wasm_f32x4_splat(s);
glmm_store(m[0], wasm_f32x4_mul(glmm_load(m[0]), x0));
glmm_store(m[1], wasm_f32x4_mul(glmm_load(m[1]), x0));
glmm_store(m[2], wasm_f32x4_mul(glmm_load(m[2]), x0));
glmm_store(m[3], wasm_f32x4_mul(glmm_load(m[3]), x0));
}
CGLM_INLINE
void
glm_mat4_transp_wasm(mat4 m, mat4 dest) {
glmm_128 r0, r1, r2, r3, tmp0, tmp1, tmp2, tmp3;
r0 = glmm_load(m[0]);
r1 = glmm_load(m[1]);
r2 = glmm_load(m[2]);
r3 = glmm_load(m[3]);
/* _MM_TRANSPOSE4_PS(r0, r1, r2, r3); */
tmp0 = wasm_i32x4_shuffle(r0, r1, 0, 4, 1, 5);
tmp1 = wasm_i32x4_shuffle(r0, r1, 2, 6, 3, 7);
tmp2 = wasm_i32x4_shuffle(r2, r3, 0, 4, 1, 5);
tmp3 = wasm_i32x4_shuffle(r2, r3, 2, 6, 3, 7);
/* r0 = _mm_movelh_ps(tmp0, tmp2); */
r0 = wasm_i32x4_shuffle(tmp0, tmp2, 0, 1, 4, 5);
/* r1 = _mm_movehl_ps(tmp2, tmp0); */
r1 = wasm_i32x4_shuffle(tmp2, tmp0, 6, 7, 2, 3);
/* r2 = _mm_movelh_ps(tmp1, tmp3); */
r2 = wasm_i32x4_shuffle(tmp1, tmp3, 0, 1, 4, 5);
/* r3 = _mm_movehl_ps(tmp3, tmp1); */
r3 = wasm_i32x4_shuffle(tmp3, tmp1, 6, 7, 2, 3);
glmm_store(dest[0], r0);
glmm_store(dest[1], r1);
glmm_store(dest[2], r2);
glmm_store(dest[3], r3);
}
CGLM_INLINE
void
glm_mat4_mul_wasm(mat4 m1, mat4 m2, mat4 dest) {
/* D = R * L (Column-Major) */
glmm_128 l, r0, r1, r2, r3, v0, v1, v2, v3;
l = glmm_load(m1[0]);
r0 = glmm_load(m2[0]);
r1 = glmm_load(m2[1]);
r2 = glmm_load(m2[2]);
r3 = glmm_load(m2[3]);
v0 = wasm_f32x4_mul(glmm_splat_x(r0), l);
v1 = wasm_f32x4_mul(glmm_splat_x(r1), l);
v2 = wasm_f32x4_mul(glmm_splat_x(r2), l);
v3 = wasm_f32x4_mul(glmm_splat_x(r3), l);
l = glmm_load(m1[1]);
v0 = glmm_fmadd(glmm_splat_y(r0), l, v0);
v1 = glmm_fmadd(glmm_splat_y(r1), l, v1);
v2 = glmm_fmadd(glmm_splat_y(r2), l, v2);
v3 = glmm_fmadd(glmm_splat_y(r3), l, v3);
l = glmm_load(m1[2]);
v0 = glmm_fmadd(glmm_splat_z(r0), l, v0);
v1 = glmm_fmadd(glmm_splat_z(r1), l, v1);
v2 = glmm_fmadd(glmm_splat_z(r2), l, v2);
v3 = glmm_fmadd(glmm_splat_z(r3), l, v3);
l = glmm_load(m1[3]);
v0 = glmm_fmadd(glmm_splat_w(r0), l, v0);
v1 = glmm_fmadd(glmm_splat_w(r1), l, v1);
v2 = glmm_fmadd(glmm_splat_w(r2), l, v2);
v3 = glmm_fmadd(glmm_splat_w(r3), l, v3);
glmm_store(dest[0], v0);
glmm_store(dest[1], v1);
glmm_store(dest[2], v2);
glmm_store(dest[3], v3);
}
CGLM_INLINE
void
glm_mat4_mulv_wasm(mat4 m, vec4 v, vec4 dest) {
glmm_128 x0, x1, m0, m1, m2, m3, v0, v1, v2, v3;
m0 = glmm_load(m[0]);
m1 = glmm_load(m[1]);
m2 = glmm_load(m[2]);
m3 = glmm_load(m[3]);
x0 = glmm_load(v);
v0 = glmm_splat_x(x0);
v1 = glmm_splat_y(x0);
v2 = glmm_splat_z(x0);
v3 = glmm_splat_w(x0);
x1 = wasm_f32x4_mul(m3, v3);
x1 = glmm_fmadd(m2, v2, x1);
x1 = glmm_fmadd(m1, v1, x1);
x1 = glmm_fmadd(m0, v0, x1);
glmm_store(dest, x1);
}
CGLM_INLINE
float
glm_mat4_det_wasm(mat4 mat) {
glmm_128 r0, r1, r2, r3, x0, x1, x2;
/* 127 <- 0, [square] det(A) = det(At) */
r0 = glmm_load(mat[0]); /* d c b a */
r1 = glmm_load(mat[1]); /* h g f e */
r2 = glmm_load(mat[2]); /* l k j i */
r3 = glmm_load(mat[3]); /* p o n m */
/*
t[1] = j * p - n * l;
t[2] = j * o - n * k;
t[3] = i * p - m * l;
t[4] = i * o - m * k;
*/
x0 = glmm_fnmadd(glmm_shuff1(r3, 0, 0, 1, 1), glmm_shuff1(r2, 2, 3, 2, 3),
wasm_f32x4_mul(glmm_shuff1(r2, 0, 0, 1, 1),
glmm_shuff1(r3, 2, 3, 2, 3)));
/*
t[0] = k * p - o * l;
t[0] = k * p - o * l;
t[5] = i * n - m * j;
t[5] = i * n - m * j;
*/
x1 = glmm_fnmadd(glmm_shuff1(r3, 0, 0, 2, 2), glmm_shuff1(r2, 1, 1, 3, 3),
wasm_f32x4_mul(glmm_shuff1(r2, 0, 0, 2, 2),
glmm_shuff1(r3, 1, 1, 3, 3)));
/*
a * (f * t[0] - g * t[1] + h * t[2])
- b * (e * t[0] - g * t[3] + h * t[4])
+ c * (e * t[1] - f * t[3] + h * t[5])
- d * (e * t[2] - f * t[4] + g * t[5])
*/
x2 = glmm_fnmadd(glmm_shuff1(r1, 1, 1, 2, 2), glmm_shuff1(x0, 3, 2, 2, 0),
wasm_f32x4_mul(glmm_shuff1(r1, 0, 0, 0, 1),
wasm_i32x4_shuffle(x1, x0, 0, 0, 4, 5)));
x2 = glmm_fmadd(glmm_shuff1(r1, 2, 3, 3, 3),
wasm_i32x4_shuffle(x0, x1, 1, 3, 6, 6),
x2);
x2 = wasm_v128_xor(x2, wasm_f32x4_const(0.f, -0.f, 0.f, -0.f));
return glmm_hadd(wasm_f32x4_mul(x2, r0));
}
CGLM_INLINE
void
glm_mat4_inv_fast_wasm(mat4 mat, mat4 dest) {
glmm_128 r0, r1, r2, r3,
v0, v1, v2, v3,
t0, t1, t2, t3, t4, t5,
x0, x1, x2, x3, x4, x5, x6, x7, x8, x9;
x8 = wasm_f32x4_const(0.f, -0.f, 0.f, -0.f);
x9 = glmm_shuff1(x8, 2, 1, 2, 1);
/* 127 <- 0 */
r0 = glmm_load(mat[0]); /* d c b a */
r1 = glmm_load(mat[1]); /* h g f e */
r2 = glmm_load(mat[2]); /* l k j i */
r3 = glmm_load(mat[3]); /* p o n m */
/* x0 = _mm_movehl_ps(r3, r2); */
x0 = wasm_i32x4_shuffle(r3, r2, 6, 7, 2, 3); /* p o l k */
/* x3 = _mm_movelh_ps(r2, r3); */
x3 = wasm_i32x4_shuffle(r2, r3, 0, 1, 4, 5); /* n m j i */
x1 = glmm_shuff1(x0, 1, 3, 3 ,3); /* l p p p */
x2 = glmm_shuff1(x0, 0, 2, 2, 2); /* k o o o */
x4 = glmm_shuff1(x3, 1, 3, 3, 3); /* j n n n */
x7 = glmm_shuff1(x3, 0, 2, 2, 2); /* i m m m */
x6 = wasm_i32x4_shuffle(r2, r1, 0, 0, 4, 4); /* e e i i */
x5 = wasm_i32x4_shuffle(r2, r1, 1, 1, 5, 5); /* f f j j */
x3 = wasm_i32x4_shuffle(r2, r1, 2, 2, 6, 6); /* g g k k */
x0 = wasm_i32x4_shuffle(r2, r1, 3, 3, 7, 7); /* h h l l */
t0 = wasm_f32x4_mul(x3, x1);
t1 = wasm_f32x4_mul(x5, x1);
t2 = wasm_f32x4_mul(x5, x2);
t3 = wasm_f32x4_mul(x6, x1);
t4 = wasm_f32x4_mul(x6, x2);
t5 = wasm_f32x4_mul(x6, x4);
/* t1[0] = k * p - o * l;
t1[0] = k * p - o * l;
t2[0] = g * p - o * h;
t3[0] = g * l - k * h; */
t0 = glmm_fnmadd(x2, x0, t0);
/* t1[1] = j * p - n * l;
t1[1] = j * p - n * l;
t2[1] = f * p - n * h;
t3[1] = f * l - j * h; */
t1 = glmm_fnmadd(x4, x0, t1);
/* t1[2] = j * o - n * k
t1[2] = j * o - n * k;
t2[2] = f * o - n * g;
t3[2] = f * k - j * g; */
t2 = glmm_fnmadd(x4, x3, t2);
/* t1[3] = i * p - m * l;
t1[3] = i * p - m * l;
t2[3] = e * p - m * h;
t3[3] = e * l - i * h; */
t3 = glmm_fnmadd(x7, x0, t3);
/* t1[4] = i * o - m * k;
t1[4] = i * o - m * k;
t2[4] = e * o - m * g;
t3[4] = e * k - i * g; */
t4 = glmm_fnmadd(x7, x3, t4);
/* t1[5] = i * n - m * j;
t1[5] = i * n - m * j;
t2[5] = e * n - m * f;
t3[5] = e * j - i * f; */
t5 = glmm_fnmadd(x7, x5, t5);
/* x4 = _mm_movelh_ps(r0, r1); */
x4 = wasm_i32x4_shuffle(r0, r1, 0, 1, 4, 5); /* f e b a */
/* x5 = _mm_movehl_ps(r1, r0); */
x5 = wasm_i32x4_shuffle(r1, r0, 6, 7, 2, 3); /* h g d c */
x0 = glmm_shuff1(x4, 0, 0, 0, 2); /* a a a e */
x1 = glmm_shuff1(x4, 1, 1, 1, 3); /* b b b f */
x2 = glmm_shuff1(x5, 0, 0, 0, 2); /* c c c g */
x3 = glmm_shuff1(x5, 1, 1, 1, 3); /* d d d h */
v2 = wasm_f32x4_mul(x0, t1);
v1 = wasm_f32x4_mul(x0, t0);
v3 = wasm_f32x4_mul(x0, t2);
v0 = wasm_f32x4_mul(x1, t0);
v2 = glmm_fnmadd(x1, t3, v2);
v3 = glmm_fnmadd(x1, t4, v3);
v0 = glmm_fnmadd(x2, t1, v0);
v1 = glmm_fnmadd(x2, t3, v1);
v3 = glmm_fmadd(x2, t5, v3);
v0 = glmm_fmadd(x3, t2, v0);
v2 = glmm_fmadd(x3, t5, v2);
v1 = glmm_fmadd(x3, t4, v1);
/*
dest[0][0] = f * t1[0] - g * t1[1] + h * t1[2];
dest[0][1] =-(b * t1[0] - c * t1[1] + d * t1[2]);
dest[0][2] = b * t2[0] - c * t2[1] + d * t2[2];
dest[0][3] =-(b * t3[0] - c * t3[1] + d * t3[2]); */
v0 = wasm_v128_xor(v0, x8);
/*
dest[2][0] = e * t1[1] - f * t1[3] + h * t1[5];
dest[2][1] =-(a * t1[1] - b * t1[3] + d * t1[5]);
dest[2][2] = a * t2[1] - b * t2[3] + d * t2[5];
dest[2][3] =-(a * t3[1] - b * t3[3] + d * t3[5]);*/
v2 = wasm_v128_xor(v2, x8);
/*
dest[1][0] =-(e * t1[0] - g * t1[3] + h * t1[4]);
dest[1][1] = a * t1[0] - c * t1[3] + d * t1[4];
dest[1][2] =-(a * t2[0] - c * t2[3] + d * t2[4]);
dest[1][3] = a * t3[0] - c * t3[3] + d * t3[4]; */
v1 = wasm_v128_xor(v1, x9);
/*
dest[3][0] =-(e * t1[2] - f * t1[4] + g * t1[5]);
dest[3][1] = a * t1[2] - b * t1[4] + c * t1[5];
dest[3][2] =-(a * t2[2] - b * t2[4] + c * t2[5]);
dest[3][3] = a * t3[2] - b * t3[4] + c * t3[5]; */
v3 = wasm_v128_xor(v3, x9);
/* determinant */
x0 = wasm_i32x4_shuffle(v0, v1, 0, 0, 4, 4);
x1 = wasm_i32x4_shuffle(v2, v3, 0, 0, 4, 4);
x0 = wasm_i32x4_shuffle(x0, x1, 0, 2, 4, 6);
/* x0 = _mm_rcp_ps(glmm_vhadd(wasm_f32x4_mul(x0, r0))); */
x0 = wasm_f32x4_div(wasm_f32x4_const_splat(1.0f),
glmm_vhadd(wasm_f32x4_mul(x0, r0)));
glmm_store(dest[0], wasm_f32x4_mul(v0, x0));
glmm_store(dest[1], wasm_f32x4_mul(v1, x0));
glmm_store(dest[2], wasm_f32x4_mul(v2, x0));
glmm_store(dest[3], wasm_f32x4_mul(v3, x0));
}
CGLM_INLINE
void
glm_mat4_inv_wasm(mat4 mat, mat4 dest) {
glmm_128 r0, r1, r2, r3,
v0, v1, v2, v3,
t0, t1, t2, t3, t4, t5,
x0, x1, x2, x3, x4, x5, x6, x7, x8, x9;
x8 = wasm_f32x4_const(0.f, -0.f, 0.f, -0.f);
x9 = glmm_shuff1(x8, 2, 1, 2, 1);
/* 127 <- 0 */
r0 = glmm_load(mat[0]); /* d c b a */
r1 = glmm_load(mat[1]); /* h g f e */
r2 = glmm_load(mat[2]); /* l k j i */
r3 = glmm_load(mat[3]); /* p o n m */
/* x0 = _mm_movehl_ps(r3, r2); */
x0 = wasm_i32x4_shuffle(r3, r2, 6, 7, 2, 3); /* p o l k */
/* x3 = _mm_movelh_ps(r2, r3); */
x3 = wasm_i32x4_shuffle(r2, r3, 0, 1, 4, 5); /* n m j i */
x1 = glmm_shuff1(x0, 1, 3, 3 ,3); /* l p p p */
x2 = glmm_shuff1(x0, 0, 2, 2, 2); /* k o o o */
x4 = glmm_shuff1(x3, 1, 3, 3, 3); /* j n n n */
x7 = glmm_shuff1(x3, 0, 2, 2, 2); /* i m m m */
x6 = wasm_i32x4_shuffle(r2, r1, 0, 0, 4, 4); /* e e i i */
x5 = wasm_i32x4_shuffle(r2, r1, 1, 1, 5, 5); /* f f j j */
x3 = wasm_i32x4_shuffle(r2, r1, 2, 2, 6, 6); /* g g k k */
x0 = wasm_i32x4_shuffle(r2, r1, 3, 3, 7, 7); /* h h l l */
t0 = wasm_f32x4_mul(x3, x1);
t1 = wasm_f32x4_mul(x5, x1);
t2 = wasm_f32x4_mul(x5, x2);
t3 = wasm_f32x4_mul(x6, x1);
t4 = wasm_f32x4_mul(x6, x2);
t5 = wasm_f32x4_mul(x6, x4);
/* t1[0] = k * p - o * l;
t1[0] = k * p - o * l;
t2[0] = g * p - o * h;
t3[0] = g * l - k * h; */
t0 = glmm_fnmadd(x2, x0, t0);
/* t1[1] = j * p - n * l;
t1[1] = j * p - n * l;
t2[1] = f * p - n * h;
t3[1] = f * l - j * h; */
t1 = glmm_fnmadd(x4, x0, t1);
/* t1[2] = j * o - n * k
t1[2] = j * o - n * k;
t2[2] = f * o - n * g;
t3[2] = f * k - j * g; */
t2 = glmm_fnmadd(x4, x3, t2);
/* t1[3] = i * p - m * l;
t1[3] = i * p - m * l;
t2[3] = e * p - m * h;
t3[3] = e * l - i * h; */
t3 = glmm_fnmadd(x7, x0, t3);
/* t1[4] = i * o - m * k;
t1[4] = i * o - m * k;
t2[4] = e * o - m * g;
t3[4] = e * k - i * g; */
t4 = glmm_fnmadd(x7, x3, t4);
/* t1[5] = i * n - m * j;
t1[5] = i * n - m * j;
t2[5] = e * n - m * f;
t3[5] = e * j - i * f; */
t5 = glmm_fnmadd(x7, x5, t5);
/* x4 = _mm_movelh_ps(r0, r1); */
x4 = wasm_i32x4_shuffle(r0, r1, 0, 1, 4, 5); /* f e b a */
/* x5 = _mm_movehl_ps(r1, r0); */
x5 = wasm_i32x4_shuffle(r1, r0, 6, 7, 2, 3); /* h g d c */
x0 = glmm_shuff1(x4, 0, 0, 0, 2); /* a a a e */
x1 = glmm_shuff1(x4, 1, 1, 1, 3); /* b b b f */
x2 = glmm_shuff1(x5, 0, 0, 0, 2); /* c c c g */
x3 = glmm_shuff1(x5, 1, 1, 1, 3); /* d d d h */
v2 = wasm_f32x4_mul(x0, t1);
v1 = wasm_f32x4_mul(x0, t0);
v3 = wasm_f32x4_mul(x0, t2);
v0 = wasm_f32x4_mul(x1, t0);
v2 = glmm_fnmadd(x1, t3, v2);
v3 = glmm_fnmadd(x1, t4, v3);
v0 = glmm_fnmadd(x2, t1, v0);
v1 = glmm_fnmadd(x2, t3, v1);
v3 = glmm_fmadd(x2, t5, v3);
v0 = glmm_fmadd(x3, t2, v0);
v2 = glmm_fmadd(x3, t5, v2);
v1 = glmm_fmadd(x3, t4, v1);
/*
dest[0][0] = f * t1[0] - g * t1[1] + h * t1[2];
dest[0][1] =-(b * t1[0] - c * t1[1] + d * t1[2]);
dest[0][2] = b * t2[0] - c * t2[1] + d * t2[2];
dest[0][3] =-(b * t3[0] - c * t3[1] + d * t3[2]); */
v0 = wasm_v128_xor(v0, x8);
/*
dest[2][0] = e * t1[1] - f * t1[3] + h * t1[5];
dest[2][1] =-(a * t1[1] - b * t1[3] + d * t1[5]);
dest[2][2] = a * t2[1] - b * t2[3] + d * t2[5];
dest[2][3] =-(a * t3[1] - b * t3[3] + d * t3[5]);*/
v2 = wasm_v128_xor(v2, x8);
/*
dest[1][0] =-(e * t1[0] - g * t1[3] + h * t1[4]);
dest[1][1] = a * t1[0] - c * t1[3] + d * t1[4];
dest[1][2] =-(a * t2[0] - c * t2[3] + d * t2[4]);
dest[1][3] = a * t3[0] - c * t3[3] + d * t3[4]; */
v1 = wasm_v128_xor(v1, x9);
/*
dest[3][0] =-(e * t1[2] - f * t1[4] + g * t1[5]);
dest[3][1] = a * t1[2] - b * t1[4] + c * t1[5];
dest[3][2] =-(a * t2[2] - b * t2[4] + c * t2[5]);
dest[3][3] = a * t3[2] - b * t3[4] + c * t3[5]; */
v3 = wasm_v128_xor(v3, x9);
/* determinant */
x0 = wasm_i32x4_shuffle(v0, v1, 0, 0, 4, 4);
x1 = wasm_i32x4_shuffle(v2, v3, 0, 0, 4, 4);
x0 = wasm_i32x4_shuffle(x0, x1, 0, 2, 4, 6);
x0 = wasm_f32x4_div(wasm_f32x4_splat(1.0f), glmm_vhadd(wasm_f32x4_mul(x0, r0)));
glmm_store(dest[0], wasm_f32x4_mul(v0, x0));
glmm_store(dest[1], wasm_f32x4_mul(v1, x0));
glmm_store(dest[2], wasm_f32x4_mul(v2, x0));
glmm_store(dest[3], wasm_f32x4_mul(v3, x0));
}
#endif
#endif /* cglm_mat_wasm_h */

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglm_quat_wasm_h
#define cglm_quat_wasm_h
#if defined(__wasm__) && defined(__wasm_simd128__)
#include "../../common.h"
#include "../intrin.h"
CGLM_INLINE
void
glm_quat_mul_wasm(versor p, versor q, versor dest) {
/*
+ (a1 b2 + b1 a2 + c1 d2 d1 c2)i
+ (a1 c2 b1 d2 + c1 a2 + d1 b2)j
+ (a1 d2 + b1 c2 c1 b2 + d1 a2)k
a1 a2 b1 b2 c1 c2 d1 d2
*/
glmm_128 xp, xq, x1, x2, x3, r, x, y, z;
xp = glmm_load(p); /* 3 2 1 0 */
xq = glmm_load(q);
x1 = wasm_f32x4_const(0.f, -0.f, 0.f, -0.f); /* TODO: _mm_set1_ss() + shuff ? */
r = wasm_f32x4_mul(glmm_splat_w(xp), xq);
/* x2 = _mm_unpackhi_ps(x1, x1); */
x2 = wasm_i32x4_shuffle(x1, x1, 2, 6, 3, 7);
x3 = glmm_shuff1(x1, 3, 2, 0, 1);
x = glmm_splat_x(xp);
y = glmm_splat_y(xp);
z = glmm_splat_z(xp);
x = wasm_v128_xor(x, x1);
y = wasm_v128_xor(y, x2);
z = wasm_v128_xor(z, x3);
x1 = glmm_shuff1(xq, 0, 1, 2, 3);
x2 = glmm_shuff1(xq, 1, 0, 3, 2);
x3 = glmm_shuff1(xq, 2, 3, 0, 1);
r = glmm_fmadd(x, x1, r);
r = glmm_fmadd(y, x2, r);
r = glmm_fmadd(z, x3, r);
glmm_store(dest, r);
}
#endif
#endif /* cglm_quat_wasm_h */

View File

@@ -45,7 +45,9 @@
CGLM_INLINE
void
glm_vec4_broadcast(float val, vec4 d) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(d, wasm_f32x4_splat(val));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(d, _mm_set1_ps(val));
#else
d[0] = d[1] = d[2] = d[3] = val;
@@ -61,7 +63,9 @@ glm_vec4_broadcast(float val, vec4 d) {
CGLM_INLINE
void
glm_vec4_fill(vec4 v, float val) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(v, wasm_f32x4_splat(val));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(v, _mm_set1_ps(val));
#else
v[0] = v[1] = v[2] = v[3] = val;
@@ -247,7 +251,9 @@ glm_vec4_sign(vec4 v, vec4 dest) {
CGLM_INLINE
void
glm_vec4_abs(vec4 v, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest, glmm_abs(glmm_load(v)));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, glmm_abs(glmm_load(v)));
#elif defined(CGLM_NEON_FP)
vst1q_f32(dest, vabsq_f32(vld1q_f32(v)));
@@ -284,7 +290,9 @@ glm_vec4_fract(vec4 v, vec4 dest) {
CGLM_INLINE
float
glm_vec4_hadd(vec4 v) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
return glmm_hadd(glmm_load(v));
#elif defined( __SSE__ ) || defined( __SSE2__ )
return glmm_hadd(glmm_load(v));
#else
return v[0] + v[1] + v[2] + v[3];
@@ -300,7 +308,9 @@ glm_vec4_hadd(vec4 v) {
CGLM_INLINE
void
glm_vec4_sqrt(vec4 v, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest, wasm_f32x4_sqrt(glmm_load(v)));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_sqrt_ps(glmm_load(v)));
#else
dest[0] = sqrtf(v[0]);

View File

@@ -137,7 +137,9 @@ glm_vec4_copy3(vec4 a, vec3 dest) {
CGLM_INLINE
void
glm_vec4_copy(vec4 v, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest, glmm_load(v));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, glmm_load(v));
#elif defined(CGLM_NEON_FP)
vst1q_f32(dest, vld1q_f32(v));
@@ -160,10 +162,15 @@ glm_vec4_copy(vec4 v, vec4 dest) {
CGLM_INLINE
void
glm_vec4_ucopy(vec4 v, vec4 dest) {
#if defined(__wasm__) && defined(__wasm_simd128__)
/* note here wasm v128.load/v128.store support unaligned loads and stores */
wasm_v128_store(dest, wasm_v128_load(v));
#else
dest[0] = v[0];
dest[1] = v[1];
dest[2] = v[2];
dest[3] = v[3];
#endif
}
/*!
@@ -174,7 +181,9 @@ glm_vec4_ucopy(vec4 v, vec4 dest) {
CGLM_INLINE
void
glm_vec4_zero(vec4 v) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(v, wasm_f32x4_const_splat(0.f));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(v, _mm_setzero_ps());
#elif defined(CGLM_NEON_FP)
vst1q_f32(v, vdupq_n_f32(0.0f));
@@ -194,7 +203,9 @@ glm_vec4_zero(vec4 v) {
CGLM_INLINE
void
glm_vec4_one(vec4 v) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(v, wasm_f32x4_const_splat(1.0f));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(v, _mm_set1_ps(1.0f));
#elif defined(CGLM_NEON_FP)
vst1q_f32(v, vdupq_n_f32(1.0f));
@@ -320,7 +331,9 @@ glm_vec4_norm_inf(vec4 v) {
CGLM_INLINE
void
glm_vec4_add(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest, wasm_f32x4_add(glmm_load(a), glmm_load(b)));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_add_ps(glmm_load(a), glmm_load(b)));
#elif defined(CGLM_NEON_FP)
vst1q_f32(dest, vaddq_f32(vld1q_f32(a), vld1q_f32(b)));
@@ -342,7 +355,9 @@ glm_vec4_add(vec4 a, vec4 b, vec4 dest) {
CGLM_INLINE
void
glm_vec4_adds(vec4 v, float s, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest, wasm_f32x4_add(glmm_load(v), wasm_f32x4_splat(s)));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_add_ps(glmm_load(v), _mm_set1_ps(s)));
#elif defined(CGLM_NEON_FP)
vst1q_f32(dest, vaddq_f32(vld1q_f32(v), vdupq_n_f32(s)));
@@ -364,7 +379,9 @@ glm_vec4_adds(vec4 v, float s, vec4 dest) {
CGLM_INLINE
void
glm_vec4_sub(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest, wasm_f32x4_sub(glmm_load(a), glmm_load(b)));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_sub_ps(glmm_load(a), glmm_load(b)));
#elif defined(CGLM_NEON_FP)
vst1q_f32(dest, vsubq_f32(vld1q_f32(a), vld1q_f32(b)));
@@ -386,7 +403,9 @@ glm_vec4_sub(vec4 a, vec4 b, vec4 dest) {
CGLM_INLINE
void
glm_vec4_subs(vec4 v, float s, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest, wasm_f32x4_sub(glmm_load(v), wasm_f32x4_splat(s)));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_sub_ps(glmm_load(v), _mm_set1_ps(s)));
#elif defined(CGLM_NEON_FP)
vst1q_f32(dest, vsubq_f32(vld1q_f32(v), vdupq_n_f32(s)));
@@ -408,7 +427,9 @@ glm_vec4_subs(vec4 v, float s, vec4 dest) {
CGLM_INLINE
void
glm_vec4_mul(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest, wasm_f32x4_mul(glmm_load(a), glmm_load(b)));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_mul_ps(glmm_load(a), glmm_load(b)));
#elif defined(CGLM_NEON_FP)
vst1q_f32(dest, vmulq_f32(vld1q_f32(a), vld1q_f32(b)));
@@ -430,7 +451,9 @@ glm_vec4_mul(vec4 a, vec4 b, vec4 dest) {
CGLM_INLINE
void
glm_vec4_scale(vec4 v, float s, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest, wasm_f32x4_mul(glmm_load(v), wasm_f32x4_splat(s)));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_mul_ps(glmm_load(v), _mm_set1_ps(s)));
#elif defined(CGLM_NEON_FP)
vst1q_f32(dest, vmulq_f32(vld1q_f32(v), vdupq_n_f32(s)));
@@ -493,7 +516,9 @@ glm_vec4_div(vec4 a, vec4 b, vec4 dest) {
CGLM_INLINE
void
glm_vec4_divs(vec4 v, float s, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest, wasm_f32x4_div(glmm_load(v), wasm_f32x4_splat(s)));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_div_ps(glmm_load(v), _mm_set1_ps(s)));
#else
glm_vec4_scale(v, 1.0f / s, dest);
@@ -512,7 +537,11 @@ glm_vec4_divs(vec4 v, float s, vec4 dest) {
CGLM_INLINE
void
glm_vec4_addadd(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest, wasm_f32x4_add(
glmm_load(dest),
wasm_f32x4_add(glmm_load(a), glmm_load(b))));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_add_ps(glmm_load(dest),
_mm_add_ps(glmm_load(a),
glmm_load(b))));
@@ -540,7 +569,11 @@ glm_vec4_addadd(vec4 a, vec4 b, vec4 dest) {
CGLM_INLINE
void
glm_vec4_subadd(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest, wasm_f32x4_add(
glmm_load(dest),
wasm_f32x4_sub(glmm_load(a), glmm_load(b))));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_add_ps(glmm_load(dest),
_mm_sub_ps(glmm_load(a),
glmm_load(b))));
@@ -612,7 +645,11 @@ glm_vec4_muladds(vec4 a, float s, vec4 dest) {
CGLM_INLINE
void
glm_vec4_maxadd(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest, wasm_f32x4_add(
glmm_load(dest),
wasm_f32x4_max(glmm_load(a), glmm_load(b))));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_add_ps(glmm_load(dest),
_mm_max_ps(glmm_load(a),
glmm_load(b))));
@@ -640,7 +677,11 @@ glm_vec4_maxadd(vec4 a, vec4 b, vec4 dest) {
CGLM_INLINE
void
glm_vec4_minadd(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest, wasm_f32x4_add(
glmm_load(dest),
wasm_f32x4_min(glmm_load(a), glmm_load(b))));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_add_ps(glmm_load(dest),
_mm_min_ps(glmm_load(a),
glmm_load(b))));
@@ -665,7 +706,9 @@ glm_vec4_minadd(vec4 a, vec4 b, vec4 dest) {
CGLM_INLINE
void
glm_vec4_negate_to(vec4 v, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest, wasm_f32x4_neg(glmm_load(v)));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_xor_ps(glmm_load(v), _mm_set1_ps(-0.0f)));
#elif defined(CGLM_NEON_FP)
vst1q_f32(dest, vnegq_f32(vld1q_f32(v)));
@@ -697,7 +740,22 @@ glm_vec4_negate(vec4 v) {
CGLM_INLINE
void
glm_vec4_normalize_to(vec4 v, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_128 xdot, x0;
float dot;
x0 = glmm_load(v);
xdot = glmm_vdot(x0, x0);
/* dot = _mm_cvtss_f32(xdot); */
dot = wasm_f32x4_extract_lane(xdot, 0);
if (dot == 0.0f) {
glmm_store(dest, wasm_f32x4_const_splat(0.f));
return;
}
glmm_store(dest, wasm_f32x4_div(x0, wasm_f32x4_sqrt(xdot)));
#elif defined( __SSE__ ) || defined( __SSE2__ )
__m128 xdot, x0;
float dot;
@@ -746,7 +804,9 @@ glm_vec4_normalize(vec4 v) {
CGLM_INLINE
float
glm_vec4_distance(vec4 a, vec4 b) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
return glmm_norm(wasm_f32x4_sub(glmm_load(a), glmm_load(b)));
#elif defined( __SSE__ ) || defined( __SSE2__ )
return glmm_norm(_mm_sub_ps(glmm_load(a), glmm_load(b)));
#elif defined(CGLM_NEON_FP)
return glmm_norm(vsubq_f32(glmm_load(a), glmm_load(b)));
@@ -768,7 +828,9 @@ glm_vec4_distance(vec4 a, vec4 b) {
CGLM_INLINE
float
glm_vec4_distance2(vec4 a, vec4 b) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
return glmm_norm2(wasm_f32x4_sub(glmm_load(a), glmm_load(b)));
#elif defined( __SSE__ ) || defined( __SSE2__ )
return glmm_norm2(_mm_sub_ps(glmm_load(a), glmm_load(b)));
#elif defined(CGLM_NEON_FP)
return glmm_norm2(vsubq_f32(glmm_load(a), glmm_load(b)));
@@ -790,7 +852,9 @@ glm_vec4_distance2(vec4 a, vec4 b) {
CGLM_INLINE
void
glm_vec4_maxv(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest, wasm_f32x4_max(glmm_load(a), glmm_load(b)));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_max_ps(glmm_load(a), glmm_load(b)));
#elif defined(CGLM_NEON_FP)
vst1q_f32(dest, vmaxq_f32(vld1q_f32(a), vld1q_f32(b)));
@@ -812,7 +876,9 @@ glm_vec4_maxv(vec4 a, vec4 b, vec4 dest) {
CGLM_INLINE
void
glm_vec4_minv(vec4 a, vec4 b, vec4 dest) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(dest, wasm_f32x4_min(glmm_load(a), glmm_load(b)));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(dest, _mm_min_ps(glmm_load(a), glmm_load(b)));
#elif defined(CGLM_NEON_FP)
vst1q_f32(dest, vminq_f32(vld1q_f32(a), vld1q_f32(b)));
@@ -834,7 +900,11 @@ glm_vec4_minv(vec4 a, vec4 b, vec4 dest) {
CGLM_INLINE
void
glm_vec4_clamp(vec4 v, float minVal, float maxVal) {
#if defined( __SSE__ ) || defined( __SSE2__ )
#if defined(__wasm__) && defined(__wasm_simd128__)
glmm_store(v, wasm_f32x4_min(
wasm_f32x4_max(glmm_load(v), wasm_f32x4_splat(minVal)),
wasm_f32x4_splat(maxVal)));
#elif defined( __SSE__ ) || defined( __SSE2__ )
glmm_store(v, _mm_min_ps(_mm_max_ps(glmm_load(v), _mm_set1_ps(minVal)),
_mm_set1_ps(maxVal)));
#elif defined(CGLM_NEON_FP)

View File

@@ -22,6 +22,11 @@ set(TEST_RUNNER_PARAMS "")
add_executable(${TEST_MAIN} ${TESTFILES})
target_compile_definitions(${TEST_MAIN} PRIVATE CGLM_DEFINE_PRINTS=1)
if(CMAKE_SYSTEM_NAME STREQUAL WASI)
target_compile_definitions(${TEST_MAIN} PRIVATE _WASI_EMULATED_PROCESS_CLOCKS=1)
target_link_options(${TEST_MAIN} PRIVATE "-lwasi-emulated-process-clocks")
endif()
if(NOT MSVC)
target_link_libraries(${TEST_MAIN} PRIVATE m)
endif()