我正在开发一些适用于图像缓冲区的内核。问题是,当我通过直接复制图像数据来创建 Image2D 时,一切正常。
如果我尝试将写入队列到我的图像缓冲区,它将不适用于我的 GPU。
这是一个基本的内核:
__kernel void myKernel(__read_only image2d_t in, __write_only image2d_t out) {
const int x = get_global_id(0);
const int y = get_global_id(1);
const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_CLAMP_TO_EDGE | CLK_FILTER_NEAREST;
uint4 pixel = read_imageui(in, sampler, (int2)(x, y));
write_imageui(out, (int2)(x, y), pixel);
}
好吧,那个简单的内核在我的 GPU 上给了我一个黑色图像,但在我的 CPU 上运行良好。
为了使它工作,我必须释放缓冲区图像并通过使用CL_MEM_COPY_HOST_PTR
. 我使用良好的数据格式:CL_RGBA、CL_UNSIGNED_INT8,而且我的图像大小很好。
JOCL 和 API 的 C++ 绑定遇到了问题。(我没有测试 C API)。
最后,它通过重新创建缓冲区来运行,但这是个好主意吗?这只是正常的吗?我可以执行哪些操作来避免它?
顺便说一句,我在 Intel SDK for OpenCL(Intel Core I7)和 ATI AMD APP SDK(HD6800)上运行。
[编辑]
这是我用来写入缓冲区的代码。
一、分配部分:
cl_image_format imageFormat = new cl_image_format();
imageFormat.image_channel_order = CL_RGBA;
imageFormat.image_channel_data_type = CL_UNSIGNED_INT8;
inputImageMem = clCreateImage2D(
context, CL_MEM_READ_ONLY,
new cl_image_format[]{imageFormat}, imageSizeX, imageSizeY,
0, null, null);
并且在运行时,为每一帧调用在 GPU 上不起作用的部分:
clEnqueueWriteImage(commandQueue, inputImageMem, CL_TRUE, new long[]{0, 0, 0},
new long[]{imageSizeX, imageSizeY, 1}, 0, 0,
Pointer.to(data), 0, null, null);
在 GPU 和 CPU 上工作但强制我重新创建缓冲区的部分:
clReleaseMemObject(inputImageMem);
cl_image_format imageFormat = new cl_image_format();
imageFormat.image_channel_order = CL_RGBA;
imageFormat.image_channel_data_type = CL_UNSIGNED_INT8;
inputImageMem = clCreateImage2D(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, new cl_image_format[]{imageFormat}, imageSizeX, imageSizeY, 0, Pointer.to(data), null);
发送的数据是一个大小为 int 的数组imageSizeX*imageSizeY
。我通过这段代码得到它:
DataBufferInt dataBuffer = (DataBufferInt)image.getRaster().getDataBuffer();
int data[] = dataBuffer.getData();
上面的代码是在使用 JOCL 的 java 中,同样的问题出现在另一个使用 C++ OpenCL Wrapper 的 C++ 程序中。唯一的区别是在 Java 中虚拟机崩溃(在 3~4 帧之后),而在 C++ 中,结果是黑色图像。