CL / GL-Interop错误的OpenGL纹理格式类型?

时间:2012-01-30 12:53:08

标签: opengl opencl texture2d libavcodec

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

我想捕获一个帧,将该数据用作OpenCL内核的输入图像(Image2D)。内核应该操纵数据并将其写入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可以在内核中读取为float,并被解释为规范化值。输出图像看起来不对,我有一个切片图片(线性),显然是因为错误的数据解释。正如我所提到的,我假设错误在纹理类型的初始化范围内。我尝试了GL_FLOAT(因为我写的是浮点到内核中的图像)。

Results: Image as PPM dump from the decoder (left), Texture output scattered (right)

左边的一个是解码器的PPM,右边的是我的输出纹理。

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

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


2 个答案:

答案 0 :(得分:2)

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

glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);

答案 1 :(得分:1)

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

我也可以通过观察行计数来承担错误:我从512行请求的行中得到384个,这恰好是.75的比率。

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

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