clMathLibraries / clFFT

a software library containing FFT functions written in OpenCL
Apache License 2.0
620 stars 192 forks source link

Is operating on images supported? #236

Open Huud opened 3 years ago

Huud commented 3 years ago

I'm trying to modify the fft2d example to work on real single channel float input/output, but, clfftEnqueueTransform keeps giving me -38 CLFFT_INVALID_MEM_OBJECT if I use a cl_mem created with clCreateImage, it works fine with clCreateBuffer. The code:


int main( void )
{

//    Mat test(4,4, CV_32F);
//    test = 5;
//    std::cout << test << std::endl;
//    cv::dft(test, test);
//    std::cout << test;

    cl_int err;
    cl_platform_id platform = 0;
    cl_device_id device = 0;
    cl_context_properties props[3] = { CL_CONTEXT_PLATFORM, 0, 0 };
    cl_context ctx = 0;
    cl_command_queue queue = 0;
    cl_mem bufX;
    float *X;
    cl_event event = NULL;
    int ret = 0;

    const size_t N0 = 4, N1 = 4;
    char platform_name[128];
    char device_name[128];

    clfftPlanHandle planHandle;
    clfftDim dim = CLFFT_2D;
    size_t clLengths[2] = {N0, N1};

    err = clGetPlatformIDs( 1, &platform, NULL );
    err = clGetDeviceIDs( platform, CL_DEVICE_TYPE_DEFAULT, 1, &device, NULL );
    props[1] = (cl_context_properties)platform;
    ctx = clCreateContext( props, 1, &device, NULL, NULL, &err );
    queue = clCreateCommandQueue( ctx, device, 0, &err );
    clfftSetupData fftSetup;
    err = clfftInitSetupData(&fftSetup);
    err = clfftSetup(&fftSetup);

    size_t buffer_size  = N0 * N1 * sizeof(float);
    X = (float *)malloc(buffer_size);
    int i, j;
    for (i=0; i<N0; ++i) for (j=0; j<N1; ++j) X[i+N0*j] = 5.0;
    cout << "input:" << endl;
    for (i=0; i<N0; ++i){ for (j=0; j<N1; ++j) cout << X[i+N0*j] << " ";  cout << endl;};

    cl_image_format clImageFormat;
    clImageFormat.image_channel_order = CL_R;
    clImageFormat.image_channel_data_type = CL_FLOAT;

    cl_image_desc clImageDesc;
    clImageDesc.image_type = CL_MEM_OBJECT_IMAGE2D;
    clImageDesc.image_width = N0;
    clImageDesc.image_height = N1;
    clImageDesc.image_row_pitch = 0;
    clImageDesc.image_slice_pitch = 0;
    clImageDesc.num_mip_levels = 0;
    clImageDesc.num_samples = 0;
    clImageDesc.buffer = NULL;

    bufX = clCreateImage(ctx, CL_MEM_READ_WRITE, &clImageFormat, &clImageDesc, NULL, &err ); if(err < 0) cout << "clCreateImage" << err << endl;
    size_t origin[3] = { 0, 0, 0 };
    size_t region[3] = { N0, N1, 1};
    err = clEnqueueWriteImage(queue, bufX, CL_TRUE, origin, region, 0, 0, X, 0,0,0);         if(err < 0) cout << "clEnqueueWriteImage" << err << endl;
    err = clfftCreateDefaultPlan(&planHandle, ctx, dim, clLengths);                          if(err < 0) cout << "clfftCreateDefaultPlan" << err << endl;
    err = clfftSetPlanPrecision(planHandle, CLFFT_SINGLE);                                   if(err < 0) cout << "clfftSetPlanPrecision" << err << endl;
    err = clfftSetLayout(planHandle, CLFFT_REAL, CLFFT_REAL);                                if(err < 0) cout << "clfftSetLayout" << err << endl;
    err = clfftSetResultLocation(planHandle, CLFFT_INPLACE);                                 if(err < 0) cout << "clfftSetResultLocation" << err << endl;
    err = clfftBakePlan(planHandle, 1, &queue, NULL, NULL);                                  if(err < 0) cout << "clfftBakePlan" << err << endl;
    err = clfftEnqueueTransform(planHandle, CLFFT_FORWARD, 1, &queue, 0, NULL, NULL, &bufX, NULL, NULL);if(err < 0) cout << "clfftEnqueueTransform" << err << endl;
    err = clEnqueueReadImage(queue, bufX, CL_TRUE, origin, region, 0, 0, X, 0,0,0);          if(err < 0) cout << "clEnqueueReadImage" << err << endl;
    err = clFinish(queue);                                                                   if(err < 0) cout << "clFinish" << err << endl;

    printf("\n\nfft result: \n");
    for (i=0; i<N0; ++i){ for (j=0; j<N1; ++j) cout << X[i+N0*j] << " ";  cout << endl;};
    printf("\n");
    clReleaseMemObject( bufX );
    free(X);
    err = clfftDestroyPlan( &planHandle );
    clfftTeardown( );
    clReleaseCommandQueue( queue );
    clReleaseContext( ctx );
}