OpenCL 内核仅在对角线上绘制
OpenCL kernel draws only on diagnoal
我目前正在 OSX 上开发 OpenCL 内核,我正在尝试将输入图像设置为全部 255。
我用 CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR
和 CL_UNSIGNED_INT8
创建了一个单通道图像,我的内核和主机代码如下:
const sampler_t linear_sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_FILTER_LINEAR | CLK_ADDRESS_CLAMP_TO_EDGE;
__kernel void test(__write_only image2d_t dst)
{
const int2 src_pos = int2(get_global_id(0), get_global_id(1));
write_imagei(dst, src_pos, 255);
}
void clTest(cl_image2d dst)
{
cl_int retval;
cl_kernel kTest = clCreateKernel(m_oclEnv.program, "test", &retval);
CHECK_OCL(clSetKernelArg(kTest, 0, sizeof(cl_mem), (void*)&dst.mem));
size_t grid_item_size[2] = {static_cast<size_t>(m_nFrameWidth), static_cast<size_t>(m_nFrameHeight)};
size_t block_item_size[2] = {8, 8};
cl_uint nDim = 2;
CHECK_OCL(clEnqueueNDRangeKernel(m_oclEnv.queue, kTest, nDim, NULL, grid_item_size, block_item_size, 0, NULL, NULL));
clReleaseKernel(kTest);
}
结果输出图像如下:
显然内核只在y=x的位置绘制,那么问题在哪里?谢谢
ps: 我试过将图像写入GPU并立即读出并且效果很好,所以opencl上下文或环境应该没有任何问题。
我认为,行
const int2 src_pos = int2(get_global_id(0), get_global_id(1));
分解为以下子表达式:
(get_global_id(0), get_global_id(1))
这是逗号运算符!换句话说,它的计算结果仅为 get_global_id(1)
。所以我们有:
const int2 src_pos = int2(get_global_id(1));
…将 get_global_id(1)
复制到 int2
的两个组件中。
请注意,我并不是说这种语法和解释 合理 或者编译器应该在没有警告的情况下接受它。不幸的是,与现代 C 和 C++ 编译器相比,OpenCL 编译器在检测和警告您可能的未定义行为或可能的意外语法方面非常糟糕。
我目前正在 OSX 上开发 OpenCL 内核,我正在尝试将输入图像设置为全部 255。
我用 CL_MEM_WRITE_ONLY | CL_MEM_ALLOC_HOST_PTR
和 CL_UNSIGNED_INT8
创建了一个单通道图像,我的内核和主机代码如下:
const sampler_t linear_sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_FILTER_LINEAR | CLK_ADDRESS_CLAMP_TO_EDGE;
__kernel void test(__write_only image2d_t dst)
{
const int2 src_pos = int2(get_global_id(0), get_global_id(1));
write_imagei(dst, src_pos, 255);
}
void clTest(cl_image2d dst)
{
cl_int retval;
cl_kernel kTest = clCreateKernel(m_oclEnv.program, "test", &retval);
CHECK_OCL(clSetKernelArg(kTest, 0, sizeof(cl_mem), (void*)&dst.mem));
size_t grid_item_size[2] = {static_cast<size_t>(m_nFrameWidth), static_cast<size_t>(m_nFrameHeight)};
size_t block_item_size[2] = {8, 8};
cl_uint nDim = 2;
CHECK_OCL(clEnqueueNDRangeKernel(m_oclEnv.queue, kTest, nDim, NULL, grid_item_size, block_item_size, 0, NULL, NULL));
clReleaseKernel(kTest);
}
结果输出图像如下:
显然内核只在y=x的位置绘制,那么问题在哪里?谢谢
ps: 我试过将图像写入GPU并立即读出并且效果很好,所以opencl上下文或环境应该没有任何问题。
我认为,行
const int2 src_pos = int2(get_global_id(0), get_global_id(1));
分解为以下子表达式:
(get_global_id(0), get_global_id(1))
这是逗号运算符!换句话说,它的计算结果仅为 get_global_id(1)
。所以我们有:
const int2 src_pos = int2(get_global_id(1));
…将 get_global_id(1)
复制到 int2
的两个组件中。
请注意,我并不是说这种语法和解释 合理 或者编译器应该在没有警告的情况下接受它。不幸的是,与现代 C 和 C++ 编译器相比,OpenCL 编译器在检测和警告您可能的未定义行为或可能的意外语法方面非常糟糕。