DPC++ Runtime
Runtime libraries for oneAPI DPC++
image_impl.cpp
Go to the documentation of this file.
1 //==------------ image_impl.cpp --------------------------------------------==//
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/image_impl.hpp>
12 #include <detail/xpti_registry.hpp>
13 
14 #include <algorithm>
15 #include <vector>
16 
17 namespace sycl {
18 inline namespace _V1 {
19 namespace detail {
20 #ifdef XPTI_ENABLE_INSTRUMENTATION
21 uint8_t GImageStreamID;
22 #endif
23 
24 template <typename Param>
25 static bool checkImageValueRange(const std::vector<device> &Devices,
26  const size_t Value) {
27  return Value >= 1 && std::all_of(Devices.cbegin(), Devices.cend(),
28  [Value](const device &Dev) {
29  return Value <= Dev.get_info<Param>();
30  });
31 }
32 
33 template <typename T, typename... Args> static bool checkAnyImpl(T) {
34  return false;
35 }
36 
37 template <typename ValT, typename VarT, typename... Args>
38 static bool checkAnyImpl(ValT Value, VarT Variant, Args... Arguments) {
39  return (Value == Variant) ? true : checkAnyImpl(Value, Arguments...);
40 }
41 
42 template <typename T, typename... Args>
43 static bool checkAny(const T Value, Args... Arguments) {
44  return checkAnyImpl(Value, Arguments...);
45 }
46 
48  switch (Order) {
54  return 1;
58  return 2;
60  return 3;
67  return 4;
68  }
69  assert(false && "Unhandled image channel order");
70  return 0;
71 }
72 
73 // Returns the number of bytes per image element
74 uint8_t getImageElementSize(uint8_t NumChannels, image_channel_type Type) {
75  size_t Retval = 0;
76  switch (Type) {
81  Retval = NumChannels;
82  break;
88  Retval = 2 * NumChannels;
89  break;
93  Retval = 4 * NumChannels;
94  break;
97  Retval = 2;
98  break;
100  Retval = 4;
101  break;
102  }
103  // OpenCL states that "The number of bits per element determined by the
104  // image_channel_type and image_channel_order must be a power of two"
105  // Retval is in bytes. The formula remains the same for bytes or bits.
106  assert(((Retval - 1) & Retval) == 0);
107  return Retval;
108 }
109 
112  switch (Order) {
143  }
144  assert(false && "Unhandled image_channel_order");
145  return static_cast<sycl::detail::pi::PiMemImageChannelOrder>(0);
146 }
147 
150  switch (Order) {
152  return image_channel_order::a;
154  return image_channel_order::r;
181  }
182  assert(false && "Unhandled image_channel_order");
183  return static_cast<image_channel_order>(0);
184 }
185 
188  switch (Type) {
219  }
220  assert(false && "Unhandled image_channel_order");
221  return static_cast<sycl::detail::pi::PiMemImageChannelType>(0);
222 }
223 
226  switch (Type) {
257  }
258  assert(false && "Unhandled image_channel_order");
259  return static_cast<image_channel_type>(0);
260 }
261 
262 template <typename T>
263 static void getImageInfo(const ContextImplPtr Context,
264  sycl::detail::pi::PiMemImageInfo Info, T &Dest,
265  sycl::detail::pi::PiMem InteropMemObject) {
266  const PluginPtr &Plugin = Context->getPlugin();
268  pi::cast<sycl::detail::pi::PiMem>(InteropMemObject);
269  Plugin->call<PiApiKind::piMemImageGetInfo>(Mem, Info, sizeof(T), &Dest,
270  nullptr);
271 }
272 
273 image_impl::image_impl(cl_mem MemObject, const context &SyclContext,
274  event AvailableEvent,
275  std::unique_ptr<SYCLMemObjAllocator> Allocator,
276  uint8_t Dimensions)
277  : BaseT(MemObject, SyclContext, std::move(AvailableEvent),
278  std::move(Allocator)),
279  MDimensions(Dimensions), MRange({0, 0, 0}) {
281  pi::cast<sycl::detail::pi::PiMem>(BaseT::MInteropMemObject);
282  const ContextImplPtr Context = getSyclObjImpl(SyclContext);
283  const PluginPtr &Plugin = Context->getPlugin();
284  Plugin->call<PiApiKind::piMemGetInfo>(Mem, PI_MEM_SIZE, sizeof(size_t),
285  &(BaseT::MSizeInBytes), nullptr);
286 
288  getImageInfo(Context, PI_IMAGE_INFO_FORMAT, Format, Mem);
289  MOrder = detail::convertChannelOrder(Format.image_channel_order);
290  MType = detail::convertChannelType(Format.image_channel_data_type);
291  MNumChannels = getImageNumberChannels(MOrder);
292 
293  getImageInfo(Context, PI_IMAGE_INFO_ELEMENT_SIZE, MElementSize, Mem);
294  assert(getImageElementSize(MNumChannels, MType) == MElementSize);
295 
296  getImageInfo(Context, PI_IMAGE_INFO_ROW_PITCH, MRowPitch, Mem);
297  getImageInfo(Context, PI_IMAGE_INFO_SLICE_PITCH, MSlicePitch, Mem);
298 
299  switch (MDimensions) {
300  case 3:
301  getImageInfo(Context, PI_IMAGE_INFO_DEPTH, MRange[2], Mem);
302  [[fallthrough]];
303  case 2:
304  getImageInfo(Context, PI_IMAGE_INFO_HEIGHT, MRange[1], Mem);
305  [[fallthrough]];
306  case 1:
307  getImageInfo(Context, PI_IMAGE_INFO_WIDTH, MRange[0], Mem);
308  }
309 }
310 
311 image_impl::image_impl(pi_native_handle MemObject, const context &SyclContext,
312  event AvailableEvent,
313  std::unique_ptr<SYCLMemObjAllocator> Allocator,
314  uint8_t Dimensions, image_channel_order Order,
315  image_channel_type Type, bool OwnNativeHandle,
316  range<3> Range3WithOnes)
317  : BaseT(MemObject, SyclContext, OwnNativeHandle, std::move(AvailableEvent),
318  std::move(Allocator), detail::convertChannelOrder(Order),
319  detail::convertChannelType(Type), Range3WithOnes, Dimensions,
321  MDimensions(Dimensions), MRange(Range3WithOnes) {
322  MOrder = Order;
323  MType = Type;
324  MNumChannels = getImageNumberChannels(MOrder);
325  MElementSize = getImageElementSize(MNumChannels, Type);
326  setPitches(); // sets MRowPitch, MSlice and BaseT::MSizeInBytes
327 }
328 
329 void *image_impl::allocateMem(ContextImplPtr Context, bool InitFromUserData,
330  void *HostPtr,
331  sycl::detail::pi::PiEvent &OutEventToWait) {
332  bool HostPtrReadOnly = false;
333  BaseT::determineHostPtr(InitFromUserData, HostPtr, HostPtrReadOnly);
334 
335  sycl::detail::pi::PiMemImageDesc Desc = getImageDesc(HostPtr != nullptr);
336  assert(checkImageDesc(Desc, Context, HostPtr) &&
337  "The check an image desc failed.");
338 
339  sycl::detail::pi::PiMemImageFormat Format = getImageFormat();
340  assert(checkImageFormat(Format, Context) &&
341  "The check an image format failed.");
342 
344  std::move(Context), this, HostPtr, HostPtrReadOnly,
346  BaseT::MInteropContext, MProps, OutEventToWait);
347 }
348 
349 bool image_impl::checkImageDesc(const sycl::detail::pi::PiMemImageDesc &Desc,
350  ContextImplPtr Context, void *UserPtr) {
353  !checkImageValueRange<info::device::image2d_max_width>(
354  getDevices(Context), Desc.image_width))
356  "For a 1D/2D image/image array, the width must be a Value "
357  ">= 1 and <= info::device::image2d_max_width");
358 
360  !checkImageValueRange<info::device::image3d_max_width>(
361  getDevices(Context), Desc.image_width))
363  "For a 3D image, the width must be a Value >= 1 and <= "
364  "info::device::image3d_max_width");
365 
368  !checkImageValueRange<info::device::image2d_max_height>(
369  getDevices(Context), Desc.image_height))
371  "For a 2D image or image array, the height must be a Value "
372  ">= 1 and <= info::device::image2d_max_height");
373 
375  !checkImageValueRange<info::device::image3d_max_height>(
376  getDevices(Context), Desc.image_height))
378  "For a 3D image, the heightmust be a Value >= 1 and <= "
379  "info::device::image3d_max_height");
380 
382  !checkImageValueRange<info::device::image3d_max_depth>(
383  getDevices(Context), Desc.image_depth))
385  "For a 3D image, the depth must be a Value >= 1 and <= "
386  "info::device::image2d_max_depth");
387 
390  !checkImageValueRange<info::device::image_max_array_size>(
391  getDevices(Context), Desc.image_array_size))
393  "For a 1D and 2D image array, the array_size must be a "
394  "Value >= 1 and <= info::device::image_max_array_size.");
395 
396  if ((nullptr == UserPtr) && (0 != Desc.image_row_pitch))
398  "The row_pitch must be 0 if host_ptr is nullptr.");
399 
400  if ((nullptr == UserPtr) && (0 != Desc.image_slice_pitch))
402  "The slice_pitch must be 0 if host_ptr is nullptr.");
403 
404  if (0 != Desc.num_mip_levels)
406  "The mip_levels must be 0.");
407 
408  if (0 != Desc.num_samples)
410  "The num_samples must be 0.");
411 
412  if (nullptr != Desc.buffer)
414  "The buffer must be nullptr, because SYCL does not support "
415  "image creation from memory objects.");
416 
417  return true;
418 }
419 
420 bool image_impl::checkImageFormat(
421  const sycl::detail::pi::PiMemImageFormat &Format, ContextImplPtr Context) {
422  (void)Context;
425  !checkAny(
430  throw exception(
432  "CL_INTENSITY or CL_LUMINANCE format can only be used if channel data "
433  "type = CL_UNORM_INT8, CL_UNORM_INT16, CL_SNORM_INT8, CL_SNORM_INT16, "
434  "CL_HALF_FLOAT, or CL_FLOAT.");
435 
443  "type = CL_UNORM_SHORT_565, CL_UNORM_SHORT_555 or "
444  "CL_UNORM_INT_101010. These channel types can only be used "
445  "with CL_RGB or CL_RGBx channel order.");
446 
449  !checkAny(
453  throw exception(
455  "CL_ARGB, CL_BGRA, CL_ABGR These formats can only be used if "
456  "channel data type = CL_UNORM_INT8, CL_SNORM_INT8, CL_SIGNED_INT8 "
457  "or CL_UNSIGNED_INT8.");
458 
459  return true;
460 }
461 
462 std::vector<device> image_impl::getDevices(const ContextImplPtr Context) {
463  if (!Context)
464  return {};
465  return Context->get_info<info::context::devices>();
466 }
467 
469  const detail::code_location &CodeLoc, void *UserObj, const void *HostObj,
470  uint32_t Dim, size_t Range[3], image_format Format,
471  const image_sampler &Sampler) {
473  UserObj, CodeLoc, HostObj, Dim, Range, (uint32_t)Format,
474  (uint32_t)Sampler.addressing, (uint32_t)Sampler.coordinate,
475  (uint32_t)Sampler.filtering);
476 }
477 
480 }
481 
483  const detail::code_location &CodeLoc, void *UserObj, const void *HostObj,
484  uint32_t Dim, size_t Range[3], image_format Format) {
486  UserObj, CodeLoc, HostObj, Dim, Range, (uint32_t)Format);
487 }
488 
491 }
492 
493 } // namespace detail
494 } // namespace _V1
495 } // namespace sycl
The context class represents a SYCL context on which kernel functions may be executed.
Definition: context.hpp:50
static void * allocateMemImage(ContextImplPtr TargetContext, SYCLMemObjI *MemObj, void *UserPtr, bool HostPtrReadOnly, size_t Size, const sycl::detail::pi::PiMemImageDesc &Desc, const sycl::detail::pi::PiMemImageFormat &Format, const EventImplPtr &InteropEvent, const ContextImplPtr &InteropContext, const sycl::property_list &PropsList, sycl::detail::pi::PiEvent &OutEventToWait)
void determineHostPtr(bool InitFromUserData, void *&HostPtr, bool &HostPtrReadOnly)
size_t getSizeInBytes() const noexcept override
static void sampledImageDestructorNotification(const void *)
static void unsampledImageDestructorNotification(const void *)
static void unsampledImageConstructorNotification(const void *, const detail::code_location &, const void *, uint32_t, size_t[3], uint32_t)
static void sampledImageConstructorNotification(const void *, const detail::code_location &, const void *, uint32_t, size_t[3], uint32_t, uint32_t, uint32_t, uint32_t)
void * allocateMem(ContextImplPtr Context, bool InitFromUserData, void *HostPtr, sycl::detail::pi::PiEvent &OutEventToWait) override
Definition: image_impl.cpp:329
void unsampledImageConstructorNotification(const detail::code_location &CodeLoc, void *UserObj, const void *HostObj, uint32_t Dim, size_t Range[3], image_format Format)
Definition: image_impl.cpp:482
void sampledImageConstructorNotification(const detail::code_location &CodeLoc, void *UserObj, const void *HostObj, uint32_t Dim, size_t Range[3], image_format Format, const image_sampler &Sampler)
Definition: image_impl.cpp:468
void sampledImageDestructorNotification(void *UserObj)
Definition: image_impl.cpp:478
void unsampledImageDestructorNotification(void *UserObj)
Definition: image_impl.cpp:489
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:87
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:64
An event object can be used to synchronize memory transfers, enqueues of kernels and signaling barrie...
Definition: event.hpp:44
decltype(Obj::impl) const & getSyclObjImpl(const Obj &SyclObject)
Definition: impl_utils.hpp:31
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
static bool checkAny(const T Value, Args... Arguments)
Definition: image_impl.cpp:43
std::shared_ptr< sycl::detail::context_impl > ContextImplPtr
Definition: event_impl.hpp:32
static bool checkImageValueRange(const std::vector< device > &Devices, const size_t Value)
Definition: image_impl.cpp:25
std::shared_ptr< plugin > PluginPtr
Definition: pi.hpp:47
static bool checkAnyImpl(T)
Definition: image_impl.cpp:33
static void getImageInfo(const ContextImplPtr Context, sycl::detail::pi::PiMemImageInfo Info, T &Dest, sycl::detail::pi::PiMem InteropMemObject)
Definition: image_impl.cpp:263
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 Dimensions
image_channel_order
Definition: image.hpp:56
image_format
Definition: image.hpp:93
image_channel_type
Definition: image.hpp:74
std::error_code make_error_code(sycl::errc E) noexcept
Constructs an error code using e and sycl_category()
Definition: exception.cpp:64
Definition: access.hpp:18
uintptr_t pi_native_handle
Definition: pi.h:258
pi_result piMemImageGetInfo(pi_mem image, pi_image_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret)
Definition: pi_cuda.cpp:805
_pi_image_channel_type
Definition: pi.h:725
@ PI_IMAGE_CHANNEL_TYPE_FLOAT
Definition: pi.h:740
@ PI_IMAGE_CHANNEL_TYPE_UNORM_SHORT_565
Definition: pi.h:730
@ PI_IMAGE_CHANNEL_TYPE_UNORM_INT8
Definition: pi.h:728
@ PI_IMAGE_CHANNEL_TYPE_SIGNED_INT16
Definition: pi.h:734
@ PI_IMAGE_CHANNEL_TYPE_SNORM_INT16
Definition: pi.h:727
@ PI_IMAGE_CHANNEL_TYPE_UNSIGNED_INT8
Definition: pi.h:736
@ PI_IMAGE_CHANNEL_TYPE_SIGNED_INT8
Definition: pi.h:733
@ PI_IMAGE_CHANNEL_TYPE_UNORM_INT_101010
Definition: pi.h:732
@ PI_IMAGE_CHANNEL_TYPE_UNSIGNED_INT32
Definition: pi.h:738
@ PI_IMAGE_CHANNEL_TYPE_UNSIGNED_INT16
Definition: pi.h:737
@ PI_IMAGE_CHANNEL_TYPE_SNORM_INT8
Definition: pi.h:726
@ PI_IMAGE_CHANNEL_TYPE_UNORM_SHORT_555
Definition: pi.h:731
@ PI_IMAGE_CHANNEL_TYPE_SIGNED_INT32
Definition: pi.h:735
@ PI_IMAGE_CHANNEL_TYPE_HALF_FLOAT
Definition: pi.h:739
@ PI_IMAGE_CHANNEL_TYPE_UNORM_INT16
Definition: pi.h:729
pi_result piMemGetInfo(pi_mem mem, pi_mem_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret)
Definition: pi_cuda.cpp:217
_pi_image_info
Definition: pi.h:595
@ PI_IMAGE_INFO_HEIGHT
Definition: pi.h:601
@ PI_IMAGE_INFO_SLICE_PITCH
Definition: pi.h:599
@ PI_IMAGE_INFO_ROW_PITCH
Definition: pi.h:598
@ PI_IMAGE_INFO_WIDTH
Definition: pi.h:600
@ PI_IMAGE_INFO_FORMAT
Definition: pi.h:596
@ PI_IMAGE_INFO_ELEMENT_SIZE
Definition: pi.h:597
@ PI_IMAGE_INFO_DEPTH
Definition: pi.h:602
_pi_image_channel_order
Definition: pi.h:707
@ PI_IMAGE_CHANNEL_ORDER_RGB
Definition: pi.h:712
@ PI_IMAGE_CHANNEL_ORDER_RA
Definition: pi.h:711
@ PI_IMAGE_CHANNEL_ORDER_RGBA
Definition: pi.h:713
@ PI_IMAGE_CHANNEL_ORDER_INTENSITY
Definition: pi.h:717
@ PI_IMAGE_CHANNEL_ORDER_R
Definition: pi.h:709
@ PI_IMAGE_CHANNEL_ORDER_ABGR
Definition: pi.h:716
@ PI_IMAGE_CHANNEL_ORDER_RGBx
Definition: pi.h:721
@ PI_IMAGE_CHANNEL_ORDER_RG
Definition: pi.h:710
@ PI_IMAGE_CHANNEL_ORDER_BGRA
Definition: pi.h:714
@ PI_IMAGE_CHANNEL_ORDER_Rx
Definition: pi.h:719
@ PI_IMAGE_CHANNEL_ORDER_A
Definition: pi.h:708
@ PI_IMAGE_CHANNEL_ORDER_sRGBA
Definition: pi.h:722
@ PI_IMAGE_CHANNEL_ORDER_LUMINANCE
Definition: pi.h:718
@ PI_IMAGE_CHANNEL_ORDER_RGx
Definition: pi.h:720
@ PI_IMAGE_CHANNEL_ORDER_ARGB
Definition: pi.h:715
@ PI_MEM_TYPE_IMAGE1D
Definition: pi.h:660
@ PI_MEM_TYPE_IMAGE1D_ARRAY
Definition: pi.h:661
@ PI_MEM_TYPE_IMAGE2D
Definition: pi.h:657
@ PI_MEM_TYPE_IMAGE2D_ARRAY
Definition: pi.h:659
@ PI_MEM_TYPE_IMAGE3D
Definition: pi.h:658
@ PI_MEM_SIZE
Definition: pi.h:1324
bool all_of(const simd_mask< _Tp, _Abi > &) noexcept
size_t image_slice_pitch
Definition: pi.h:1315
pi_uint32 num_mip_levels
Definition: pi.h:1316
size_t image_height
Definition: pi.h:1311
size_t image_row_pitch
Definition: pi.h:1314
pi_uint32 num_samples
Definition: pi.h:1317
size_t image_depth
Definition: pi.h:1312
pi_mem buffer
Definition: pi.h:1318
size_t image_width
Definition: pi.h:1310
pi_mem_type image_type
Definition: pi.h:1309
size_t image_array_size
Definition: pi.h:1313
pi_image_channel_type image_channel_data_type
Definition: pi.h:1305
pi_image_channel_order image_channel_order
Definition: pi.h:1304
addressing_mode addressing
Definition: sampler.hpp:141
coordinate_normalization_mode coordinate
Definition: sampler.hpp:142
filtering_mode filtering
Definition: sampler.hpp:143