Template issue (weird?)

This commit is contained in:
Paul Ferrand 2019-08-04 16:42:44 +02:00
parent 2a87e873d6
commit ea4e72e6f6
7 changed files with 65 additions and 64 deletions

View file

@ -79,7 +79,6 @@ set(COMMON_SOURCES
sources/Synth.cpp sources/Synth.cpp
sources/FilePool.cpp sources/FilePool.cpp
sources/Region.cpp sources/Region.cpp
sources/StereoBuffer.cpp
sources/Parser.cpp sources/Parser.cpp
) )

View file

@ -4,7 +4,7 @@
#include <cstdlib> #include <cstdlib>
#include <memory> #include <memory>
template<class Type, unsigned int Alignment = config::defaultAlignment> template<class Type, unsigned int Alignment = SIMDConfig::defaultAlignment>
class Buffer class Buffer
{ {
public: public:

View file

@ -46,7 +46,7 @@ public:
auto preloadedSize = std::min(returnedValue.end, static_cast<uint32_t>(config::preloadSize)); auto preloadedSize = std::min(returnedValue.end, static_cast<uint32_t>(config::preloadSize));
returnedValue.preloadedData = std::make_shared<StereoBuffer<float>>(preloadedSize); returnedValue.preloadedData = std::make_shared<StereoBuffer<float>>(preloadedSize);
sndFile.readf(tempReadBuffer.data(), preloadedSize); sndFile.readf(tempReadBuffer.data(), preloadedSize);
returnedValue.preloadedData->readInterleaved(tempReadBuffer.data(), preloadedSize); returnedValue.preloadedData->readInterleaved<SIMDConfig::supported>(tempReadBuffer.data(), preloadedSize);
preloadedData[filename] = returnedValue.preloadedData; preloadedData[filename] = returnedValue.preloadedData;
// char buffer [2048] ; // char buffer [2048] ;
// sndFile.command(SFC_GET_LOG_INFO, buffer, sizeof(buffer)) ; // sndFile.command(SFC_GET_LOG_INFO, buffer, sizeof(buffer)) ;

View file

@ -21,10 +21,14 @@ namespace config
} // namespace sfz } // namespace sfz
enum class SIMD { scalar, sse, neon }; enum class SIMD { scalar, sse, neon };
namespace config namespace SIMDConfig
{ {
inline constexpr unsigned int defaultAlignment { 16 }; inline constexpr unsigned int defaultAlignment { 16 };
inline constexpr SIMD vectorOperation { SIMD::scalar }; #if HAVE_X86INTRIN_H || HAVE_INTRIN_H
inline constexpr SIMD supported { SIMD::sse };
#else
inline constexpr SIMD supported {SIMD::scalar};
#endif
} // namespace config } // namespace config
#if HAVE_X86INTRIN_H #if HAVE_X86INTRIN_H

View file

@ -7,6 +7,7 @@
#include "EGDescription.h" #include "EGDescription.h"
#include "Defaults.h" #include "Defaults.h"
#include "CCMap.h" #include "CCMap.h"
namespace sfz namespace sfz
{ {
struct Region struct Region

View file

@ -1,58 +0,0 @@
#include "StereoBuffer.h"
template<>
template<>
void StereoBuffer<float>::readInterleaved<SIMD::sse>(float* input, int numFrames) noexcept
{
ASSERT(this->numFrames >= numFrames);
const int residualFrames = numFrames & (2 * TypeAlignment - 1);
const int lastAligned = numFrames - residualFrames;
float* in = input;
auto [lOut, rOut] = getChannels();
const float* end = input + 2 * lastAligned;
while (in < end)
{
auto register0 = _mm_loadu_ps(in);
in += 4;
auto register1 = _mm_loadu_ps(in);
in += 4;
auto register2 = register0;
// register 2 holds the copy of register 0 that is going to get erased by the first operation
// Remember that the bit mask reads from the end; 10 00 10 00 means
// "take 0 from a, take 2 from a, take 0 from b, take 2 from b"
register0 = _mm_shuffle_ps(register0, register1, 0b10001000);
register1 = _mm_shuffle_ps(register2, register1, 0b11011101);
_mm_store_ps(lOut, register0);
_mm_store_ps(rOut, register1);
lOut += 4;
rOut += 4;
}
end = input + numChannels * numFrames;
while (in < end)
{
*lOut = *in;
in++;
*rOut = *in;
in++;
lOut += 1;
rOut += 1;
}
}
template<>
template<>
void StereoBuffer<float, 16>::fill<SIMD::sse>(float value) noexcept
{
const __m128 mmValue = _mm_set_ps1(value);
auto [lBegin, rBegin] = getChannels();
auto [lEnd, rEnd] = alignedEnds();
auto mmLeft = reinterpret_cast<__m128*>(lBegin);
auto mmRight = reinterpret_cast<__m128*>(rBegin);
while(mmLeft < reinterpret_cast<__m128*>(lEnd)) // we should only need to test a single channel
{
_mm_store_ps(reinterpret_cast<float*>(mmLeft), mmValue);
_mm_store_ps(reinterpret_cast<float*>(mmRight), mmValue);
mmLeft++;
mmRight++;
}
}

View file

@ -8,7 +8,7 @@
enum class Channel {left, right}; enum class Channel {left, right};
template<class Type, unsigned int Alignment = config::defaultAlignment> template<class Type, unsigned int Alignment = SIMDConfig::defaultAlignment>
class StereoBuffer class StereoBuffer
{ {
public: public:
@ -70,6 +70,61 @@ public:
} }
} }
template <>
void readInterleaved<SIMD::sse>(float *input, int numFrames) noexcept
{
ASSERT(this->numFrames >= numFrames);
const int residualFrames = numFrames & (2 * TypeAlignment - 1);
const int lastAligned = numFrames - residualFrames;
float *in = input;
auto [lOut, rOut] = getChannels();
const float *end = input + 2 * lastAligned;
while (in < end)
{
auto register0 = _mm_loadu_ps(in);
in += 4;
auto register1 = _mm_loadu_ps(in);
in += 4;
auto register2 = register0;
// register 2 holds the copy of register 0 that is going to get erased by the first operation
// Remember that the bit mask reads from the end; 10 00 10 00 means
// "take 0 from a, take 2 from a, take 0 from b, take 2 from b"
register0 = _mm_shuffle_ps(register0, register1, 0b10001000);
register1 = _mm_shuffle_ps(register2, register1, 0b11011101);
_mm_store_ps(lOut, register0);
_mm_store_ps(rOut, register1);
lOut += 4;
rOut += 4;
}
end = input + numChannels * numFrames;
while (in < end)
{
*lOut = *in;
in++;
*rOut = *in;
in++;
lOut += 1;
rOut += 1;
}
}
template<>
void fill<SIMD::sse>(float value) noexcept
{
const __m128 mmValue = _mm_set_ps1(value);
auto [lBegin, rBegin] = getChannels();
auto [lEnd, rEnd] = alignedEnds();
auto mmLeft = reinterpret_cast<__m128 *>(lBegin);
auto mmRight = reinterpret_cast<__m128 *>(rBegin);
while (mmLeft < reinterpret_cast<__m128 *>(lEnd)) // we should only need to test a single channel
{
_mm_store_ps(reinterpret_cast<float *>(mmLeft), mmValue);
_mm_store_ps(reinterpret_cast<float *>(mmRight), mmValue);
mmLeft++;
mmRight++;
}
}
Type* getChannel(Channel channel) noexcept Type* getChannel(Channel channel) noexcept
{ {
switch(channel) switch(channel)