对于float4 :: set_wxy(和其他set-swizzle操作符)更好的SSE2实现?
问题描述:
我正在使用SSE2/AVX内在函数编写C++中的HLSL float4兼容类型,此刻我正在实现HLSL中用于float4的所有set-swizzle操作。我试图找出一个最佳的SSE2实现来处理涉及(swizzle)设置2个或3个组件的set-swizzle操作(因为使用一个SSE shuffle op实现4个组件集合 - swizzle是微不足道的)。例如,我不能没有至少4/5 SSE洗牌OPS例如为:找出实现一个更好的办法说set_wxy对于float4 :: set_wxy(和其他set-swizzle操作符)更好的SSE2实现?
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设置W,X,使用X,Y,Z的参数以该顺序y分量,原始Z值被保留。
答
你想模仿HLSL的这一行,对吧?
vec2.wxy = vec1.xyz;
您可以通过使用一个事实,即_mm_shuffle_ps
可以在某种方式有限的结合两个向量得到的地方。这是我的刺伤:
// 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;
什么是set_wxy应该这样做,究竟是什么?我试图从代码中推断出来,但其中太多内容是隐藏的。 – harold 2012-07-08 16:09:41
@harold好吧我刚刚添加了一些关于这些函数行为的更多信息,我希望这可以清理一些东西。谢谢阅读。 – 2012-07-08 16:25:40
查看Windows 8 SDK('DirectXMath.h')中DirectXMath的源代码,它具有非常快速的SSE2操作系统,用于swizzles等(并且它的编写符合DX&HLSL)。 TBH,你可以直接使用DX数学,节省你的努力 – Necrolis 2012-07-08 16:29:35