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