0
votes

I am following along with Heterogeneous Computing with OpenCL and it is leaving me hanging.

They pass an image, as an array of floats, to enqueueWriteBuffer. I think the image, in this case, has no values for color. It is simply {col,row,col,row,col,row} e.g. {0,0,0,1,0,2,1,0,1,1,1,2...}.

but when they do enqueueReadBuffer the size they expect is HW and if you are going to do an array like I just did the array size would be HW*2.

// SETUP BUFFERS
Buffer d_ip = Buffer(context, CL_MEM_READ_ONLY, W*H*sizeof(float));
Buffer d_op = Buffer(context, CL_MEM_WRITE_ONLY, W*H*sizeof(float));
queue.enqueueWriteBuffer(d_ip, CL_TRUE, 0, W*H*sizeof(float), img); //img, what is img? the book just says it is my image.

// SETUP RANGES
NDRange globalws(W, H);
NDRange localws(16, 16);

// QUEUE AND READ
queue.enqueueNDRangeKernel(rotn_kernel, NullRange, globalws, localws);
queue.enqueueReadBuffer(d_op, CL_TRUE, 0, W*H*sizeof(float), img);

// X AND Y INSIDE THE KERNEL
const int x = get_global_id(0);
const int y = get_global_id(1);

If all of the new pixel coordinates are calculated in the kernel couldn't you just pass an empty float array of the appropriate size (WH apparently although I don't see how it isn't WH*2). But then I tried hard coding this (on a 500x300 image) and it blew up my stack.

2

2 Answers

1
votes

It isn't size W*H*2 because they're probably not storing the data quite like you think. Usually, data of this nature is stored such that the first row of the data is stored in the first W entries, the second in the second W, etc.; this results in an array of size W*H. Thus, to get information about something in row X, column Y, you have to get the element at index (W * X) + Y

1
votes

When writing my OpenCL code, I always treat each kernel as reading a 3D set of data, regardless if the data is 1D, 2D, or 3D:

 __kernel void TestKernel(__global float *Data){
      k = get_global_id(0); //also z
      j = get_global_id(1); //also y
      i = get_global_id(2); //also x

      //Convert 3D to 1D
      int linear_coord = i + get_global_size(0)*j + get_global_size(0)*get_global_size(1)*k;

      //do stuff
 }

When doing the clEnqueueNDKernelRange(...), just set the dimension to be:

 int X = 500;
 int Y = 300;
 int Z = 1;

 size_t GlobalDim = {Z, Y, X};

This let's all of my kernels work easily in all dimensions.

Your code doesn't call any clSetKernelArg, have you added these? Are the OpenCL functions kicking back any errors? You might want to take a step back and use the OpenCL C code instead of the C++ class.