2012-11-28 25 views
0

我正在使用Opencl.net,我正在嘗試在GPU上執行一些圖像處理。不幸的是,只有第一個像素([0; 0])具有正確的值,剩下的是(0; 0; 0; 0)。 OpenCL內核應該爲每個像素的所有顏色分量賦值0.5。在我看來,內核只被執行一次(或者讀取功能可能只讀取第一個像素)。我究竟做錯了什麼?我從我的代碼中省略了不相關的部分:OpenCL成像 - 只更新一個像素

... 
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] + ")"); 
} 

謝謝!

回答

2

我已經知道了這個問題。 Cl.EnqueueWriteImage/Cl.EnqueueReadImage中的區域應該是(imageWidth,imageHeight,1)而不是(1,1,1):

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