我正在尝试使用 Eigen's我的应用程序代码中与图形相关的基本线性代数的 vector 和矩阵类型(例如 Vector3f
、 Matrix3f
)。但为了将它们传递给 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 最有效的方法是什么 Vector3f
到simd_float3
,和Matrix3f
至simd_float3x3
?
也许它们在内存中的布局相同,我不需要转换它们?那太好了。虽然理想情况下我想 static_assert
用编译器仔细检查它。
编辑添加:
我假设我不能在 Metal 着色器代码中使用 Eigen,并且在着色器代码中我应该使用的唯一 vector 和矩阵类型是 simd 类型 - simd_float3
, simd_float3x3
等等。如果我可以简单地使用特征类型而不损失性能或造成重大不便,那么我可能会这样做。
最佳答案
Metal 缓冲区不限于仅使用simd
对象。事实上,您通过 memcpy 传递数据,它接受任意数据指针,因此您可以使用任何类型。不过,您必须注意两个陷阱:
simd
对象自动添加一个额外元素,以便允许矩阵/vector 乘法(例如simd::float3
vector 实际上包含 4 个元素)- 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/