user2415010
user2415010

Reputation:

clSetKernelArg returns with CL_INVALID_MEM_OBJECT

I'm totally green with OpenCL. I'm trying to get a sample on Intel's website to work, but I cannot. This is the sample.

I'm getting the error CL_INVALID_MEM_OBJECT when trying to pass an integer argument to clSetKernelArg like so:

err = clSetKernelArg(ocl->kernel, 2, sizeof(cl_mem), (void *)&width);
if (CL_SUCCESS != err)
{
    LogError("Error: Failed to set argument dstMem, returned %s\n", TranslateOpenCLError(err));
    return err;
}

The tutorial is supposed to work on an image, and specifically states the arguments should be set as such:

err  |= clSetKernelArg(ocl->kernel, 2, sizeof(cl_mem), (void *) &width);
err  |= clSetKernelArg(ocl->kernel, 3, sizeof(cl_mem), (void *) &height);

Here is the full function:

cl_uint SetKernelArguments(ocl_args_d_t *ocl, cl_uint width, cl_uint height)
{
    cl_int err = CL_SUCCESS;

    err  =  clSetKernelArg(ocl->kernel, 0, sizeof(cl_mem), (void *)&ocl->srcA);
    if (CL_SUCCESS != err)
    {
        LogError("error: Failed to set argument srcA, returned %s\n", TranslateOpenCLError(err));
        return err;
    }

    err  = clSetKernelArg(ocl->kernel, 1, sizeof(cl_mem), (void *)&ocl->dstMem);
    if (CL_SUCCESS != err)
    {
        LogError("Error: Failed to set argument dstMem, returned %s\n", TranslateOpenCLError(err));
        return err;
    }

    err = clSetKernelArg(ocl->kernel, 2, sizeof(cl_uint), (void *)&width);
    if (CL_SUCCESS != err)
    {
        LogError("Error: Failed to set argument dstMem, returned %s\n", TranslateOpenCLError(err));
        return err;
    }

    err = clSetKernelArg(ocl->kernel, 3, sizeof(cl_mem), (void *)&height);
    if (CL_SUCCESS != err)
    {
        LogError("Error: Failed to set argument dstMem, returned %s\n", TranslateOpenCLError(err));
        return err;
    }

    return err;
}

One last note: changing the size to sizeof(cl_uint) for clSetKernelArg changes the error to CL_INVALID_ARG_SIZE.

In case this isn't enough, I have the source made public on github here.

Quite certain I followed the instructions well on the tutorial, but I cannot figure out what I may have missed. Thanks for your time.

Upvotes: 2

Views: 6002

Answers (2)

Robert Wang
Robert Wang

Reputation: 1221

Let me try to answer your question briefly.

If we take a look at the definition of clSetKernelArg function:

cl_int clSetKernelArg ( cl_kernel kernel,
    cl_uint arg_index,
    size_t arg_size,
    const void *arg_value)

you can see, what you need pass to clSetKernelArg is a pointer to your argument, and the size of the argument. Now, your argument is just a normal cl_uint variable. Therefore, we can have the followings:

const void *arg_value -> &width
size_t arg_size -> sizeof(width)

So, your API call will be like this:

err  |= clSetKernelArg(ocl->kernel, 2, sizeof(width), (void *) &width);
err  |= clSetKernelArg(ocl->kernel, 3, sizeof(height), (void *) &height);

Upvotes: 1

Hu Yixuan
Hu Yixuan

Reputation: 21

I went through your code on github quickly, I think I can give you some advice.

First, call "clCreateBuffer" before you use the "cl_mem" type memory object, in other words, make sure "width" has the type of "cl_mem" before you call

cl_mem cl_width = clCreateBuffer(context,CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR, sizeof(width), &width,*err); err = clSetKernelArg(ocl->kernel, 2, sizeof(cl_mem), &cl_width);

I am not sure whether it will work.

Second, it's depreciated to use "cl_mem" to pass a value such as an "int" or a "char" according to my experience. If I were you, I'll omit the "clCreateBuffer" clause and write the code like:

cl_int width = doSomeThingYouWant();

err = clSetKernelArg(ocl->kernel, 2, sizeof(cl_uint), &width);

Hope it can be helpful.

Upvotes: 2

Related Questions