DPC++ Runtime
Runtime libraries for oneAPI DPC++
buffer.hpp
Go to the documentation of this file.
1 //==----------- buffer.hpp --- SYCL buffer ---------------------------------==//
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 
9 #pragma once
10 
11 #include <sycl/detail/common.hpp>
14 #include <sycl/event.hpp>
15 #include <sycl/exception.hpp>
17 #include <sycl/property_list.hpp>
18 #include <sycl/range.hpp>
19 #include <sycl/stl.hpp>
20 
21 namespace sycl {
23 
24 class handler;
25 class queue;
26 template <int dimensions> class range;
27 
28 template <typename DataT>
30 
31 template <typename DataT, int Dimensions, access::mode AccessMode>
32 class host_accessor;
33 
34 template <typename T, int Dimensions, typename AllocatorT, typename Enable>
35 class buffer;
36 
37 namespace detail {
38 
39 class buffer_impl;
40 
41 template <typename T, int Dimensions, typename AllocatorT>
43 make_buffer_helper(pi_native_handle Handle, const context &Ctx, event Evt = {},
44  bool OwnNativeHandle = true) {
45  return buffer<T, Dimensions, AllocatorT, void>(Handle, Ctx, OwnNativeHandle,
46  Evt);
47 }
48 
49 template <backend BackendName, typename DataT, int Dimensions,
50  typename Allocator>
51 auto get_native_buffer(const buffer<DataT, Dimensions, Allocator, void> &Obj)
52  -> backend_return_t<BackendName,
53  buffer<DataT, Dimensions, Allocator, void>>;
54 
55 template <backend Backend, typename DataT, int Dimensions,
56  typename AllocatorT = buffer_allocator<std::remove_const_t<DataT>>>
57 struct BufferInterop;
58 
59 // The non-template base for the sycl::buffer class
60 class __SYCL_EXPORT buffer_plain {
61 protected:
62  buffer_plain(size_t SizeInBytes, size_t, const property_list &Props,
63  std::unique_ptr<detail::SYCLMemObjAllocator> Allocator);
64 
65  buffer_plain(void *HostData, size_t SizeInBytes, size_t RequiredAlign,
66  const property_list &Props,
67  std::unique_ptr<detail::SYCLMemObjAllocator> Allocator);
68 
69  buffer_plain(const void *HostData, size_t SizeInBytes, size_t RequiredAlign,
70  const property_list &Props,
71  std::unique_ptr<detail::SYCLMemObjAllocator> Allocator);
72 
73  buffer_plain(const std::shared_ptr<const void> &HostData,
74  const size_t SizeInBytes, size_t RequiredAlign,
75  const property_list &Props,
76  std::unique_ptr<detail::SYCLMemObjAllocator> Allocator,
77  bool IsConstPtr);
78 
79  buffer_plain(const std::function<void(void *)>
80  &CopyFromInput, // EnableIfNotConstIterator<InputIterator>
81  // First, InputIterator Last,
82  const size_t SizeInBytes, size_t RequiredAlign,
83  const property_list &Props,
84  std::unique_ptr<detail::SYCLMemObjAllocator> Allocator,
85  bool IsConstPtr);
86 
87  buffer_plain(pi_native_handle MemObject, context SyclContext,
88  std::unique_ptr<detail::SYCLMemObjAllocator> Allocator,
89  bool OwnNativeHandle, event AvailableEvent);
90 
91  buffer_plain(const std::shared_ptr<detail::buffer_impl> &impl) : impl(impl) {}
92 
93  void set_final_data_internal();
94 
95  void set_final_data_internal(
96  const std::function<void(const std::function<void(void *const Ptr)> &)>
97  &FinalDataFunc);
98 
99  void set_write_back(bool NeedWriteBack);
100 
102  void *UserObj, const void *HostObj,
103  const void *Type, uint32_t Dim,
104  uint32_t ElemType, size_t Range[3]);
105 
106  template <typename propertyT> bool has_property() const noexcept;
107 
108  template <typename propertyT> propertyT get_property() const;
109 
110  std::vector<pi_native_handle> getNativeVector(backend BackendName) const;
111 
112  const std::unique_ptr<SYCLMemObjAllocator> &get_allocator_internal() const;
113 
114  void deleteAccProps(const sycl::detail::PropWithDataKind &Kind);
115 
116  void addOrReplaceAccessorProperties(const property_list &PropertyList);
117 
118  size_t getSize() const;
119 
120  std::shared_ptr<detail::buffer_impl> impl;
121 };
122 
123 } // namespace detail
124 
133 template <typename T, int dimensions = 1,
134  typename AllocatorT = buffer_allocator<std::remove_const_t<T>>,
135  typename __Enabled = typename detail::enable_if_t<(dimensions > 0) &&
136  (dimensions <= 3)>>
137 class buffer : public detail::buffer_plain {
138  // TODO check is_device_copyable<T>::value after converting sycl::vec into a
139  // trivially copyable class.
140  static_assert(!std::is_same<T, std::string>::value,
141  "'std::string' is not a device copyable type");
142 
143 public:
144  using value_type = T;
146  using const_reference = const value_type &;
147  using allocator_type = AllocatorT;
148  template <int dims>
150  // using same requirement for contiguous container as std::span
151  template <class Container>
152  using EnableIfContiguous =
153  detail::void_t<detail::enable_if_t<std::is_convertible<
155  decltype(std::declval<Container>().data())> (*)[],
156  const T (*)[]>::value>,
157  decltype(std::declval<Container>().size())>;
158  template <class It>
160  std::is_convertible<typename std::iterator_traits<It>::iterator_category,
161  std::input_iterator_tag>::value>;
162  template <typename ItA, typename ItB>
164  std::is_same<ItA, ItB>::value && !std::is_const<ItA>::value, ItA>;
165 
166  std::array<size_t, 3> rangeToArray(range<3> &r) { return {r[0], r[1], r[2]}; }
167 
168  std::array<size_t, 3> rangeToArray(range<2> &r) { return {r[0], r[1], 0}; }
169 
170  std::array<size_t, 3> rangeToArray(range<1> &r) { return {r[0], 0, 0}; }
171 
172  buffer(const range<dimensions> &bufferRange,
173  const property_list &propList = {},
174  const detail::code_location CodeLoc = detail::code_location::current())
175  : buffer_plain(bufferRange.size() * sizeof(T),
176  detail::getNextPowerOfTwo(sizeof(T)), propList,
179  Range(bufferRange) {
181  CodeLoc, (void *)impl.get(), nullptr, (const void *)typeid(T).name(),
182  dimensions, sizeof(T), rangeToArray(Range).data());
183  }
184 
185  buffer(const range<dimensions> &bufferRange, AllocatorT allocator,
186  const property_list &propList = {},
187  const detail::code_location CodeLoc = detail::code_location::current())
188  : buffer_plain(
189  bufferRange.size() * sizeof(T),
190  detail::getNextPowerOfTwo(sizeof(T)), propList,
192  allocator)),
193  Range(bufferRange) {
195  CodeLoc, (void *)impl.get(), nullptr, (const void *)typeid(T).name(),
196  dimensions, sizeof(T), rangeToArray(Range).data());
197  }
198 
199  buffer(T *hostData, const range<dimensions> &bufferRange,
200  const property_list &propList = {},
201  const detail::code_location CodeLoc = detail::code_location::current())
202  : buffer_plain(hostData, bufferRange.size() * sizeof(T),
203  detail::getNextPowerOfTwo(sizeof(T)), propList,
206  Range(bufferRange) {
208  CodeLoc, (void *)impl.get(), hostData, (const void *)typeid(T).name(),
209  dimensions, sizeof(T), rangeToArray(Range).data());
210  }
211 
212  buffer(T *hostData, const range<dimensions> &bufferRange,
213  AllocatorT allocator, const property_list &propList = {},
214  const detail::code_location CodeLoc = detail::code_location::current())
215  : buffer_plain(
216  hostData, bufferRange.size() * sizeof(T),
217  detail::getNextPowerOfTwo(sizeof(T)), propList,
219  allocator)),
220  Range(bufferRange) {
222  CodeLoc, (void *)impl.get(), hostData, (const void *)typeid(T).name(),
223  dimensions, sizeof(T), rangeToArray(Range).data());
224  }
225 
226  template <typename _T = T>
228  const range<dimensions> &bufferRange,
229  const property_list &propList = {},
230  const detail::code_location CodeLoc = detail::code_location::current())
231  : buffer_plain(hostData, bufferRange.size() * sizeof(T),
232  detail::getNextPowerOfTwo(sizeof(T)), propList,
235  Range(bufferRange) {
237  CodeLoc, (void *)impl.get(), hostData, (const void *)typeid(T).name(),
238  dimensions, sizeof(T), rangeToArray(Range).data());
239  }
240 
241  template <typename _T = T>
243  const range<dimensions> &bufferRange, AllocatorT allocator,
244  const property_list &propList = {},
245  const detail::code_location CodeLoc = detail::code_location::current())
246  : buffer_plain(
247  bufferRange.size() * sizeof(T),
248  detail::getNextPowerOfTwo(sizeof(T)), propList,
250  allocator)),
251  Range(bufferRange) {
253  CodeLoc, (void *)impl.get(), hostData, (const void *)typeid(T).name(),
254  dimensions, sizeof(T), rangeToArray(Range).data());
255  }
256 
257  buffer(const std::shared_ptr<T> &hostData,
258  const range<dimensions> &bufferRange, AllocatorT allocator,
259  const property_list &propList = {},
260  const detail::code_location CodeLoc = detail::code_location::current())
261  : buffer_plain(
262  hostData, bufferRange.size() * sizeof(T),
263  detail::getNextPowerOfTwo(sizeof(T)), propList,
265  allocator),
266  std::is_const<T>::value),
267  Range(bufferRange) {
269  CodeLoc, (void *)impl.get(), (void *)hostData.get(),
270  (const void *)typeid(T).name(), dimensions, sizeof(T),
271  rangeToArray(Range).data());
272  }
273 
274  buffer(const std::shared_ptr<T[]> &hostData,
275  const range<dimensions> &bufferRange, AllocatorT allocator,
276  const property_list &propList = {},
277  const detail::code_location CodeLoc = detail::code_location::current())
278  : buffer_plain(
279  hostData, bufferRange.size() * sizeof(T),
280  detail::getNextPowerOfTwo(sizeof(T)), propList,
282  allocator),
283  std::is_const<T>::value),
284  Range(bufferRange) {
286  CodeLoc, (void *)impl.get(), (void *)hostData.get(),
287  (const void *)typeid(T).name(), dimensions, sizeof(T),
288  rangeToArray(Range).data());
289  }
290 
291  buffer(const std::shared_ptr<T> &hostData,
292  const range<dimensions> &bufferRange,
293  const property_list &propList = {},
294  const detail::code_location CodeLoc = detail::code_location::current())
295  : buffer_plain(
296  hostData, bufferRange.size() * sizeof(T),
297  detail::getNextPowerOfTwo(sizeof(T)), propList,
299  std::is_const<T>::value),
300  Range(bufferRange) {
302  CodeLoc, (void *)impl.get(), (void *)hostData.get(),
303  (const void *)typeid(T).name(), dimensions, sizeof(T),
304  rangeToArray(Range).data());
305  }
306 
307  buffer(const std::shared_ptr<T[]> &hostData,
308  const range<dimensions> &bufferRange,
309  const property_list &propList = {},
310  const detail::code_location CodeLoc = detail::code_location::current())
311  : buffer_plain(
312  hostData, bufferRange.size() * sizeof(T),
313  detail::getNextPowerOfTwo(sizeof(T)), propList,
315  std::is_const<T>::value),
316  Range(bufferRange) {
318  CodeLoc, (void *)impl.get(), (void *)hostData.get(),
319  (const void *)typeid(T).name(), dimensions, sizeof(T),
320  rangeToArray(Range).data());
321  }
322 
323  template <class InputIterator, int N = dimensions,
324  typename = EnableIfOneDimension<N>,
325  typename = EnableIfItInputIterator<InputIterator>>
326  buffer(InputIterator first, InputIterator last, AllocatorT allocator,
327  const property_list &propList = {},
328  const detail::code_location CodeLoc = detail::code_location::current())
329  : buffer_plain(
330  // The functor which will be used to initialize the data
331  [first, last](void *ToPtr) {
332  // We need to cast MUserPtr to pointer to the iteration type to
333  // get correct offset in std::copy when it will increment
334  // destination pointer.
335  using IteratorValueType =
337  using IteratorNonConstValueType =
339  using IteratorPointerToNonConstValueType =
341  std::copy(first, last,
342  static_cast<IteratorPointerToNonConstValueType>(ToPtr));
343  },
344  std::distance(first, last) * sizeof(T),
345  detail::getNextPowerOfTwo(sizeof(T)), propList,
346  make_unique_ptr<detail::SYCLMemObjAllocatorHolder<AllocatorT, T>>(
347  allocator),
348  detail::iterator_to_const_type_t<InputIterator>::value),
349  Range(range<1>(std::distance(first, last))) {
350  size_t r[3] = {Range[0], 0, 0};
351  buffer_plain::constructorNotification(CodeLoc, (void *)impl.get(), &first,
352  (const void *)typeid(T).name(),
353  dimensions, sizeof(T), r);
354  }
355 
356  template <class InputIterator, int N = dimensions,
357  typename = EnableIfOneDimension<N>,
358  typename = EnableIfItInputIterator<InputIterator>>
359  buffer(InputIterator first, InputIterator last,
360  const property_list &propList = {},
361  const detail::code_location CodeLoc = detail::code_location::current())
362  : buffer_plain(
363  // The functor which will be used to initialize the data
364  [first, last](void *ToPtr) {
365  // We need to cast MUserPtr to pointer to the iteration type to
366  // get correct offset in std::copy when it will increment
367  // destination pointer.
368  using IteratorValueType =
370  using IteratorNonConstValueType =
372  using IteratorPointerToNonConstValueType =
374  std::copy(first, last,
375  static_cast<IteratorPointerToNonConstValueType>(ToPtr));
376  },
377  std::distance(first, last) * sizeof(T),
378  detail::getNextPowerOfTwo(sizeof(T)), propList,
379  make_unique_ptr<detail::SYCLMemObjAllocatorHolder<AllocatorT, T>>(),
380  detail::iterator_to_const_type_t<InputIterator>::value),
381  Range(range<1>(std::distance(first, last))) {
382  size_t r[3] = {Range[0], 0, 0};
383  buffer_plain::constructorNotification(CodeLoc, (void *)impl.get(), &first,
384  (const void *)typeid(T).name(),
385  dimensions, sizeof(T), r);
386  }
387 
388  // This constructor is a prototype for a future SYCL specification
389  template <class Container, int N = dimensions,
390  typename = EnableIfOneDimension<N>,
391  typename = EnableIfContiguous<Container>>
392  buffer(Container &container, AllocatorT allocator,
393  const property_list &propList = {},
394  const detail::code_location CodeLoc = detail::code_location::current())
395  : buffer_plain(
396  container.data(), container.size() * sizeof(T),
397  detail::getNextPowerOfTwo(sizeof(T)), propList,
399  allocator)),
400  Range(range<1>(container.size())) {
401  size_t r[3] = {Range[0], 0, 0};
403  CodeLoc, (void *)impl.get(), container.data(),
404  (const void *)typeid(T).name(), dimensions, sizeof(T), r);
405  }
406 
407  // This constructor is a prototype for a future SYCL specification
408  template <class Container, int N = dimensions,
409  typename = EnableIfOneDimension<N>,
410  typename = EnableIfContiguous<Container>>
411  buffer(Container &container, const property_list &propList = {},
412  const detail::code_location CodeLoc = detail::code_location::current())
413  : buffer(container, {}, propList, CodeLoc) {}
414 
416  const range<dimensions> &subRange,
417  const detail::code_location CodeLoc = detail::code_location::current())
418  : buffer_plain(b.impl), Range(subRange),
419  OffsetInBytes(getOffsetInBytes<T>(baseIndex, b.Range)),
420  IsSubBuffer(true) {
422  CodeLoc, (void *)impl.get(), impl.get(), (const void *)typeid(T).name(),
423  dimensions, sizeof(T), rangeToArray(Range).data());
424 
425  if (b.is_sub_buffer())
426  throw sycl::invalid_object_error(
427  "Cannot create sub buffer from sub buffer.", PI_ERROR_INVALID_VALUE);
428  if (isOutOfBounds(baseIndex, subRange, b.Range))
429  throw sycl::invalid_object_error(
430  "Requested sub-buffer size exceeds the size of the parent buffer",
431  PI_ERROR_INVALID_VALUE);
432  if (!isContiguousRegion(baseIndex, subRange, b.Range))
433  throw sycl::invalid_object_error(
434  "Requested sub-buffer region is not contiguous",
435  PI_ERROR_INVALID_VALUE);
436  }
437 
438  buffer(const buffer &rhs,
439  const detail::code_location CodeLoc = detail::code_location::current())
440  : buffer_plain(rhs.impl), Range(rhs.Range),
441  OffsetInBytes(rhs.OffsetInBytes), IsSubBuffer(rhs.IsSubBuffer) {
443  CodeLoc, (void *)impl.get(), impl.get(), (const void *)typeid(T).name(),
444  dimensions, sizeof(T), rangeToArray(Range).data());
445  }
446 
447  buffer(buffer &&rhs,
448  const detail::code_location CodeLoc = detail::code_location::current())
449  : buffer_plain(std::move(rhs.impl)), Range(rhs.Range),
450  OffsetInBytes(rhs.OffsetInBytes), IsSubBuffer(rhs.IsSubBuffer) {
452  CodeLoc, (void *)impl.get(), impl.get(), (const void *)typeid(T).name(),
453  dimensions, sizeof(T), rangeToArray(Range).data());
454  }
455 
456  buffer &operator=(const buffer &rhs) = default;
457 
458  buffer &operator=(buffer &&rhs) = default;
459 
460  ~buffer() = default;
461 
462  bool operator==(const buffer &rhs) const { return impl == rhs.impl; }
463 
464  bool operator!=(const buffer &rhs) const { return !(*this == rhs); }
465 
466  /* -- common interface members -- */
467 
468  /* -- property interface members -- */
469 
470  range<dimensions> get_range() const { return Range; }
471 
472  __SYCL2020_DEPRECATED("get_count() is deprecated, please use size() instead")
473  size_t get_count() const { return size(); }
474  size_t size() const noexcept { return Range.size(); }
475 
477  "get_size() is deprecated, please use byte_size() instead")
478  size_t get_size() const { return byte_size(); }
479  size_t byte_size() const noexcept { return size() * sizeof(T); }
480 
481  AllocatorT get_allocator() const {
482  return buffer_plain::get_allocator_internal()
483  ->template getAllocator<AllocatorT>();
484  }
485 
486  template <access::mode Mode, access::target Target = access::target::device>
487  accessor<T, dimensions, Mode, Target, access::placeholder::false_t,
490  handler &CommandGroupHandler,
491  const detail::code_location CodeLoc = detail::code_location::current()) {
492  return accessor<T, dimensions, Mode, Target, access::placeholder::false_t,
494  *this, CommandGroupHandler, {}, CodeLoc);
495  }
496 
497  template <access::mode mode>
498  accessor<T, dimensions, mode, access::target::host_buffer,
499  access::placeholder::false_t, ext::oneapi::accessor_property_list<>>
501  const detail::code_location CodeLoc = detail::code_location::current()) {
502  return accessor<T, dimensions, mode, access::target::host_buffer,
503  access::placeholder::false_t,
504  ext::oneapi::accessor_property_list<>>(*this, {}, CodeLoc);
505  }
506 
507  template <access::mode mode, access::target target = access::target::device>
508  accessor<T, dimensions, mode, target, access::placeholder::false_t,
511  handler &commandGroupHandler, range<dimensions> accessRange,
512  id<dimensions> accessOffset = {},
513  const detail::code_location CodeLoc = detail::code_location::current()) {
514  if (isOutOfBounds(accessOffset, accessRange, this->Range))
515  throw sycl::invalid_object_error(
516  "Requested accessor would exceed the bounds of the buffer",
517  PI_ERROR_INVALID_VALUE);
518 
519  return accessor<T, dimensions, mode, target, access::placeholder::false_t,
521  *this, commandGroupHandler, accessRange, accessOffset, {}, CodeLoc);
522  }
523 
524  template <access::mode mode>
525  accessor<T, dimensions, mode, access::target::host_buffer,
526  access::placeholder::false_t, ext::oneapi::accessor_property_list<>>
528  range<dimensions> accessRange, id<dimensions> accessOffset = {},
529  const detail::code_location CodeLoc = detail::code_location::current()) {
530  if (isOutOfBounds(accessOffset, accessRange, this->Range))
531  throw sycl::invalid_object_error(
532  "Requested accessor would exceed the bounds of the buffer",
533  PI_ERROR_INVALID_VALUE);
534 
535  return accessor<T, dimensions, mode, access::target::host_buffer,
536  access::placeholder::false_t,
538  *this, accessRange, accessOffset, {}, CodeLoc);
539  }
540 
541 #if __cplusplus >= 201703L
542 
543  template <typename... Ts> auto get_access(Ts... args) {
544  return accessor{*this, args...};
545  }
546 
547  template <typename... Ts>
548  auto get_access(handler &commandGroupHandler, Ts... args) {
549  return accessor{*this, commandGroupHandler, args...};
550  }
551 
552  template <typename... Ts> auto get_host_access(Ts... args) {
553  return host_accessor{*this, args...};
554  }
555 
556  template <typename... Ts>
557  auto get_host_access(handler &commandGroupHandler, Ts... args) {
558  return host_accessor{*this, commandGroupHandler, args...};
559  }
560 
561 #endif
562 
563  template <typename Destination = std::nullptr_t>
564  void set_final_data(Destination finalData = nullptr) {
565  this->set_final_data_internal(finalData);
566  }
567 
568  void set_final_data_internal(std::nullptr_t) {
569  buffer_plain::set_final_data_internal();
570  }
571 
572  template <template <typename WeakT> class WeakPtrT, typename WeakT>
574  std::is_convertible<WeakPtrT<WeakT>, std::weak_ptr<WeakT>>::value>
575  set_final_data_internal(WeakPtrT<WeakT> FinalData) {
576  std::weak_ptr<WeakT> TempFinalData(FinalData);
577  this->set_final_data_internal(TempFinalData);
578  }
579 
580  template <typename WeakT>
581  void set_final_data_internal(std::weak_ptr<WeakT> FinalData) {
582  buffer_plain::set_final_data_internal(
583  [FinalData](const std::function<void(void *const Ptr)> &F) {
584  if (std::shared_ptr<WeakT> LockedFinalData = FinalData.lock())
585  F(LockedFinalData.get());
586  });
587  }
588 
589  template <typename Destination>
591  set_final_data_internal(Destination FinalData) {
592  if (!FinalData)
593  buffer_plain::set_final_data_internal();
594  else
595  buffer_plain::set_final_data_internal(
596  [FinalData](const std::function<void(void *const Ptr)> &F) {
597  F(FinalData);
598  });
599  }
600 
601  template <typename Destination>
603  set_final_data_internal(Destination FinalData) {
604  const size_t Size = size();
605  buffer_plain::set_final_data_internal(
606  [FinalData, Size](const std::function<void(void *const Ptr)> &F) {
607  using DestinationValueT = detail::iterator_value_type_t<Destination>;
608  // TODO if Destination is ContiguousIterator then don't create
609  // ContiguousStorage. updateHostMemory works only with pointer to
610  // continuous data.
611  std::unique_ptr<DestinationValueT[]> ContiguousStorage(
612  new DestinationValueT[Size]);
613  F(ContiguousStorage.get());
614  std::copy(ContiguousStorage.get(), ContiguousStorage.get() + Size,
615  FinalData);
616  });
617  }
618 
619  void set_final_data(std::nullptr_t) {
620  buffer_plain::set_final_data_internal();
621  }
622 
623  void set_write_back(bool flag = true) { buffer_plain::set_write_back(flag); }
624 
625  bool is_sub_buffer() const { return IsSubBuffer; }
626 
627  template <typename ReinterpretT, int ReinterpretDim>
628  buffer<ReinterpretT, ReinterpretDim,
629  typename std::allocator_traits<AllocatorT>::template rebind_alloc<
630  ReinterpretT>>
631  reinterpret(range<ReinterpretDim> reinterpretRange) const {
632  if (sizeof(ReinterpretT) * reinterpretRange.size() != byte_size())
633  throw sycl::invalid_object_error(
634  "Total size in bytes represented by the type and range of the "
635  "reinterpreted SYCL buffer does not equal the total size in bytes "
636  "represented by the type and range of this SYCL buffer",
637  PI_ERROR_INVALID_VALUE);
638 
639  return buffer<ReinterpretT, ReinterpretDim,
640  typename std::allocator_traits<
641  AllocatorT>::template rebind_alloc<ReinterpretT>>(
642  impl, reinterpretRange, OffsetInBytes, IsSubBuffer);
643  }
644 
645  template <typename ReinterpretT, int ReinterpretDim = dimensions>
646  typename std::enable_if<
647  (sizeof(ReinterpretT) == sizeof(T)) && (dimensions == ReinterpretDim),
648  buffer<ReinterpretT, ReinterpretDim,
649  typename std::allocator_traits<AllocatorT>::template rebind_alloc<
650  ReinterpretT>>>::type
651  reinterpret() const {
652  return buffer<ReinterpretT, ReinterpretDim,
653  typename std::allocator_traits<
654  AllocatorT>::template rebind_alloc<ReinterpretT>>(
655  impl, get_range(), OffsetInBytes, IsSubBuffer);
656  }
657 
658  template <typename ReinterpretT, int ReinterpretDim = dimensions>
659  typename std::enable_if<
660  (ReinterpretDim == 1) && ((dimensions != ReinterpretDim) ||
661  (sizeof(ReinterpretT) != sizeof(T))),
663  reinterpret() const {
664  long sz = byte_size();
665  if (sz % sizeof(ReinterpretT) != 0)
666  throw sycl::invalid_object_error(
667  "Total byte size of buffer is not evenly divisible by the size of "
668  "the reinterpreted type",
669  PI_ERROR_INVALID_VALUE);
670 
672  impl, range<1>{sz / sizeof(ReinterpretT)}, OffsetInBytes, IsSubBuffer);
673  }
674 
675  template <typename propertyT> bool has_property() const noexcept {
676  return buffer_plain::template has_property<propertyT>();
677  }
678 
679  template <typename propertyT> propertyT get_property() const {
680  return buffer_plain::template get_property<propertyT>();
681  }
682 
683 protected:
684  bool isOutOfBounds(const id<dimensions> &offset,
685  const range<dimensions> &newRange,
686  const range<dimensions> &parentRange) {
687  bool outOfBounds = false;
688  for (int i = 0; i < dimensions; ++i)
689  outOfBounds |= newRange[i] + offset[i] > parentRange[i];
690 
691  return outOfBounds;
692  }
693 
694 private:
695  template <class Obj>
696  friend decltype(Obj::impl) detail::getSyclObjImpl(const Obj &SyclObject);
697  template <typename A, int dims, typename C, typename Enable>
698  friend class buffer;
699  template <typename DataT, int dims, access::mode mode, access::target target,
700  access::placeholder isPlaceholder, typename PropertyListT>
701  friend class accessor;
702  template <typename HT, int HDims, typename HAllocT>
705  range<dimensions> Range;
706  // Offset field specifies the origin of the sub buffer inside the parent
707  // buffer
708  size_t OffsetInBytes = 0;
709  bool IsSubBuffer = false;
710 
711  // Interop constructor
712  template <int N = dimensions, typename = EnableIfOneDimension<N>>
713  buffer(pi_native_handle MemObject, const context &SyclContext,
714  bool OwnNativeHandle, event AvailableEvent = {},
715  const detail::code_location CodeLoc = detail::code_location::current())
716  : buffer_plain(
717  MemObject, SyclContext,
719  OwnNativeHandle, std::move(AvailableEvent)),
720  Range{0} {
721 
722  Range[0] = buffer_plain::getSize() / sizeof(T);
724  CodeLoc, (void *)impl.get(), &MemObject, (const void *)typeid(T).name(),
725  dimensions, sizeof(T), rangeToArray(Range).data());
726  }
727 
728  void addOrReplaceAccessorProperties(const property_list &PropertyList) {
729  buffer_plain::addOrReplaceAccessorProperties(PropertyList);
730  }
731 
732  void deleteAccProps(const sycl::detail::PropWithDataKind &Kind) {
733  buffer_plain::deleteAccProps(Kind);
734  }
735 
736  // Reinterpret contructor
737  buffer(const std::shared_ptr<detail::buffer_impl> &Impl,
738  range<dimensions> reinterpretRange, size_t reinterpretOffset,
739  bool isSubBuffer,
740  const detail::code_location CodeLoc = detail::code_location::current())
741  : buffer_plain(Impl), Range(reinterpretRange),
742  OffsetInBytes(reinterpretOffset), IsSubBuffer(isSubBuffer) {
744  CodeLoc, (void *)impl.get(), Impl.get(), (const void *)typeid(T).name(),
745  dimensions, sizeof(T), rangeToArray(Range).data());
746  }
747 
748  template <typename Type, int N>
749  size_t getOffsetInBytes(const id<N> &offset, const range<N> &range) {
750  return detail::getLinearIndex(offset, range) * sizeof(Type);
751  }
752 
753  bool isContiguousRegion(const id<1> &, const range<1> &, const range<1> &) {
754  // 1D sub buffer always has contiguous region
755  return true;
756  }
757 
758  bool isContiguousRegion(const id<2> &offset, const range<2> &newRange,
759  const range<2> &parentRange) {
760  // For 2D sub buffer there are 2 cases:
761  // 1) Offset {Any, Any} | a piece of any line of a buffer
762  // Range {1, Any} |
763  // 2) Offset {Any, 0 } | any number of full lines
764  // Range {Any, Col} |
765  // where Col is a number of columns of original buffer
766  if (offset[1])
767  return newRange[0] == 1;
768  return newRange[1] == parentRange[1];
769  }
770 
771  bool isContiguousRegion(const id<3> &offset, const range<3> &newRange,
772  const range<3> &parentRange) {
773  // For 3D sub buffer there are 3 cases:
774  // 1) Offset {Any, Any, Any} | a piece of any line in any slice of a buffer
775  // Range {1, 1, Any} |
776  // 2) Offset {Any, Any, 0 } | any number of full lines in any slice
777  // Range {1, Any, Col} |
778  // 3) Offset {Any, 0, 0 } | any number of slices
779  // Range {Any, Row, Col} |
780  // where Row and Col are numbers of rows and columns of original buffer
781  if (offset[2])
782  return newRange[0] == 1 && newRange[1] == 1;
783  if (offset[1])
784  return newRange[0] == 1 && newRange[2] == parentRange[2];
785  return newRange[1] == parentRange[1] && newRange[2] == parentRange[2];
786  }
787 
788  template <backend BackendName, typename DataT, int Dimensions,
789  typename Allocator>
790  friend auto detail::get_native_buffer(
791  const buffer<DataT, Dimensions, Allocator, void> &Obj)
792  -> backend_return_t<BackendName,
793  buffer<DataT, Dimensions, Allocator, void>>;
794 
795  template <backend BackendName>
796  backend_return_t<BackendName, buffer<T, dimensions, AllocatorT>>
797  getNative() const {
798  auto NativeHandles = buffer_plain::getNativeVector(BackendName);
799  return detail::BufferInterop<BackendName, T, dimensions,
800  AllocatorT>::GetNativeObjs(NativeHandles);
801  }
802 };
803 
804 #ifdef __cpp_deduction_guides
805 template <class InputIterator, class AllocatorT>
806 buffer(InputIterator, InputIterator, AllocatorT, const property_list & = {})
807  -> buffer<typename std::iterator_traits<InputIterator>::value_type, 1,
808  AllocatorT>;
809 template <class InputIterator>
810 buffer(InputIterator, InputIterator, const property_list & = {})
811  -> buffer<typename std::iterator_traits<InputIterator>::value_type, 1>;
812 template <class Container, class AllocatorT>
813 buffer(Container &, AllocatorT, const property_list & = {})
814  -> buffer<typename Container::value_type, 1, AllocatorT>;
815 template <class Container>
816 buffer(Container &, const property_list & = {})
817  -> buffer<typename Container::value_type, 1>;
818 template <class T, int dimensions, class AllocatorT>
819 buffer(const T *, const range<dimensions> &, AllocatorT,
820  const property_list & = {}) -> buffer<T, dimensions, AllocatorT>;
821 template <class T, int dimensions>
822 buffer(const T *, const range<dimensions> &, const property_list & = {})
823  -> buffer<T, dimensions>;
824 #endif // __cpp_deduction_guides
825 
826 } // __SYCL_INLINE_VER_NAMESPACE(_V1)
827 } // namespace sycl
828 
829 namespace std {
830 template <typename T, int dimensions, typename AllocatorT>
831 struct hash<sycl::buffer<T, dimensions, AllocatorT>> {
832  size_t operator()(const sycl::buffer<T, dimensions, AllocatorT> &b) const {
833  return hash<std::shared_ptr<sycl::detail::buffer_impl>>()(
835  }
836 };
837 } // namespace std
sycl::_V1::buffer::size
size_t size() const noexcept
Definition: buffer.hpp:474
sycl::_V1::buffer::buffer
buffer(const range< dimensions > &bufferRange, const property_list &propList={}, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:172
sycl::_V1::buffer::set_final_data
void set_final_data(Destination finalData=nullptr)
Definition: buffer.hpp:564
sycl::_V1::buffer::get_access
accessor< T, dimensions, mode, access::target::host_buffer, access::placeholder::false_t, ext::oneapi::accessor_property_list<> > get_access(const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:500
sycl::_V1::property_list
Objects of the property_list class are containers for the SYCL properties.
Definition: property_list.hpp:26
property_list.hpp
sycl::_V1::buffer::get_access
accessor< T, dimensions, mode, access::target::host_buffer, access::placeholder::false_t, ext::oneapi::accessor_property_list<> > get_access(range< dimensions > accessRange, id< dimensions > accessOffset={}, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:527
sycl::_V1::buffer::reinterpret
std::enable_if<(ReinterpretDim==1) &&((dimensions !=ReinterpretDim)||(sizeof(ReinterpretT) !=sizeof(T))), buffer< ReinterpretT, ReinterpretDim, AllocatorT > >::type reinterpret() const
Definition: buffer.hpp:663
sycl::_V1::access::mode
mode
Definition: access.hpp:28
sycl::_V1::range::size
size_t size() const
Definition: range.hpp:50
sycl::_V1::backend
backend
Definition: backend_types.hpp:21
sycl::_V1::detail::SYCLMemObjAllocator
Definition: sycl_mem_obj_allocator.hpp:20
sycl::_V1::buffer::buffer
buffer(const range< dimensions > &bufferRange, AllocatorT allocator, const property_list &propList={}, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:185
sycl::_V1::detail::buffer_plain::buffer_plain
buffer_plain(const std::shared_ptr< detail::buffer_impl > &impl)
Definition: buffer.hpp:91
sycl::_V1::buffer< char, 1 >::EnableIfItInputIterator
detail::enable_if_t< std::is_convertible< typename std::iterator_traits< It >::iterator_category, std::input_iterator_tag >::value > EnableIfItInputIterator
Definition: buffer.hpp:161
stl.hpp
sycl::_V1::detail::remove_const_t
typename std::remove_const< T >::type remove_const_t
Definition: stl_type_traits.hpp:30
__SYCL_INLINE_VER_NAMESPACE
#define __SYCL_INLINE_VER_NAMESPACE(X)
Definition: defines_elementary.hpp:13
sycl::_V1::buffer::buffer
buffer(EnableIfSameNonConstIterators< T, _T > const *hostData, const range< dimensions > &bufferRange, AllocatorT allocator, const property_list &propList={}, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:242
sycl::_V1::buffer::buffer
buffer(buffer< T, dimensions, AllocatorT > &b, const id< dimensions > &baseIndex, const range< dimensions > &subRange, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:415
sycl::_V1::buffer
Defines a shared array that can be used by kernels in queues.
Definition: buffer.hpp:35
sycl::_V1::buffer::has_property
bool has_property() const noexcept
Definition: buffer.hpp:675
sycl::_V1::buffer::operator==
bool operator==(const buffer &rhs) const
Definition: buffer.hpp:462
sycl::_V1::buffer::buffer
buffer(InputIterator first, InputIterator last, AllocatorT allocator, const property_list &propList={}, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:326
accessor_property_list.hpp
sycl::_V1::buffer< char, 1 >::EnableIfSameNonConstIterators
typename detail::enable_if_t< std::is_same< ItA, ItB >::value &&!std::is_const< ItA >::value, ItA > EnableIfSameNonConstIterators
Definition: buffer.hpp:164
sycl::_V1::buffer::buffer
buffer(const std::shared_ptr< T[]> &hostData, const range< dimensions > &bufferRange, const property_list &propList={}, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:307
sycl::_V1::distance
float distance(T p0, T p1) __NOEXC
Definition: builtins.hpp:1011
sycl::_V1::detail::PropWithDataKind
PropWithDataKind
Definition: property_helper.hpp:45
sycl::_V1::buffer::buffer
buffer(buffer &&rhs, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:447
event.hpp
sycl::_V1::detail::get_native_buffer
auto get_native_buffer(const buffer< DataT, Dimensions, Allocator, void > &Obj) -> backend_return_t< BackendName, buffer< DataT, Dimensions, Allocator, void >>
sycl::_V1::detail::constructorNotification
void constructorNotification(void *BufferObj, void *AccessorObj, access::target Target, access::mode Mode, const code_location &CodeLoc)
sycl::_V1::buffer::get_property
propertyT get_property() const
Definition: buffer.hpp:679
sycl::_V1::host_accessor
Definition: accessor.hpp:2831
sycl::_V1::buffer::buffer
buffer(const std::shared_ptr< T[]> &hostData, const range< dimensions > &bufferRange, AllocatorT allocator, const property_list &propList={}, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:274
sycl::_V1::buffer::set_final_data
void set_final_data(std::nullptr_t)
Definition: buffer.hpp:619
sycl
---— Error handling, matching OpenCL plugin semantics.
Definition: access.hpp:13
sycl::_V1::buffer::operator!=
bool operator!=(const buffer &rhs) const
Definition: buffer.hpp:464
sycl::_V1::event
An event object can be used to synchronize memory transfers, enqueues of kernels and signaling barrie...
Definition: event.hpp:38
sycl::_V1::buffer::get_access
accessor< T, dimensions, mode, target, access::placeholder::false_t, ext::oneapi::accessor_property_list<> > get_access(handler &commandGroupHandler, range< dimensions > accessRange, id< dimensions > accessOffset={}, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:510
sycl::_V1::buffer::set_final_data_internal
detail::EnableIfOutputPointerT< Destination > set_final_data_internal(Destination FinalData)
Definition: buffer.hpp:591
sycl::_V1::detail::iterator_value_type_t
typename std::iterator_traits< T >::value_type iterator_value_type_t
Definition: stl_type_traits.hpp:55
sycl::_V1::id
A unique identifier of an item in an index space.
Definition: array.hpp:17
sycl::_V1::errc::accessor
@ accessor
sycl::_V1::buffer::is_sub_buffer
bool is_sub_buffer() const
Definition: buffer.hpp:625
sycl::_V1::ext::oneapi::experimental::detail::get_property
static constexpr std::enable_if_t< HasProperty, typename FindCompileTimePropertyValueType< CTPropertyT, PropertiesT >::type > get_property()
Definition: properties.hpp:65
sycl::_V1::detail::enable_if_t
typename std::enable_if< B, T >::type enable_if_t
Definition: stl_type_traits.hpp:24
stl_type_traits.hpp
sycl::_V1::buffer::set_final_data_internal
void set_final_data_internal(std::weak_ptr< WeakT > FinalData)
Definition: buffer.hpp:581
sycl::_V1::range
Defines the iteration domain of either a single work-group in a parallel dispatch,...
Definition: buffer.hpp:26
sycl::_V1::buffer::buffer
buffer(Container &container, AllocatorT allocator, const property_list &propList={}, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:392
sycl::_V1::detail::aligned_allocator
Definition: aligned_allocator.hpp:23
sycl::_V1::detail::remove_pointer_t
typename remove_pointer< T >::type remove_pointer_t
Definition: type_traits.hpp:283
sycl::_V1::buffer::set_final_data_internal
detail::EnableIfOutputIteratorT< Destination > set_final_data_internal(Destination FinalData)
Definition: buffer.hpp:603
sycl::_V1::access::placeholder
placeholder
Definition: access.hpp:43
char
sycl::_V1::buffer::buffer
buffer(const std::shared_ptr< T > &hostData, const range< dimensions > &bufferRange, const property_list &propList={}, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:291
sycl::_V1::buffer::buffer
buffer(T *hostData, const range< dimensions > &bufferRange, const property_list &propList={}, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:199
sycl::_V1::buffer::set_final_data_internal
detail::enable_if_t< std::is_convertible< WeakPtrT< WeakT >, std::weak_ptr< WeakT > >::value > set_final_data_internal(WeakPtrT< WeakT > FinalData)
Definition: buffer.hpp:575
sycl::_V1::detail::EnableIfOutputPointerT
detail::enable_if_t< std::is_pointer< DataT >::value > EnableIfOutputPointerT
Definition: common.hpp:34
sycl::_V1::buffer::rangeToArray
std::array< size_t, 3 > rangeToArray(range< 3 > &r)
Definition: buffer.hpp:166
range.hpp
sycl::_V1::Dimensions
class __SYCL_SPECIAL_CLASS __SYCL_TYPE(local_accessor) local_accessor class __SYCL_SPECIAL_CLASS Dimensions
Definition: accessor.hpp:2686
sycl::_V1::buffer::get_range
range< dimensions > get_range() const
Definition: buffer.hpp:470
sycl::_V1::buffer< char, 1 >::EnableIfOneDimension
typename detail::enable_if_t< 1==dims > EnableIfOneDimension
Definition: buffer.hpp:149
sycl::_V1::handler
Command group handler class.
Definition: handler.hpp:352
common.hpp
std::hash< sycl::buffer< T, dimensions, AllocatorT > >::operator()
size_t operator()(const sycl::buffer< T, dimensions, AllocatorT > &b) const
Definition: buffer.hpp:832
sycl::_V1::backend_return_t
typename backend_traits< Backend >::template return_type< SyclType > backend_return_t
Definition: backend.hpp:72
sycl::_V1::ext::oneapi::accessor_property_list
Definition: property_list.hpp:19
sycl::_V1::buffer::reinterpret
std::enable_if<(sizeof(ReinterpretT)==sizeof(T)) &&(dimensions==ReinterpretDim), buffer< ReinterpretT, ReinterpretDim, typename std::allocator_traits< AllocatorT >::template rebind_alloc< ReinterpretT > > >::type reinterpret() const
Definition: buffer.hpp:651
sycl::_V1::buffer::__SYCL2020_DEPRECATED
__SYCL2020_DEPRECATED("get_count() is deprecated, please use size() instead") size_t get_count() const
Definition: buffer.hpp:472
sycl::_V1::access::target
target
Definition: access.hpp:17
sycl::_V1::buffer::buffer
buffer(T *hostData, const range< dimensions > &bufferRange, AllocatorT allocator, const property_list &propList={}, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:212
sycl::_V1::detail::EnableIfOutputIteratorT
detail::enable_if_t< !std::is_pointer< DataT >::value > EnableIfOutputIteratorT
Definition: common.hpp:38
pi_native_handle
uintptr_t pi_native_handle
Definition: pi.h:103
sycl::_V1::accessor
Definition: accessor.hpp:227
sycl::_V1::buffer::isOutOfBounds
bool isOutOfBounds(const id< dimensions > &offset, const range< dimensions > &newRange, const range< dimensions > &parentRange)
Definition: buffer.hpp:684
sycl::_V1::make_unique_ptr
std::unique_ptr< T > make_unique_ptr(ArgsT &&...Args)
Definition: stl.hpp:51
sycl::_V1::detail::getNextPowerOfTwo
constexpr size_t getNextPowerOfTwo(size_t Var)
Definition: common.hpp:367
sycl::_V1::detail::SYCLMemObjAllocatorHolder
Definition: sycl_mem_obj_allocator.hpp:37
sycl::_V1::detail::code_location
Definition: common.hpp:66
exception.hpp
std
Definition: accessor.hpp:3071
sycl_mem_obj_allocator.hpp
sycl::_V1::detail::buffer_plain
Definition: buffer.hpp:60
sycl::_V1::buffer::buffer
buffer(InputIterator first, InputIterator last, const property_list &propList={}, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:359
sycl::_V1::buffer::buffer
buffer(Container &container, const property_list &propList={}, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:411
sycl::_V1::image_channel_order::r
@ r
sycl::_V1::buffer::get_access
accessor< T, dimensions, Mode, Target, access::placeholder::false_t, ext::oneapi::accessor_property_list<> > get_access(handler &CommandGroupHandler, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:489
sycl::_V1::buffer::set_final_data_internal
void set_final_data_internal(std::nullptr_t)
Definition: buffer.hpp:568
sycl::_V1::detail::make_buffer_helper
buffer< T, Dimensions, AllocatorT, void > make_buffer_helper(pi_native_handle Handle, const context &Ctx, event Evt={}, bool OwnNativeHandle=true)
Definition: buffer.hpp:43
sycl::_V1::detail::getLinearIndex
size_t getLinearIndex(const T< Dims > &Index, const U< Dims > &Range)
Definition: common.hpp:373
sycl::_V1::buffer::set_write_back
void set_write_back(bool flag=true)
Definition: buffer.hpp:623
sycl::_V1::buffer::rangeToArray
std::array< size_t, 3 > rangeToArray(range< 2 > &r)
Definition: buffer.hpp:168
sycl::_V1::detail::buffer_impl
Definition: buffer_impl.hpp:41
sycl::_V1::buffer::rangeToArray
std::array< size_t, 3 > rangeToArray(range< 1 > &r)
Definition: buffer.hpp:170
sycl::_V1::buffer::buffer
buffer(const std::shared_ptr< T > &hostData, const range< dimensions > &bufferRange, AllocatorT allocator, const property_list &propList={}, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:257
sycl::_V1::detail::add_pointer_t
typename std::add_pointer< T >::type add_pointer_t
Definition: stl_type_traits.hpp:37
sycl::_V1::buffer::reinterpret
buffer< ReinterpretT, ReinterpretDim, typename std::allocator_traits< AllocatorT >::template rebind_alloc< ReinterpretT > > reinterpret(range< ReinterpretDim > reinterpretRange) const
Definition: buffer.hpp:631
sycl::_V1::buffer< char, 1 >::EnableIfContiguous
detail::void_t< detail::enable_if_t< std::is_convertible< detail::remove_pointer_t< decltype(std::declval< Container >().data())>(*)[], const char(*)[]>::value >, decltype(std::declval< Container >().size())> EnableIfContiguous
Definition: buffer.hpp:157
sycl::_V1::buffer::buffer
buffer(const buffer &rhs, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:438
sycl::_V1::buffer::get_allocator
AllocatorT get_allocator() const
Definition: buffer.hpp:481
sycl::_V1::buffer::__SYCL2020_DEPRECATED
__SYCL2020_DEPRECATED("get_size() is deprecated, please use byte_size() instead") size_t get_size() const
Definition: buffer.hpp:476
sycl::_V1::buffer::buffer
buffer(EnableIfSameNonConstIterators< T, _T > const *hostData, const range< dimensions > &bufferRange, const property_list &propList={}, const detail::code_location CodeLoc=detail::code_location::current())
Definition: buffer.hpp:227
sycl::_V1::detail::void_t
void void_t
Definition: stl_type_traits.hpp:42
sycl::_V1::detail::getSyclObjImpl
decltype(Obj::impl) getSyclObjImpl(const Obj &SyclObject)
Definition: common.hpp:240
sycl::_V1::buffer::byte_size
size_t byte_size() const noexcept
Definition: buffer.hpp:479
sycl::_V1::context
The context class represents a SYCL context on which kernel functions may be executed.
Definition: context.hpp:39