Simplified SIMD dispatch wrappers
This commit is contained in:
parent
75073cf8c0
commit
c0fac2cfbb
4 changed files with 277 additions and 129 deletions
|
|
@ -5,236 +5,361 @@
|
||||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||||
|
|
||||||
#include "SIMDHelpers.h"
|
#include "SIMDHelpers.h"
|
||||||
#include <array>
|
|
||||||
#include "cpuid/cpuinfo.hpp"
|
|
||||||
#include "SIMDConfig.h"
|
#include "SIMDConfig.h"
|
||||||
|
#include "Debug.h"
|
||||||
#include "simd/HelpersSSE.h"
|
#include "simd/HelpersSSE.h"
|
||||||
#include "simd/HelpersAVX.h"
|
#include "simd/HelpersAVX.h"
|
||||||
|
#include "cpuid/cpuinfo.hpp"
|
||||||
|
#include <array>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
namespace sfz {
|
namespace sfz {
|
||||||
|
|
||||||
static std::array<bool, static_cast<unsigned>(SIMDOps::_sentinel)> simdStatus;
|
template <class T>
|
||||||
static bool simdStatusInitialized = false;
|
struct SIMDDispatch {
|
||||||
static cpuid::cpuinfo cpuInfo;
|
constexpr SIMDDispatch() = default;
|
||||||
|
|
||||||
void resetSIMDStatus()
|
void resetStatus();
|
||||||
|
bool getStatus(SIMDOps op) const;
|
||||||
|
void setStatus(SIMDOps op, bool enable);
|
||||||
|
|
||||||
|
void (*writeInterleaved)(const T* inputLeft, const T* inputRight, T* output, unsigned outputSize) noexcept = &writeInterleavedScalar<float>;
|
||||||
|
void (*readInterleaved)(const T* input, T* outputLeft, T* outputRight, unsigned inputSize) noexcept = &readInterleavedScalar<float>;
|
||||||
|
void (*applyGain)(const T* gain, const T* input, T* output, unsigned size) noexcept = &applyGainScalar<float>;
|
||||||
|
void (*applyGain1)(T gain, const T* input, T* output, unsigned size) noexcept = &applyGainScalar<float>;
|
||||||
|
void (*divide)(const T* input, const T* divisor, T* output, unsigned size) noexcept = ÷Scalar<float>;
|
||||||
|
void (*multiplyAdd)(const T* gain, const T* input, T* output, unsigned size) noexcept = &multiplyAddScalar<float>;
|
||||||
|
void (*multiplyAdd1)(T gain, const T* input, T* output, unsigned size) noexcept = &multiplyAddScalar<float>;
|
||||||
|
T (*linearRamp)(T* output, T start, T step, unsigned size) noexcept = &linearRampScalar<float>;
|
||||||
|
T (*multiplicativeRamp)(T* output, T start, T step, unsigned size) noexcept = &multiplicativeRampScalar<float>;
|
||||||
|
void (*add)(const T* input, T* output, unsigned size) noexcept = &addScalar<float>;
|
||||||
|
void (*add1)(T value, T* output, unsigned size) noexcept = &addScalar<float>;
|
||||||
|
void (*subtract)(const T* input, T* output, unsigned size) noexcept = &subtractScalar<float>;
|
||||||
|
void (*subtract1)(T value, T* output, unsigned size) noexcept = &subtractScalar<float>;
|
||||||
|
void (*copy)(const T* input, T* output, unsigned size) noexcept = ©Scalar<float>;
|
||||||
|
void (*cumsum)(const T* input, T* output, unsigned size) noexcept = &cumsumScalar<float>;
|
||||||
|
void (*diff)(const T* input, T* output, unsigned size) noexcept = &diffScalar<float>;
|
||||||
|
T (*mean)(const T* vector, unsigned size) noexcept = &meanScalar<float>;
|
||||||
|
T (*meanSquared)(const T* vector, unsigned size) noexcept = &meanSquaredScalar<float>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<bool, static_cast<unsigned>(SIMDOps::_sentinel)> simdStatus;
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
static SIMDDispatch<float> simdDispatch;
|
||||||
|
|
||||||
|
void resetSIMDOpStatus()
|
||||||
{
|
{
|
||||||
simdStatus[static_cast<unsigned>(SIMDOps::writeInterleaved)] = false;
|
simdDispatch.resetStatus();
|
||||||
simdStatus[static_cast<unsigned>(SIMDOps::readInterleaved)] = false;
|
|
||||||
simdStatus[static_cast<unsigned>(SIMDOps::fill)] = true;
|
|
||||||
simdStatus[static_cast<unsigned>(SIMDOps::gain)] = true;
|
|
||||||
simdStatus[static_cast<unsigned>(SIMDOps::divide)] = false;
|
|
||||||
simdStatus[static_cast<unsigned>(SIMDOps::linearRamp)] = false;
|
|
||||||
simdStatus[static_cast<unsigned>(SIMDOps::multiplicativeRamp)] = true;
|
|
||||||
simdStatus[static_cast<unsigned>(SIMDOps::add)] = false;
|
|
||||||
simdStatus[static_cast<unsigned>(SIMDOps::subtract)] = false;
|
|
||||||
simdStatus[static_cast<unsigned>(SIMDOps::multiplyAdd)] = false;
|
|
||||||
simdStatus[static_cast<unsigned>(SIMDOps::copy)] = false;
|
|
||||||
simdStatus[static_cast<unsigned>(SIMDOps::cumsum)] = true;
|
|
||||||
simdStatus[static_cast<unsigned>(SIMDOps::diff)] = false;
|
|
||||||
simdStatus[static_cast<unsigned>(SIMDOps::sfzInterpolationCast)] = true;
|
|
||||||
simdStatus[static_cast<unsigned>(SIMDOps::mean)] = false;
|
|
||||||
simdStatus[static_cast<unsigned>(SIMDOps::meanSquared)] = false;
|
|
||||||
simdStatus[static_cast<unsigned>(SIMDOps::upsampling)] = true;
|
|
||||||
simdStatusInitialized = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSIMDOpStatus(SIMDOps op, bool status)
|
void setSIMDOpStatus(SIMDOps op, bool status)
|
||||||
{
|
{
|
||||||
if (!simdStatusInitialized)
|
simdDispatch.setStatus(op, status);
|
||||||
resetSIMDStatus();
|
|
||||||
|
|
||||||
simdStatus[static_cast<unsigned>(op)] = status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getSIMDOpStatus(SIMDOps op)
|
bool getSIMDOpStatus(SIMDOps op)
|
||||||
{
|
{
|
||||||
if (!simdStatusInitialized)
|
return simdDispatch.getStatus(op);
|
||||||
resetSIMDStatus();
|
|
||||||
|
|
||||||
return simdStatus[static_cast<unsigned>(op)];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
void readInterleaved(const float* input, float* outputLeft, float* outputRight, unsigned inputSize) noexcept
|
void readInterleaved(const float* input, float* outputLeft, float* outputRight, unsigned inputSize) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::readInterleaved)) {
|
return simdDispatch.readInterleaved(input, outputLeft, outputRight, inputSize);
|
||||||
if (cpuInfo.has_sse())
|
|
||||||
return readInterleavedSSE(input, outputLeft, outputRight, inputSize);
|
|
||||||
}
|
|
||||||
return readInterleavedScalar(input, outputLeft, outputRight, inputSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeInterleaved(const float* inputLeft, const float* inputRight, float* output, unsigned outputSize) noexcept
|
void writeInterleaved(const float* inputLeft, const float* inputRight, float* output, unsigned outputSize) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::writeInterleaved)) {
|
return simdDispatch.writeInterleaved(inputLeft, inputRight, output, outputSize);
|
||||||
if (cpuInfo.has_sse())
|
|
||||||
return writeInterleavedSSE(inputLeft, inputRight, output, outputSize);
|
|
||||||
}
|
|
||||||
return writeInterleavedScalar(inputLeft, inputRight, output, outputSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void applyGain<float>(float gain, const float* input, float* output, unsigned size) noexcept
|
void applyGain<float>(float gain, const float* input, float* output, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::gain)) {
|
return simdDispatch.applyGain1(gain, input, output, size);
|
||||||
if (cpuInfo.has_avx())
|
|
||||||
return applyGainAVX(gain, input, output, size);
|
|
||||||
else if (cpuInfo.has_sse())
|
|
||||||
return applyGainSSE(gain, input, output, size);
|
|
||||||
}
|
|
||||||
return applyGainScalar(gain, input, output, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void applyGain<float>(const float* gain, const float* input, float* output, unsigned size) noexcept
|
void applyGain<float>(const float* gain, const float* input, float* output, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::gain)) {
|
return simdDispatch.applyGain(gain, input, output, size);
|
||||||
if (cpuInfo.has_avx())
|
|
||||||
return applyGainAVX(gain, input, output, size);
|
|
||||||
else if (cpuInfo.has_sse())
|
|
||||||
return applyGainSSE(gain, input, output, size);
|
|
||||||
}
|
|
||||||
return applyGainScalar(gain, input, output, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void divide<float>(const float* input, const float* divisor, float* output, unsigned size) noexcept
|
void divide<float>(const float* input, const float* divisor, float* output, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::divide)) {
|
return simdDispatch.divide(input, divisor, output, size);
|
||||||
if (cpuInfo.has_sse())
|
|
||||||
return divideSSE(input, divisor, output, size);
|
|
||||||
}
|
|
||||||
return divideScalar(input, divisor, output, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void multiplyAdd<float>(const float* gain, const float* input, float* output, unsigned size) noexcept
|
void multiplyAdd<float>(const float* gain, const float* input, float* output, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::multiplyAdd)) {
|
return simdDispatch.multiplyAdd(gain, input, output, size);
|
||||||
if (cpuInfo.has_sse())
|
|
||||||
return multiplyAddSSE(gain, input, output, size);
|
|
||||||
}
|
|
||||||
return multiplyAddScalar(gain, input, output, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void multiplyAdd<float>(float gain, const float* input, float* output, unsigned size) noexcept
|
void multiplyAdd<float>(float gain, const float* input, float* output, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::multiplyAdd)) {
|
return simdDispatch.multiplyAdd1(gain, input, output, size);
|
||||||
if (cpuInfo.has_sse())
|
|
||||||
return multiplyAddSSE(gain, input, output, size);
|
|
||||||
}
|
|
||||||
return multiplyAddScalar(gain, input, output, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
float linearRamp<float>(float* output, float start, float step, unsigned size) noexcept
|
float linearRamp<float>(float* output, float start, float step, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::linearRamp)) {
|
return simdDispatch.linearRamp(output, start, step, size);
|
||||||
if (cpuInfo.has_sse())
|
|
||||||
return linearRampSSE(output, start, step, size);
|
|
||||||
}
|
|
||||||
return linearRampScalar(output, start, step, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
float multiplicativeRamp<float>(float* output, float start, float step, unsigned size) noexcept
|
float multiplicativeRamp<float>(float* output, float start, float step, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::multiplicativeRamp)) {
|
return simdDispatch.multiplicativeRamp(output, start, step, size);
|
||||||
if (cpuInfo.has_sse())
|
|
||||||
return multiplicativeRampSSE(output, start, step, size);
|
|
||||||
}
|
|
||||||
return multiplicativeRampScalar(output, start, step, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void add<float>(const float* input, float* output, unsigned size) noexcept
|
void add<float>(const float* input, float* output, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::add)) {
|
return simdDispatch.add(input, output, size);
|
||||||
if (cpuInfo.has_sse())
|
|
||||||
return addSSE(input, output, size);
|
|
||||||
}
|
|
||||||
return addScalar(input, output, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void add<float>(float value, float* output, unsigned size) noexcept
|
void add<float>(float value, float* output, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::add)) {
|
return simdDispatch.add1(value, output, size);
|
||||||
if (cpuInfo.has_sse())
|
|
||||||
return addSSE(value, output, size);
|
|
||||||
}
|
|
||||||
return addScalar(value, output, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void subtract<float>(const float* input, float* output, unsigned size) noexcept
|
void subtract<float>(const float* input, float* output, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::subtract)) {
|
return simdDispatch.subtract(input, output, size);
|
||||||
if (cpuInfo.has_sse())
|
|
||||||
return subtractSSE(input, output, size);
|
|
||||||
}
|
|
||||||
return subtractScalar(input, output, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void subtract<float>(float value, float* output, unsigned size) noexcept
|
void subtract<float>(float value, float* output, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::subtract)) {
|
return simdDispatch.subtract1(value, output, size);
|
||||||
if (cpuInfo.has_sse())
|
|
||||||
return subtractSSE(value, output, size);
|
|
||||||
}
|
|
||||||
return subtractScalar(value, output, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void copy<float>(const float* input, float* output, unsigned size) noexcept
|
void copy<float>(const float* input, float* output, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::copy)) {
|
return simdDispatch.copy(input, output, size);
|
||||||
if (cpuInfo.has_sse())
|
|
||||||
return copySSE(input, output, size);
|
|
||||||
}
|
|
||||||
std::copy(input, input + size, output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
float mean<float>(const float* vector, unsigned size) noexcept
|
float mean<float>(const float* vector, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::mean)) {
|
return simdDispatch.mean(vector, size);
|
||||||
if (cpuInfo.has_sse())
|
|
||||||
return meanSSE(vector, size);
|
|
||||||
}
|
|
||||||
return meanScalar(vector, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
float meanSquared<float>(const float* vector, unsigned size) noexcept
|
float meanSquared<float>(const float* vector, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::meanSquared)) {
|
return simdDispatch.meanSquared(vector, size);
|
||||||
if (cpuInfo.has_sse())
|
|
||||||
return meanSquaredSSE(vector, size);
|
|
||||||
}
|
|
||||||
return meanSquaredScalar(vector, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void cumsum<float>(const float* input, float* output, unsigned size) noexcept
|
void cumsum<float>(const float* input, float* output, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::cumsum)) {
|
return simdDispatch.cumsum(input, output, size);
|
||||||
if (cpuInfo.has_sse())
|
|
||||||
return cumsumSSE(input, output, size);
|
|
||||||
}
|
|
||||||
return cumsumScalar(input, output, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void diff<float>(const float* input, float* output, unsigned size) noexcept
|
void diff<float>(const float* input, float* output, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
if (getSIMDOpStatus(SIMDOps::diff)) {
|
return simdDispatch.diff(input, output, size);
|
||||||
if (cpuInfo.has_sse())
|
}
|
||||||
return diffSSE(input, output, size);
|
|
||||||
|
///
|
||||||
|
|
||||||
|
static cpuid::cpuinfo& cpuInfo()
|
||||||
|
{
|
||||||
|
static cpuid::cpuinfo info;
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
bool SIMDDispatch<T>::getStatus(SIMDOps op) const
|
||||||
|
{
|
||||||
|
const unsigned index = static_cast<unsigned>(op);
|
||||||
|
ASSERT(index < simdStatus.size());
|
||||||
|
return simdStatus[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void SIMDDispatch<T>::setStatus(SIMDOps op, bool enable)
|
||||||
|
{
|
||||||
|
const unsigned index = static_cast<unsigned>(op);
|
||||||
|
ASSERT(index < simdStatus.size());
|
||||||
|
|
||||||
|
simdStatus[index] = enable;
|
||||||
|
|
||||||
|
const cpuid::cpuinfo& info = cpuInfo();
|
||||||
|
bool useSSE = enable && info.has_sse();
|
||||||
|
bool useAVX = enable && info.has_avx();
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIMDOps::writeInterleaved:
|
||||||
|
if (useSSE)
|
||||||
|
writeInterleaved = &writeInterleavedSSE;
|
||||||
|
else
|
||||||
|
writeInterleaved = &writeInterleavedScalar<float>;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIMDOps::readInterleaved:
|
||||||
|
if (useSSE)
|
||||||
|
readInterleaved = &readInterleavedSSE;
|
||||||
|
else
|
||||||
|
readInterleaved = &readInterleavedScalar<float>;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIMDOps::gain:
|
||||||
|
if (useAVX) {
|
||||||
|
applyGain = &applyGainAVX;
|
||||||
|
applyGain1 = &applyGainAVX;
|
||||||
|
}
|
||||||
|
else if (useSSE) {
|
||||||
|
applyGain = &applyGainSSE;
|
||||||
|
applyGain1 = &applyGainSSE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
applyGain = &applyGainScalar<float>;
|
||||||
|
applyGain1 = &applyGainScalar<float>;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIMDOps::divide:
|
||||||
|
if (useSSE)
|
||||||
|
divide = ÷SSE;
|
||||||
|
else
|
||||||
|
divide = ÷Scalar<float>;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIMDOps::multiplyAdd:
|
||||||
|
if (useSSE) {
|
||||||
|
multiplyAdd = &multiplyAddSSE;
|
||||||
|
multiplyAdd1 = &multiplyAddSSE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
multiplyAdd = &multiplyAddScalar<float>;
|
||||||
|
multiplyAdd1 = &multiplyAddScalar<float>;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIMDOps::linearRamp:
|
||||||
|
if (useSSE)
|
||||||
|
linearRamp = &linearRampSSE;
|
||||||
|
else
|
||||||
|
linearRamp = &linearRampScalar<float>;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIMDOps::multiplicativeRamp:
|
||||||
|
if (useSSE)
|
||||||
|
multiplicativeRamp = &multiplicativeRampSSE;
|
||||||
|
else
|
||||||
|
multiplicativeRamp = &multiplicativeRampScalar<float>;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIMDOps::add:
|
||||||
|
if (useSSE) {
|
||||||
|
add = &addSSE;
|
||||||
|
add1 = &addSSE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
add = &addScalar<float>;
|
||||||
|
add1 = &addScalar<float>;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIMDOps::subtract:
|
||||||
|
if (useSSE) {
|
||||||
|
subtract = &subtractSSE;
|
||||||
|
subtract1 = &subtractSSE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
subtract = &subtractScalar<float>;
|
||||||
|
subtract1 = &subtractScalar<float>;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIMDOps::copy:
|
||||||
|
if (useSSE)
|
||||||
|
copy = ©SSE;
|
||||||
|
else
|
||||||
|
copy = ©Scalar<float>;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIMDOps::cumsum:
|
||||||
|
if (useSSE)
|
||||||
|
cumsum = &cumsumSSE;
|
||||||
|
else
|
||||||
|
cumsum = &cumsumScalar<float>;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIMDOps::diff:
|
||||||
|
if (useSSE)
|
||||||
|
diff = &diffSSE;
|
||||||
|
else
|
||||||
|
diff = &diffScalar<float>;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIMDOps::mean:
|
||||||
|
if (useSSE)
|
||||||
|
mean = &meanSSE;
|
||||||
|
else
|
||||||
|
mean = &meanScalar<float>;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIMDOps::meanSquared:
|
||||||
|
if (useSSE)
|
||||||
|
meanSquared = &meanSquaredSSE;
|
||||||
|
else
|
||||||
|
meanSquared = &meanSquaredScalar<float>;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void SIMDDispatch<T>::resetStatus()
|
||||||
|
{
|
||||||
|
setStatus(SIMDOps::writeInterleaved, false);
|
||||||
|
setStatus(SIMDOps::readInterleaved, false);
|
||||||
|
setStatus(SIMDOps::fill, true);
|
||||||
|
setStatus(SIMDOps::gain, true);
|
||||||
|
setStatus(SIMDOps::divide, false);
|
||||||
|
setStatus(SIMDOps::linearRamp, false);
|
||||||
|
setStatus(SIMDOps::multiplicativeRamp, true);
|
||||||
|
setStatus(SIMDOps::add, false);
|
||||||
|
setStatus(SIMDOps::subtract, false);
|
||||||
|
setStatus(SIMDOps::multiplyAdd, false);
|
||||||
|
setStatus(SIMDOps::copy, false);
|
||||||
|
setStatus(SIMDOps::cumsum, true);
|
||||||
|
setStatus(SIMDOps::diff, false);
|
||||||
|
setStatus(SIMDOps::sfzInterpolationCast, true);
|
||||||
|
setStatus(SIMDOps::mean, false);
|
||||||
|
setStatus(SIMDOps::meanSquared, false);
|
||||||
|
setStatus(SIMDOps::upsampling, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
static volatile bool simdInitialized = false;
|
||||||
|
static std::mutex simdMutex;
|
||||||
|
|
||||||
|
SIMDInitializer::SIMDInitializer()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock { simdMutex };
|
||||||
|
|
||||||
|
if (!simdInitialized) {
|
||||||
|
simdDispatch.resetStatus();
|
||||||
|
simdInitialized = true;
|
||||||
}
|
}
|
||||||
return diffScalar(input, output, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,15 @@ enum class SIMDOps {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Enable or disable SIMD accelerators at runtime
|
// Enable or disable SIMD accelerators at runtime
|
||||||
|
void resetSIMDOpStatus();
|
||||||
void setSIMDOpStatus(SIMDOps op, bool status);
|
void setSIMDOpStatus(SIMDOps op, bool status);
|
||||||
bool getSIMDOpStatus(SIMDOps op);
|
bool getSIMDOpStatus(SIMDOps op);
|
||||||
|
|
||||||
|
// Initializer object which ensures to prepare SIMD dispatch
|
||||||
|
struct SIMDInitializer {
|
||||||
|
SIMDInitializer();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read interleaved stereo data from a buffer and separate it in a left/right pair of buffers.
|
* @brief Read interleaved stereo data from a buffer and separate it in a left/right pair of buffers.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,10 @@
|
||||||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline void readInterleavedScalar(const T* input, T* outputLeft, T* outputRight, unsigned inputSize)
|
inline void readInterleavedScalar(const T* input, T* outputLeft, T* outputRight, unsigned inputSize) noexcept
|
||||||
{
|
{
|
||||||
const auto sentinel = input + inputSize - 1;
|
const auto sentinel = input + inputSize - 1;
|
||||||
while (input < sentinel) {
|
while (input < sentinel) {
|
||||||
|
|
@ -17,7 +18,7 @@ inline void readInterleavedScalar(const T* input, T* outputLeft, T* outputRight,
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline void writeInterleavedScalar(const T* inputLeft, const T* inputRight, T* output, unsigned outputSize)
|
inline void writeInterleavedScalar(const T* inputLeft, const T* inputRight, T* output, unsigned outputSize) noexcept
|
||||||
{
|
{
|
||||||
const auto sentinel = output + outputSize - 1;
|
const auto sentinel = output + outputSize - 1;
|
||||||
while (output < sentinel) {
|
while (output < sentinel) {
|
||||||
|
|
@ -120,6 +121,12 @@ inline void subtractScalar(T value, T* output, unsigned size) noexcept
|
||||||
*output++ -= value;
|
*output++ -= value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void copyScalar(const T* input, T* output, unsigned size) noexcept
|
||||||
|
{
|
||||||
|
std::copy(input, input + size, output);
|
||||||
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
T meanScalar(const T* vector, unsigned size) noexcept
|
T meanScalar(const T* vector, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,12 @@
|
||||||
#define CATCH_CONFIG_MAIN
|
#include "sfizz/SIMDHelpers.h"
|
||||||
#include "catch2/catch.hpp"
|
|
||||||
|
#define CATCH_CONFIG_RUNNER
|
||||||
|
#include "catch2/catch.hpp"
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
sfz::SIMDInitializer simdInit;
|
||||||
|
|
||||||
|
int result = Catch::Session().run(argc, argv);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue