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