简体   繁体   English

OpenCL成像 - 只更新一个像素

[英]OpenCL imaging - only one pixel is updated

I'm using Opencl.net and I'm trying to do some image processing on the GPU. 我正在使用Opencl.net,我正在尝试在GPU上进行一些图像处理。 Unfortunately only the first pixel ([0;0]) has the correct value, and the rest is (0;0;0;0). 不幸的是,只有第一个像素([0; 0])具有正确的值,其余的是(0; 0; 0; 0)。 The OpenCL kernel should assign 0.5 to all color components of every pixel. OpenCL内核应该为每个像素的所有颜色分量分配0.5。 It seems to me that the kernel is being executed only once (or perhaps the read function is reading only the first pixel). 在我看来,内核只执行一次(或者读取函数可能只读取第一个像素)。 What am I doing wrong? 我究竟做错了什么? I've omitted not relevant parts from my code: 我从代码中省略了不相关的部分:

...
int intPtrSize = 0;
intPtrSize = Marshal.SizeOf(typeof(IntPtr));
Cl.Mem srcImage2DBuffer;
Cl.ImageFormat imageFormat = new Cl.ImageFormat(Cl.ChannelOrder.ARGB, Cl.ChannelType.Float);
int imgWidth = 0, imgHeight = 0;

IntPtr srcFloatDataPtr;

int srcIMGBytesSize = 0;

GCHandle pinnedSrcFloatArray;

//Load image from file into OpenCL buffer
using (FileStream imageFileStream = new FileStream(inputImagePath, FileMode.Open) ) {
    System.Drawing.Image inputImage = System.Drawing.Image.FromStream( imageFileStream );

    imgWidth = inputImage.Width;
    imgHeight = inputImage.Height;

    System.Drawing.Bitmap bmpImage = new System.Drawing.Bitmap(inputImage);

    BitmapData bitmapData = bmpImage.LockBits( new Rectangle(0, 0, bmpImage.Width, bmpImage.Height),
                                   ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

    srcIMGBytesSize = bitmapData.Stride * bitmapData.Height;

    //Convert image from byte to float array
    byte[] inputByteArray = new byte[srcIMGBytesSize];
    Marshal.Copy(bitmapData.Scan0, inputByteArray, 0, srcIMGBytesSize);
    bmpImage.UnlockBits( bitmapData );

    float[] inputFloatArray = new float[srcIMGBytesSize];
    Array.Copy(inputByteArray, inputFloatArray, srcIMGBytesSize);

    for (int i = 0; i < srcIMGBytesSize; i++) {
        inputFloatArray[i] /= 255.0f;
    }

    pinnedSrcFloatArray = GCHandle.Alloc(inputFloatArray, GCHandleType.Pinned);
    srcFloatDataPtr = pinnedSrcFloatArray.AddrOfPinnedObject();
    srcImage2DBuffer = Cl.CreateImage2D(_context, Cl.MemFlags.CopyHostPtr | Cl.MemFlags.ReadOnly, imageFormat,
                                        (IntPtr)bitmapData.Width, (IntPtr)bitmapData.Height,
                                        (IntPtr)0, srcFloatDataPtr, out error);
}
float[] outputFloatArray = new float[srcIMGBytesSize];

//I'm not sure whether the pointer here is correct or not.
Cl.Mem resultImage2DBuffer = Cl.CreateImage2D(_context, Cl.MemFlags.CopyHostPtr | Cl.MemFlags.WriteOnly, imageFormat,
                                              (IntPtr)imgWidth, (IntPtr)imgHeight, (IntPtr)0, outputFloatDataPtr, out error);

error = Cl.SetKernelArg(kernel, 0, (IntPtr)intPtrSize, srcImage2DBuffer);
error |= Cl.SetKernelArg(kernel, 1, (IntPtr)intPtrSize, resultImage2DBuffer);

...

IntPtr[] originPtr = new IntPtr[] { (IntPtr)0, (IntPtr)0, (IntPtr)0 };
IntPtr[] regionPtr = new IntPtr[] { (IntPtr)1, (IntPtr)1, (IntPtr)1 };
IntPtr[] workGroupSizePtr = new IntPtr[] { (IntPtr)imgWidth, (IntPtr)imgHeight, (IntPtr)1 };

error = Cl.EnqueueWriteImage(cmdQueue, srcImage2DBuffer, Cl.Bool.True, originPtr, regionPtr, (IntPtr)0, (IntPtr)0, srcFloatDataPtr, 0, null, out clevent);

pinnedSrcFloatArray.Free();
error = Cl.EnqueueNDRangeKernel(cmdQueue, kernel, 2, null, workGroupSizePtr, null, 0, null, out clevent);

error = Cl.EnqueueReadImage(cmdQueue, resultImage2DBuffer, Cl.Bool.True, originPtr, regionPtr,
                            (IntPtr)0, (IntPtr)0, outputFloatArray, 0, null, out clevent);

for (int i = 0; i < srcIMGBytesSize; i++) {
    outputFloatArray[i] *= 255.0f;
}

//Right here I'm learning that all of the components are 0
for (int i = 0; i < srcIMGBytesSize; i+=4) {
    Console.WriteLine("(" + outputFloatArray[i] + "; " + outputFloatArray[i+1] + "; "
                      + outputFloatArray[i+2] + "; " + outputFloatArray[i+3] + ")");
}

Thank you! 谢谢!

I've figured out the problem. 我已经找到了问题所在。 The region in Cl.EnqueueWriteImage/Cl.EnqueueReadImage should be (imageWidth, imageHeight, 1) instead of (1, 1, 1): Cl.EnqueueWriteImage / Cl.EnqueueReadImage中的区域应该是(imageWidth,imageHeight,1)而不是(1,1,1):

IntPtr[] regionPtr = new IntPtr[] { (IntPtr)imgWidth, (IntPtr)imgHeight, (IntPtr)1 };

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

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