| // |
| // Copyright 2021 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // CLDevice.cpp: Implements the cl::Device class. |
| |
| #include "libANGLE/CLDevice.h" |
| |
| #include "libANGLE/CLPlatform.h" |
| |
| namespace cl |
| { |
| |
| Device::~Device() |
| { |
| if (isRoot()) |
| { |
| removeRef(); |
| } |
| } |
| |
| bool Device::release() |
| { |
| if (isRoot()) |
| { |
| return false; |
| } |
| const bool released = removeRef(); |
| if (released) |
| { |
| mParent->destroySubDevice(this); |
| } |
| return released; |
| } |
| |
| cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *valueSizeRet) |
| { |
| static_assert(std::is_same<cl_uint, cl_bool>::value && |
| std::is_same<cl_uint, cl_device_mem_cache_type>::value && |
| std::is_same<cl_uint, cl_device_local_mem_type>::value && |
| std::is_same<cl_uint, cl_version>::value && |
| std::is_same<cl_ulong, cl_device_type>::value && |
| std::is_same<cl_ulong, cl_device_fp_config>::value && |
| std::is_same<cl_ulong, cl_device_exec_capabilities>::value && |
| std::is_same<cl_ulong, cl_command_queue_properties>::value && |
| std::is_same<cl_ulong, cl_device_affinity_domain>::value && |
| std::is_same<cl_ulong, cl_device_svm_capabilities>::value && |
| std::is_same<cl_ulong, cl_device_atomic_capabilities>::value && |
| std::is_same<cl_ulong, cl_device_device_enqueue_capabilities>::value, |
| "OpenCL type mismatch"); |
| |
| cl_uint valUInt = 0u; |
| cl_ulong valULong = 0u; |
| size_t valSizeT = 0u; |
| void *valPointer = nullptr; |
| std::vector<char> valString; |
| |
| const void *copyValue = nullptr; |
| size_t copySize = 0u; |
| cl_int result = CL_SUCCESS; |
| |
| // The info names are sorted within their type group in the order they appear in the OpenCL |
| // specification, so it is easier to compare them side-by-side when looking for changes. |
| // https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#clGetDeviceInfo |
| switch (name) |
| { |
| // Handle all cl_uint and aliased types |
| case DeviceInfo::VendorID: |
| case DeviceInfo::MaxComputeUnits: |
| case DeviceInfo::PreferredVectorWidthChar: |
| case DeviceInfo::PreferredVectorWidthShort: |
| case DeviceInfo::PreferredVectorWidthInt: |
| case DeviceInfo::PreferredVectorWidthLong: |
| case DeviceInfo::PreferredVectorWidthFloat: |
| case DeviceInfo::PreferredVectorWidthDouble: |
| case DeviceInfo::PreferredVectorWidthHalf: |
| case DeviceInfo::NativeVectorWidthChar: |
| case DeviceInfo::NativeVectorWidthShort: |
| case DeviceInfo::NativeVectorWidthInt: |
| case DeviceInfo::NativeVectorWidthLong: |
| case DeviceInfo::NativeVectorWidthFloat: |
| case DeviceInfo::NativeVectorWidthDouble: |
| case DeviceInfo::NativeVectorWidthHalf: |
| case DeviceInfo::MaxClockFrequency: |
| case DeviceInfo::AddressBits: |
| case DeviceInfo::ImageSupport: |
| case DeviceInfo::MaxReadImageArgs: |
| case DeviceInfo::MaxWriteImageArgs: |
| case DeviceInfo::MaxReadWriteImageArgs: |
| case DeviceInfo::MaxSamplers: |
| case DeviceInfo::ImagePitchAlignment: |
| case DeviceInfo::ImageBaseAddressAlignment: |
| case DeviceInfo::MaxPipeArgs: |
| case DeviceInfo::PipeMaxActiveReservations: |
| case DeviceInfo::PipeMaxPacketSize: |
| case DeviceInfo::MemBaseAddrAlign: |
| case DeviceInfo::MinDataTypeAlignSize: |
| case DeviceInfo::GlobalMemCacheType: |
| case DeviceInfo::GlobalMemCachelineSize: |
| case DeviceInfo::MaxConstantArgs: |
| case DeviceInfo::LocalMemType: |
| case DeviceInfo::ErrorCorrectionSupport: |
| case DeviceInfo::HostUnifiedMemory: |
| case DeviceInfo::EndianLittle: |
| case DeviceInfo::Available: |
| case DeviceInfo::CompilerAvailable: |
| case DeviceInfo::LinkerAvailable: |
| case DeviceInfo::QueueOnDevicePreferredSize: |
| case DeviceInfo::QueueOnDeviceMaxSize: |
| case DeviceInfo::MaxOnDeviceQueues: |
| case DeviceInfo::MaxOnDeviceEvents: |
| case DeviceInfo::NumericVersion: |
| case DeviceInfo::PreferredInteropUserSync: |
| case DeviceInfo::PartitionMaxSubDevices: |
| case DeviceInfo::PreferredPlatformAtomicAlignment: |
| case DeviceInfo::PreferredGlobalAtomicAlignment: |
| case DeviceInfo::PreferredLocalAtomicAlignment: |
| case DeviceInfo::MaxNumSubGroups: |
| case DeviceInfo::SubGroupIndependentForwardProgress: |
| case DeviceInfo::NonUniformWorkGroupSupport: |
| case DeviceInfo::WorkGroupCollectiveFunctionsSupport: |
| case DeviceInfo::GenericAddressSpaceSupport: |
| case DeviceInfo::PipeSupport: |
| result = mImpl->getInfoUInt(name, &valUInt); |
| copyValue = &valUInt; |
| copySize = sizeof(valUInt); |
| break; |
| |
| // Handle all cl_ulong and aliased types |
| case DeviceInfo::Type: |
| case DeviceInfo::MaxMemAllocSize: |
| case DeviceInfo::SingleFpConfig: |
| case DeviceInfo::DoubleFpConfig: |
| case DeviceInfo::GlobalMemCacheSize: |
| case DeviceInfo::GlobalMemSize: |
| case DeviceInfo::MaxConstantBufferSize: |
| case DeviceInfo::LocalMemSize: |
| case DeviceInfo::ExecutionCapabilities: |
| case DeviceInfo::QueueOnHostProperties: |
| case DeviceInfo::QueueOnDeviceProperties: |
| case DeviceInfo::PartitionAffinityDomain: |
| case DeviceInfo::SVM_Capabilities: |
| case DeviceInfo::AtomicMemoryCapabilities: |
| case DeviceInfo::AtomicFenceCapabilities: |
| case DeviceInfo::DeviceEnqueueCapabilities: |
| case DeviceInfo::HalfFpConfig: |
| result = mImpl->getInfoULong(name, &valULong); |
| copyValue = &valULong; |
| copySize = sizeof(valULong); |
| break; |
| |
| // Handle all size_t and aliased types |
| case DeviceInfo::MaxWorkGroupSize: |
| case DeviceInfo::Image2D_MaxWidth: |
| case DeviceInfo::Image2D_MaxHeight: |
| case DeviceInfo::Image3D_MaxWidth: |
| case DeviceInfo::Image3D_MaxHeight: |
| case DeviceInfo::Image3D_MaxDepth: |
| case DeviceInfo::ImageMaxBufferSize: |
| case DeviceInfo::ImageMaxArraySize: |
| case DeviceInfo::MaxParameterSize: |
| case DeviceInfo::MaxGlobalVariableSize: |
| case DeviceInfo::GlobalVariablePreferredTotalSize: |
| case DeviceInfo::ProfilingTimerResolution: |
| case DeviceInfo::PrintfBufferSize: |
| case DeviceInfo::PreferredWorkGroupSizeMultiple: |
| result = mImpl->getInfoSizeT(name, &valSizeT); |
| copyValue = &valSizeT; |
| copySize = sizeof(valSizeT); |
| break; |
| |
| // Handle all string types |
| case DeviceInfo::IL_Version: |
| case DeviceInfo::BuiltInKernels: |
| case DeviceInfo::Name: |
| case DeviceInfo::Vendor: |
| case DeviceInfo::DriverVersion: |
| case DeviceInfo::Profile: |
| case DeviceInfo::Version: |
| case DeviceInfo::OpenCL_C_Version: |
| case DeviceInfo::LatestConformanceVersionPassed: |
| result = mImpl->getInfoStringLength(name, ©Size); |
| if (result != CL_SUCCESS) |
| { |
| return result; |
| } |
| valString.resize(copySize, '\0'); |
| result = mImpl->getInfoString(name, copySize, valString.data()); |
| copyValue = valString.data(); |
| break; |
| |
| // Handle all cached values |
| case DeviceInfo::MaxWorkItemDimensions: |
| valUInt = static_cast<cl_uint>(mInfo.mMaxWorkItemSizes.size()); |
| copyValue = &valUInt; |
| copySize = sizeof(valUInt); |
| break; |
| case DeviceInfo::MaxWorkItemSizes: |
| copyValue = mInfo.mMaxWorkItemSizes.data(); |
| copySize = mInfo.mMaxWorkItemSizes.size() * |
| sizeof(decltype(mInfo.mMaxWorkItemSizes)::value_type); |
| break; |
| case DeviceInfo::ILsWithVersion: |
| if (!mInfo.mIsSupportedILsWithVersion) |
| { |
| return CL_INVALID_VALUE; |
| } |
| copyValue = mInfo.mILsWithVersion.data(); |
| copySize = |
| mInfo.mILsWithVersion.size() * sizeof(decltype(mInfo.mILsWithVersion)::value_type); |
| break; |
| case DeviceInfo::BuiltInKernelsWithVersion: |
| if (!mInfo.mIsSupportedBuiltInKernelsWithVersion) |
| { |
| return CL_INVALID_VALUE; |
| } |
| copyValue = mInfo.mBuiltInKernelsWithVersion.data(); |
| copySize = mInfo.mBuiltInKernelsWithVersion.size() * |
| sizeof(decltype(mInfo.mBuiltInKernelsWithVersion)::value_type); |
| break; |
| case DeviceInfo::OpenCL_C_AllVersions: |
| if (!mInfo.mIsSupportedOpenCL_C_AllVersions) |
| { |
| return CL_INVALID_VALUE; |
| } |
| copyValue = mInfo.mOpenCL_C_AllVersions.data(); |
| copySize = mInfo.mOpenCL_C_AllVersions.size() * |
| sizeof(decltype(mInfo.mOpenCL_C_AllVersions)::value_type); |
| break; |
| case DeviceInfo::OpenCL_C_Features: |
| if (!mInfo.mIsSupportedOpenCL_C_Features) |
| { |
| return CL_INVALID_VALUE; |
| } |
| copyValue = mInfo.mOpenCL_C_Features.data(); |
| copySize = mInfo.mOpenCL_C_Features.size() * |
| sizeof(decltype(mInfo.mOpenCL_C_Features)::value_type); |
| break; |
| case DeviceInfo::Extensions: |
| copyValue = mInfo.mExtensions.c_str(); |
| copySize = mInfo.mExtensions.length() + 1u; |
| break; |
| case DeviceInfo::ExtensionsWithVersion: |
| if (!mInfo.mIsSupportedExtensionsWithVersion) |
| { |
| return CL_INVALID_VALUE; |
| } |
| copyValue = mInfo.mExtensionsWithVersion.data(); |
| copySize = mInfo.mExtensionsWithVersion.size() * |
| sizeof(decltype(mInfo.mExtensionsWithVersion)::value_type); |
| break; |
| case DeviceInfo::PartitionProperties: |
| copyValue = mInfo.mPartitionProperties.data(); |
| copySize = mInfo.mPartitionProperties.size() * |
| sizeof(decltype(mInfo.mPartitionProperties)::value_type); |
| break; |
| case DeviceInfo::PartitionType: |
| copyValue = mInfo.mPartitionType.data(); |
| copySize = |
| mInfo.mPartitionType.size() * sizeof(decltype(mInfo.mPartitionType)::value_type); |
| break; |
| |
| // Handle all mapped values |
| case DeviceInfo::Platform: |
| valPointer = &mPlatform; |
| copyValue = &valPointer; |
| copySize = sizeof(valPointer); |
| break; |
| case DeviceInfo::ParentDevice: |
| copyValue = &mParent; |
| copySize = sizeof(mParent); |
| break; |
| case DeviceInfo::ReferenceCount: |
| copyValue = getRefCountPtr(); |
| copySize = sizeof(*getRefCountPtr()); |
| break; |
| |
| default: |
| WARN() << "CL device info " << name << " is not (yet) supported"; |
| return CL_INVALID_VALUE; |
| } |
| |
| if (result != CL_SUCCESS) |
| { |
| return result; |
| } |
| if (value != nullptr) |
| { |
| if (valueSize < copySize) |
| { |
| return CL_INVALID_VALUE; |
| } |
| if (copyValue != nullptr) |
| { |
| std::memcpy(value, copyValue, copySize); |
| } |
| } |
| if (valueSizeRet != nullptr) |
| { |
| *valueSizeRet = copySize; |
| } |
| return CL_SUCCESS; |
| } |
| |
| cl_int Device::createSubDevices(const cl_device_partition_property *properties, |
| cl_uint numDevices, |
| Device **devices, |
| cl_uint *numDevicesRet) |
| { |
| if (devices == nullptr) |
| { |
| numDevices = 0u; |
| } |
| rx::CLDeviceImpl::InitList initList; |
| const cl_int result = mImpl->createSubDevices(properties, numDevices, initList, numDevicesRet); |
| if (result == CL_SUCCESS) |
| { |
| while (!initList.empty()) |
| { |
| mSubDevices.emplace_back(new Device(mPlatform, this, initList.front())); |
| *devices++ = mSubDevices.back().get(); |
| initList.pop_front(); |
| } |
| } |
| return result; |
| } |
| |
| Device::PtrList Device::CreateDevices(Platform &platform, rx::CLDeviceImpl::InitList &&initList) |
| { |
| PtrList devices; |
| while (!initList.empty()) |
| { |
| devices.emplace_back(new Device(platform, nullptr, initList.front())); |
| initList.pop_front(); |
| } |
| return devices; |
| } |
| |
| bool Device::IsValid(const Device *device) |
| { |
| const Platform::PtrList &platforms = Platform::GetPlatforms(); |
| return std::find_if(platforms.cbegin(), platforms.cend(), [=](const Platform::Ptr &platform) { |
| return platform->hasDevice(device); |
| }) != platforms.cend(); |
| } |
| |
| Device::Device(Platform &platform, Device *parent, rx::CLDeviceImpl::InitData &initData) |
| : _cl_device_id(platform.getDispatch()), |
| mPlatform(platform), |
| mParent(parent), |
| mImpl(std::move(initData.first)), |
| mInfo(std::move(initData.second)) |
| {} |
| |
| void Device::destroySubDevice(Device *device) |
| { |
| auto deviceIt = mSubDevices.cbegin(); |
| while (deviceIt != mSubDevices.cend() && deviceIt->get() != device) |
| { |
| ++deviceIt; |
| } |
| if (deviceIt != mSubDevices.cend()) |
| { |
| mSubDevices.erase(deviceIt); |
| release(); |
| } |
| else |
| { |
| ERR() << "Sub-device not found"; |
| } |
| } |
| |
| } // namespace cl |