• 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 // 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, &copySize);
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