1 //
2 // Copyright 2012 Francisco Jerez
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
21 //
22 
23 #include <unordered_map>
24 
25 #include "api/dispatch.hpp"
26 #include "api/util.hpp"
27 #include "core/platform.hpp"
28 #include "git_sha1.h"
29 #include "util/u_debug.h"
30 
31 using namespace clover;
32 
33 namespace {
34    platform _clover_platform;
35 }
36 
37 CLOVER_API cl_int
clGetPlatformIDs(cl_uint num_entries,cl_platform_id * rd_platforms,cl_uint * rnum_platforms)38 clGetPlatformIDs(cl_uint num_entries, cl_platform_id *rd_platforms,
39                  cl_uint *rnum_platforms) {
40    if ((!num_entries && rd_platforms) ||
41        (!rnum_platforms && !rd_platforms))
42       return CL_INVALID_VALUE;
43 
44    if (rnum_platforms)
45       *rnum_platforms = 1;
46    if (rd_platforms)
47       *rd_platforms = desc(_clover_platform);
48 
49    return CL_SUCCESS;
50 }
51 
find_platform(cl_platform_id d_platform)52 platform &clover::find_platform(cl_platform_id d_platform)
53 {
54    /* this error is only added in CL2.0 */
55    if (d_platform != desc(_clover_platform))
56       throw error(CL_INVALID_PLATFORM);
57    return obj(d_platform);
58 }
59 
60 cl_int
GetPlatformInfo(cl_platform_id d_platform,cl_platform_info param,size_t size,void * r_buf,size_t * r_size)61 clover::GetPlatformInfo(cl_platform_id d_platform, cl_platform_info param,
62                         size_t size, void *r_buf, size_t *r_size) try {
63    property_buffer buf { r_buf, size, r_size };
64 
65    auto &platform = find_platform(d_platform);
66 
67    switch (param) {
68    case CL_PLATFORM_PROFILE:
69       buf.as_string() = "FULL_PROFILE";
70       break;
71 
72    case CL_PLATFORM_VERSION: {
73       buf.as_string() = "OpenCL " + platform.platform_version_as_string() + " Mesa " PACKAGE_VERSION MESA_GIT_SHA1;
74       break;
75    }
76    case CL_PLATFORM_NAME:
77       buf.as_string() = "Clover";
78       break;
79 
80    case CL_PLATFORM_VENDOR:
81       buf.as_string() = "Mesa";
82       break;
83 
84    case CL_PLATFORM_EXTENSIONS:
85       buf.as_string() = platform.supported_extensions_as_string();
86       break;
87 
88    case CL_PLATFORM_ICD_SUFFIX_KHR:
89       buf.as_string() = "MESA";
90       break;
91 
92    case CL_PLATFORM_NUMERIC_VERSION: {
93       buf.as_scalar<cl_version>() = platform.platform_version();
94       break;
95    }
96 
97    case CL_PLATFORM_EXTENSIONS_WITH_VERSION:
98       buf.as_vector<cl_name_version>() = platform.supported_extensions();
99       break;
100 
101    case CL_PLATFORM_HOST_TIMER_RESOLUTION:
102       buf.as_scalar<cl_ulong>() = 0;
103       break;
104 
105    default:
106       throw error(CL_INVALID_VALUE);
107    }
108 
109    return CL_SUCCESS;
110 
111 } catch (error &e) {
112    return e.get();
113 }
114 
115 void *
GetExtensionFunctionAddressForPlatform(cl_platform_id d_platform,const char * p_name)116 clover::GetExtensionFunctionAddressForPlatform(cl_platform_id d_platform,
117                                                const char *p_name) try {
118    obj(d_platform);
119    return GetExtensionFunctionAddress(p_name);
120 
121 } catch (error &) {
122    return NULL;
123 }
124 
125 namespace {
126 
127 cl_int
enqueueSVMFreeARM(cl_command_queue command_queue,cl_uint num_svm_pointers,void * svm_pointers[],void (CL_CALLBACK * pfn_free_func)(cl_command_queue queue,cl_uint num_svm_pointers,void * svm_pointers[],void * user_data),void * user_data,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event)128 enqueueSVMFreeARM(cl_command_queue command_queue,
129                   cl_uint num_svm_pointers,
130                   void *svm_pointers[],
131                   void (CL_CALLBACK *pfn_free_func) (
132                     cl_command_queue queue, cl_uint num_svm_pointers,
133                     void *svm_pointers[], void *user_data),
134                   void *user_data,
135                   cl_uint num_events_in_wait_list,
136                   const cl_event *event_wait_list,
137                   cl_event *event) {
138 
139    return EnqueueSVMFree(command_queue, num_svm_pointers, svm_pointers,
140                          pfn_free_func, user_data, num_events_in_wait_list,
141                          event_wait_list, event, CL_COMMAND_SVM_FREE_ARM);
142 }
143 
144 cl_int
enqueueSVMMapARM(cl_command_queue command_queue,cl_bool blocking_map,cl_map_flags map_flags,void * svm_ptr,size_t size,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event)145 enqueueSVMMapARM(cl_command_queue command_queue,
146                  cl_bool blocking_map,
147                  cl_map_flags map_flags,
148                  void *svm_ptr,
149                  size_t size,
150                  cl_uint num_events_in_wait_list,
151                  const cl_event *event_wait_list,
152                  cl_event *event) {
153 
154    return EnqueueSVMMap(command_queue, blocking_map, map_flags, svm_ptr, size,
155                         num_events_in_wait_list, event_wait_list, event,
156                         CL_COMMAND_SVM_MAP_ARM);
157 }
158 
159 cl_int
enqueueSVMMemcpyARM(cl_command_queue command_queue,cl_bool blocking_copy,void * dst_ptr,const void * src_ptr,size_t size,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event)160 enqueueSVMMemcpyARM(cl_command_queue command_queue,
161                     cl_bool blocking_copy,
162                     void *dst_ptr,
163                     const void *src_ptr,
164                     size_t size,
165                     cl_uint num_events_in_wait_list,
166                     const cl_event *event_wait_list,
167                     cl_event *event) {
168 
169    return EnqueueSVMMemcpy(command_queue, blocking_copy, dst_ptr, src_ptr,
170                            size, num_events_in_wait_list, event_wait_list,
171                            event, CL_COMMAND_SVM_MEMCPY_ARM);
172 }
173 
174 cl_int
enqueueSVMMemFillARM(cl_command_queue command_queue,void * svm_ptr,const void * pattern,size_t pattern_size,size_t size,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event)175 enqueueSVMMemFillARM(cl_command_queue command_queue,
176                      void *svm_ptr,
177                      const void *pattern,
178                      size_t pattern_size,
179                      size_t size,
180                      cl_uint num_events_in_wait_list,
181                      const cl_event *event_wait_list,
182                      cl_event *event) {
183 
184    return EnqueueSVMMemFill(command_queue, svm_ptr, pattern, pattern_size,
185                             size, num_events_in_wait_list, event_wait_list,
186                             event, CL_COMMAND_SVM_MEMFILL_ARM);
187 }
188 
189 cl_int
enqueueSVMUnmapARM(cl_command_queue command_queue,void * svm_ptr,cl_uint num_events_in_wait_list,const cl_event * event_wait_list,cl_event * event)190 enqueueSVMUnmapARM(cl_command_queue command_queue,
191                    void *svm_ptr,
192                    cl_uint num_events_in_wait_list,
193                    const cl_event *event_wait_list,
194                    cl_event *event) {
195 
196    return EnqueueSVMUnmap(command_queue, svm_ptr, num_events_in_wait_list,
197                           event_wait_list, event, CL_COMMAND_SVM_UNMAP_ARM);
198 }
199 
200 const std::unordered_map<std::string, void *>
201 ext_funcs = {
202    // cl_arm_shared_virtual_memory
203    { "clEnqueueSVMFreeARM", reinterpret_cast<void *>(enqueueSVMFreeARM) },
204    { "clEnqueueSVMMapARM", reinterpret_cast<void *>(enqueueSVMMapARM) },
205    { "clEnqueueSVMMemcpyARM", reinterpret_cast<void *>(enqueueSVMMemcpyARM) },
206    { "clEnqueueSVMMemFillARM", reinterpret_cast<void *>(enqueueSVMMemFillARM) },
207    { "clEnqueueSVMUnmapARM", reinterpret_cast<void *>(enqueueSVMUnmapARM) },
208    { "clSetKernelArgSVMPointerARM", reinterpret_cast<void *>(clSetKernelArgSVMPointer) },
209    { "clSetKernelExecInfoARM", reinterpret_cast<void *>(clSetKernelExecInfo) },
210    { "clSVMAllocARM", reinterpret_cast<void *>(clSVMAlloc) },
211    { "clSVMFreeARM", reinterpret_cast<void *>(clSVMFree) },
212 
213    // cl_khr_icd
214    { "clIcdGetPlatformIDsKHR", reinterpret_cast<void *>(IcdGetPlatformIDsKHR) },
215 
216    // cl_khr_il_program
217    { "clCreateProgramWithILKHR", reinterpret_cast<void *>(CreateProgramWithILKHR) },
218 };
219 
220 } // anonymous namespace
221 
222 void *
GetExtensionFunctionAddress(const char * p_name)223 clover::GetExtensionFunctionAddress(const char *p_name) try {
224    return ext_funcs.at(p_name);
225 } catch (...) {
226    return nullptr;
227 }
228 
229 cl_int
IcdGetPlatformIDsKHR(cl_uint num_entries,cl_platform_id * rd_platforms,cl_uint * rnum_platforms)230 clover::IcdGetPlatformIDsKHR(cl_uint num_entries, cl_platform_id *rd_platforms,
231                              cl_uint *rnum_platforms) {
232    return clGetPlatformIDs(num_entries, rd_platforms, rnum_platforms);
233 }
234 
235 CLOVER_ICD_API cl_int
clGetPlatformInfo(cl_platform_id d_platform,cl_platform_info param,size_t size,void * r_buf,size_t * r_size)236 clGetPlatformInfo(cl_platform_id d_platform, cl_platform_info param,
237                   size_t size, void *r_buf, size_t *r_size) {
238    return GetPlatformInfo(d_platform, param, size, r_buf, r_size);
239 }
240 
241 CLOVER_ICD_API void *
clGetExtensionFunctionAddress(const char * p_name)242 clGetExtensionFunctionAddress(const char *p_name) {
243    return GetExtensionFunctionAddress(p_name);
244 }
245 
246 CLOVER_ICD_API void *
clGetExtensionFunctionAddressForPlatform(cl_platform_id d_platform,const char * p_name)247 clGetExtensionFunctionAddressForPlatform(cl_platform_id d_platform,
248                                          const char *p_name) {
249    return GetExtensionFunctionAddressForPlatform(d_platform, p_name);
250 }
251 
252 CLOVER_ICD_API cl_int
clIcdGetPlatformIDsKHR(cl_uint num_entries,cl_platform_id * rd_platforms,cl_uint * rnum_platforms)253 clIcdGetPlatformIDsKHR(cl_uint num_entries, cl_platform_id *rd_platforms,
254                        cl_uint *rnum_platforms) {
255    return IcdGetPlatformIDsKHR(num_entries, rd_platforms, rnum_platforms);
256 }
257