简体   繁体   English

OpenCL“ read_image”返回空白像素

[英]OpenCL “read_image” Returns a Blank Pixel

Description of Issue and Examples 问题说明和示例

I am working with OpenCL and I am trying to get an image resize working. 我正在使用OpenCL,并且正在尝试调整图像大小。 I've gone through a few tutorials and I've pretty much ended on trying to write my own kernel for this. 我已经看了一些教程,并且在尝试为此编写自己的内核方面几乎结束了。

My issue is I cannot get OpenCL to read the pixel from an image that I transfer to it. 我的问题是我无法让OpenCL从传输到它的图像读取像素

Here is Kernel in 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 );
}

I am using OpenCL.Net, but I don't think that is what is causing the issue. 我正在使用OpenCL.Net,但我认为这不是导致问题的原因。 This is how I am transferring the image from the host to device memory: 这就是我将映像从主机传输到设备内存的方式:

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( );

I Need Help 我需要帮助

I would love if someone could suggest a method of debugging if I am not transferring images properly to the device or if it is something with my device. 如果有人没有建议将图像正确地传输到设备上,或者设备附带了某种东西,我会希望有人提出一种调试方法。 I am kind of at a dead end. 我有点死胡同。 Like I said I dont think it is an issue with OpenCL.Net, but I am almost willing to try anything now. 就像我说的那样,我认为这与OpenCL.Net无关,但是我几乎愿意尝试任何事情。 I think that I am probably doing something stupid when transferring the host memory, but I've looked that code over 100 times and rewritten it almost a dozen. 我认为在传输主机内存时我可能会做一些愚蠢的事情,但是我看过该代码100多次,并将其重写了将近十二次。 Nothing that I can see should be causing this issue. 我看不到应该导致此问题。

I know for a fact that I can transfer a regular buffer to the device and read it back, reading images are my only issue. 我知道,我可以将常规缓冲区传输到设备并读回,读取图像是我唯一的问题。 If you look at my OpenCL code, you will see a commented line. 如果您查看我的OpenCL代码,将会看到一条注释行。 By uncommenting it, I can get data back to my host (a lime green color). 通过取消注释,我可以将数据返回到主机(灰绿色)。 This leads be to believe the issue is with read_image. 这导致人们相信问题出在read_image上。

I am working on a 2013 MacBook Air using the Intel 5000 GPU to run my OpenCL code. 我正在使用Intel 5000 GPU运行2013 MacBook Air来运行我的OpenCL代码。

Depending on what values you are passing for WRATIO and HRATIO, the problem is very like that you're using CLK_NORMALIZED_COORDS_TRUE and should likely be using CLK_NORMALIZED_COORDS_FALSE . 根据您为WRATIO和HRATIO传递的值,问题非常像您正在使用CLK_NORMALIZED_COORDS_TRUE并且可能应该使用CLK_NORMALIZED_COORDS_FALSE The latter lets you use pixel coordinates instead of 0.0 to 1.0 "normalized" coordinates. 后者允许您使用像素坐标,而不是0.0到1.0的“标准化”坐标。

Also, while you're at it, be aware that with CLK_FILTER_LINEAR and float2 coordinates, integral coordinates will give filtered results. 另外,在使用它时,请注意,使用CLK_FILTER_LINEAR和float2坐标时,整数坐标将给出过滤后的结果。 Add (float2)(0.5f, 0.5f) to get unfiltered values. 加(float2)(0.5f,0.5f)以获取未过滤的值。 In other words, for the pixel at (2,6) read (2.5, 6.5). 换句话说,对于(2,6)处的像素,读取(2.5,6.5)。 This will matter when your ratio is near 1.0 so you don't get a fuzzy image. 当您的比率接近1.0时,这很重要,因此您不会得到模糊的图像。

So, with the help of Dithermaster (thank you!), I've figure out the issue. 因此,在Dithermaster的帮助下(谢谢!),我找出了问题所在。 The issue was that I was not using normalized coordinates when reading back pixels. 问题是读回像素时我没有使用归一化坐标。 Here is my current kernel, which is working amazingly! 这是我当前的内核,运行异常!


Resize.cl 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 );
}

Again, thanks to Dithermaster for pointing out the spec sheet. 再次感谢Dithermaster指出了规格表。 OpenCL is very specific when it comes to the filter flags and which read_image you are using. 当涉及到过滤器标志以及所使用的read_image时,OpenCL非常具体。 I am super glad I have this fixed finally :) 我很高兴终于解决了这个问题:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM