From 56361b52e7de7e235b72bd8241589537a1a40b18 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sat, 2 Aug 2025 12:18:18 +0500 Subject: [PATCH] 3rdparty: opus: enable platform optimized code (x86 SSE/AVX with runtime detection and NEON on ARM) Along that enable hardening and check for C99 lrintf (probably can do the same in the engine at some point). --- 3rdparty/opus/wscript | 71 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/3rdparty/opus/wscript b/3rdparty/opus/wscript index 211cb10b..ed473963 100644 --- a/3rdparty/opus/wscript +++ b/3rdparty/opus/wscript @@ -23,6 +23,17 @@ int main (void) { int * array = alloca(foo); }''' +FRAGMENT_LRINT='''#include +#include +int main (int argc, char **argv) { + return lrint%s((%s)atof(argv[1])); +}''' + +# assuming MSVC always enables NEON +FRAGMENT_NEON='''#if !defined __ARM_NEON__ && !defined _MSC_VER +#error +#endif''' + def options(opt): pass @@ -31,15 +42,59 @@ def configure(conf): conf.fatal('Can\'t find opus submodule. Run `git submodule update --init --recursive`.') return + if conf.check_cc(fragment=FRAGMENT_LRINT % ('', 'double'), msg = 'Checking for C99 lrint', use = 'M', mandatory = False): + conf.define('HAVE_LRINT', 1) + + if conf.check_cc(fragment=FRAGMENT_LRINT % ('f', 'float'), msg = 'Checking for C99 lrintf', use = 'M', mandatory = False): + conf.define('HAVE_LRINTF', 1) + # Check for C99 variable-size arrays, or alloca() as fallback if conf.check_cc(fragment=FRAGMENT_VLA, msg = 'Checking for C99 VLA support', mandatory = False): conf.define('VAR_ARRAYS', 1) elif conf.check_cc(fragment=FRAGMENT_ALLOCA_H, msg = 'Checking for alloca in alloca.h header', mandatory = False): conf.define('USE_ALLOCA', 1) conf.define('HAVE_ALLOCA_H', 1) - elif conf.check_cc(fragmenmt=FRAGMENT_STDLIB_H, msg = 'Checking for alloca.h in stdlib.h', mandatory = False): + elif conf.check_cc(fragment=FRAGMENT_STDLIB_H, msg = 'Checking for alloca.h in stdlib.h', mandatory = False): conf.define('USE_ALLOCA', 1) + if conf.env.DEST_CPU in ['thumb', 'arm']: + if conf.check(header_name='arm_neon.h', mandatory = False): + if conf.check(fragment=FRAGMENT_NEON, msg = 'Checking if compiler enabled NEON', mandatory = False): + conf.env.HAVE_NEON = True + conf.define('OPUS_ARM_MAY_HAVE_NEON_INTR', 1) + conf.define('OPUS_ARM_PRESUME_NEON', 1) + elif conf.env.DEST_CPU.startswith('x86'): + if conf.check(header_name='cpuid.h', mandatory=False): + conf.define('CPU_INFO_BY_C', 1) + else: + conf.define('CPU_INFO_BY_ASM', 1) + + conf.define('OPUS_HAVE_RTCD', 1) + + if conf.check(header_name='xmmintrin.h', mandatory = False): + if conf.env.COMPILER_CC != 'msvc': + conf.env.CFLAGS += ['-msse'] + conf.define('OPUS_X86_MAY_HAVE_SSE', 1) + if conf.env.DEST_SIZEOF_VOID_P > 4: + conf.define('OPUS_X86_PRESUME_SSE', 1) + + if conf.check(header_name='emmintrin.h', mandatory = False): + if conf.env.COMPILER_CC != 'msvc': + conf.env.CFLAGS += ['-msse2'] + conf.define('OPUS_X86_MAY_HAVE_SSE2', 1) + if conf.env.DEST_SIZEOF_VOID_P > 4: + conf.define('OPUS_X86_PRESUME_SSE2', 1) + + if conf.check(header_name='smmintrin.h', mandatory = False): + if conf.env.COMPILER_CC != 'msvc': + conf.env.CFLAGS += ['-msse4.1'] + conf.define('OPUS_X86_MAY_HAVE_SSE4_1', 1) + + if conf.check(header_name='immintrin.h', mandatory = False): + if conf.env.COMPILER_CC != 'msvc': + conf.env.CFLAGS += ['-mavx'] + conf.define('OPUS_X86_MAY_HAVE_AVX', 1) + # TODO: ARM/x86 intrinsics detection # TODO: maybe call autotools/cmake/meson instead? @@ -55,8 +110,18 @@ def build(bld): 'opus/src/opus_compare.c', 'opus/celt/opus_custom_demo.c' ]) - includes = ['opus/include/', 'opus/celt/', 'opus/silk/', 'opus/silk/float/'] - defines = ['OPUS_BUILD', 'FLOAT_APPROX', 'PACKAGE_VERSION="1.4.0"', 'CUSTOM_MODES'] + + includes = ['opus', 'opus/include/', 'opus/celt/', 'opus/silk/', 'opus/silk/float/'] + + if bld.env.DEST_CPU in ['thumb', 'arm']: + if bld.env.HAVE_NEON: + sources += bld.path.ant_glob(['opus/silk/arm/*.c', 'opus/celt/arm/*.c']) + includes += ['opus/silk/arm', 'opus/celt/arm'] + elif bld.env.DEST_CPU.startswith('x86'): + sources += bld.path.ant_glob(['opus/silk/x86/*.c', 'opus/celt/x86/*.c']) + includes += ['opus/silk/x86', 'opus/celt/x86'] + + defines = ['OPUS_BUILD', 'FLOAT_APPROX', 'PACKAGE_VERSION="1.4.0"', 'CUSTOM_MODES', 'ENABLE_HARDENING'] bld.stlib( source = sources,