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 
18 #ifndef CLARGS_H_
19 #define CLARGS_H_
20 
21 #if defined(__APPLE__) || defined(__MACOSX)
22 #include <OpenCL/cl.h>
23 #else
24 #include <CL/cl.h>
25 #endif
26 
27 #include <string.h>
28 #include <dis_warning.h>
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 #define INIT_KARG(karg, val)                            \
35 do {                                                    \
36     memcpy((karg)->arg.data, &(val), sizeof(val));      \
37     (karg)->typeSize = sizeof(val);                     \
38 } while (0)
39 
40 enum {
41     MAX_KERNEL_ARGS = 32,
42     MAX_ARG_SIZE = sizeof(cl_double2),
43     MAX_WORK_DIM = 3
44 };
45 
46 // memory object data transfer direction
47 typedef enum MemobjDir {
48     MEMOBJ_READ = 0x1,
49     MEMOBJ_WRITE = 0x2
50 } MemobjDir;
51 
52 typedef enum KernelLaunchPhase {
53     PHASE_SET_ARGS,
54     PHASE_ENQUEUE_WRITE,
55     PHASE_ENQUEUE_KERNEL,
56     PHASE_PROFILING,
57     PHASE_ENQUEUE_READ
58 } KernelLaunchPhase;
59 
60 typedef union KernelArgValue {
61     cl_mem mem;
62     int ival;
63     unsigned char data[MAX_ARG_SIZE];
64 } KernelArgValue;
65 
66 /*
67  * Structure describing an argument to be passed to a kernel
68  *
69  * @arg:        pointer to the argument
70  * @ardIdx:     argument index in the kernel argument list
71  * @hostBuf:    buffer to copy data to/from from/to GPU memory
72  * @enqType:    buffer enqueue type
73  * @sync:       blocking I/O
74  * @event:      event for I/O
75  */
76 typedef struct KernelArg {
77     KernelArgValue arg;
78     unsigned int typeSize;  // argument type size, ignored for mem objects
79     void *hostBuf;          // host buffer for using with OpenCL memory objects
80     size_t hostBufLen;
81     MemobjDir dir;
82 } KernelArg;
83 
84 typedef struct KernelDesc {
85     cl_kernel kernel;
86     size_t globalThreads[MAX_WORK_DIM];
87     size_t localThreads[MAX_WORK_DIM];
88     size_t workDim;
89     const cl_event *eventWaitList;
90     size_t waitListSize;
91     cl_event *event;
92     int nowait;
93     int needExecTime;
94     KernelArg args[MAX_KERNEL_ARGS];
95     unsigned long execTime;
96 } KernelDesc;
97 
98 typedef struct KernelErrorInfo {
99     unsigned int wrongArg;
100     KernelLaunchPhase phase;
101 } KernelErrorInfo;
102 
103 /*
104  * store kernel arguments launch the kernel and read its results
105  *
106  * @kernDesc:    descriptor of the kernel to be launched
107  * @queue:       command queue associated with the device
108  * @errInfo:     location to store info about occurred error,
109  *               ignored if NULL
110  *
111  * The function gets itself number of arguments to the kernel
112  * usging the OpenCL API
113  */
114 cl_int launchClKernel(
115     KernelDesc *kernDesc,
116     cl_command_queue queue,
117     KernelErrorInfo *errInfo);
118 
119 /*
120  * build a program from source
121  *
122  * @source:     program source
123  * @buildOpts:  options to the opencl program builder
124  * @DevID:      ID of device to create program for
125  * @logBuf:     buffer to store build log at error
126  * @status:     location to store OpenCL status at error
127  *
128  * On success returns a build program object.
129  * On error returns <NULL>, and stores to the 'status' location
130  * opencl status; if <NULL> result is returned, but 'status'
131  * cointains 'CL_SUCCESS', it means an file I/O or memory allocation
132  * failure is occurred. If 'status' is set to NULL, it is ignored
133  */
134 cl_program
135 buildClProgram(
136     const char *source,
137     const char *buildOpts,
138     cl_context ctx,
139     cl_device_id devID,
140     char *logBuf,
141     size_t logBufSize,
142     cl_int *status);
143 
144 /*
145  * TODO: Doxygen-style comments
146  */
147 cl_program
148 createClProgramWithBinary(
149     cl_context ctx,
150     cl_device_id devID,
151     unsigned char *binary,
152     size_t binSize,
153     cl_int *status);
154 
155 /*
156  * TODO: Doxygen-style comments
157  */
158 size_t
159 getProgramBinarySize(cl_program program);
160 
161 /*
162  * TODO: Doxygen-style comments
163  */
164 unsigned char
165 *getProgramBinary(cl_program program);
166 
167 /*
168  * set a kernel argument of the size_t type
169  */
170 static __inline void
initSizeKarg(KernelArg * arg,size_t value)171 initSizeKarg(KernelArg *arg, size_t value)
172 {
173     memcpy(arg->arg.data, &value, sizeof(cl_uint));
174     arg->typeSize = sizeof(cl_uint);
175 }
176 
177 /*
178  * @inOut: memory object data transfer direction
179  */
180 static __inline void
initMemobjKarg(KernelArg * karg,cl_mem memobj,void * hostBuf,size_t hostBufLen,MemobjDir dir)181 initMemobjKarg(
182     KernelArg *karg,
183     cl_mem memobj,
184     void *hostBuf,
185     size_t hostBufLen,
186     MemobjDir dir)
187 {
188     karg->arg.mem = memobj;
189     karg->typeSize = sizeof(cl_mem);
190     karg->hostBuf = hostBuf;
191     karg->hostBufLen = hostBufLen;
192     karg->dir = dir;
193 }
194 
195 #ifdef __cplusplus
196 }
197 #endif
198 
199 #endif /* CLARGS_H_ */
200