RGBA to (single channel) grayscale : clEnqueueReadBuffer pbl

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_CLAMP|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.

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.

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 ?

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).

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.