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(Context, 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))
355  throw invalid_parameter_error(
356  "For a 1D/2D image/image array, the width must be a Value >= 1 and "
357  "<= info::device::image2d_max_width",
358  PI_ERROR_INVALID_VALUE);
359 
361  !checkImageValueRange<info::device::image3d_max_width>(
362  getDevices(Context), Desc.image_width))
363  throw invalid_parameter_error(
364  "For a 3D image, the width must be a Value >= 1 and <= "
365  "info::device::image3d_max_width",
366  PI_ERROR_INVALID_VALUE);
367 
370  !checkImageValueRange<info::device::image2d_max_height>(
371  getDevices(Context), Desc.image_height))
372  throw invalid_parameter_error("For a 2D image or image array, the height "
373  "must be a Value >= 1 and <= "
374  "info::device::image2d_max_height",
375  PI_ERROR_INVALID_VALUE);
376 
378  !checkImageValueRange<info::device::image3d_max_height>(
379  getDevices(Context), Desc.image_height))
380  throw invalid_parameter_error(
381  "For a 3D image, the heightmust be a Value >= 1 and <= "
382  "info::device::image3d_max_height",
383  PI_ERROR_INVALID_VALUE);
384 
386  !checkImageValueRange<info::device::image3d_max_depth>(
387  getDevices(Context), Desc.image_depth))
388  throw invalid_parameter_error(
389  "For a 3D image, the depth must be a Value >= 1 and <= "
390  "info::device::image2d_max_depth",
391  PI_ERROR_INVALID_VALUE);
392 
395  !checkImageValueRange<info::device::image_max_array_size>(
396  getDevices(Context), Desc.image_array_size))
397  throw invalid_parameter_error(
398  "For a 1D and 2D image array, the array_size must be a "
399  "Value >= 1 and <= info::device::image_max_array_size.",
400  PI_ERROR_INVALID_VALUE);
401 
402  if ((nullptr == UserPtr) && (0 != Desc.image_row_pitch))
403  throw invalid_parameter_error(
404  "The row_pitch must be 0 if host_ptr is nullptr.",
405  PI_ERROR_INVALID_VALUE);
406 
407  if ((nullptr == UserPtr) && (0 != Desc.image_slice_pitch))
408  throw invalid_parameter_error(
409  "The slice_pitch must be 0 if host_ptr is nullptr.",
410  PI_ERROR_INVALID_VALUE);
411 
412  if (0 != Desc.num_mip_levels)
413  throw invalid_parameter_error("The mip_levels must be 0.",
414  PI_ERROR_INVALID_VALUE);
415 
416  if (0 != Desc.num_samples)
417  throw invalid_parameter_error("The num_samples must be 0.",
418  PI_ERROR_INVALID_VALUE);
419 
420  if (nullptr != Desc.buffer)
421  throw invalid_parameter_error(
422  "The buffer must be nullptr, because SYCL does not support "
423  "image creation from memory objects.",
424  PI_ERROR_INVALID_VALUE);
425 
426  return true;
427 }
428 
429 bool image_impl::checkImageFormat(
430  const sycl::detail::pi::PiMemImageFormat &Format, ContextImplPtr Context) {
431  (void)Context;
434  !checkAny(
439  throw invalid_parameter_error(
440  "CL_INTENSITY or CL_LUMINANCE format can only be used if channel "
441  "data type = CL_UNORM_INT8, CL_UNORM_INT16, CL_SNORM_INT8, "
442  "CL_SNORM_INT16, CL_HALF_FLOAT, or CL_FLOAT.",
443  PI_ERROR_INVALID_VALUE);
444 
451  throw invalid_parameter_error(
452  "type = CL_UNORM_SHORT_565, CL_UNORM_SHORT_555 or "
453  "CL_UNORM_INT_101010."
454  "These channel types can only be used with CL_RGB or CL_RGBx channel "
455  "order.",
456  PI_ERROR_INVALID_VALUE);
457 
460  !checkAny(
464  throw invalid_parameter_error(
465  "CL_ARGB, CL_BGRA, CL_ABGR These formats can only be used if "
466  "channel data type = CL_UNORM_INT8, CL_SNORM_INT8, CL_SIGNED_INT8 "
467  "or CL_UNSIGNED_INT8.",
468  PI_ERROR_INVALID_VALUE);
469 
470  return true;
471 }
472 
473 std::vector<device> image_impl::getDevices(const ContextImplPtr Context) {
474  return Context->get_info<info::context::devices>();
475 }
476 
478  const detail::code_location &CodeLoc, void *UserObj, const void *HostObj,
479  uint32_t Dim, size_t Range[3], image_format Format,
480  const image_sampler &Sampler) {
482  UserObj, CodeLoc, HostObj, Dim, Range, (uint32_t)Format,
483  (uint32_t)Sampler.addressing, (uint32_t)Sampler.coordinate,
484  (uint32_t)Sampler.filtering);
485 }
486 
489 }
490 
492  const detail::code_location &CodeLoc, void *UserObj, const void *HostObj,
493  uint32_t Dim, size_t Range[3], image_format Format) {
495  UserObj, CodeLoc, HostObj, Dim, Range, (uint32_t)Format);
496 }
497 
500 }
501 
502 } // namespace detail
503 } // namespace _V1
504 } // 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)
size_t getSizeInBytes() const noexcept override
void determineHostPtr(const ContextImplPtr &Context, bool InitFromUserData, void *&HostPtr, bool &HostPtrReadOnly)
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:491
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:477
void sampledImageDestructorNotification(void *UserObj)
Definition: image_impl.cpp:487
void unsampledImageDestructorNotification(void *UserObj)
Definition: image_impl.cpp:498
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
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
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
decltype(Obj::impl) getSyclObjImpl(const Obj &SyclObject)
Definition: impl_utils.hpp:30
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:48
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
Definition: access.hpp:18
uintptr_t pi_native_handle
Definition: pi.h:217
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:781
_pi_image_channel_type
Definition: pi.h:658
@ PI_IMAGE_CHANNEL_TYPE_FLOAT
Definition: pi.h:673
@ PI_IMAGE_CHANNEL_TYPE_UNORM_SHORT_565
Definition: pi.h:663
@ PI_IMAGE_CHANNEL_TYPE_UNORM_INT8
Definition: pi.h:661
@ PI_IMAGE_CHANNEL_TYPE_SIGNED_INT16
Definition: pi.h:667
@ PI_IMAGE_CHANNEL_TYPE_SNORM_INT16
Definition: pi.h:660
@ PI_IMAGE_CHANNEL_TYPE_UNSIGNED_INT8
Definition: pi.h:669
@ PI_IMAGE_CHANNEL_TYPE_SIGNED_INT8
Definition: pi.h:666
@ PI_IMAGE_CHANNEL_TYPE_UNORM_INT_101010
Definition: pi.h:665
@ PI_IMAGE_CHANNEL_TYPE_UNSIGNED_INT32
Definition: pi.h:671
@ PI_IMAGE_CHANNEL_TYPE_UNSIGNED_INT16
Definition: pi.h:670
@ PI_IMAGE_CHANNEL_TYPE_SNORM_INT8
Definition: pi.h:659
@ PI_IMAGE_CHANNEL_TYPE_UNORM_SHORT_555
Definition: pi.h:664
@ PI_IMAGE_CHANNEL_TYPE_SIGNED_INT32
Definition: pi.h:668
@ PI_IMAGE_CHANNEL_TYPE_HALF_FLOAT
Definition: pi.h:672
@ PI_IMAGE_CHANNEL_TYPE_UNORM_INT16
Definition: pi.h:662
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:528
@ PI_IMAGE_INFO_HEIGHT
Definition: pi.h:534
@ PI_IMAGE_INFO_SLICE_PITCH
Definition: pi.h:532
@ PI_IMAGE_INFO_ROW_PITCH
Definition: pi.h:531
@ PI_IMAGE_INFO_WIDTH
Definition: pi.h:533
@ PI_IMAGE_INFO_FORMAT
Definition: pi.h:529
@ PI_IMAGE_INFO_ELEMENT_SIZE
Definition: pi.h:530
@ PI_IMAGE_INFO_DEPTH
Definition: pi.h:535
_pi_image_channel_order
Definition: pi.h:640
@ PI_IMAGE_CHANNEL_ORDER_RGB
Definition: pi.h:645
@ PI_IMAGE_CHANNEL_ORDER_RA
Definition: pi.h:644
@ PI_IMAGE_CHANNEL_ORDER_RGBA
Definition: pi.h:646
@ PI_IMAGE_CHANNEL_ORDER_INTENSITY
Definition: pi.h:650
@ PI_IMAGE_CHANNEL_ORDER_R
Definition: pi.h:642
@ PI_IMAGE_CHANNEL_ORDER_ABGR
Definition: pi.h:649
@ PI_IMAGE_CHANNEL_ORDER_RGBx
Definition: pi.h:654
@ PI_IMAGE_CHANNEL_ORDER_RG
Definition: pi.h:643
@ PI_IMAGE_CHANNEL_ORDER_BGRA
Definition: pi.h:647
@ PI_IMAGE_CHANNEL_ORDER_Rx
Definition: pi.h:652
@ PI_IMAGE_CHANNEL_ORDER_A
Definition: pi.h:641
@ PI_IMAGE_CHANNEL_ORDER_sRGBA
Definition: pi.h:655
@ PI_IMAGE_CHANNEL_ORDER_LUMINANCE
Definition: pi.h:651
@ PI_IMAGE_CHANNEL_ORDER_RGx
Definition: pi.h:653
@ PI_IMAGE_CHANNEL_ORDER_ARGB
Definition: pi.h:648
@ PI_MEM_TYPE_IMAGE1D
Definition: pi.h:593
@ PI_MEM_TYPE_IMAGE1D_ARRAY
Definition: pi.h:594
@ PI_MEM_TYPE_IMAGE2D
Definition: pi.h:590
@ PI_MEM_TYPE_IMAGE2D_ARRAY
Definition: pi.h:592
@ PI_MEM_TYPE_IMAGE3D
Definition: pi.h:591
@ PI_MEM_SIZE
Definition: pi.h:1183
bool all_of(const simd_mask< _Tp, _Abi > &) noexcept
size_t image_slice_pitch
Definition: pi.h:1174
pi_uint32 num_mip_levels
Definition: pi.h:1175
size_t image_height
Definition: pi.h:1170
size_t image_row_pitch
Definition: pi.h:1173
pi_uint32 num_samples
Definition: pi.h:1176
size_t image_depth
Definition: pi.h:1171
pi_mem buffer
Definition: pi.h:1177
size_t image_width
Definition: pi.h:1169
pi_mem_type image_type
Definition: pi.h:1168
size_t image_array_size
Definition: pi.h:1172
pi_image_channel_type image_channel_data_type
Definition: pi.h:1164
pi_image_channel_order image_channel_order
Definition: pi.h:1163
addressing_mode addressing
Definition: sampler.hpp:134
coordinate_normalization_mode coordinate
Definition: sampler.hpp:135
filtering_mode filtering
Definition: sampler.hpp:136