Added using cpufeatures crate for no_std environment.

This commit is contained in:
Kirill Kuzminykh
2026-01-07 15:41:38 +03:00
parent 9dbc621ff4
commit afb04d2f42
6 changed files with 72 additions and 59 deletions
Generated
+1
View File
@@ -575,6 +575,7 @@ version = "5.5.0"
dependencies = [
"bytemuck",
"cfg-if",
"cpufeatures",
"criterion",
"document-features",
"fast_image_resize",
+2 -2
View File
@@ -28,7 +28,7 @@ document-features = { version = "0.2.12", optional = true }
image = { version = "0.25.6", optional = true, default-features = false }
bytemuck = { version = "1.24", optional = true }
rayon = { version = "1.11", optional = true }
cpufeatures = { version = "0.2.17", optional = true }
[features]
default = ["std"]
@@ -38,7 +38,7 @@ std = ["thiserror/std", "num-traits/std", "dep:document-features"]
## To prevent conflicts with the `std` feature it is not used for
## conditional compilation. It just installs additional dependencies
## or activates some features of existing dependencies.
no_std = ["num-traits/libm"]
no_std = ["num-traits/libm", "dep:cpufeatures"]
## Enable this feature to implement traits [IntoImageView](crate::IntoImageView) and
## [IntoImageViewMut](crate::IntoImageViewMut) for the
## [DynamicImage](https://docs.rs/image/latest/image/enum.DynamicImage.html)
+4 -9
View File
@@ -2,15 +2,10 @@
cfg_if::cfg_if! {
if #[cfg(feature = "std")] {
pub use std::boxed::Box;
pub use std::{vec, vec::Vec};
pub use std::borrow::ToOwned;
mod std_impl;
pub use std_impl::*;
} else {
pub use alloc::boxed::Box;
pub use alloc::{vec, vec::Vec};
pub use alloc::borrow::ToOwned;
// `no_std` feature must be enabled
pub use num_traits::Float;
mod no_std_impl;
pub use no_std_impl::*;
}
}
+31
View File
@@ -0,0 +1,31 @@
pub use alloc::borrow::ToOwned;
pub use alloc::boxed::Box;
pub use alloc::vec;
pub use alloc::vec::Vec;
// `no_std` feature must be enabled
pub use num_traits::Float;
// `no_std` feature must be enabled
cpufeatures::new!(cpuid_sse41, "sse4.1");
cpufeatures::new!(cpuid_avx2, "avx2");
#[cfg(target_arch = "x86_64")]
pub fn has_avx2() -> bool {
cpuid_avx2::get()
}
#[cfg(target_arch = "x86_64")]
pub fn has_sse41() -> bool {
cpuid_sse41::get()
}
#[cfg(target_arch = "aarch64")]
pub fn has_neon() -> bool {
true
}
#[cfg(target_arch = "wasm32")]
pub fn has_simd128() -> bool {
true
}
+24
View File
@@ -0,0 +1,24 @@
pub use std::borrow::ToOwned;
pub use std::boxed::Box;
pub use std::vec;
pub use std::vec::Vec;
#[cfg(target_arch = "x86_64")]
pub fn has_avx2() -> bool {
std::is_x86_feature_detected!("avx2")
}
#[cfg(target_arch = "x86_64")]
pub fn has_sse41() -> bool {
std::is_x86_feature_detected!("sse4.1")
}
#[cfg(target_arch = "aarch64")]
pub fn has_neon() -> bool {
std::arch::is_aarch64_feature_detected!("neon")
}
#[cfg(target_arch = "wasm32")]
pub fn has_simd128() -> bool {
true
}
+10 -48
View File
@@ -1,3 +1,5 @@
use crate::compat::*;
/// SIMD extension of CPU.
/// Specific variants depend on target architecture.
/// Look at source code to see all available variants.
@@ -23,63 +25,24 @@ impl CpuExtensions {
pub fn is_supported(&self) -> bool {
match self {
#[cfg(target_arch = "x86_64")]
Self::Avx2 => Self::has_avx2(),
Self::Avx2 => has_avx2(),
#[cfg(target_arch = "x86_64")]
Self::Sse4_1 => Self::has_sse41(),
Self::Sse4_1 => has_sse41(),
#[cfg(target_arch = "aarch64")]
// FIXME: Not sure how, I don't know ARM assembly. AFAIK, all ARM compliant
// processors must implement NEON
Self::Neon => true,
Self::Neon => has_neon(),
#[cfg(target_arch = "wasm32")]
Self::Simd128 => true,
Self::Simd128 => has_simd128(),
Self::None => true,
}
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[inline]
fn has_avx2() -> bool {
use core::arch::x86_64::{__cpuid, __cpuid_count, _xgetbv};
unsafe {
let cpuid1 = __cpuid(1);
if (cpuid1.ecx & (1 << 27)) == 0 || (cpuid1.ecx & (1 << 28)) == 0 {
// OSXSAVE + AVX
return false;
}
let xcr0 = _xgetbv(0);
if (xcr0 & 0b110) != 0b110 {
// XCR0: XMM (bit 1) and YMM (bit 2) enabled
return false;
}
// CPUID leaf 7 subleaf 0: AVX2
let cpuid7 = __cpuid_count(7, 0);
(cpuid7.ebx & (1 << 5)) != 0
}
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[inline]
fn has_sse41() -> bool {
use core::arch::x86_64::__cpuid;
// CPUID leaf 1: feature bits
let res = unsafe { __cpuid(1) };
// ECX bit 19 = SSE4.1
(res.ecx & (1 << 19)) != 0
}
}
impl Default for CpuExtensions {
#[cfg(target_arch = "x86_64")]
fn default() -> Self {
if Self::has_avx2() {
if has_avx2() {
Self::Avx2
} else if Self::has_sse41() {
} else if has_sse41() {
Self::Sse4_1
} else {
Self::None
@@ -88,12 +51,11 @@ impl Default for CpuExtensions {
#[cfg(target_arch = "aarch64")]
fn default() -> Self {
// FIXME: Maybe we detect?
Self::Neon
has_neon()
}
#[cfg(target_arch = "wasm32")]
fn default() -> Self {
Self::Simd128
has_simd128()
}
#[cfg(not(any(