• 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 // CLDeviceCL.cpp: Implements the class methods for CLDeviceCL.
7 
8 #include "libANGLE/renderer/cl/CLDeviceCL.h"
9 
10 #include "libANGLE/renderer/cl/cl_util.h"
11 
12 #include "libANGLE/CLDevice.h"
13 #include "libANGLE/cl_utils.h"
14 
15 namespace rx
16 {
17 
18 namespace
19 {
20 
21 // Object information is queried in OpenCL by providing allocated memory into which the requested
22 // data is copied. If the size of the data is unknown, it can be queried first with an additional
23 // call to the same function, but without requesting the data itself. This function provides the
24 // functionality to request and validate the size and the data.
25 template <typename T>
GetDeviceInfo(cl_device_id device,cl::DeviceInfo name,std::vector<T> & vector)26 bool GetDeviceInfo(cl_device_id device, cl::DeviceInfo name, std::vector<T> &vector)
27 {
28     size_t size = 0u;
29     if (device->getDispatch().clGetDeviceInfo(device, cl::ToCLenum(name), 0u, nullptr, &size) ==
30             CL_SUCCESS &&
31         (size % sizeof(T)) == 0u)  // size has to be a multiple of the data type
32     {
33         vector.resize(size / sizeof(T));
34         if (device->getDispatch().clGetDeviceInfo(device, cl::ToCLenum(name), size, vector.data(),
35                                                   nullptr) == CL_SUCCESS)
36         {
37             return true;
38         }
39     }
40     ERR() << "Failed to query CL device info for " << name;
41     return false;
42 }
43 
44 // This queries the OpenCL device info for value types with known size
45 template <typename T>
GetDeviceInfo(cl_device_id device,cl::DeviceInfo name,T & value)46 bool GetDeviceInfo(cl_device_id device, cl::DeviceInfo name, T &value)
47 {
48     if (device->getDispatch().clGetDeviceInfo(device, cl::ToCLenum(name), sizeof(T), &value,
49                                               nullptr) != CL_SUCCESS)
50     {
51         ERR() << "Failed to query CL device info for " << name;
52         return false;
53     }
54     return true;
55 }
56 
57 }  // namespace
58 
~CLDeviceCL()59 CLDeviceCL::~CLDeviceCL()
60 {
61     if (!mDevice.isRoot() && mNative->getDispatch().clReleaseDevice(mNative) != CL_SUCCESS)
62     {
63         ERR() << "Error while releasing CL device";
64     }
65 }
66 
createInfo(cl::DeviceType type) const67 CLDeviceImpl::Info CLDeviceCL::createInfo(cl::DeviceType type) const
68 {
69     Info info(type);
70     std::vector<char> valString;
71 
72     if (!GetDeviceInfo(mNative, cl::DeviceInfo::MaxWorkItemSizes, info.maxWorkItemSizes))
73     {
74         return Info{};
75     }
76     // From the OpenCL specification for info name CL_DEVICE_MAX_WORK_ITEM_SIZES:
77     // "The minimum value is (1, 1, 1) for devices that are not of type CL_DEVICE_TYPE_CUSTOM."
78     // https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#clGetDeviceInfo
79     // Custom devices are currently not supported by this back end.
80     if (info.maxWorkItemSizes.size() < 3u || info.maxWorkItemSizes[0] == 0u ||
81         info.maxWorkItemSizes[1] == 0u || info.maxWorkItemSizes[2] == 0u)
82     {
83         ERR() << "Invalid CL_DEVICE_MAX_WORK_ITEM_SIZES";
84         return Info{};
85     }
86 
87     if (!GetDeviceInfo(mNative, cl::DeviceInfo::MaxMemAllocSize, info.maxMemAllocSize) ||
88         !GetDeviceInfo(mNative, cl::DeviceInfo::ImageSupport, info.imageSupport) ||
89         !GetDeviceInfo(mNative, cl::DeviceInfo::Image2D_MaxWidth, info.image2D_MaxWidth) ||
90         !GetDeviceInfo(mNative, cl::DeviceInfo::Image2D_MaxHeight, info.image2D_MaxHeight) ||
91         !GetDeviceInfo(mNative, cl::DeviceInfo::Image3D_MaxWidth, info.image3D_MaxWidth) ||
92         !GetDeviceInfo(mNative, cl::DeviceInfo::Image3D_MaxHeight, info.image3D_MaxHeight) ||
93         !GetDeviceInfo(mNative, cl::DeviceInfo::Image3D_MaxDepth, info.image3D_MaxDepth) ||
94         !GetDeviceInfo(mNative, cl::DeviceInfo::MemBaseAddrAlign, info.memBaseAddrAlign) ||
95         !GetDeviceInfo(mNative, cl::DeviceInfo::ExecutionCapabilities, info.execCapabilities))
96     {
97         return Info{};
98     }
99 
100     if (!GetDeviceInfo(mNative, cl::DeviceInfo::Version, valString))
101     {
102         return Info{};
103     }
104     info.versionStr.assign(valString.data());
105 
106     if (!GetDeviceInfo(mNative, cl::DeviceInfo::Extensions, valString))
107     {
108         return Info{};
109     }
110     std::string extensionStr(valString.data());
111 
112     // TODO(jplate) Remove workaround after bug is fixed http://anglebug.com/6053
113     if (info.versionStr.compare(0u, 15u, "OpenCL 3.0 CUDA", 15u) == 0)
114     {
115         extensionStr.append(" cl_khr_depth_images cl_khr_image2d_from_buffer");
116     }
117 
118     // Limit version number to supported version
119     if (info.versionStr[7] != '1')
120     {
121         info.versionStr[7] = '1';
122         info.versionStr[9] = '2';
123     }
124 
125     info.version = ExtractCLVersion(info.versionStr);
126     if (info.version == 0u)
127     {
128         return Info{};
129     }
130 
131     RemoveUnsupportedCLExtensions(extensionStr);
132     info.initializeExtensions(std::move(extensionStr));
133 
134     if (info.version >= CL_MAKE_VERSION(1, 2, 0))
135     {
136         if (!GetDeviceInfo(mNative, cl::DeviceInfo::ImageMaxBufferSize, info.imageMaxBufferSize) ||
137             !GetDeviceInfo(mNative, cl::DeviceInfo::ImageMaxArraySize, info.imageMaxArraySize) ||
138             !GetDeviceInfo(mNative, cl::DeviceInfo::BuiltInKernels, valString))
139         {
140             return Info{};
141         }
142         info.builtInKernels.assign(valString.data());
143         if (!GetDeviceInfo(mNative, cl::DeviceInfo::PartitionProperties,
144                            info.partitionProperties) ||
145             !GetDeviceInfo(mNative, cl::DeviceInfo::PartitionType, info.partitionType))
146         {
147             return Info{};
148         }
149     }
150 
151     if (info.version >= CL_MAKE_VERSION(2, 0, 0) &&
152         (!GetDeviceInfo(mNative, cl::DeviceInfo::ImagePitchAlignment, info.imagePitchAlignment) ||
153          !GetDeviceInfo(mNative, cl::DeviceInfo::ImageBaseAddressAlignment,
154                         info.imageBaseAddressAlignment) ||
155          !GetDeviceInfo(mNative, cl::DeviceInfo::QueueOnDeviceMaxSize, info.queueOnDeviceMaxSize)))
156     {
157         return Info{};
158     }
159 
160     if (info.version >= CL_MAKE_VERSION(2, 1, 0))
161     {
162         if (!GetDeviceInfo(mNative, cl::DeviceInfo::IL_Version, valString))
163         {
164             return Info{};
165         }
166         info.IL_Version.assign(valString.data());
167     }
168 
169     if (info.version >= CL_MAKE_VERSION(3, 0, 0) &&
170         (!GetDeviceInfo(mNative, cl::DeviceInfo::ILsWithVersion, info.ILsWithVersion) ||
171          !GetDeviceInfo(mNative, cl::DeviceInfo::BuiltInKernelsWithVersion,
172                         info.builtInKernelsWithVersion) ||
173          !GetDeviceInfo(mNative, cl::DeviceInfo::OpenCL_C_AllVersions, info.OpenCL_C_AllVersions) ||
174          !GetDeviceInfo(mNative, cl::DeviceInfo::OpenCL_C_Features, info.OpenCL_C_Features) ||
175          !GetDeviceInfo(mNative, cl::DeviceInfo::ExtensionsWithVersion,
176                         info.extensionsWithVersion)))
177     {
178         return Info{};
179     }
180     RemoveUnsupportedCLExtensions(info.extensionsWithVersion);
181 
182     return info;
183 }
184 
getInfoUInt(cl::DeviceInfo name,cl_uint * value) const185 angle::Result CLDeviceCL::getInfoUInt(cl::DeviceInfo name, cl_uint *value) const
186 {
187     ANGLE_CL_TRY(mNative->getDispatch().clGetDeviceInfo(mNative, cl::ToCLenum(name), sizeof(*value),
188                                                         value, nullptr));
189     return angle::Result::Continue;
190 }
191 
getInfoULong(cl::DeviceInfo name,cl_ulong * value) const192 angle::Result CLDeviceCL::getInfoULong(cl::DeviceInfo name, cl_ulong *value) const
193 {
194     ANGLE_CL_TRY(mNative->getDispatch().clGetDeviceInfo(mNative, cl::ToCLenum(name), sizeof(*value),
195                                                         value, nullptr));
196     return angle::Result::Continue;
197 }
198 
getInfoSizeT(cl::DeviceInfo name,size_t * value) const199 angle::Result CLDeviceCL::getInfoSizeT(cl::DeviceInfo name, size_t *value) const
200 {
201     ANGLE_CL_TRY(mNative->getDispatch().clGetDeviceInfo(mNative, cl::ToCLenum(name), sizeof(*value),
202                                                         value, nullptr));
203     return angle::Result::Continue;
204 }
205 
getInfoStringLength(cl::DeviceInfo name,size_t * value) const206 angle::Result CLDeviceCL::getInfoStringLength(cl::DeviceInfo name, size_t *value) const
207 {
208     ANGLE_CL_TRY(
209         mNative->getDispatch().clGetDeviceInfo(mNative, cl::ToCLenum(name), 0u, nullptr, value));
210     return angle::Result::Continue;
211 }
212 
getInfoString(cl::DeviceInfo name,size_t size,char * value) const213 angle::Result CLDeviceCL::getInfoString(cl::DeviceInfo name, size_t size, char *value) const
214 {
215     ANGLE_CL_TRY(
216         mNative->getDispatch().clGetDeviceInfo(mNative, cl::ToCLenum(name), size, value, nullptr));
217     return angle::Result::Continue;
218 }
219 
createSubDevices(const cl_device_partition_property * properties,cl_uint numDevices,CreateFuncs & createFuncs,cl_uint * numDevicesRet)220 angle::Result CLDeviceCL::createSubDevices(const cl_device_partition_property *properties,
221                                            cl_uint numDevices,
222                                            CreateFuncs &createFuncs,
223                                            cl_uint *numDevicesRet)
224 {
225     if (numDevices == 0u)
226     {
227         ANGLE_CL_TRY(mNative->getDispatch().clCreateSubDevices(mNative, properties, 0u, nullptr,
228                                                                numDevicesRet));
229         return angle::Result::Continue;
230     }
231 
232     std::vector<cl_device_id> nativeSubDevices(numDevices, nullptr);
233     ANGLE_CL_TRY(mNative->getDispatch().clCreateSubDevices(mNative, properties, numDevices,
234                                                            nativeSubDevices.data(), nullptr));
235 
236     for (cl_device_id nativeSubDevice : nativeSubDevices)
237     {
238         createFuncs.emplace_back([nativeSubDevice](const cl::Device &device) {
239             return Ptr(new CLDeviceCL(device, nativeSubDevice));
240         });
241     }
242     return angle::Result::Continue;
243 }
244 
CLDeviceCL(const cl::Device & device,cl_device_id native)245 CLDeviceCL::CLDeviceCL(const cl::Device &device, cl_device_id native)
246     : CLDeviceImpl(device), mNative(native)
247 {}
248 
249 }  // namespace rx
250