如何强制 OpenCL 不重新对齐结构?

Posted

技术标签:

【中文标题】如何强制 OpenCL 不重新对齐结构?【英文标题】:How to force OpenCL not to re-align structs? 【发布时间】:2015-11-10 10:51:10 【问题描述】:

我正在构建一个内核代码,用于捕获当前 GL 场景中的三角形。 为此,我将我的顶点流与我的索引一起发送到内核代码。

这是我的内核条目的声明:

__kernel
void CaptureTriangles(
    const uint NumTriangles,
    const float16 WorldMatrix,
    __constant ushort3 *IndexDataBlock,
    __constant struct Vertex *DataBlock,
    __global struct Triangle *TriangleBuffer,
    __global uint *TriangleBufferCount)

Vertex 结构是这样定义的:

struct Vertex

    float3  position;
    float3  normal;
    float   materialIndex;

__attribute__((packed));

现在这个流是通过 GL 创建的,这就是数据的布局方式。

获取三角形时,我在内核代码中执行以下操作:

const ushort3 idx = IndexDataBlock[get_global_id(0)];
const struct Vertex v0 = DataBlock[idx.x],
                    v1 = DataBlock[idx.y],
                    v2 = DataBlock[idx.z];

但似乎 OpenCL 一直在将 Vertex 结构重新对齐到它自己的内部要求,即使它被声明为 __attribute((packed))。 所以三角形永远不会被正确捕获。

__constant struct Vertex *DataBlock 切换到__constant float *DataBlock 并在内核代码中显式获取每个浮点数可以解决此问题。 所以这在通过浮点数读取浮点数时有效:

// __constant float *DataBlock
float4 p0 = (float4)(DataBlock[7 * idx.x + 0], DataBlock[7 * idx.x + 1], DataBlock[7 * idx.x + 2], 1.0f),
       p1 = (float4)(DataBlock[7 * idx.y + 0], DataBlock[7 * idx.y + 1], DataBlock[7 * idx.y + 2], 1.0f),
       p2 = (float4)(DataBlock[7 * idx.z + 0], DataBlock[7 * idx.z + 1], DataBlock[7 * idx.z + 2], 1.0f);

为了代码清晰,我宁愿使用 struct Vertex 语法,有没有办法让 OpenCL 不重新对齐结构?

【问题讨论】:

酷,是的,我在其他地方也看到过。所以 float3 总是与 float4 对齐,忽略任何打包属性......我想我想要的是告诉 OpenCL 如何解释一些已经在内存中布局的数据。听起来那是不可能的,感谢您难以置信的快速响应!干杯。 【参考方案1】:

对于 CL,cl_float3cl_float4 的大小相等。但在您的情况下,您的 GL 代码会提供真正的 float3 值作为输出。

__attribute__((packed)) 不会解决您的问题,因为对于 CL,结构已经被打包,只是内部元素大小不同。

恐怕你必须手动解析它。

【讨论】:

以上是关于如何强制 OpenCL 不重新对齐结构?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 PyOpenCL 将带有数组和变量的 C 结构传递给 OpenCL 内核

如何强制 Office UI Fabric ChoiceGroup 水平对齐

自然对齐和强制对齐

GCC - 如何重新对齐堆栈?

WPF - 如何强制命令通过其 CommandBindings 重新评估“CanExecute”

OpenCL 缓冲区大小填充