5

我正在使用 CUDA Toolkit 4.0 在 Geforce 330M 上尝试 OpenCL-OpenGL 互操作纹理。

我想捕获一个帧,将该数据用作Image2DOpenCL 内核的输入图像 ( )。内核应该操作数据并将其写入一个Image2DGL,这是一个附加了 OpenGL 纹理的图像对象。基本上它看起来像这样:

 _______________      RGB        _______________
|               |    uint8*     |               |   CL_RGBA / CL_UNORM_INT8
|   Grabber     | ------------> |   Image2D     | -------------------------.
|   avcodec     |               |   [input]     |                          |
|_______________|               |_______________|                          |
                                                                           |    
                                                                           V
 _______________                 _______________                       _______________
|               |               |               |                     |               |
|   Texture     | ------------> |   Image2DGL   | <-----------------> |    Kernel     |
|_______________|               |   [output]    |                     |_______________|
                                |_______________|
Internal
Format: GL_RGBA
Format: GL_RGBA
Type: ?

我正在像这样初始化纹理:

GLuint tex = 0;

void initTexture( int width, int height )
{
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_RECTANGLE, tex);
// now here is where I need assistance: The type parameter of the Texture (GL_FLOAT)
    glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_FLOAT, NULL );
} 


编辑:我也可以有一种GL_UNSIGNED_INT


然后我创建共享图像 ( Image2DGL):

texMems.push_back(Image2DGL(clw->context, CL_MEM_READ_WRITE, GL_TEXTURE_RECTANGLE, 0, tex, &err));

然后我创建源图像(输入图像):

ImageFormat format;
format.image_channel_data_type = CL_UNORM_INT8;
format.image_channel_order = CL_RGBA;
srcImgBuffer = Image2D(clw->context, CL_MEM_READ_WRITE, format, width, height, 0, NULL, &err);

在每个渲染循环中,我将数据写入srcImgBuffer

// write the frame to the image buffer
clw->queue.enqueueWriteImage(srcImgBuffer, CL_TRUE, origin, region, 0, 0, (void*)data, NULL, NULL);

另外我正在为内核设置参数:

tex_kernel.setArg(0, texMems[0]);
tex_kernel.setArg(1, srcImgBuffer);
tex_kernel.setArg(2, width);
tex_kernel.setArg(3, height);

在我获取和释放 GL 对象之前和之后。测试内核如下所示:

__kernel void init_texture_kernel(__write_only image2d_t out, __read_only image2d_t in, int w, int h)
{
    const sampler_t smp = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP | CLK_FILTER_NEAREST;

    int2 coords = { get_global_id(0), get_global_id(1) };
    float4 pixel = read_imagef(in, smp, coords);
    float4 test = { (float)coords.x/(float)w , 0, 0, 1};
    write_imagef( out, coords, pixel );
}

image_channel_data_type可以在内核中读取为浮点数并解释为标准化值。输出图像看起来不正确,我有一张切片图片(逐行),显然是因为错误的数据解释。正如我所提到的,我假设错误在纹理类型的初始化中。我尝试了 GL_FLOAT (因为我将浮点数写入内核中的图像)。

结果:图像作为解码器的 PPM 转储(左),纹理输出分散(右)

左边是PPM解码器的输出,右边是我在输出纹理上得到的。

如果有人真的读到这里:你有关于纹理类型的建议来解决这个问题吗?


编辑:如果我直接将捕获的帧绑定到纹理,则视频播放正常。所以它必须以某种方式与CL-GL接口相关。


4

2 回答 2

2

我相信,如果你对 glTexture2D 的最后一个参数是 NULL,那么格式和类型参数可以是任何有效的 OpenGL 格式/类型——但它们没有被使用并且不会影响任何东西。如果你想要浮点纹理,那么你必须通过传递正确的 internal_format 参数来指定它:

glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
于 2012-01-30T16:39:33.317 回答
1

我最终想出了解决方案,没有看到明显的问题。我有一个 RGB 视频。因此,我以 RGB 格式捕获了帧。这可以很好地显示在纹理上。但是,如果一个人一次从只有三个通道的缓冲区中抓取一个float4(如内核代码所示),这当然会搞砸。啊。

我也可以通过观察行数来假设我的错误:在 512 行请求的行中,我得到了 384 行,这很好地达到了.75.

我只是要求我的抓取器(使用 libavcodec)抓取 RGBA,它会为我填充四通道图片。

我会将这个问题标记为已关闭。

于 2012-02-01T16:10:48.930 回答