Browse Source

Add SIMD methods to Port.

tags/v1.0.0
Andrew Belt 5 years ago
parent
commit
9e830a61e6
2 changed files with 36 additions and 2 deletions
  1. +25
    -0
      include/engine/Port.hpp
  2. +11
    -2
      include/simd/vector.hpp

+ 25
- 0
include/engine/Port.hpp View File

@@ -96,6 +96,31 @@ struct alignas(32) Port {
return sum; return sum;
} }


template <typename T>
T getVoltageSimd(int firstChannel) {
return T::load(&voltages[firstChannel]);
}

template <typename T>
T getPolyVoltageSimd(int firstChannel) {
return (channels == 1) ? getVoltage(0) : getVoltageSimd<T>(firstChannel);
}

template <typename T>
T getNormalVoltageSimd(T normalVoltage, int firstChannel) {
return isConnected() ? getVoltageSimd<T>(firstChannel) : normalVoltage;
}

template <typename T>
T getNormalPolyVoltageSimd(T normalVoltage, int firstChannel) {
return isConnected() ? getPolyVoltageSimd<T>(firstChannel) : normalVoltage;
}

template <typename T>
void setVoltageSimd(T voltage, int firstChannel) {
voltage.store(&voltages[firstChannel]);
}

/** Sets the number of polyphony channels. /** Sets the number of polyphony channels.
Also clears voltages of higher channels. Also clears voltages of higher channels.
If disconnected, this does nothing (`channels` remains 0). If disconnected, this does nothing (`channels` remains 0).


+ 11
- 2
include/simd/vector.hpp View File

@@ -63,7 +63,14 @@ struct Vector<float, 4> {
return _mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128())); return _mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128()));
} }


/** Reads an array of 4 values. */
/** Constructs a vector from four values in reverse. */
static Vector setr(float x1, float x2, float x3, float x4) {
return Vector(_mm_setr_ps(x1, x2, x3, x4));
}

/** Reads an array of 4 values.
On little-endian machines (e.g. x86), the order is reversed, so `x[0]` corresponds to `vector.s[3]`.
*/
static Vector load(const float *x) { static Vector load(const float *x) {
/* /*
My benchmarks show that _mm_loadu_ps() performs equally as fast as _mm_load_ps() when data is actually aligned. My benchmarks show that _mm_loadu_ps() performs equally as fast as _mm_load_ps() when data is actually aligned.
@@ -73,7 +80,9 @@ struct Vector<float, 4> {
return Vector(_mm_loadu_ps(x)); return Vector(_mm_loadu_ps(x));
} }


/** Writes an array of 4 values. */
/** Writes an array of 4 values.
On little-endian machines (e.g. x86), the order is reversed, so `x[0]` corresponds to `vector.s[3]`.
*/
void store(float *x) { void store(float *x) {
_mm_storeu_ps(x, v); _mm_storeu_ps(x, v);
} }


Loading…
Cancel
Save