【问题标题】:C++ template related error with XMVectorPermute与 XMVectorPermute 相关的 C++ 模板相关错误
【发布时间】:2019-02-15 05:02:17
【问题描述】:

我是 DirectX11 的新手,我正在尝试将使用 DirectX Legacy 编写的文件改编为新的 DirectX,但我在使用模板 XMVectorPermute 时遇到了一些问题,它曾经是 Legacy 文件中的一个函数。

我正在尝试让编译器识别DirectXMath.h 中的模板:

// General permute template
template<uint32_t PermuteX, uint32_t PermuteY, uint32_t PermuteZ, uint32_t PermuteW>
    inline XMVECTOR     XM_CALLCONV     XMVectorPermute(FXMVECTOR V1, FXMVECTOR V2)
{
   //...Definition

使用以下代码:

template DirectX::XMVECTOR  DirectX::XMVectorPermute<PermuteXXY.i[0], PermuteXXY.i[1], PermuteXXY.i[2], PermuteXXY.i[3]>(FXMVECTOR V1, FXMVECTOR V2);

其中PermuteXXY定义为:

static CONST DirectX::XMVECTORI32 PermuteXXY =
{
    DirectX::XM_PERMUTE_0X, DirectX::XM_PERMUTE_0X, DirectX::XM_PERMUTE_0Y, DirectX::XM_PERMUTE_0W
};

但编译器或链接器无法匹配: Error reported

XM_PERMUTE_...DirectXMath.h中定义为const uint32_tXMVECTORI32定义为联合:

union
    {
        int32_t i[4];
        XMVECTOR v;
    };

我不太擅长 c++ 模板,所以请尽可能彻底地帮助我。非常感谢!

【问题讨论】:

  • 传递给模板版本的模板参数必须是编译时值,而不是变量。可能constexpr 可以在这里做一些有趣的事情,但我还没有尝试过,迄今为止DirectXMath 对 C++11/C++14/C++17 语言特性的使用相当少。如果您知道您的代码将始终使用相同的模式,请更改代码以使用新的模板版本。否则,使用参数版本。
  • 顺便说一句,你读过porting guide吗?
  • 谢谢! constexpr 确实有助于解决这种情况,程序现在可以通过编译。 @Chuck Walbourn

标签: c++ directx directx-11 directxmath


【解决方案1】:

这里有几个问题会导致您的代码失败。

首先,您不能使用XMVECTORI32 的成员向XMVectorPermute 提供模板参数。这不是因为类型差异(XMVECTORU32 也会发生同样的事情)。我相信这个问题是因为数组i 没有声明为const,并且值必须是常量才能用作模板参数。无论如何,VS2017拒绝编译代码。

其次,如果不为该函数提供主体,就无法专门化模板函数。这意味着您的第二行不完整,需要您编写一个实现才能编译。

但这并不意味着你是 SOL,只是你需要改变你的方法。如果模板参数始终是常量(在您的代码中看起来应该如此),您可以定义一个函数,该函数采用两个向量参数并指定用于该特定操作的确切置换常量。

下面的代码就是一个例子:

DirectX::XMVECTOR XMVectorPermuteXXY(DirectX::FXMVECTOR V1, DirectX::FXMVECTOR V2)
{
    return DirectX::XMVectorPermute<DirectX::XM_PERMUTE_0X,
                                    DirectX::XM_PERMUTE_0X, 
                                    DirectX::XM_PERMUTE_0Y,
                                    DirectX::XM_PERMUTE_0W>(V1, V2);
}

任何其他需要指定的操作(XYXY、ZZWW、YYWZ 等)都可以用类似的方式定义,使用指定正确模板参数的包装函数。

第二种选择是使用XMVectorPermute 的非模板版本,它采用两个向量和四个置换常数。此版本可能会慢一些,但允许您在运行时指定置换常量。

该代码如下所示:

XMVECTOR XMVectorPermuteXXY(FXMVECTOR V1, FXMVECTOR V2)
{
    return XMVectorPermute(V1, V2, 
                           XM_PERMUTE_0X, 
                           XM_PERMUTE_0X, 
                           XM_PERMUTE_0Y, 
                           XM_PERMUTE_0W);
}

根据您要迁移的代码,您需要确定计划使用的版本。

【讨论】:

  • 当我从 xboxmath/xnamath 转到 DirectXMath 时,如何处理 XMVectorPermute 绝对是一个挑战。最初的实现在带有 VMX128 指令集的 Xbox 360 上运行良好,但在 SSE 上总是很糟糕。引入XMVectorPermuteXMVectorSwizzle 的模板版本是为了尝试为SSE ​​优化类似的东西。如果 OP 使用旧的基于参数的 XMVectorPermute 而不是模板版本,则性能应该与使用 XNAMath 的性能相同。
  • 谢谢!指定函数可以解决问题。 @亚历克斯
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-23
  • 2015-10-31
  • 1970-01-01
  • 2016-12-23
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
相关资源
最近更新 更多