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 // CLDevice.cpp: Implements the cl::Device class.
7
8 #include "libANGLE/CLDevice.h"
9
10 #include "libANGLE/CLPlatform.h"
11
12 #include "common/string_utils.h"
13
14 #include <cstring>
15
16 namespace cl
17 {
18
getInfo(DeviceInfo name,size_t valueSize,void * value,size_t * valueSizeRet) const19 cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const
20 {
21 static_assert(std::is_same<cl_uint, cl_bool>::value &&
22 std::is_same<cl_uint, cl_device_mem_cache_type>::value &&
23 std::is_same<cl_uint, cl_device_local_mem_type>::value &&
24 std::is_same<cl_uint, cl_version>::value &&
25 std::is_same<cl_ulong, cl_device_type>::value &&
26 std::is_same<cl_ulong, cl_device_fp_config>::value &&
27 std::is_same<cl_ulong, cl_device_exec_capabilities>::value &&
28 std::is_same<cl_ulong, cl_command_queue_properties>::value &&
29 std::is_same<cl_ulong, cl_device_affinity_domain>::value &&
30 std::is_same<cl_ulong, cl_device_svm_capabilities>::value &&
31 std::is_same<cl_ulong, cl_device_atomic_capabilities>::value &&
32 std::is_same<cl_ulong, cl_device_device_enqueue_capabilities>::value,
33 "OpenCL type mismatch");
34
35 cl_uint valUInt = 0u;
36 cl_ulong valULong = 0u;
37 size_t valSizeT = 0u;
38 void *valPointer = nullptr;
39 std::vector<char> valString;
40
41 const void *copyValue = nullptr;
42 size_t copySize = 0u;
43 cl_int result = CL_SUCCESS;
44
45 // The info names are sorted within their type group in the order they appear in the OpenCL
46 // specification, so it is easier to compare them side-by-side when looking for changes.
47 // https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#clGetDeviceInfo
48 switch (name)
49 {
50 // Handle all cl_uint and aliased types
51 case DeviceInfo::VendorID:
52 case DeviceInfo::MaxComputeUnits:
53 case DeviceInfo::PreferredVectorWidthChar:
54 case DeviceInfo::PreferredVectorWidthShort:
55 case DeviceInfo::PreferredVectorWidthInt:
56 case DeviceInfo::PreferredVectorWidthLong:
57 case DeviceInfo::PreferredVectorWidthFloat:
58 case DeviceInfo::PreferredVectorWidthDouble:
59 case DeviceInfo::PreferredVectorWidthHalf:
60 case DeviceInfo::NativeVectorWidthChar:
61 case DeviceInfo::NativeVectorWidthShort:
62 case DeviceInfo::NativeVectorWidthInt:
63 case DeviceInfo::NativeVectorWidthLong:
64 case DeviceInfo::NativeVectorWidthFloat:
65 case DeviceInfo::NativeVectorWidthDouble:
66 case DeviceInfo::NativeVectorWidthHalf:
67 case DeviceInfo::MaxClockFrequency:
68 case DeviceInfo::AddressBits:
69 case DeviceInfo::MaxReadImageArgs:
70 case DeviceInfo::MaxWriteImageArgs:
71 case DeviceInfo::MaxReadWriteImageArgs:
72 case DeviceInfo::MaxSamplers:
73 case DeviceInfo::MaxPipeArgs:
74 case DeviceInfo::PipeMaxActiveReservations:
75 case DeviceInfo::PipeMaxPacketSize:
76 case DeviceInfo::MinDataTypeAlignSize:
77 case DeviceInfo::GlobalMemCacheType:
78 case DeviceInfo::GlobalMemCachelineSize:
79 case DeviceInfo::MaxConstantArgs:
80 case DeviceInfo::LocalMemType:
81 case DeviceInfo::ErrorCorrectionSupport:
82 case DeviceInfo::HostUnifiedMemory:
83 case DeviceInfo::EndianLittle:
84 case DeviceInfo::Available:
85 case DeviceInfo::CompilerAvailable:
86 case DeviceInfo::LinkerAvailable:
87 case DeviceInfo::QueueOnDevicePreferredSize:
88 case DeviceInfo::MaxOnDeviceQueues:
89 case DeviceInfo::MaxOnDeviceEvents:
90 case DeviceInfo::PreferredInteropUserSync:
91 case DeviceInfo::PartitionMaxSubDevices:
92 case DeviceInfo::PreferredPlatformAtomicAlignment:
93 case DeviceInfo::PreferredGlobalAtomicAlignment:
94 case DeviceInfo::PreferredLocalAtomicAlignment:
95 case DeviceInfo::MaxNumSubGroups:
96 case DeviceInfo::SubGroupIndependentForwardProgress:
97 case DeviceInfo::NonUniformWorkGroupSupport:
98 case DeviceInfo::WorkGroupCollectiveFunctionsSupport:
99 case DeviceInfo::GenericAddressSpaceSupport:
100 case DeviceInfo::PipeSupport:
101 result = mImpl->getInfoUInt(name, &valUInt);
102 copyValue = &valUInt;
103 copySize = sizeof(valUInt);
104 break;
105
106 // Handle all cl_ulong and aliased types
107 case DeviceInfo::SingleFpConfig:
108 case DeviceInfo::DoubleFpConfig:
109 case DeviceInfo::GlobalMemCacheSize:
110 case DeviceInfo::GlobalMemSize:
111 case DeviceInfo::MaxConstantBufferSize:
112 case DeviceInfo::LocalMemSize:
113 case DeviceInfo::QueueOnHostProperties:
114 case DeviceInfo::QueueOnDeviceProperties:
115 case DeviceInfo::PartitionAffinityDomain:
116 case DeviceInfo::SVM_Capabilities:
117 case DeviceInfo::AtomicMemoryCapabilities:
118 case DeviceInfo::AtomicFenceCapabilities:
119 case DeviceInfo::DeviceEnqueueCapabilities:
120 case DeviceInfo::HalfFpConfig:
121 result = mImpl->getInfoULong(name, &valULong);
122 copyValue = &valULong;
123 copySize = sizeof(valULong);
124 break;
125
126 // Handle all size_t and aliased types
127 case DeviceInfo::MaxWorkGroupSize:
128 case DeviceInfo::MaxParameterSize:
129 case DeviceInfo::MaxGlobalVariableSize:
130 case DeviceInfo::GlobalVariablePreferredTotalSize:
131 case DeviceInfo::ProfilingTimerResolution:
132 case DeviceInfo::PrintfBufferSize:
133 case DeviceInfo::PreferredWorkGroupSizeMultiple:
134 result = mImpl->getInfoSizeT(name, &valSizeT);
135 copyValue = &valSizeT;
136 copySize = sizeof(valSizeT);
137 break;
138
139 // Handle all string types
140 case DeviceInfo::Name:
141 case DeviceInfo::Vendor:
142 case DeviceInfo::DriverVersion:
143 case DeviceInfo::Profile:
144 case DeviceInfo::OpenCL_C_Version:
145 case DeviceInfo::LatestConformanceVersionPassed:
146 result = mImpl->getInfoStringLength(name, ©Size);
147 if (result != CL_SUCCESS)
148 {
149 return result;
150 }
151 valString.resize(copySize, '\0');
152 result = mImpl->getInfoString(name, copySize, valString.data());
153 copyValue = valString.data();
154 break;
155
156 // Handle all cached values
157 case DeviceInfo::Type:
158 copyValue = &mInfo.type;
159 copySize = sizeof(mInfo.type);
160 break;
161 case DeviceInfo::MaxWorkItemDimensions:
162 valUInt = static_cast<cl_uint>(mInfo.maxWorkItemSizes.size());
163 copyValue = &valUInt;
164 copySize = sizeof(valUInt);
165 break;
166 case DeviceInfo::MaxWorkItemSizes:
167 copyValue = mInfo.maxWorkItemSizes.data();
168 copySize = mInfo.maxWorkItemSizes.size() *
169 sizeof(decltype(mInfo.maxWorkItemSizes)::value_type);
170 break;
171 case DeviceInfo::MaxMemAllocSize:
172 copyValue = &mInfo.maxMemAllocSize;
173 copySize = sizeof(mInfo.maxMemAllocSize);
174 break;
175 case DeviceInfo::ImageSupport:
176 copyValue = &mInfo.imageSupport;
177 copySize = sizeof(mInfo.imageSupport);
178 break;
179 case DeviceInfo::IL_Version:
180 copyValue = mInfo.IL_Version.c_str();
181 copySize = mInfo.IL_Version.length() + 1u;
182 break;
183 case DeviceInfo::ILsWithVersion:
184 copyValue = mInfo.ILsWithVersion.data();
185 copySize =
186 mInfo.ILsWithVersion.size() * sizeof(decltype(mInfo.ILsWithVersion)::value_type);
187 break;
188 case DeviceInfo::Image2D_MaxWidth:
189 copyValue = &mInfo.image2D_MaxWidth;
190 copySize = sizeof(mInfo.image2D_MaxWidth);
191 break;
192 case DeviceInfo::Image2D_MaxHeight:
193 copyValue = &mInfo.image2D_MaxHeight;
194 copySize = sizeof(mInfo.image2D_MaxHeight);
195 break;
196 case DeviceInfo::Image3D_MaxWidth:
197 copyValue = &mInfo.image3D_MaxWidth;
198 copySize = sizeof(mInfo.image3D_MaxWidth);
199 break;
200 case DeviceInfo::Image3D_MaxHeight:
201 copyValue = &mInfo.image3D_MaxHeight;
202 copySize = sizeof(mInfo.image3D_MaxHeight);
203 break;
204 case DeviceInfo::Image3D_MaxDepth:
205 copyValue = &mInfo.image3D_MaxDepth;
206 copySize = sizeof(mInfo.image3D_MaxDepth);
207 break;
208 case DeviceInfo::ImageMaxBufferSize:
209 copyValue = &mInfo.imageMaxBufferSize;
210 copySize = sizeof(mInfo.imageMaxBufferSize);
211 break;
212 case DeviceInfo::ImageMaxArraySize:
213 copyValue = &mInfo.imageMaxArraySize;
214 copySize = sizeof(mInfo.imageMaxArraySize);
215 break;
216 case DeviceInfo::ImagePitchAlignment:
217 copyValue = &mInfo.imagePitchAlignment;
218 copySize = sizeof(mInfo.imagePitchAlignment);
219 break;
220 case DeviceInfo::ImageBaseAddressAlignment:
221 copyValue = &mInfo.imageBaseAddressAlignment;
222 copySize = sizeof(mInfo.imageBaseAddressAlignment);
223 break;
224 case DeviceInfo::MemBaseAddrAlign:
225 copyValue = &mInfo.memBaseAddrAlign;
226 copySize = sizeof(mInfo.memBaseAddrAlign);
227 break;
228 case DeviceInfo::ExecutionCapabilities:
229 copyValue = &mInfo.execCapabilities;
230 copySize = sizeof(mInfo.execCapabilities);
231 break;
232 case DeviceInfo::QueueOnDeviceMaxSize:
233 copyValue = &mInfo.queueOnDeviceMaxSize;
234 copySize = sizeof(mInfo.queueOnDeviceMaxSize);
235 break;
236 case DeviceInfo::BuiltInKernels:
237 copyValue = mInfo.builtInKernels.c_str();
238 copySize = mInfo.builtInKernels.length() + 1u;
239 break;
240 case DeviceInfo::BuiltInKernelsWithVersion:
241 copyValue = mInfo.builtInKernelsWithVersion.data();
242 copySize = mInfo.builtInKernelsWithVersion.size() *
243 sizeof(decltype(mInfo.builtInKernelsWithVersion)::value_type);
244 break;
245 case DeviceInfo::Version:
246 copyValue = mInfo.versionStr.c_str();
247 copySize = mInfo.versionStr.length() + 1u;
248 break;
249 case DeviceInfo::NumericVersion:
250 copyValue = &mInfo.version;
251 copySize = sizeof(mInfo.version);
252 break;
253 case DeviceInfo::OpenCL_C_AllVersions:
254 copyValue = mInfo.OpenCL_C_AllVersions.data();
255 copySize = mInfo.OpenCL_C_AllVersions.size() *
256 sizeof(decltype(mInfo.OpenCL_C_AllVersions)::value_type);
257 break;
258 case DeviceInfo::OpenCL_C_Features:
259 copyValue = mInfo.OpenCL_C_Features.data();
260 copySize = mInfo.OpenCL_C_Features.size() *
261 sizeof(decltype(mInfo.OpenCL_C_Features)::value_type);
262 break;
263 case DeviceInfo::Extensions:
264 copyValue = mInfo.extensions.c_str();
265 copySize = mInfo.extensions.length() + 1u;
266 break;
267 case DeviceInfo::ExtensionsWithVersion:
268 copyValue = mInfo.extensionsWithVersion.data();
269 copySize = mInfo.extensionsWithVersion.size() *
270 sizeof(decltype(mInfo.extensionsWithVersion)::value_type);
271 break;
272 case DeviceInfo::PartitionProperties:
273 copyValue = mInfo.partitionProperties.data();
274 copySize = mInfo.partitionProperties.size() *
275 sizeof(decltype(mInfo.partitionProperties)::value_type);
276 break;
277 case DeviceInfo::PartitionType:
278 copyValue = mInfo.partitionType.data();
279 copySize =
280 mInfo.partitionType.size() * sizeof(decltype(mInfo.partitionType)::value_type);
281 break;
282
283 // Handle all mapped values
284 case DeviceInfo::Platform:
285 valPointer = mPlatform.getNative();
286 copyValue = &valPointer;
287 copySize = sizeof(valPointer);
288 break;
289 case DeviceInfo::ParentDevice:
290 valPointer = Device::CastNative(mParent.get());
291 copyValue = &valPointer;
292 copySize = sizeof(valPointer);
293 break;
294 case DeviceInfo::ReferenceCount:
295 valUInt = isRoot() ? 1u : getRefCount();
296 copyValue = &valUInt;
297 copySize = sizeof(valUInt);
298 break;
299
300 default:
301 ASSERT(false);
302 return CL_INVALID_VALUE;
303 }
304
305 if (result != CL_SUCCESS)
306 {
307 return result;
308 }
309 if (value != nullptr)
310 {
311 // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return
312 // type as specified in the Device Queries table and param_value is not a NULL value
313 if (valueSize < copySize)
314 {
315 return CL_INVALID_VALUE;
316 }
317 if (copyValue != nullptr)
318 {
319 std::memcpy(value, copyValue, copySize);
320 }
321 }
322 if (valueSizeRet != nullptr)
323 {
324 *valueSizeRet = copySize;
325 }
326 return CL_SUCCESS;
327 }
328
createSubDevices(const cl_device_partition_property * properties,cl_uint numDevices,cl_device_id * subDevices,cl_uint * numDevicesRet)329 cl_int Device::createSubDevices(const cl_device_partition_property *properties,
330 cl_uint numDevices,
331 cl_device_id *subDevices,
332 cl_uint *numDevicesRet)
333 {
334 if (subDevices == nullptr)
335 {
336 numDevices = 0u;
337 }
338 rx::CLDeviceImpl::CreateFuncs subDeviceCreateFuncs;
339 const cl_int errorCode =
340 mImpl->createSubDevices(properties, numDevices, subDeviceCreateFuncs, numDevicesRet);
341 if (errorCode == CL_SUCCESS)
342 {
343 cl::DeviceType type = mInfo.type;
344 type.clear(CL_DEVICE_TYPE_DEFAULT);
345 DevicePtrs devices;
346 devices.reserve(subDeviceCreateFuncs.size());
347 while (!subDeviceCreateFuncs.empty())
348 {
349 devices.emplace_back(new Device(mPlatform, this, type, subDeviceCreateFuncs.front()));
350 // Release initialization reference, lifetime controlled by RefPointer.
351 devices.back()->release();
352 if (!devices.back()->mInfo.isValid())
353 {
354 return CL_INVALID_VALUE;
355 }
356 subDeviceCreateFuncs.pop_front();
357 }
358 for (DevicePtr &subDevice : devices)
359 {
360 *subDevices++ = subDevice.release();
361 }
362 }
363 return errorCode;
364 }
365
366 Device::~Device() = default;
367
supportsBuiltInKernel(const std::string & name) const368 bool Device::supportsBuiltInKernel(const std::string &name) const
369 {
370 return angle::ContainsToken(mInfo.builtInKernels, ';', name);
371 }
372
supportsNativeImageDimensions(const cl_image_desc & desc) const373 bool Device::supportsNativeImageDimensions(const cl_image_desc &desc) const
374 {
375 switch (FromCLenum<MemObjectType>(desc.image_type))
376 {
377 case MemObjectType::Image1D:
378 return desc.image_width <= mInfo.image2D_MaxWidth;
379 case MemObjectType::Image2D:
380 return desc.image_width <= mInfo.image2D_MaxWidth &&
381 desc.image_height <= mInfo.image2D_MaxHeight;
382 case MemObjectType::Image3D:
383 return desc.image_width <= mInfo.image3D_MaxWidth &&
384 desc.image_height <= mInfo.image3D_MaxHeight &&
385 desc.image_depth <= mInfo.image3D_MaxDepth;
386 case MemObjectType::Image1D_Array:
387 return desc.image_width <= mInfo.image2D_MaxWidth &&
388 desc.image_array_size <= mInfo.imageMaxArraySize;
389 case MemObjectType::Image2D_Array:
390 return desc.image_width <= mInfo.image2D_MaxWidth &&
391 desc.image_height <= mInfo.image2D_MaxHeight &&
392 desc.image_array_size <= mInfo.imageMaxArraySize;
393 case MemObjectType::Image1D_Buffer:
394 return desc.image_width <= mInfo.imageMaxBufferSize;
395 default:
396 ASSERT(false);
397 break;
398 }
399 return false;
400 }
401
supportsImageDimensions(const ImageDescriptor & desc) const402 bool Device::supportsImageDimensions(const ImageDescriptor &desc) const
403 {
404 switch (desc.type)
405 {
406 case MemObjectType::Image1D:
407 return desc.width <= mInfo.image2D_MaxWidth;
408 case MemObjectType::Image2D:
409 return desc.width <= mInfo.image2D_MaxWidth && desc.height <= mInfo.image2D_MaxHeight;
410 case MemObjectType::Image3D:
411 return desc.width <= mInfo.image3D_MaxWidth && desc.height <= mInfo.image3D_MaxHeight &&
412 desc.depth <= mInfo.image3D_MaxDepth;
413 case MemObjectType::Image1D_Array:
414 return desc.width <= mInfo.image2D_MaxWidth &&
415 desc.arraySize <= mInfo.imageMaxArraySize;
416 case MemObjectType::Image2D_Array:
417 return desc.width <= mInfo.image2D_MaxWidth && desc.height <= mInfo.image2D_MaxHeight &&
418 desc.arraySize <= mInfo.imageMaxArraySize;
419 case MemObjectType::Image1D_Buffer:
420 return desc.width <= mInfo.imageMaxBufferSize;
421 default:
422 ASSERT(false);
423 break;
424 }
425 return false;
426 }
427
Device(Platform & platform,Device * parent,DeviceType type,const rx::CLDeviceImpl::CreateFunc & createFunc)428 Device::Device(Platform &platform,
429 Device *parent,
430 DeviceType type,
431 const rx::CLDeviceImpl::CreateFunc &createFunc)
432 : mPlatform(platform), mParent(parent), mImpl(createFunc(*this)), mInfo(mImpl->createInfo(type))
433 {}
434
435 } // namespace cl
436