0

假设一个数据数组

int data[256][256][256];

包含值 0 和 1。此数据将被复制到设备内存(展平)并由 cuda 内核处理,将某些值从 0 更改为 1,反之亦然。我怎样才能以这种方式显示数据

if data[x]][y][z]==1
{
//a point of size 1 will be displayed in (x,y,z) coords
}

无需将该数组复制回主机内存。我想直接从设备(gpu)内存中完成。一个简单的例子会很有帮助。

4

1 回答 1

2

想到的第一种方法是首先使用简单的流压缩技术,从流中消除所有 0 值。由于您已经拥有概念上布尔格式的数据,因此这相当于这些值的扫描/前缀总和,以便之后每个数组元素存储其前面元素的数量。然后,您使用这些计算的偏移量将数组元素重新定位到新缓冲区(有效地连续存储所有 1 项),但不是仅复制(现在不相关的)偏移量,而是存储 3D 位置(可以从旧数组索引轻松计算) )。

然后,您拥有的是缓冲区中 3D 点的简单列表,您可以使用 OpenGL 轻松绘制,无需任何复制到主机。如果您将最终的 1 点数(扫描的副产品)写入额外的缓冲区,您甚至可以使用间接渲染,甚至不需要从主机查询点数,因此只需绘制整个事情没有任何回读。

这些只是关于这可能如何工作的一些一般性想法,如果您不知道我在说什么,请随时在 Google 上搜索各个关键字。如果您不知道如何使用 OpenGL 绘制任何东西,则需要先熟悉 OpenGL 或 Direct3D,然后才能从 GPU 绘制任何东西(CUDA 不会为您做这件事)。


编辑:嗯,有一种方法可以在 CUDA 中绘制整个东西。如果它真的只是一堆点并且你不需要任何复杂的光栅化,你也可以像 OpenGL 那样简单地将这些点从 3D 转换为 2D(OpenGL 也不是魔法,只是一堆 CUDA 内核和一些小的之间的专用硬件位)。因此,每个数据项都有一个线程,如果该项是1,您只需使用通常的模型视图和均匀 4D 坐标上的投影转换来转换点的 3D 坐标(由线程 ID 给出)(但不要忘记执行透视分割和视口会自行转换,因为现在没有固定功能的硬件可以为您做到这一点)。并使用这个最终的 2D 坐标来设置输出图像中的单个像素。

当然,这不会让您从 OpenGL 的其他复杂事物中获利(至少不是那么容易或直接),例如光栅化以及您可以考虑的其他效果。但它避免了流压缩步骤,您至少可以在已经存在的 OpenGL 渲染图像(包含可视化场景的其余部分,如坐标系或文本或其他)之上渲染这些点,甚至可以使用您自己的深度测试实施。


编辑:避免流压缩的另一种方法是直接使用 OpenGL 绘制0s 和1s 的整个缓冲区,使用几何着色器进行坐标计算和0-removal。所以你要做的是绘制所有点,使用整个整数数组来提供单个int属性并将其放入以下着色器。首先是一个简单的直通顶点着色器:

layout(location=0) in int flag;    //single integer attribute
out int vFlag;                     //just passed through

void main()
{
    vFlag = flag;        //GS does the real work
}

几何着色器决定该点是否有效(值为1),如果是则为它发出一个实际的点(如果不是什么都不做,即没有渲染点),从图元 ID 计算其 3D 坐标,这实际上是数组索引,因为我们只是在绘制点:

layout(points) in;
layout(points,max_vertices=1) out;

uniform mat4 modelViewProj;

in int vFlag[];

void main()
{
    if(vFlag[0] == 1)
    {
        vec3 position = simpleIndexMagic(gl_PrimitiveID);
        gl_Position = modelViewProj * vec4(position, 1.0);
        EmitVertex();
    }
}

片段着色器就是一个普通的着色器。当然,这些着色器可以按照您认为合适的方式进行定制。但是一般的方法很清楚,直接绘制整数值,将数组索引转换为仅用于1几何着色器中的值的点。但是需要评估这在多大程度上比以前的流压缩有改进。

于 2013-04-04T10:03:32.453 回答