1 /* ************************************************************************
2  * Copyright 2013 Advanced Micro Devices, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  * ************************************************************************/
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 
20 /* No need to explicitely include the OpenCL headers */
21 #include <clFFT.h>
22 
main(void)23 int main( void )
24 {
25     cl_int err;
26     cl_platform_id platform = 0;
27     cl_device_id device = 0;
28     cl_context_properties props[3] = { CL_CONTEXT_PLATFORM, 0, 0 };
29     cl_context ctx = 0;
30     cl_command_queue queue = 0;
31     cl_mem bufX;
32     float *X;
33     cl_event event = NULL;
34     int ret = 0;
35 
36     const size_t N0 = 4, N1 = 4, N2 = 4;
37     char platform_name[128];
38     char device_name[128];
39 
40     /* FFT library realted declarations */
41     clfftPlanHandle planHandle;
42     clfftDim dim = CLFFT_3D;
43     size_t clLengths[3] = {N0, N1, N2};
44 
45     /* Setup OpenCL environment. */
46     err = clGetPlatformIDs( 1, &platform, NULL );
47 
48     size_t ret_param_size = 0;
49     err = clGetPlatformInfo(platform, CL_PLATFORM_NAME,
50             sizeof(platform_name), platform_name,
51             &ret_param_size);
52     printf("Platform found: %s\n", platform_name);
53 
54     err = clGetDeviceIDs( platform, CL_DEVICE_TYPE_DEFAULT, 1, &device, NULL );
55 
56     err = clGetDeviceInfo(device, CL_DEVICE_NAME,
57             sizeof(device_name), device_name,
58             &ret_param_size);
59     printf("Device found on the above platform: %s\n", device_name);
60 
61     props[1] = (cl_context_properties)platform;
62     ctx = clCreateContext( props, 1, &device, NULL, NULL, &err );
63     queue = clCreateCommandQueue( ctx, device, 0, &err );
64 
65     /* Setup clFFT. */
66     clfftSetupData fftSetup;
67     err = clfftInitSetupData(&fftSetup);
68     err = clfftSetup(&fftSetup);
69 
70     /* Allocate host & initialize data. */
71     /* Only allocation shown for simplicity. */
72     size_t buffer_size  = N0 * N1 * N2 * 2 * sizeof(*X);
73     X = (float *)malloc(buffer_size);
74 
75     /* print input array just using the
76      * indices to fill the array with data */
77     printf("\nPerforming fft on an two dimensional array of size N0 x N1 x N2 : %lu x %lu x %lu\n", (unsigned long)N0, (unsigned long)N1, (unsigned long)N2);
78     size_t i, j, k;
79     i = j = k = 0;
80     for (i=0; i<N0; ++i) {
81         for (j=0; j<N1; ++j) {
82             for (k=0; k<N2; ++k) {
83                 float x = 0.0f;
84                 float y = 0.0f;
85                 if (i==0 && j==0 && k==0) {
86                     x = y = 0.5f;
87                 }
88                 size_t idx = 2*(k+j*N2+i*N1*N2);
89                 X[idx] = x;
90                 X[idx+1] = y;
91                 printf("(%f, %f) ", X[idx], X[idx+1]);
92             }
93             printf("\n");
94         }
95         printf("\n");
96     }
97 
98     /* Prepare OpenCL memory objects and place data inside them. */
99     bufX = clCreateBuffer( ctx, CL_MEM_READ_WRITE, buffer_size, NULL, &err );
100 
101     err = clEnqueueWriteBuffer( queue, bufX, CL_TRUE, 0, buffer_size, X, 0, NULL, NULL );
102 
103     /* Create a default plan for a complex FFT. */
104     err = clfftCreateDefaultPlan(&planHandle, ctx, dim, clLengths);
105 
106     /* Set plan parameters. */
107     err = clfftSetPlanPrecision(planHandle, CLFFT_SINGLE);
108     err = clfftSetLayout(planHandle, CLFFT_COMPLEX_INTERLEAVED, CLFFT_COMPLEX_INTERLEAVED);
109     err = clfftSetResultLocation(planHandle, CLFFT_INPLACE);
110 
111     /* Bake the plan. */
112     err = clfftBakePlan(planHandle, 1, &queue, NULL, NULL);
113 
114     /* Execute the plan. */
115     err = clfftEnqueueTransform(planHandle, CLFFT_FORWARD, 1, &queue, 0, NULL, NULL, &bufX, NULL, NULL);
116 
117     /* Wait for calculations to be finished. */
118     err = clFinish(queue);
119 
120     /* Fetch results of calculations. */
121     err = clEnqueueReadBuffer( queue, bufX, CL_TRUE, 0, buffer_size, X, 0, NULL, NULL );
122 
123     /* print output array */
124     printf("\n\nfft result: \n");
125     i = j = k = 0;
126     for (i=0; i<N0; ++i) {
127         for (j=0; j<N1; ++j) {
128             for (k=0; k<N2; ++k) {
129                 size_t idx = 2*(k+j*N2+i*N1*N2);
130                 printf("(%f, %f) ", X[idx], X[idx+1]);
131             }
132             printf("\n");
133         }
134         printf("\n");
135     }
136     printf("\n");
137 
138     /* Release OpenCL memory objects. */
139     clReleaseMemObject( bufX );
140 
141     free(X);
142 
143     /* Release the plan. */
144     err = clfftDestroyPlan( &planHandle );
145 
146     /* Release clFFT library. */
147     clfftTeardown( );
148 
149     /* Release OpenCL working objects. */
150     clReleaseCommandQueue( queue );
151     clReleaseContext( ctx );
152 
153     return ret;
154 }
155