// // 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" #include "common/string_utils.h" #include namespace cl { cl_int Device::getInfo(DeviceInfo name, size_t valueSize, void *value, size_t *valueSizeRet) const { static_assert(std::is_same::value && std::is_same::value && std::is_same::value && std::is_same::value && std::is_same::value && std::is_same::value && std::is_same::value && std::is_same::value && std::is_same::value && std::is_same::value && std::is_same::value && std::is_same::value, "OpenCL type mismatch"); cl_uint valUInt = 0u; cl_ulong valULong = 0u; size_t valSizeT = 0u; void *valPointer = nullptr; std::vector 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::MaxReadImageArgs: case DeviceInfo::MaxWriteImageArgs: case DeviceInfo::MaxReadWriteImageArgs: case DeviceInfo::MaxSamplers: case DeviceInfo::MaxPipeArgs: case DeviceInfo::PipeMaxActiveReservations: case DeviceInfo::PipeMaxPacketSize: 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::MaxOnDeviceQueues: case DeviceInfo::MaxOnDeviceEvents: 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::SingleFpConfig: case DeviceInfo::DoubleFpConfig: case DeviceInfo::GlobalMemCacheSize: case DeviceInfo::GlobalMemSize: case DeviceInfo::MaxConstantBufferSize: case DeviceInfo::LocalMemSize: 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::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::Name: case DeviceInfo::Vendor: case DeviceInfo::DriverVersion: case DeviceInfo::Profile: 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::Type: copyValue = &mInfo.type; copySize = sizeof(mInfo.type); break; case DeviceInfo::MaxWorkItemDimensions: valUInt = static_cast(mInfo.maxWorkItemSizes.size()); copyValue = &valUInt; copySize = sizeof(valUInt); break; case DeviceInfo::MaxWorkItemSizes: copyValue = mInfo.maxWorkItemSizes.data(); copySize = mInfo.maxWorkItemSizes.size() * sizeof(decltype(mInfo.maxWorkItemSizes)::value_type); break; case DeviceInfo::MaxMemAllocSize: copyValue = &mInfo.maxMemAllocSize; copySize = sizeof(mInfo.maxMemAllocSize); break; case DeviceInfo::ImageSupport: copyValue = &mInfo.imageSupport; copySize = sizeof(mInfo.imageSupport); break; case DeviceInfo::IL_Version: copyValue = mInfo.IL_Version.c_str(); copySize = mInfo.IL_Version.length() + 1u; break; case DeviceInfo::ILsWithVersion: copyValue = mInfo.ILsWithVersion.data(); copySize = mInfo.ILsWithVersion.size() * sizeof(decltype(mInfo.ILsWithVersion)::value_type); break; case DeviceInfo::Image2D_MaxWidth: copyValue = &mInfo.image2D_MaxWidth; copySize = sizeof(mInfo.image2D_MaxWidth); break; case DeviceInfo::Image2D_MaxHeight: copyValue = &mInfo.image2D_MaxHeight; copySize = sizeof(mInfo.image2D_MaxHeight); break; case DeviceInfo::Image3D_MaxWidth: copyValue = &mInfo.image3D_MaxWidth; copySize = sizeof(mInfo.image3D_MaxWidth); break; case DeviceInfo::Image3D_MaxHeight: copyValue = &mInfo.image3D_MaxHeight; copySize = sizeof(mInfo.image3D_MaxHeight); break; case DeviceInfo::Image3D_MaxDepth: copyValue = &mInfo.image3D_MaxDepth; copySize = sizeof(mInfo.image3D_MaxDepth); break; case DeviceInfo::ImageMaxBufferSize: copyValue = &mInfo.imageMaxBufferSize; copySize = sizeof(mInfo.imageMaxBufferSize); break; case DeviceInfo::ImageMaxArraySize: copyValue = &mInfo.imageMaxArraySize; copySize = sizeof(mInfo.imageMaxArraySize); break; case DeviceInfo::ImagePitchAlignment: copyValue = &mInfo.imagePitchAlignment; copySize = sizeof(mInfo.imagePitchAlignment); break; case DeviceInfo::ImageBaseAddressAlignment: copyValue = &mInfo.imageBaseAddressAlignment; copySize = sizeof(mInfo.imageBaseAddressAlignment); break; case DeviceInfo::MemBaseAddrAlign: copyValue = &mInfo.memBaseAddrAlign; copySize = sizeof(mInfo.memBaseAddrAlign); break; case DeviceInfo::ExecutionCapabilities: copyValue = &mInfo.execCapabilities; copySize = sizeof(mInfo.execCapabilities); break; case DeviceInfo::QueueOnDeviceMaxSize: copyValue = &mInfo.queueOnDeviceMaxSize; copySize = sizeof(mInfo.queueOnDeviceMaxSize); break; case DeviceInfo::BuiltInKernels: copyValue = mInfo.builtInKernels.c_str(); copySize = mInfo.builtInKernels.length() + 1u; break; case DeviceInfo::BuiltInKernelsWithVersion: copyValue = mInfo.builtInKernelsWithVersion.data(); copySize = mInfo.builtInKernelsWithVersion.size() * sizeof(decltype(mInfo.builtInKernelsWithVersion)::value_type); break; case DeviceInfo::Version: copyValue = mInfo.versionStr.c_str(); copySize = mInfo.versionStr.length() + 1u; break; case DeviceInfo::NumericVersion: copyValue = &mInfo.version; copySize = sizeof(mInfo.version); break; case DeviceInfo::OpenCL_C_AllVersions: copyValue = mInfo.OpenCL_C_AllVersions.data(); copySize = mInfo.OpenCL_C_AllVersions.size() * sizeof(decltype(mInfo.OpenCL_C_AllVersions)::value_type); break; case DeviceInfo::OpenCL_C_Features: copyValue = mInfo.OpenCL_C_Features.data(); copySize = mInfo.OpenCL_C_Features.size() * sizeof(decltype(mInfo.OpenCL_C_Features)::value_type); break; case DeviceInfo::Extensions: copyValue = mInfo.extensions.c_str(); copySize = mInfo.extensions.length() + 1u; break; case DeviceInfo::ExtensionsWithVersion: copyValue = mInfo.extensionsWithVersion.data(); copySize = mInfo.extensionsWithVersion.size() * sizeof(decltype(mInfo.extensionsWithVersion)::value_type); break; case DeviceInfo::PartitionProperties: copyValue = mInfo.partitionProperties.data(); copySize = mInfo.partitionProperties.size() * sizeof(decltype(mInfo.partitionProperties)::value_type); break; case DeviceInfo::PartitionType: copyValue = mInfo.partitionType.data(); copySize = mInfo.partitionType.size() * sizeof(decltype(mInfo.partitionType)::value_type); break; // Handle all mapped values case DeviceInfo::Platform: valPointer = mPlatform.getNative(); copyValue = &valPointer; copySize = sizeof(valPointer); break; case DeviceInfo::ParentDevice: valPointer = Device::CastNative(mParent.get()); copyValue = &valPointer; copySize = sizeof(valPointer); break; case DeviceInfo::ReferenceCount: valUInt = isRoot() ? 1u : getRefCount(); copyValue = &valUInt; copySize = sizeof(valUInt); break; default: ASSERT(false); return CL_INVALID_VALUE; } if (result != CL_SUCCESS) { return result; } if (value != nullptr) { // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return // type as specified in the Device Queries table and param_value is not a NULL value 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, cl_device_id *subDevices, cl_uint *numDevicesRet) { if (subDevices == nullptr) { numDevices = 0u; } rx::CLDeviceImpl::CreateFuncs subDeviceCreateFuncs; const cl_int errorCode = mImpl->createSubDevices(properties, numDevices, subDeviceCreateFuncs, numDevicesRet); if (errorCode == CL_SUCCESS) { cl::DeviceType type = mInfo.type; type.clear(CL_DEVICE_TYPE_DEFAULT); DevicePtrs devices; devices.reserve(subDeviceCreateFuncs.size()); while (!subDeviceCreateFuncs.empty()) { devices.emplace_back(new Device(mPlatform, this, type, subDeviceCreateFuncs.front())); // Release initialization reference, lifetime controlled by RefPointer. devices.back()->release(); if (!devices.back()->mInfo.isValid()) { return CL_INVALID_VALUE; } subDeviceCreateFuncs.pop_front(); } for (DevicePtr &subDevice : devices) { *subDevices++ = subDevice.release(); } } return errorCode; } Device::~Device() = default; bool Device::supportsBuiltInKernel(const std::string &name) const { return angle::ContainsToken(mInfo.builtInKernels, ';', name); } bool Device::supportsNativeImageDimensions(const cl_image_desc &desc) const { switch (FromCLenum(desc.image_type)) { case MemObjectType::Image1D: return desc.image_width <= mInfo.image2D_MaxWidth; case MemObjectType::Image2D: return desc.image_width <= mInfo.image2D_MaxWidth && desc.image_height <= mInfo.image2D_MaxHeight; case MemObjectType::Image3D: return desc.image_width <= mInfo.image3D_MaxWidth && desc.image_height <= mInfo.image3D_MaxHeight && desc.image_depth <= mInfo.image3D_MaxDepth; case MemObjectType::Image1D_Array: return desc.image_width <= mInfo.image2D_MaxWidth && desc.image_array_size <= mInfo.imageMaxArraySize; case MemObjectType::Image2D_Array: return desc.image_width <= mInfo.image2D_MaxWidth && desc.image_height <= mInfo.image2D_MaxHeight && desc.image_array_size <= mInfo.imageMaxArraySize; case MemObjectType::Image1D_Buffer: return desc.image_width <= mInfo.imageMaxBufferSize; default: ASSERT(false); break; } return false; } bool Device::supportsImageDimensions(const ImageDescriptor &desc) const { switch (desc.type) { case MemObjectType::Image1D: return desc.width <= mInfo.image2D_MaxWidth; case MemObjectType::Image2D: return desc.width <= mInfo.image2D_MaxWidth && desc.height <= mInfo.image2D_MaxHeight; case MemObjectType::Image3D: return desc.width <= mInfo.image3D_MaxWidth && desc.height <= mInfo.image3D_MaxHeight && desc.depth <= mInfo.image3D_MaxDepth; case MemObjectType::Image1D_Array: return desc.width <= mInfo.image2D_MaxWidth && desc.arraySize <= mInfo.imageMaxArraySize; case MemObjectType::Image2D_Array: return desc.width <= mInfo.image2D_MaxWidth && desc.height <= mInfo.image2D_MaxHeight && desc.arraySize <= mInfo.imageMaxArraySize; case MemObjectType::Image1D_Buffer: return desc.width <= mInfo.imageMaxBufferSize; default: ASSERT(false); break; } return false; } Device::Device(Platform &platform, Device *parent, DeviceType type, const rx::CLDeviceImpl::CreateFunc &createFunc) : mPlatform(platform), mParent(parent), mImpl(createFunc(*this)), mInfo(mImpl->createInfo(type)) {} } // namespace cl