Make sure FTZ is always enabled
This commit is contained in:
parent
dfedd7b2c4
commit
e642fb5ff8
|
@ -118,7 +118,6 @@ impl Plugin for Gain {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process(&mut self, buffer: &mut Buffer, _context: &dyn ProcessContext) -> ProcessStatus {
|
fn process(&mut self, buffer: &mut Buffer, _context: &dyn ProcessContext) -> ProcessStatus {
|
||||||
// TODO: The wrapper should set FTZ if not yet enabled, mention ths in the process fuctnion
|
|
||||||
for samples in buffer.iter_mut() {
|
for samples in buffer.iter_mut() {
|
||||||
// Smoothing is optionally built into the parameters themselves
|
// Smoothing is optionally built into the parameters themselves
|
||||||
let gain = self.params.gain.smoothed.next();
|
let gain = self.params.gain.smoothed.next();
|
||||||
|
|
|
@ -93,7 +93,6 @@ pub trait Plugin: Default + Send + Sync {
|
||||||
///
|
///
|
||||||
/// TODO: Provide a way to access auxiliary input channels if the IO configuration is
|
/// TODO: Provide a way to access auxiliary input channels if the IO configuration is
|
||||||
/// assymetric
|
/// assymetric
|
||||||
/// TODO: Handle FTZ stuff on the wrapper side and mention that this has been handled
|
|
||||||
/// TODO: Pass transport and other context information to the plugin
|
/// TODO: Pass transport and other context information to the plugin
|
||||||
fn process(&mut self, buffer: &mut Buffer, context: &dyn ProcessContext) -> ProcessStatus;
|
fn process(&mut self, buffer: &mut Buffer, context: &dyn ProcessContext) -> ProcessStatus;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
use std::marker::PhantomData;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
use vst3_sys::vst::TChar;
|
use vst3_sys::vst::TChar;
|
||||||
use widestring::U16CString;
|
use widestring::U16CString;
|
||||||
|
@ -92,6 +93,9 @@ pub fn u16strlcpy(dest: &mut [TChar], src: &str) {
|
||||||
/// `assert_no_alloc` if needed, while also making sure that things like FTZ are set up correctly if
|
/// `assert_no_alloc` if needed, while also making sure that things like FTZ are set up correctly if
|
||||||
/// the host has not already done so.
|
/// the host has not already done so.
|
||||||
pub fn process_wrapper<T, F: FnOnce() -> T>(f: F) -> T {
|
pub fn process_wrapper<T, F: FnOnce() -> T>(f: F) -> T {
|
||||||
|
// Make sure FTZ is always enabled, even if the host doesn't do it for us
|
||||||
|
let _ftz_guard = ScopedFtz::enable();
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(all(debug_assertions, feature = "assert_process_allocs"))] {
|
if #[cfg(all(debug_assertions, feature = "assert_process_allocs"))] {
|
||||||
assert_no_alloc::assert_no_alloc(f)
|
assert_no_alloc::assert_no_alloc(f)
|
||||||
|
@ -100,3 +104,54 @@ pub fn process_wrapper<T, F: FnOnce() -> T>(f: F) -> T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable the CPU's Flush To Zero flag while this object is in scope. If the flag was not already
|
||||||
|
/// set, it will be restored to its old value when this gets dropped.
|
||||||
|
struct ScopedFtz {
|
||||||
|
/// The old FTZ mode to restore to, if FTZ was not already set.
|
||||||
|
old_ftz_mode: Option<u32>,
|
||||||
|
/// We can't directly implement !Send and !Sync, but this will do the same thing. This object
|
||||||
|
/// affects the current thread's floating point registers, so it may only be dropped on the
|
||||||
|
/// current thread.
|
||||||
|
send_sync_marker: PhantomData<*const ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ScopedFtz {
|
||||||
|
fn enable() -> Self {
|
||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(target_feature = "sse")] {
|
||||||
|
let mode = unsafe { std::arch::x86_64::_MM_GET_FLUSH_ZERO_MODE() };
|
||||||
|
if mode != std::arch::x86_64::_MM_FLUSH_ZERO_ON {
|
||||||
|
unsafe { std::arch::x86_64::_MM_SET_FLUSH_ZERO_MODE(std::arch::x86_64::_MM_FLUSH_ZERO_ON) };
|
||||||
|
|
||||||
|
Self {
|
||||||
|
old_ftz_mode: Some(mode),
|
||||||
|
send_sync_marker: PhantomData,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Self {
|
||||||
|
old_ftz_mode: None,
|
||||||
|
send_sync_marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Self {
|
||||||
|
old_ftz_mode: None,
|
||||||
|
send_sync_marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for ScopedFtz {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Some(mode) = self.old_ftz_mode {
|
||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(target_feature = "sse")] {
|
||||||
|
unsafe { std::arch::x86_64::_MM_SET_FLUSH_ZERO_MODE(mode) };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue