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] + ")");
}
고맙습니다!