DPC++ Runtime
Runtime libraries for oneAPI DPC++
image_impl.hpp
Go to the documentation of this file.
1 //==------------ image_impl.hpp --------------------------------------------==//
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 
13 #include <sycl/detail/common.hpp>
14 #include <sycl/detail/export.hpp>
16 #include <sycl/device.hpp>
17 #include <sycl/event.hpp>
18 #include <sycl/image.hpp>
19 #include <sycl/property_list.hpp>
20 #include <sycl/range.hpp>
21 #include <sycl/sampler.hpp>
22 
23 namespace sycl {
24 inline namespace _V1 {
25 
26 // forward declarations
27 enum class image_channel_order : unsigned int;
28 enum class image_channel_type : unsigned int;
29 
30 template <int Dimensions, typename AllocatorT> class image;
31 template <typename DataT, int Dimensions, access::mode AccessMode,
32  access::target AccessTarget, access::placeholder IsPlaceholder,
33  typename property_listT>
34 class accessor;
35 class handler;
36 
37 namespace detail {
38 
39 // utility functions and typedefs for image_impl
41 
42 // utility function: Returns the Number of Channels for a given Order.
43 __SYCL_EXPORT uint8_t getImageNumberChannels(image_channel_order Order);
44 
45 // utility function: Returns the number of bytes per image element
46 __SYCL_EXPORT uint8_t getImageElementSize(uint8_t NumChannels,
47  image_channel_type Type);
48 
51 
52 __SYCL_EXPORT image_channel_order
54 
57 
58 __SYCL_EXPORT image_channel_type
60 
61 class __SYCL_EXPORT image_impl final : public SYCLMemObjT {
62  using BaseT = SYCLMemObjT;
63  using typename BaseT::MemObjType;
64 
65 private:
66  void setPitches() {
67  size_t WHD[3] = {1, 1, 1}; // Width, Height, Depth.
68  for (int I = 0; I < MDimensions; I++)
69  WHD[I] = MRange[I];
70 
71  MRowPitch = MElementSize * WHD[0];
72  MSlicePitch = MRowPitch * WHD[1];
73  BaseT::MSizeInBytes = MSlicePitch * WHD[2];
74  }
75 
76  void setPitches(const range<2> &Pitch) {
77  MRowPitch = Pitch[0];
78  MSlicePitch =
79  (MDimensions == 3) ? Pitch[1] : MRowPitch; // Dimensions will be 2/3.
80  // NumSlices is depth when dim==3, and height when dim==2.
81  size_t NumSlices =
82  (MDimensions == 3) ? MRange[2] : MRange[1]; // Dimensions will be 2/3.
83 
84  BaseT::MSizeInBytes = MSlicePitch * NumSlices;
85  }
86 
87 public:
89  const range<3> &ImageRange,
90  std::unique_ptr<SYCLMemObjAllocator> Allocator, uint8_t Dimensions,
91  const property_list &PropList = {})
92  : image_impl((void *)nullptr, Order, Type, ImageRange,
93  std::move(Allocator), Dimensions, PropList) {}
94 
96  const range<3> &ImageRange, const range<2> &Pitch,
97  std::unique_ptr<SYCLMemObjAllocator> Allocator, uint8_t Dimensions,
98  const property_list &PropList = {})
99  : image_impl((void *)nullptr, Order, Type, ImageRange, Pitch,
100  std::move(Allocator), Dimensions, PropList) {}
101 
103  const range<3> &ImageRange,
104  std::unique_ptr<SYCLMemObjAllocator> Allocator, uint8_t Dimensions,
105  const property_list &PropList = {})
106  : BaseT(PropList, std::move(Allocator)), MDimensions(Dimensions),
107  MRange(ImageRange), MOrder(Order), MType(Type),
108  MNumChannels(getImageNumberChannels(MOrder)),
109  MElementSize(getImageElementSize(MNumChannels, MType)) {
110  setPitches();
111  BaseT::handleHostData(HData, detail::getNextPowerOfTwo(MElementSize));
112  }
113 
114  image_impl(const void *HData, image_channel_order Order,
115  image_channel_type Type, const range<3> &ImageRange,
116  std::unique_ptr<SYCLMemObjAllocator> Allocator, uint8_t Dimensions,
117  const property_list &PropList = {})
118  : BaseT(PropList, std::move(Allocator)), MDimensions(Dimensions),
119  MRange(ImageRange), MOrder(Order), MType(Type),
120  MNumChannels(getImageNumberChannels(MOrder)),
121  MElementSize(getImageElementSize(MNumChannels, MType)) {
122  setPitches();
123  BaseT::handleHostData(HData, detail::getNextPowerOfTwo(MElementSize));
124  }
125 
127  const range<3> &ImageRange, const range<2> &Pitch,
128  std::unique_ptr<SYCLMemObjAllocator> Allocator, uint8_t Dimensions,
129  const property_list &PropList = {})
130  : BaseT(PropList, std::move(Allocator)), MDimensions(Dimensions),
131  MRange(ImageRange), MOrder(Order), MType(Type),
132  MNumChannels(getImageNumberChannels(MOrder)),
133  MElementSize(getImageElementSize(MNumChannels, MType)) {
134  setPitches(Pitch);
135  BaseT::handleHostData(HData, detail::getNextPowerOfTwo(MElementSize));
136  }
137 
138  image_impl(const std::shared_ptr<const void> &HData,
140  const range<3> &ImageRange,
141  std::unique_ptr<SYCLMemObjAllocator> Allocator, uint8_t Dimensions,
142  const property_list &PropList, bool IsConstPtr)
143  : BaseT(PropList, std::move(Allocator)), MDimensions(Dimensions),
144  MRange(ImageRange), MOrder(Order), MType(Type),
145  MNumChannels(getImageNumberChannels(MOrder)),
146  MElementSize(getImageElementSize(MNumChannels, MType)) {
147  setPitches();
148  BaseT::handleHostData(std::const_pointer_cast<void>(HData),
149  detail::getNextPowerOfTwo(MElementSize), IsConstPtr);
150  }
151 
152  image_impl(const std::shared_ptr<const void> &HData,
154  const range<3> &ImageRange, const range<2> &Pitch,
155  std::unique_ptr<SYCLMemObjAllocator> Allocator, uint8_t Dimensions,
156  const property_list &PropList, bool IsConstPtr)
157  : BaseT(PropList, std::move(Allocator)), MDimensions(Dimensions),
158  MRange(ImageRange), MOrder(Order), MType(Type),
159  MNumChannels(getImageNumberChannels(MOrder)),
160  MElementSize(getImageElementSize(MNumChannels, MType)) {
161  setPitches(Pitch);
162  BaseT::handleHostData(std::const_pointer_cast<void>(HData),
163  detail::getNextPowerOfTwo(MElementSize), IsConstPtr);
164  }
165 
166  image_impl(const void *HData, image_channel_order Order,
167  image_channel_type Type, image_sampler Sampler,
168  const range<3> &ImageRange,
169  std::unique_ptr<SYCLMemObjAllocator> Allocator, uint8_t Dimensions,
170  const property_list &PropList = {})
171  : BaseT(PropList, std::move(Allocator)), MDimensions(Dimensions),
172  MRange(ImageRange), MOrder(Order), MType(Type),
173  MNumChannels(getImageNumberChannels(MOrder)),
174  MElementSize(getImageElementSize(MNumChannels, MType)),
175  MSampler(Sampler) {
176  setPitches();
177  BaseT::handleHostData(HData, detail::getNextPowerOfTwo(MElementSize));
178  }
179 
180  image_impl(const void *HData, image_channel_order Order,
181  image_channel_type Type, image_sampler Sampler,
182  const range<3> &ImageRange, const range<2> &Pitch,
183  std::unique_ptr<SYCLMemObjAllocator> Allocator, uint8_t Dimensions,
184  const property_list &PropList = {})
185  : BaseT(PropList, std::move(Allocator)), MDimensions(Dimensions),
186  MRange(ImageRange), MOrder(Order), MType(Type),
187  MNumChannels(getImageNumberChannels(MOrder)),
188  MElementSize(getImageElementSize(MNumChannels, MType)),
189  MSampler(Sampler) {
190  setPitches(Pitch);
191  BaseT::handleHostData(HData, detail::getNextPowerOfTwo(MElementSize));
192  }
193 
194  image_impl(const std::shared_ptr<const void> &HData,
196  image_sampler Sampler, const range<3> &ImageRange,
197  std::unique_ptr<SYCLMemObjAllocator> Allocator, uint8_t Dimensions,
198  const property_list &PropList)
199  : BaseT(PropList, std::move(Allocator)), MDimensions(Dimensions),
200  MRange(ImageRange), MOrder(Order), MType(Type),
201  MNumChannels(getImageNumberChannels(MOrder)),
202  MElementSize(getImageElementSize(MNumChannels, MType)),
203  MSampler(Sampler) {
204  setPitches();
205  BaseT::handleHostData(std::const_pointer_cast<void>(HData),
206  detail::getNextPowerOfTwo(MElementSize),
207  /*IsConstPtr=*/true);
208  }
209 
210  image_impl(const std::shared_ptr<const void> &HData,
212  image_sampler Sampler, const range<3> &ImageRange,
213  const range<2> &Pitch,
214  std::unique_ptr<SYCLMemObjAllocator> Allocator, uint8_t Dimensions,
215  const property_list &PropList)
216  : BaseT(PropList, std::move(Allocator)), MDimensions(Dimensions),
217  MRange(ImageRange), MOrder(Order), MType(Type),
218  MNumChannels(getImageNumberChannels(MOrder)),
219  MElementSize(getImageElementSize(MNumChannels, MType)),
220  MSampler(Sampler) {
221  setPitches(Pitch);
222  BaseT::handleHostData(std::const_pointer_cast<void>(HData),
223  detail::getNextPowerOfTwo(MElementSize),
224  /*IsConstPtr=*/true);
225  }
226 
227  image_impl(cl_mem MemObject, const context &SyclContext, event AvailableEvent,
228  std::unique_ptr<SYCLMemObjAllocator> Allocator,
229  uint8_t Dimensions);
230 
231  image_impl(pi_native_handle MemObject, const context &SyclContext,
232  event AvailableEvent,
233  std::unique_ptr<SYCLMemObjAllocator> Allocator, uint8_t Dimensions,
235  bool OwnNativeHandle, range<3> Range3WithOnes);
236 
237  // Return a range object representing the size of the image in terms of the
238  // number of elements in each dimension as passed to the constructor
239  range<3> get_range() const { return MRange; }
240 
241  // Return a range object representing the pitch of the image in bytes.
242  range<2> get_pitch() const { return {MRowPitch, MSlicePitch}; }
243 
244  // Returns the total number of elements in the image
245  size_t get_count() const { return size(); }
246  size_t size() const noexcept { return MRange.size(); }
247 
248  void *allocateMem(ContextImplPtr Context, bool InitFromUserData,
249  void *HostPtr,
250  sycl::detail::pi::PiEvent &OutEventToWait) override;
251 
252  MemObjType getType() const override { return MemObjType::Image; }
253 
254  // This utility api is currently used by accessor to get the element size of
255  // the image. Element size is dependent on num of channels and channel type.
256  // This information is not accessible from the image using any public API.
257  size_t getElementSize() const { return MElementSize; };
258 
259  image_channel_order getChannelOrder() const { return MOrder; }
260 
261  image_channel_type getChannelType() const { return MType; }
262 
263  size_t getRowPitch() const { return MRowPitch; }
264 
265  size_t getSlicePitch() const { return MSlicePitch; }
266 
268  return MSampler.value_or(image_sampler{
271  }
272 
274  try {
275  BaseT::updateHostMemory();
276  } catch (...) {
277  }
278  }
279 
281  void *UserObj, const void *HostObj,
282  uint32_t Dim, size_t Range[3],
283  image_format Format,
284  const image_sampler &Sampler);
285  void sampledImageDestructorNotification(void *UserObj);
286 
288  const detail::code_location &CodeLoc, void *UserObj, const void *HostObj,
289  uint32_t Dim, size_t Range[3], image_format Format);
290  void unsampledImageDestructorNotification(void *UserObj);
291 
292 private:
293  std::vector<device> getDevices(const ContextImplPtr Context);
294 
296  if (MDimensions == 1)
297  return (MIsArrayImage ? PI_MEM_TYPE_IMAGE1D_ARRAY : PI_MEM_TYPE_IMAGE1D);
298  if (MDimensions == 2)
299  return (MIsArrayImage ? PI_MEM_TYPE_IMAGE2D_ARRAY : PI_MEM_TYPE_IMAGE2D);
300  return PI_MEM_TYPE_IMAGE3D;
301  }
302 
303  sycl::detail::pi::PiMemImageDesc getImageDesc(bool InitFromHostPtr) {
305  Desc.image_type = getImageType();
306 
307  // MRange<> is [width], [width,height], or [width,height,depth] (which
308  // is different than MAccessRange, etc in bufffers)
309  constexpr int XTermPos = 0, YTermPos = 1, ZTermPos = 2;
310  Desc.image_width = MRange[XTermPos];
311  Desc.image_height = MDimensions > 1 ? MRange[YTermPos] : 1;
312  Desc.image_depth = MDimensions > 2 ? MRange[ZTermPos] : 1;
313 
314  // TODO handle cases with IMAGE1D_ARRAY and IMAGE2D_ARRAY
315  Desc.image_array_size = 0;
316  // Pitches must be 0 if host ptr is not provided.
317  Desc.image_row_pitch = InitFromHostPtr ? MRowPitch : 0;
318  Desc.image_slice_pitch = InitFromHostPtr ? MSlicePitch : 0;
319  Desc.num_mip_levels = 0;
320  Desc.num_samples = 0;
321  Desc.buffer = nullptr;
322  return Desc;
323  }
324 
325  bool checkImageDesc(const sycl::detail::pi::PiMemImageDesc &Desc,
326  ContextImplPtr Context, void *UserPtr);
327 
328  sycl::detail::pi::PiMemImageFormat getImageFormat() {
332  return Format;
333  }
334 
335  bool checkImageFormat(const sycl::detail::pi::PiMemImageFormat &Format,
336  ContextImplPtr Context);
337 
338  uint8_t MDimensions = 0;
339  bool MIsArrayImage = false;
340  range<3> MRange;
341  image_channel_order MOrder;
342  image_channel_type MType;
343  uint8_t MNumChannels = 0; // Maximum Value - 4
344  size_t MElementSize = 0; // Maximum Value - 16
345  size_t MRowPitch = 0;
346  size_t MSlicePitch = 0;
347 
348  // Image may carry a 2020 sampler.
349  std::optional<image_sampler> MSampler = std::nullopt;
350 };
351 } // namespace detail
352 } // namespace _V1
353 } // namespace sycl
The context class represents a SYCL context on which kernel functions may be executed.
Definition: context.hpp:51
image_impl(image_channel_order Order, image_channel_type Type, const range< 3 > &ImageRange, const range< 2 > &Pitch, std::unique_ptr< SYCLMemObjAllocator > Allocator, uint8_t Dimensions, const property_list &PropList={})
Definition: image_impl.hpp:95
image_impl(const void *HData, image_channel_order Order, image_channel_type Type, image_sampler Sampler, const range< 3 > &ImageRange, const range< 2 > &Pitch, std::unique_ptr< SYCLMemObjAllocator > Allocator, uint8_t Dimensions, const property_list &PropList={})
Definition: image_impl.hpp:180
image_impl(const std::shared_ptr< const void > &HData, image_channel_order Order, image_channel_type Type, const range< 3 > &ImageRange, std::unique_ptr< SYCLMemObjAllocator > Allocator, uint8_t Dimensions, const property_list &PropList, bool IsConstPtr)
Definition: image_impl.hpp:138
image_sampler getSampler() const noexcept
Definition: image_impl.hpp:267
image_channel_type getChannelType() const
Definition: image_impl.hpp:261
range< 3 > get_range() const
Definition: image_impl.hpp:239
image_impl(void *HData, image_channel_order Order, image_channel_type Type, const range< 3 > &ImageRange, std::unique_ptr< SYCLMemObjAllocator > Allocator, uint8_t Dimensions, const property_list &PropList={})
Definition: image_impl.hpp:102
MemObjType getType() const override
Definition: image_impl.hpp:252
image_impl(const void *HData, image_channel_order Order, image_channel_type Type, image_sampler Sampler, const range< 3 > &ImageRange, std::unique_ptr< SYCLMemObjAllocator > Allocator, uint8_t Dimensions, const property_list &PropList={})
Definition: image_impl.hpp:166
image_impl(const std::shared_ptr< const void > &HData, image_channel_order Order, image_channel_type Type, image_sampler Sampler, const range< 3 > &ImageRange, const range< 2 > &Pitch, std::unique_ptr< SYCLMemObjAllocator > Allocator, uint8_t Dimensions, const property_list &PropList)
Definition: image_impl.hpp:210
image_impl(const std::shared_ptr< const void > &HData, image_channel_order Order, image_channel_type Type, const range< 3 > &ImageRange, const range< 2 > &Pitch, std::unique_ptr< SYCLMemObjAllocator > Allocator, uint8_t Dimensions, const property_list &PropList, bool IsConstPtr)
Definition: image_impl.hpp:152
range< 2 > get_pitch() const
Definition: image_impl.hpp:242
image_impl(const std::shared_ptr< const void > &HData, image_channel_order Order, image_channel_type Type, image_sampler Sampler, const range< 3 > &ImageRange, std::unique_ptr< SYCLMemObjAllocator > Allocator, uint8_t Dimensions, const property_list &PropList)
Definition: image_impl.hpp:194
size_t size() const noexcept
Definition: image_impl.hpp:246
image_impl(void *HData, image_channel_order Order, image_channel_type Type, const range< 3 > &ImageRange, const range< 2 > &Pitch, std::unique_ptr< SYCLMemObjAllocator > Allocator, uint8_t Dimensions, const property_list &PropList={})
Definition: image_impl.hpp:126
image_impl(const void *HData, image_channel_order Order, image_channel_type Type, const range< 3 > &ImageRange, std::unique_ptr< SYCLMemObjAllocator > Allocator, uint8_t Dimensions, const property_list &PropList={})
Definition: image_impl.hpp:114
image_impl(image_channel_order Order, image_channel_type Type, const range< 3 > &ImageRange, std::unique_ptr< SYCLMemObjAllocator > Allocator, uint8_t Dimensions, const property_list &PropList={})
Definition: image_impl.hpp:88
image_channel_order getChannelOrder() const
Definition: image_impl.hpp:259
An event object can be used to synchronize memory transfers, enqueues of kernels and signaling barrie...
Definition: event.hpp:44
Objects of the property_list class are containers for the SYCL properties.
Defines the iteration domain of either a single work-group in a parallel dispatch,...
Definition: range.hpp:26
class __SYCL_EBO __SYCL_SPECIAL_CLASS __SYCL_TYPE(accessor) accessor accessor(buffer< DataT, Dimensions, AllocatorT >) -> accessor< DataT, Dimensions, access::mode::read_write, target::device, access::placeholder::true_t >
Buffer accessor.
void unsampledImageConstructorNotification(void *ImageObj, void *AccessorObj, const std::optional< image_target > &Target, access::mode Mode, const void *Type, uint32_t ElemSize, const code_location &CodeLoc)
uint8_t getImageElementSize(uint8_t NumChannels, image_channel_type Type)
Definition: image_impl.cpp:74
sycl::detail::pi::PiMemImageChannelOrder convertChannelOrder(image_channel_order Order)
Definition: image_impl.cpp:111
std::shared_ptr< sycl::detail::context_impl > ContextImplPtr
Definition: event_impl.hpp:32
sycl::detail::pi::PiMemObjectType getImageType(int Dimensions)
constexpr size_t getNextPowerOfTwo(size_t Var)
Definition: common.hpp:361
void sampledImageConstructorNotification(void *ImageObj, void *AccessorObj, const std::optional< image_target > &Target, const void *Type, uint32_t ElemSize, const code_location &CodeLoc)
sycl::detail::pi::PiMemImageChannelType convertChannelType(image_channel_type Type)
Definition: image_impl.cpp:187
uint8_t getImageNumberChannels(image_channel_order Order)
Definition: image_impl.cpp:47
std::shared_ptr< sycl::detail::context_impl > ContextImplPtr
Definition: helpers.cpp:22
class __SYCL_EBO __SYCL_SPECIAL_CLASS __SYCL_TYPE(local_accessor) local_accessor class __SYCL_EBO __SYCL_SPECIAL_CLASS Dimensions
Definition: accessor.hpp:3233
image_channel_order
Definition: image.hpp:56
image_format
Definition: image.hpp:93
image_channel_type
Definition: image.hpp:74
Definition: access.hpp:18
uintptr_t pi_native_handle
Definition: pi.h:209
_pi_image_channel_type
Definition: pi.h:645
_pi_image_channel_order
Definition: pi.h:627
_pi_mem_type
Definition: pi.h:576
@ PI_MEM_TYPE_IMAGE1D
Definition: pi.h:581
@ PI_MEM_TYPE_IMAGE1D_ARRAY
Definition: pi.h:582
@ PI_MEM_TYPE_IMAGE2D
Definition: pi.h:578
@ PI_MEM_TYPE_IMAGE2D_ARRAY
Definition: pi.h:580
@ PI_MEM_TYPE_IMAGE3D
Definition: pi.h:579
_Abi const simd< _Tp, _Abi > & noexcept
Definition: simd.hpp:1324
size_t image_slice_pitch
Definition: pi.h:1154
pi_uint32 num_mip_levels
Definition: pi.h:1155
size_t image_height
Definition: pi.h:1150
size_t image_row_pitch
Definition: pi.h:1153
pi_uint32 num_samples
Definition: pi.h:1156
size_t image_depth
Definition: pi.h:1151
pi_mem buffer
Definition: pi.h:1157
size_t image_width
Definition: pi.h:1149
pi_mem_type image_type
Definition: pi.h:1148
size_t image_array_size
Definition: pi.h:1152
pi_image_channel_type image_channel_data_type
Definition: pi.h:1144
pi_image_channel_order image_channel_order
Definition: pi.h:1143