diff --git a/audio/filters/echo.c b/audio/filters/echo.c index 22d4cb1123..843da2f997 100644 --- a/audio/filters/echo.c +++ b/audio/filters/echo.c @@ -180,8 +180,9 @@ static const struct dspfilter_implementation generic_echo_dsp = { NULL }; -const struct dspfilter_implementation *rarch_dsp_plugin_init(void) +const struct dspfilter_implementation *rarch_dsp_plugin_init(dspfilter_simd_mask_t simd) { + (void)simd; return &generic_echo_dsp; } diff --git a/audio/filters/eq.c b/audio/filters/eq.c index e02625619f..ad5b50b968 100644 --- a/audio/filters/eq.c +++ b/audio/filters/eq.c @@ -412,8 +412,9 @@ const struct dspfilter_implementation generic_eq_dsp = { NULL }; -const struct dspfilter_implementation *rarch_dsp_plugin_init(void) +const struct dspfilter_implementation *rarch_dsp_plugin_init(dspfilter_simd_mask_t simd) { + (void)simd; return &generic_eq_dsp; } diff --git a/audio/filters/iir.c b/audio/filters/iir.c index 4c59b276c5..cecd3f46d8 100644 --- a/audio/filters/iir.c +++ b/audio/filters/iir.c @@ -293,7 +293,8 @@ static void iir_process_batch(void *data, float *out, const float *in, unsigned iir->fir_buf[1] = fir_buf[1]; iir->iir_buf = iir_buf; } -#else +#endif + static float iir_process(void *data, float samp) { struct iir_filter *iir = (struct iir_filter*)data; @@ -307,7 +308,6 @@ static float iir_process(void *data, float samp) iir->yn1 = out; return out; } -#endif static void * iir_dsp_init(const rarch_dsp_info_t *info) { @@ -337,9 +337,6 @@ static void iir_dsp_process(void *data, rarch_dsp_output_t *output, output->samples = iir->buf; -#ifdef __SSE2__ - iir_process_batch(&iir->iir_l, iir->buf, input->samples, input->frames); -#else int num_samples = input->frames * 2; for (int i = 0; ibuf[i] = iir_process(&iir->iir_r, input->samples[i]); i++; } -#endif output->frames = input->frames; } +#ifdef __SSE2__ +static void iir_dsp_process_sse2(void *data, rarch_dsp_output_t *output, + const rarch_dsp_input_t *input) +{ + struct iir_filter_data *iir = (struct iir_filter_data*)data; + + output->samples = iir->buf; + iir_process_batch(&iir->iir_l, iir->buf, input->samples, input->frames); + output->frames = input->frames; +} +#endif + static void iir_dsp_free(void *data) { struct iir_filter_data *iir = (struct iir_filter_data*)data; @@ -371,16 +379,28 @@ const struct dspfilter_implementation generic_iir_dsp = { iir_dsp_free, RARCH_DSP_API_VERSION, iir_dsp_config, -#ifdef __SSE2__ - "IIR (SSE2)", -#else "IIR", -#endif NULL }; -const struct dspfilter_implementation *rarch_dsp_plugin_init(void) +#ifdef __SSE2__ +const struct dspfilter_implementation sse2_iir_dsp = { + iir_dsp_init, + iir_dsp_process_sse2, + iir_dsp_free, + RARCH_DSP_API_VERSION, + iir_dsp_config, + "IIR (SSE2)", + NULL +}; +#endif + +const struct dspfilter_implementation *rarch_dsp_plugin_init(dspfilter_simd_mask_t simd) { +#ifdef __SSE2__ + if (simd & DSPFILTER_SIMD_SSE2) + return &sse2_iir_dsp; +#endif return &generic_iir_dsp; } diff --git a/audio/filters/phaser.c b/audio/filters/phaser.c index 70372ca4fc..bc2bfec468 100644 --- a/audio/filters/phaser.c +++ b/audio/filters/phaser.c @@ -182,8 +182,9 @@ const struct dspfilter_implementation generic_phaser_dsp = { NULL }; -const struct dspfilter_implementation *rarch_dsp_plugin_init(void) +const struct dspfilter_implementation *rarch_dsp_plugin_init(dspfilter_simd_mask_t simd) { + (void)simd; return &generic_phaser_dsp; } diff --git a/audio/filters/rarch_dsp.h b/audio/filters/rarch_dsp.h index f8f0568c48..ba7ae9ef8c 100644 --- a/audio/filters/rarch_dsp.h +++ b/audio/filters/rarch_dsp.h @@ -22,11 +22,30 @@ extern "C" { #endif +#define DSPFILTER_SIMD_SSE (1 << 0) +#define DSPFILTER_SIMD_SSE2 (1 << 1) +#define DSPFILTER_SIMD_VMX (1 << 2) +#define DSPFILTER_SIMD_VMX128 (1 << 3) +#define DSPFILTER_SIMD_AVX (1 << 4) +#define DSPFILTER_SIMD_NEON (1 << 5) +#define DSPFILTER_SIMD_SSE3 (1 << 6) +#define DSPFILTER_SIMD_SSSE3 (1 << 7) +#define DSPFILTER_SIMD_MMX (1 << 8) +#define DSPFILTER_SIMD_MMXEXT (1 << 9) +#define DSPFILTER_SIMD_SSE4 (1 << 10) +#define DSPFILTER_SIMD_SSE42 (1 << 11) +#define DSPFILTER_SIMD_AVX2 (1 << 12) +#define DSPFILTER_SIMD_VFPU (1 << 13) +#define DSPFILTER_SIMD_PS (1 << 14) + +// A bit-mask of all supported SIMD instruction sets. +// Allows an implementation to pick different dspfilter_implementation structs. +typedef unsigned dspfilter_simd_mask_t; + // Dynamic library endpoint. -typedef const struct dspfilter_implementation *(*dspfilter_get_implementation_t)(void); -// Called at startup to get the callback struct. -// This is NOT dynamically allocated! -const struct dspfilter_implementation *rarch_dsp_plugin_init(void); +typedef const struct dspfilter_implementation *(*dspfilter_get_implementation_t)(dspfilter_simd_mask_t); +// The same SIMD mask argument is forwarded to create() callback as well to avoid having to keep lots of state around. +const struct dspfilter_implementation *rarch_dsp_plugin_init(dspfilter_simd_mask_t); #define RARCH_DSP_API_VERSION 6 diff --git a/audio/filters/reverb.c b/audio/filters/reverb.c index e09b69c850..4c7e1062b7 100644 --- a/audio/filters/reverb.c +++ b/audio/filters/reverb.c @@ -386,8 +386,9 @@ const struct dspfilter_implementation generic_reverb_dsp = { NULL }; -const struct dspfilter_implementation *rarch_dsp_plugin_init(void) +const struct dspfilter_implementation *rarch_dsp_plugin_init(dspfilter_simd_mask_t simd) { + (void)simd; return &generic_reverb_dsp; } diff --git a/audio/filters/volume.c b/audio/filters/volume.c index bcbf5b9f1d..d95119b673 100644 --- a/audio/filters/volume.c +++ b/audio/filters/volume.c @@ -120,8 +120,9 @@ const struct dspfilter_implementation generic_volume_dsp = { NULL }; -const struct dspfilter_implementation *rarch_dsp_plugin_init(void) +const struct dspfilter_implementation *rarch_dsp_plugin_init(dspfilter_simd_mask_t simd) { + (void)simd; return &generic_volume_dsp; } diff --git a/audio/filters/wah.c b/audio/filters/wah.c index 95beb8554f..6c5450a3db 100644 --- a/audio/filters/wah.c +++ b/audio/filters/wah.c @@ -175,8 +175,9 @@ const struct dspfilter_implementation generic_wah_dsp = { NULL }; -const struct dspfilter_implementation *rarch_dsp_plugin_init(void) +const struct dspfilter_implementation *rarch_dsp_plugin_init(dspfilter_simd_mask_t simd) { + (void)simd; return &generic_wah_dsp; } diff --git a/driver.c b/driver.c index e6ed29f7bc..889a63abf4 100644 --- a/driver.c +++ b/driver.c @@ -969,6 +969,7 @@ void uninit_drivers(void) void rarch_init_dsp_filter(void) { + unsigned cpu_features; dspfilter_get_implementation_t cb; rarch_dsp_info_t info = {0}; @@ -994,7 +995,9 @@ void rarch_init_dsp_filter(void) goto error; } - g_extern.audio_data.dsp_plugin = cb(); + cpu_features = rarch_get_cpu_features(); + g_extern.audio_data.dsp_plugin = cb(cpu_features); + if (!g_extern.audio_data.dsp_plugin) { RARCH_ERR("Failed to get a valid DSP plugin.\n");