Added OpenCL Universal Driver Support for Win10 RS3 (#21)
[platform/upstream/OpenCL-ICD-Loader.git] / icd.c
1 /*
2  * Copyright (c) 2016 The Khronos Group Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software source and associated documentation files (the "Materials"),
6  * to deal in the Materials without restriction, including without limitation
7  * the rights to use, copy, modify, compile, merge, publish, distribute,
8  * sublicense, and/or sell copies of the Materials, and to permit persons to
9  * whom the Materials are furnished to do so, subject the following terms and
10  * conditions:
11  *
12  * All modifications to the Materials used to create a binary that is
13  * distributed to third parties shall be provided to Khronos with an
14  * unrestricted license to use for the purposes of implementing bug fixes and
15  * enhancements to the Materials;
16  *
17  * If the binary is used as part of an OpenCL(TM) implementation, whether binary
18  * is distributed together with or separately to that implementation, then
19  * recipient must become an OpenCL Adopter and follow the published OpenCL
20  * conformance process for that implementation, details at:
21  * http://www.khronos.org/conformance/;
22  *
23  * The above copyright notice, the OpenCL trademark license, and this permission
24  * notice shall be included in all copies or substantial portions of the
25  * Materials.
26  *
27  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32  * OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS IN
33  * THE MATERIALS.
34  *
35  * OpenCL is a trademark of Apple Inc. used under license by Khronos.
36  */
37
38 #include "icd.h"
39 #include "icd_dispatch.h"
40 #include <stdlib.h>
41 #include <string.h>
42
43 KHRicdVendor *khrIcdVendors = NULL;
44
45 // entrypoint to initialize the ICD and add all vendors
46 void khrIcdInitialize(void)
47 {
48     // enumerate vendors present on the system
49     khrIcdOsVendorsEnumerateOnce();
50 }
51
52 void khrIcdVendorAdd(const char *libraryName)
53 {
54     void *library = NULL;
55     cl_int result = CL_SUCCESS;
56     pfn_clGetExtensionFunctionAddress p_clGetExtensionFunctionAddress = NULL;
57     pfn_clIcdGetPlatformIDs p_clIcdGetPlatformIDs = NULL;
58     cl_uint i = 0;
59     cl_uint platformCount = 0;
60     cl_platform_id *platforms = NULL;
61     KHRicdVendor *vendorIterator = NULL;
62
63     // require that the library name be valid
64     if (!libraryName) 
65     {
66         goto Done;
67     }
68     KHR_ICD_TRACE("attempting to add vendor %s...\n", libraryName);
69
70     // load its library and query its function pointers
71     library = khrIcdOsLibraryLoad(libraryName);
72     if (!library)
73     {
74         KHR_ICD_TRACE("failed to load library %s\n", libraryName);
75         goto Done;
76     }
77
78     // ensure that we haven't already loaded this vendor
79     for (vendorIterator = khrIcdVendors; vendorIterator; vendorIterator = vendorIterator->next)
80     {
81         if (vendorIterator->library == library)
82         {
83             KHR_ICD_TRACE("already loaded vendor %s, nothing to do here\n", libraryName);
84             goto Done;
85         }
86     }
87
88     // get the library's clGetExtensionFunctionAddress pointer
89     p_clGetExtensionFunctionAddress = (pfn_clGetExtensionFunctionAddress)(size_t)khrIcdOsLibraryGetFunctionAddress(library, "clGetExtensionFunctionAddress");
90     if (!p_clGetExtensionFunctionAddress)
91     {
92         KHR_ICD_TRACE("failed to get function address clGetExtensionFunctionAddress\n");
93         goto Done;
94     }
95
96     // use that function to get the clIcdGetPlatformIDsKHR function pointer
97     p_clIcdGetPlatformIDs = (pfn_clIcdGetPlatformIDs)(size_t)p_clGetExtensionFunctionAddress("clIcdGetPlatformIDsKHR");
98     if (!p_clIcdGetPlatformIDs)
99     {
100         KHR_ICD_TRACE("failed to get extension function address clIcdGetPlatformIDsKHR\n");
101         goto Done;
102     }
103
104     // query the number of platforms available and allocate space to store them
105     result = p_clIcdGetPlatformIDs(0, NULL, &platformCount);
106     if (CL_SUCCESS != result)
107     {
108         KHR_ICD_TRACE("failed clIcdGetPlatformIDs\n");
109         goto Done;
110     }
111     platforms = (cl_platform_id *)malloc(platformCount * sizeof(cl_platform_id) );
112     if (!platforms)
113     {
114         KHR_ICD_TRACE("failed to allocate memory\n");
115         goto Done;
116     }
117     memset(platforms, 0, platformCount * sizeof(cl_platform_id) );
118     result = p_clIcdGetPlatformIDs(platformCount, platforms, NULL);
119     if (CL_SUCCESS != result)
120     {
121         KHR_ICD_TRACE("failed clIcdGetPlatformIDs\n");
122         goto Done;
123     }
124
125     // for each platform, add it
126     for (i = 0; i < platformCount; ++i)
127     {
128         KHRicdVendor* vendor = NULL;
129         char *suffix;
130         size_t suffixSize;
131
132         // call clGetPlatformInfo on the returned platform to get the suffix
133         if (!platforms[i])
134         {
135             continue;
136         }
137         result = platforms[i]->dispatch->clGetPlatformInfo(
138             platforms[i],
139             CL_PLATFORM_ICD_SUFFIX_KHR,
140             0,
141             NULL,
142             &suffixSize);
143         if (CL_SUCCESS != result)
144         {
145             continue;
146         }
147         suffix = (char *)malloc(suffixSize);
148         if (!suffix)
149         {
150             continue;
151         }
152         result = platforms[i]->dispatch->clGetPlatformInfo(
153             platforms[i],
154             CL_PLATFORM_ICD_SUFFIX_KHR,
155             suffixSize,
156             suffix,
157             NULL);            
158         if (CL_SUCCESS != result)
159         {
160             free(suffix);
161             continue;
162         }
163
164         // allocate a structure for the vendor
165         vendor = (KHRicdVendor*)malloc(sizeof(*vendor) );
166         if (!vendor) 
167         {
168             free(suffix);
169             KHR_ICD_TRACE("failed to allocate memory\n");
170             continue;
171         }
172         memset(vendor, 0, sizeof(*vendor) );
173
174         // populate vendor data
175         vendor->library = khrIcdOsLibraryLoad(libraryName);
176         if (!vendor->library) 
177         {
178             free(suffix);
179             free(vendor);
180             KHR_ICD_TRACE("failed get platform handle to library\n");
181             continue;
182         }
183         vendor->clGetExtensionFunctionAddress = p_clGetExtensionFunctionAddress;
184         vendor->platform = platforms[i];
185         vendor->suffix = suffix;
186
187         // add this vendor to the list of vendors at the tail
188         {
189             KHRicdVendor **prevNextPointer = NULL;
190             for (prevNextPointer = &khrIcdVendors; *prevNextPointer; prevNextPointer = &( (*prevNextPointer)->next) );
191             *prevNextPointer = vendor;
192         }
193
194         KHR_ICD_TRACE("successfully added vendor %s with suffix %s\n", libraryName, suffix);
195
196     }
197
198 Done:
199
200     if (library)
201     {
202         khrIcdOsLibraryUnload(library);
203     }
204     if (platforms)
205     {
206         free(platforms);
207     }
208 }
209
210 void khrIcdContextPropertiesGetPlatform(const cl_context_properties *properties, cl_platform_id *outPlatform)
211 {
212     if (properties == NULL && khrIcdVendors != NULL)
213     {
214         *outPlatform = khrIcdVendors[0].platform;
215         return;
216     }
217
218     const cl_context_properties *property = (cl_context_properties *)NULL;
219     *outPlatform = NULL;
220     for (property = properties; property && property[0]; property += 2)
221     {
222         if ((cl_context_properties)CL_CONTEXT_PLATFORM == property[0])
223         {
224             *outPlatform = (cl_platform_id)property[1];
225         }    
226     }
227 }
228