OpenCL“read_image"返回一个空白像素

本文关键字:一个 像素 空白 返回 read image quot OpenCL | 更新日期: 2023-09-27 18:01:19

问题说明及示例

我正在使用OpenCL,我正试图获得图像调整工作。我已经读了一些教程,我几乎已经结束了尝试为这个编写我自己的内核。

我的问题是我无法让OpenCL从我传输给它的图像中读取像素。

这里是内核在OpenCL:

const sampler_t SMPL_PREF = CLK_NORMALIZED_COORDS_TRUE |
                            CLK_ADDRESS_CLAMP |
                            CLK_FILTER_LINEAR;
__kernel void image_scaling( __read_only  image2d_t src_img,
                             __write_only image2d_t dest_img,
                                              float WRATIO,
                                              float HRATIO )
{
    int2       coor = (int2)( get_global_id(0), get_global_id(1) );
    float2 origCoor = (float2)(convert_float2(coor).x * WRATIO,
                               convert_float2(coor).y * HRATIO );
    uint4     color = read_imageui( src_img, SMPL_PREF, origCoor );
    // Test write_imageui -- THIS WORKS!!! :(
    //color = (uint4)(20, 255, 20, 255);
    write_imageui( dest_img, coor, color );
}

我正在使用OpenCL。但我不认为这是导致这个问题的原因。这就是我如何将图像从主机传输到设备内存:

ImageFormat clImageFormat = new ImageFormat( ChannelOrder.RGBA,
                                             ChannelType.Unsigned_Int8 );
// Allocate Memory on Device
IMem inputImage2DBuffer = Cl.CreateImage2D( env.Context,
                                            MemFlags.AllocHostPtr |
                                                MemFlags.ReadOnly,
                                            clImageFormat,
                                   (IntPtr) originalWidth,
                                   (IntPtr) originalHeight,
                                   (IntPtr) 0,
                                   (IntPtr) 0, //imageData,
                                        out error );
// Copy the host data to the device
error = Cl.EnqueueWriteImage( env.CommandQueues[ 0 ],  // OpenCL Command Queue
                              inputImage2DBuffer,      // Ptr on device for image
                              Bool.True,               // Blocking write
                              originPtr,               // origin x,y (0,0)
                              regionPtrInput,          // dimension w,h
                     (IntPtr) 0,                       // rowPitch
                     (IntPtr) 0,                       // rowSlice
                              imageData,               // Ptr to byte[] host data
                              0,                       // Number of wait events
                              null,                    // array of wait events
                          out clEvent );
Cl.WaitForEvents( (uint) 1, new Event[] { clEvent } );
CheckError( error, "EnqueueWriteImage" );
clEvent.Dispose( );

我需要帮助

如果有人可以建议调试的方法,如果我没有正确地将图像传输到设备,或者如果它是我的设备。我好像走到死胡同了。就像我说的,我不认为这是一个问题与OpenCL。但我现在几乎什么都愿意尝试。我认为我可能在传输主机内存时做了一些愚蠢的事情,但我已经查看了该代码100多次,并重写了近十几次。我看不出是什么原因导致这个问题。

我知道一个事实,我可以将一个常规缓冲区传输到设备并读取它,读取图像是我唯一的问题。如果您查看我的OpenCL代码,您将看到一条注释行。通过取消注释,我可以将数据返回给主机(石灰绿色)。这使他相信问题出在read_image上。

我正在使用英特尔5000 GPU运行我的OpenCL代码的2013 MacBook Air上工作。

OpenCL“read_image"返回一个空白像素

根据您传递给WRATIO和HRATIO的值,问题非常类似于您正在使用CLK_NORMALIZED_COORDS_TRUE,而应该使用CLK_NORMALIZED_COORDS_FALSE。后者允许你使用像素坐标,而不是0.0到1.0的"标准化"坐标。

另外,当你在这里的时候,要注意CLK_FILTER_LINEAR和float2坐标,积分坐标将给出过滤的结果。添加(float2)(0.5f, 0.5f)以获得未过滤的值。换句话说,对于(2,6)处的像素,读取(2.5,6.5)。当你的比例接近1.0时,这一点很重要,这样你就不会得到一个模糊的图像。

所以,在Dithermaster的帮助下(谢谢!),我已经弄清楚了这个问题。问题是我在读取像素时没有使用标准化坐标。这是我当前的内核,它工作得非常好!


Resize.cl

const sampler_t SMPL_PREF = CLK_NORMALIZED_COORDS_TRUE |
                            CLK_FILTER_LINEAR |
                            CLK_ADDRESS_NONE ;
__kernel void image_scaling( __read_only  image2d_t src_img,
                             __write_only image2d_t dest_img,
                                               uint WIDTH,     // resized width
                                               uint HEIGHT )   // resized height
{
    int2       coor = (int2)( get_global_id(0), get_global_id(1) );
    float2 normCoor = convert_float2(coor) / (float2)( WIDTH, HEIGHT );
    float4    color = read_imagef( src_img, SMPL_PREF, normCoor );
    write_imagef( dest_img, coor, color );
}

再次,感谢Dithermaster指出的规格表。OpenCL在过滤器标志和使用哪个read_image方面非常具体。我很高兴我终于修复了这个问题:)