c++ - 如何将 Eigen 矩阵和 vector 类型转换为 Apple 的 simd 类型以传递给 GPU?

标签 c++ eigen simd metal

我正在尝试使用 Eigen's我的应用程序代码中与图形相关的基本线性代数的 vector 和矩阵类型(例如 Vector3fMatrix3f )。但为了将它们传递给 GPU,我想使用 Apple 的 Metal API,它从 <simd/simd.h> 中获取类型。 header 。它们以我不认识的奇怪方式声明。例如,这里是 3 个 float 的 vector ,以及 3x3 float 的矩阵。

// From <simd/vector_types.h>
typedef __attribute__((__ext_vector_type__(3))) float simd_float3;
...
// From <simd/types.h>
typedef struct { simd_float3 columns[3]; } simd_float3x3;

构建 Eigen 最有效的方法是什么 Vector3fsimd_float3 ,和Matrix3fsimd_float3x3

也许它们在内存中的布局相同,我不需要转换它们?那太好了。虽然理想情况下我想 static_assert用编译器仔细检查它。

编辑添加:

我假设我不能在 Metal 着色器代码中使用 Eigen,并且在着色器代码中我应该使用的唯一 vector 和矩阵类型是 simd 类型 - simd_float3 , simd_float3x3等等。如果我可以简单地使用特征类型而不损失性能或造成重大不便,那么我可能会这样做。

最佳答案

Metal 缓冲区不限于仅使用simd对象。事实上,您通过 memcpy 传递数据,它接受任意数据指针,因此您可以使用任何类型。不过,您必须注意两个陷阱:

  1. simd 对象自动添加一个额外元素,以便允许矩阵/vector 乘法(例如 simd::float3 vector 实际上包含 4 个元素)
  2. Eigen 对象必须进行转置,否则它们的内部表示与预期的内存布局不匹配。例如。为了传递三角形 3 个顶点的数据:
  • { -0.8f, 0.8f, 0.0f } - 顶点的 x, y, z 1;
  • { 0.0f, -0.8f, 0.0f } - 顶点的 x, y, z 2;
  • { 0.8f, 0.8f, 0.0f } - 顶点 3 的 x, y, z ;

你应该用以下内容制作一个 4x3 矩阵:

  • { -0.8f, 0.0f, 0.8f } - x 轴上的值;
  • { 0.8f, -0.8f, 0.8f } - y 轴上的值;
  • { 0.0f, 0.0f, 0.0f } - z 轴上的值;

这是一个简约的示例:

Eigen::Matrix<float, 4, 3> positions{
    { -0.8f, 0.0f, 0.8f },  // x
    { 0.8f, -0.8f, 0.8f },  // y
    { 0.0f, 0.0f, 0.0f },   // z
    { 0.0f, 0.0f, 0.0f }    // w
};  // v1  // v2  // v3

auto* positionsBuffer = metalDevice->newBuffer(positionsDataSize, MTL::ResourceStorageModeManaged);

const std::size_t positionsDataSize = positions.rows() * positions.cols() * sizeof(decltype(positions)::Scalar);

std::memcpy(positionsBuffer->contents(), positions.data(), positionsDataSize );

关于c++ - 如何将 Eigen 矩阵和 vector 类型转换为 Apple 的 simd 类型以传递给 GPU?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75904584/

相关文章:

c++ - Eigen3 矩阵乘法性能

c++ - 如何获得特征矩阵的形状(尺寸)?

c++ - 将 "__m256 with random-bits"转换为 [0, 1] 范围的浮点值

c++ - Visual Studio强制在项目的所有编译单元中包含预编译头文件?

c++ - 如何检查两个矩阵是否相同?

c++ - 非结构对象布局

parallel-processing - 编译器通常会在没有明确告知的情况下发出向量 (SIMD) 指令吗?

c++ - 调度 SIMD 指令 + SIMDPP + qmake

c++ - 使用qt连接到SQLite数据库

c++ - 很好的替代Qt