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
31using namespace clover;
32
33namespace {
34   platform _clover_platform;
35}
36
37CLOVER_API cl_int
38clGetPlatformIDs(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
52platform &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
60cl_int
61clover::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
115void *
116clover::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
125namespace {
126
127cl_int
128enqueueSVMFreeARM(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
144cl_int
145enqueueSVMMapARM(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
159cl_int
160enqueueSVMMemcpyARM(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
174cl_int
175enqueueSVMMemFillARM(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
189cl_int
190enqueueSVMUnmapARM(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
200const std::unordered_map<std::string, void *>
201ext_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
222void *
223clover::GetExtensionFunctionAddress(const char *p_name) try {
224   return ext_funcs.at(p_name);
225} catch (...) {
226   return nullptr;
227}
228
229cl_int
230clover::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
235CLOVER_ICD_API cl_int
236clGetPlatformInfo(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
241CLOVER_ICD_API void *
242clGetExtensionFunctionAddress(const char *p_name) {
243   return GetExtensionFunctionAddress(p_name);
244}
245
246CLOVER_ICD_API void *
247clGetExtensionFunctionAddressForPlatform(cl_platform_id d_platform,
248                                         const char *p_name) {
249   return GetExtensionFunctionAddressForPlatform(d_platform, p_name);
250}
251
252CLOVER_ICD_API cl_int
253clIcdGetPlatformIDsKHR(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