diff --git a/modules/core/include/opencv2/core/simd_intrinsics.hpp b/modules/core/include/opencv2/core/simd_intrinsics.hpp new file mode 100644 index 0000000000..c3d65cded5 --- /dev/null +++ b/modules/core/include/opencv2/core/simd_intrinsics.hpp @@ -0,0 +1,88 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +#ifndef OPENCV_CORE_SIMD_INTRINSICS_HPP +#define OPENCV_CORE_SIMD_INTRINSICS_HPP + +/** +Helper header to support SIMD intrinsics (universal intrinsics) in user code. +Intrinsics documentation: https://docs.opencv.org/3.4/df/d91/group__core__hal__intrin.html + + +Checks of target CPU instruction set based on compiler definitions don't work well enough. +More reliable solutions require utilization of configuration systems (like CMake). + +So, probably you need to specify your own configuration. + +You can do that via CMake in this way: + add_definitions(/DOPENCV_SIMD_CONFIG_HEADER=opencv_simd_config_custom.hpp) +or + add_definitions(/DOPENCV_SIMD_CONFIG_INCLUDE_DIR=1) + +Additionally you may need to add include directory to your files: + include_directories("${CMAKE_CURRENT_LIST_DIR}/opencv_config_${MYTARGET}") + +These files can be pre-generated for target configurations of your application +or generated by CMake on the fly (use CMAKE_BINARY_DIR for that). + +Notes: +- H/W capability checks are still responsibility of your applcation +- runtime dispatching is not covered by this helper header +*/ + +#ifdef __OPENCV_BUILD +#error "Use core/hal/intrin.hpp during OpenCV build" +#endif + +#ifdef OPENCV_HAL_INTRIN_HPP +#error "core/simd_intrinsics.hpp must be included before core/hal/intrin.hpp" +#endif + +#include "opencv2/core/cvdef.h" +#include "opencv2/core/version.hpp" + +#ifdef OPENCV_SIMD_CONFIG_HEADER +#include CVAUX_STR(OPENCV_SIMD_CONFIG_HEADER) +#elif defined(OPENCV_SIMD_CONFIG_INCLUDE_DIR) +#include "opencv_simd_config.hpp" // corresponding directory should be added via -I compiler parameter +#else // custom config headers + +#if (!defined(CV_AVX_512F) || !CV_AVX_512F) && (defined(__AVX512__) || defined(__AVX512F__)) +# include +# undef CV_AVX_512F +# define CV_AVX_512F 1 +# ifndef OPENCV_SIMD_DONT_ASSUME_SKX // Skylake-X with AVX-512F/CD/BW/DQ/VL +# undef CV_AVX512_SKX +# define CV_AVX512_SKX 1 +# undef CV_AVX_512CD +# define CV_AVX_512CD 1 +# undef CV_AVX_512BW +# define CV_AVX_512BW 1 +# undef CV_AVX_512DQ +# define CV_AVX_512DQ 1 +# undef CV_AVX_512VL +# define CV_AVX_512VL 1 +# endif +#endif // AVX512 + +// GCC/Clang: -mavx2 +// MSVC: /arch:AVX2 +#if defined __AVX2__ +# include +# undef CV_AVX2 +# define CV_AVX2 1 +# if defined __F16C__ +# undef CV_FP16 +# define CV_FP16 1 +# endif +#endif + +#endif + +// SSE / NEON / VSX is handled by cv_cpu_dispatch.h compatibility block +#include "cv_cpu_dispatch.h" + +#include "hal/intrin.hpp" + +#endif // OPENCV_CORE_SIMD_INTRINSICS_HPP diff --git a/samples/cpp/CMakeLists.txt b/samples/cpp/CMakeLists.txt index d4417f90ac..109675da04 100644 --- a/samples/cpp/CMakeLists.txt +++ b/samples/cpp/CMakeLists.txt @@ -57,6 +57,13 @@ foreach(sample_filename ${cpp_samples}) if(HAVE_OPENGL AND sample_filename MATCHES "detect_mser") target_compile_definitions(${tgt} PRIVATE HAVE_OPENGL) endif() + if(sample_filename MATCHES "simd_") + # disabled intentionally - demonstation purposes only + #target_include_directories(${tgt} PRIVATE "${CMAKE_CURRENT_LIST_DIR}") + #target_compile_definitions(${tgt} PRIVATE OPENCV_SIMD_CONFIG_HEADER=opencv_simd_config_custom.hpp) + #target_compile_definitions(${tgt} PRIVATE OPENCV_SIMD_CONFIG_INCLUDE_DIR=1) + #target_compile_options(${tgt} PRIVATE -mavx2) + endif() endforeach() include("tutorial_code/calib3d/real_time_pose_estimation/CMakeLists.txt" OPTIONAL) diff --git a/samples/cpp/simd_basic.cpp b/samples/cpp/simd_basic.cpp new file mode 100644 index 0000000000..9af4d91cef --- /dev/null +++ b/samples/cpp/simd_basic.cpp @@ -0,0 +1,49 @@ +#include "opencv2/core.hpp" +#include "opencv2/core/simd_intrinsics.hpp" + +using namespace cv; + +int main(int /*argc*/, char** /*argv*/) +{ + printf("================== macro dump ===================\n"); +#ifdef CV_SIMD + printf("CV_SIMD is defined: " CVAUX_STR(CV_SIMD) "\n"); +#ifdef CV_SIMD_WIDTH + printf("CV_SIMD_WIDTH is defined: " CVAUX_STR(CV_SIMD_WIDTH) "\n"); +#endif +#ifdef CV_SIMD128 + printf("CV_SIMD128 is defined: " CVAUX_STR(CV_SIMD128) "\n"); +#endif +#ifdef CV_SIMD256 + printf("CV_SIMD256 is defined: " CVAUX_STR(CV_SIMD256) "\n"); +#endif +#ifdef CV_SIMD512 + printf("CV_SIMD512 is defined: " CVAUX_STR(CV_SIMD512) "\n"); +#endif +#ifdef CV_SIMD_64F + printf("CV_SIMD_64F is defined: " CVAUX_STR(CV_SIMD_64F) "\n"); +#endif +#ifdef CV_SIMD_FP16 + printf("CV_SIMD_FP16 is defined: " CVAUX_STR(CV_SIMD_FP16) "\n"); +#endif +#else + printf("CV_SIMD is NOT defined\n"); +#endif + +#ifdef CV_SIMD + printf("================= sizeof checks =================\n"); + printf("sizeof(v_uint8) = %d\n", (int)sizeof(v_uint8)); + printf("sizeof(v_int32) = %d\n", (int)sizeof(v_int32)); + printf("sizeof(v_float32) = %d\n", (int)sizeof(v_float32)); + + printf("================== arithm check =================\n"); + v_uint8 a = vx_setall_u8(10); + v_uint8 c = a + vx_setall_u8(45); + printf("(vx_setall_u8(10) + vx_setall_u8(45)).get0() => %d\n", (int)c.get0()); +#else + printf("\nSIMD intrinsics are not available. Check compilation target and passed build options.\n"); +#endif + + printf("===================== done ======================\n"); + return 0; +}