PDA

View Full Version : RGBA to (single channel) grayscale : clEnqueueReadBuffer pbl



wrx
03-11-2011, 02:42 AM
Hi,

I'm trying to convert RGBA grayscale image to single channel buffer. But I have problem with clEnqueueReadBuffer . There is no compilation error but during execution, "Bus error " at execution.



error = clEnqueueReadBuffer(command_queue,
gpu_graybuffer,
CL_TRUE,
0,
sizeof(unsigned char)*SIZE,
&cpu_graybuffer,
0, NULL, NULL);


additional codes :


#define WIDTH 32
#define HEIGHT 32

#define SIZE WIDTH * HEIGHT
...
unsigned char *cpu_graybuffer;
cpu_graybuffer = (unsigned char*)malloc(SIZE);
...
cl_mem gpu_image = clCreateImage2D (context,
CL_MEM_READ_ONLY ,
&format,
width,
height,
rowpitch,
0,
&error);
...

cl_mem gpu_graybuffer = clCreateBuffer ( context,

CL_MEM_WRITE_ONLY,

sizeof(unsigned char)*SIZE,

NULL,

&error);


and maybe where the problem comes, the kernel :



// rgb to grayscale & multi-channel to simple channel
__kernel void rgb_to_gray(__read_only image2d_t image, __global unsigned char *grayscale)
{
const sampler_t sampler=CLK_NORMALIZED_COORDS_FALSE|CLK_ADDRESS_CL AMP|CLK_FILTER_NEAREST;
int x = get_global_id(0); // width
int y = get_global_id(1); // height
uint4 pixel;

//READ PIXEL
pixel = read_imageui(imageIn,sampler,(int2)(x,y));

grayscale[ (HEIGHT-y-1) * HEIGHT + x ] = pixel.x;
// grayscale[0]='a';
}

Maybe, "clEnqueueCopyImageToBuffer" can be another/better solution?

Thanks for sharing your experience.

david.garcia
03-11-2011, 06:06 AM
Okay, so your source image data is grayscale (1 byte per pixel). What is the value of "format" that you pass to clCreateImage2D()?

You are right that clEnqueueCopyImageToBuffer() is a good way to achieve what you want. You could also call clEnqueueMapImage() and that would give you a regular pointer to the image data, which is like having the image as a 1-D buffer. Even if EnqueueMapImage looks a bit scary with so many arguments, in reality it's not very difficult to use and it usually has the best performance.

One more thing: the kernel should say:


grayscale[ (HEIGHT-y-1) * WIDTH + x ] = pixel.x;

...although that's not what is causing the issue.

wrx
03-11-2011, 07:20 AM
Actually a have RGBA grayscale image R=graylevel, G=graylevel, B=graylevel.
format :

cl_image_format format;
format.image_channel_order = CL_RGBA;
format.image_channel_data_type = CL_UNSIGNED_INT8;


I tried to do it with clEnqueueCopyImageToBuffer :



error = clEnqueueWriteImage (command_queue,
gpu_image, //cl_mem image,
CL_TRUE, //cl_bool blocking_write,
origin, //const size_t origin[3],
region, //const size_t region[3],
width * sizeof(char)*4,//size_t input_row_pitch, width * sizeof(unsigned char) * 4
0, //size_t input_slice_pitch,
image, //const void * ptr,
0, //cl_uint num_events_in_wait_list,
NULL, //const cl_event *event_wait_list,
NULL //cl_event *event
);
if(error != CL_SUCCESS){cerr << "Error Code : clEnqueueWriteImage 1 : " << error << endl;return 1;}


error = clEnqueueCopyImageToBuffer (command_queue,
gpu_image, //cl_mem image,
gpu_graybuffer,
origin, //const size_t origin[3],
region, //const size_t region[3],
0,//dst_offset
0, //cl_uint num_events_in_wait_list,
NULL, //const cl_event *event_wait_list,
NULL //cl_event *event
);
if(error != CL_SUCCESS){cerr << "Error Code : clEnqueueCopyImageToBuffer : " << error << endl;return 1;}
/*
result = clEnqueueNDRangeKernel (command_queue,
kernel,
2,
NULL,
&global_work_size[0],
// &local_work_size[0],
NULL,
0, NULL, NULL);
//*/

error = clEnqueueReadBuffer(command_queue,
gpu_graybuffer,
CL_TRUE,
0,
sizeof(unsigned char)*SIZE,
&cpu_graybuffer,
0, NULL, NULL);


Like you can see, I commented clEnqueueNDRangeKernel . I throught there is no kernel to execute, maybe i am wrong ?
But I have segmentation fault during execution at clEnqueueReadBuffer.

Moreover, the image that I use is (SIZE*4) size and grayscale buffer ise (SIZE) size. It can cause the error ?

david.garcia
03-11-2011, 09:52 AM
Moreover, the image that I use is (SIZE*4) size and grayscale buffer ise (SIZE) size. It can cause the error ?

Yes, it is. All that MapImage does is give you a pointer to the image data. Since your image is RGBA8888, it contains 4*SIZE bytes (plus padding).

wrx
03-16-2011, 02:20 AM
I think that it was a size problem like you said. For now, I do the conversion on CPU, like :


rgba_buffer[4*i] = gray_buffer[i]


I'll try to do it soon on GPU.