DPC++ Runtime
Runtime libraries for oneAPI DPC++
context_impl.cpp
Go to the documentation of this file.
1 //==---------------- context_impl.cpp - SYCL context -----------*- C++ -*---==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 // ===--------------------------------------------------------------------=== //
8 
10 #include <detail/context_info.hpp>
11 #include <detail/event_info.hpp>
12 #include <detail/platform_impl.hpp>
13 #include <detail/queue_impl.hpp>
14 #include <sycl/detail/common.hpp>
16 #include <sycl/detail/pi.hpp>
17 #include <sycl/device.hpp>
18 #include <sycl/exception.hpp>
19 #include <sycl/exception_list.hpp>
20 #include <sycl/info/info_desc.hpp>
21 #include <sycl/platform.hpp>
23 #include <sycl/property_list.hpp>
24 
25 #include <algorithm>
26 
27 namespace sycl {
28 inline namespace _V1 {
29 namespace detail {
30 
31 context_impl::context_impl(const device &Device, async_handler AsyncHandler,
32  const property_list &PropList)
33  : MOwnedByRuntime(true), MAsyncHandler(AsyncHandler), MDevices(1, Device),
34  MContext(nullptr),
35  MPlatform(detail::getSyclObjImpl(Device.get_platform())),
36  MPropList(PropList),
37  MHostContext(detail::getSyclObjImpl(Device)->is_host()),
38  MSupportBufferLocationByDevices(NotChecked) {
39  MKernelProgramCache.setContextPtr(this);
40 }
41 
42 context_impl::context_impl(const std::vector<sycl::device> Devices,
43  async_handler AsyncHandler,
44  const property_list &PropList)
45  : MOwnedByRuntime(true), MAsyncHandler(AsyncHandler), MDevices(Devices),
46  MContext(nullptr), MPlatform(), MPropList(PropList), MHostContext(false),
47  MSupportBufferLocationByDevices(NotChecked) {
48  MPlatform = detail::getSyclObjImpl(MDevices[0].get_platform());
49  std::vector<sycl::detail::pi::PiDevice> DeviceIds;
50  for (const auto &D : MDevices) {
51  if (D.has(aspect::ext_oneapi_is_composite)) {
52  // Component devices are considered to be descendent devices from a
53  // composite device and therefore context created for a composite
54  // device should also work for a component device.
55  // In order to achieve that, we implicitly add all component devices to
56  // the list if a composite device was passed by user to us.
57  std::vector<device> ComponentDevices = D.get_info<
58  ext::oneapi::experimental::info::device::component_devices>();
59  for (const auto &CD : ComponentDevices)
60  DeviceIds.push_back(getSyclObjImpl(CD)->getHandleRef());
61  }
62 
63  DeviceIds.push_back(getSyclObjImpl(D)->getHandleRef());
64  }
65 
67  const bool UseCUDAPrimaryContext = MPropList.has_property<
68  ext::oneapi::cuda::property::context::use_primary_context>();
69  const pi_context_properties Props[] = {
70  static_cast<pi_context_properties>(
72  static_cast<pi_context_properties>(UseCUDAPrimaryContext), 0};
73 
75  Props, DeviceIds.size(), DeviceIds.data(), nullptr, nullptr, &MContext);
76  } else {
77  getPlugin()->call<PiApiKind::piContextCreate>(nullptr, DeviceIds.size(),
78  DeviceIds.data(), nullptr,
79  nullptr, &MContext);
80  }
81 
82  MKernelProgramCache.setContextPtr(this);
83 }
84 
86  async_handler AsyncHandler, const PluginPtr &Plugin,
87  const std::vector<sycl::device> &DeviceList,
88  bool OwnedByRuntime)
89  : MOwnedByRuntime(OwnedByRuntime), MAsyncHandler(AsyncHandler),
90  MDevices(DeviceList), MContext(PiContext), MPlatform(),
91  MHostContext(false), MSupportBufferLocationByDevices(NotChecked) {
92  if (!MDevices.empty()) {
93  MPlatform = detail::getSyclObjImpl(MDevices[0].get_platform());
94  } else {
95  std::vector<sycl::detail::pi::PiDevice> DeviceIds;
96  uint32_t DevicesNum = 0;
97  // TODO catch an exception and put it to list of asynchronous exceptions
98  Plugin->call<PiApiKind::piContextGetInfo>(
99  MContext, PI_CONTEXT_INFO_NUM_DEVICES, sizeof(DevicesNum), &DevicesNum,
100  nullptr);
101  DeviceIds.resize(DevicesNum);
102  // TODO catch an exception and put it to list of asynchronous exceptions
103  Plugin->call<PiApiKind::piContextGetInfo>(
104  MContext, PI_CONTEXT_INFO_DEVICES,
105  sizeof(sycl::detail::pi::PiDevice) * DevicesNum, &DeviceIds[0],
106  nullptr);
107 
108  if (!DeviceIds.empty()) {
109  std::shared_ptr<detail::platform_impl> Platform =
110  platform_impl::getPlatformFromPiDevice(DeviceIds[0], Plugin);
111  for (sycl::detail::pi::PiDevice Dev : DeviceIds) {
112  MDevices.emplace_back(createSyclObjFromImpl<device>(
113  Platform->getOrMakeDeviceImpl(Dev, Platform)));
114  }
115  MPlatform = Platform;
116  } else {
117  throw invalid_parameter_error(
118  "No devices in the provided device list and native context.",
119  PI_ERROR_INVALID_VALUE);
120  }
121  }
122  // TODO catch an exception and put it to list of asynchronous exceptions
123  // getPlugin() will be the same as the Plugin passed. This should be taken
124  // care of when creating device object.
125  //
126  // TODO: Move this backend-specific retain of the context to SYCL-2020 style
127  // make_context<backend::opencl> interop, when that is created.
128  if (getBackend() == sycl::backend::opencl) {
129  getPlugin()->call<PiApiKind::piContextRetain>(MContext);
130  }
131  MKernelProgramCache.setContextPtr(this);
132 }
133 
134 cl_context context_impl::get() const {
135  if (MHostContext) {
136  throw invalid_object_error(
137  "This instance of context doesn't support OpenCL interoperability.",
138  PI_ERROR_INVALID_CONTEXT);
139  }
140  // TODO catch an exception and put it to list of asynchronous exceptions
141  getPlugin()->call<PiApiKind::piContextRetain>(MContext);
142  return pi::cast<cl_context>(MContext);
143 }
144 
145 bool context_impl::is_host() const { return MHostContext; }
146 
148  // Free all events associated with the initialization of device globals.
149  for (auto &DeviceGlobalInitializer : MDeviceGlobalInitializers)
150  DeviceGlobalInitializer.second.ClearEvents(getPlugin());
151  // Free all device_global USM allocations associated with this context.
152  for (const void *DeviceGlobal : MAssociatedDeviceGlobals) {
153  DeviceGlobalMapEntry *DGEntry =
155  DeviceGlobal);
156  DGEntry->removeAssociatedResources(this);
157  }
158  for (auto LibProg : MCachedLibPrograms) {
159  assert(LibProg.second && "Null program must not be kept in the cache");
160  getPlugin()->call<PiApiKind::piProgramRelease>(LibProg.second);
161  }
162  if (!MHostContext) {
163  // TODO catch an exception and put it to list of asynchronous exceptions
164  getPlugin()->call_nocheck<PiApiKind::piContextRelease>(MContext);
165  }
166 }
167 
169  return MAsyncHandler;
170 }
171 
172 template <>
173 uint32_t context_impl::get_info<info::context::reference_count>() const {
174  if (is_host())
175  return 0;
176  return get_context_info<info::context::reference_count>(this->getHandleRef(),
177  this->getPlugin());
178 }
179 template <> platform context_impl::get_info<info::context::platform>() const {
180  if (is_host())
181  return createSyclObjFromImpl<platform>(
183  return createSyclObjFromImpl<platform>(MPlatform);
184 }
185 template <>
186 std::vector<sycl::device>
187 context_impl::get_info<info::context::devices>() const {
188  return MDevices;
189 }
190 template <>
191 std::vector<sycl::memory_order>
192 context_impl::get_info<info::context::atomic_memory_order_capabilities>()
193  const {
194  std::vector<sycl::memory_order> CapabilityList{
195  sycl::memory_order::relaxed, sycl::memory_order::acquire,
196  sycl::memory_order::release, sycl::memory_order::acq_rel,
197  sycl::memory_order::seq_cst};
198  if (is_host())
199  return CapabilityList;
200 
202  sycl::memory_order, info::device::atomic_memory_order_capabilities>(
203  MDevices, CapabilityList);
204 
205  return CapabilityList;
206 }
207 template <>
208 std::vector<sycl::memory_scope>
209 context_impl::get_info<info::context::atomic_memory_scope_capabilities>()
210  const {
211  std::vector<sycl::memory_scope> CapabilityList{
212  sycl::memory_scope::work_item, sycl::memory_scope::sub_group,
213  sycl::memory_scope::work_group, sycl::memory_scope::device,
214  sycl::memory_scope::system};
215  if (is_host())
216  return CapabilityList;
217 
219  sycl::memory_scope, info::device::atomic_memory_scope_capabilities>(
220  MDevices, CapabilityList);
221 
222  return CapabilityList;
223 }
224 template <>
225 std::vector<sycl::memory_order>
226 context_impl::get_info<info::context::atomic_fence_order_capabilities>() const {
227  std::vector<sycl::memory_order> CapabilityList{
228  sycl::memory_order::relaxed, sycl::memory_order::acquire,
229  sycl::memory_order::release, sycl::memory_order::acq_rel,
230  sycl::memory_order::seq_cst};
231  if (is_host())
232  return CapabilityList;
233 
235  info::device::atomic_fence_order_capabilities>(
236  MDevices, CapabilityList);
237 
238  return CapabilityList;
239 }
240 template <>
241 std::vector<sycl::memory_scope>
242 context_impl::get_info<info::context::atomic_fence_scope_capabilities>() const {
243  std::vector<sycl::memory_scope> CapabilityList{
244  sycl::memory_scope::work_item, sycl::memory_scope::sub_group,
245  sycl::memory_scope::work_group, sycl::memory_scope::device,
246  sycl::memory_scope::system};
247  if (is_host())
248  return CapabilityList;
249 
251  info::device::atomic_fence_scope_capabilities>(
252  MDevices, CapabilityList);
253 
254  return CapabilityList;
255 }
256 
257 template <>
258 typename info::platform::version::return_type
259 context_impl::get_backend_info<info::platform::version>() const {
260  if (getBackend() != backend::opencl) {
262  "the info::platform::version info descriptor can "
263  "only be queried with an OpenCL backend");
264  }
265  return MDevices[0].get_platform().get_info<info::platform::version>();
266 }
267 
268 device select_device(DSelectorInvocableType DeviceSelectorInvocable,
269  std::vector<device> &Devices);
270 
271 template <>
272 typename info::device::version::return_type
273 context_impl::get_backend_info<info::device::version>() const {
274  if (getBackend() != backend::opencl) {
276  "the info::device::version info descriptor can only "
277  "be queried with an OpenCL backend");
278  }
279  auto Devices = get_info<info::context::devices>();
280  if (Devices.empty()) {
281  return "No available device";
282  }
283  // Use default selector to pick a device.
284  return select_device(default_selector_v, Devices)
285  .get_info<info::device::version>();
286 }
287 
288 template <>
289 typename info::device::backend_version::return_type
290 context_impl::get_backend_info<info::device::backend_version>() const {
291  if (getBackend() != backend::ext_oneapi_level_zero) {
293  "the info::device::backend_version info descriptor "
294  "can only be queried with a Level Zero backend");
295  }
296  return "";
297  // Currently The Level Zero backend does not define the value of this
298  // information descriptor and implementations are encouraged to return the
299  // empty string as per specification.
300 }
301 
304  return MContext;
305 }
306 
308  return MKernelProgramCache;
309 }
310 
312  std::shared_ptr<detail::device_impl> Device) const {
313  for (auto D : MDevices)
314  if (getSyclObjImpl(D) == Device)
315  return true;
316  return false;
317 }
318 
320  sycl::detail::pi::PiDevice &DevicePI) const {
321  for (device D : MDevices)
322  if (getSyclObjImpl(D)->getHandleRef() == DevicePI)
323  return getSyclObjImpl(D);
324 
325  return nullptr;
326 }
327 
329  const auto &Plugin = getPlugin();
330  if (getBackend() == backend::opencl)
331  Plugin->call<PiApiKind::piContextRetain>(getHandleRef());
332  pi_native_handle Handle;
333  Plugin->call<PiApiKind::piextContextGetNativeHandle>(getHandleRef(), &Handle);
334  return Handle;
335 }
336 
338  if (MSupportBufferLocationByDevices != NotChecked)
339  return MSupportBufferLocationByDevices == Supported ? true : false;
340  // Check that devices within context have support of buffer location
341  MSupportBufferLocationByDevices = Supported;
342  for (auto &Device : MDevices) {
343  if (!Device.has_extension("cl_intel_mem_alloc_buffer_location")) {
344  MSupportBufferLocationByDevices = NotSupported;
345  break;
346  }
347  }
348  return MSupportBufferLocationByDevices == Supported ? true : false;
349 }
350 
351 void context_impl::addAssociatedDeviceGlobal(const void *DeviceGlobalPtr) {
352  std::lock_guard<std::mutex> Lock{MAssociatedDeviceGlobalsMutex};
353  MAssociatedDeviceGlobals.insert(DeviceGlobalPtr);
354 }
355 
357  sycl::detail::pi::PiProgram Program, const std::vector<device> &Devs,
358  const RTDeviceBinaryImage *BinImage) {
359  std::lock_guard<std::mutex> Lock(MDeviceGlobalInitializersMutex);
360  for (const device &Dev : Devs) {
361  auto Key = std::make_pair(Program, getSyclObjImpl(Dev)->getHandleRef());
362  MDeviceGlobalInitializers.emplace(Key, BinImage);
363  }
364 }
365 
366 std::vector<sycl::detail::pi::PiEvent> context_impl::initializeDeviceGlobals(
367  pi::PiProgram NativePrg, const std::shared_ptr<queue_impl> &QueueImpl) {
368  const PluginPtr &Plugin = getPlugin();
369  const DeviceImplPtr &DeviceImpl = QueueImpl->getDeviceImplPtr();
370  std::lock_guard<std::mutex> NativeProgramLock(MDeviceGlobalInitializersMutex);
371  auto ImgIt = MDeviceGlobalInitializers.find(
372  std::make_pair(NativePrg, DeviceImpl->getHandleRef()));
373  if (ImgIt == MDeviceGlobalInitializers.end() ||
374  ImgIt->second.MDeviceGlobalsFullyInitialized)
375  return {};
376 
377  DeviceGlobalInitializer &InitRef = ImgIt->second;
378  {
379  std::lock_guard<std::mutex> InitLock(InitRef.MDeviceGlobalInitMutex);
380  std::vector<sycl::detail::pi::PiEvent> &InitEventsRef =
381  InitRef.MDeviceGlobalInitEvents;
382  if (!InitEventsRef.empty()) {
383  // Initialization has begun but we do not know if the events are done.
384  auto NewEnd = std::remove_if(
385  InitEventsRef.begin(), InitEventsRef.end(),
386  [&Plugin](const sycl::detail::pi::PiEvent &Event) {
387  return get_event_info<info::event::command_execution_status>(
388  Event, Plugin) == info::event_command_status::complete;
389  });
390  // Release the removed events.
391  for (auto EventIt = NewEnd; EventIt != InitEventsRef.end(); ++EventIt)
392  Plugin->call<PiApiKind::piEventRelease>(*EventIt);
393  // Remove them from the collection.
394  InitEventsRef.erase(NewEnd, InitEventsRef.end());
395  // If there are no more events, we can mark it as fully initialized.
396  if (InitEventsRef.empty())
397  InitRef.MDeviceGlobalsFullyInitialized = true;
398  return InitEventsRef;
399  } else if (InitRef.MDeviceGlobalsFullyInitialized) {
400  // MDeviceGlobalsFullyInitialized could have been set while we were
401  // waiting on the lock and since there were no init events we are done.
402  return {};
403  }
404 
405  // There were no events and it was not set as fully initialized, so this is
406  // responsible for intializing the device globals.
407  auto DeviceGlobals = InitRef.MBinImage->getDeviceGlobals();
408  std::vector<std::string> DeviceGlobalIds;
409  DeviceGlobalIds.reserve(DeviceGlobals.size());
410  for (const pi_device_binary_property &DeviceGlobal : DeviceGlobals)
411  DeviceGlobalIds.push_back(DeviceGlobal->Name);
412  std::vector<DeviceGlobalMapEntry *> DeviceGlobalEntries =
414  DeviceGlobalIds,
415  /*ExcludeDeviceImageScopeDecorated=*/true);
416 
417  // If there were no device globals without device_image_scope the device
418  // globals are trivially fully initialized and we can end early.
419  if (DeviceGlobalEntries.empty()) {
420  InitRef.MDeviceGlobalsFullyInitialized = true;
421  return {};
422  }
423 
424  // We may have reserved too much for DeviceGlobalEntries, but now that we
425  // know number of device globals to initialize, we can use that for the
426  // list.
427  InitEventsRef.reserve(DeviceGlobalEntries.size());
428 
429  // Device global map entry pointers will not die before the end of the
430  // program and the pointers will stay the same, so we do not need
431  // m_DeviceGlobalsMutex here.
432  for (DeviceGlobalMapEntry *DeviceGlobalEntry : DeviceGlobalEntries) {
433  // Get or allocate the USM memory associated with the device global.
434  DeviceGlobalUSMMem &DeviceGlobalUSM =
435  DeviceGlobalEntry->getOrAllocateDeviceGlobalUSM(QueueImpl);
436 
437  // If the device global still has a initialization event it should be
438  // added to the initialization events list. Since initialization events
439  // are cleaned up separately from cleaning up the device global USM memory
440  // this must retain the event.
441  {
442  if (OwnedPiEvent ZIEvent = DeviceGlobalUSM.getInitEvent(Plugin))
443  InitEventsRef.push_back(ZIEvent.TransferOwnership());
444  }
445  // Write the pointer to the device global and store the event in the
446  // initialize events list.
447  sycl::detail::pi::PiEvent InitEvent;
448  void *const &USMPtr = DeviceGlobalUSM.getPtr();
450  QueueImpl->getHandleRef(), NativePrg,
451  DeviceGlobalEntry->MUniqueId.c_str(), false, sizeof(void *), 0,
452  &USMPtr, 0, nullptr, &InitEvent);
453 
454  InitEventsRef.push_back(InitEvent);
455  }
456  return InitEventsRef;
457  }
458 }
459 
460 void context_impl::DeviceGlobalInitializer::ClearEvents(
461  const PluginPtr &Plugin) {
462  for (const sycl::detail::pi::PiEvent &Event : MDeviceGlobalInitEvents)
463  Plugin->call<PiApiKind::piEventRelease>(Event);
464  MDeviceGlobalInitEvents.clear();
465 }
466 
468  const std::shared_ptr<device_impl> &DeviceImpl, const void *DeviceGlobalPtr,
469  const void *Src, size_t DeviceGlobalTSize, bool IsDeviceImageScoped,
470  size_t NumBytes, size_t Offset) {
471  std::optional<sycl::detail::pi::PiDevice> KeyDevice = std::nullopt;
472  if (IsDeviceImageScoped)
473  KeyDevice = DeviceImpl->getHandleRef();
474  auto Key = std::make_pair(DeviceGlobalPtr, KeyDevice);
475 
476  std::lock_guard<std::mutex> InitLock(MDeviceGlobalUnregisteredDataMutex);
477 
478  auto UnregisteredDataIt = MDeviceGlobalUnregisteredData.find(Key);
479  if (UnregisteredDataIt == MDeviceGlobalUnregisteredData.end()) {
480  std::unique_ptr<std::byte[]> NewData =
481  std::make_unique<std::byte[]>(DeviceGlobalTSize);
482  UnregisteredDataIt =
483  MDeviceGlobalUnregisteredData.insert({Key, std::move(NewData)}).first;
484  }
485  std::byte *ValuePtr = UnregisteredDataIt->second.get();
486  std::memcpy(ValuePtr + Offset, Src, NumBytes);
487 }
488 
490  const std::shared_ptr<device_impl> &DeviceImpl, void *Dest,
491  const void *DeviceGlobalPtr, bool IsDeviceImageScoped, size_t NumBytes,
492  size_t Offset) {
493 
494  std::optional<sycl::detail::pi::PiDevice> KeyDevice = std::nullopt;
495  if (IsDeviceImageScoped)
496  KeyDevice = DeviceImpl->getHandleRef();
497  auto Key = std::make_pair(DeviceGlobalPtr, KeyDevice);
498 
499  std::lock_guard<std::mutex> InitLock(MDeviceGlobalUnregisteredDataMutex);
500 
501  auto UnregisteredDataIt = MDeviceGlobalUnregisteredData.find(Key);
502  if (UnregisteredDataIt == MDeviceGlobalUnregisteredData.end()) {
503  // If there is no entry we do not need to add it as it would just be
504  // zero-initialized.
505  char *FillableDest = reinterpret_cast<char *>(Dest);
506  std::fill(FillableDest, FillableDest + NumBytes, 0);
507  return;
508  }
509  std::byte *ValuePtr = UnregisteredDataIt->second.get();
510  std::memcpy(Dest, ValuePtr + Offset, NumBytes);
511 }
512 
513 std::optional<sycl::detail::pi::PiProgram> context_impl::getProgramForDevImgs(
514  const device &Device, const std::set<std::uintptr_t> &ImgIdentifiers,
515  const std::string &ObjectTypeName) {
516 
518  {
519  auto LockedCache = MKernelProgramCache.acquireCachedPrograms();
520  auto &KeyMap = LockedCache.get().KeyMap;
521  auto &Cache = LockedCache.get().Cache;
522  sycl::detail::pi::PiDevice &DevHandle =
523  getSyclObjImpl(Device)->getHandleRef();
524  for (std::uintptr_t ImageIDs : ImgIdentifiers) {
525  auto OuterKey = std::make_pair(ImageIDs, DevHandle);
526  size_t NProgs = KeyMap.count(OuterKey);
527  if (NProgs == 0)
528  continue;
529  // If the cache has multiple programs for the identifiers or if we have
530  // already found a program in the cache with the device_global or host
531  // pipe we cannot proceed.
532  if (NProgs > 1 || (BuildRes && NProgs == 1))
534  "More than one image exists with the " +
535  ObjectTypeName + ".");
536 
537  auto KeyMappingsIt = KeyMap.find(OuterKey);
538  assert(KeyMappingsIt != KeyMap.end());
539  auto CachedProgIt = Cache.find(KeyMappingsIt->second);
540  assert(CachedProgIt != Cache.end());
541  BuildRes = CachedProgIt->second;
542  }
543  }
544  if (!BuildRes)
545  return std::nullopt;
546  using BuildState = KernelProgramCache::BuildState;
547  BuildState NewState = BuildRes->waitUntilTransition();
548  if (NewState == BuildState::BS_Failed)
549  throw compile_program_error(BuildRes->Error.Msg, BuildRes->Error.Code);
550 
551  assert(NewState == BuildState::BS_Done);
552  return BuildRes->Val;
553 }
554 
555 std::optional<sycl::detail::pi::PiProgram>
557  const device &Device, DeviceGlobalMapEntry *DeviceGlobalEntry) {
558  return getProgramForDevImgs(Device, DeviceGlobalEntry->MImageIdentifiers,
559  "device_global");
560 }
562 std::optional<sycl::detail::pi::PiProgram>
564  HostPipeMapEntry *HostPipeEntry) {
565  // One HostPipe entry belongs to one Img
566  std::set<std::uintptr_t> ImgIdentifiers;
567  ImgIdentifiers.insert(HostPipeEntry->getDevBinImage()->getImageID());
568  return getProgramForDevImgs(Device, ImgIdentifiers, "host_pipe");
569 }
570 
571 } // namespace detail
572 } // namespace _V1
573 } // namespace sycl
std::shared_ptr< ProgramBuildResult > ProgramBuildResultPtr
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)
bool hasDevice(std::shared_ptr< detail::device_impl > Device) const
Returns true if and only if context contains the given device.
context_impl(const device &Device, async_handler AsyncHandler, const property_list &PropList)
Constructs a context_impl using a single SYCL devices.
KernelProgramCache & getKernelProgramCache() const
void addDeviceGlobalInitializer(sycl::detail::pi::PiProgram Program, const std::vector< device > &Devs, const RTDeviceBinaryImage *BinImage)
Adds a device global initializer.
pi_native_handle getNative() const
Gets the native handle of the SYCL context.
void addAssociatedDeviceGlobal(const void *DeviceGlobalPtr)
Adds an associated device global to the tracked associates.
std::optional< sycl::detail::pi::PiProgram > getProgramForDeviceGlobal(const device &Device, DeviceGlobalMapEntry *DeviceGlobalEntry)
Gets a program associated with a device global from the cache.
std::optional< sycl::detail::pi::PiProgram > getProgramForDevImgs(const device &Device, const std::set< std::uintptr_t > &ImgIdentifiers, const std::string &ObjectTypeName)
Gets a program associated with Dev / Images pairs.
void memcpyFromHostOnlyDeviceGlobal(const std::shared_ptr< device_impl > &DeviceImpl, void *Dest, const void *DeviceGlobalPtr, bool IsDeviceImageScoped, size_t NumBytes, size_t Offset)
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)
std::vector< sycl::detail::pi::PiEvent > initializeDeviceGlobals(pi::PiProgram NativePrg, const std::shared_ptr< queue_impl > &QueueImpl)
Initializes device globals for a program on the associated queue.
std::optional< sycl::detail::pi::PiProgram > getProgramForHostPipe(const device &Device, HostPipeMapEntry *HostPipeEntry)
Gets a program associated with a HostPipe Entry from the cache.
const PluginPtr & getPlugin() const
bool is_host() const
Checks if this context is a host context.
cl_context get() const
Gets OpenCL interoperability context handle.
const async_handler & get_async_handler() const
Gets asynchronous exception handler.
DeviceImplPtr findMatchingDeviceImpl(sycl::detail::pi::PiDevice &DevicePI) const
Given a PiDevice, returns the matching shared_ptr<device_impl> within this context.
sycl::detail::pi::PiContext & getHandleRef()
Gets the underlying context object (if any) without reference count modification.
static std::shared_ptr< platform_impl > getHostPlatformImpl()
Static functions that help maintain platform uniquess and equality of comparison.
static std::shared_ptr< platform_impl > getPlatformFromPiDevice(sycl::detail::pi::PiDevice PiDevice, const PluginPtr &Plugin)
Queries the cache for the specified platform based on an input device.
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:64
detail::is_device_info_desc< Param >::return_type get_info() const
Queries this SYCL device for information requested by the template parameter param.
Definition: device.hpp:223
Encapsulates a SYCL platform on which kernels may be executed.
Definition: platform.hpp:99
Objects of the property_list class are containers for the SYCL properties.
bool has_property() const noexcept
#define __SYCL_PI_CONTEXT_PROPERTIES_CUDA_PRIMARY
class __SYCL2020_DEPRECATED("Host device is no longer supported.") host_selector int default_selector_v(const device &dev)
Selects SYCL host device.
::pi_device PiDevice
Definition: pi.hpp:131
::pi_context PiContext
Definition: pi.hpp:135
static const PluginPtr & getPlugin(backend Backend)
Definition: backend.cpp:32
decltype(Obj::impl) getSyclObjImpl(const Obj &SyclObject)
Definition: impl_utils.hpp:30
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
Definition: pi.hpp:48
std::shared_ptr< device_impl > DeviceImplPtr
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()
Definition: exception.cpp:87
Definition: access.hpp:18
static sycl::event fill(sycl::queue q, void *dev_ptr, const T &pattern, size_t count)
Set pattern to the first count elements of type T starting from dev_ptr.
Definition: memory.hpp:185
uintptr_t pi_native_handle
Definition: pi.h:217
pi_result piProgramRelease(pi_program program)
Definition: pi_cuda.cpp:324
pi_result piextEnqueueDeviceGlobalVariableWrite(pi_queue queue, pi_program program, const char *name, pi_bool blocking_write, size_t count, size_t offset, const void *src, pi_uint32 num_events_in_wait_list, const pi_event *event_wait_list, pi_event *event)
Device global variable.
Definition: pi_cuda.cpp:993
pi_result piContextRetain(pi_context context)
Definition: pi_cuda.cpp:152
intptr_t pi_context_properties
Definition: pi.h:716
pi_result piContextCreate(const pi_context_properties *properties, pi_uint32 num_devices, const pi_device *devices, void(*pfn_notify)(const char *errinfo, const void *private_info, size_t cb, void *user_data), void *user_data, pi_context *ret_context)
pi_result piextContextGetNativeHandle(pi_context context, pi_native_handle *nativeHandle)
Gets the native handle of a PI context object.
Definition: pi_cuda.cpp:138
@ PI_CONTEXT_INFO_NUM_DEVICES
Definition: pi.h:482
@ PI_CONTEXT_INFO_DEVICES
Definition: pi.h:480
pi_result piEventRelease(pi_event event)
Definition: pi_cuda.cpp:617
pi_result piContextRelease(pi_context context)
Definition: pi_cuda.cpp:157
pi_result piContextGetInfo(pi_context context, pi_context_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret)
Definition: pi_cuda.cpp:124
C++ wrapper of extern "C" PI interfaces.
void removeAssociatedResources(const context_impl *CtxImpl)
OwnedPiEvent getInitEvent(const PluginPtr &Plugin)