c++ - float4::set_wxy(和其他 set-swizzle 操作)的更好 SSE2 实现?

标签 c++ sse simd intrinsics sse2

我正在使用 SSE2/AVX 内在函数在 C++ 中编写 HLSL float4 兼容类型,目前我正在 HLSL 中实现所有可用于 float4 的 set-swizzle 操作。我正在尝试找出一个最佳的 SSE2 实现来处理涉及 (swizzle) 设置 2 或 3 个组件的 set-swizzle 操作(因为 4-component set-swizzles 使用一个 SSE shuffle op 来实现是微不足道的)。例如,如果没有至少 4/5 SSE shuffle 操作,我想不出更好的方法来实现 set_wxy,例如:

inline/__forceinline void float4::set_wxy(const float4& x)
{
    float4 tmp2 = *this;
    tmp2.set_wxyz(x);                         // set_wxyz = 1 x _mm_shuffle_ps
    const __m128 xyw_tmp = tmp2.zxyw().data;  // zxyw() = 1 x _mm_shuffle_ps
    const __m128 z_tmp = zxyw().data;         // zxyw() = 1 x _mm_shuffle_ps
    tmp2 = _mm_move_ss(xyw_tmp, z_tmp);
    set_zxyw(tmp2);                           // set_zxyw() = 1 x _mm_shuffle_ps
}

在不使用 SSE2 以外的操作的情况下,有没有人有更好的实现的想法?因为我知道 SSE4/AVX 中的 _mm_blend_ps,我将在通过预处理器条件可用时使用它,但我想至少支持仅 SSE2 的代码路径。提前致谢!

编辑:此函数的行为示例是:

float4 k(5,5,5,5);
k.set_wxy(float4(1,2,3,4));
// now k == (2, 3, 5, 1)

基本上 set_wxy 使用 x,y,z 的参数按顺序设置 w,x,y 分量,保留原始 z 值。

最佳答案

您正在尝试模拟这行 HLSL,对吗?

vec2.wxy = vec1.xyz;

利用 _mm_shuffle_ps 可以以一种有限的方式组合两个 vector 这一事实,您可以有所收获。这是我的尝试:

// xyzw is vec1, XYZW is vec2
__m128 xxZZ = _mm_shuffle_ps(vec1, vec2, _MM_SHUFFLE(2, 2, 0, 0));
__m128 ZxZx = _mm_shuffle_ps(xxZZ, xxZZ, _MM_SHUFFLE(0, 2, 0, 2));
__m128 yzZx = _mm_shuffle_ps(vec1, ZxZx, _MM_SHUFFLE(1, 0, 2, 1));

vec2 = yzZx;

关于c++ - float4::set_wxy(和其他 set-swizzle 操作)的更好 SSE2 实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11384503/

相关文章:

c++ - VC++ Express 2008 中的错误 LNK2019 和 LNK2028

c++ - 满足条件后如何终止函数

simd - AVX512中有没有像_mm512_sign_epi16 (__m512i a, __m512i b)这样的函数

algorithm - 当您有先前的答案时,更快的计算模数的方法?

assembly - 在 double/simd 中构建 2^n

c++ - 可以组合部分模板特化来生成隐式生成的共享代码路径吗?

c++ - C++ 20:左半部分或右半部分是否有子范围?

c++ - 用于 float 阈值操作的 SIMD

c - 使用 SSE/SSE2 对 2*Pi 取模

c - SSE 内部函数 : Fastest way to test for all 0s or 1s?