【问题标题】:What's the difference between XMVectorSetByIndex when index = 0 and XMVectorSetX?index = 0 时的 XMVectorSetByIndex 和 XMVectorSetX 有什么区别?
【发布时间】:2016-08-21 09:21:39
【问题描述】:

看了DirectXMath库的源码,发现XMVectorSetByIndexXMVectorSetX的实现完全不同。为什么XMVectorSetX 不直接返回XMVectorSetByIndex (index = 0)?

【问题讨论】:

    标签: directx directx-11 directxmath


    【解决方案1】:

    XMVectorSetX 实际上能够使用 SSE 或 ARM-NEON 内部函数,而 XMVectorSetByIndex 必须“溢出到内存”(即它根本不是 SIMD)。

    // Set a single indexed floating point component
    inline XMVECTOR XM_CALLCONV XMVectorSetByIndex(FXMVECTOR V, float f, size_t i)
    {
        assert( i < 4 );
        _Analysis_assume_( i < 4 );
    #if defined(_XM_NO_INTRINSICS_)
        XMVECTOR U;
        U = V;
        U.vector4_f32[i] = f;
        return U;
    #elif defined(_XM_ARM_NEON_INTRINSICS_)
        XMVECTOR U = V;
        U.n128_f32[i] = f;
        return U;
    #elif defined(_XM_SSE_INTRINSICS_)
        XMVECTOR U = V;
        U.m128_f32[i] = f;
        return U;
    #endif
    }       
    

    对比

    // Sets the X component of a vector to a passed floating point value
    inline XMVECTOR XM_CALLCONV XMVectorSetX(FXMVECTOR V, float x)
    {
    #if defined(_XM_NO_INTRINSICS_)
        XMVECTOR U;
        U.vector4_f32[0] = x;
        U.vector4_f32[1] = V.vector4_f32[1];
        U.vector4_f32[2] = V.vector4_f32[2];
        U.vector4_f32[3] = V.vector4_f32[3];
        return U;
    #elif defined(_XM_ARM_NEON_INTRINSICS_)
        return vsetq_lane_f32(x,V,0);
    #elif defined(_XM_SSE_INTRINSICS_)
        XMVECTOR vResult = _mm_set_ss(x);
        vResult = _mm_move_ss(V,vResult);
        return vResult;
    #endif
    }
    

    查看XMVectorSetY 的情况以及/arch:AVX/arch:AVX2 能够使用SSE4 指令_mm_insert_ps 的情况非常有用,否则它必须做相当多的工作才能获得SIMD 代码生成不得不“溢出记忆”。

    inline XMVECTOR XM_CALLCONV XMVectorSetY(FXMVECTOR V, float y)
    {
    #if defined(_XM_NO_INTRINSICS_)
        XMVECTOR U;
        U.vector4_f32[0] = V.vector4_f32[0];
        U.vector4_f32[1] = y;
        U.vector4_f32[2] = V.vector4_f32[2];
        U.vector4_f32[3] = V.vector4_f32[3];
        return U;
    #elif defined(_XM_ARM_NEON_INTRINSICS_)
        return vsetq_lane_f32(y,V,1);
    #elif defined(_XM_SSE4_INTRINSICS_)
        XMVECTOR vResult = _mm_set_ss(y);
        vResult = _mm_insert_ps( V, vResult, 0x10 );
        return vResult;
    #elif defined(_XM_SSE_INTRINSICS_)
        // Swap y and x
        XMVECTOR vResult = XM_PERMUTE_PS(V,_MM_SHUFFLE(3,2,0,1));
        // Convert input to vector
        XMVECTOR vTemp = _mm_set_ss(y);
        // Replace the x component
        vResult = _mm_move_ss(vResult,vTemp);
        // Swap y and x again
        vResult = XM_PERMUTE_PS(vResult,_MM_SHUFFLE(3,2,0,1));
        return vResult;
    #endif
    }
    

    请注意,DirectXMath 现在可在 GitHub 上使用。

    【讨论】:

      猜你喜欢
      • 2013-06-11
      • 2016-03-23
      • 2021-06-16
      • 2015-05-11
      • 2015-04-08
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多