blob: 91e699e149d556087d362a3903e48b45fd6ab54a [file] [edit]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include <sycl/__impl/detail/config.hpp>
#include <sycl/__impl/detail/obj_utils.hpp>
#include <sycl/__impl/property_list.hpp>
#include <detail/context_impl.hpp>
#include <detail/device_impl.hpp>
#include <detail/global_objects.hpp>
#include <detail/platform_impl.hpp>
#include <algorithm>
#include <cassert>
#include <memory>
#include <utility>
_LIBSYCL_BEGIN_NAMESPACE_SYCL
namespace detail {
bool PlatformImpl::MRediscoverIfEmpty = false;
const std::vector<PlatformImplUPtr> &PlatformImpl::getPlatforms() {
static auto InitPlatforms = []() {
discoverOffloadDevices();
registerStaticVarShutdownHandler();
auto &PlatformCache = getPlatformCache();
for (const auto &Topo : getOffloadTopologies()) {
if (Topo.getBackend() == OL_PLATFORM_BACKEND_HOST)
continue;
for (const auto &PlatformGroup : Topo.getPlatformGroups()) {
PlatformCache.emplace_back(std::make_unique<PlatformImpl>(
PlatformGroup.Platform, PlatformGroup.Devices, PrivateTag{}));
}
}
};
[[maybe_unused]] static auto InitPlatformsOnce = []() {
callAndThrow(olInit, nullptr);
InitPlatforms();
return true;
}();
auto &PlatformCache = getPlatformCache();
if (MRediscoverIfEmpty && PlatformCache.empty())
InitPlatforms();
return PlatformCache;
}
PlatformImpl::PlatformImpl(ol_platform_handle_t Platform,
const std::vector<ol_device_handle_t> &Devices,
PrivateTag)
: MOffloadPlatform(Platform) {
assert(!Devices.empty() && "Platform must contain at least one device");
ol_platform_backend_t Backend = OL_PLATFORM_BACKEND_UNKNOWN;
callAndThrow(olGetPlatformInfo, MOffloadPlatform, OL_PLATFORM_INFO_BACKEND,
sizeof(Backend), &Backend);
MBackend = convertBackend(Backend);
MRootDevices.reserve(Devices.size());
for (const ol_device_handle_t &Device : Devices) {
MRootDevices.emplace_back(
std::make_unique<DeviceImpl>(Device, *this, DeviceImpl::PrivateTag{}));
}
std::vector<DeviceImpl *> DeviceImpls;
DeviceImpls.reserve(MRootDevices.size());
for (const auto &Device : MRootDevices)
DeviceImpls.push_back(Device.get());
MDefaultContext = ContextImpl::create(std::move(DeviceImpls),
defaultAsyncHandler, property_list{});
}
const std::vector<DeviceImplUPtr> &PlatformImpl::getRootDevices() const {
return MRootDevices;
}
bool PlatformImpl::has(aspect Aspect) const {
const auto &Devices = getRootDevices();
return std::all_of(
Devices.begin(), Devices.end(),
[&Aspect](const DeviceImplUPtr &Device) { return Device->has(Aspect); });
}
void PlatformImpl::iterateDevices(
info::device_type DeviceType,
const std::function<void(DeviceImpl *)> &Callback) const {
// Early exit if host/custom/accelerator device is requested:
// - host device is deprecated and not required by the SYCL 2020
// specification.
// - accelerator and custom devices are unsupported by liboffload.
if ((DeviceType == info::device_type::host) ||
(DeviceType == info::device_type::custom) ||
(DeviceType == info::device_type::accelerator))
return;
const auto &DeviceImpls = getRootDevices();
assert(!DeviceImpls.empty() &&
"Platform can't exist without at least one device.");
// TODO: Need a way to get default device from liboffload.
// As a temporal solution just return the first device for DeviceType ==
// automatic.
if (DeviceType == info::device_type::automatic) {
Callback(DeviceImpls[0].get());
return;
}
bool KeepAll = DeviceType == info::device_type::all;
for (auto &Impl : DeviceImpls) {
if (KeepAll || DeviceType == Impl->getDeviceType())
Callback(Impl.get());
}
}
ContextImpl &PlatformImpl::getDefaultContext() {
assert(MDefaultContext && "Default context must be created in platform ctor");
return *MDefaultContext;
}
} // namespace detail
_LIBSYCL_END_NAMESPACE_SYCL