Skip to content

Latest commit

 

History

History
98 lines (87 loc) · 5.63 KB

simd.md

File metadata and controls

98 lines (87 loc) · 5.63 KB

Universal intrinsics

Enable simd to import OpenCV's native 128-bit CPU intrinsics with their original cv:: vector types and function names:

[dependencies]
"mcpplibs.mwrap.opencv" = { version = "5.0.0", features = ["simd"] }
import mcpplibs.mwrap.opencv.core.simd;
int main() {
    float input[4]{1, 2, 3, 4}, output[4]{};
    auto sum = cv::v_add(cv::v_load(input), cv::v_setall_f32(2));
    cv::v_store(output, sum);
    return output[0] != 3;
}

The root mcpplibs.mwrap.opencv import also exposes this surface when simd is selected. It is separate from all-modules, which selects sixteen main algorithm modules. No external SDK, GPU backend or additional ISA flag is added.

The implementation selects the library's compiled baseline: x86_64 SSE2 or ARM64 NEON, with sixteen-byte vector storage. The imported macros module maps CV_SIMD_WIDTH, CV_SIMD128, CV_SIMD_64F and related values under mcpplibs::mwrap::opencv::macros. These describe the library module; they do not change with an importing translation unit's flags. Per-translation-unit CPU dispatch, AVX2/AVX512 variants and other native architectures still need separate integration and verification. No empty features are registered for those implementations.

simd-emulated implies simd and selects the SDK's software implementation (CV_FORCE_SIMD128_CPP) for this package's public intrinsics. It uses the same module and cv:: names, including original v_reg<T, N> generic templates. The package feature union selects one implementation for all consumers; it does not provide two interchangeable vector ABIs. Textual comparisons must use the same upstream force macro. The compiled algorithm kernels keep their own native dispatch configuration.

The emulator adapter includes ordinary core declarations first, then temporarily maps CV_INLINE to inline while including the original intrinsics header. This changes the linkage of namespace function templates needed by module exports; vector class definitions and implementation bodies remain unchanged. The original macro is restored afterward. Its SDK reference test uses unmodified headers without this linkage adaptation. Software mode exports generic memory templates directly, including on GCC; it does not use native memory forwards. The pinned SDK's generic v_reinterpret_as_uint references a missing V_TypeTraits<T>::reinterpret_uint. Its name remains exported; matching negative SDK/import probes record the original instantiation failure. Concrete v_reinterpret_as_u32 and the other width-specific SDK operations remain usable.

Vector classes and ordinary inline functions refer to original SDK entities. The original Type2Vec128_Traits<T>, v_setall<T> and vx_setall<T> are also available. The ten SDK scalar specializations use producer-compiled forwards to the original static-inline broadcasts, preserving the SDK vector types, argument deduction and function-pointer signatures. Unsupported traits such as plain char remain rejected. These forwards add a call boundary; performance parity has not been measured. GCC memory-entry adapters call ordinary producer-compiled forwards: GCC 16 miscompiled an unaligned load through the imported inline intrinsic body. The adapter retains unaligned input/output support. This introduces a call boundary for those GCC entries; performance parity has not been measured. vx_store and vx_store_aligned keep their compatibility spellings through explicit forwards. Public aggregation is separate from the header adapter to avoid GCC's full-header/default-argument merge issue. Full textual SDK header mixing follows the restrictions in architecture.

For the operators removed from the ordinary intrinsics header in OpenCV 4.11, explicitly import mcpplibs.mwrap.opencv.core.simd.legacy with simd enabled. It corresponds to manually including the original intrin_legacy_ops.h after the intrinsics header. All 21 original operator templates stay in cv::hal; use its operators as with the SDK, for example using cv::hal::operator+;. Keep these declarations scoped to vector expressions. The SDK's unconstrained comparison templates can override a derived iterator's base-class comparison, as observed with MSVC's std::array iterators when importing all of cv::hal. The base SIMD and root imports deliberately do not introduce these overloads. No additional feature or implementation library is required. The opt-in interface is built with the same native/software vector configuration.

The SDK software implementation declares v_not<float,N> without defining it: floating legacy operator~ therefore fails to link in both SDK and module consumers. Integer complement is tested in software mode; native mode also checks floating complement. The adapter re-exports the SDK templates and does not manufacture a replacement definition for the broken specialization.

tools/check_simd.py compares independent original-header/import-only consumers. It exercises unaligned memory, saturating/wrapping arithmetic, packing/widening, lane ordering, masks, dot products, rounding, doubles and interleaved RGB. It also checks every enabled name through direct/root imports. Pass --emulated to check software mode, including eight-lane generic arithmetic, bitwise operations, double conversion, reductions and rounding shifts. Both modes compare the 21 legacy operators against independent SDK consumers, including compound reference identity, function-pointer selection and byte saturation, and verify that base/root imports keep those operators opt-in. Native CI covers the declared platforms; pending results remain acceptance gates. See coverage for the current verified scope.