Frage

I'm using Opencl.net and I'm trying to do some image processing on the GPU. Unfortunately only the first pixel ([0;0]) has the correct value, and the rest is (0;0;0;0). The OpenCL kernel should assign 0.5 to all color components of every pixel. 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!

War es hilfreich?

Lösung

I've figured out the problem. The region in Cl.EnqueueWriteImage/Cl.EnqueueReadImage should be (imageWidth, imageHeight, 1) instead of (1, 1, 1):

IntPtr[] regionPtr = new IntPtr[] { (IntPtr)imgWidth, (IntPtr)imgHeight, (IntPtr)1 };
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top