我正在使用SSE2 / AVX内在函数在C中编写符合HLSL float4的类型,目前我正在实现HLSL中所有可用于float4的set-swizzle操作.我正在试图找出一个最佳的SSE2实现来处理涉及(swizzle)设置2或3组件的set-swizzle操作(因为4组件set-swizzle对于一个SSE shuffle op来实现是微不足道的).例如,我无法想出一个更好的方法来实现说set_wxy而不至少4/5 SSE shuffle ops例如:
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); k.set_wxy(float4(1,2,3,4)); // now k == (2,1)
基本上,set_wxy使用x,y,z的参数按此顺序设置w,x,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,0)); __m128 ZxZx = _mm_shuffle_ps(xxZZ,xxZZ,_MM_SHUFFLE(0,2)); __m128 yzZx = _mm_shuffle_ps(vec1,ZxZx,_MM_SHUFFLE(1,1)); vec2 = yzZx;