1 /*
2 * Copyright (c) 2012-2020 The Khronos Group 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 * OpenCL is a trademark of Apple Inc. used under license by Khronos.
17 */
18
19 #include "icd.h"
20 #include "icd_dispatch.h"
21 #include "icd_version.h"
22
23 #include <stdlib.h>
24 #include <string.h>
25
26 static clGetICDLoaderInfoOCLICD_t clGetICDLoaderInfoOCLICD;
27 cl_int CL_API_CALL
clGetICDLoaderInfoOCLICD(cl_icdl_info param_name,size_t param_value_size,void * param_value,size_t * param_value_size_ret)28 clGetICDLoaderInfoOCLICD(
29 cl_icdl_info param_name,
30 size_t param_value_size,
31 void * param_value,
32 size_t * param_value_size_ret)
33 {
34 static const char cl_icdl_OCL_VERSION[] = OPENCL_ICD_LOADER_OCL_VERSION_STRING;
35 static const char cl_icdl_VERSION[] = OPENCL_ICD_LOADER_VERSION_STRING;
36 static const char cl_icdl_NAME[] = OPENCL_ICD_LOADER_NAME_STRING;
37 static const char cl_icdl_VENDOR[] = OPENCL_ICD_LOADER_VENDOR_STRING;
38 size_t pvs;
39 void * pv;
40
41 #define KHR_ICD_CASE_STRING_PARAM_NAME(name) \
42 case CL_ICDL_ ## name: \
43 pvs = strlen(cl_icdl_ ## name) + 1; \
44 pv = (void *)cl_icdl_ ## name; \
45 break
46
47 switch (param_name) {
48 KHR_ICD_CASE_STRING_PARAM_NAME(OCL_VERSION);
49 KHR_ICD_CASE_STRING_PARAM_NAME(VERSION);
50 KHR_ICD_CASE_STRING_PARAM_NAME(NAME);
51 KHR_ICD_CASE_STRING_PARAM_NAME(VENDOR);
52 default:
53 return CL_INVALID_VALUE;
54 }
55
56 #undef KHR_ICD_CASE_PARAM_NAME
57
58 if (param_value) {
59 if (param_value_size < pvs)
60 return CL_INVALID_VALUE;
61 memcpy(param_value, pv, pvs);
62 }
63 if (param_value_size_ret != NULL)
64 *param_value_size_ret = pvs;
65 return CL_SUCCESS;
66 }
67
khrIcdGetExtensionFunctionAddress(const char * function_name)68 static void* khrIcdGetExtensionFunctionAddress(const char* function_name)
69 {
70 // Most extensions, including multi-vendor KHR and EXT extensions,
71 // do not need to be ICD-aware and do not require any ICD loader
72 // modifications. The KHR and EXT extensions below were added for
73 // backwards compatibility only.
74 #define KHR_ICD_CHECK_EXTENSION_FUNCTION(name) \
75 do \
76 { \
77 if (!strcmp(function_name, #name)) \
78 { \
79 return (void*)(size_t)&name; \
80 } \
81 } while (0)
82
83 // Functions supporting the creation of OpenCL Memory Objects
84 // from OpenGL Objects (cl_apple_gl_sharing, cl_khr_gl_sharing)
85 KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromGLBuffer);
86 KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromGLTexture);
87 KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromGLTexture2D);
88 KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromGLTexture3D);
89 KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromGLRenderbuffer);
90 KHR_ICD_CHECK_EXTENSION_FUNCTION(clGetGLObjectInfo);
91 KHR_ICD_CHECK_EXTENSION_FUNCTION(clGetGLTextureInfo);
92 KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueAcquireGLObjects);
93 KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueReleaseGLObjects);
94
95 // cl_khr_gl_sharing
96 KHR_ICD_CHECK_EXTENSION_FUNCTION(clGetGLContextInfoKHR);
97
98 // cl_khr_gl_event
99 KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateEventFromGLsyncKHR);
100
101 #if defined(_WIN32)
102 // cl_khr_d3d10_sharing
103 KHR_ICD_CHECK_EXTENSION_FUNCTION(clGetDeviceIDsFromD3D10KHR);
104 KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromD3D10BufferKHR);
105 KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromD3D10Texture2DKHR);
106 KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromD3D10Texture3DKHR);
107 KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueAcquireD3D10ObjectsKHR);
108 KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueReleaseD3D10ObjectsKHR);
109 // cl_khr_d3d11_sharing
110 KHR_ICD_CHECK_EXTENSION_FUNCTION(clGetDeviceIDsFromD3D11KHR);
111 KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromD3D11BufferKHR);
112 KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromD3D11Texture2DKHR);
113 KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromD3D11Texture3DKHR);
114 KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueAcquireD3D11ObjectsKHR);
115 KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueReleaseD3D11ObjectsKHR);
116 // cl_khr_dx9_media_sharing
117 KHR_ICD_CHECK_EXTENSION_FUNCTION(clGetDeviceIDsFromDX9MediaAdapterKHR);
118 KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromDX9MediaSurfaceKHR);
119 KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueAcquireDX9MediaSurfacesKHR);
120 KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueReleaseDX9MediaSurfacesKHR);
121 #endif
122
123 // cl_ext_device_fission
124 KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateSubDevicesEXT);
125 KHR_ICD_CHECK_EXTENSION_FUNCTION(clRetainDeviceEXT);
126 KHR_ICD_CHECK_EXTENSION_FUNCTION(clReleaseDeviceEXT);
127
128 // cl_khr_egl_image
129 KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromEGLImageKHR);
130 KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueAcquireEGLObjectsKHR);
131 KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueReleaseEGLObjectsKHR);
132
133 // cl_khr_egl_event
134 KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateEventFromEGLSyncKHR);
135
136 // cl_khr_sub_groups
137 KHR_ICD_CHECK_EXTENSION_FUNCTION(clGetKernelSubGroupInfoKHR);
138
139 // cl_icdl
140 KHR_ICD_CHECK_EXTENSION_FUNCTION(clGetICDLoaderInfoOCLICD);
141
142 #undef KHR_ICD_CHECK_EXTENSION_FUNCTION
143
144 return NULL;
145 }
146
147 #ifdef __cplusplus
148 extern "C" {
149 #endif
150
clGetPlatformIDs_body(cl_uint num_entries,cl_platform_id * platforms,cl_uint * num_platforms)151 static inline cl_int clGetPlatformIDs_body(
152 cl_uint num_entries,
153 cl_platform_id* platforms,
154 cl_uint* num_platforms)
155 {
156 KHRicdVendor* vendor = NULL;
157 cl_uint i;
158
159 if (!num_entries && platforms)
160 {
161 return CL_INVALID_VALUE;
162 }
163 if (!platforms && !num_platforms)
164 {
165 return CL_INVALID_VALUE;
166 }
167 // set num_platforms to 0 and set all platform pointers to NULL
168 if (num_platforms)
169 {
170 *num_platforms = 0;
171 }
172 for (i = 0; i < num_entries && platforms; ++i)
173 {
174 platforms[i] = NULL;
175 }
176 // return error if we have no platforms
177 if (!khrIcdVendors)
178 {
179 return CL_PLATFORM_NOT_FOUND_KHR;
180 }
181 // otherwise enumerate all platforms
182 for (vendor = khrIcdVendors; vendor; vendor = vendor->next)
183 {
184 if (num_entries && platforms)
185 {
186 *(platforms++) = vendor->platform;
187 --num_entries;
188 }
189 if (num_platforms)
190 {
191 ++(*num_platforms);
192 }
193 }
194 return CL_SUCCESS;
195 }
196
clGetPlatformIDs_disp(cl_uint num_entries,cl_platform_id * platforms,cl_uint * num_platforms)197 cl_int CL_API_CALL clGetPlatformIDs_disp(
198 cl_uint num_entries,
199 cl_platform_id* platforms,
200 cl_uint* num_platforms)
201 {
202 return clGetPlatformIDs_body(
203 num_entries,
204 platforms,
205 num_platforms);
206 }
207
clGetPlatformIDs(cl_uint num_entries,cl_platform_id * platforms,cl_uint * num_platforms)208 CL_API_ENTRY cl_int CL_API_CALL clGetPlatformIDs(
209 cl_uint num_entries,
210 cl_platform_id* platforms,
211 cl_uint* num_platforms)
212 {
213 // initialize the platforms (in case they have not been already)
214 khrIcdInitialize();
215
216 #if defined(CL_ENABLE_LAYERS)
217 if (khrFirstLayer)
218 return khrFirstLayer->dispatch.clGetPlatformIDs(
219 num_entries,
220 platforms,
221 num_platforms);
222 #endif // defined(CL_ENABLE_LAYERS)
223 return clGetPlatformIDs_body(
224 num_entries,
225 platforms,
226 num_platforms);
227 }
228
clGetExtensionFunctionAddress_body(const char * function_name)229 static inline void* clGetExtensionFunctionAddress_body(
230 const char* function_name)
231 {
232 void* function_address = NULL;
233 size_t function_name_length = 0;
234 KHRicdVendor* vendor = NULL;
235
236 KHR_ICD_VALIDATE_HANDLE_RETURN_ERROR(function_name, NULL);
237
238 // check if this is an ICD-aware extension
239 function_address = khrIcdGetExtensionFunctionAddress(function_name);
240 if (function_address)
241 {
242 return function_address;
243 }
244
245 // fall back to vendor extension detection
246 function_name_length = strlen(function_name);
247 for (vendor = khrIcdVendors; vendor; vendor = vendor->next)
248 {
249 size_t vendor_suffix_length = strlen(vendor->suffix);
250 if (vendor_suffix_length <= function_name_length &&
251 vendor_suffix_length > 0)
252 {
253 const char* function_suffix =
254 function_name + function_name_length - vendor_suffix_length;
255 if (!strcmp(function_suffix, vendor->suffix))
256 {
257 return vendor->clGetExtensionFunctionAddress(function_name);
258 }
259 }
260 }
261
262 return NULL;
263 }
264
clGetExtensionFunctionAddress_disp(const char * function_name)265 void* CL_API_CALL clGetExtensionFunctionAddress_disp(
266 const char* function_name)
267 {
268 return clGetExtensionFunctionAddress_body(
269 function_name);
270 }
271
clGetExtensionFunctionAddress(const char * function_name)272 CL_API_ENTRY void* CL_API_CALL clGetExtensionFunctionAddress(
273 const char* function_name)
274 {
275 // make sure the ICD is initialized
276 khrIcdInitialize();
277
278 #if defined(CL_ENABLE_LAYERS)
279 if (khrFirstLayer)
280 return khrFirstLayer->dispatch.clGetExtensionFunctionAddress(
281 function_name);
282 #endif // defined(CL_ENABLE_LAYERS)
283 return clGetExtensionFunctionAddress_body(
284 function_name);
285 }
286
clGetExtensionFunctionAddressForPlatform_body(cl_platform_id platform,const char * function_name)287 static inline void* clGetExtensionFunctionAddressForPlatform_body(
288 cl_platform_id platform,
289 const char* function_name)
290 {
291 void* function_address = NULL;
292
293 KHR_ICD_VALIDATE_HANDLE_RETURN_ERROR(function_name, NULL);
294
295 // check if this is an ICD-aware extension
296 function_address = khrIcdGetExtensionFunctionAddress(function_name);
297 if (function_address)
298 {
299 return function_address;
300 }
301
302 // This is not an ICD-aware extension, so call into the implementation
303 // to get the extension function address.
304
305 KHR_ICD_VALIDATE_HANDLE_RETURN_ERROR(platform, NULL);
306 return platform->dispatch->clGetExtensionFunctionAddressForPlatform(
307 platform,
308 function_name);
309 }
310
clGetExtensionFunctionAddressForPlatform_disp(cl_platform_id platform,const char * function_name)311 void* CL_API_CALL clGetExtensionFunctionAddressForPlatform_disp(
312 cl_platform_id platform,
313 const char* function_name)
314 {
315 return clGetExtensionFunctionAddressForPlatform_body(
316 platform,
317 function_name);
318 }
319
clGetExtensionFunctionAddressForPlatform(cl_platform_id platform,const char * function_name)320 CL_API_ENTRY void* CL_API_CALL clGetExtensionFunctionAddressForPlatform(
321 cl_platform_id platform,
322 const char* function_name)
323 {
324 // make sure the ICD is initialized
325 khrIcdInitialize();
326 #if defined(CL_ENABLE_LAYERS)
327 if (khrFirstLayer)
328 return khrFirstLayer->dispatch.clGetExtensionFunctionAddressForPlatform(
329 platform,
330 function_name);
331 #endif // defined(CL_ENABLE_LAYERS)
332 return clGetExtensionFunctionAddressForPlatform_body(
333 platform,
334 function_name);
335 }
336
337 #ifdef __cplusplus
338 }
339 #endif
340