• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2021 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // CLPlatform.cpp: Implements the cl::Platform class.
7 
8 #include "libANGLE/CLPlatform.h"
9 
10 #include "libANGLE/CLContext.h"
11 #include "libANGLE/CLDevice.h"
12 
13 #include <cstring>
14 
15 namespace cl
16 {
17 
18 namespace
19 {
20 
IsDeviceTypeMatch(DeviceType select,DeviceType type)21 bool IsDeviceTypeMatch(DeviceType select, DeviceType type)
22 {
23     // The type 'DeviceType' is a bitfield, so it matches if any selected bit is set.
24     // A custom device is an exception, which only matches if it was explicitely selected, see:
25     // https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#clGetDeviceIDs
26     return type == CL_DEVICE_TYPE_CUSTOM ? select == CL_DEVICE_TYPE_CUSTOM : type.isSet(select);
27 }
28 
ParseContextProperties(const cl_context_properties * properties,Platform * & platform,bool & userSync)29 Context::PropArray ParseContextProperties(const cl_context_properties *properties,
30                                           Platform *&platform,
31                                           bool &userSync)
32 {
33     Context::PropArray propArray;
34     if (properties != nullptr)
35     {
36         const cl_context_properties *propIt = properties;
37         while (*propIt != 0)
38         {
39             switch (*propIt++)
40             {
41                 case CL_CONTEXT_PLATFORM:
42                     platform = &reinterpret_cast<cl_platform_id>(*propIt++)->cast<Platform>();
43                     break;
44                 case CL_CONTEXT_INTEROP_USER_SYNC:
45                     userSync = *propIt++ != CL_FALSE;
46                     break;
47             }
48         }
49         // Include the trailing zero
50         ++propIt;
51         propArray.reserve(propIt - properties);
52         propArray.insert(propArray.cend(), properties, propIt);
53     }
54     if (platform == nullptr)
55     {
56         platform = Platform::GetDefault();
57     }
58     return propArray;
59 }
60 
61 }  // namespace
62 
Initialize(const cl_icd_dispatch & dispatch,rx::CLPlatformImpl::CreateFuncs && createFuncs)63 void Platform::Initialize(const cl_icd_dispatch &dispatch,
64                           rx::CLPlatformImpl::CreateFuncs &&createFuncs)
65 {
66     PlatformPtrs &platforms = GetPointers();
67     ASSERT(_cl_platform_id::sDispatch == nullptr && platforms.empty());
68     if (_cl_platform_id::sDispatch != nullptr || !platforms.empty())
69     {
70         ERR() << "Already initialized";
71         return;
72     }
73     Dispatch::sDispatch = &dispatch;
74 
75     platforms.reserve(createFuncs.size());
76     while (!createFuncs.empty())
77     {
78         platforms.emplace_back(new Platform(createFuncs.front()));
79         // Release initialization reference, lifetime controlled by RefPointer.
80         platforms.back()->release();
81         if (!platforms.back()->mInfo.isValid() || platforms.back()->mDevices.empty())
82         {
83             platforms.pop_back();
84         }
85         createFuncs.pop_front();
86     }
87 }
88 
GetPlatformIDs(cl_uint numEntries,cl_platform_id * platforms,cl_uint * numPlatforms)89 cl_int Platform::GetPlatformIDs(cl_uint numEntries,
90                                 cl_platform_id *platforms,
91                                 cl_uint *numPlatforms)
92 {
93     const PlatformPtrs &availPlatforms = GetPlatforms();
94     if (numPlatforms != nullptr)
95     {
96         *numPlatforms = static_cast<cl_uint>(availPlatforms.size());
97     }
98     if (platforms != nullptr)
99     {
100         cl_uint entry   = 0u;
101         auto platformIt = availPlatforms.cbegin();
102         while (entry < numEntries && platformIt != availPlatforms.cend())
103         {
104             platforms[entry++] = (*platformIt++).get();
105         }
106     }
107     return CL_SUCCESS;
108 }
109 
getInfo(PlatformInfo name,size_t valueSize,void * value,size_t * valueSizeRet) const110 cl_int Platform::getInfo(PlatformInfo name,
111                          size_t valueSize,
112                          void *value,
113                          size_t *valueSizeRet) const
114 {
115     const void *copyValue = nullptr;
116     size_t copySize       = 0u;
117 
118     switch (name)
119     {
120         case PlatformInfo::Profile:
121             copyValue = mInfo.profile.c_str();
122             copySize  = mInfo.profile.length() + 1u;
123             break;
124         case PlatformInfo::Version:
125             copyValue = mInfo.versionStr.c_str();
126             copySize  = mInfo.versionStr.length() + 1u;
127             break;
128         case PlatformInfo::NumericVersion:
129             copyValue = &mInfo.version;
130             copySize  = sizeof(mInfo.version);
131             break;
132         case PlatformInfo::Name:
133             copyValue = mInfo.name.c_str();
134             copySize  = mInfo.name.length() + 1u;
135             break;
136         case PlatformInfo::Vendor:
137             copyValue = kVendor;
138             copySize  = sizeof(kVendor);
139             break;
140         case PlatformInfo::Extensions:
141             copyValue = mInfo.extensions.c_str();
142             copySize  = mInfo.extensions.length() + 1u;
143             break;
144         case PlatformInfo::ExtensionsWithVersion:
145             copyValue = mInfo.extensionsWithVersion.data();
146             copySize  = mInfo.extensionsWithVersion.size() *
147                        sizeof(decltype(mInfo.extensionsWithVersion)::value_type);
148             break;
149         case PlatformInfo::HostTimerResolution:
150             copyValue = &mInfo.hostTimerRes;
151             copySize  = sizeof(mInfo.hostTimerRes);
152             break;
153         case PlatformInfo::IcdSuffix:
154             copyValue = kIcdSuffix;
155             copySize  = sizeof(kIcdSuffix);
156             break;
157         default:
158             ASSERT(false);
159             return CL_INVALID_VALUE;
160     }
161 
162     if (value != nullptr)
163     {
164         // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
165         // as specified in the OpenCL Platform Queries table, and param_value is not a NULL value.
166         if (valueSize < copySize)
167         {
168             return CL_INVALID_VALUE;
169         }
170         if (copyValue != nullptr)
171         {
172             std::memcpy(value, copyValue, copySize);
173         }
174     }
175     if (valueSizeRet != nullptr)
176     {
177         *valueSizeRet = copySize;
178     }
179     return CL_SUCCESS;
180 }
181 
getDeviceIDs(DeviceType deviceType,cl_uint numEntries,cl_device_id * devices,cl_uint * numDevices) const182 cl_int Platform::getDeviceIDs(DeviceType deviceType,
183                               cl_uint numEntries,
184                               cl_device_id *devices,
185                               cl_uint *numDevices) const
186 {
187     cl_uint found = 0u;
188     for (const DevicePtr &device : mDevices)
189     {
190         if (IsDeviceTypeMatch(deviceType, device->getInfo().type))
191         {
192             if (devices != nullptr && found < numEntries)
193             {
194                 devices[found] = device.get();
195             }
196             ++found;
197         }
198     }
199     if (numDevices != nullptr)
200     {
201         *numDevices = found;
202     }
203 
204     // CL_DEVICE_NOT_FOUND if no OpenCL devices that matched device_type were found.
205     if (found == 0u)
206     {
207         return CL_DEVICE_NOT_FOUND;
208     }
209 
210     return CL_SUCCESS;
211 }
212 
CreateContext(const cl_context_properties * properties,cl_uint numDevices,const cl_device_id * devices,ContextErrorCB notify,void * userData,cl_int & errorCode)213 cl_context Platform::CreateContext(const cl_context_properties *properties,
214                                    cl_uint numDevices,
215                                    const cl_device_id *devices,
216                                    ContextErrorCB notify,
217                                    void *userData,
218                                    cl_int &errorCode)
219 {
220     Platform *platform           = nullptr;
221     bool userSync                = false;
222     Context::PropArray propArray = ParseContextProperties(properties, platform, userSync);
223     ASSERT(platform != nullptr);
224     DevicePtrs devs;
225     devs.reserve(numDevices);
226     while (numDevices-- != 0u)
227     {
228         devs.emplace_back(&(*devices++)->cast<Device>());
229     }
230     return Object::Create<Context>(errorCode, *platform, std::move(propArray), std::move(devs),
231                                    notify, userData, userSync);
232 }
233 
CreateContextFromType(const cl_context_properties * properties,DeviceType deviceType,ContextErrorCB notify,void * userData,cl_int & errorCode)234 cl_context Platform::CreateContextFromType(const cl_context_properties *properties,
235                                            DeviceType deviceType,
236                                            ContextErrorCB notify,
237                                            void *userData,
238                                            cl_int &errorCode)
239 {
240     Platform *platform           = nullptr;
241     bool userSync                = false;
242     Context::PropArray propArray = ParseContextProperties(properties, platform, userSync);
243     ASSERT(platform != nullptr);
244     return Object::Create<Context>(errorCode, *platform, std::move(propArray), deviceType, notify,
245                                    userData, userSync);
246 }
247 
unloadCompiler()248 cl_int Platform::unloadCompiler()
249 {
250     return mImpl->unloadCompiler();
251 }
252 
253 Platform::~Platform() = default;
254 
Platform(const rx::CLPlatformImpl::CreateFunc & createFunc)255 Platform::Platform(const rx::CLPlatformImpl::CreateFunc &createFunc)
256     : mImpl(createFunc(*this)),
257       mInfo(mImpl->createInfo()),
258       mDevices(createDevices(mImpl->createDevices()))
259 {}
260 
createDevices(rx::CLDeviceImpl::CreateDatas && createDatas)261 DevicePtrs Platform::createDevices(rx::CLDeviceImpl::CreateDatas &&createDatas)
262 {
263     DevicePtrs devices;
264     devices.reserve(createDatas.size());
265     while (!createDatas.empty())
266     {
267         devices.emplace_back(
268             new Device(*this, nullptr, createDatas.front().first, createDatas.front().second));
269         // Release initialization reference, lifetime controlled by RefPointer.
270         devices.back()->release();
271         if (!devices.back()->mInfo.isValid())
272         {
273             devices.pop_back();
274         }
275         createDatas.pop_front();
276     }
277     return devices;
278 }
279 
280 constexpr char Platform::kVendor[];
281 constexpr char Platform::kIcdSuffix[];
282 
283 }  // namespace cl
284