我正在使用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.Net,但我不认为这是导致问题的原因。这就是我将图像从主机传输到设备存储器的方式:
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.Net的问题,但我现在几乎愿意尝试任何事情。我认为在转移主机内存时我可能做了一些愚蠢的事情,但是我已经看过那段代码超过100次并重写了近十几个。我所看到的任何内容都不应该导致这个问题。
我知道我可以将常规缓冲区传输到设备并将其读回来,读取图像是我唯一的问题。如果您查看我的OpenCL代码,您将看到一条注释行。通过取消注释,我可以将数据恢复到我的主机(浅绿色)。这导致相信问题在于read_image。
我正在使用Intel 5000 GPU在2013 MacBook Air上运行我的OpenCL代码。
答案 0 :(得分:1)
根据您为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时,这将很重要,因此您不会得到模糊的图像。
答案 1 :(得分:0)
所以,在Dithermaster的帮助下(谢谢!),我已经找到了问题所在。问题是我在回读像素时没有使用标准化坐标。这是我当前的内核,它的工作非常出色!
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方面非常具体。我很高兴终于解决了这个问题:)