26 inline namespace _V1 {
31 : MOwnedByRuntime(true), MAsyncHandler(AsyncHandler), MDevices(1, Device),
34 MPropList(PropList), MSupportBufferLocationByDevices(NotChecked) {
41 : MOwnedByRuntime(true), MAsyncHandler(AsyncHandler), MDevices(Devices),
42 MContext(nullptr), MPlatform(), MPropList(PropList),
43 MSupportBufferLocationByDevices(NotChecked) {
45 std::vector<ur_device_handle_t> DeviceIds;
46 for (
const auto &D : MDevices) {
47 if (D.has(aspect::ext_oneapi_is_composite)) {
53 std::vector<device> ComponentDevices = D.get_info<
54 ext::oneapi::experimental::info::device::component_devices>();
55 for (
const auto &CD : ComponentDevices)
62 getPlugin()->call(urContextCreate, DeviceIds.size(), DeviceIds.data(),
70 const std::vector<sycl::device> &DeviceList,
72 : MOwnedByRuntime(OwnedByRuntime), MAsyncHandler(AsyncHandler),
73 MDevices(DeviceList), MContext(UrContext), MPlatform(),
74 MSupportBufferLocationByDevices(NotChecked) {
75 if (!MDevices.empty()) {
78 std::vector<ur_device_handle_t> DeviceIds;
79 uint32_t DevicesNum = 0;
81 Plugin->call(urContextGetInfo, MContext, UR_CONTEXT_INFO_NUM_DEVICES,
82 sizeof(DevicesNum), &DevicesNum,
nullptr);
83 DeviceIds.resize(DevicesNum);
85 Plugin->call(urContextGetInfo, MContext, UR_CONTEXT_INFO_DEVICES,
86 sizeof(ur_device_handle_t) * DevicesNum, &DeviceIds[0],
89 if (DeviceIds.empty())
92 "No devices in the provided device list and native context.");
94 std::shared_ptr<detail::platform_impl> Platform =
96 for (ur_device_handle_t Dev : DeviceIds) {
97 MDevices.emplace_back(createSyclObjFromImpl<device>(
98 Platform->getOrMakeDeviceImpl(Dev, Platform)));
100 MPlatform = Platform;
109 getPlugin()->call(urContextRetain, MContext);
116 getPlugin()->call(urContextRetain, MContext);
117 ur_native_handle_t nativeHandle = 0;
118 getPlugin()->call(urContextGetNativeHandle, MContext, &nativeHandle);
119 return ur::cast<cl_context>(nativeHandle);
125 for (
auto &DeviceGlobalInitializer : MDeviceGlobalInitializers)
126 DeviceGlobalInitializer.second.ClearEvents(
getPlugin());
128 for (
const void *DeviceGlobal : MAssociatedDeviceGlobals) {
134 for (
auto LibProg : MCachedLibPrograms) {
135 assert(LibProg.second &&
"Null program must not be kept in the cache");
136 getPlugin()->call(urProgramRelease, LibProg.second);
139 getPlugin()->call_nocheck(urContextRelease, MContext);
140 }
catch (std::exception &e) {
146 return MAsyncHandler;
150 uint32_t context_impl::get_info<info::context::reference_count>()
const {
151 return get_context_info<info::context::reference_count>(this->getHandleRef(),
154 template <>
platform context_impl::get_info<info::context::platform>()
const {
155 return createSyclObjFromImpl<platform>(MPlatform);
158 std::vector<sycl::device>
159 context_impl::get_info<info::context::devices>()
const {
163 std::vector<sycl::memory_order>
164 context_impl::get_info<info::context::atomic_memory_order_capabilities>()
166 std::vector<sycl::memory_order> CapabilityList{
167 sycl::memory_order::relaxed, sycl::memory_order::acquire,
169 sycl::memory_order::seq_cst};
173 MDevices, CapabilityList);
175 return CapabilityList;
178 std::vector<sycl::memory_scope>
179 context_impl::get_info<info::context::atomic_memory_scope_capabilities>()
181 std::vector<sycl::memory_scope> CapabilityList{
184 sycl::memory_scope::system};
188 MDevices, CapabilityList);
190 return CapabilityList;
193 std::vector<sycl::memory_order>
194 context_impl::get_info<info::context::atomic_fence_order_capabilities>()
const {
195 std::vector<sycl::memory_order> CapabilityList{
196 sycl::memory_order::relaxed, sycl::memory_order::acquire,
198 sycl::memory_order::seq_cst};
201 info::device::atomic_fence_order_capabilities>(
202 MDevices, CapabilityList);
204 return CapabilityList;
207 std::vector<sycl::memory_scope>
208 context_impl::get_info<info::context::atomic_fence_scope_capabilities>()
const {
209 std::vector<sycl::memory_scope> CapabilityList{
212 sycl::memory_scope::system};
215 info::device::atomic_fence_scope_capabilities>(
216 MDevices, CapabilityList);
218 return CapabilityList;
222 typename info::platform::version::return_type
223 context_impl::get_backend_info<info::platform::version>()
const {
226 "the info::platform::version info descriptor can "
227 "only be queried with an OpenCL backend");
229 return MDevices[0].get_platform().get_info<info::platform::version>();
233 std::vector<device> &Devices);
236 typename info::device::version::return_type
237 context_impl::get_backend_info<info::device::version>()
const {
240 "the info::device::version info descriptor can only "
241 "be queried with an OpenCL backend");
243 auto Devices = get_info<info::context::devices>();
244 if (Devices.empty()) {
245 return "No available device";
253 typename info::device::backend_version::return_type
254 context_impl::get_backend_info<info::device::backend_version>()
const {
257 "the info::device::backend_version info descriptor "
258 "can only be queried with a Level Zero backend");
272 return MKernelProgramCache;
276 std::shared_ptr<detail::device_impl> Device)
const {
277 for (
auto D : MDevices)
296 ur_native_handle_t Handle;
297 Plugin->call(urContextGetNativeHandle,
getHandleRef(), &Handle);
302 if (MSupportBufferLocationByDevices !=
NotChecked)
303 return MSupportBufferLocationByDevices ==
Supported ? true :
false;
305 MSupportBufferLocationByDevices =
Supported;
306 for (
auto &Device : MDevices) {
307 if (!Device.has_extension(
"cl_intel_mem_alloc_buffer_location")) {
312 return MSupportBufferLocationByDevices ==
Supported ? true :
false;
316 std::lock_guard<std::mutex> Lock{MAssociatedDeviceGlobalsMutex};
317 MAssociatedDeviceGlobals.insert(DeviceGlobalPtr);
321 ur_program_handle_t Program,
const std::vector<device> &Devs,
323 std::lock_guard<std::mutex> Lock(MDeviceGlobalInitializersMutex);
324 for (
const device &Dev : Devs) {
326 MDeviceGlobalInitializers.emplace(Key, BinImage);
331 ur_program_handle_t NativePrg,
332 const std::shared_ptr<queue_impl> &QueueImpl) {
334 const DeviceImplPtr &DeviceImpl = QueueImpl->getDeviceImplPtr();
335 std::lock_guard<std::mutex> NativeProgramLock(MDeviceGlobalInitializersMutex);
336 auto ImgIt = MDeviceGlobalInitializers.find(
337 std::make_pair(NativePrg, DeviceImpl->getHandleRef()));
338 if (ImgIt == MDeviceGlobalInitializers.end() ||
339 ImgIt->second.MDeviceGlobalsFullyInitialized)
342 DeviceGlobalInitializer &InitRef = ImgIt->second;
344 std::lock_guard<std::mutex> InitLock(InitRef.MDeviceGlobalInitMutex);
345 std::vector<ur_event_handle_t> &InitEventsRef =
346 InitRef.MDeviceGlobalInitEvents;
347 if (!InitEventsRef.empty()) {
349 auto NewEnd = std::remove_if(
350 InitEventsRef.begin(), InitEventsRef.end(),
351 [&Plugin](
const ur_event_handle_t &Event) {
352 return get_event_info<info::event::command_execution_status>(
353 Event, Plugin) == info::event_command_status::complete;
357 for (
auto EventIt = NewEnd; EventIt != InitEventsRef.end(); ++EventIt)
358 Plugin->call(urEventRelease, *EventIt);
360 InitEventsRef.erase(NewEnd, InitEventsRef.end());
362 if (InitEventsRef.empty())
363 InitRef.MDeviceGlobalsFullyInitialized =
true;
364 return InitEventsRef;
365 }
else if (InitRef.MDeviceGlobalsFullyInitialized) {
373 auto DeviceGlobals = InitRef.MBinImage->getDeviceGlobals();
374 std::vector<std::string> DeviceGlobalIds;
375 DeviceGlobalIds.reserve(DeviceGlobals.size());
377 DeviceGlobalIds.push_back(DeviceGlobal->Name);
378 std::vector<DeviceGlobalMapEntry *> DeviceGlobalEntries =
385 if (DeviceGlobalEntries.empty()) {
386 InitRef.MDeviceGlobalsFullyInitialized =
true;
393 InitEventsRef.reserve(DeviceGlobalEntries.size());
401 DeviceGlobalEntry->getOrAllocateDeviceGlobalUSM(QueueImpl);
409 InitEventsRef.push_back(ZIEvent.TransferOwnership());
413 ur_event_handle_t InitEvent;
414 void *
const &USMPtr = DeviceGlobalUSM.
getPtr();
415 Plugin->call(urEnqueueDeviceGlobalVariableWrite,
416 QueueImpl->getHandleRef(), NativePrg,
417 DeviceGlobalEntry->MUniqueId.c_str(),
false,
sizeof(
void *),
418 0, &USMPtr, 0,
nullptr, &InitEvent);
420 InitEventsRef.push_back(InitEvent);
422 return InitEventsRef;
426 void context_impl::DeviceGlobalInitializer::ClearEvents(
428 for (
const ur_event_handle_t &Event : MDeviceGlobalInitEvents)
429 Plugin->call(urEventRelease, Event);
430 MDeviceGlobalInitEvents.clear();
434 const std::shared_ptr<device_impl> &DeviceImpl,
const void *DeviceGlobalPtr,
435 const void *Src,
size_t DeviceGlobalTSize,
bool IsDeviceImageScoped,
436 size_t NumBytes,
size_t Offset) {
437 std::optional<ur_device_handle_t> KeyDevice = std::nullopt;
438 if (IsDeviceImageScoped)
439 KeyDevice = DeviceImpl->getHandleRef();
440 auto Key = std::make_pair(DeviceGlobalPtr, KeyDevice);
442 std::lock_guard<std::mutex> InitLock(MDeviceGlobalUnregisteredDataMutex);
444 auto UnregisteredDataIt = MDeviceGlobalUnregisteredData.find(Key);
445 if (UnregisteredDataIt == MDeviceGlobalUnregisteredData.end()) {
446 std::unique_ptr<std::byte[]> NewData =
447 std::make_unique<std::byte[]>(DeviceGlobalTSize);
449 MDeviceGlobalUnregisteredData.insert({Key, std::move(NewData)}).first;
451 std::byte *ValuePtr = UnregisteredDataIt->second.get();
452 std::memcpy(ValuePtr + Offset, Src, NumBytes);
456 const std::shared_ptr<device_impl> &DeviceImpl,
void *Dest,
457 const void *DeviceGlobalPtr,
bool IsDeviceImageScoped,
size_t NumBytes,
460 std::optional<ur_device_handle_t> KeyDevice = std::nullopt;
461 if (IsDeviceImageScoped)
462 KeyDevice = DeviceImpl->getHandleRef();
463 auto Key = std::make_pair(DeviceGlobalPtr, KeyDevice);
465 std::lock_guard<std::mutex> InitLock(MDeviceGlobalUnregisteredDataMutex);
467 auto UnregisteredDataIt = MDeviceGlobalUnregisteredData.find(Key);
468 if (UnregisteredDataIt == MDeviceGlobalUnregisteredData.end()) {
471 char *FillableDest =
reinterpret_cast<char *
>(Dest);
472 std::fill(FillableDest, FillableDest + NumBytes, 0);
475 std::byte *ValuePtr = UnregisteredDataIt->second.get();
476 std::memcpy(Dest, ValuePtr + Offset, NumBytes);
480 const device &Device,
const std::set<std::uintptr_t> &ImgIdentifiers,
481 const std::string &ObjectTypeName) {
486 auto &KeyMap = LockedCache.get().KeyMap;
487 auto &Cache = LockedCache.get().Cache;
488 ur_device_handle_t &DevHandle =
getSyclObjImpl(Device)->getHandleRef();
489 for (std::uintptr_t ImageIDs : ImgIdentifiers) {
490 auto OuterKey = std::make_pair(ImageIDs, DevHandle);
491 size_t NProgs = KeyMap.count(OuterKey);
497 if (NProgs > 1 || (BuildRes && NProgs == 1))
499 "More than one image exists with the " +
500 ObjectTypeName +
".");
502 auto KeyMappingsIt = KeyMap.find(OuterKey);
503 assert(KeyMappingsIt != KeyMap.end());
504 auto CachedProgIt = Cache.find(KeyMappingsIt->second);
505 assert(CachedProgIt != Cache.end());
506 BuildRes = CachedProgIt->second;
512 BuildState NewState = BuildRes->waitUntilTransition();
513 if (NewState == BuildState::BS_Failed)
516 BuildRes->Error.Code);
518 assert(NewState == BuildState::BS_Done);
519 return BuildRes->Val;
528 std::optional<ur_program_handle_t>
532 std::set<std::uintptr_t> ImgIdentifiers;
std::shared_ptr< ProgramBuildResult > ProgramBuildResultPtr
Locked< ProgramCache > acquireCachedPrograms()
BuildState
Denotes the state of a build.
void setContextPtr(const ContextPtr &AContext)
static ProgramManager & getInstance()
DeviceGlobalMapEntry * getDeviceGlobalEntry(const void *DeviceGlobalPtr)
std::vector< DeviceGlobalMapEntry * > getDeviceGlobalEntries(const std::vector< std::string > &UniqueIds, bool ExcludeDeviceImageScopeDecorated=false)
std::uintptr_t getImageID() const
bool hasDevice(std::shared_ptr< detail::device_impl > Device) const
Returns true if and only if context contains the given device.
ur_context_handle_t & getHandleRef()
Gets the underlying context object (if any) without reference count modification.
context_impl(const device &Device, async_handler AsyncHandler, const property_list &PropList)
Constructs a context_impl using a single SYCL devices.
std::optional< ur_program_handle_t > getProgramForDevImgs(const device &Device, const std::set< std::uintptr_t > &ImgIdentifiers, const std::string &ObjectTypeName)
Gets a program associated with Dev / Images pairs.
KernelProgramCache & getKernelProgramCache() const
void addDeviceGlobalInitializer(ur_program_handle_t Program, const std::vector< device > &Devs, const RTDeviceBinaryImage *BinImage)
Adds a device global initializer.
bool isBufferLocationSupported() const
void addAssociatedDeviceGlobal(const void *DeviceGlobalPtr)
Adds an associated device global to the tracked associates.
DeviceImplPtr findMatchingDeviceImpl(ur_device_handle_t &DeviceUR) const
Given a UR device, returns the matching shared_ptr<device_impl> within this context.
std::vector< ur_event_handle_t > initializeDeviceGlobals(ur_program_handle_t NativePrg, const std::shared_ptr< queue_impl > &QueueImpl)
Initializes device globals for a program on the associated queue.
void memcpyFromHostOnlyDeviceGlobal(const std::shared_ptr< device_impl > &DeviceImpl, void *Dest, const void *DeviceGlobalPtr, bool IsDeviceImageScoped, size_t NumBytes, size_t Offset)
std::optional< ur_program_handle_t > getProgramForHostPipe(const device &Device, HostPipeMapEntry *HostPipeEntry)
Gets a program associated with a HostPipe Entry from the cache.
void memcpyToHostOnlyDeviceGlobal(const std::shared_ptr< device_impl > &DeviceImpl, const void *DeviceGlobalPtr, const void *Src, size_t DeviceGlobalTSize, bool IsDeviceImageScoped, size_t NumBytes, size_t Offset)
backend getBackend() const
const PluginPtr & getPlugin() const
ur_native_handle_t getNative() const
Gets the native handle of the SYCL context.
cl_context get() const
Gets OpenCL interoperability context handle.
const async_handler & get_async_handler() const
Gets asynchronous exception handler.
std::optional< ur_program_handle_t > getProgramForDeviceGlobal(const device &Device, DeviceGlobalMapEntry *DeviceGlobalEntry)
Gets a program associated with a device global from the cache.
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
detail::is_device_info_desc< Param >::return_type get_info() const
Queries this SYCL device for information requested by the template parameter param.
Objects of the property_list class are containers for the SYCL properties.
#define __SYCL_REPORT_EXCEPTION_TO_STREAM(str, e)
decltype(Obj::impl) const & getSyclObjImpl(const Obj &SyclObject)
static const PluginPtr & getPlugin(backend Backend)
std::function< int(const sycl::device &)> DSelectorInvocableType
device select_device(const DSelectorInvocableType &DeviceSelectorInvocable)
void GetCapabilitiesIntersectionSet(const std::vector< sycl::device > &Devices, std::vector< T > &CapabilityList)
std::shared_ptr< plugin > PluginPtr
std::shared_ptr< device_impl > DeviceImplPtr
exception set_ur_error(exception &&e, int32_t ur_err)
void fill(sycl::handler &CGH, T *Ptr, const T &Pattern, size_t Count)
int default_selector_v(const device &dev)
std::function< void(sycl::exception_list)> async_handler
std::error_code make_error_code(sycl::errc E) noexcept
Constructs an error code using e and sycl_category()
std::set< std::uintptr_t > MImageIdentifiers
void removeAssociatedResources(const context_impl *CtxImpl)
OwnedUrEvent getInitEvent(const PluginPtr &Plugin)
void *const & getPtr() const noexcept
RTDeviceBinaryImage * getDevBinImage()
C++ utilities for Unified Runtime integration.