DPC++ Runtime
Runtime libraries for oneAPI DPC++
sycl_mem_obj_t.hpp
Go to the documentation of this file.
1 //==------------ sycl_mem_obj_t.hpp - SYCL standard header file ------------==//
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 
12 #include <sycl/detail/common.hpp>
13 #include <sycl/detail/export.hpp>
16 #include <sycl/event.hpp>
19 #include <sycl/property_list.hpp>
20 #include <sycl/stl.hpp>
21 
22 #include <cstring>
23 #include <memory>
24 #include <type_traits>
25 
26 namespace sycl {
28 namespace detail {
29 
30 // Forward declarations
31 class context_impl;
32 class event_impl;
33 class plugin;
34 
35 using ContextImplPtr = std::shared_ptr<context_impl>;
36 using EventImplPtr = std::shared_ptr<event_impl>;
37 
38 // The class serves as a base for all SYCL memory objects.
39 class __SYCL_EXPORT SYCLMemObjT : public SYCLMemObjI {
40 
41  // The check for output iterator is commented out as it blocks set_final_data
42  // with void * argument to be used.
43  // TODO: Align these checks with the SYCL specification when the behaviour
44  // with void * is clarified.
45  template <typename T>
46  using EnableIfOutputPointerT = std::enable_if_t<
47  /*is_output_iterator<T>::value &&*/ std::is_pointer<T>::value>;
48 
49  template <typename T>
50  using EnableIfOutputIteratorT = std::enable_if_t<
51  /*is_output_iterator<T>::value &&*/ !std::is_pointer<T>::value>;
52 
53 public:
54  SYCLMemObjT(const size_t SizeInBytes, const property_list &Props,
55  std::unique_ptr<SYCLMemObjAllocator> Allocator)
56  : MAllocator(std::move(Allocator)), MProps(Props), MInteropEvent(nullptr),
57  MInteropContext(nullptr), MInteropMemObject(nullptr),
58  MOpenCLInterop(false), MHostPtrReadOnly(false), MNeedWriteBack(true),
59  MSizeInBytes(SizeInBytes), MUserPtr(nullptr), MShadowCopy(nullptr),
60  MUploadDataFunctor(nullptr), MSharedPtrStorage(nullptr),
61  MHostPtrProvided(false) {}
62 
63  SYCLMemObjT(const property_list &Props,
64  std::unique_ptr<SYCLMemObjAllocator> Allocator)
65  : SYCLMemObjT(/*SizeInBytes*/ 0, Props, std::move(Allocator)) {}
66 
67  SYCLMemObjT(pi_native_handle MemObject, const context &SyclContext,
68  const size_t SizeInBytes, event AvailableEvent,
69  std::unique_ptr<SYCLMemObjAllocator> Allocator);
70 
71  SYCLMemObjT(cl_mem MemObject, const context &SyclContext,
72  event AvailableEvent,
73  std::unique_ptr<SYCLMemObjAllocator> Allocator)
74  : SYCLMemObjT(pi::cast<pi_native_handle>(MemObject), SyclContext,
75  /*SizeInBytes*/ (size_t)0, AvailableEvent,
76  std::move(Allocator)) {}
77 
78  SYCLMemObjT(pi_native_handle MemObject, const context &SyclContext,
79  bool OwmNativeHandle, event AvailableEvent,
80  std::unique_ptr<SYCLMemObjAllocator> Allocator);
81 
82  SYCLMemObjT(pi_native_handle MemObject, const context &SyclContext,
83  bool OwnNativeHandle, event AvailableEvent,
84  std::unique_ptr<SYCLMemObjAllocator> Allocator,
86  range<3> Range3WithOnes, unsigned Dimensions, size_t ElementSize);
87 
88  virtual ~SYCLMemObjT() = default;
89 
90  const PluginPtr &getPlugin() const;
91 
92  size_t getSizeInBytes() const noexcept override { return MSizeInBytes; }
93  __SYCL2020_DEPRECATED("get_count() is deprecated, please use size() instead")
94  size_t get_count() const { return size(); }
95  size_t size() const noexcept {
96  size_t AllocatorValueSize = MAllocator->getValueSize();
97  return (getSizeInBytes() + AllocatorValueSize - 1) / AllocatorValueSize;
98  }
99 
100  template <typename propertyT> bool has_property() const noexcept {
101  return MProps.has_property<propertyT>();
102  }
103 
104  template <typename propertyT> propertyT get_property() const {
105  return MProps.get_property<propertyT>();
106  }
107 
108  void addOrReplaceAccessorProperties(const property_list &PropertyList) {
109  MProps.add_or_replace_accessor_properties(PropertyList);
110  }
111 
113  MProps.delete_accessor_property(Kind);
114  }
115 
116  const std::unique_ptr<SYCLMemObjAllocator> &get_allocator_internal() const {
117  return MAllocator;
118  }
119 
120  void *allocateHostMem() override { return MAllocator->allocate(size()); }
121 
122  void releaseHostMem(void *Ptr) override {
123  if (Ptr)
124  MAllocator->deallocate(Ptr, size());
125  }
126 
127  void releaseMem(ContextImplPtr Context, void *MemAllocation) override;
128 
129  void *getUserPtr() const {
130  return MOpenCLInterop ? static_cast<void *>(MInteropMemObject) : MUserPtr;
131  }
132 
133  void set_write_back(bool NeedWriteBack) { MNeedWriteBack = NeedWriteBack; }
134 
135  void set_final_data(std::nullptr_t) { MUploadDataFunctor = nullptr; }
136 
138  MUploadDataFunctor = [this]() {
139  if (MSharedPtrStorage.use_count() > 1) {
140  void *FinalData = const_cast<void *>(MSharedPtrStorage.get());
141  updateHostMemory(FinalData);
142  }
143  };
144  MHostPtrProvided = true;
145  }
146 
148  const std::function<void(const std::function<void(void *const Ptr)> &)>
149  &FinalDataFunc) {
150 
151  auto UpdateFunc = [this](void *const Ptr) { updateHostMemory(Ptr); };
152  MUploadDataFunctor = [FinalDataFunc, UpdateFunc]() {
153  FinalDataFunc(UpdateFunc);
154  };
155  MHostPtrProvided = true;
156  }
157 
158 protected:
159  void updateHostMemory(void *const Ptr);
160 
161  // Update host with the latest data + notify scheduler that the memory object
162  // is going to die. After this method is finished no further operations with
163  // the memory object is allowed. This method is executed from child's
164  // destructor. This cannot be done in SYCLMemObjT's destructor as child's
165  // members must be alive.
166  void updateHostMemory();
167 
168 public:
169  bool useHostPtr() {
170  return has_property<property::buffer::use_host_ptr>() ||
171  has_property<property::image::use_host_ptr>();
172  }
173 
174  bool canReuseHostPtr(void *HostPtr, const size_t RequiredAlign) {
175  bool Aligned =
176  (reinterpret_cast<std::uintptr_t>(HostPtr) % RequiredAlign) == 0;
177  return Aligned || useHostPtr();
178  }
179 
180  void handleHostData(void *HostPtr, const size_t RequiredAlign) {
181  MHostPtrProvided = true;
182  if (!MHostPtrReadOnly && HostPtr) {
183  set_final_data([HostPtr](const std::function<void(void *const Ptr)> &F) {
184  F(HostPtr);
185  });
186  }
187 
188  if (canReuseHostPtr(HostPtr, RequiredAlign)) {
189  MUserPtr = HostPtr;
190  } else {
191  setAlign(RequiredAlign);
192  MShadowCopy = allocateHostMem();
193  MUserPtr = MShadowCopy;
194  std::memcpy(MUserPtr, HostPtr, MSizeInBytes);
195  }
196  }
197 
198  void handleHostData(const void *HostPtr, const size_t RequiredAlign) {
199  MHostPtrReadOnly = true;
200  handleHostData(const_cast<void *>(HostPtr), RequiredAlign);
201  }
202 
203  void handleHostData(const std::shared_ptr<void> &HostPtr,
204  const size_t RequiredAlign, bool IsConstPtr) {
205  MHostPtrProvided = true;
206  MSharedPtrStorage = HostPtr;
207  MHostPtrReadOnly = IsConstPtr;
208  if (HostPtr) {
209  if (!MHostPtrReadOnly)
210  set_final_data_from_storage();
211 
212  if (canReuseHostPtr(HostPtr.get(), RequiredAlign))
213  MUserPtr = HostPtr.get();
214  else {
215  setAlign(RequiredAlign);
216  MShadowCopy = allocateHostMem();
217  MUserPtr = MShadowCopy;
218  std::memcpy(MUserPtr, HostPtr.get(), MSizeInBytes);
219  }
220  }
221  }
222 
223  void handleHostData(const std::function<void(void *)> &CopyFromInput,
224  const size_t RequiredAlign, bool IsConstPtr) {
225  MHostPtrReadOnly = IsConstPtr;
226  setAlign(RequiredAlign);
227  if (useHostPtr())
228  throw runtime_error(
229  "Buffer constructor from a pair of iterator values does not support "
230  "use_host_ptr property.",
231  PI_ERROR_INVALID_OPERATION);
232 
233  setAlign(RequiredAlign);
234  MShadowCopy = allocateHostMem();
235  MUserPtr = MShadowCopy;
236 
237  CopyFromInput(MUserPtr);
238  }
239 
240  void setAlign(size_t RequiredAlign) {
241  MAllocator->setAlignment(RequiredAlign);
242  }
243 
244  static size_t getBufSizeForContext(const ContextImplPtr &Context,
245  pi_native_handle MemObject);
246 
247  void *allocateMem(ContextImplPtr Context, bool InitFromUserData,
248  void *HostPtr, RT::PiEvent &InteropEvent) override {
249  (void)Context;
250  (void)InitFromUserData;
251  (void)HostPtr;
252  (void)InteropEvent;
253  throw runtime_error("Not implemented", PI_ERROR_INVALID_OPERATION);
254  }
255 
256  MemObjType getType() const override { return MemObjType::Undefined; }
257 
258  ContextImplPtr getInteropContext() const override { return MInteropContext; }
259 
260  bool hasUserDataPtr() const { return MUserPtr != nullptr; };
261 
262  bool isInterop() const;
263 
264  bool isHostPointerReadOnly() const { return MHostPtrReadOnly; }
265 
266  void detachMemoryObject(const std::shared_ptr<SYCLMemObjT> &Self) const;
267 
268 protected:
269  // An allocateMem helper that determines which host ptr to use
270  void determineHostPtr(const ContextImplPtr &Context, bool InitFromUserData,
271  void *&HostPtr, bool &HostPtrReadOnly);
272 
273  // Allocator used for allocation memory on host.
274  std::unique_ptr<SYCLMemObjAllocator> MAllocator;
275  // Properties passed by user.
277  // Event passed by user to interoperability constructor.
278  // Should wait on this event before start working with such memory object.
280  // Context passed by user to interoperability constructor.
282  // Native backend memory object handle passed by user to interoperability
283  // constructor.
285  // Indicates whether memory object is created using interoperability
286  // constructor or not.
288  // Indicates if user provided pointer is read only.
290  // Indicates if memory object should write memory to the host on destruction.
292  // Size of memory.
293  size_t MSizeInBytes;
294  // User's pointer passed to constructor.
295  void *MUserPtr;
296  // Copy of memory passed by user to constructor.
297  void *MShadowCopy;
298  // Function which update host with final data on memory object destruction.
299  std::function<void(void)> MUploadDataFunctor;
300  // Field which holds user's shared_ptr in case of memory object is created
301  // using constructor with shared_ptr.
302  std::shared_ptr<const void> MSharedPtrStorage;
303  // Field to identify if dtor is not necessarily blocking.
304  // check for MUploadDataFunctor is not enough to define it since for case when
305  // we have read only HostPtr - MUploadDataFunctor is empty but delayed release
306  // must be not allowed.
308 };
309 } // namespace detail
310 } // __SYCL_INLINE_VER_NAMESPACE(_V1)
311 } // namespace sycl
sycl::_V1::detail::SYCLMemObjT::get_allocator_internal
const std::unique_ptr< SYCLMemObjAllocator > & get_allocator_internal() const
Definition: sycl_mem_obj_t.hpp:116
sycl::_V1::property_list
Objects of the property_list class are containers for the SYCL properties.
Definition: property_list.hpp:24
sycl::_V1::detail::SYCLMemObjT::size
size_t size() const noexcept
Definition: sycl_mem_obj_t.hpp:95
property_list.hpp
sycl_mem_obj_i.hpp
sycl::_V1::detail::pi::getPlugin
const PluginPtr & getPlugin()
Definition: pi.cpp:504
sycl::_V1::detail::SYCLMemObjT::MUploadDataFunctor
std::function< void(void)> MUploadDataFunctor
Definition: sycl_mem_obj_t.hpp:299
sycl::_V1::detail::SYCLMemObjT::SYCLMemObjT
SYCLMemObjT(cl_mem MemObject, const context &SyclContext, event AvailableEvent, std::unique_ptr< SYCLMemObjAllocator > Allocator)
Definition: sycl_mem_obj_t.hpp:71
sycl::_V1::detail::SYCLMemObjT::SYCLMemObjT
SYCLMemObjT(const property_list &Props, std::unique_ptr< SYCLMemObjAllocator > Allocator)
Definition: sycl_mem_obj_t.hpp:63
sycl::_V1::detail::ContextImplPtr
std::shared_ptr< sycl::detail::context_impl > ContextImplPtr
Definition: event_impl.hpp:30
sycl::_V1::detail::SYCLMemObjT::has_property
bool has_property() const noexcept
Definition: sycl_mem_obj_t.hpp:100
sycl::_V1::detail::SYCLMemObjT::useHostPtr
bool useHostPtr()
Definition: sycl_mem_obj_t.hpp:169
type_traits.hpp
sycl::_V1::detail::SYCLMemObjT::MAllocator
std::unique_ptr< SYCLMemObjAllocator > MAllocator
Definition: sycl_mem_obj_t.hpp:274
sycl::_V1::detail::SYCLMemObjT::releaseHostMem
void releaseHostMem(void *Ptr) override
Definition: sycl_mem_obj_t.hpp:122
stl.hpp
sycl::_V1::detail::SYCLMemObjT::handleHostData
void handleHostData(void *HostPtr, const size_t RequiredAlign)
Definition: sycl_mem_obj_t.hpp:180
__SYCL_INLINE_VER_NAMESPACE
#define __SYCL_INLINE_VER_NAMESPACE(X)
Definition: defines_elementary.hpp:11
sycl::_V1::detail::SYCLMemObjT::getInteropContext
ContextImplPtr getInteropContext() const override
Definition: sycl_mem_obj_t.hpp:258
sycl::_V1::detail::memcpy
void memcpy(void *Dst, const void *Src, size_t Size)
Definition: memcpy.hpp:16
sycl::_V1::detail::SYCLMemObjT::set_final_data
void set_final_data(const std::function< void(const std::function< void(void *const Ptr)> &)> &FinalDataFunc)
Definition: sycl_mem_obj_t.hpp:147
sycl::_V1::detail::SYCLMemObjT::isHostPointerReadOnly
bool isHostPointerReadOnly() const
Definition: sycl_mem_obj_t.hpp:264
sycl::_V1::detail::SYCLMemObjT::get_property
propertyT get_property() const
Definition: sycl_mem_obj_t.hpp:104
sycl::_V1::detail::PropWithDataKind
PropWithDataKind
Definition: property_helper.hpp:53
event.hpp
sycl::_V1::detail::SYCLMemObjT::MInteropMemObject
RT::PiMem MInteropMemObject
Definition: sycl_mem_obj_t.hpp:284
sycl::_V1::detail::SYCLMemObjT::__SYCL2020_DEPRECATED
__SYCL2020_DEPRECATED("get_count() is deprecated, please use size() instead") size_t get_count() const
Definition: sycl_mem_obj_t.hpp:93
sycl::_V1::detail::SYCLMemObjT::canReuseHostPtr
bool canReuseHostPtr(void *HostPtr, const size_t RequiredAlign)
Definition: sycl_mem_obj_t.hpp:174
sycl::_V1::Dimensions
class __SYCL_EBO __SYCL_SPECIAL_CLASS __SYCL_TYPE(local_accessor) local_accessor class __SYCL_EBO __SYCL_SPECIAL_CLASS Dimensions
Definition: accessor.hpp:3059
sycl
---— Error handling, matching OpenCL plugin semantics.
Definition: access.hpp:14
sycl::_V1::event
An event object can be used to synchronize memory transfers, enqueues of kernels and signaling barrie...
Definition: event.hpp:40
cast
To cast(From value)
Definition: pi_opencl.cpp:44
sycl::_V1::detail::SYCLMemObjT::allocateMem
void * allocateMem(ContextImplPtr Context, bool InitFromUserData, void *HostPtr, RT::PiEvent &InteropEvent) override
Definition: sycl_mem_obj_t.hpp:247
sycl::_V1::detail::SYCLMemObjT::MProps
property_list MProps
Definition: sycl_mem_obj_t.hpp:276
sycl::_V1::range< 3 >
sycl::_V1::detail::SYCLMemObjT::handleHostData
void handleHostData(const std::shared_ptr< void > &HostPtr, const size_t RequiredAlign, bool IsConstPtr)
Definition: sycl_mem_obj_t.hpp:203
export.hpp
sycl::_V1::detail::SYCLMemObjT::hasUserDataPtr
bool hasUserDataPtr() const
Definition: sycl_mem_obj_t.hpp:260
sycl::_V1::detail::SYCLMemObjT::MUserPtr
void * MUserPtr
Definition: sycl_mem_obj_t.hpp:295
sycl::_V1::detail::SYCLMemObjT::getUserPtr
void * getUserPtr() const
Definition: sycl_mem_obj_t.hpp:129
sycl::_V1::detail::SYCLMemObjT::MHostPtrReadOnly
bool MHostPtrReadOnly
Definition: sycl_mem_obj_t.hpp:289
sycl::_V1::detail::pi::PiMemImageChannelType
::pi_image_channel_type PiMemImageChannelType
Definition: pi.hpp:149
image_properties.hpp
sycl::_V1::detail::SYCLMemObjT::MInteropEvent
EventImplPtr MInteropEvent
Definition: sycl_mem_obj_t.hpp:279
common.hpp
sycl::_V1::detail::pi::PiMem
::pi_mem PiMem
Definition: pi.hpp:136
sycl::_V1::detail::SYCLMemObjT::allocateHostMem
void * allocateHostMem() override
Definition: sycl_mem_obj_t.hpp:120
sycl::_V1::detail::EventImplPtr
std::shared_ptr< event_impl > EventImplPtr
Definition: cg.hpp:42
sycl::_V1::detail::SYCLMemObjT::SYCLMemObjT
SYCLMemObjT(const size_t SizeInBytes, const property_list &Props, std::unique_ptr< SYCLMemObjAllocator > Allocator)
Definition: sycl_mem_obj_t.hpp:54
sycl::_V1::detail::pi::PiMemImageChannelOrder
::pi_image_channel_order PiMemImageChannelOrder
Definition: pi.hpp:148
sycl::_V1::detail::SYCLMemObjT::MNeedWriteBack
bool MNeedWriteBack
Definition: sycl_mem_obj_t.hpp:291
sycl::_V1::detail::SYCLMemObjT::set_final_data
void set_final_data(std::nullptr_t)
Definition: sycl_mem_obj_t.hpp:135
pi_native_handle
uintptr_t pi_native_handle
Definition: pi.h:146
sycl::_V1::detail::SYCLMemObjT::getSizeInBytes
size_t getSizeInBytes() const noexcept override
Definition: sycl_mem_obj_t.hpp:92
sycl::_V1::detail::SYCLMemObjT::handleHostData
void handleHostData(const std::function< void(void *)> &CopyFromInput, const size_t RequiredAlign, bool IsConstPtr)
Definition: sycl_mem_obj_t.hpp:223
sycl::_V1::detail::SYCLMemObjT::MOpenCLInterop
bool MOpenCLInterop
Definition: sycl_mem_obj_t.hpp:287
sycl::_V1::detail::SYCLMemObjT::MSharedPtrStorage
std::shared_ptr< const void > MSharedPtrStorage
Definition: sycl_mem_obj_t.hpp:302
sycl::_V1::detail::SYCLMemObjT::MShadowCopy
void * MShadowCopy
Definition: sycl_mem_obj_t.hpp:297
sycl::_V1::detail::SYCLMemObjT::setAlign
void setAlign(size_t RequiredAlign)
Definition: sycl_mem_obj_t.hpp:240
sycl::_V1::detail::SYCLMemObjT::MHostPtrProvided
bool MHostPtrProvided
Definition: sycl_mem_obj_t.hpp:307
std
Definition: accessor.hpp:3914
sycl::_V1::detail::SYCLMemObjT::handleHostData
void handleHostData(const void *HostPtr, const size_t RequiredAlign)
Definition: sycl_mem_obj_t.hpp:198
sycl::_V1::detail::SYCLMemObjT::MSizeInBytes
size_t MSizeInBytes
Definition: sycl_mem_obj_t.hpp:293
sycl_mem_obj_allocator.hpp
sycl::_V1::detail::SYCLMemObjI
Definition: sycl_mem_obj_i.hpp:28
sycl::_V1::detail::SYCLMemObjT
Definition: sycl_mem_obj_t.hpp:39
sycl::_V1::detail::SYCLMemObjT::set_write_back
void set_write_back(bool NeedWriteBack)
Definition: sycl_mem_obj_t.hpp:133
sycl::_V1::detail::SYCLMemObjI::MemObjType
MemObjType
Definition: sycl_mem_obj_i.hpp:32
sycl::_V1::detail::SYCLMemObjT::set_final_data_from_storage
void set_final_data_from_storage()
Definition: sycl_mem_obj_t.hpp:137
sycl::_V1::detail::SYCLMemObjT::MInteropContext
ContextImplPtr MInteropContext
Definition: sycl_mem_obj_t.hpp:281
sycl::_V1::detail::SYCLMemObjT::addOrReplaceAccessorProperties
void addOrReplaceAccessorProperties(const property_list &PropertyList)
Definition: sycl_mem_obj_t.hpp:108
sycl::_V1::detail::SYCLMemObjT::getType
MemObjType getType() const override
Definition: sycl_mem_obj_t.hpp:256
sycl::_V1::detail::pi::PiEvent
::pi_event PiEvent
Definition: pi.hpp:138
sycl::_V1::detail::SYCLMemObjT::deleteAccessorProperty
void deleteAccessorProperty(const PropWithDataKind &Kind)
Definition: sycl_mem_obj_t.hpp:112
buffer_properties.hpp
sycl::_V1::context
The context class represents a SYCL context on which kernel functions may be executed.
Definition: context.hpp:41
sycl::_V1::detail::PluginPtr
std::shared_ptr< plugin > PluginPtr
Definition: pi.hpp:47